From: John Hodge Date: Sun, 2 Feb 2014 00:50:36 +0000 (+0800) Subject: UDI/16c550 - Untested TX, planning RX X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=a32af8dfa5eb5184da620a4efd6484ef50f4a9de;p=tpg%2Facess2.git UDI/16c550 - Untested TX, planning RX --- diff --git a/UDI/drivers/uart_16c550/uart16c550.c b/UDI/drivers/uart_16c550/uart16c550.c index b9d6e081..62b3de80 100644 --- a/UDI/drivers/uart_16c550/uart16c550.c +++ b/UDI/drivers/uart_16c550/uart16c550.c @@ -111,15 +111,27 @@ void uart_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle) return ; } + // Spawn the interrupt channel CONTIN( uart_bus_dev_bind, udi_channel_spawn, (gcb->channel, 0, UART_OPS_IRQ, rdata), (udi_channel_t new_channel)) - // new function rdata->interrupt_channel = new_channel; - + + // Allocate an RX buffer + CONTIN( uart_bus_dev_bind, udi_buf_write, (NULL, RX_BUFFER_SIZE, NULL, 0, 0, UDI_NULL_BUF_PATH), + (udi_buf_t *new_buf)); + if( !new_buf ) + { + // Oh... + udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), + UDI_STAT_RESOURCE_UNAVAIL ); + return ; + } + rdata->rx_buffer = new_buf; + + // Create interrupt CB CONTIN( uart_bus_dev_bind, udi_cb_alloc, (UART_CB_INTR, gcb->channel), (udi_cb_t *new_cb)) - // new function if( !new_cb ) { // Oh... @@ -131,6 +143,8 @@ void uart_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle) intr_cb->interrupt_idx = 0; intr_cb->min_event_pend = 2; intr_cb->preprocessing_handle = rdata->pio_handles[PIO_RX]; + + // Attach interrupt udi_intr_attach_req(intr_cb); // continued in uart_bus_dev_intr_attach_ack } @@ -184,7 +198,7 @@ void uart_gio_prov_xfer_req(udi_gio_xfer_cb_t *cb) { case UDI_GIO_OP_READ: // Read from local FIFO - if( rdata->rx_buffer->buf_size < cb->data_buf->buf_size ) { + if( rdata->rx_bytes < cb->data_buf->buf_size ) { // Local FIFO was empty udi_gio_xfer_nak(cb, UDI_STAT_DATA_UNDERRUN); } @@ -200,7 +214,7 @@ void uart_gio_prov_xfer_req(udi_gio_xfer_cb_t *cb) case UDI_GIO_OP_WRITE: // Send to device udi_pio_trans(uart_gio_write_complete, gcb, - rdata->pio_handles[PIO_TX], 0, cb->data_buf, NULL); + rdata->pio_handles[PIO_TX], 0, cb->data_buf, &cb->data_buf->buf_size); break; default: udi_gio_xfer_nak(cb, UDI_STAT_NOT_SUPPORTED); diff --git a/UDI/drivers/uart_16c550/uart16c550_common.h b/UDI/drivers/uart_16c550/uart16c550_common.h index 1c702779..5b91bf5c 100644 --- a/UDI/drivers/uart_16c550/uart16c550_common.h +++ b/UDI/drivers/uart_16c550/uart16c550_common.h @@ -20,6 +20,8 @@ enum { N_PIO }; +#define RX_BUFFER_SIZE 32 + typedef struct { udi_cb_t *active_cb; struct { @@ -28,6 +30,8 @@ typedef struct { udi_pio_handle_t pio_handles[N_PIO]; udi_channel_t interrupt_channel; + + udi_ubit8_t rx_bytes; udi_buf_t *rx_buffer; } rdata_t; diff --git a/UDI/drivers/uart_16c550/uart16c550_pio.h b/UDI/drivers/uart_16c550/uart16c550_pio.h index dc3f307e..db9998d1 100644 --- a/UDI/drivers/uart_16c550/uart16c550_pio.h +++ b/UDI/drivers/uart_16c550/uart16c550_pio.h @@ -1,7 +1,6 @@ #define PIO_op_RI(op, reg, sz, val) {UDI_PIO_##op+UDI_PIO_DIRECT+UDI_PIO_##reg, UDI_PIO_##sz##BYTE, val} #define PIO_MOV_RI2(reg, val) PIO_op_RI(LOAD_IMM, reg, 2, val) -#define PIO_ADD_RI2(reg, val) PIO_op_RI(ADD, reg, 2, val) -#define PIO_SUB_RI2(reg, val) PIO_op_RI(SUB, reg, 2, val) +#define PIO_MOV_RI1(reg, val) PIO_op_RI(LOAD_IMM, reg, 1, val) #define PIO_OUT_RI1(reg, ofs) PIO_op_RI(OUT, reg, 1, ofs) #define PIO_IN_RI1(reg, ofs) PIO_op_RI(IN, reg, 1, ofs) @@ -10,23 +9,22 @@ // udi_pio_trans_t uart_pio_reset[] = { // TODO: Programmable baud rate - //PIO_MOV_RI2(R0, 0x3F8), // TODO: programmable port number - PIO_ADD_RI2(R0, 1), - PIO_OUT_RI1(R0, 0x00), // +1 = 0x00 - Disable interrupts - PIO_ADD_RI2(R0, 2), - PIO_OUT_RI1(R0, 0x80), // +3 = 0x80 - Enable DLAB - PIO_SUB_RI2(R0, 3), - PIO_OUT_RI1(R0, 0x01), // +0 = 0x01 - Divisor low (115200 baud) - PIO_ADD_RI2(R0, 1), - PIO_OUT_RI1(R0, 0x00), // +1 = 0x00 - Divisor high - PIO_ADD_RI2(R0, 2), - PIO_OUT_RI1(R0, 0x03), // +3 = 0x03 - 8n1 - PIO_SUB_RI2(R0, 1), - PIO_OUT_RI1(R0, 0xC7), // +2 = 0xC7 - Clear FIFO, 14-byte threshold - PIO_ADD_RI2(R0, 2), - PIO_OUT_RI1(R0, 0x0B), // +4 = 0x0B - IRQs enabled, RTS/DSR set - PIO_SUB_RI2(R0, 3), - PIO_OUT_RI1(R0, 0x0B), // +1 = 0x05 - Enable ERBFI (Rx Full), ELSI (Line Status) + PIO_MOV_RI1(R0, 0x00), + PIO_OUT_RI1(R0, 1), // +1 = 0x00 - Disable interrupts + PIO_MOV_RI1(R0, 0x80), + PIO_OUT_RI1(R0, 3), // +3 = 0x80 - Enable DLAB + PIO_MOV_RI1(R0, 0x01), + PIO_OUT_RI1(R0, 0), // +0 = 0x01 - Divisor low (115200 baud) + PIO_MOV_RI1(R0, 0x00), + PIO_OUT_RI1(R0, 1), // +1 = 0x00 - Divisor high + PIO_MOV_RI1(R0, 0x03), + PIO_OUT_RI1(R0, 3), // +3 = 0x03 - 8n1 + PIO_MOV_RI1(R0, 0xC7), + PIO_OUT_RI1(R0, 2), // +2 = 0xC7 - Clear FIFO, 14-byte threshold + PIO_MOV_RI1(R0, 0x0B), + PIO_OUT_RI1(R0, 4), // +4 = 0x0B - IRQs enabled, RTS/DSR set + PIO_MOV_RI1(R0, 0x0B), + PIO_OUT_RI1(R0, 1), // +1 = 0x05 - Enable ERBFI (Rx Full), ELSI (Line Status) {UDI_PIO_END, UDI_PIO_2BYTE, 0} }; // @@ -35,6 +33,38 @@ udi_pio_trans_t uart_pio_reset[] = { udi_pio_trans_t uart_pio_tx[] = { // while( (inb(SERIAL_PORT + 5) & 0x20) == 0 ); // outb(SERIAL_PORT, ch); + + // R0: Temp + // R1: Byte to write + // R2: Buffer size + // R3: Position + {UDI_PIO_LOAD_IMM+UDI_PIO_DIRECT+UDI_PIO_R0, UDI_PIO_2BYTE, 0}, + {UDI_PIO_LOAD+UDI_PIO_MEM+UDI_PIO_R0, UDI_PIO_4BYTE, UDI_PIO_R2}, + + {UDI_PIO_LABEL, 0, 1}, // Loop top + + PIO_op_RI(LOAD, R0, 2, UDI_PIO_R3), + PIO_op_RI(SUB, R0, 2, UDI_PIO_R2), + {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_Z}, + {UDI_PIO_BRANCH, 0, 3}, + + // Load byte into R1 (and increment R3) + {UDI_PIO_LOAD+UDI_PIO_BUF+UDI_PIO_R3, UDI_PIO_1BYTE, UDI_PIO_R1}, + PIO_op_RI(ADD_IMM, R3, 2, 1), + + // TX single byte from R1 + // - Wait for FIFO to clear + {UDI_PIO_LABEL, 0, 2}, + PIO_IN_RI1(R0, 5), + {UDI_PIO_AND_IMM+UDI_PIO_DIRECT+UDI_PIO_DIRECT, UDI_PIO_1BYTE, 0x20}, + {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_Z}, + {UDI_PIO_BRANCH, 0, 1}, + // - TX + PIO_OUT_RI1(R1, 0), + {UDI_PIO_BRANCH, 0, 2}, + + // Done + {UDI_PIO_LABEL, 0, 3}, {UDI_PIO_END, UDI_PIO_2BYTE, 0} }; //