* Copyright (c) 1982, 1990, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
* @(#)ppi.c 8.2 (Berkeley) %G%
* Printer/Plotter HPIB interface
#include <hp/dev/device.h>
#include <hp300/dev/ppiioctl.h>
int ppiattach(), ppistart();
struct driver ppidriver
= {
ppiattach
, "ppi", ppistart
,
struct ppiparam sc_param
;
#define sc_burst sc_param.burst
#define sc_timo sc_param.timo
#define sc_delay sc_param.delay
register struct hp_device
*hd
;
register struct ppi_softc
*sc
= &ppi_softc
[hd
->hp_unit
];
if ((ppidebug
& PDB_NOCHECK
) == 0)
* XXX: the printer/plotter doesn't seem to really return
* an ID but this will at least prevent us from mistaking
* a cs80 disk or tape for a ppi device.
if (hpibid(hd
->hp_ctlr
, hd
->hp_slave
) & 0x200)
sc
->sc_flags
= PPIF_ALIVE
;
sc
->sc_dq
.dq_ctlr
= hd
->hp_ctlr
;
sc
->sc_dq
.dq_unit
= hd
->hp_unit
;
sc
->sc_dq
.dq_slave
= hd
->hp_slave
;
sc
->sc_dq
.dq_driver
= &ppidriver
;
register int unit
= UNIT(dev
);
register struct ppi_softc
*sc
= &ppi_softc
[unit
];
if (unit
>= NPPI
|| (sc
->sc_flags
& PPIF_ALIVE
) == 0)
if (ppidebug
& PDB_FOLLOW
)
printf("ppiopen(%x, %x): flags %x\n",
dev
, flags
, sc
->sc_flags
);
if (sc
->sc_flags
& PPIF_OPEN
)
sc
->sc_flags
|= PPIF_OPEN
;
sc
->sc_burst
= PPI_BURST
;
sc
->sc_timo
= ppimstohz(PPI_TIMO
);
sc
->sc_delay
= ppimstohz(PPI_DELAY
);
register int unit
= UNIT(dev
);
register struct ppi_softc
*sc
= &ppi_softc
[unit
];
if (ppidebug
& PDB_FOLLOW
)
printf("ppiclose(%x, %x): flags %x\n",
dev
, flags
, sc
->sc_flags
);
sc
->sc_flags
&= ~PPIF_OPEN
;
if (ppidebug
& PDB_FOLLOW
)
printf("ppistart(%x)\n", unit
);
ppi_softc
[unit
].sc_flags
&= ~PPIF_DELAY
;
wakeup(&ppi_softc
[unit
]);
if (ppidebug
& PDB_FOLLOW
)
printf("ppitimo(%x)\n", unit
);
ppi_softc
[unit
].sc_flags
&= ~(PPIF_UIO
|PPIF_TIMO
);
wakeup(&ppi_softc
[unit
]);
if (ppidebug
& PDB_FOLLOW
)
printf("ppiread(%x, %x)\n", dev
, uio
);
return (ppirw(dev
, uio
));
if (ppidebug
& PDB_FOLLOW
)
printf("ppiwrite(%x, %x)\n", dev
, uio
);
return (ppirw(dev
, uio
));
register struct uio
*uio
;
register struct ppi_softc
*sc
= &ppi_softc
[unit
];
register int s
, len
, cnt
;
int error
= 0, gotdata
= 0;
if (ppidebug
& (PDB_FOLLOW
|PDB_IO
))
printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n",
dev
, uio
, uio
->uio_rw
== UIO_READ
? 'R' : 'W',
sc
->sc_burst
, sc
->sc_timo
, uio
->uio_resid
);
buflen
= min(sc
->sc_burst
, uio
->uio_resid
);
buf
= (char *)malloc(buflen
, M_DEVBUF
, M_WAITOK
);
sc
->sc_flags
|= PPIF_UIO
;
sc
->sc_flags
|= PPIF_TIMO
;
timeout(ppitimo
, (void *)unit
, sc
->sc_timo
);
while (uio
->uio_resid
> 0) {
len
= min(buflen
, uio
->uio_resid
);
if (uio
->uio_rw
== UIO_WRITE
) {
error
= uiomove(cp
, len
, uio
);
if ((sc
->sc_flags
& PPIF_UIO
) && hpibreq(&sc
->sc_dq
) == 0)
* Check if we timed out during sleep or uiomove
if ((sc
->sc_flags
& PPIF_UIO
) == 0) {
printf("ppirw: uiomove/sleep timo, flags %x\n",
if (sc
->sc_flags
& PPIF_TIMO
) {
untimeout(ppitimo
, (void *)unit
);
sc
->sc_flags
&= ~PPIF_TIMO
;
if (uio
->uio_rw
== UIO_WRITE
)
cnt
= hpibsend(sc
->sc_hd
->hp_ctlr
, sc
->sc_hd
->hp_slave
,
cnt
= hpibrecv(sc
->sc_hd
->hp_ctlr
, sc
->sc_hd
->hp_slave
,
printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n",
uio
->uio_rw
== UIO_READ
? "recv" : "send",
sc
->sc_hd
->hp_ctlr
, sc
->sc_hd
->hp_slave
,
sc
->sc_sec
, cp
, len
, cnt
);
if (uio
->uio_rw
== UIO_READ
) {
error
= uiomove(cp
, cnt
, uio
);
* Didn't get anything this time, but did in the past.
* Operation timeout (or non-blocking), quit now.
if ((sc
->sc_flags
& PPIF_UIO
) == 0) {
printf("ppirw: timeout/done\n");
* Implement inter-read delay
sc
->sc_flags
|= PPIF_DELAY
;
timeout((void (*)__P((void *)))ppistart
, (void *)unit
,
error
= tsleep(sc
, PCATCH
|PZERO
+1, "hpib", 0);
* Must not call uiomove again til we've used all data
* that we already grabbed.
if (uio
->uio_rw
== UIO_WRITE
&& cnt
!= len
) {
if (sc
->sc_flags
& PPIF_TIMO
) {
untimeout(ppitimo
, (void *)unit
);
sc
->sc_flags
&= ~PPIF_TIMO
;
if (sc
->sc_flags
& PPIF_DELAY
) {
untimeout((void (*)__P((void *)))ppistart
, (void *)unit
);
sc
->sc_flags
&= ~PPIF_DELAY
;
* Adjust for those chars that we uiomove'ed but never wrote
if (uio
->uio_rw
== UIO_WRITE
&& cnt
!= len
) {
uio
->uio_resid
+= (len
- cnt
);
printf("ppirw: short write, adjust by %d\n",
if (ppidebug
& (PDB_FOLLOW
|PDB_IO
))
printf("ppirw: return %d, resid %d\n", error
, uio
->uio_resid
);
ppiioctl(dev
, cmd
, data
, flag
)
struct ppi_softc
*sc
= &ppi_softc
[UNIT(dev
)];
struct ppiparam
*pp
, *upp
;
upp
= (struct ppiparam
*)data
;
upp
->timo
= ppihztoms(pp
->timo
);
upp
->delay
= ppihztoms(pp
->delay
);
upp
= (struct ppiparam
*)data
;
if (upp
->burst
< PPI_BURST_MIN
|| upp
->burst
> PPI_BURST_MAX
||
upp
->delay
< PPI_DELAY_MIN
|| upp
->delay
> PPI_DELAY_MAX
)
pp
->timo
= ppimstohz(upp
->timo
);
pp
->delay
= ppimstohz(upp
->delay
);
sc
->sc_sec
= *(int *)data
;