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*40727Skarels * @(#)ad.c 7.7 (Berkeley) 04/03/90 723317Smckusick */ 87295Ssam 97295Ssam #include "ad.h" 107295Ssam #if NAD > 0 117295Ssam /* 127295Ssam * Data translation AD converter interface -- Bill Reeves 137295Ssam */ 1437511Smckusick #include "machine/pte.h" 159771Ssam 1617073Sbloom #include "param.h" 1731091Smckusick #include "ioctl.h" 1817073Sbloom #include "user.h" 1917073Sbloom #include "buf.h" 2017073Sbloom #include "systm.h" 2117073Sbloom #include "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 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 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 847295Ssam adclose(dev) 857295Ssam dev_t dev; 867295Ssam { 877295Ssam 887295Ssam ad[ADUNIT(dev)].ad_open = 0; 897295Ssam ad[ADUNIT(dev)].ad_state = 0; 90*40727Skarels return (0); 917295Ssam } 927295Ssam 937295Ssam /*ARGSUSED*/ 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; 123*40727Skarels i = 0; 1248566Sroot while (adp->ad_state&ADBUSY) 125*40727Skarels if (i = tsleep((caddr_t)adp, ADWAITPRI | PCATCH, 126*40727Skarels devio, 0) 127*40727Skarels break; 1287295Ssam spl0(); 129*40727Skarels if (i) 130*40727Skarels 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