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