Tidy cell types and format strings
[openbios.git] / drivers / pc_serial.c
blob583d1c07d5bfd9473cfe672ab9cd19c8d9a490d7
1 /*
2 * Copyright (C) 2003, 2004 Stefan Reinauer
4 * See the file "COPYING" for further information about
5 * the copyright and warranty status of this work.
6 */
8 #include "config.h"
9 #include "libopenbios/bindings.h"
10 #include "kernel/kernel.h"
11 #include "drivers/drivers.h"
12 #include "libc/vsprintf.h"
14 /* ******************************************************************
15 * serial console functions
16 * ****************************************************************** */
18 #define SER_SIZE 8
20 #define RBR(x) x==2?0x2f8:0x3f8
21 #define THR(x) x==2?0x2f8:0x3f8
22 #define IER(x) x==2?0x2f9:0x3f9
23 #define IIR(x) x==2?0x2fa:0x3fa
24 #define LCR(x) x==2?0x2fb:0x3fb
25 #define MCR(x) x==2?0x2fc:0x3fc
26 #define LSR(x) x==2?0x2fd:0x3fd
27 #define MSR(x) x==2?0x2fe:0x3fe
28 #define SCR(x) x==2?0x2ff:0x3ff
29 #define DLL(x) x==2?0x2f8:0x3f8
30 #define DLM(x) x==2?0x2f9:0x3f9
32 int uart_charav(int port)
34 return ((inb(LSR(port)) & 1) != 0);
37 char uart_getchar(int port)
39 while (!uart_charav(port));
40 return ((char) inb(RBR(port)) & 0177);
43 static void uart_putchar(int port, unsigned char c)
45 if (c == '\n')
46 uart_putchar(port, '\r');
47 while (!(inb(LSR(port)) & 0x20));
48 outb(c, THR(port));
51 static void uart_init_line(int port, unsigned long baud)
53 int i, baudconst;
55 switch (baud) {
56 case 115200:
57 baudconst = 1;
58 break;
59 case 57600:
60 baudconst = 2;
61 break;
62 case 38400:
63 baudconst = 3;
64 break;
65 case 19200:
66 baudconst = 6;
67 break;
68 case 9600:
69 default:
70 baudconst = 12;
71 break;
74 outb(0x87, LCR(port));
75 outb(0x00, DLM(port));
76 outb(baudconst, DLL(port));
77 outb(0x07, LCR(port));
78 outb(0x0f, MCR(port));
80 for (i = 10; i > 0; i--) {
81 if (inb(LSR(port)) == (unsigned int) 0)
82 break;
83 inb(RBR(port));
87 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
88 int uart_init(int port, unsigned long speed)
90 uart_init_line(port, speed);
91 return -1;
94 void serial_putchar(int c)
96 uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
98 #endif
100 /* ( addr len -- actual ) */
101 static void
102 pc_serial_read(unsigned long *address)
104 char *addr;
105 int len;
107 len = POP();
108 addr = (char *)POP();
110 if (len != 1)
111 printk("pc_serial_read: bad len, addr %lx len %x\n", (unsigned long)addr, len);
113 if (uart_charav(*address)) {
114 *addr = (char)uart_getchar(*address);
115 PUSH(1);
116 } else {
117 PUSH(0);
121 /* ( addr len -- actual ) */
122 static void
123 pc_serial_write(unsigned long *address)
125 unsigned char *addr;
126 int i, len;
128 len = POP();
129 addr = (unsigned char *)POP();
131 for (i = 0; i < len; i++) {
132 uart_putchar(*address, addr[i]);
134 PUSH(len);
137 static void
138 pc_serial_close(void)
142 static void
143 pc_serial_open(unsigned long *address)
145 int len;
146 phandle_t ph;
147 unsigned long *prop;
149 fword("my-self");
150 fword("ihandle>phandle");
151 ph = (phandle_t)POP();
152 prop = (unsigned long *)get_property(ph, "address", &len);
153 *address = *prop;
155 RET ( -1 );
158 DECLARE_UNNAMED_NODE(pc_serial, INSTALL_OPEN, sizeof(unsigned long));
160 NODE_METHODS(pc_serial) = {
161 { "open", pc_serial_open },
162 { "close", pc_serial_close },
163 { "read", pc_serial_read },
164 { "write", pc_serial_write },
167 void
168 ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base,
169 uint64_t offset, int intr)
171 phandle_t aliases;
172 char nodebuff[128];
174 snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
175 REGISTER_NAMED_NODE(pc_serial, nodebuff);
177 push_str(nodebuff);
178 fword("find-device");
180 push_str("serial");
181 fword("device-type");
183 PUSH((base + offset) >> 32);
184 fword("encode-int");
185 PUSH((base + offset) & 0xffffffff);
186 fword("encode-int");
187 fword("encode+");
188 PUSH(SER_SIZE);
189 fword("encode-int");
190 fword("encode+");
191 push_str("reg");
192 fword("property");
194 aliases = find_dev("/aliases");
195 set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1);