|
|
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.