|
|
1.1 root 1: /*
2: * Copyright (C) 2003, 2004 Stefan Reinauer
3: *
4: * See the file "COPYING" for further information about
5: * the copyright and warranty status of this work.
6: */
7:
8: #include "config.h"
9: #include "libopenbios/bindings.h"
10: #include "kernel/kernel.h"
11: #include "drivers/drivers.h"
12: #include "libc/vsprintf.h"
13:
14: /* ******************************************************************
15: * serial console functions
16: * ****************************************************************** */
17:
18: #define SER_SIZE 8
19:
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
31:
32: int uart_charav(int port)
33: {
34: return ((inb(LSR(port)) & 1) != 0);
35: }
36:
37: char uart_getchar(int port)
38: {
39: while (!uart_charav(port));
40: return ((char) inb(RBR(port)) & 0177);
41: }
42:
43: static void uart_putchar(int port, unsigned char c)
44: {
45: if (c == '\n')
46: uart_putchar(port, '\r');
47: while (!(inb(LSR(port)) & 0x20));
48: outb(c, THR(port));
49: }
50:
51: static void uart_init_line(int port, unsigned long baud)
52: {
53: int i, baudconst;
54:
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;
72: }
73:
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));
79:
80: for (i = 10; i > 0; i--) {
81: if (inb(LSR(port)) == (unsigned int) 0)
82: break;
83: inb(RBR(port));
84: }
85: }
86:
87: #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
88: int uart_init(int port, unsigned long speed)
89: {
90: uart_init_line(port, speed);
91: return -1;
92: }
93:
94: void serial_putchar(int c)
95: {
96: uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
97: }
98: #endif
99:
100: /* ( addr len -- actual ) */
101: static void
102: pc_serial_read(unsigned long *address)
103: {
104: char *addr;
105: int len;
106:
107: len = POP();
108: addr = (char *)POP();
109:
110: if (len != 1)
111: printk("pc_serial_read: bad len, addr %lx len %x\n", (unsigned long)addr, len);
112:
113: if (uart_charav(*address)) {
114: *addr = (char)uart_getchar(*address);
115: PUSH(1);
116: } else {
117: PUSH(0);
118: }
119: }
120:
121: /* ( addr len -- actual ) */
122: static void
123: pc_serial_write(unsigned long *address)
124: {
125: unsigned char *addr;
126: int i, len;
127:
128: len = POP();
129: addr = (unsigned char *)POP();
130:
131: for (i = 0; i < len; i++) {
132: uart_putchar(*address, addr[i]);
133: }
134: PUSH(len);
135: }
136:
137: static void
138: pc_serial_close(void)
139: {
140: }
141:
142: static void
143: pc_serial_open(unsigned long *address)
144: {
145: int len;
146: phandle_t ph;
147: unsigned long *prop;
148:
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;
154:
155: RET ( -1 );
156: }
157:
158: DECLARE_UNNAMED_NODE(pc_serial, INSTALL_OPEN, sizeof(unsigned long));
159:
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 },
165: };
166:
167: void
168: ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base,
169: uint64_t offset, int intr)
170: {
171: phandle_t aliases;
172: char nodebuff[128];
173:
174: snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
175: REGISTER_NAMED_NODE(pc_serial, nodebuff);
176:
177: push_str(nodebuff);
178: fword("find-device");
179:
180: push_str("serial");
181: fword("device-type");
182:
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");
193:
194: aliases = find_dev("/aliases");
195: set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1);
196: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.