123325Smckusick /* 229218Smckusick * Copyright (c) 1982, 1986 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*40728Skarels * @(#)dn.c 7.6 (Berkeley) 04/03/90 723325Smckusick */ 84737Swnj 94737Swnj #include "dn.h" 104737Swnj #if NDN > 0 114737Swnj /* 124737Swnj * DN-11 ACU interface 134737Swnj */ 1437511Smckusick #include "machine/pte.h" 154737Swnj 1617073Sbloom #include "param.h" 1717073Sbloom #include "systm.h" 1817073Sbloom #include "user.h" 1917073Sbloom #include "buf.h" 2017073Sbloom #include "map.h" 2117073Sbloom #include "conf.h" 2217073Sbloom #include "uio.h" 234737Swnj 2417073Sbloom #include "ubavar.h" 258474Sroot 264737Swnj struct dndevice { 276593Ssam u_short dn_reg[4]; 284737Swnj }; 294737Swnj 304737Swnj struct uba_device *dninfo[NDN]; 318779Sroot int dnprobe(), dnattach(), dnintr(); 3225521Stef u_short dnstd[] = { 0175200, 0 }; 334737Swnj struct uba_driver dndriver = 344737Swnj { dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo }; 354737Swnj 366593Ssam #define CRQ 0x001 /* call request */ 376593Ssam #define DPR 0x002 /* digit present */ 386593Ssam #define MENABLE 0x004 /* master enable */ 396593Ssam #define MAINT 0x008 /* maintenance mode */ 406593Ssam #define PND 0x010 /* present next digit */ 416593Ssam #define DSS 0x020 /* data set status */ 426593Ssam #define IENABLE 0x040 /* interrupt enable */ 436593Ssam #define DONE 0x080 /* operation complete */ 446593Ssam #define DLO 0x1000 /* data line occupied */ 456593Ssam #define ACR 0x4000 /* abandon call and retry */ 466593Ssam #define PWI 0x8000 /* power indicate */ 474737Swnj 484737Swnj #define DNPRI (PZERO+5) 494737Swnj #define DNUNIT(dev) (minor(dev)>>2) 504737Swnj #define DNREG(dev) ((dev)&03) 514737Swnj 524737Swnj #define OBUFSIZ 40 /* largest phone # dialer can handle */ 534737Swnj 544737Swnj /* 554737Swnj * There's no good way to determine the correct number of dialers attached 564933Swnj * to a single device (especially when dialers such as Vadic-821 MACS 576593Ssam * exist which can address four chassis, each with its own dialer). 584737Swnj */ 594737Swnj dnprobe(reg) 604737Swnj caddr_t reg; 614737Swnj { 626593Ssam register int br, cvec; /* value-result, must be r11, r10 */ 634737Swnj register struct dndevice *dnaddr = (struct dndevice *)reg; 644737Swnj 658608Sroot #ifdef lint 668608Sroot br = 0; cvec = 0; br = cvec; cvec = br; 678779Sroot dnintr(0); 688608Sroot #endif 694737Swnj /* 704737Swnj * If there's at least one dialer out there it better be 718608Sroot * at chassis 0. 724737Swnj */ 734737Swnj dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE; 744737Swnj DELAY(5); 754737Swnj dnaddr->dn_reg[0] = 0; 767409Skre return (sizeof (struct dndevice)); 774737Swnj } 784737Swnj 798608Sroot /*ARGSUSED*/ 804737Swnj dnattach(ui) 814737Swnj struct uba_device *ui; 828568Sroot { 834933Swnj 848568Sroot } 858568Sroot 864737Swnj /*ARGSUSED*/ 874737Swnj dnopen(dev, flag) 884737Swnj dev_t dev; 898647Sroot int flag; 904737Swnj { 914737Swnj register struct dndevice *dp; 926593Ssam register u_short unit, *dnreg; 934737Swnj register struct uba_device *ui; 944737Swnj register short dialer; 954737Swnj 964737Swnj if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 || 978568Sroot ui->ui_alive == 0) 988568Sroot return (ENXIO); 996593Ssam dialer = DNREG(dev); 1006593Ssam dp = (struct dndevice *)ui->ui_addr; 1018568Sroot if (dp->dn_reg[dialer] & PWI) 1028568Sroot return (ENXIO); 1034737Swnj dnreg = &(dp->dn_reg[dialer]); 1048568Sroot if (*dnreg&(DLO|CRQ)) 1058568Sroot return (EBUSY); 1064737Swnj dp->dn_reg[0] |= MENABLE; 1074737Swnj *dnreg = IENABLE|MENABLE|CRQ; 1088568Sroot return (0); 1094737Swnj } 1104737Swnj 1114737Swnj /*ARGSUSED*/ 1124737Swnj dnclose(dev, flag) 1134737Swnj dev_t dev; 1144737Swnj { 1154737Swnj register struct dndevice *dp; 1164737Swnj 1174737Swnj dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr; 1184737Swnj dp->dn_reg[DNREG(dev)] = MENABLE; 119*40728Skarels return (0); 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; 13837762Smckusick error = uiomove(cp, cc, uio); 1398491Sroot if (error) 1408491Sroot return (error); 141*40728Skarels while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0 && error == 0) { 1428715Sroot (void) spl4(); 1436593Ssam if ((*dnreg & PND) == 0 || cc == 0) 144*40728Skarels error = tsleep((caddr_t)dnreg, DNPRI | PCATCH, 145*40728Skarels devout, 0); 1464737Swnj else switch(*cp) { 1474737Swnj 1484737Swnj case '-': 149*40728Skarels error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 150*40728Skarels devout, 0); 151*40728Skarels if (error == 0) 152*40728Skarels error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 153*40728Skarels devout, 0); 1544737Swnj break; 1554737Swnj 1564737Swnj case 'f': 1574737Swnj *dnreg &= ~CRQ; 158*40728Skarels error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH, 159*40728Skarels devout, 0); 1604737Swnj *dnreg |= CRQ; 1614737Swnj break; 1624737Swnj 1634737Swnj case '*': case ':': 1644737Swnj *cp = 012; 1654737Swnj goto dial; 1664737Swnj 1674737Swnj case '#': case ';': 1684737Swnj *cp = 013; 1694737Swnj goto dial; 1704737Swnj 1714737Swnj case 'e': case '<': 1724737Swnj *cp = 014; 1734737Swnj goto dial; 1744737Swnj 1754737Swnj case 'w': case '=': 1764737Swnj *cp = 015; 1774737Swnj goto dial; 1784737Swnj 1794737Swnj default: 1804737Swnj if (*cp < '0' || *cp > '9') 1814737Swnj break; 1824737Swnj dial: 1836593Ssam *dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ); 184*40728Skarels error = tsleep((caddr_t)dnreg, DNPRI | PCATCH, 185*40728Skarels devout, 0); 1864737Swnj } 1874737Swnj cp++, cc--; 1884737Swnj spl0(); 1894737Swnj } 190*40728Skarels if (error) 191*40728Skarels return (error); 1926593Ssam if (*dnreg & (PWI|ACR)) 1938491Sroot return (EIO); 1948491Sroot return (0); 1954737Swnj } 1964737Swnj 1974737Swnj dnintr(dev) 1984737Swnj dev_t dev; 1994737Swnj { 2006593Ssam register u_short *basereg, *dnreg; 2014737Swnj 2026593Ssam basereg = (u_short *)dninfo[dev]->ui_addr; 2034737Swnj *basereg &= ~MENABLE; 2046593Ssam for (dnreg = basereg; dnreg < basereg + 4; dnreg++) 2056593Ssam if (*dnreg & DONE) { 2064737Swnj *dnreg &= ~(DONE|DPR); 2074737Swnj wakeup((caddr_t)dnreg); 2084737Swnj } 2094737Swnj *basereg |= MENABLE; 2104737Swnj } 2114737Swnj #endif 212