1 #define PIO_op_RI(op, reg, sz, val) {UDI_PIO_##op+UDI_PIO_DIRECT+UDI_PIO_##reg, UDI_PIO_##sz##BYTE, val}
2 #define PIO_MOV_RI2(reg, val) PIO_op_RI(LOAD_IMM, reg, 2, val)
3 #define PIO_MOV_RI1(reg, val) PIO_op_RI(LOAD_IMM, reg, 2, val) // Load IMM has to be 2 bytes
4 #define PIO_OUT_RI1(reg, ofs) PIO_op_RI(OUT, reg, 1, ofs)
5 #define PIO_IN_RI1(reg, ofs) PIO_op_RI(IN, reg, 1, ofs)
10 udi_pio_trans_t uart_pio_reset[] = {
11 // TODO: Programmable baud rate
12 PIO_MOV_RI1(R0, 0x00),
13 PIO_OUT_RI1(R0, 1), // +1 = 0x00 - Disable interrupts
14 PIO_MOV_RI1(R0, 0x80),
15 PIO_OUT_RI1(R0, 3), // +3 = 0x80 - Enable DLAB
16 PIO_MOV_RI1(R0, 0x01),
17 PIO_OUT_RI1(R0, 0), // +0 = 0x01 - Divisor low (115200 baud)
18 PIO_MOV_RI1(R0, 0x00),
19 PIO_OUT_RI1(R0, 1), // +1 = 0x00 - Divisor high
20 PIO_MOV_RI1(R0, 0x03),
21 PIO_OUT_RI1(R0, 3), // +3 = 0x03 - 8n1
22 PIO_MOV_RI1(R0, 0xC7),
23 PIO_OUT_RI1(R0, 2), // +2 = 0xC7 - Clear FIFO, 14-byte threshold
24 PIO_MOV_RI1(R0, 0x0B),
25 PIO_OUT_RI1(R0, 4), // +4 = 0x0B - IRQs enabled, RTS/DSR set
26 {UDI_PIO_END, UDI_PIO_2BYTE, 0}
31 udi_pio_trans_t uart_pio_tx[] = {
32 // while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
33 // outb(SERIAL_PORT, ch);
39 {UDI_PIO_LOAD_IMM+UDI_PIO_DIRECT+UDI_PIO_R3, UDI_PIO_2BYTE, 0},
40 {UDI_PIO_LOAD_IMM+UDI_PIO_DIRECT+UDI_PIO_R0, UDI_PIO_2BYTE, 0},
41 {UDI_PIO_LOAD+UDI_PIO_MEM+UDI_PIO_R0, UDI_PIO_4BYTE, UDI_PIO_R2},
43 {UDI_PIO_LABEL, 0, 1}, // Loop top
45 {UDI_PIO_STORE+UDI_PIO_DIRECT+UDI_PIO_R0, UDI_PIO_2BYTE, UDI_PIO_R3},
46 //PIO_op_RI(LOAD, R0, 2, UDI_PIO_R3),
47 PIO_op_RI(SUB, R0, 2, UDI_PIO_R2),
48 {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ},
49 {UDI_PIO_BRANCH, 0, 3},
51 // Load byte into R1 (and increment R3)
52 {UDI_PIO_LOAD+UDI_PIO_BUF+UDI_PIO_R3, UDI_PIO_1BYTE, UDI_PIO_R1},
53 PIO_op_RI(ADD_IMM, R3, 2, 1),
55 // TX single byte from R1
56 // - Wait for FIFO to clear
57 // while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
58 {UDI_PIO_LABEL, 0, 2},
60 PIO_op_RI(AND_IMM, R0, 1, 0x20),
61 {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ},
62 {UDI_PIO_BRANCH, 0, 2},
64 // outb(SERIAL_PORT, ch);
66 {UDI_PIO_BRANCH, 0, 1},
69 {UDI_PIO_LABEL, 0, 3},
70 {UDI_PIO_END, UDI_PIO_2BYTE, 0}
73 // Recieve (interrupt)
75 udi_pio_trans_t uart_pio_intr[] = {
76 // 0: Enable interrupts
77 PIO_MOV_RI1(R0, 0x09),
78 PIO_OUT_RI1(R0, 1), // +1 = EDSSI (Delta Line status), ELSI (Line Status), ERBFI (Rx Full)
79 {UDI_PIO_END, UDI_PIO_2BYTE, 0},
81 // - Check if the interrupt was for this device,
82 // if so rx into buffer and return byte count
83 // return inb(SERIAL_PORT);
84 {UDI_PIO_LABEL, 0, 1},
85 // if( (inb(SERIAL_PORT+5) & 0x01) == 0 ) {
87 PIO_op_RI(AND_IMM, R0, 1, 0x01),
88 {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_Z},
89 {UDI_PIO_BRANCH, 0, 3},
92 PIO_MOV_RI1(R1, UDI_INTR_UNCLAIMED),
93 {UDI_PIO_STORE+UDI_PIO_SCRATCH+UDI_PIO_R2, UDI_PIO_1BYTE, UDI_PIO_R1},
95 {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
98 {UDI_PIO_LABEL, 0, 3},
100 PIO_MOV_RI2(R2, 0), // Buffer offset
102 {UDI_PIO_LABEL, 0, 4},
103 // buffer[buf_ofs] = inb(SERIAL_PORT+0);
105 {UDI_PIO_STORE+UDI_PIO_BUF+UDI_PIO_R2, UDI_PIO_1BYTE, UDI_PIO_R0},
107 PIO_op_RI(ADD_IMM, R2, 1, 0x01),
108 // } while( inb(SERIAL_PORT+5) & 0x01 );
110 PIO_op_RI(AND_IMM, R0, 1, 0x01),
111 {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_Z},
112 {UDI_PIO_BRANCH, 0, 4},
114 {UDI_PIO_END, UDI_PIO_1BYTE, UDI_PIO_R2},
117 // 2: Interrupt Overrun
118 {UDI_PIO_LABEL, 0, 2},
119 PIO_MOV_RI1(R0, 0x08), // EDSSI only
121 {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0}
124 #define ARRAY_SIZEOF(arr) (sizeof(arr)/sizeof(arr[0]))
127 udi_pio_trans_t *trans_list;
128 udi_ubit16_t list_length;
129 udi_ubit16_t pio_attributes;
131 [PIO_RESET] = {uart_pio_reset, ARRAY_SIZEOF(uart_pio_reset), 0},
132 [PIO_TX] = {uart_pio_tx, ARRAY_SIZEOF(uart_pio_tx), 0},
133 [PIO_INTR] = {uart_pio_intr, ARRAY_SIZEOF(uart_pio_intr), 0},
135 //const int UART_NUM_PIO_OPS = ARRAY_SIZEOF(uart_pio_ops);