mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-22 11:17:19 +00:00
1122 lines
32 KiB
C
1122 lines
32 KiB
C
/*
|
|
* GPIB driver for FreeBSD.
|
|
* Version 0.1 (No interrupts, no DMA)
|
|
* Supports National Instruments AT-GPIB and AT-GPIB/TNT boards.
|
|
* (AT-GPIB not tested, but it should work)
|
|
*
|
|
* Written by Fred Cawthorne (fcawth@delphi.umd.edu)
|
|
* Some sections were based partly on the lpt driver.
|
|
* (some remnants may remain)
|
|
*
|
|
* This software is distributed with NO WARRANTIES, not even the implied
|
|
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* The author grants any other persons or organizations permission to use
|
|
* or modify this software as long as this message is kept with the software,
|
|
* all derivative works or modified versions.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
/* Please read the README file for usage information */
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/bus.h>
|
|
#include <i386/isa/gpibreg.h>
|
|
#include <i386/isa/gpib.h>
|
|
#include <i386/isa/isa_device.h>
|
|
|
|
#ifndef COMPAT_OLDISA
|
|
#error "The gpib device requires the old isa compatibility shims"
|
|
#endif
|
|
|
|
#define GPIBPRI (PZERO + 8) | PCATCH
|
|
#define SLEEP_MAX 1000
|
|
#define SLEEP_MIN 4
|
|
|
|
static int initgpib(void);
|
|
static void closegpib(void);
|
|
static int sendgpibfifo(unsigned char device, char *data, int count);
|
|
static int sendrawgpibfifo(unsigned char device, char *data, int count);
|
|
static int readgpibfifo(unsigned char device, char *data, int count);
|
|
#if 0
|
|
static void showregs(void);
|
|
#endif
|
|
static void enableremote(unsigned char device);
|
|
static void gotolocal(unsigned char device);
|
|
static void menableremote(unsigned char *device);
|
|
static void mgotolocal(unsigned char *device);
|
|
static void mtrigger(unsigned char *device);
|
|
static void trigger(unsigned char device);
|
|
static char spoll(unsigned char device);
|
|
|
|
static int gpprobe(struct isa_device *dvp);
|
|
static int gpattach(struct isa_device *dvp);
|
|
|
|
struct isa_driver gpdriver = {
|
|
INTR_TYPE_TTY,
|
|
gpprobe,
|
|
gpattach,
|
|
"gp"
|
|
};
|
|
COMPAT_ISA_DRIVER(gp, gpdriver);
|
|
|
|
static d_open_t gpopen;
|
|
static d_close_t gpclose;
|
|
static d_write_t gpwrite;
|
|
static d_ioctl_t gpioctl;
|
|
|
|
#define CDEV_MAJOR 44
|
|
static struct cdevsw gp_cdevsw = {
|
|
.d_open = gpopen,
|
|
.d_close = gpclose,
|
|
.d_write = gpwrite,
|
|
.d_ioctl = gpioctl,
|
|
.d_name = "gp",
|
|
.d_maj = CDEV_MAJOR,
|
|
};
|
|
|
|
#define BUFSIZE 1024
|
|
#define ATTACHED 0x08
|
|
#define OPEN 0x04
|
|
#define INIT 0x02
|
|
|
|
static struct gpib_softc {
|
|
char *sc_cp; /* current data to send */
|
|
int sc_count; /* bytes queued in sc_inbuf */
|
|
int sc_type; /* Type of gpib controller */
|
|
u_char sc_flags; /* flags (open and internal) */
|
|
char sc_unit; /* gpib device number */
|
|
char *sc_inbuf; /* buffer for data */
|
|
} gpib_sc; /* only support one of these? */
|
|
|
|
static int oldcount;
|
|
static char oldbytes[2];
|
|
|
|
/*
|
|
* Probe routine
|
|
* This needs to be changed to be a bit more robust
|
|
*/
|
|
static int
|
|
gpprobe(struct isa_device *dvp)
|
|
{
|
|
int status;
|
|
struct gpib_softc *sc = &gpib_sc;
|
|
|
|
gpib_port = dvp->id_iobase;
|
|
status = 1;
|
|
sc->sc_type = 3;
|
|
if ((inb(KSR) & 0xF7) == 0x34)
|
|
sc->sc_type = 3;
|
|
else if ((inb(KSR) & 0xF7) == 0x24)
|
|
sc->sc_type = 2;
|
|
else if ((inb(KSR) & 0xF7) == 0x14)
|
|
sc->sc_type = 1;
|
|
else
|
|
status = 0;
|
|
return (status);
|
|
}
|
|
|
|
/*
|
|
* gpattach()
|
|
* Attach device and print the type of card to the screen.
|
|
*/
|
|
static int
|
|
gpattach(isdp)
|
|
struct isa_device *isdp;
|
|
{
|
|
struct gpib_softc *sc = &gpib_sc;
|
|
|
|
sc->sc_unit = isdp->id_unit;
|
|
if (sc->sc_type == 3)
|
|
printf ("gp%d: type AT-GPIB/TNT\n", sc->sc_unit);
|
|
if (sc->sc_type == 2)
|
|
printf ("gp%d: type AT-GPIB chip NAT4882B\n", sc->sc_unit);
|
|
if (sc->sc_type == 1)
|
|
printf ("gp%d: type AT-GPIB chip NAT4882A\n", sc->sc_unit);
|
|
sc->sc_flags |= ATTACHED;
|
|
make_dev(&gp_cdevsw, 0, 0, 0, 0600, "gp");
|
|
return (1);
|
|
}
|
|
|
|
/*
|
|
* gpopen()
|
|
* New open on device.
|
|
*
|
|
* More than 1 open is not allowed on the entire device.
|
|
* i.e. even if gpib5 is open, we can't open another minor device
|
|
*/
|
|
static int
|
|
gpopen(dev, flags, fmt, td)
|
|
dev_t dev;
|
|
int flags;
|
|
int fmt;
|
|
struct thread *td;
|
|
{
|
|
struct gpib_softc *sc = &gpib_sc;
|
|
u_char unit;
|
|
int status;
|
|
|
|
unit = minor(dev);
|
|
|
|
/* minor number out of limits ? */
|
|
if (unit >= 32)
|
|
return (ENXIO);
|
|
|
|
/* Attached ? */
|
|
if (!(sc->sc_flags&ATTACHED)) /* not attached */
|
|
return (ENXIO);
|
|
|
|
/* Already open */
|
|
if (sc->sc_flags&OPEN) /* too late .. */
|
|
return (EBUSY);
|
|
|
|
/* Have memory for buffer? */
|
|
sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
|
|
if (sc->sc_inbuf == 0)
|
|
return (ENOMEM);
|
|
|
|
if (initgpib()) return (EBUSY);
|
|
sc->sc_flags |= OPEN;
|
|
sc->sc_count = 0;
|
|
oldcount = 0;
|
|
if (unit != 0) { /* Someone is trying to access an actual device */
|
|
/* So.. we'll address it to listen */
|
|
enableremote(unit);
|
|
do {
|
|
status = inb(ISR2);
|
|
} while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
|
|
outb(CDOR, (unit & 31) + 32); /* address device to listen */
|
|
|
|
do
|
|
status = inb(ISR2);
|
|
while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
outb(CDOR, 64); /* Address controller (me) to talk */
|
|
do {
|
|
status = inb(ISR2);
|
|
} while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
outb(AUXMR, gts); /* Set to Standby (Controller) */
|
|
|
|
|
|
do {
|
|
status = inb(ISR1);
|
|
} while (!(status & 2) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
|
|
/* Set up the TURBO488 registers */
|
|
outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
|
|
outb(CNT0, 0); /* NOTE this does not enable DMA to the host computer!! */
|
|
outb(CNT1, 0);
|
|
outb(CNT2, 0);
|
|
outb(CNT3, 0);
|
|
outb(CMDR, 0x20);
|
|
outb(CFG, 0x47); /* 16 bit, write, fifo B first, TMOE TIM */
|
|
outb(CMDR, 0x10); /* RESET fifos */
|
|
outb(CMDR, 0x04); /* Tell TURBO488 to GO */
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
/*
|
|
* gpclose()
|
|
* Close gpib device.
|
|
*/
|
|
static int
|
|
gpclose(dev, flags, fmt, td)
|
|
dev_t dev;
|
|
int flags;
|
|
int fmt;
|
|
struct thread *td;
|
|
{
|
|
struct gpib_softc *sc = &gpib_sc;
|
|
unsigned char unit;
|
|
unsigned char status;
|
|
|
|
unit = minor(dev);
|
|
if (unit != 0) { /* Here we need to send the last character with EOS */
|
|
/* and unaddress the listening device */
|
|
|
|
status = EWOULDBLOCK;
|
|
|
|
/* Wait for fifo to become empty */
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while ((inb(ISR3) & 0x04) && status == EWOULDBLOCK); /* Fifo is not empty */
|
|
|
|
outb(CMDR, 0x08); /* Issue STOP to TURBO488 */
|
|
|
|
/* Wait for DONE and STOP */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* not done and stop */
|
|
|
|
/* Shut down TURBO488 */
|
|
outb(IMR2, 0x00); /* DISABLE DMA to turbo488 */
|
|
outb(CMDR, 0x20); /* soft reset turbo488 */
|
|
outb(CMDR, 0x10); /* reset fifos */
|
|
|
|
/* Send last byte with EOI set */
|
|
/* Send second to last byte if there are 2 bytes left */
|
|
if (status == EWOULDBLOCK) {
|
|
do {
|
|
if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
|
|
if (oldcount == 2) {
|
|
outb(CDOR, oldbytes[0]); /* Send second to last byte */
|
|
while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1);
|
|
}
|
|
|
|
outb(AUXMR, seoi); /* Set EOI for the last byte */
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
if (oldcount == 1)
|
|
outb(CDOR, oldbytes[0]);
|
|
else
|
|
if (oldcount == 2)
|
|
outb(CDOR, oldbytes[1]);
|
|
else {
|
|
outb(CDOR, 13); /* Send a CR.. we've got trouble */
|
|
printf("gpib: Warning: gpclose called with nothing left in buffer\n");
|
|
}
|
|
}
|
|
|
|
do {
|
|
if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc,
|
|
GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
|
|
|
|
if (!(inb(ISR1) & 2) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && status == EWOULDBLOCK);
|
|
|
|
outb(AUXMR, tca); /* Regain full control of the bus */
|
|
|
|
do {
|
|
status = inb(ISR2);
|
|
} while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
outb(CDOR, 63); /* unlisten */
|
|
do {
|
|
status = inb(ISR2);
|
|
} while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, 95); /* untalk */
|
|
do {
|
|
status = inb(ISR2);
|
|
} while (!(status & 8) && tsleep((caddr_t)&gpib_sc, GPIBPRI,
|
|
"gpibpoll", 1) == EWOULDBLOCK);
|
|
#if 0
|
|
gotolocal(minor(dev));
|
|
#endif
|
|
}
|
|
closegpib();
|
|
sc->sc_flags = ATTACHED;
|
|
free(sc->sc_inbuf, M_DEVBUF);
|
|
sc->sc_inbuf = 0; /* Sanity */
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* gpwrite()
|
|
* Copy from user's buffer, then write to GPIB device referenced
|
|
* by minor(dev).
|
|
*/
|
|
static int
|
|
gpwrite(dev, uio, ioflag)
|
|
dev_t dev;
|
|
struct uio *uio;
|
|
int ioflag;
|
|
{
|
|
int err, count;
|
|
|
|
/* main loop */
|
|
while ((gpib_sc.sc_count = MIN(BUFSIZE-1, uio->uio_resid)) > 0) {
|
|
/* If there were >1 bytes left over, send them */
|
|
if (oldcount == 2)
|
|
sendrawgpibfifo(minor(dev), oldbytes, 2);
|
|
|
|
/* If there was 1 character left, put it at the beginning
|
|
of the new buffer */
|
|
if (oldcount == 1) {
|
|
(gpib_sc.sc_inbuf)[0] = oldbytes[0];
|
|
gpib_sc.sc_cp = gpib_sc.sc_inbuf;
|
|
/* get from user-space */
|
|
uiomove(gpib_sc.sc_inbuf + 1, gpib_sc.sc_count, uio);
|
|
gpib_sc.sc_count++;
|
|
} else {
|
|
gpib_sc.sc_cp = gpib_sc.sc_inbuf;
|
|
/* get from user-space */
|
|
uiomove(gpib_sc.sc_inbuf, gpib_sc.sc_count, uio);
|
|
}
|
|
|
|
/*
|
|
* NOTE we always leave one byte in case this is the last write
|
|
* so close can send EOI with the last byte There may be 2 bytes
|
|
* since we are doing 16 bit transfers.(note the -1 in the count below)
|
|
*/
|
|
|
|
/* If count <= 2 we'll either pick it up on the next write or on close */
|
|
if (gpib_sc.sc_count>2) {
|
|
count = sendrawgpibfifo(minor(dev), gpib_sc.sc_cp, gpib_sc.sc_count-1);
|
|
err = !count;
|
|
if (err)
|
|
return (1);
|
|
oldcount = gpib_sc.sc_count-count; /* Set # of remaining bytes */
|
|
gpib_sc.sc_count -= count;
|
|
gpib_sc.sc_cp += count; /* point char pointer to remaining bytes */
|
|
}
|
|
else
|
|
oldcount = gpib_sc.sc_count;
|
|
oldbytes[0] = gpib_sc.sc_cp[0];
|
|
if (oldcount == 2)
|
|
oldbytes[1] = gpib_sc.sc_cp[1];
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Here is how you would usually access a GPIB device
|
|
* An exception would be a plotter or printer that you can just
|
|
* write to using a minor device = its GPIB address
|
|
*/
|
|
|
|
static int
|
|
gpioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td)
|
|
{
|
|
struct gpibdata *gd = (struct gpibdata *)data;
|
|
int error, result;
|
|
error = 0;
|
|
|
|
switch (cmd) {
|
|
case GPIBWRITE:
|
|
sendgpibfifo(gd->address, gd->data, *(gd->count));
|
|
error = 0;
|
|
break;
|
|
case GPIBREAD:
|
|
result = readgpibfifo(gd->address, gd->data, *(gd->count));
|
|
*(gd->count) = result;
|
|
error = 0;
|
|
break;
|
|
case GPIBINIT:
|
|
initgpib();
|
|
error = 0;
|
|
break;
|
|
case GPIBTRIGGER:
|
|
trigger(gd->address);
|
|
error = 0;
|
|
break;
|
|
case GPIBREMOTE:
|
|
enableremote(gd->address);
|
|
error = 0;
|
|
break;
|
|
case GPIBLOCAL:
|
|
gotolocal(gd->address);
|
|
error = 0;
|
|
break;
|
|
case GPIBMTRIGGER:
|
|
mtrigger(gd->data);
|
|
error = 0;
|
|
break;
|
|
case GPIBMREMOTE:
|
|
menableremote(gd->data);
|
|
error = 0;
|
|
break;
|
|
case GPIBMLOCAL:
|
|
mgotolocal(gd->data);
|
|
error = 0;
|
|
break;
|
|
case GPIBSPOLL:
|
|
*(gd->data) = spoll(gd->address);
|
|
error = 0;
|
|
break;
|
|
default:
|
|
error = ENODEV;
|
|
}
|
|
|
|
return (error);
|
|
}
|
|
|
|
#if 0
|
|
/* Just in case you want a dump of the registers... */
|
|
|
|
static void showregs() {
|
|
printf ("NAT4882:\n");
|
|
printf ("ISR1=%X\t", inb(ISR1));
|
|
printf ("ISR2=%X\t", inb(ISR2));
|
|
printf ("SPSR=%X\t", inb(SPSR));
|
|
printf ("KSR =%X\t", inb(KSR));
|
|
printf ("ADSR=%X\t", inb(ADSR));
|
|
printf ("CPTR=%X\t", inb(CPTR));
|
|
printf ("SASR=%X\t", inb(SASR));
|
|
printf ("ADR0=%X\t", inb(ADR0));
|
|
printf ("ISR0=%X\t", inb(ISR0));
|
|
printf ("ADR1=%X\t", inb(ADR1));
|
|
printf ("BSR =%X\n", inb(BSR));
|
|
|
|
printf ("Turbo488\n");
|
|
printf ("STS1=%X ", inb(STS1));
|
|
printf ("STS2=%X ", inb(STS2));
|
|
printf ("ISR3=%X ", inb(ISR3));
|
|
printf ("CNT0=%X ", inb(CNT0));
|
|
printf ("CNT1=%X ", inb(CNT1));
|
|
printf ("CNT2=%X ", inb(CNT2));
|
|
printf ("CNT3=%X ", inb(CNT3));
|
|
printf ("IMR3=%X ", inb(IMR3));
|
|
printf ("TIMER=%X\n", inb(TIMER));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Set up the NAT4882 and TURBO488 registers
|
|
* This will be nonsense to you unless you have a data sheet from
|
|
* National Instruments. They should give you one if you call them
|
|
*/
|
|
|
|
static int
|
|
initgpib()
|
|
{
|
|
outb(CMDR, 0x20);
|
|
outb(CFG, 0x16);
|
|
outb(IMR3, 0);
|
|
outb(CMDR, 0x10);
|
|
outb(CNT0, 0);
|
|
outb(CNT1, 0);
|
|
outb(CNT2, 0);
|
|
outb(CNT3, 0);
|
|
outb(INTR, 0); /* Put interrupt line in tri-state mode?? */
|
|
outb(AUXMR, chip_reset);
|
|
|
|
outb(IMR1, 0x10); /* send interrupt to TURBO488 when END received */
|
|
outb(IMR2, 0);
|
|
outb(IMR0, 0x90); /* Do we want nba here too??? */
|
|
outb(ADMR, 1);
|
|
outb(ADR, 0);
|
|
outb(ADR, 128);
|
|
outb(AUXMR, 0xE9);
|
|
outb(AUXMR, 0x49);
|
|
outb(AUXMR, 0x70);
|
|
outb(AUXMR, 0xD0);
|
|
outb(AUXMR, 0xA0);
|
|
|
|
outb(EOSR, 10); /* set EOS message to newline */
|
|
/* should I make the default to interpret END as EOS? */
|
|
/* It isn't now. The following changes this */
|
|
outb(AUXMR, 0x80); /* No special EOS handling */
|
|
#if 0
|
|
outb(AUXMR, 0x88) /* Transmit END with EOS */
|
|
outb(AUXMR, 0x84) /* Set END on EOS received */
|
|
outb(AUXMR, 0x8C) /* Do both of the above */
|
|
#endif
|
|
|
|
#if 0
|
|
/* Not currently supported */
|
|
outb(AUXMR, hldi); /* Perform RFD Holdoff for all data in */
|
|
#endif
|
|
|
|
outb(AUXMR, pon);
|
|
outb(AUXMR, sic_rsc);
|
|
tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
|
|
outb(AUXMR, sic_rsc_off);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* This is kind of Brute force.. But it works */
|
|
|
|
static void
|
|
closegpib()
|
|
{
|
|
outb(AUXMR, chip_reset);
|
|
}
|
|
|
|
/*
|
|
* GPIB ROUTINES:
|
|
* These will also make little sense unless you have a data sheet.
|
|
* Note that the routines with an "m" in the beginning are for
|
|
* accessing multiple devices in one call
|
|
*/
|
|
|
|
/*
|
|
* This is one thing I could not figure out how to do correctly.
|
|
* I tried to use the auxilary command to enable remote, but it
|
|
* never worked. Here, I bypass everything and write to the BSR
|
|
* to enable the remote line. NOTE that these lines are effectively
|
|
* "OR'ed" with the actual lines, so writing a 1 to the bit in the BSR
|
|
* forces the GPIB line true, no matter what the fancy circuitry of the
|
|
* NAT4882 wants to do with it
|
|
*/
|
|
|
|
static void
|
|
enableremote(unsigned char device)
|
|
{
|
|
int status;
|
|
|
|
status = EWOULDBLOCK;
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(BSR, 1); /* Set REN bit on GPIB */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, (device & 31) + 32); /* address device to listen */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, 63); /* Unaddress device */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
}
|
|
|
|
/*
|
|
* This does not release the REM line on the gpib port, because if it did,
|
|
* all the remote devices would go to local mode. This only sends the
|
|
* gotolocal message to one device. Currently, REM is always held true
|
|
* after enableremote is called, and is reset only on a close of the
|
|
* gpib device
|
|
*/
|
|
|
|
static void
|
|
gotolocal(unsigned char device)
|
|
{
|
|
int status;
|
|
|
|
status = EWOULDBLOCK;
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(CDOR, (device & 31) + 32);
|
|
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, 1);
|
|
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 63); /* unaddress device */
|
|
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
}
|
|
|
|
static void
|
|
menableremote(unsigned char *device)
|
|
{
|
|
int status, counter = 0;
|
|
|
|
status = EWOULDBLOCK;
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(BSR, 1); /* Set REN bit on GPIB */
|
|
do {
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, (device[counter] & 31) + 32); /* address device to listen */
|
|
counter++;
|
|
} while (device[counter] < 32);
|
|
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(CDOR, 63); /* Unaddress device */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
}
|
|
|
|
static void
|
|
mgotolocal(unsigned char *device)
|
|
{
|
|
int status;
|
|
int counter = 0;
|
|
|
|
status = EWOULDBLOCK;
|
|
if (device[counter] < 32) do {
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, (device[counter] & 31) + 32);
|
|
counter++;
|
|
} while (device[counter] < 32);
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, 1);
|
|
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 63); /* unaddress device */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 2);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
}
|
|
|
|
/* Trigger a device. What happens depends on how the device is configured. */
|
|
|
|
static void
|
|
trigger(unsigned char device)
|
|
{
|
|
int status;
|
|
|
|
status = EWOULDBLOCK;
|
|
if (device < 32) {
|
|
if (!(inb(ISR2) & 0x08)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, (device & 31) + 32); /* address device to listen */
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
|
|
outb(CDOR, 8); /* send GET */
|
|
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 63); /* unaddress device */
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Trigger multiple devices by addressing them all to listen, and then
|
|
* sending GET
|
|
*/
|
|
|
|
static void
|
|
mtrigger(unsigned char *device)
|
|
{
|
|
int status = EWOULDBLOCK;
|
|
int counter = 0;
|
|
if (device[0] < 32) {
|
|
do {
|
|
if (device[counter] < 32)
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, (device[counter] & 31) + 32); /* address device to listen */
|
|
counter++;
|
|
} while (device[counter] < 32);
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(CDOR, 8); /* send GET */
|
|
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 63); /* unaddress device */
|
|
if (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 0x08) && status == EWOULDBLOCK); /* Wait to send next cmd */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This is not used now, but it should work with NI's 8 bit gpib board
|
|
* since it does not use the TURBO488 registers at all
|
|
*/
|
|
|
|
/*
|
|
* Send data through the TURBO488 FIFOS to a device that is already
|
|
* addressed to listen. This is used by the write call when someone is
|
|
* writing to a printer or plotter, etc...
|
|
*
|
|
* The last byte of each write is held off until either the next
|
|
* write or close, so it can be sent with EOI set
|
|
*/
|
|
|
|
static int
|
|
sendrawgpibfifo(unsigned char device, char *data, int count)
|
|
{
|
|
int status;
|
|
int counter;
|
|
int sleeptime;
|
|
|
|
sleeptime = SLEEP_MIN;
|
|
counter = 0;
|
|
|
|
status = EWOULDBLOCK;
|
|
do {
|
|
/* Wait for fifo to become not full if it is full */
|
|
sleeptime = SLEEP_MIN;
|
|
if (!(inb(ISR3) & 0x08)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", sleeptime);
|
|
if (sleeptime < SLEEP_MAX) sleeptime = sleeptime * 2;
|
|
} while (!(inb(ISR3) & 0x08) && (status == EWOULDBLOCK)); /* Fifo is full */
|
|
|
|
if ((count>1) && (inb(ISR3) & 0x08)) {
|
|
outw(FIFOB, *(unsigned *)(data + counter));
|
|
#if 0
|
|
printf ("gpib: sent:%c, %c\n", data[counter], data[counter + 1]);
|
|
#endif
|
|
counter += 2;
|
|
count -= 2;
|
|
}
|
|
}
|
|
while ((count>1) && (status == EWOULDBLOCK));
|
|
|
|
/*
|
|
* The write routine and close routine must check if there is 1
|
|
* byte left and handle it accordingly
|
|
*/
|
|
|
|
/* Return the number of bytes written to the device */
|
|
return (counter);
|
|
}
|
|
|
|
static int
|
|
sendgpibfifo(unsigned char device, char *data, int count)
|
|
{
|
|
int status;
|
|
int counter;
|
|
int sleeptime;
|
|
|
|
outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
|
|
outb(CNT0, 0);
|
|
outb(CNT1, 0);
|
|
outb(CNT2, 0);
|
|
outb(CNT3, 0);
|
|
status = EWOULDBLOCK;
|
|
if (!(inb(ISR2) & 8)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, (device & 31) + 32); /* address device to listen */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
outb(CDOR, 64); /* Address controller (me) to talk */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(AUXMR, gts); /* Set to Standby (Controller) */
|
|
|
|
sleeptime = SLEEP_MIN;
|
|
counter = 0;
|
|
|
|
outb(CMDR, 0x20);
|
|
outb(CFG, 0x47); /* 16 bit, write, fifo B first, TMOE TIM */
|
|
outb(CMDR, 0x10); /* RESET fifos */
|
|
outb(CCRG, seoi); /* program to send EOI at end */
|
|
outb(CMDR, 0x04); /* Tell TURBO488 to GO */
|
|
status = EWOULDBLOCK;
|
|
do {
|
|
/* Wait for fifo to become not full if it is full */
|
|
sleeptime = SLEEP_MIN;
|
|
if (!(inb(ISR3) & 0x08)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", sleeptime);
|
|
if (sleeptime < SLEEP_MAX) sleeptime = sleeptime * 2;
|
|
} while (!(inb(ISR3) & 0x08) && (status == EWOULDBLOCK)); /* Fifo is full */
|
|
|
|
if ((count>1) && (inb(ISR3) & 0x08)) {
|
|
#if 0
|
|
if (count == 2) outb(CFG, 15 + 0x40); /* send eoi when done */
|
|
#endif
|
|
outw(FIFOB, *(unsigned *)(data + counter));
|
|
|
|
counter += 2;
|
|
count -= 2;
|
|
}
|
|
} while ((count>2) && (status == EWOULDBLOCK));
|
|
|
|
if (count == 2 && status == EWOULDBLOCK) {
|
|
/* Wait for fifo to become not full */
|
|
if (status == EWOULDBLOCK && !(inb(ISR3) & 0x08)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", SLEEP_MIN);
|
|
} while (!(inb(ISR3) & 0x08) && status == EWOULDBLOCK); /* Fifo is full */
|
|
#if 0
|
|
outb(CFG, 0x40 + 15); /* send eoi when done */
|
|
#endif
|
|
outb(FIFOB, data[counter]);
|
|
counter++;
|
|
count--;
|
|
}
|
|
|
|
#if 0
|
|
outb(CMDR, 0x04);
|
|
#endif
|
|
|
|
/* Wait for fifo to become empty */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while ((inb(ISR3) & 0x04) && status == EWOULDBLOCK); /* Fifo is not empty */
|
|
|
|
outb(CMDR, 0x08); /* Issue STOP to TURBO488 */
|
|
|
|
/* Wait for DONE and STOP */
|
|
if (status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* not done and stop */
|
|
|
|
outb(IMR2, 0x00); /* we have to enable DMA (0x30) for turbo488 to work */
|
|
outb(CMDR, 0x20); /* soft reset turbo488 */
|
|
outb(CMDR, 0x10); /* reset fifos */
|
|
|
|
|
|
/*
|
|
* Send last byte with EOI set
|
|
* Here EOI is handled correctly since the string to be sent
|
|
* is actually all sent during the ioctl. (See above)
|
|
*/
|
|
if (count == 1 && status == EWOULDBLOCK) { /* Count should always=1 here */
|
|
|
|
do {
|
|
if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
|
|
|
|
outb(AUXMR, seoi); /* Set EOI for the last byte */
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, data[counter]);
|
|
counter++;
|
|
count--;
|
|
}
|
|
|
|
do {
|
|
if (!(inb(ISR1) & 2)) status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && (status == EWOULDBLOCK));
|
|
|
|
|
|
if (!(inb(ISR1) & 2) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2) && status == EWOULDBLOCK);
|
|
outb(AUXMR, tca); /* Regain full control of the bus */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, 63); /* unlisten */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, 95); /* untalk */
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
return (counter);
|
|
}
|
|
|
|
static int
|
|
readgpibfifo(unsigned char device, char *data, int count)
|
|
{
|
|
int status;
|
|
int status2 = 0;
|
|
int status1;
|
|
int counter;
|
|
unsigned inword;
|
|
|
|
outb(IMR2, 0x30); /* we have to enable DMA (0x30) for turbo488 to work */
|
|
#if 0
|
|
outb(IMR3, 0x1F);
|
|
outb(INTR, 1);
|
|
#endif
|
|
outb(CMDR, 0x20);
|
|
|
|
outb(CFG, 14 + 0x60 + 1); /* Halt on int, read, fifo B first, CCEN TMOE TIM */
|
|
outb(CMDR, 0x10); /* RESET fifos */
|
|
outb(CCRG, tcs); /* program to tcs at end */
|
|
outb(CMDR, 0x08); /* STOP?? */
|
|
|
|
status = EWOULDBLOCK;
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, 32); /* Address controller (me) to listen */
|
|
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, (device & 31) + 64); /* address device to talk */
|
|
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(AUXMR, gts); /* Set to Standby (Controller) */
|
|
|
|
counter = 0;
|
|
|
|
outb(CMDR, 0x04); /* Tell TURBO488 to GO */
|
|
|
|
do {
|
|
status1 = inb(ISR3);
|
|
if (!(status1 & 0x01) && (status1 & 0x04)) {
|
|
status2 = inb(STS2);
|
|
inword = inw(FIFOB);
|
|
*(unsigned *)(data + counter) = inword;
|
|
#if 0
|
|
printf ("Read:%c, %c\n", data[counter], data[counter + 1]);
|
|
#endif
|
|
counter += 2;
|
|
} else {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 4);
|
|
}
|
|
} while (!(status1 & 0x01) && status == EWOULDBLOCK);
|
|
if (!(status2 & 0x04)) { /* Only 1 byte came in on last 16 bit transfer */
|
|
data[counter-1] = 0;
|
|
counter--;
|
|
} else
|
|
data[counter] = 0;
|
|
outb(CMDR, 0x08); /* send STOP */
|
|
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR3) & 0x11) && status == EWOULDBLOCK); /* wait for DONE and STOP */
|
|
outb(AUXMR, 0x55);
|
|
|
|
outb(IMR2, 0x00); /* we have to enable DMA (0x30) for turbo488 to work */
|
|
outb(CMDR, 0x20); /* soft reset turbo488 */
|
|
outb(CMDR, 0x10); /* reset fifos */
|
|
|
|
#if 0
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 2));
|
|
#endif
|
|
outb(AUXMR, tca); /* Regain full control of the bus */
|
|
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
outb(CDOR, 63); /* unlisten */
|
|
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(AUXMR, 0x5E); /* Clear SYNC */
|
|
outb(CDOR, 95); /* untalk */
|
|
do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
return (counter);
|
|
}
|
|
|
|
|
|
/* Return the status byte from device */
|
|
static char
|
|
spoll(unsigned char device)
|
|
{
|
|
int status = EWOULDBLOCK;
|
|
unsigned int statusbyte;
|
|
|
|
if (!(inb(ISR2) & 8)) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, (device & 31) + 64); /* address device to talk */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, 32); /* Address controller (me) to listen */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 0x18); /* Send SPE (serial poll enable) */
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
/* wait for bus to be synced */
|
|
if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
|
|
|
|
outb(AUXMR, gts); /* Set to Standby (Controller) */
|
|
|
|
if (!(inb(ISR1) & 1) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR1) & 1) && status == EWOULDBLOCK);
|
|
outb(AUXMR, 0x5E);
|
|
outb(AUXMR, tcs); /* Take control after next read */
|
|
statusbyte = inb(DIR);
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, 0x19); /* SPD (serial poll disable) */
|
|
|
|
/* wait for bus to be synced */
|
|
if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
|
|
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
outb(CDOR, 95); /* untalk */
|
|
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
outb(AUXMR, 0x5E);
|
|
outb(CDOR, 63); /* unlisten */
|
|
if (!(inb(ISR2) & 8) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR2) & 8) && status == EWOULDBLOCK);
|
|
|
|
/* wait for bus to be synced */
|
|
if (!(inb(ISR0) & 1) && status == EWOULDBLOCK) do {
|
|
status = tsleep((caddr_t)&gpib_sc, GPIBPRI, "gpibpoll", 1);
|
|
} while (!(inb(ISR0) & 1) && status == EWOULDBLOCK);
|
|
|
|
return (statusbyte);
|
|
}
|