1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)dn.c 7.7 (Berkeley) 12/16/90 7 */ 8 9 #include "dn.h" 10 #if NDN > 0 11 /* 12 * DN-11 ACU interface 13 */ 14 #include "../include/pte.h" 15 16 #include "sys/param.h" 17 #include "sys/systm.h" 18 #include "sys/user.h" 19 #include "sys/buf.h" 20 #include "sys/map.h" 21 #include "sys/conf.h" 22 #include "sys/uio.h" 23 24 #include "ubavar.h" 25 26 struct dndevice { 27 u_short dn_reg[4]; 28 }; 29 30 struct uba_device *dninfo[NDN]; 31 int dnprobe(), dnattach(), dnintr(); 32 u_short dnstd[] = { 0175200, 0 }; 33 struct uba_driver dndriver = 34 { dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo }; 35 36 #define CRQ 0x001 /* call request */ 37 #define DPR 0x002 /* digit present */ 38 #define MENABLE 0x004 /* master enable */ 39 #define MAINT 0x008 /* maintenance mode */ 40 #define PND 0x010 /* present next digit */ 41 #define DSS 0x020 /* data set status */ 42 #define IENABLE 0x040 /* interrupt enable */ 43 #define DONE 0x080 /* operation complete */ 44 #define DLO 0x1000 /* data line occupied */ 45 #define ACR 0x4000 /* abandon call and retry */ 46 #define PWI 0x8000 /* power indicate */ 47 48 #define DNPRI (PZERO+5) 49 #define DNUNIT(dev) (minor(dev)>>2) 50 #define DNREG(dev) ((dev)&03) 51 52 #define OBUFSIZ 40 /* largest phone # dialer can handle */ 53 54 /* 55 * There's no good way to determine the correct number of dialers attached 56 * to a single device (especially when dialers such as Vadic-821 MACS 57 * exist which can address four chassis, each with its own dialer). 58 */ 59 dnprobe(reg) 60 caddr_t reg; 61 { 62 register int br, cvec; /* value-result, must be r11, r10 */ 63 register struct dndevice *dnaddr = (struct dndevice *)reg; 64 65 #ifdef lint 66 br = 0; cvec = 0; br = cvec; cvec = br; 67 dnintr(0); 68 #endif 69 /* 70 * If there's at least one dialer out there it better be 71 * at chassis 0. 72 */ 73 dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE; 74 DELAY(5); 75 dnaddr->dn_reg[0] = 0; 76 return (sizeof (struct dndevice)); 77 } 78 79 /*ARGSUSED*/ 80 dnattach(ui) 81 struct uba_device *ui; 82 { 83 84 } 85 86 /*ARGSUSED*/ 87 dnopen(dev, flag) 88 dev_t dev; 89 int flag; 90 { 91 register struct dndevice *dp; 92 register u_short unit, *dnreg; 93 register struct uba_device *ui; 94 register short dialer; 95 96 if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 || 97 ui->ui_alive == 0) 98 return (ENXIO); 99 dialer = DNREG(dev); 100 dp = (struct dndevice *)ui->ui_addr; 101 if (dp->dn_reg[dialer] & PWI) 102 return (ENXIO); 103 dnreg = &(dp->dn_reg[dialer]); 104 if (*dnreg&(DLO|CRQ)) 105 return (EBUSY); 106 dp->dn_reg[0] |= MENABLE; 107 *dnreg = IENABLE|MENABLE|CRQ; 108 return (0); 109 } 110 111 /*ARGSUSED*/ 112 dnclose(dev, flag) 113 dev_t dev; 114 { 115 register struct dndevice *dp; 116 117 dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 118 dp->dn_reg[DNREG(dev)] = MENABLE; 119 return (0); 120 } 121 122 dnwrite(dev, uio) 123 dev_t dev; 124 struct uio *uio; 125 { 126 register u_short *dnreg; 127 register int cc; 128 register struct dndevice *dp; 129 char obuf[OBUFSIZ]; 130 register char *cp; 131 extern lbolt; 132 int error; 133 134 dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 135 dnreg = &(dp->dn_reg[DNREG(dev)]); 136 cc = MIN(uio->uio_resid, OBUFSIZ); 137 cp = obuf; 138 error = uiomove(cp, cc, uio); 139 if (error) 140 return (error); 141 while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0 && error == 0) { 142 (void) spl4(); 143 if ((*dnreg & PND) == 0 || cc == 0) 144 error = tsleep((caddr_t)dnreg, DNPRI | PCATCH, 145 devout, 0); 146 else switch(*cp) { 147 148 case '-': 149 error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 150 devout, 0); 151 if (error == 0) 152 error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 153 devout, 0); 154 break; 155 156 case 'f': 157 *dnreg &= ~CRQ; 158 error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 159 devout, 0); 160 *dnreg |= CRQ; 161 break; 162 163 case '*': case ':': 164 *cp = 012; 165 goto dial; 166 167 case '#': case ';': 168 *cp = 013; 169 goto dial; 170 171 case 'e': case '<': 172 *cp = 014; 173 goto dial; 174 175 case 'w': case '=': 176 *cp = 015; 177 goto dial; 178 179 default: 180 if (*cp < '0' || *cp > '9') 181 break; 182 dial: 183 *dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ); 184 error = tsleep((caddr_t)dnreg, DNPRI | PCATCH, 185 devout, 0); 186 } 187 cp++, cc--; 188 spl0(); 189 } 190 if (error) 191 return (error); 192 if (*dnreg & (PWI|ACR)) 193 return (EIO); 194 return (0); 195 } 196 197 dnintr(dev) 198 dev_t dev; 199 { 200 register u_short *basereg, *dnreg; 201 202 basereg = (u_short *)dninfo[dev]->ui_addr; 203 *basereg &= ~MENABLE; 204 for (dnreg = basereg; dnreg < basereg + 4; dnreg++) 205 if (*dnreg & DONE) { 206 *dnreg &= ~(DONE|DPR); 207 wakeup((caddr_t)dnreg); 208 } 209 *basereg |= MENABLE; 210 } 211 #endif 212