1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ad.c 7.2 (Berkeley) 05/12/87 7 */ 8 9 #include "ad.h" 10 #if NAD > 0 11 /* 12 * Data translation AD converter interface -- Bill Reeves 13 */ 14 #include "../machine/pte.h" 15 16 #include "param.h" 17 #include "ioctl.h" 18 #include "dir.h" 19 #include "user.h" 20 #include "buf.h" 21 #include "systm.h" 22 #include "map.h" 23 24 #include "ubareg.h" 25 #include "ubavar.h" 26 #include "adreg.h" 27 28 #define ADBUSY 01 29 #define ADWAITPRI (PZERO+1) 30 31 int adprobe(), adattach(); 32 struct uba_device *addinfo[NAD]; 33 u_short adstd[] = { 0770400, 0000000, 0 }; 34 struct uba_driver addriver = 35 { adprobe, 0, adattach, 0, adstd, "ad", addinfo, 0, 0 }; 36 37 struct ad { 38 char ad_open; 39 short int ad_uid; 40 short int ad_state; 41 short int ad_softcsr; 42 short int ad_softdata; 43 short int ad_chan; 44 int ad_icnt; 45 int ad_loop; 46 } ad[NAD]; 47 48 #define ADUNIT(dev) (minor(dev)) 49 50 adprobe(reg) 51 caddr_t reg; 52 { 53 register int br, cvec; /* value-result */ 54 register struct addevice *adaddr = (struct addevice *) reg; 55 56 adaddr->ad_csr = AD_IENABLE | AD_START; 57 DELAY(40000); 58 adaddr->ad_csr = 0; 59 return (sizeof (struct addevice)); 60 } 61 62 /*ARGSUSED*/ 63 adattach(ui) 64 struct uba_device *ui; 65 { 66 67 } 68 69 adopen(dev) 70 dev_t dev; 71 { 72 register struct ad *adp; 73 register struct uba_device *ui; 74 75 if (ADUNIT(dev) >= NAD || (adp = &ad[ADUNIT(dev)])->ad_open || 76 (ui = addinfo[ADUNIT(dev)]) == 0 || ui->ui_alive == 0) 77 return (ENXIO); 78 adp->ad_open = 1; 79 adp->ad_icnt = 0; 80 adp->ad_state = 0; 81 adp->ad_uid = u.u_uid; 82 return (0); 83 } 84 85 adclose(dev) 86 dev_t dev; 87 { 88 89 ad[ADUNIT(dev)].ad_open = 0; 90 ad[ADUNIT(dev)].ad_state = 0; 91 } 92 93 /*ARGSUSED*/ 94 adioctl(dev, cmd, addr, flag) 95 dev_t dev; 96 register caddr_t addr; 97 { 98 register struct addevice *adaddr = 99 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr; 100 register struct uba_device *ui = addinfo[ADUNIT(dev)]; 101 register struct ad *adp; 102 register int i; 103 short int chan; 104 105 switch (cmd) { 106 107 case ADIOSCHAN: 108 adp = &ad[ADUNIT(dev)]; 109 adp->ad_chan = (*(int *)addr)<<8; 110 break; 111 112 case ADIOGETW: 113 adp = &ad[ADUNIT(dev)]; 114 spl6(); 115 adaddr->ad_csr = adp->ad_chan; 116 i = 1000; 117 while (i-- > 0 && (adaddr->ad_csr&037400) != adp->ad_chan) { 118 adp->ad_loop++; 119 adaddr->ad_csr = adp->ad_chan; 120 } 121 adp->ad_state |= ADBUSY; 122 adaddr->ad_csr |= AD_IENABLE|AD_START; 123 while (adp->ad_state&ADBUSY) 124 sleep((caddr_t)adp, ADWAITPRI); 125 spl0(); 126 *(int *)addr = adp->ad_softdata; 127 break; 128 129 default: 130 return (ENOTTY); /* Not a legal ioctl cmd. */ 131 } 132 return (0); 133 } 134 135 /*ARGSUSED*/ 136 adintr(dev) 137 dev_t dev; 138 { 139 register struct addevice *adaddr = 140 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr; 141 register struct ad *adp = &ad[ADUNIT(dev)]; 142 143 adp->ad_icnt++; 144 adp->ad_softcsr = adaddr->ad_csr; 145 adp->ad_softdata = adaddr->ad_data; 146 if(adp->ad_state&ADBUSY) { 147 adp->ad_state &= ~ADBUSY; 148 wakeup((caddr_t)adp); 149 } 150 } 151 152 adreset(uban) 153 int uban; 154 { 155 register int i; 156 register struct uba_device *ui; 157 register struct ad *adp = ad; 158 register struct addevice *adaddr; 159 160 for(i = 0; i < NAD; i++, adp++) { 161 if((ui = addinfo[i]) == 0 || ui->ui_alive == 0 || 162 ui->ui_ubanum != uban || adp->ad_open == 0) 163 continue; 164 printf(" ad%d", i); 165 if(adp->ad_state&ADBUSY == 0) 166 continue; 167 adaddr = (struct addevice *) ui->ui_addr; 168 adaddr->ad_csr = 0; 169 adaddr->ad_csr = adp->ad_chan|AD_IENABLE|AD_START; 170 } 171 } 172 #endif 173