FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/gpib.c
1 /*
2 * GPIB driver for FreeBSD.
3 * Version 0.1 (No interrupts, no DMA)
4 * Supports National Instruments AT-GPIB and AT-GPIB/TNT boards.
5 * (AT-GPIB not tested, but it should work)
6 *
7 * Written by Fred Cawthorne (fcawth@delphi.umd.edu)
8 * Some sections were based partly on the lpt driver.
9 * (some remnants may remain)
10 *
11 * This software is distributed with NO WARRANTIES, not even the implied
12 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * The author grants any other persons or organizations permission to use
15 * or modify this software as long as this message is kept with the software,
16 * all derivative works or modified versions.
17 */
18
19 #include <sys/cdefs.h>
20 __FBSDID("$FreeBSD: releng/5.2/sys/i386/isa/gpib.c 115703 2003-06-02 16:32:55Z obrien $");
21
22 /* Please read the README file for usage information */
23
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/kernel.h>
27 #include <sys/conf.h>
28 #include <sys/uio.h>
29 #include <sys/malloc.h>
30 #include <sys/bus.h>
31 #include <i386/isa/gpibreg.h>
32 #include <i386/isa/gpib.h>
33 #include <i386/isa/isa_device.h>
34
35 #ifndef COMPAT_OLDISA
36 #error "The gpib device requires the old isa compatibility shims"
37 #endif
38
39 #define GPIBPRI (PZERO + 8) | PCATCH
40 #define SLEEP_MAX 1000
41 #define SLEEP_MIN 4
42
43 static int initgpib(void);
44 static void closegpib(void);
45 static int sendgpibfifo(unsigned char device, char *data, int count);
46 static int sendrawgpibfifo(unsigned char device, char *data, int count);
47 static int readgpibfifo(unsigned char device, char *data, int count);
48 #if 0
49 static void showregs(void);
50 #endif
51 static void enableremote(unsigned char device);
52 static void gotolocal(unsigned char device);
53 static void menableremote(unsigned char *device);
54 static void mgotolocal(unsigned char *device);
55 static void mtrigger(unsigned char *device);
56 static void trigger(unsigned char device);
57 static char spoll(unsigned char device);
58
59 static int gpprobe(struct isa_device *dvp);
60 static int gpattach(struct isa_device *dvp);
61
62 struct isa_driver gpdriver = {
63 INTR_TYPE_TTY,
64 gpprobe,
65 gpattach,
66 "gp"
67 };
68 COMPAT_ISA_DRIVER(gp, gpdriver);
69
70 static d_open_t gpopen;
71 static d_close_t gpclose;
72 static d_write_t gpwrite;
73 static d_ioctl_t gpioctl;
74
75 #define CDEV_MAJOR 44
76 static struct cdevsw gp_cdevsw = {
77 .d_open = gpopen,
78 .d_close = gpclose,
79 .d_write = gpwrite,
80 .d_ioctl = gpioctl,
81 .d_name = "gp",
82 .d_maj = CDEV_MAJOR,
83 };
84
85 #define BUFSIZE 1024
86 #define ATTACHED 0x08
87 #define OPEN 0x04
88 #define INIT 0x02
89
90 static struct gpib_softc {
91 char *sc_cp; /* current data to send */
92 int sc_count; /* bytes queued in sc_inbuf */
93 int sc_type; /* Type of gpib controller */
94 u_char sc_flags; /* flags (open and internal) */
95 char sc_unit; /* gpib device number */
96 char *sc_inbuf; /* buffer for data */
97 } gpib_sc; /* only support one of these? */
98
99 static int oldcount;
100 static char oldbytes[2];
101
102 /*
103 * Probe routine
104 * This needs to be changed to be a bit more robust
105 */
106 static int
107 gpprobe(struct isa_device *dvp)
108 {
109 int status;
110 struct gpib_softc *sc = &gpib_sc;
111
112 gpib_port = dvp->id_iobase;
113 status = 1;
114 sc->sc_type = 3;
115 if ((inb(KSR) & 0xF7) == 0x34)
116 sc->sc_type = 3;
117 else if ((inb(KSR) & 0xF7) == 0x24)
118 sc->sc_type = 2;
119 else if ((inb(KSR) & 0xF7) == 0x14)
120 sc->sc_type = 1;
121 else
122 status = 0;
123 return (status);
124 }
125
126 /*
127 * gpattach()
128 * Attach device and print the type of card to the screen.
129 */
130 static int
131 gpattach(isdp)
132 struct isa_device *isdp;
133 {
134 struct gpib_softc *sc = &gpib_sc;
135
136 sc->sc_unit = isdp->id_unit;
137 if (sc->sc_type == 3)
138 printf ("gp%d: type AT-GPIB/TNT\n", sc->sc_unit);
139 if (sc->sc_type == 2)
140 printf ("gp%d: type AT-GPIB chip NAT4882B\n", sc->sc_unit);
141 if (sc->sc_type == 1)
142 printf ("gp%d: type AT-GPIB chip NAT4882A\n", sc->sc_unit);
143 sc->sc_flags |= ATTACHED;
144 make_dev(&gp_cdevsw, 0, 0, 0, 0600, "gp");
145 return (1);
146 }
147
148 /*
149 * gpopen()
150 * New open on device.
151 *
152 * More than 1 open is not allowed on the entire device.
153 * i.e. even if gpib5 is open, we can't open another minor device
154 */
155 static int
156 gpopen(dev, flags, fmt, td)
157 dev_t dev;
158 int flags;
159 int fmt;
160 struct thread *td;
161 {
162 struct gpib_softc *sc = &gpib_sc;
163 u_char unit;
164 int status;
165
166 unit = minor(dev);
167
168 /* minor number out of limits ? */
169 if (unit >= 32)
170 return (ENXIO);
171
172 /* Attached ? */
173 if (!(sc->sc_flags&ATTACHED)) /* not attached */
174 return (ENXIO);
175
176 /* Already open */
177 if (sc->sc_flags&OPEN) /* too late .. */
178 return (EBUSY);
179
180 /* Have memory for buffer? */
181 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
182 if (sc->sc_inbuf == 0)
183 return (ENOMEM);
184
185 if (initgpib()) return (EBUSY);
186 sc->sc_flags |= OPEN;
187 sc->sc_count = 0;
188 oldcount = 0;
189 if (unit != 0) { /* Someone is trying to access an actual device */
190 /* So.. we'll address it to listen */
191 enableremote(unit);
192 do {
193 status = inb(ISR2);
194 } while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
195 "gpibpoll", 1) == EWOULDBLOCK);
196
197 outb(CDOR, (unit & 31) + 32); /* address device to listen */
198
199 do
200 status = inb(ISR2);
201 while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
202 "gpibpoll", 1) == EWOULDBLOCK);
203 outb(CDOR, 64); /* Address controller (me) to talk */
204 do {
205 status = inb(ISR2);
206 } while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
207 "gpibpoll", 1) == EWOULDBLOCK);
208 outb(AUXMR, gts); /* Set to Standby (Controller) */
209
210
211 do {
212 status = inb(ISR1);
213 } while (!(status & 2) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
214 "gpibpoll", 1) == EWOULDBLOCK);
215
216 /* Set up the TURBO488 registers */
217 outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
218 outb(CNT0, 0); /* NOTE this does not enable DMA to the host computer!! */
219 outb(CNT1, 0);
220 outb(CNT2, 0);
221 outb(CNT3, 0);
222 outb(CMDR, 0x20);
223 outb(CFG, 0x47); /* 16 bit, write, fifo B first, TMOE TIM */
224 outb(CMDR, 0x10); /* RESET fifos */
225 outb(CMDR, 0x04); /* Tell TURBO488 to GO */
226 }
227 return (0);
228 }
229
230
231 /*
232 * gpclose()
233 * Close gpib device.
234 */
235 static int
236 gpclose(dev, flags, fmt, td)
237 dev_t dev;
238 int flags;
239 int fmt;
240 struct thread *td;
241 {
242 struct gpib_softc *sc = &gpib_sc;
243 unsigned char unit;
244 unsigned char status;
245
246 unit = minor(dev);
247 if (unit != 0) { /* Here we need to send the last character with EOS */
248 /* and unaddress the listening device */
249
250 status = EWOULDBLOCK;
251
252 /* Wait for fifo to become empty */
253 do {
254 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
255 } while ((inb(ISR3) & 0x04) && status == EWOULDBLOCK); /* Fifo is not empty */
256
257 outb(CMDR, 0x08); /* Issue STOP to TURBO488 */
258
259 /* Wait for DONE and STOP */
260 if (status == EWOULDBLOCK) do {
261 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
262 } while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* not done and stop */
263
264 /* Shut down TURBO488 */
265 outb(IMR2, 0x00); /* DISABLE DMA to turbo488 */
266 outb(CMDR, 0x20); /* soft reset turbo488 */
267 outb(CMDR, 0x10); /* reset fifos */
268
269 /* Send last byte with EOI set */
270 /* Send second to last byte if there are 2 bytes left */
271 if (status == EWOULDBLOCK) {
272 do {
273 if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
274 } while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
275 if (oldcount == 2) {
276 outb(CDOR, oldbytes[0]); /* Send second to last byte */
277 while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
278 status = tsleep((caddr_t)&gpib_sc, GPIBPRI,
279 "gpibpoll", 1);
280 }
281
282 outb(AUXMR, seoi); /* Set EOI for the last byte */
283 outb(AUXMR, 0x5E); /* Clear SYNC */
284 if (oldcount == 1)
285 outb(CDOR, oldbytes[0]);
286 else
287 if (oldcount == 2)
288 outb(CDOR, oldbytes[1]);
289 else {
290 outb(CDOR, 13); /* Send a CR.. we've got trouble */
291 printf("gpib: Warning: gpclose called with nothing left in buffer\n");
292 }
293 }
294
295 do {
296 if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc,
297 GPIBPRI, "gpibpoll", 1);
298 } while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
299
300 if (!(inb(ISR1) & 2) && status == EWOULDBLOCK) do {
301 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
302 } while (!(inb(ISR1) & 2) && status == EWOULDBLOCK);
303
304 outb(AUXMR, tca); /* Regain full control of the bus */
305
306 do {
307 status = inb(ISR2);
308 } while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
309 "gpibpoll", 1) == EWOULDBLOCK);
310 outb(CDOR, 63); /* unlisten */
311 do {
312 status = inb(ISR2);
313 } while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
314 "gpibpoll", 1) == EWOULDBLOCK);
315 outb(AUXMR, 0x5E); /* Clear SYNC */
316 outb(CDOR, 95); /* untalk */
317 do {
318 status = inb(ISR2);
319 } while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
320 "gpibpoll", 1) == EWOULDBLOCK);
321 #if 0
322 gotolocal(minor(dev));
323 #endif
324 }
325 closegpib();
326 sc->sc_flags = ATTACHED;
327 free(sc->sc_inbuf, M_DEVBUF);
328 sc->sc_inbuf = 0; /* Sanity */
329 return (0);
330 }
331
332 /*
333 * gpwrite()
334 * Copy from user's buffer, then write to GPIB device referenced
335 * by minor(dev).
336 */
337 static int
338 gpwrite(dev, uio, ioflag)
339 dev_t dev;
340 struct uio *uio;
341 int ioflag;
342 {
343 int err, count;
344
345 /* main loop */
346 while ((gpib_sc.sc_count = MIN(BUFSIZE-1, uio->uio_resid)) > 0) {
347 /* If there were >1 bytes left over, send them */
348 if (oldcount == 2)
349 sendrawgpibfifo(minor(dev), oldbytes, 2);
350
351 /* If there was 1 character left, put it at the beginning
352 of the new buffer */
353 if (oldcount == 1) {
354 (gpib_sc.sc_inbuf)[0] = oldbytes[0];
355 gpib_sc.sc_cp = gpib_sc.sc_inbuf;
356 /* get from user-space */
357 uiomove(gpib_sc.sc_inbuf + 1, gpib_sc.sc_count, uio);
358 gpib_sc.sc_count++;
359 } else {
360 gpib_sc.sc_cp = gpib_sc.sc_inbuf;
361 /* get from user-space */
362 uiomove(gpib_sc.sc_inbuf, gpib_sc.sc_count, uio);
363 }
364
365 /*
366 * NOTE we always leave one byte in case this is the last write
367 * so close can send EOI with the last byte There may be 2 bytes
368 * since we are doing 16 bit transfers.(note the -1 in the count below)
369 */
370
371 /* If count <= 2 we'll either pick it up on the next write or on close */
372 if (gpib_sc.sc_count>2) {
373 count = sendrawgpibfifo(minor(dev), gpib_sc.sc_cp, gpib_sc.sc_count-1);
374 err = !count;
375 if (err)
376 return (1);
377 oldcount = gpib_sc.sc_count-count; /* Set # of remaining bytes */
378 gpib_sc.sc_count -= count;
379 gpib_sc.sc_cp += count; /* point char pointer to remaining bytes */
380 }
381 else
382 oldcount = gpib_sc.sc_count;
383 oldbytes[0] = gpib_sc.sc_cp[0];
384 if (oldcount == 2)
385 oldbytes[1] = gpib_sc.sc_cp[1];
386 }
387 return (0);
388 }
389
390 /*
391 * Here is how you would usually access a GPIB device
392 * An exception would be a plotter or printer that you can just
393 * write to using a minor device = its GPIB address
394 */
395
396 static int
397 gpioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td)
398 {
399 struct gpibdata *gd = (struct gpibdata *)data;
400 int error, result;
401 error = 0;
402
403 switch (cmd) {
404 case GPIBWRITE:
405 sendgpibfifo(gd->address, gd->data, *(gd->count));
406 error = 0;
407 break;
408 case GPIBREAD:
409 result = readgpibfifo(gd->address, gd->data, *(gd->count));
410 *(gd->count) = result;
411 error = 0;
412 break;
413 case GPIBINIT:
414 initgpib();
415 error = 0;
416 break;
417 case GPIBTRIGGER:
418 trigger(gd->address);
419 error = 0;
420 break;
421 case GPIBREMOTE:
422 enableremote(gd->address);
423 error = 0;
424 break;
425 case GPIBLOCAL:
426 gotolocal(gd->address);
427 error = 0;
428 break;
429 case GPIBMTRIGGER:
430 mtrigger(gd->data);
431 error = 0;
432 break;
433 case GPIBMREMOTE:
434 menableremote(gd->data);
435 error = 0;
436 break;
437 case GPIBMLOCAL:
438 mgotolocal(gd->data);
439 error = 0;
440 break;
441 case GPIBSPOLL:
442 *(gd->data) = spoll(gd->address);
443 error = 0;
444 break;
445 default:
446 error = ENODEV;
447 }
448
449 return (error);
450 }
451
452 #if 0
453 /* Just in case you want a dump of the registers... */
454
455 static void showregs() {
456 printf ("NAT4882:\n");
457 printf ("ISR1=%X\t", inb(ISR1));
458 printf ("ISR2=%X\t", inb(ISR2));
459 printf ("SPSR=%X\t", inb(SPSR));
460 printf ("KSR =%X\t", inb(KSR));
461 printf ("ADSR=%X\t", inb(ADSR));
462 printf ("CPTR=%X\t", inb(CPTR));
463 printf ("SASR=%X\t", inb(SASR));
464 printf ("ADR0=%X\t", inb(ADR0));
465 printf ("ISR0=%X\t", inb(ISR0));
466 printf ("ADR1=%X\t", inb(ADR1));
467 printf ("BSR =%X\n", inb(BSR));
468
469 printf ("Turbo488\n");
470 printf ("STS1=%X ", inb(STS1));
471 printf ("STS2=%X ", inb(STS2));
472 printf ("ISR3=%X ", inb(ISR3));
473 printf ("CNT0=%X ", inb(CNT0));
474 printf ("CNT1=%X ", inb(CNT1));
475 printf ("CNT2=%X ", inb(CNT2));
476 printf ("CNT3=%X ", inb(CNT3));
477 printf ("IMR3=%X ", inb(IMR3));
478 printf ("TIMER=%X\n", inb(TIMER));
479 }
480 #endif
481
482 /*
483 * Set up the NAT4882 and TURBO488 registers
484 * This will be nonsense to you unless you have a data sheet from
485 * National Instruments. They should give you one if you call them
486 */
487
488 static int
489 initgpib()
490 {
491 outb(CMDR, 0x20);
492 outb(CFG, 0x16);
493 outb(IMR3, 0);
494 outb(CMDR, 0x10);
495 outb(CNT0, 0);
496 outb(CNT1, 0);
497 outb(CNT2, 0);
498 outb(CNT3, 0);
499 outb(INTR, 0); /* Put interrupt line in tri-state mode?? */
500 outb(AUXMR, chip_reset);
501
502 outb(IMR1, 0x10); /* send interrupt to TURBO488 when END received */
503 outb(IMR2, 0);
504 outb(IMR0, 0x90); /* Do we want nba here too??? */
505 outb(ADMR, 1);
506 outb(ADR, 0);
507 outb(ADR, 128);
508 outb(AUXMR, 0xE9);
509 outb(AUXMR, 0x49);
510 outb(AUXMR, 0x70);
511 outb(AUXMR, 0xD0);
512 outb(AUXMR, 0xA0);
513
514 outb(EOSR, 10); /* set EOS message to newline */
515 /* should I make the default to interpret END as EOS? */
516 /* It isn't now. The following changes this */
517 outb(AUXMR, 0x80); /* No special EOS handling */
518 #if 0
519 outb(AUXMR, 0x88) /* Transmit END with EOS */
520 outb(AUXMR, 0x84) /* Set END on EOS received */
521 outb(AUXMR, 0x8C) /* Do both of the above */
522 #endif
523
524 #if 0
525 /* Not currently supported */
526 outb(AUXMR, hldi); /* Perform RFD Holdoff for all data in */
527 #endif
528
529 outb(AUXMR, pon);
530 outb(AUXMR, sic_rsc);
531 tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
532
533 outb(AUXMR, sic_rsc_off);
534
535 return (0);
536 }
537
538 /* This is kind of Brute force.. But it works */
539
540 static void
541 closegpib()
542 {
543 outb(AUXMR, chip_reset);
544 }
545
546 /*
547 * GPIB ROUTINES:
548 * These will also make little sense unless you have a data sheet.
549 * Note that the routines with an "m" in the beginning are for
550 * accessing multiple devices in one call
551 */
552
553 /*
554 * This is one thing I could not figure out how to do correctly.
555 * I tried to use the auxilary command to enable remote, but it
556 * never worked. Here, I bypass everything and write to the BSR
557 * to enable the remote line. NOTE that these lines are effectively
558 * "OR'ed" with the actual lines, so writing a 1 to the bit in the BSR
559 * forces the GPIB line true, no matter what the fancy circuitry of the
560 * NAT4882 wants to do with it
561 */
562
563 static void
564 enableremote(unsigned char device)
565 {
566 int status;
567
568 status = EWOULDBLOCK;
569 if (status == EWOULDBLOCK) do {
570 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
571 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
572
573 outb(BSR, 1); /* Set REN bit on GPIB */
574 if (status == EWOULDBLOCK) do {
575 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
576 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
577 outb(CDOR, (device & 31) + 32); /* address device to listen */
578 if (status == EWOULDBLOCK) do {
579 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
580 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
581 outb(CDOR, 63); /* Unaddress device */
582 if (status == EWOULDBLOCK) do {
583 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
584 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
585
586 }
587
588 /*
589 * This does not release the REM line on the gpib port, because if it did,
590 * all the remote devices would go to local mode. This only sends the
591 * gotolocal message to one device. Currently, REM is always held true
592 * after enableremote is called, and is reset only on a close of the
593 * gpib device
594 */
595
596 static void
597 gotolocal(unsigned char device)
598 {
599 int status;
600
601 status = EWOULDBLOCK;
602 if (status == EWOULDBLOCK) do {
603 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
604 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
605
606 outb(CDOR, (device & 31) + 32);
607
608 if (status == EWOULDBLOCK) do {
609 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
610 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
611
612 outb(AUXMR, 0x5E); /* Clear SYNC */
613 outb(CDOR, 1);
614
615 if (status == EWOULDBLOCK) do {
616 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
617 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
618
619 outb(AUXMR, 0x5E);
620 outb(CDOR, 63); /* unaddress device */
621
622 if (status == EWOULDBLOCK) do {
623 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
624 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
625 }
626
627 static void
628 menableremote(unsigned char *device)
629 {
630 int status, counter = 0;
631
632 status = EWOULDBLOCK;
633 if (status == EWOULDBLOCK) do {
634 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
635 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
636
637 outb(BSR, 1); /* Set REN bit on GPIB */
638 do {
639 if (status == EWOULDBLOCK) do {
640 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
641 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
642 outb(CDOR, (device[counter] & 31) + 32); /* address device to listen */
643 counter++;
644 } while (device[counter] < 32);
645
646 if (status == EWOULDBLOCK) do {
647 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
648 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
649
650 outb(CDOR, 63); /* Unaddress device */
651 if (status == EWOULDBLOCK) do {
652 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
653 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
654
655 }
656
657 static void
658 mgotolocal(unsigned char *device)
659 {
660 int status;
661 int counter = 0;
662
663 status = EWOULDBLOCK;
664 if (device[counter] < 32) do {
665 if (status == EWOULDBLOCK) do {
666 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
667 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
668 outb(CDOR, (device[counter] & 31) + 32);
669 counter++;
670 } while (device[counter] < 32);
671 if (status == EWOULDBLOCK) do {
672 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
673 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
674
675 outb(AUXMR, 0x5E); /* Clear SYNC */
676 outb(CDOR, 1);
677
678 if (status == EWOULDBLOCK) do {
679 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
680 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
681 outb(AUXMR, 0x5E);
682 outb(CDOR, 63); /* unaddress device */
683 if (status == EWOULDBLOCK) do {
684 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
685 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
686 }
687
688 /* Trigger a device. What happens depends on how the device is configured. */
689
690 static void
691 trigger(unsigned char device)
692 {
693 int status;
694
695 status = EWOULDBLOCK;
696 if (device < 32) {
697 if (!(inb(ISR2) & 0x08)) do {
698 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
699 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
700 outb(CDOR, (device & 31) + 32); /* address device to listen */
701 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
702 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
703 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
704
705 outb(CDOR, 8); /* send GET */
706
707 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
708 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
709 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
710 outb(AUXMR, 0x5E);
711 outb(CDOR, 63); /* unaddress device */
712 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
713 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
714 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
715 }
716 }
717
718 /*
719 * Trigger multiple devices by addressing them all to listen, and then
720 * sending GET
721 */
722
723 static void
724 mtrigger(unsigned char *device)
725 {
726 int status = EWOULDBLOCK;
727 int counter = 0;
728 if (device[0] < 32) {
729 do {
730 if (device[counter] < 32)
731 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
732 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
733 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
734 outb(CDOR, (device[counter] & 31) + 32); /* address device to listen */
735 counter++;
736 } while (device[counter] < 32);
737 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
738 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
739 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
740 outb(CDOR, 8); /* send GET */
741
742 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
743 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
744 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
745 outb(AUXMR, 0x5E);
746 outb(CDOR, 63); /* unaddress device */
747 if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
748 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
749 } while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
750 }
751 }
752
753 /*
754 * This is not used now, but it should work with NI's 8 bit gpib board
755 * since it does not use the TURBO488 registers at all
756 */
757
758 /*
759 * Send data through the TURBO488 FIFOS to a device that is already
760 * addressed to listen. This is used by the write call when someone is
761 * writing to a printer or plotter, etc...
762 *
763 * The last byte of each write is held off until either the next
764 * write or close, so it can be sent with EOI set
765 */
766
767 static int
768 sendrawgpibfifo(unsigned char device, char *data, int count)
769 {
770 int status;
771 int counter;
772 int sleeptime;
773
774 sleeptime = SLEEP_MIN;
775 counter = 0;
776
777 status = EWOULDBLOCK;
778 do {
779 /* Wait for fifo to become not full if it is full */
780 sleeptime = SLEEP_MIN;
781 if (!(inb(ISR3) & 0x08)) do {
782 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", sleeptime);
783 if (sleeptime < SLEEP_MAX) sleeptime = sleeptime * 2;
784 } while (!(inb(ISR3) & 0x08) && (status == EWOULDBLOCK)); /* Fifo is full */
785
786 if ((count>1) && (inb(ISR3) & 0x08)) {
787 outw(FIFOB, *(unsigned *)(data + counter));
788 #if 0
789 printf ("gpib: sent:%c, %c\n", data[counter], data[counter + 1]);
790 #endif
791 counter += 2;
792 count -= 2;
793 }
794 }
795 while ((count>1) && (status == EWOULDBLOCK));
796
797 /*
798 * The write routine and close routine must check if there is 1
799 * byte left and handle it accordingly
800 */
801
802 /* Return the number of bytes written to the device */
803 return (counter);
804 }
805
806 static int
807 sendgpibfifo(unsigned char device, char *data, int count)
808 {
809 int status;
810 int counter;
811 int sleeptime;
812
813 outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
814 outb(CNT0, 0);
815 outb(CNT1, 0);
816 outb(CNT2, 0);
817 outb(CNT3, 0);
818 status = EWOULDBLOCK;
819 if (!(inb(ISR2) & 8)) do {
820 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
821 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
822
823 outb(CDOR, (device & 31) + 32); /* address device to listen */
824
825 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
826 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
827 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
828 outb(CDOR, 64); /* Address controller (me) to talk */
829
830 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
831 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
832 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
833
834 outb(AUXMR, gts); /* Set to Standby (Controller) */
835
836 sleeptime = SLEEP_MIN;
837 counter = 0;
838
839 outb(CMDR, 0x20);
840 outb(CFG, 0x47); /* 16 bit, write, fifo B first, TMOE TIM */
841 outb(CMDR, 0x10); /* RESET fifos */
842 outb(CCRG, seoi); /* program to send EOI at end */
843 outb(CMDR, 0x04); /* Tell TURBO488 to GO */
844 status = EWOULDBLOCK;
845 do {
846 /* Wait for fifo to become not full if it is full */
847 sleeptime = SLEEP_MIN;
848 if (!(inb(ISR3) & 0x08)) do {
849 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", sleeptime);
850 if (sleeptime < SLEEP_MAX) sleeptime = sleeptime * 2;
851 } while (!(inb(ISR3) & 0x08) && (status == EWOULDBLOCK)); /* Fifo is full */
852
853 if ((count>1) && (inb(ISR3) & 0x08)) {
854 #if 0
855 if (count == 2) outb(CFG, 15 + 0x40); /* send eoi when done */
856 #endif
857 outw(FIFOB, *(unsigned *)(data + counter));
858
859 counter += 2;
860 count -= 2;
861 }
862 } while ((count>2) && (status == EWOULDBLOCK));
863
864 if (count == 2 && status == EWOULDBLOCK) {
865 /* Wait for fifo to become not full */
866 if (status == EWOULDBLOCK && !(inb(ISR3) & 0x08)) do {
867 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", SLEEP_MIN);
868 } while (!(inb(ISR3) & 0x08) && status == EWOULDBLOCK); /* Fifo is full */
869 #if 0
870 outb(CFG, 0x40 + 15); /* send eoi when done */
871 #endif
872 outb(FIFOB, data[counter]);
873 counter++;
874 count--;
875 }
876
877 #if 0
878 outb(CMDR, 0x04);
879 #endif
880
881 /* Wait for fifo to become empty */
882 if (status == EWOULDBLOCK) do {
883 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
884 } while ((inb(ISR3) & 0x04) && status == EWOULDBLOCK); /* Fifo is not empty */
885
886 outb(CMDR, 0x08); /* Issue STOP to TURBO488 */
887
888 /* Wait for DONE and STOP */
889 if (status == EWOULDBLOCK) do {
890 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
891 } while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* not done and stop */
892
893 outb(IMR2, 0x00); /* we have to enable DMA (0x30) for turbo488 to work */
894 outb(CMDR, 0x20); /* soft reset turbo488 */
895 outb(CMDR, 0x10); /* reset fifos */
896
897
898 /*
899 * Send last byte with EOI set
900 * Here EOI is handled correctly since the string to be sent
901 * is actually all sent during the ioctl. (See above)
902 */
903 if (count == 1 && status == EWOULDBLOCK) { /* Count should always=1 here */
904
905 do {
906 if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
907 } while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
908
909 outb(AUXMR, seoi); /* Set EOI for the last byte */
910 outb(AUXMR, 0x5E); /* Clear SYNC */
911 outb(CDOR, data[counter]);
912 counter++;
913 count--;
914 }
915
916 do {
917 if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
918 } while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
919
920
921 if (!(inb(ISR1) & 2) && status == EWOULDBLOCK) do {
922 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
923 } while (!(inb(ISR1) & 2) && status == EWOULDBLOCK);
924 outb(AUXMR, tca); /* Regain full control of the bus */
925
926 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
927 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
928 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
929
930 outb(CDOR, 63); /* unlisten */
931
932 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
933 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
934 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
935
936
937 outb(AUXMR, 0x5E); /* Clear SYNC */
938 outb(CDOR, 95); /* untalk */
939 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
940 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
941 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
942
943 return (counter);
944 }
945
946 static int
947 readgpibfifo(unsigned char device, char *data, int count)
948 {
949 int status;
950 int status2 = 0;
951 int status1;
952 int counter;
953 unsigned inword;
954
955 outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
956 #if 0
957 outb(IMR3, 0x1F);
958 outb(INTR, 1);
959 #endif
960 outb(CMDR, 0x20);
961
962 outb(CFG, 14 + 0x60 + 1); /* Halt on int, read, fifo B first, CCEN TMOE TIM */
963 outb(CMDR, 0x10); /* RESET fifos */
964 outb(CCRG, tcs); /* program to tcs at end */
965 outb(CMDR, 0x08); /* STOP?? */
966
967 status = EWOULDBLOCK;
968 do {
969 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
970 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
971
972 outb(CDOR, 32); /* Address controller (me) to listen */
973
974 do {
975 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
976 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
977
978 outb(CDOR, (device & 31) + 64); /* address device to talk */
979
980 do {
981 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
982 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
983
984 outb(AUXMR, gts); /* Set to Standby (Controller) */
985
986 counter = 0;
987
988 outb(CMDR, 0x04); /* Tell TURBO488 to GO */
989
990 do {
991 status1 = inb(ISR3);
992 if (!(status1 & 0x01) && (status1 & 0x04)) {
993 status2 = inb(STS2);
994 inword = inw(FIFOB);
995 *(unsigned *)(data + counter) = inword;
996 #if 0
997 printf ("Read:%c, %c\n", data[counter], data[counter + 1]);
998 #endif
999 counter += 2;
1000 } else {
1001 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 4);
1002 }
1003 } while (!(status1 & 0x01) && status == EWOULDBLOCK);
1004 if (!(status2 & 0x04)) { /* Only 1 byte came in on last 16 bit transfer */
1005 data[counter-1] = 0;
1006 counter--;
1007 } else
1008 data[counter] = 0;
1009 outb(CMDR, 0x08); /* send STOP */
1010
1011 do {
1012 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1013 } while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* wait for DONE and STOP */
1014 outb(AUXMR, 0x55);
1015
1016 outb(IMR2, 0x00); /* we have to enable DMA (0x30) for turbo488 to work */
1017 outb(CMDR, 0x20); /* soft reset turbo488 */
1018 outb(CMDR, 0x10); /* reset fifos */
1019
1020 #if 0
1021 do {
1022 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1023 } while (!(inb(ISR1) & 2));
1024 #endif
1025 outb(AUXMR, tca); /* Regain full control of the bus */
1026
1027 do {
1028 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1029 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1030 outb(CDOR, 63); /* unlisten */
1031
1032 do {
1033 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1034 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1035
1036 outb(AUXMR, 0x5E); /* Clear SYNC */
1037 outb(CDOR, 95); /* untalk */
1038 do {
1039 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1040 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1041
1042 return (counter);
1043 }
1044
1045
1046 /* Return the status byte from device */
1047 static char
1048 spoll(unsigned char device)
1049 {
1050 int status = EWOULDBLOCK;
1051 unsigned int statusbyte;
1052
1053 if (!(inb(ISR2) & 8)) do {
1054 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1055 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1056
1057 outb(CDOR, (device & 31) + 64); /* address device to talk */
1058
1059 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1060 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1061 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1062
1063 outb(CDOR, 32); /* Address controller (me) to listen */
1064
1065 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1066 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1067 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1068 outb(AUXMR, 0x5E);
1069 outb(CDOR, 0x18); /* Send SPE (serial poll enable) */
1070 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1071 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1072 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1073
1074 /* wait for bus to be synced */
1075 if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
1076 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1077 } while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
1078
1079 outb(AUXMR, gts); /* Set to Standby (Controller) */
1080
1081 if (!(inb(ISR1) & 1) && status == EWOULDBLOCK) do {
1082 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1083 } while (!(inb(ISR1) & 1) && status == EWOULDBLOCK);
1084 outb(AUXMR, 0x5E);
1085 outb(AUXMR, tcs); /* Take control after next read */
1086 statusbyte = inb(DIR);
1087
1088 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1089 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1090 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1091
1092 outb(CDOR, 0x19); /* SPD (serial poll disable) */
1093
1094 /* wait for bus to be synced */
1095 if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
1096 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1097 } while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
1098
1099
1100 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1101 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1102 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1103
1104 outb(CDOR, 95); /* untalk */
1105
1106 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1107 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1108 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1109 outb(AUXMR, 0x5E);
1110 outb(CDOR, 63); /* unlisten */
1111 if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
1112 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1113 } while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
1114
1115 /* wait for bus to be synced */
1116 if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
1117 status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
1118 } while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
1119
1120 return (statusbyte);
1121 }
Cache object: 0a56b2d72f4b8a5f7a26d6c7493d4e41
|