UDI/16c550 - Untested TX, planning RX
authorJohn Hodge <[email protected]>
Sun, 2 Feb 2014 00:50:36 +0000 (08:50 +0800)
committerJohn Hodge <[email protected]>
Sun, 2 Feb 2014 00:50:36 +0000 (08:50 +0800)
UDI/drivers/uart_16c550/uart16c550.c
UDI/drivers/uart_16c550/uart16c550_common.h
UDI/drivers/uart_16c550/uart16c550_pio.h

index b9d6e08..62b3de8 100644 (file)
@@ -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);
index 1c70277..5b91bf5 100644 (file)
@@ -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;
 
index dc3f307..db9998d 100644 (file)
@@ -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)
 
 // 
 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}
 };
 //

UCC git Repository :: git.ucc.asn.au