|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version 1.1.0
3: * Copyright (c) 1982, 1990 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: *
6: * $Log: al.c,v $
7: * Revision 1.8 91/08/01 13:47:28 bin
8: * updated by hal to include rts/cts handshaking.
9: *
10: * Revision 1.4 91/07/31 16:06:33 hal
11: * Change include usage. Use AL[01]_MAJOR.
12: *
13: * Revision 1.2 91/02/21 11:21:28 hal
14: * Used in COH Release 3.1.0 - add COM3/COM4 and polling
15: *
16: * Revision 1.1 91/02/21 11:07:36 hal
17: * Used in COH Release 3.0.0 - no COM3/COM4
18: *
19: -lgl) */
20: /*
21: * Driver for an IBM PC asyncronous
22: * line, using interrupts. The interface
23: * uses a Natty/WD 8250 chip.
24: */
25: #include <sys/coherent.h>
26: #include <sys/i8086.h>
27: #include <sys/con.h>
28: #include <errno.h>
29: #include <sys/stat.h>
30: #include <sys/tty.h>
31: #include <sys/uproc.h>
32: #include <sys/clist.h>
33: #include <sys/ins8250.h>
34: #include <sys/sched.h>
35: #include <sys/al.h>
36: #include <sys/devices.h>
37:
38: #define minor_st(dev) (dev & 0x3f)
39: #define DEV_TTY (alttab[minor_st(dev)])
40: #define ALPORT (((COM_DDP *)(DEV_TTY.t_ddp))->port)
41:
42: /*
43: * This driver can be compiled to drive any possible
44: * async port by appropriate definitions of:
45: * ALPORT[ab] the io port address(es)
46: * ALNUM[ab] com index number (0..3 for com[1..4])
47: * ALINT the interrupt level
48: * ALNAME the xxcon name
49: * ALMAJ the major device number
50: * ALCNT number of ports sharing the interrupt
51: *
52: * NOTE: if ALCNT is changed, alttab and alintr will need hacking
53: * Common code for the different ports is handled by alx.c
54: */
55:
56: #ifdef ALCOM1 /* COM1_3 definitions */
57: #define ALPORTa 0x3F8 /* Base of com1 port */
58: #define ALPORTb 0x3E8 /* Base of com3 port */
59: #define ALNUMa 0 /* com1 has com number of 0 */
60: #define ALNUMb 2 /* com3 has com number of 2 */
61: #define ALINT 4 /* Interrupt level of com1_3 ports */
62: #define ALNAME a0con /* CON name of com1_3 ports */
63: #define ALMAJ AL0_MAJOR /* Major number of com1_3 port */
64: #define ALCNT A0CNT /* Number of ports for this IRQ */
65: #define ALSPEEDa C1BAUD /* Name of patchable variable for com1 speed */
66: #define ALSPEEDb C3BAUD /* Name of patchable variable for com3 speed */
67: #endif
68:
69: #ifdef ALCOM2 /* COM2_4 definitions */
70: #define ALPORTa 0x2F8 /* Base of com2 port */
71: #define ALPORTb 0x2E8 /* Base of com4 port */
72: #define ALNUMa 1 /* com2 has com number of 1 */
73: #define ALNUMb 3 /* com4 has com number of 3 */
74: #define ALINT 3 /* Interrupt level of com2_4 ports */
75: #define ALNAME a1con /* CON name of com2_4 ports */
76: #define ALMAJ AL1_MAJOR /* Major number of com2_4 ports */
77: #define ALCNT A1CNT /* Number of ports for this IRQ */
78: #define ALSPEEDa C2BAUD /* Name of patchable variable for com2 speed */
79: #define ALSPEEDb C4BAUD /* Name of patchable variable for com4 speed */
80: #endif
81:
82: /*
83: * Functions.
84: */
85: int alxopen();
86: int alxclose();
87: int alxioctl();
88: int alxtimer();
89: int alxparam();
90: int alxcycle();
91: int alxstart();
92: int alxbreak();
93:
94: int alintr();
95: int alopen();
96: int alclose();
97: int alread();
98: int alwrite();
99: int alioctl();
100: int alload();
101: int alunload();
102: int alpoll();
103: int nulldev();
104: int nonedev();
105:
106: /*
107: * Configuration table.
108: */
109: CON ALNAME ={
110: DFCHR|DFPOL, /* Flags */
111: ALMAJ, /* Major index */
112: alopen, /* Open */
113: alclose, /* Close */
114: nulldev, /* Block */
115: alread, /* Read */
116: alwrite, /* Write */
117: alioctl, /* Ioctl */
118: nulldev, /* Powerfail */
119: alxtimer, /* Timeout */
120: alload, /* Load */
121: alunload, /* Unload */
122: alpoll /* Poll */
123: };
124:
125: /*
126: * Terminal structures.
127: */
128: static COM_DDP * ddp;
129: static TTY * alttab;
130: static TTY * irqtty; /* point to alttab entry which is IRQ-enabled */
131:
132: /*
133: * to change default speeds - patch kernel variables C1BAUD..C4BAUD
134: * new value should be one of B0..B9600 in /usr/include/sgtty.h
135: */
136: int ALSPEEDa = B9600;
137: int ALSPEEDb = B9600;
138:
139: /*
140: * to enable com[34], patch here
141: * A0CNT should be 2 if you want com3, 1 otherwise
142: * A1CNT should be 2 if you want com4, 1 otherwise
143: */
144: int ALCNT = 2;
145:
146: static
147: alload()
148: {
149: register int s;
150: static int init;
151: extern int albaud[];
152: int port, i;
153:
154: if (init == 0
155: && (alttab = (TTY *)kalloc(ALCNT * sizeof(TTY)))
156: && (ddp = (COM_DDP *)kalloc(ALCNT * sizeof(COM_DDP)))) {
157: kclear(alttab, ALCNT*sizeof(TTY));
158: kclear(ddp, ALCNT*sizeof(COM_DDP));
159: s = sphi();
160: ++init;
161:
162: alttab[0].t_dispeed = alttab[0].t_dospeed = ALSPEEDa;
163: alttab[0].t_ddp = (char *)&ddp[0];
164: tp_table[ALNUMa] = alttab; /* set TTY pointers for polling */
165: ddp[0].port = ALPORTa;
166: ddp[0].com_num = ALNUMa;
167:
168: if (ALCNT > 1) {
169: alttab[1].t_dispeed = alttab[1].t_dospeed = ALSPEEDb;
170: alttab[1].t_ddp = (char *)&ddp[1];
171: tp_table[ALNUMb] = alttab+1;
172: ddp[1].port = ALPORTb;
173: ddp[1].com_num = ALNUMb;
174: }
175:
176: for (i = 0; i < ALCNT; i++) {
177: int speed = alttab[i].t_dospeed;
178:
179: /* port = base I/O address */
180: port = ((COM_DDP *)(alttab[i].t_ddp))->port;
181: outb(port+IER, 0); /* disable port interrupts */
182: if (inb(port+IER) == 0) {
183: outb(port+MCR, 0); /* hangup port */
184: outb(port+LCR, LC_DLAB);
185: outb(port+DLL, albaud[speed]);
186: outb(port+DLH, albaud[speed] >> 8);
187: outb(port+LCR, LC_CS8);
188: }
189: alttab[i].t_start = alxstart;
190: alttab[i].t_param = alxparam;
191: alttab[i].t_cs_sel= cs_sel();
192: }
193:
194: setivec(ALINT, alintr); /* set interrupt vector */
195: spl(s);
196: }
197: }
198:
199: static
200: alunload()
201: {
202: int port, i;
203:
204: for (i = 0; i < ALCNT; i++) {
205: port = ((COM_DDP *)(alttab[i].t_ddp))->port;
206: outb(port+IER, 0); /* disable port interrupts */
207: outb(port+MCR, 0); /* hangup port */
208: timeout(alttab[i].t_rawtim, 0, NULL, 0);/* cancel timer */
209: }
210: clrivec(ALINT); /* release interrupt vector */
211: kfree(alttab);
212: kfree(ddp);
213: }
214:
215: static
216: alopen(dev, mode)
217: dev_t dev;
218: int mode;
219: {
220: if (minor_st(dev) < ALCNT) {
221: alload();
222: alxcycle(&DEV_TTY);
223: alxopen(dev, mode, &DEV_TTY, &irqtty);
224: } else
225: u.u_error = ENXIO;
226: }
227:
228: static
229: alclose(dev, mode)
230: dev_t dev;
231: int mode;
232: {
233: register int s;
234:
235: if (--DEV_TTY.t_open == 0) { /* Last open */
236: s = sphi();
237: alxclose(dev, mode, &DEV_TTY);
238: spl(s);
239: }
240: }
241:
242: static
243: alread(dev, iop)
244: dev_t dev;
245: IO *iop;
246: {
247: ttread(&DEV_TTY, iop);
248: }
249:
250: static
251: alwrite(dev, iop)
252: dev_t dev;
253: register IO *iop;
254: {
255: register int c;
256:
257: /*
258: * Treat user writes through tty driver.
259: */
260: if (iop->io_seg != IOSYS) {
261: ttwrite(&DEV_TTY, iop);
262: return;
263: }
264:
265: /*
266: * Treat kernel writes by blocking on transmit buffer.
267: */
268: while ((c = iogetc(iop)) >= 0) {
269: /*
270: * Wait until transmit buffer is empty.
271: * Check twice to prevent critical race with interrupt handler.
272: */
273: for (;;) {
274: if (inb(ALPORT+LSR) & LS_TxRDY)
275: if (inb(ALPORT+LSR) & LS_TxRDY)
276: break;
277: }
278:
279: /*
280: * Output the next character.
281: */
282: outb(ALPORT+DREG, c);
283: }
284: }
285:
286: static
287: alioctl(dev, com, vec)
288: dev_t dev;
289: struct sgttyb *vec;
290: {
291: alxioctl(dev, com, vec, &DEV_TTY);
292: }
293:
294: static
295: alpoll(dev, ev, msec)
296: dev_t dev;
297: int ev;
298: int msec;
299: {
300: return ttpoll(&DEV_TTY, ev, msec);
301: }
302:
303: static
304: alintr()
305: {
306: alxintr(irqtty);
307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.