123317Smckusick /*
229206Smckusick * Copyright (c) 1982, 1986 Regents of the University of California.
323317Smckusick * All rights reserved. The Berkeley software License Agreement
423317Smckusick * specifies the terms and conditions for redistribution.
523317Smckusick *
6*45804Sbostic * @(#)ad.c 7.8 (Berkeley) 12/16/90
723317Smckusick */
87295Ssam
97295Ssam #include "ad.h"
107295Ssam #if NAD > 0
117295Ssam /*
127295Ssam * Data translation AD converter interface -- Bill Reeves
137295Ssam */
14*45804Sbostic #include "../include/pte.h"
159771Ssam
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/ioctl.h"
18*45804Sbostic #include "sys/user.h"
19*45804Sbostic #include "sys/buf.h"
20*45804Sbostic #include "sys/systm.h"
21*45804Sbostic #include "sys/map.h"
227295Ssam
2317073Sbloom #include "ubareg.h"
2417073Sbloom #include "ubavar.h"
2517073Sbloom #include "adreg.h"
268472Sroot
277295Ssam #define ADBUSY 01
287295Ssam #define ADWAITPRI (PZERO+1)
297295Ssam
307295Ssam int adprobe(), adattach();
317295Ssam struct uba_device *addinfo[NAD];
327295Ssam u_short adstd[] = { 0770400, 0000000, 0 };
337295Ssam struct uba_driver addriver =
347295Ssam { adprobe, 0, adattach, 0, adstd, "ad", addinfo, 0, 0 };
357295Ssam
367295Ssam struct ad {
377295Ssam char ad_open;
387295Ssam short int ad_uid;
397295Ssam short int ad_state;
407295Ssam short int ad_softcsr;
417295Ssam short int ad_softdata;
427295Ssam short int ad_chan;
437295Ssam int ad_icnt;
447295Ssam int ad_loop;
457295Ssam } ad[NAD];
467295Ssam
477295Ssam #define ADUNIT(dev) (minor(dev))
487295Ssam
adprobe(reg)497295Ssam adprobe(reg)
507295Ssam caddr_t reg;
517295Ssam {
528566Sroot register int br, cvec; /* value-result */
537295Ssam register struct addevice *adaddr = (struct addevice *) reg;
547295Ssam
557295Ssam adaddr->ad_csr = AD_IENABLE | AD_START;
567295Ssam DELAY(40000);
577295Ssam adaddr->ad_csr = 0;
587417Skre return (sizeof (struct addevice));
597295Ssam }
607295Ssam
618566Sroot /*ARGSUSED*/
627295Ssam adattach(ui)
637295Ssam struct uba_device *ui;
647295Ssam {
658566Sroot
667295Ssam }
677295Ssam
adopen(dev)687295Ssam adopen(dev)
697295Ssam dev_t dev;
707295Ssam {
717295Ssam register struct ad *adp;
727295Ssam register struct uba_device *ui;
737295Ssam
748566Sroot if (ADUNIT(dev) >= NAD || (adp = &ad[ADUNIT(dev)])->ad_open ||
758566Sroot (ui = addinfo[ADUNIT(dev)]) == 0 || ui->ui_alive == 0)
768566Sroot return (ENXIO);
777295Ssam adp->ad_open = 1;
787295Ssam adp->ad_icnt = 0;
797295Ssam adp->ad_state = 0;
807295Ssam adp->ad_uid = u.u_uid;
818566Sroot return (0);
827295Ssam }
837295Ssam
adclose(dev)847295Ssam adclose(dev)
857295Ssam dev_t dev;
867295Ssam {
877295Ssam
887295Ssam ad[ADUNIT(dev)].ad_open = 0;
897295Ssam ad[ADUNIT(dev)].ad_state = 0;
9040727Skarels return (0);
917295Ssam }
927295Ssam
937295Ssam /*ARGSUSED*/
adioctl(dev,cmd,addr,flag)947295Ssam adioctl(dev, cmd, addr, flag)
957295Ssam dev_t dev;
967295Ssam register caddr_t addr;
977295Ssam {
987295Ssam register struct addevice *adaddr =
998566Sroot (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr;
1007295Ssam register struct uba_device *ui = addinfo[ADUNIT(dev)];
1017295Ssam register struct ad *adp;
1027295Ssam register int i;
1037295Ssam short int chan;
1047295Ssam
1057295Ssam switch (cmd) {
1067629Ssam
1077629Ssam case ADIOSCHAN:
1087295Ssam adp = &ad[ADUNIT(dev)];
10931091Smckusick adp->ad_chan = (*(int *)addr)<<8;
1107295Ssam break;
1117629Ssam
1127629Ssam case ADIOGETW:
1137295Ssam adp = &ad[ADUNIT(dev)];
1147295Ssam spl6();
1157295Ssam adaddr->ad_csr = adp->ad_chan;
1167295Ssam i = 1000;
1178566Sroot while (i-- > 0 && (adaddr->ad_csr&037400) != adp->ad_chan) {
1187295Ssam adp->ad_loop++;
1197295Ssam adaddr->ad_csr = adp->ad_chan;
1207295Ssam }
1217295Ssam adp->ad_state |= ADBUSY;
1227295Ssam adaddr->ad_csr |= AD_IENABLE|AD_START;
12340727Skarels i = 0;
1248566Sroot while (adp->ad_state&ADBUSY)
12540727Skarels if (i = tsleep((caddr_t)adp, ADWAITPRI | PCATCH,
12640727Skarels devio, 0)
12740727Skarels break;
1287295Ssam spl0();
12940727Skarels if (i)
13040727Skarels return (i);
13131091Smckusick *(int *)addr = adp->ad_softdata;
1327295Ssam break;
1337629Ssam
1347295Ssam default:
1358566Sroot return (ENOTTY); /* Not a legal ioctl cmd. */
1367295Ssam }
1378566Sroot return (0);
1387295Ssam }
1397295Ssam
1407295Ssam /*ARGSUSED*/
1417295Ssam adintr(dev)
1427295Ssam dev_t dev;
1437295Ssam {
1447295Ssam register struct addevice *adaddr =
1457295Ssam (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr;
1467295Ssam register struct ad *adp = &ad[ADUNIT(dev)];
1477295Ssam
1487295Ssam adp->ad_icnt++;
1497295Ssam adp->ad_softcsr = adaddr->ad_csr;
1507295Ssam adp->ad_softdata = adaddr->ad_data;
1517295Ssam if(adp->ad_state&ADBUSY) {
1527295Ssam adp->ad_state &= ~ADBUSY;
1537295Ssam wakeup((caddr_t)adp);
1547295Ssam }
1557295Ssam }
1567295Ssam
1577295Ssam adreset(uban)
1587295Ssam int uban;
1597295Ssam {
1607295Ssam register int i;
1617295Ssam register struct uba_device *ui;
1627295Ssam register struct ad *adp = ad;
1637295Ssam register struct addevice *adaddr;
1647295Ssam
1657295Ssam for(i = 0; i < NAD; i++, adp++) {
1667295Ssam if((ui = addinfo[i]) == 0 || ui->ui_alive == 0 ||
1677295Ssam ui->ui_ubanum != uban || adp->ad_open == 0)
1687295Ssam continue;
1697295Ssam printf(" ad%d", i);
1707295Ssam if(adp->ad_state&ADBUSY == 0)
1717295Ssam continue;
1727295Ssam adaddr = (struct addevice *) ui->ui_addr;
1737295Ssam adaddr->ad_csr = 0;
1747295Ssam adaddr->ad_csr = adp->ad_chan|AD_IENABLE|AD_START;
1757295Ssam }
1767295Ssam }
1777295Ssam #endif
178