xref: /csrg-svn/sys/vax/uba/dn.c (revision 25521)
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