ppi.c revision 60194
128219Smsmith/*-
255939Snsouch * Copyright (c) 1997, 1998, 1999 Nicolas Souchu, Michael Smith
328219Smsmith * All rights reserved.
428219Smsmith *
528219Smsmith * Redistribution and use in source and binary forms, with or without
628219Smsmith * modification, are permitted provided that the following conditions
728219Smsmith * are met:
828219Smsmith * 1. Redistributions of source code must retain the above copyright
928219Smsmith *    notice, this list of conditions and the following disclaimer.
1028219Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1128219Smsmith *    notice, this list of conditions and the following disclaimer in the
1228219Smsmith *    documentation and/or other materials provided with the distribution.
1328219Smsmith *
1428219Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1528219Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1628219Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1728219Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1828219Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1928219Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2028219Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2128219Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2228219Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2328219Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2428219Smsmith * SUCH DAMAGE.
2528219Smsmith *
2650477Speter * $FreeBSD: head/sys/dev/ppbus/ppi.c 60194 2000-05-07 20:46:49Z n_hibma $
2728219Smsmith *
2828219Smsmith */
2955939Snsouch#include "opt_ppb_1284.h"
3055939Snsouch
3128219Smsmith#include <sys/param.h>
3228219Smsmith#include <sys/systm.h>
3355939Snsouch#include <sys/module.h>
3455939Snsouch#include <sys/bus.h>
3528219Smsmith#include <sys/conf.h>
3628219Smsmith#include <sys/kernel.h>
3742475Snsouch#include <sys/uio.h>
3832178Smsmith#include <sys/fcntl.h>
3928219Smsmith
4042475Snsouch#include <machine/clock.h>
4155939Snsouch#include <machine/bus.h>
4255939Snsouch#include <machine/resource.h>
4355939Snsouch#include <sys/rman.h>
4442475Snsouch
4528219Smsmith#include <dev/ppbus/ppbconf.h>
4642475Snsouch#include <dev/ppbus/ppb_msq.h>
4742475Snsouch
4842475Snsouch#ifdef PERIPH_1284
4942475Snsouch#include <dev/ppbus/ppb_1284.h>
5042475Snsouch#endif
5142475Snsouch
5232178Smsmith#include <dev/ppbus/ppi.h>
5328219Smsmith
5455939Snsouch#include "ppbus_if.h"
5555939Snsouch
5655939Snsouch#include <dev/ppbus/ppbio.h>
5755939Snsouch
5842475Snsouch#define BUFSIZE		512
5932178Smsmith
6028257Smsmithstruct ppi_data {
6128257Smsmith
6232178Smsmith    int		ppi_unit;
6332178Smsmith    int		ppi_flags;
6432178Smsmith#define HAVE_PPBUS	(1<<0)
6542475Snsouch#define HAD_PPBUS	(1<<1)
6628257Smsmith
6742475Snsouch    int		ppi_count;
6842475Snsouch    int		ppi_mode;			/* IEEE1284 mode */
6942475Snsouch    char	ppi_buffer[BUFSIZE];
7042475Snsouch
7160194Sn_hibma#ifdef PERIPH_1284
7255939Snsouch    struct resource *intr_resource;	/* interrupt resource */
7355939Snsouch    void *intr_cookie;			/* interrupt registration cookie */
7460194Sn_hibma#endif /* PERIPH_1284 */
7528257Smsmith};
7628257Smsmith
7755939Snsouch#define DEVTOSOFTC(dev) \
7855939Snsouch	((struct ppi_data *)device_get_softc(dev))
7955939Snsouch#define UNITOSOFTC(unit) \
8055939Snsouch	((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit)))
8155939Snsouch#define UNITODEVICE(unit) \
8255939Snsouch	(devclass_get_device(ppi_devclass, (unit)))
8328219Smsmith
8455939Snsouchstatic devclass_t ppi_devclass;
8528219Smsmith
8628219Smsmithstatic	d_open_t	ppiopen;
8728219Smsmithstatic	d_close_t	ppiclose;
8828219Smsmithstatic	d_ioctl_t	ppiioctl;
8942475Snsouchstatic	d_write_t	ppiwrite;
9042475Snsouchstatic	d_read_t	ppiread;
9128219Smsmith
9228261Smsmith#define CDEV_MAJOR 82
9347625Sphkstatic struct cdevsw ppi_cdevsw = {
9447625Sphk	/* open */	ppiopen,
9547625Sphk	/* close */	ppiclose,
9647625Sphk	/* read */	ppiread,
9747625Sphk	/* write */	ppiwrite,
9847625Sphk	/* ioctl */	ppiioctl,
9947625Sphk	/* poll */	nopoll,
10047625Sphk	/* mmap */	nommap,
10147625Sphk	/* strategy */	nostrategy,
10247625Sphk	/* name */	"ppi",
10347625Sphk	/* maj */	CDEV_MAJOR,
10447625Sphk	/* dump */	nodump,
10547625Sphk	/* psize */	nopsize,
10647625Sphk	/* flags */	0,
10747625Sphk	/* bmaj */	-1
10847625Sphk};
10928219Smsmith
11042475Snsouch#ifdef PERIPH_1284
11142475Snsouch
11242475Snsouchstatic void
11355939Snsouchppi_enable_intr(device_t ppidev)
11442475Snsouch{
11542475Snsouch	char r;
11655939Snsouch	device_t ppbus = device_get_parent(ppidev);
11742475Snsouch
11855939Snsouch	r = ppb_rctr(ppbus);
11955939Snsouch	ppb_wctr(ppbus, r | IRQENABLE);
12042475Snsouch
12142475Snsouch	return;
12242475Snsouch}
12342475Snsouch
12442475Snsouchstatic void
12555939Snsouchppi_disable_intr(device_t ppidev)
12642475Snsouch{
12742475Snsouch	char r;
12855939Snsouch        device_t ppbus = device_get_parent(ppidev);
12942475Snsouch
13055939Snsouch	r = ppb_rctr(ppbus);
13155939Snsouch	ppb_wctr(ppbus, r & ~IRQENABLE);
13242475Snsouch
13342475Snsouch	return;
13442475Snsouch}
13542475Snsouch
13642475Snsouch#endif /* PERIPH_1284 */
13742475Snsouch
13856455Speterstatic void
13956455Speterppi_identify(driver_t *driver, device_t parent)
14056455Speter{
14156455Speter
14256455Speter	BUS_ADD_CHILD(parent, 0, "ppi", 0);
14356455Speter}
14456455Speter
14528219Smsmith/*
14655939Snsouch * ppi_probe()
14728219Smsmith */
14855939Snsouchstatic int
14955939Snsouchppi_probe(device_t dev)
15028219Smsmith{
15128219Smsmith	struct ppi_data *ppi;
15228219Smsmith
15355939Snsouch	/* probe is always ok */
15455939Snsouch	device_set_desc(dev, "Parallel I/O");
15555939Snsouch
15655939Snsouch	ppi = DEVTOSOFTC(dev);
15728219Smsmith	bzero(ppi, sizeof(struct ppi_data));
15828219Smsmith
15955939Snsouch	return (0);
16055939Snsouch}
16128219Smsmith
16255939Snsouch/*
16355939Snsouch * ppi_attach()
16455939Snsouch */
16555939Snsouchstatic int
16655939Snsouchppi_attach(device_t dev)
16755939Snsouch{
16860194Sn_hibma#ifdef PERIPH_1284
16955939Snsouch	uintptr_t irq;
17055939Snsouch	int zero = 0;
17160194Sn_hibma#endif /* PERIPH_1284 */
17255939Snsouch	struct ppi_data *ppi = DEVTOSOFTC(dev);
17328219Smsmith
17460194Sn_hibma#ifdef PERIPH_1284
17555939Snsouch	/* retrive the irq */
17655939Snsouch	BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq);
17728219Smsmith
17855939Snsouch	/* declare our interrupt handler */
17955939Snsouch	ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
18055939Snsouch						&zero, irq, irq, 1, RF_ACTIVE);
18160194Sn_hibma#endif /* PERIPH_1284 */
18228219Smsmith
18355939Snsouch	make_dev(&ppi_cdevsw, device_get_unit(dev),	/* XXX cleanup */
18455939Snsouch		 UID_ROOT, GID_WHEEL,
18555939Snsouch		 0600, "ppi%d", device_get_unit(dev));
18628219Smsmith
18755939Snsouch	return (0);
18828219Smsmith}
18928219Smsmith
19060194Sn_hibma#ifdef PERIPH_1284
19142475Snsouch/*
19242475Snsouch * Cable
19342475Snsouch * -----
19442475Snsouch *
19542475Snsouch * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks:
19642475Snsouch *
19742475Snsouch * nStrobe   <-> nAck		1  <-> 10
19842475Snsouch * nAutofd   <-> Busy		11 <-> 14
19942475Snsouch * nSelectin <-> Select		17 <-> 13
20042475Snsouch * nInit     <-> nFault		15 <-> 16
20142475Snsouch *
20242475Snsouch */
20328219Smsmithstatic void
20455939Snsouchppiintr(void *arg)
20528219Smsmith{
20655939Snsouch	device_t ppidev = (device_t)arg;
20755939Snsouch        device_t ppbus = device_get_parent(ppidev);
20855939Snsouch	struct ppi_data *ppi = DEVTOSOFTC(ppidev);
20942475Snsouch
21055939Snsouch	ppi_disable_intr(ppidev);
21142475Snsouch
21255939Snsouch	switch (ppb_1284_get_state(ppbus)) {
21342475Snsouch
21442475Snsouch	/* accept IEEE1284 negociation then wakeup an waiting process to
21542475Snsouch	 * continue negociation at process level */
21642475Snsouch	case PPB_FORWARD_IDLE:
21742475Snsouch		/* Event 1 */
21855939Snsouch		if ((ppb_rstr(ppbus) & (SELECT | nBUSY)) ==
21942475Snsouch							(SELECT | nBUSY)) {
22042475Snsouch			/* IEEE1284 negociation */
22142475Snsouch#ifdef DEBUG_1284
22242475Snsouch			printf("N");
22342475Snsouch#endif
22442475Snsouch
22542475Snsouch			/* Event 2 - prepare for reading the ext. value */
22655939Snsouch			ppb_wctr(ppbus, (PCD | STROBE | nINIT) & ~SELECTIN);
22742475Snsouch
22855939Snsouch			ppb_1284_set_state(ppbus, PPB_NEGOCIATION);
22942475Snsouch
23042475Snsouch		} else {
23142475Snsouch#ifdef DEBUG_1284
23255939Snsouch			printf("0x%x", ppb_rstr(ppbus));
23342475Snsouch#endif
23455939Snsouch			ppb_peripheral_terminate(ppbus, PPB_DONTWAIT);
23542475Snsouch			break;
23642475Snsouch		}
23742475Snsouch
23842475Snsouch		/* wake up any process waiting for negociation from
23942475Snsouch		 * remote master host */
24042475Snsouch
24142475Snsouch		/* XXX should set a variable to warn the process about
24242475Snsouch		 * the interrupt */
24342475Snsouch
24442475Snsouch		wakeup(ppi);
24542475Snsouch		break;
24642475Snsouch	default:
24742475Snsouch#ifdef DEBUG_1284
24855977Speter		printf("?%d", ppb_1284_get_state(ppbus));
24942475Snsouch#endif
25055939Snsouch		ppb_1284_set_state(ppbus, PPB_FORWARD_IDLE);
25155939Snsouch		ppb_set_mode(ppbus, PPB_COMPATIBLE);
25242475Snsouch		break;
25342475Snsouch	}
25442475Snsouch
25555939Snsouch	ppi_enable_intr(ppidev);
25642475Snsouch
25728219Smsmith	return;
25828219Smsmith}
25960194Sn_hibma#endif /* PERIPH_1284 */
26028219Smsmith
26128219Smsmithstatic int
26228219Smsmithppiopen(dev_t dev, int flags, int fmt, struct proc *p)
26328219Smsmith{
26428257Smsmith	u_int unit = minor(dev);
26555939Snsouch	struct ppi_data *ppi = UNITOSOFTC(unit);
26655939Snsouch	device_t ppidev = UNITODEVICE(unit);
26755939Snsouch        device_t ppbus = device_get_parent(ppidev);
26832178Smsmith	int res;
26928257Smsmith
27055939Snsouch	if (!ppi)
27128257Smsmith		return (ENXIO);
27228257Smsmith
27342475Snsouch	if (!(ppi->ppi_flags & HAVE_PPBUS)) {
27455939Snsouch		if ((res = ppb_request_bus(ppbus, ppidev,
27542475Snsouch			(flags & O_NONBLOCK) ? PPB_DONTWAIT :
27642475Snsouch						(PPB_WAIT | PPB_INTR))))
27732178Smsmith			return (res);
27828257Smsmith
27942475Snsouch		ppi->ppi_flags |= HAVE_PPBUS;
28055939Snsouch
28160194Sn_hibma#ifdef PERIPH_1284
28260194Sn_hibma		if (ppi->intr_resource) {
28360194Sn_hibma			/* register our interrupt handler */
28460194Sn_hibma			BUS_SETUP_INTR(device_get_parent(ppidev), ppidev, ppi->intr_resource,
28560194Sn_hibma				       INTR_TYPE_TTY, ppiintr, dev, &ppi->intr_cookie);
28660194Sn_hibma		}
28760194Sn_hibma#endif /* PERIPH_1284 */
28842475Snsouch	}
28942475Snsouch	ppi->ppi_count += 1;
29042475Snsouch
29132178Smsmith	return (0);
29228219Smsmith}
29328219Smsmith
29428219Smsmithstatic int
29528219Smsmithppiclose(dev_t dev, int flags, int fmt, struct proc *p)
29628219Smsmith{
29732178Smsmith	u_int unit = minor(dev);
29855939Snsouch	struct ppi_data *ppi = UNITOSOFTC(unit);
29955939Snsouch	device_t ppidev = UNITODEVICE(unit);
30055939Snsouch        device_t ppbus = device_get_parent(ppidev);
30132178Smsmith
30242475Snsouch	ppi->ppi_count --;
30342475Snsouch	if (!ppi->ppi_count) {
30442475Snsouch
30542475Snsouch#ifdef PERIPH_1284
30655939Snsouch		switch (ppb_1284_get_state(ppbus)) {
30742475Snsouch		case PPB_PERIPHERAL_IDLE:
30855939Snsouch			ppb_peripheral_terminate(ppbus, 0);
30942475Snsouch			break;
31042475Snsouch		case PPB_REVERSE_IDLE:
31142475Snsouch		case PPB_EPP_IDLE:
31242475Snsouch		case PPB_ECP_FORWARD_IDLE:
31342475Snsouch		default:
31455939Snsouch			ppb_1284_terminate(ppbus);
31542475Snsouch			break;
31642475Snsouch		}
31742475Snsouch#endif /* PERIPH_1284 */
31842475Snsouch
31955939Snsouch		/* unregistration of interrupt forced by release */
32055939Snsouch		ppb_release_bus(ppbus, ppidev);
32155939Snsouch
32242475Snsouch		ppi->ppi_flags &= ~HAVE_PPBUS;
32342475Snsouch	}
32442475Snsouch
32532178Smsmith	return (0);
32628219Smsmith}
32728219Smsmith
32842475Snsouch/*
32942475Snsouch * ppiread()
33042475Snsouch *
33142475Snsouch * IEEE1284 compliant read.
33242475Snsouch *
33342475Snsouch * First, try negociation to BYTE then NIBBLE mode
33442475Snsouch * If no data is available, wait for it otherwise transfer as much as possible
33542475Snsouch */
33628219Smsmithstatic int
33742475Snsouchppiread(dev_t dev, struct uio *uio, int ioflag)
33842475Snsouch{
33942475Snsouch#ifdef PERIPH_1284
34042475Snsouch	u_int unit = minor(dev);
34155939Snsouch	struct ppi_data *ppi = UNITOSOFTC(unit);
34255939Snsouch	device_t ppidev = UNITODEVICE(unit);
34355939Snsouch        device_t ppbus = device_get_parent(ppidev);
34442475Snsouch	int len, error = 0;
34542475Snsouch
34655939Snsouch	switch (ppb_1284_get_state(ppbus)) {
34742475Snsouch	case PPB_PERIPHERAL_IDLE:
34855939Snsouch		ppb_peripheral_terminate(ppbus, 0);
34942475Snsouch		/* fall throught */
35042475Snsouch
35142475Snsouch	case PPB_FORWARD_IDLE:
35242475Snsouch		/* if can't negociate NIBBLE mode then try BYTE mode,
35342475Snsouch		 * the peripheral may be a computer
35442475Snsouch		 */
35555939Snsouch		if ((ppb_1284_negociate(ppbus,
35642475Snsouch			ppi->ppi_mode = PPB_NIBBLE, 0))) {
35742475Snsouch
35842475Snsouch			/* XXX Wait 2 seconds to let the remote host some
35942475Snsouch			 * time to terminate its interrupt
36042475Snsouch			 */
36142475Snsouch			tsleep(ppi, PPBPRI, "ppiread", 2*hz);
36242475Snsouch
36355939Snsouch			if ((error = ppb_1284_negociate(ppbus,
36442475Snsouch				ppi->ppi_mode = PPB_BYTE, 0)))
36542475Snsouch				return (error);
36642475Snsouch		}
36742475Snsouch		break;
36842475Snsouch
36942475Snsouch	case PPB_REVERSE_IDLE:
37042475Snsouch	case PPB_EPP_IDLE:
37142475Snsouch	case PPB_ECP_FORWARD_IDLE:
37242475Snsouch	default:
37342475Snsouch		break;
37442475Snsouch	}
37542475Snsouch
37642475Snsouch#ifdef DEBUG_1284
37742475Snsouch	printf("N");
37842475Snsouch#endif
37942475Snsouch	/* read data */
38042475Snsouch	len = 0;
38142475Snsouch	while (uio->uio_resid) {
38255939Snsouch		if ((error = ppb_1284_read(ppbus, ppi->ppi_mode,
38342475Snsouch			ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid),
38442475Snsouch			&len))) {
38542475Snsouch			goto error;
38642475Snsouch		}
38742475Snsouch
38842475Snsouch		if (!len)
38942475Snsouch			goto error;		/* no more data */
39042475Snsouch
39142475Snsouch#ifdef DEBUG_1284
39242475Snsouch		printf("d");
39342475Snsouch#endif
39442475Snsouch		if ((error = uiomove(ppi->ppi_buffer, len, uio)))
39542475Snsouch			goto error;
39642475Snsouch	}
39742475Snsouch
39842475Snsoucherror:
39942475Snsouch
40042475Snsouch#else /* PERIPH_1284 */
40142475Snsouch	int error = ENODEV;
40242475Snsouch#endif
40342475Snsouch
40442475Snsouch	return (error);
40542475Snsouch}
40642475Snsouch
40742475Snsouch/*
40842475Snsouch * ppiwrite()
40942475Snsouch *
41042475Snsouch * IEEE1284 compliant write
41142475Snsouch *
41242475Snsouch * Actually, this is the peripheral side of a remote IEEE1284 read
41342475Snsouch *
41442475Snsouch * The first part of the negociation (IEEE1284 device detection) is
41542475Snsouch * done at interrupt level, then the remaining is done by the writing
41642475Snsouch * process
41742475Snsouch *
41842475Snsouch * Once negociation done, transfer data
41942475Snsouch */
42042475Snsouchstatic int
42142475Snsouchppiwrite(dev_t dev, struct uio *uio, int ioflag)
42242475Snsouch{
42342475Snsouch#ifdef PERIPH_1284
42442475Snsouch	u_int unit = minor(dev);
42555939Snsouch	struct ppi_data *ppi = UNITOSOFTC(unit);
42655939Snsouch	device_t ppidev = UNITODEVICE(unit);
42755939Snsouch        device_t ppbus = device_get_parent(ppidev);
42842475Snsouch	int len, error = 0, sent;
42942475Snsouch
43042475Snsouch#if 0
43142475Snsouch	int ret;
43242475Snsouch
43342475Snsouch	#define ADDRESS		MS_PARAM(0, 0, MS_TYP_PTR)
43442475Snsouch	#define LENGTH		MS_PARAM(0, 1, MS_TYP_INT)
43542475Snsouch
43642475Snsouch	struct ppb_microseq msq[] = {
43742475Snsouch		  { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } },
43842475Snsouch		  MS_RET(0)
43942475Snsouch	};
44042475Snsouch
44142475Snsouch	/* negociate ECP mode */
44255939Snsouch	if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) {
44342475Snsouch		printf("ppiwrite: ECP negociation failed\n");
44442475Snsouch	}
44542475Snsouch
44642475Snsouch	while (!error && (len = min(uio->uio_resid, BUFSIZE))) {
44742475Snsouch		uiomove(ppi->ppi_buffer, len, uio);
44842475Snsouch
44942475Snsouch		ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len);
45042475Snsouch
45155939Snsouch		error = ppb_MS_microseq(ppbus, msq, &ret);
45242475Snsouch	}
45342475Snsouch#endif
45442475Snsouch
45542475Snsouch	/* we have to be peripheral to be able to send data, so
45642475Snsouch	 * wait for the appropriate state
45742475Snsouch	 */
45855957Snsouch 	if (ppb_1284_get_state(ppbus) < PPB_PERIPHERAL_NEGOCIATION)
45955939Snsouch		ppb_1284_terminate(ppbus);
46042475Snsouch
46155957Snsouch 	while (ppb_1284_get_state(ppbus) != PPB_PERIPHERAL_IDLE) {
46242475Snsouch		/* XXX should check a variable before sleeping */
46342475Snsouch#ifdef DEBUG_1284
46442475Snsouch		printf("s");
46542475Snsouch#endif
46642475Snsouch
46755939Snsouch		ppi_enable_intr(ppidev);
46842475Snsouch
46942475Snsouch		/* sleep until IEEE1284 negociation starts */
47042475Snsouch		error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0);
47142475Snsouch
47242475Snsouch		switch (error) {
47342475Snsouch		case 0:
47442475Snsouch			/* negociate peripheral side with BYTE mode */
47555939Snsouch			ppb_peripheral_negociate(ppbus, PPB_BYTE, 0);
47642475Snsouch			break;
47742475Snsouch		case EWOULDBLOCK:
47842475Snsouch			break;
47942475Snsouch		default:
48042475Snsouch			goto error;
48142475Snsouch		}
48242475Snsouch	}
48342475Snsouch#ifdef DEBUG_1284
48442475Snsouch	printf("N");
48542475Snsouch#endif
48642475Snsouch
48742475Snsouch	/* negociation done, write bytes to master host */
48843301Sdillon	while ((len = min(uio->uio_resid, BUFSIZE)) != 0) {
48942475Snsouch		uiomove(ppi->ppi_buffer, len, uio);
49055939Snsouch		if ((error = byte_peripheral_write(ppbus,
49142475Snsouch						ppi->ppi_buffer, len, &sent)))
49242475Snsouch			goto error;
49342475Snsouch#ifdef DEBUG_1284
49442475Snsouch		printf("d");
49542475Snsouch#endif
49642475Snsouch	}
49742475Snsouch
49842475Snsoucherror:
49942475Snsouch
50042475Snsouch#else /* PERIPH_1284 */
50142475Snsouch	int error = ENODEV;
50242475Snsouch#endif
50342475Snsouch
50442475Snsouch	return (error);
50542475Snsouch}
50642475Snsouch
50742475Snsouchstatic int
50836735Sdfrppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
50928219Smsmith{
51032178Smsmith	u_int unit = minor(dev);
51155939Snsouch	device_t ppidev = UNITODEVICE(unit);
51255939Snsouch        device_t ppbus = device_get_parent(ppidev);
51332178Smsmith	int error = 0;
51432178Smsmith	u_int8_t *val = (u_int8_t *)data;
51532178Smsmith
51632178Smsmith	switch (cmd) {
51732178Smsmith
51832178Smsmith	case PPIGDATA:			/* get data register */
51955939Snsouch		*val = ppb_rdtr(ppbus);
52032178Smsmith		break;
52132178Smsmith	case PPIGSTATUS:		/* get status bits */
52255939Snsouch		*val = ppb_rstr(ppbus);
52332178Smsmith		break;
52432178Smsmith	case PPIGCTRL:			/* get control bits */
52555939Snsouch		*val = ppb_rctr(ppbus);
52632178Smsmith		break;
52743433Snsouch	case PPIGEPPD:			/* get EPP data bits */
52855939Snsouch		*val = ppb_repp_D(ppbus);
52932178Smsmith		break;
53032178Smsmith	case PPIGECR:			/* get ECP bits */
53155939Snsouch		*val = ppb_recr(ppbus);
53232178Smsmith		break;
53332178Smsmith	case PPIGFIFO:			/* read FIFO */
53455939Snsouch		*val = ppb_rfifo(ppbus);
53532178Smsmith		break;
53632178Smsmith	case PPISDATA:			/* set data register */
53755939Snsouch		ppb_wdtr(ppbus, *val);
53832178Smsmith		break;
53932178Smsmith	case PPISSTATUS:		/* set status bits */
54055939Snsouch		ppb_wstr(ppbus, *val);
54132178Smsmith		break;
54232178Smsmith	case PPISCTRL:			/* set control bits */
54355939Snsouch		ppb_wctr(ppbus, *val);
54432178Smsmith		break;
54543433Snsouch	case PPISEPPD:			/* set EPP data bits */
54655939Snsouch		ppb_wepp_D(ppbus, *val);
54732178Smsmith		break;
54832178Smsmith	case PPISECR:			/* set ECP bits */
54955939Snsouch		ppb_wecr(ppbus, *val);
55032178Smsmith		break;
55132178Smsmith	case PPISFIFO:			/* write FIFO */
55255939Snsouch		ppb_wfifo(ppbus, *val);
55332178Smsmith		break;
55443433Snsouch	case PPIGEPPA:			/* get EPP address bits */
55555939Snsouch		*val = ppb_repp_A(ppbus);
55643433Snsouch		break;
55743433Snsouch	case PPISEPPA:			/* set EPP address bits */
55855939Snsouch		ppb_wepp_A(ppbus, *val);
55943433Snsouch		break;
56032178Smsmith	default:
56132178Smsmith		error = ENOTTY;
56232178Smsmith		break;
56332178Smsmith	}
56432178Smsmith
56532178Smsmith	return (error);
56628219Smsmith}
56728219Smsmith
56856455Speterstatic device_method_t ppi_methods[] = {
56956455Speter	/* device interface */
57056455Speter	DEVMETHOD(device_identify,	ppi_identify),
57156455Speter	DEVMETHOD(device_probe,		ppi_probe),
57256455Speter	DEVMETHOD(device_attach,	ppi_attach),
57356455Speter
57456455Speter	{ 0, 0 }
57556455Speter};
57656455Speter
57756455Speterstatic driver_t ppi_driver = {
57856455Speter	"ppi",
57956455Speter	ppi_methods,
58056455Speter	sizeof(struct ppi_data),
58156455Speter};
58255939SnsouchDRIVER_MODULE(ppi, ppbus, ppi_driver, ppi_devclass, 0, 0);
583