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.4 (Berkeley) 02/08/90 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 #include "tsleep.h" 28 29 #define ADBUSY 01 30 #define ADWAITPRI (PZERO+1) 31 32 int adprobe(), adattach(); 33 struct uba_device *addinfo[NAD]; 34 u_short adstd[] = { 0770400, 0000000, 0 }; 35 struct uba_driver addriver = 36 { adprobe, 0, adattach, 0, adstd, "ad", addinfo, 0, 0 }; 37 38 struct ad { 39 char ad_open; 40 short int ad_uid; 41 short int ad_state; 42 short int ad_softcsr; 43 short int ad_softdata; 44 short int ad_chan; 45 int ad_icnt; 46 int ad_loop; 47 } ad[NAD]; 48 49 #define ADUNIT(dev) (minor(dev)) 50 51 adprobe(reg) 52 caddr_t reg; 53 { 54 register int br, cvec; /* value-result */ 55 register struct addevice *adaddr = (struct addevice *) reg; 56 57 adaddr->ad_csr = AD_IENABLE | AD_START; 58 DELAY(40000); 59 adaddr->ad_csr = 0; 60 return (sizeof (struct addevice)); 61 } 62 63 /*ARGSUSED*/ 64 adattach(ui) 65 struct uba_device *ui; 66 { 67 68 } 69 70 adopen(dev) 71 dev_t dev; 72 { 73 register struct ad *adp; 74 register struct uba_device *ui; 75 76 if (ADUNIT(dev) >= NAD || (adp = &ad[ADUNIT(dev)])->ad_open || 77 (ui = addinfo[ADUNIT(dev)]) == 0 || ui->ui_alive == 0) 78 return (ENXIO); 79 adp->ad_open = 1; 80 adp->ad_icnt = 0; 81 adp->ad_state = 0; 82 adp->ad_uid = u.u_uid; 83 return (0); 84 } 85 86 adclose(dev) 87 dev_t dev; 88 { 89 90 ad[ADUNIT(dev)].ad_open = 0; 91 ad[ADUNIT(dev)].ad_state = 0; 92 } 93 94 /*ARGSUSED*/ 95 adioctl(dev, cmd, addr, flag) 96 dev_t dev; 97 register caddr_t addr; 98 { 99 register struct addevice *adaddr = 100 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr; 101 register struct uba_device *ui = addinfo[ADUNIT(dev)]; 102 register struct ad *adp; 103 register int i; 104 short int chan; 105 106 switch (cmd) { 107 108 case ADIOSCHAN: 109 adp = &ad[ADUNIT(dev)]; 110 adp->ad_chan = (*(int *)addr)<<8; 111 break; 112 113 case ADIOGETW: 114 adp = &ad[ADUNIT(dev)]; 115 spl6(); 116 adaddr->ad_csr = adp->ad_chan; 117 i = 1000; 118 while (i-- > 0 && (adaddr->ad_csr&037400) != adp->ad_chan) { 119 adp->ad_loop++; 120 adaddr->ad_csr = adp->ad_chan; 121 } 122 adp->ad_state |= ADBUSY; 123 adaddr->ad_csr |= AD_IENABLE|AD_START; 124 while (adp->ad_state&ADBUSY) 125 tsleep((caddr_t)adp, ADWAITPRI, SLP_AD_GETW), 0; 126 spl0(); 127 *(int *)addr = adp->ad_softdata; 128 break; 129 130 default: 131 return (ENOTTY); /* Not a legal ioctl cmd. */ 132 } 133 return (0); 134 } 135 136 /*ARGSUSED*/ 137 adintr(dev) 138 dev_t dev; 139 { 140 register struct addevice *adaddr = 141 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr; 142 register struct ad *adp = &ad[ADUNIT(dev)]; 143 144 adp->ad_icnt++; 145 adp->ad_softcsr = adaddr->ad_csr; 146 adp->ad_softdata = adaddr->ad_data; 147 if(adp->ad_state&ADBUSY) { 148 adp->ad_state &= ~ADBUSY; 149 wakeup((caddr_t)adp); 150 } 151 } 152 153 adreset(uban) 154 int uban; 155 { 156 register int i; 157 register struct uba_device *ui; 158 register struct ad *adp = ad; 159 register struct addevice *adaddr; 160 161 for(i = 0; i < NAD; i++, adp++) { 162 if((ui = addinfo[i]) == 0 || ui->ui_alive == 0 || 163 ui->ui_ubanum != uban || adp->ad_open == 0) 164 continue; 165 printf(" ad%d", i); 166 if(adp->ad_state&ADBUSY == 0) 167 continue; 168 adaddr = (struct addevice *) ui->ui_addr; 169 adaddr->ad_csr = 0; 170 adaddr->ad_csr = adp->ad_chan|AD_IENABLE|AD_START; 171 } 172 } 173 #endif 174