1*6593Ssam /* dn.c 4.4 82/04/25 */ 24737Swnj 34737Swnj #include "dn.h" 44737Swnj #if NDN > 0 54737Swnj /* 64737Swnj * DN-11 ACU interface 74737Swnj */ 84737Swnj 94737Swnj #include "../h/param.h" 104737Swnj #include "../h/systm.h" 114737Swnj #include "../h/dir.h" 124737Swnj #include "../h/user.h" 134737Swnj #include "../h/buf.h" 144737Swnj #include "../h/map.h" 154737Swnj #include "../h/pte.h" 164737Swnj #include "../h/ubavar.h" 174737Swnj #include "../h/conf.h" 184737Swnj #include "../h/ioctl.h" 194737Swnj 204737Swnj struct dndevice { 21*6593Ssam u_short dn_reg[4]; 224737Swnj }; 234737Swnj 244737Swnj struct uba_device *dninfo[NDN]; 254737Swnj int dnprobe(), dnattach(); 264737Swnj u_short dnstd[] = { 0175200 }; 274737Swnj struct uba_driver dndriver = 284737Swnj { dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo }; 294737Swnj 30*6593Ssam #define CRQ 0x001 /* call request */ 31*6593Ssam #define DPR 0x002 /* digit present */ 32*6593Ssam #define MENABLE 0x004 /* master enable */ 33*6593Ssam #define MAINT 0x008 /* maintenance mode */ 34*6593Ssam #define PND 0x010 /* present next digit */ 35*6593Ssam #define DSS 0x020 /* data set status */ 36*6593Ssam #define IENABLE 0x040 /* interrupt enable */ 37*6593Ssam #define DONE 0x080 /* operation complete */ 38*6593Ssam #define DLO 0x1000 /* data line occupied */ 39*6593Ssam #define ACR 0x4000 /* abandon call and retry */ 40*6593Ssam #define PWI 0x8000 /* power indicate */ 414737Swnj 424737Swnj #define DNPRI (PZERO+5) 434737Swnj #define DNUNIT(dev) (minor(dev)>>2) 444737Swnj #define DNREG(dev) ((dev)&03) 454737Swnj 464737Swnj #define OBUFSIZ 40 /* largest phone # dialer can handle */ 474737Swnj 484737Swnj /* 494737Swnj * There's no good way to determine the correct number of dialers attached 504933Swnj * to a single device (especially when dialers such as Vadic-821 MACS 51*6593Ssam * exist which can address four chassis, each with its own dialer). 524737Swnj */ 534737Swnj dnprobe(reg) 544737Swnj caddr_t reg; 554737Swnj { 56*6593Ssam register int br, cvec; /* value-result, must be r11, r10 */ 574737Swnj register struct dndevice *dnaddr = (struct dndevice *)reg; 584737Swnj 594737Swnj /* 604737Swnj * If there's at least one dialer out there it better be 61*6593Ssam * at chassis 0. 624737Swnj */ 634737Swnj dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE; 644737Swnj DELAY(5); 654737Swnj dnaddr->dn_reg[0] = 0; 664737Swnj } 674737Swnj 684737Swnj dnattach(ui) 694737Swnj struct uba_device *ui; 70*6593Ssam {} 714933Swnj 724737Swnj /*ARGSUSED*/ 734737Swnj dnopen(dev, flag) 744737Swnj dev_t dev; 754737Swnj { 764737Swnj register struct dndevice *dp; 77*6593Ssam register u_short unit, *dnreg; 784737Swnj register struct uba_device *ui; 794737Swnj register short dialer; 804737Swnj 814737Swnj if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 || 82*6593Ssam ui->ui_alive == 0) { 834737Swnj u.u_error = ENXIO; 844737Swnj return; 854737Swnj } 86*6593Ssam dialer = DNREG(dev); 87*6593Ssam dp = (struct dndevice *)ui->ui_addr; 88*6593Ssam if (dp->dn_reg[dialer] & PWI) { 89*6593Ssam u.u_error = ENXIO; 90*6593Ssam return; 91*6593Ssam } 924737Swnj dnreg = &(dp->dn_reg[dialer]); 934737Swnj if (*dnreg&(DLO|CRQ)) { 944737Swnj u.u_error = EBUSY; 954737Swnj return; 964737Swnj } 974737Swnj dp->dn_reg[0] |= MENABLE; 984737Swnj *dnreg = IENABLE|MENABLE|CRQ; 994737Swnj } 1004737Swnj 1014737Swnj /*ARGSUSED*/ 1024737Swnj dnclose(dev, flag) 1034737Swnj dev_t dev; 1044737Swnj { 1054737Swnj register struct dndevice *dp; 1064737Swnj 1074737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1084737Swnj dp->dn_reg[DNREG(dev)] = MENABLE; 1094737Swnj } 1104737Swnj 1114737Swnj dnwrite(dev) 1124737Swnj dev_t dev; 1134737Swnj { 114*6593Ssam register u_short *dnreg; 115*6593Ssam register int cc; 1164737Swnj register struct dndevice *dp; 117*6593Ssam char buf[OBUFSIZ]; 1184737Swnj register char *cp; 1194737Swnj extern lbolt; 1204737Swnj 1214737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1224737Swnj dnreg = &(dp->dn_reg[DNREG(dev)]); 1234737Swnj cc = MIN(u.u_count, OBUFSIZ); 124*6593Ssam cp = buf; 1254737Swnj iomove(cp, (unsigned)cc, B_WRITE); 1264737Swnj if (u.u_error) 1274737Swnj return; 1284737Swnj while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0) { 129*6593Ssam spl4(); 130*6593Ssam if ((*dnreg & PND) == 0 || cc == 0) 1314737Swnj sleep((caddr_t)dnreg, DNPRI); 1324737Swnj else switch(*cp) { 1334737Swnj 1344737Swnj case '-': 1354737Swnj sleep((caddr_t)&lbolt, DNPRI); 1364737Swnj sleep((caddr_t)&lbolt, DNPRI); 1374737Swnj break; 1384737Swnj 1394737Swnj case 'f': 1404737Swnj *dnreg &= ~CRQ; 1414737Swnj sleep((caddr_t)&lbolt, DNPRI); 1424737Swnj *dnreg |= CRQ; 1434737Swnj break; 1444737Swnj 1454737Swnj case '*': case ':': 1464737Swnj *cp = 012; 1474737Swnj goto dial; 1484737Swnj 1494737Swnj case '#': case ';': 1504737Swnj *cp = 013; 1514737Swnj goto dial; 1524737Swnj 1534737Swnj case 'e': case '<': 1544737Swnj *cp = 014; 1554737Swnj goto dial; 1564737Swnj 1574737Swnj case 'w': case '=': 1584737Swnj *cp = 015; 1594737Swnj goto dial; 1604737Swnj 1614737Swnj default: 1624737Swnj if (*cp < '0' || *cp > '9') 1634737Swnj break; 1644737Swnj dial: 165*6593Ssam *dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ); 1664737Swnj sleep((caddr_t)dnreg, DNPRI); 1674737Swnj } 1684737Swnj cp++, cc--; 1694737Swnj spl0(); 1704737Swnj } 171*6593Ssam if (*dnreg & (PWI|ACR)) 1724737Swnj u.u_error = EIO; 1734737Swnj } 1744737Swnj 1754737Swnj dnintr(dev) 1764737Swnj dev_t dev; 1774737Swnj { 178*6593Ssam register u_short *basereg, *dnreg; 1794737Swnj 180*6593Ssam basereg = (u_short *)dninfo[dev]->ui_addr; 1814737Swnj *basereg &= ~MENABLE; 182*6593Ssam for (dnreg = basereg; dnreg < basereg + 4; dnreg++) 183*6593Ssam if (*dnreg & DONE) { 1844737Swnj *dnreg &= ~(DONE|DPR); 1854737Swnj wakeup((caddr_t)dnreg); 1864737Swnj } 1874737Swnj *basereg |= MENABLE; 1884737Swnj } 1894737Swnj #endif 190