1/*- 2 * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * High-level driver for �PD7210 based GPIB cards. 27 * 28 */ 29 30#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * High-level driver for �PD7210 based GPIB cards. 27 * 28 */ 29 30#include <sys/cdefs.h>
|
89 u->wreg[reg] = val; 90 if (reg == AUXMR) 91 u->wreg[8 + (val >> 5)] = val & 0x1f; 92} 93 94void 95upd7210intr(void *arg) 96{ 97 u_int isr1, isr2; 98 struct upd7210 *u; 99 100 u = arg; 101 mtx_lock(&u->mutex); 102 isr1 = upd7210_rd(u, ISR1); 103 isr2 = upd7210_rd(u, ISR2); 104 if (u->busy == 0 || u->irq == NULL || !u->irq(u, 1)) { 105 printf("upd7210intr [%02x %02x %02x", 106 upd7210_rd(u, DIR), isr1, isr2); 107 printf(" %02x %02x %02x %02x %02x] ", 108 upd7210_rd(u, SPSR), 109 upd7210_rd(u, ADSR), 110 upd7210_rd(u, CPTR), 111 upd7210_rd(u, ADR0), 112 upd7210_rd(u, ADR1)); 113 upd7210_print_isr(isr1, isr2); 114 printf("\n"); 115 } 116 mtx_unlock(&u->mutex); 117} 118 119int 120upd7210_take_ctrl_async(struct upd7210 *u) 121{ 122 int i; 123 124 upd7210_wr(u, AUXMR, AUXMR_TCA); 125 126 if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 127 return (0); 128 for (i = 0; i < 20; i++) { 129 DELAY(1); 130 if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 131 return (0); 132 } 133 return (1); 134} 135 136int 137upd7210_goto_standby(struct upd7210 *u) 138{ 139 int i; 140 141 upd7210_wr(u, AUXMR, AUXMR_GTS); 142 143 if (upd7210_rd(u, ADSR) & ADSR_ATN) 144 return (0); 145 for (i = 0; i < 20; i++) { 146 DELAY(1); 147 if (upd7210_rd(u, ADSR) & ADSR_ATN) 148 return (0); 149 } 150 return (1); 151} 152 153/* Unaddressed Listen Only mode */ 154 155static int 156gpib_l_irq(struct upd7210 *u, int intr __unused) 157{ 158 int i; 159 160 if (u->rreg[ISR1] & 1) { 161 i = upd7210_rd(u, DIR); 162 u->buf[u->buf_wp++] = i; 163 u->buf_wp &= (u->bufsize - 1); 164 i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1); 165 if (i < 8) 166 upd7210_wr(u, IMR1, 0); 167 wakeup(u->buf); 168 return (1); 169 } 170 return (0); 171} 172 173static int 174gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 175{ 176 struct upd7210 *u; 177 178 u = dev->si_drv1; 179 180 mtx_lock(&u->mutex); 181 if (u->busy) { 182 mtx_unlock(&u->mutex); 183 return (EBUSY); 184 } 185 u->busy = 1; 186 u->irq = gpib_l_irq; 187 mtx_unlock(&u->mutex); 188 189 u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK); 190 u->bufsize = PAGE_SIZE; 191 u->buf_wp = 0; 192 u->buf_rp = 0; 193 194 upd7210_wr(u, AUXMR, AUXMR_CRST); 195 DELAY(10000); 196 upd7210_wr(u, AUXMR, C_ICR | 8); 197 DELAY(1000); 198 upd7210_wr(u, ADR, 0x60); 199 upd7210_wr(u, ADR, 0xe0); 200 upd7210_wr(u, ADMR, 0x70); 201 upd7210_wr(u, AUXMR, AUXMR_PON); 202 upd7210_wr(u, IMR1, 0x01); 203 return (0); 204} 205 206static int 207gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 208{ 209 struct upd7210 *u; 210 211 u = dev->si_drv1; 212 213 mtx_lock(&u->mutex); 214 u->busy = 0; 215 upd7210_wr(u, AUXMR, AUXMR_CRST); 216 DELAY(10000); 217 upd7210_wr(u, IMR1, 0x00); 218 upd7210_wr(u, IMR2, 0x00); 219 free(u->buf, M_GPIB); 220 u->buf = NULL; 221 mtx_unlock(&u->mutex); 222 return (0); 223} 224 225static int 226gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag) 227{ 228 struct upd7210 *u; 229 int error; 230 size_t z; 231 232 u = dev->si_drv1; 233 error = 0; 234 235 mtx_lock(&u->mutex); 236 while (u->buf_wp == u->buf_rp) { 237 error = msleep(u->buf, &u->mutex, PZERO | PCATCH, 238 "gpibrd", hz); 239 if (error && error != EWOULDBLOCK) { 240 mtx_unlock(&u->mutex); 241 return (error); 242 } 243 } 244 while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) { 245 if (u->buf_wp < u->buf_rp) 246 z = u->bufsize - u->buf_rp; 247 else 248 z = u->buf_wp - u->buf_rp; 249 if (z > uio->uio_resid) 250 z = uio->uio_resid; 251 mtx_unlock(&u->mutex); 252 error = uiomove(u->buf + u->buf_rp, z, uio); 253 mtx_lock(&u->mutex); 254 if (error) 255 break; 256 u->buf_rp += z; 257 u->buf_rp &= (u->bufsize - 1); 258 } 259 if (u->wreg[IMR1] == 0) 260 upd7210_wr(u, IMR1, 0x01); 261 mtx_unlock(&u->mutex); 262 return (error); 263} 264 265static struct cdevsw gpib_l_cdevsw = { 266 .d_version = D_VERSION, 267 .d_name = "gpib_l", 268 .d_open = gpib_l_open, 269 .d_close = gpib_l_close, 270 .d_read = gpib_l_read, 271}; 272 273/* Housekeeping */ 274 275static struct unrhdr *units; 276 277void 278upd7210attach(struct upd7210 *u) 279{ 280 struct cdev *dev; 281 282 if (units == NULL) 283 units = new_unrhdr(0, minor2unit(MAXMINOR), NULL); 284 u->unit = alloc_unr(units); 285 mtx_init(&u->mutex, "gpib", NULL, MTX_DEF); 286 u->cdev = make_dev(&gpib_l_cdevsw, u->unit, 287 UID_ROOT, GID_WHEEL, 0444, 288 "gpib%ul", u->unit); 289 u->cdev->si_drv1 = u; 290 291 dev = make_dev(&gpib_ib_cdevsw, u->unit, 292 UID_ROOT, GID_WHEEL, 0444, 293 "gpib%uib", u->unit); 294 dev->si_drv1 = u; 295 dev_depends(u->cdev, dev); 296} 297 298void 299upd7210detach(struct upd7210 *u) 300{ 301 302 destroy_dev(u->cdev); 303 mtx_destroy(&u->mutex); 304 free_unr(units, u->unit); 305}
| 84 u->wreg[reg] = val; 85 if (reg == AUXMR) 86 u->wreg[8 + (val >> 5)] = val & 0x1f; 87} 88 89void 90upd7210intr(void *arg) 91{ 92 u_int isr1, isr2; 93 struct upd7210 *u; 94 95 u = arg; 96 mtx_lock(&u->mutex); 97 isr1 = upd7210_rd(u, ISR1); 98 isr2 = upd7210_rd(u, ISR2); 99 if (u->busy == 0 || u->irq == NULL || !u->irq(u, 1)) { 100 printf("upd7210intr [%02x %02x %02x", 101 upd7210_rd(u, DIR), isr1, isr2); 102 printf(" %02x %02x %02x %02x %02x] ", 103 upd7210_rd(u, SPSR), 104 upd7210_rd(u, ADSR), 105 upd7210_rd(u, CPTR), 106 upd7210_rd(u, ADR0), 107 upd7210_rd(u, ADR1)); 108 upd7210_print_isr(isr1, isr2); 109 printf("\n"); 110 } 111 mtx_unlock(&u->mutex); 112} 113 114int 115upd7210_take_ctrl_async(struct upd7210 *u) 116{ 117 int i; 118 119 upd7210_wr(u, AUXMR, AUXMR_TCA); 120 121 if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 122 return (0); 123 for (i = 0; i < 20; i++) { 124 DELAY(1); 125 if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 126 return (0); 127 } 128 return (1); 129} 130 131int 132upd7210_goto_standby(struct upd7210 *u) 133{ 134 int i; 135 136 upd7210_wr(u, AUXMR, AUXMR_GTS); 137 138 if (upd7210_rd(u, ADSR) & ADSR_ATN) 139 return (0); 140 for (i = 0; i < 20; i++) { 141 DELAY(1); 142 if (upd7210_rd(u, ADSR) & ADSR_ATN) 143 return (0); 144 } 145 return (1); 146} 147 148/* Unaddressed Listen Only mode */ 149 150static int 151gpib_l_irq(struct upd7210 *u, int intr __unused) 152{ 153 int i; 154 155 if (u->rreg[ISR1] & 1) { 156 i = upd7210_rd(u, DIR); 157 u->buf[u->buf_wp++] = i; 158 u->buf_wp &= (u->bufsize - 1); 159 i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1); 160 if (i < 8) 161 upd7210_wr(u, IMR1, 0); 162 wakeup(u->buf); 163 return (1); 164 } 165 return (0); 166} 167 168static int 169gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 170{ 171 struct upd7210 *u; 172 173 u = dev->si_drv1; 174 175 mtx_lock(&u->mutex); 176 if (u->busy) { 177 mtx_unlock(&u->mutex); 178 return (EBUSY); 179 } 180 u->busy = 1; 181 u->irq = gpib_l_irq; 182 mtx_unlock(&u->mutex); 183 184 u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK); 185 u->bufsize = PAGE_SIZE; 186 u->buf_wp = 0; 187 u->buf_rp = 0; 188 189 upd7210_wr(u, AUXMR, AUXMR_CRST); 190 DELAY(10000); 191 upd7210_wr(u, AUXMR, C_ICR | 8); 192 DELAY(1000); 193 upd7210_wr(u, ADR, 0x60); 194 upd7210_wr(u, ADR, 0xe0); 195 upd7210_wr(u, ADMR, 0x70); 196 upd7210_wr(u, AUXMR, AUXMR_PON); 197 upd7210_wr(u, IMR1, 0x01); 198 return (0); 199} 200 201static int 202gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 203{ 204 struct upd7210 *u; 205 206 u = dev->si_drv1; 207 208 mtx_lock(&u->mutex); 209 u->busy = 0; 210 upd7210_wr(u, AUXMR, AUXMR_CRST); 211 DELAY(10000); 212 upd7210_wr(u, IMR1, 0x00); 213 upd7210_wr(u, IMR2, 0x00); 214 free(u->buf, M_GPIB); 215 u->buf = NULL; 216 mtx_unlock(&u->mutex); 217 return (0); 218} 219 220static int 221gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag) 222{ 223 struct upd7210 *u; 224 int error; 225 size_t z; 226 227 u = dev->si_drv1; 228 error = 0; 229 230 mtx_lock(&u->mutex); 231 while (u->buf_wp == u->buf_rp) { 232 error = msleep(u->buf, &u->mutex, PZERO | PCATCH, 233 "gpibrd", hz); 234 if (error && error != EWOULDBLOCK) { 235 mtx_unlock(&u->mutex); 236 return (error); 237 } 238 } 239 while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) { 240 if (u->buf_wp < u->buf_rp) 241 z = u->bufsize - u->buf_rp; 242 else 243 z = u->buf_wp - u->buf_rp; 244 if (z > uio->uio_resid) 245 z = uio->uio_resid; 246 mtx_unlock(&u->mutex); 247 error = uiomove(u->buf + u->buf_rp, z, uio); 248 mtx_lock(&u->mutex); 249 if (error) 250 break; 251 u->buf_rp += z; 252 u->buf_rp &= (u->bufsize - 1); 253 } 254 if (u->wreg[IMR1] == 0) 255 upd7210_wr(u, IMR1, 0x01); 256 mtx_unlock(&u->mutex); 257 return (error); 258} 259 260static struct cdevsw gpib_l_cdevsw = { 261 .d_version = D_VERSION, 262 .d_name = "gpib_l", 263 .d_open = gpib_l_open, 264 .d_close = gpib_l_close, 265 .d_read = gpib_l_read, 266}; 267 268/* Housekeeping */ 269 270static struct unrhdr *units; 271 272void 273upd7210attach(struct upd7210 *u) 274{ 275 struct cdev *dev; 276 277 if (units == NULL) 278 units = new_unrhdr(0, minor2unit(MAXMINOR), NULL); 279 u->unit = alloc_unr(units); 280 mtx_init(&u->mutex, "gpib", NULL, MTX_DEF); 281 u->cdev = make_dev(&gpib_l_cdevsw, u->unit, 282 UID_ROOT, GID_WHEEL, 0444, 283 "gpib%ul", u->unit); 284 u->cdev->si_drv1 = u; 285 286 dev = make_dev(&gpib_ib_cdevsw, u->unit, 287 UID_ROOT, GID_WHEEL, 0444, 288 "gpib%uib", u->unit); 289 dev->si_drv1 = u; 290 dev_depends(u->cdev, dev); 291} 292 293void 294upd7210detach(struct upd7210 *u) 295{ 296 297 destroy_dev(u->cdev); 298 mtx_destroy(&u->mutex); 299 free_unr(units, u->unit); 300}
|