1*4933Swnj /* dn.c 4.2 81/11/18 */ 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 { 214737Swnj int 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 304737Swnj #define PWI 0100000 /* power indicate */ 314737Swnj #define ACR 040000 /* abandon call and retry */ 324737Swnj #define DLO 010000 /* data line occupied */ 334737Swnj #define DONE 0200 /* operation complete */ 344737Swnj #define IENABLE 0100 /* interrupt enable */ 354737Swnj #define DSS 040 /* data set status */ 364737Swnj #define PND 020 /* present next digit */ 374737Swnj #define MAINT 010 /* maintenance mode */ 384737Swnj #define MENABLE 04 /* master enable */ 394737Swnj #define DPR 02 /* digit present */ 404737Swnj #define CRQ 01 /* call request */ 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 50*4933Swnj * to a single device (especially when dialers such as Vadic-821 MACS 51*4933Swnj * exist which can address four chassis, each with its own dialer), so 52*4933Swnj * we take the "flags" value supplied by config as the number of devices 53*4933Swnj * attached (see dnintr). 544737Swnj */ 554737Swnj dnprobe(reg) 564737Swnj caddr_t reg; 574737Swnj { 58*4933Swnj register int br, cvec; /* value-result */ 594737Swnj register struct dndevice *dnaddr = (struct dndevice *)reg; 604737Swnj 61*4933Swnj #ifdef lint 62*4933Swnj br = 0; cvec = br; br = cvec; 63*4933Swnj dnintr(0); 64*4933Swnj #endif 65*4933Swnj 664737Swnj /* 674737Swnj * If there's at least one dialer out there it better be 68*4933Swnj * at chassis 0. 694737Swnj */ 704737Swnj dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE; 714737Swnj DELAY(5); 724737Swnj dnaddr->dn_reg[0] = 0; 734737Swnj } 744737Swnj 754737Swnj dnattach(ui) 764737Swnj struct uba_device *ui; 774737Swnj { 78*4933Swnj 794737Swnj if (ui->ui_flags == 0) /* no flags =>'s don't care */ 804737Swnj ui->ui_flags = 4; 814737Swnj else if (ui->ui_flags > 4 || ui->ui_flags < 0) { 824737Swnj printf("dn%d: bad flags value %d (disabled)\n", ui->ui_unit, 834737Swnj ui->ui_flags); 844737Swnj ui->ui_flags = 0; 854737Swnj ui->ui_alive = 0; 864737Swnj } 874737Swnj } 884737Swnj 894737Swnj /*ARGSUSED*/ 904737Swnj dnopen(dev, flag) 914737Swnj dev_t dev; 924737Swnj { 934737Swnj register struct dndevice *dp; 944737Swnj register int unit, *dnreg; 954737Swnj register struct uba_device *ui; 964737Swnj register short dialer; 974737Swnj 984737Swnj if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 || 994737Swnj ui->ui_alive == 0 || (dialer = DNREG(dev)) >= ui->ui_flags || 1004737Swnj ((dp = (struct dndevice *)ui->ui_addr)->dn_reg[dialer]&PWI)) { 1014737Swnj u.u_error = ENXIO; 1024737Swnj return; 1034737Swnj } 1044737Swnj dnreg = &(dp->dn_reg[dialer]); 1054737Swnj if (*dnreg&(DLO|CRQ)) { 1064737Swnj u.u_error = EBUSY; 1074737Swnj return; 1084737Swnj } 1094737Swnj dp->dn_reg[0] |= MENABLE; 1104737Swnj *dnreg = IENABLE|MENABLE|CRQ; 1114737Swnj } 1124737Swnj 1134737Swnj /*ARGSUSED*/ 1144737Swnj dnclose(dev, flag) 1154737Swnj dev_t dev; 1164737Swnj { 1174737Swnj register struct dndevice *dp; 1184737Swnj 1194737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1204737Swnj dp->dn_reg[DNREG(dev)] = MENABLE; 1214737Swnj } 1224737Swnj 1234737Swnj dnwrite(dev) 1244737Swnj dev_t dev; 1254737Swnj { 1264737Swnj register int *dnreg, cc; 1274737Swnj register struct dndevice *dp; 1284737Swnj char buf[OBUFSIZ]; 1294737Swnj register char *cp; 1304737Swnj extern lbolt; 1314737Swnj 1324737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1334737Swnj dnreg = &(dp->dn_reg[DNREG(dev)]); 1344737Swnj cc = MIN(u.u_count, OBUFSIZ); 1354737Swnj cp = buf; 1364737Swnj iomove(cp, (unsigned)cc, B_WRITE); 1374737Swnj if (u.u_error) 1384737Swnj return; 1394737Swnj while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0) { 1404737Swnj spl4(); 1414737Swnj if ((*dnreg&PND) == 0 || cc == 0) 1424737Swnj sleep((caddr_t)dnreg, DNPRI); 1434737Swnj else switch(*cp) { 1444737Swnj 1454737Swnj case '-': 1464737Swnj sleep((caddr_t)&lbolt, DNPRI); 1474737Swnj sleep((caddr_t)&lbolt, DNPRI); 1484737Swnj break; 1494737Swnj 1504737Swnj case 'f': 1514737Swnj *dnreg &= ~CRQ; 1524737Swnj sleep((caddr_t)&lbolt, DNPRI); 1534737Swnj *dnreg |= CRQ; 1544737Swnj break; 1554737Swnj 1564737Swnj case '*': case ':': 1574737Swnj *cp = 012; 1584737Swnj goto dial; 1594737Swnj 1604737Swnj case '#': case ';': 1614737Swnj *cp = 013; 1624737Swnj goto dial; 1634737Swnj 1644737Swnj case 'e': case '<': 1654737Swnj *cp = 014; 1664737Swnj goto dial; 1674737Swnj 1684737Swnj case 'w': case '=': 1694737Swnj *cp = 015; 1704737Swnj goto dial; 1714737Swnj 1724737Swnj default: 1734737Swnj if (*cp < '0' || *cp > '9') 1744737Swnj break; 1754737Swnj dial: 1764737Swnj *dnreg = (*cp<<8)|IENABLE|MENABLE|DPR|CRQ; 1774737Swnj sleep((caddr_t)dnreg, DNPRI); 1784737Swnj } 1794737Swnj cp++, cc--; 1804737Swnj spl0(); 1814737Swnj } 1824737Swnj if (*dnreg&(PWI|ACR)) 1834737Swnj u.u_error = EIO; 1844737Swnj } 1854737Swnj 1864737Swnj /* 1874737Swnj * NOTE that the flags from the config file define the number 188*4933Swnj * of dialers attached to this controller. 1894737Swnj */ 1904737Swnj dnintr(dev) 1914737Swnj dev_t dev; 1924737Swnj { 1934737Swnj register int *basereg, *dnreg, *lastreg; 1944737Swnj 1954737Swnj basereg = (int *)dninfo[dev]->ui_addr; 1964737Swnj *basereg &= ~MENABLE; 1974737Swnj lastreg = basereg+dninfo[dev]->ui_flags; 1984737Swnj for (dnreg = basereg; dnreg < lastreg; dnreg++) 1994737Swnj if (*dnreg&DONE) { 2004737Swnj *dnreg &= ~(DONE|DPR); 2014737Swnj wakeup((caddr_t)dnreg); 2024737Swnj } 2034737Swnj *basereg |= MENABLE; 2044737Swnj } 2054737Swnj #endif 206