xref: /csrg-svn/sys/vax/uba/dn.c (revision 45804)
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*45804Sbostic  *	@(#)dn.c	7.7 (Berkeley) 12/16/90
723325Smckusick  */
84737Swnj 
94737Swnj #include "dn.h"
104737Swnj #if NDN > 0
114737Swnj /*
124737Swnj  * DN-11 ACU interface
134737Swnj  */
14*45804Sbostic #include "../include/pte.h"
154737Swnj 
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/systm.h"
18*45804Sbostic #include "sys/user.h"
19*45804Sbostic #include "sys/buf.h"
20*45804Sbostic #include "sys/map.h"
21*45804Sbostic #include "sys/conf.h"
22*45804Sbostic #include "sys/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  */
dnprobe(reg)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*/
dnopen(dev,flag)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*/
dnclose(dev,flag)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;
11940728Skarels 	return (0);
1204737Swnj }
1214737Swnj 
dnwrite(dev,uio)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);
14140728Skarels 	while ((*dnreg & (PWI|ACR|DSS)) == 0 && cc >= 0 && error == 0) {
1428715Sroot 		(void) spl4();
1436593Ssam 		if ((*dnreg & PND) == 0 || cc == 0)
14440728Skarels 			error = tsleep((caddr_t)dnreg, DNPRI | PCATCH,
14540728Skarels 			   devout, 0);
1464737Swnj 		else switch(*cp) {
1474737Swnj 
1484737Swnj 		case '-':
14940728Skarels 			error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
15040728Skarels 			    devout, 0);
15140728Skarels 			if (error == 0)
15240728Skarels 				error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
15340728Skarels 				    devout, 0);
1544737Swnj 			break;
1554737Swnj 
1564737Swnj 		case 'f':
1574737Swnj 			*dnreg &= ~CRQ;
15840728Skarels 			error = tsleep((caddr_t)&lbolt, DNPRI | PCATCH,
15940728Skarels 			    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);
18440728Skarels 			error = tsleep((caddr_t)dnreg, DNPRI | PCATCH,
18540728Skarels 			    devout, 0);
1864737Swnj 		}
1874737Swnj 		cp++, cc--;
1884737Swnj 		spl0();
1894737Swnj 	}
19040728Skarels 	if (error)
19140728Skarels 		return (error);
1926593Ssam 	if (*dnreg & (PWI|ACR))
1938491Sroot 		return (EIO);
1948491Sroot 	return (0);
1954737Swnj }
1964737Swnj 
dnintr(dev)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