123325Smckusick /* 223325Smckusick * Copyright (c) 1982 Regents of the University of California. 323325Smckusick * All rights reserved. The Berkeley software License Agreement 423325Smckusick * specifies the terms and conditions for redistribution. 523325Smckusick * 6*25521Stef * @(#)dn.c 6.4 (Berkeley) 11/22/85 723325Smckusick */ 84737Swnj 94737Swnj #include "dn.h" 104737Swnj #if NDN > 0 114737Swnj /* 124737Swnj * DN-11 ACU interface 134737Swnj */ 149773Ssam #include "../machine/pte.h" 154737Swnj 1617073Sbloom #include "param.h" 1717073Sbloom #include "systm.h" 1817073Sbloom #include "dir.h" 1917073Sbloom #include "user.h" 2017073Sbloom #include "buf.h" 2117073Sbloom #include "map.h" 2217073Sbloom #include "conf.h" 2317073Sbloom #include "uio.h" 244737Swnj 2517073Sbloom #include "ubavar.h" 268474Sroot 274737Swnj struct dndevice { 286593Ssam u_short dn_reg[4]; 294737Swnj }; 304737Swnj 314737Swnj struct uba_device *dninfo[NDN]; 328779Sroot int dnprobe(), dnattach(), dnintr(); 33*25521Stef u_short dnstd[] = { 0175200, 0 }; 344737Swnj struct uba_driver dndriver = 354737Swnj { dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo }; 364737Swnj 376593Ssam #define CRQ 0x001 /* call request */ 386593Ssam #define DPR 0x002 /* digit present */ 396593Ssam #define MENABLE 0x004 /* master enable */ 406593Ssam #define MAINT 0x008 /* maintenance mode */ 416593Ssam #define PND 0x010 /* present next digit */ 426593Ssam #define DSS 0x020 /* data set status */ 436593Ssam #define IENABLE 0x040 /* interrupt enable */ 446593Ssam #define DONE 0x080 /* operation complete */ 456593Ssam #define DLO 0x1000 /* data line occupied */ 466593Ssam #define ACR 0x4000 /* abandon call and retry */ 476593Ssam #define PWI 0x8000 /* power indicate */ 484737Swnj 494737Swnj #define DNPRI (PZERO+5) 504737Swnj #define DNUNIT(dev) (minor(dev)>>2) 514737Swnj #define DNREG(dev) ((dev)&03) 524737Swnj 534737Swnj #define OBUFSIZ 40 /* largest phone # dialer can handle */ 544737Swnj 554737Swnj /* 564737Swnj * There's no good way to determine the correct number of dialers attached 574933Swnj * to a single device (especially when dialers such as Vadic-821 MACS 586593Ssam * exist which can address four chassis, each with its own dialer). 594737Swnj */ 604737Swnj dnprobe(reg) 614737Swnj caddr_t reg; 624737Swnj { 636593Ssam register int br, cvec; /* value-result, must be r11, r10 */ 644737Swnj register struct dndevice *dnaddr = (struct dndevice *)reg; 654737Swnj 668608Sroot #ifdef lint 678608Sroot br = 0; cvec = 0; br = cvec; cvec = br; 688779Sroot dnintr(0); 698608Sroot #endif 704737Swnj /* 714737Swnj * If there's at least one dialer out there it better be 728608Sroot * at chassis 0. 734737Swnj */ 744737Swnj dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE; 754737Swnj DELAY(5); 764737Swnj dnaddr->dn_reg[0] = 0; 777409Skre return (sizeof (struct dndevice)); 784737Swnj } 794737Swnj 808608Sroot /*ARGSUSED*/ 814737Swnj dnattach(ui) 824737Swnj struct uba_device *ui; 838568Sroot { 844933Swnj 858568Sroot } 868568Sroot 874737Swnj /*ARGSUSED*/ 884737Swnj dnopen(dev, flag) 894737Swnj dev_t dev; 908647Sroot int flag; 914737Swnj { 924737Swnj register struct dndevice *dp; 936593Ssam register u_short unit, *dnreg; 944737Swnj register struct uba_device *ui; 954737Swnj register short dialer; 964737Swnj 974737Swnj if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 || 988568Sroot ui->ui_alive == 0) 998568Sroot return (ENXIO); 1006593Ssam dialer = DNREG(dev); 1016593Ssam dp = (struct dndevice *)ui->ui_addr; 1028568Sroot if (dp->dn_reg[dialer] & PWI) 1038568Sroot return (ENXIO); 1044737Swnj dnreg = &(dp->dn_reg[dialer]); 1058568Sroot if (*dnreg&(DLO|CRQ)) 1068568Sroot return (EBUSY); 1074737Swnj dp->dn_reg[0] |= MENABLE; 1084737Swnj *dnreg = IENABLE|MENABLE|CRQ; 1098568Sroot return (0); 1104737Swnj } 1114737Swnj 1124737Swnj /*ARGSUSED*/ 1134737Swnj dnclose(dev, flag) 1144737Swnj dev_t dev; 1154737Swnj { 1164737Swnj register struct dndevice *dp; 1174737Swnj 1184737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1194737Swnj dp->dn_reg[DNREG(dev)] = MENABLE; 1204737Swnj } 1214737Swnj 1227833Sroot dnwrite(dev, uio) 1234737Swnj dev_t dev; 1247833Sroot struct uio *uio; 1254737Swnj { 1266593Ssam register u_short *dnreg; 1276593Ssam register int cc; 1284737Swnj register struct dndevice *dp; 1298608Sroot char obuf[OBUFSIZ]; 1304737Swnj register char *cp; 1314737Swnj extern lbolt; 1328491Sroot int error; 1334737Swnj 1344737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1354737Swnj dnreg = &(dp->dn_reg[DNREG(dev)]); 1367833Sroot cc = MIN(uio->uio_resid, OBUFSIZ); 1378608Sroot cp = obuf; 1388647Sroot error = uiomove(cp, cc, UIO_WRITE, uio); 1398491Sroot if (error) 1408491Sroot return (error); 1414737Swnj while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0) { 1428715Sroot (void) spl4(); 1436593Ssam if ((*dnreg & PND) == 0 || cc == 0) 1444737Swnj sleep((caddr_t)dnreg, DNPRI); 1454737Swnj else switch(*cp) { 1464737Swnj 1474737Swnj case '-': 1484737Swnj sleep((caddr_t)&lbolt, DNPRI); 1494737Swnj sleep((caddr_t)&lbolt, DNPRI); 1504737Swnj break; 1514737Swnj 1524737Swnj case 'f': 1534737Swnj *dnreg &= ~CRQ; 1544737Swnj sleep((caddr_t)&lbolt, DNPRI); 1554737Swnj *dnreg |= CRQ; 1564737Swnj break; 1574737Swnj 1584737Swnj case '*': case ':': 1594737Swnj *cp = 012; 1604737Swnj goto dial; 1614737Swnj 1624737Swnj case '#': case ';': 1634737Swnj *cp = 013; 1644737Swnj goto dial; 1654737Swnj 1664737Swnj case 'e': case '<': 1674737Swnj *cp = 014; 1684737Swnj goto dial; 1694737Swnj 1704737Swnj case 'w': case '=': 1714737Swnj *cp = 015; 1724737Swnj goto dial; 1734737Swnj 1744737Swnj default: 1754737Swnj if (*cp < '0' || *cp > '9') 1764737Swnj break; 1774737Swnj dial: 1786593Ssam *dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ); 1794737Swnj sleep((caddr_t)dnreg, DNPRI); 1804737Swnj } 1814737Swnj cp++, cc--; 1824737Swnj spl0(); 1834737Swnj } 1846593Ssam if (*dnreg & (PWI|ACR)) 1858491Sroot return (EIO); 1868491Sroot return (0); 1874737Swnj } 1884737Swnj 1894737Swnj dnintr(dev) 1904737Swnj dev_t dev; 1914737Swnj { 1926593Ssam register u_short *basereg, *dnreg; 1934737Swnj 1946593Ssam basereg = (u_short *)dninfo[dev]->ui_addr; 1954737Swnj *basereg &= ~MENABLE; 1966593Ssam for (dnreg = basereg; dnreg < basereg + 4; dnreg++) 1976593Ssam if (*dnreg & DONE) { 1984737Swnj *dnreg &= ~(DONE|DPR); 1994737Swnj wakeup((caddr_t)dnreg); 2004737Swnj } 2014737Swnj *basereg |= MENABLE; 2024737Swnj } 2034737Swnj #endif 204