xref: /csrg-svn/sys/vax/uba/dn.c (revision 8647)
1*8647Sroot /*	dn.c	4.11	82/10/17	*/
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/conf.h"
174737Swnj #include "../h/ioctl.h"
188608Sroot #include "../h/uio.h"
194737Swnj 
208474Sroot #include "../vaxuba/ubavar.h"
218474Sroot 
224737Swnj struct dndevice {
236593Ssam 	u_short	dn_reg[4];
244737Swnj };
254737Swnj 
264737Swnj struct uba_device *dninfo[NDN];
274737Swnj int dnprobe(), dnattach();
284737Swnj u_short dnstd[] = { 0175200 };
294737Swnj struct uba_driver dndriver =
304737Swnj 	{ dnprobe, 0, dnattach, 0, dnstd, "dn", dninfo };
314737Swnj 
326593Ssam #define	CRQ	0x001		/* call request */
336593Ssam #define	DPR	0x002		/* digit present */
346593Ssam #define	MENABLE	0x004		/* master enable */
356593Ssam #define MAINT	0x008		/* maintenance mode */
366593Ssam #define	PND	0x010		/* present next digit */
376593Ssam #define	DSS	0x020		/* data set status */
386593Ssam #define	IENABLE	0x040		/* interrupt enable */
396593Ssam #define	DONE	0x080		/* operation complete */
406593Ssam #define	DLO	0x1000		/* data line occupied */
416593Ssam #define	ACR	0x4000		/* abandon call and retry */
426593Ssam #define	PWI	0x8000		/* power indicate */
434737Swnj 
444737Swnj #define	DNPRI	(PZERO+5)
454737Swnj #define DNUNIT(dev)	(minor(dev)>>2)
464737Swnj #define DNREG(dev)	((dev)&03)
474737Swnj 
484737Swnj #define OBUFSIZ	40		/* largest phone # dialer can handle */
494737Swnj 
504737Swnj /*
514737Swnj  * There's no good way to determine the correct number of dialers attached
524933Swnj  * to a single device (especially when dialers such as Vadic-821 MACS
536593Ssam  * exist which can address four chassis, each with its own dialer).
544737Swnj  */
554737Swnj dnprobe(reg)
564737Swnj 	caddr_t reg;
574737Swnj {
586593Ssam 	register int br, cvec;	/* value-result, must be r11, r10 */
594737Swnj 	register struct dndevice *dnaddr = (struct dndevice *)reg;
604737Swnj 
618608Sroot #ifdef lint
628608Sroot 	br = 0; cvec = 0; br = cvec; cvec = br;
638608Sroot #endif
644737Swnj 	/*
654737Swnj 	 * If there's at least one dialer out there it better be
668608Sroot 	 * at chassis 0.
674737Swnj 	 */
684737Swnj 	dnaddr->dn_reg[0] = MENABLE|IENABLE|DONE;
694737Swnj 	DELAY(5);
704737Swnj 	dnaddr->dn_reg[0] = 0;
717409Skre 	return (sizeof (struct dndevice));
724737Swnj }
734737Swnj 
748608Sroot /*ARGSUSED*/
754737Swnj dnattach(ui)
764737Swnj 	struct uba_device *ui;
778568Sroot {
784933Swnj 
798568Sroot }
808568Sroot 
814737Swnj /*ARGSUSED*/
824737Swnj dnopen(dev, flag)
834737Swnj 	dev_t dev;
84*8647Sroot 	int flag;
854737Swnj {
864737Swnj 	register struct dndevice *dp;
876593Ssam 	register u_short unit, *dnreg;
884737Swnj 	register struct uba_device *ui;
894737Swnj 	register short dialer;
904737Swnj 
914737Swnj 	if ((unit = DNUNIT(dev)) >= NDN || (ui = dninfo[unit]) == 0 ||
928568Sroot 	    ui->ui_alive == 0)
938568Sroot 		return (ENXIO);
946593Ssam 	dialer = DNREG(dev);
956593Ssam 	dp = (struct dndevice *)ui->ui_addr;
968568Sroot 	if (dp->dn_reg[dialer] & PWI)
978568Sroot 		return (ENXIO);
984737Swnj 	dnreg = &(dp->dn_reg[dialer]);
998568Sroot 	if (*dnreg&(DLO|CRQ))
1008568Sroot 		return (EBUSY);
1014737Swnj 	dp->dn_reg[0] |= MENABLE;
1024737Swnj 	*dnreg = IENABLE|MENABLE|CRQ;
1038568Sroot 	return (0);
1044737Swnj }
1054737Swnj 
1064737Swnj /*ARGSUSED*/
1074737Swnj dnclose(dev, flag)
1084737Swnj 	dev_t dev;
1094737Swnj {
1104737Swnj 	register struct dndevice *dp;
1114737Swnj 
1124737Swnj 	dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr;
1134737Swnj 	dp->dn_reg[DNREG(dev)] = MENABLE;
1144737Swnj }
1154737Swnj 
1167833Sroot dnwrite(dev, uio)
1174737Swnj 	dev_t dev;
1187833Sroot 	struct uio *uio;
1194737Swnj {
1206593Ssam 	register u_short *dnreg;
1216593Ssam 	register int cc;
1224737Swnj 	register struct dndevice *dp;
1238608Sroot 	char obuf[OBUFSIZ];
1244737Swnj 	register char *cp;
1254737Swnj 	extern lbolt;
1268491Sroot 	int error;
1274737Swnj 
1284737Swnj 	dp = (struct dndevice *)dninfo[DNUNIT(dev)]->ui_addr;
1294737Swnj 	dnreg = &(dp->dn_reg[DNREG(dev)]);
1307833Sroot 	cc = MIN(uio->uio_resid, OBUFSIZ);
1318608Sroot 	cp = obuf;
132*8647Sroot 	error = uiomove(cp, cc, UIO_WRITE, uio);
1338491Sroot 	if (error)
1348491Sroot 		return (error);
1354737Swnj 	while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0) {
1366593Ssam 		spl4();
1376593Ssam 		if ((*dnreg & PND) == 0 || cc == 0)
1384737Swnj 			sleep((caddr_t)dnreg, DNPRI);
1394737Swnj 		else switch(*cp) {
1404737Swnj 
1414737Swnj 		case '-':
1424737Swnj 			sleep((caddr_t)&lbolt, DNPRI);
1434737Swnj 			sleep((caddr_t)&lbolt, DNPRI);
1444737Swnj 			break;
1454737Swnj 
1464737Swnj 		case 'f':
1474737Swnj 			*dnreg &= ~CRQ;
1484737Swnj 			sleep((caddr_t)&lbolt, DNPRI);
1494737Swnj 			*dnreg |= CRQ;
1504737Swnj 			break;
1514737Swnj 
1524737Swnj 		case '*': case ':':
1534737Swnj 			*cp = 012;
1544737Swnj 			goto dial;
1554737Swnj 
1564737Swnj 		case '#': case ';':
1574737Swnj 			*cp = 013;
1584737Swnj 			goto dial;
1594737Swnj 
1604737Swnj 		case 'e': case '<':
1614737Swnj 			*cp = 014;
1624737Swnj 			goto dial;
1634737Swnj 
1644737Swnj 		case 'w': case '=':
1654737Swnj 			*cp = 015;
1664737Swnj 			goto dial;
1674737Swnj 
1684737Swnj 		default:
1694737Swnj 			if (*cp < '0' || *cp > '9')
1704737Swnj 				break;
1714737Swnj 		dial:
1726593Ssam 			*dnreg = (*cp << 8) | (IENABLE|MENABLE|DPR|CRQ);
1734737Swnj 			sleep((caddr_t)dnreg, DNPRI);
1744737Swnj 		}
1754737Swnj 		cp++, cc--;
1764737Swnj 		spl0();
1774737Swnj 	}
1786593Ssam 	if (*dnreg & (PWI|ACR))
1798491Sroot 		return (EIO);
1808491Sroot 	return (0);
1814737Swnj }
1824737Swnj 
1834737Swnj dnintr(dev)
1844737Swnj 	dev_t dev;
1854737Swnj {
1866593Ssam 	register u_short *basereg, *dnreg;
1874737Swnj 
1886593Ssam 	basereg = (u_short *)dninfo[dev]->ui_addr;
1894737Swnj 	*basereg &= ~MENABLE;
1906593Ssam 	for (dnreg = basereg; dnreg < basereg + 4; dnreg++)
1916593Ssam 		if (*dnreg & DONE) {
1924737Swnj 			*dnreg &= ~(DONE|DPR);
1934737Swnj 			wakeup((caddr_t)dnreg);
1944737Swnj 		}
1954737Swnj 	*basereg |= MENABLE;
1964737Swnj }
1974737Swnj #endif
198