ppi.c revision 127189
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 * 2628219Smsmith * 2728219Smsmith */ 28119418Sobrien 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ppbus/ppi.c 127189 2004-03-18 21:10:11Z guido $"); 3155939Snsouch#include "opt_ppb_1284.h" 3255939Snsouch 3328219Smsmith#include <sys/param.h> 3428219Smsmith#include <sys/systm.h> 3555939Snsouch#include <sys/module.h> 3655939Snsouch#include <sys/bus.h> 3728219Smsmith#include <sys/conf.h> 3828219Smsmith#include <sys/kernel.h> 3942475Snsouch#include <sys/uio.h> 4032178Smsmith#include <sys/fcntl.h> 4128219Smsmith 4255939Snsouch#include <machine/bus.h> 4355939Snsouch#include <machine/resource.h> 4455939Snsouch#include <sys/rman.h> 4542475Snsouch 4628219Smsmith#include <dev/ppbus/ppbconf.h> 4742475Snsouch#include <dev/ppbus/ppb_msq.h> 4842475Snsouch 4942475Snsouch#ifdef PERIPH_1284 5042475Snsouch#include <dev/ppbus/ppb_1284.h> 5142475Snsouch#endif 5242475Snsouch 5332178Smsmith#include <dev/ppbus/ppi.h> 5428219Smsmith 5555939Snsouch#include "ppbus_if.h" 5655939Snsouch 5755939Snsouch#include <dev/ppbus/ppbio.h> 5855939Snsouch 5942475Snsouch#define BUFSIZE 512 6032178Smsmith 6128257Smsmithstruct ppi_data { 6228257Smsmith 6332178Smsmith int ppi_unit; 6432178Smsmith int ppi_flags; 6532178Smsmith#define HAVE_PPBUS (1<<0) 6642475Snsouch#define HAD_PPBUS (1<<1) 6728257Smsmith 6842475Snsouch int ppi_count; 6942475Snsouch int ppi_mode; /* IEEE1284 mode */ 7042475Snsouch char ppi_buffer[BUFSIZE]; 7142475Snsouch 7260194Sn_hibma#ifdef PERIPH_1284 7355939Snsouch struct resource *intr_resource; /* interrupt resource */ 7455939Snsouch void *intr_cookie; /* interrupt registration cookie */ 7560194Sn_hibma#endif /* PERIPH_1284 */ 7628257Smsmith}; 7728257Smsmith 7855939Snsouch#define DEVTOSOFTC(dev) \ 7955939Snsouch ((struct ppi_data *)device_get_softc(dev)) 8055939Snsouch#define UNITOSOFTC(unit) \ 8155939Snsouch ((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit))) 8255939Snsouch#define UNITODEVICE(unit) \ 8355939Snsouch (devclass_get_device(ppi_devclass, (unit))) 8428219Smsmith 8555939Snsouchstatic devclass_t ppi_devclass; 8628219Smsmith 8728219Smsmithstatic d_open_t ppiopen; 8828219Smsmithstatic d_close_t ppiclose; 8928219Smsmithstatic d_ioctl_t ppiioctl; 9042475Snsouchstatic d_write_t ppiwrite; 9142475Snsouchstatic d_read_t ppiread; 9228219Smsmith 9347625Sphkstatic struct cdevsw ppi_cdevsw = { 94126080Sphk .d_version = D_VERSION, 95126080Sphk .d_flags = D_NEEDGIANT, 96111815Sphk .d_open = ppiopen, 97111815Sphk .d_close = ppiclose, 98111815Sphk .d_read = ppiread, 99111815Sphk .d_write = ppiwrite, 100111815Sphk .d_ioctl = ppiioctl, 101111815Sphk .d_name = "ppi", 10247625Sphk}; 10328219Smsmith 10442475Snsouch#ifdef PERIPH_1284 10542475Snsouch 10642475Snsouchstatic void 10755939Snsouchppi_enable_intr(device_t ppidev) 10842475Snsouch{ 10942475Snsouch char r; 11055939Snsouch device_t ppbus = device_get_parent(ppidev); 11142475Snsouch 11255939Snsouch r = ppb_rctr(ppbus); 11355939Snsouch ppb_wctr(ppbus, r | IRQENABLE); 11442475Snsouch 11542475Snsouch return; 11642475Snsouch} 11742475Snsouch 11842475Snsouchstatic void 11955939Snsouchppi_disable_intr(device_t ppidev) 12042475Snsouch{ 12142475Snsouch char r; 12255939Snsouch device_t ppbus = device_get_parent(ppidev); 12342475Snsouch 12455939Snsouch r = ppb_rctr(ppbus); 12555939Snsouch ppb_wctr(ppbus, r & ~IRQENABLE); 12642475Snsouch 12742475Snsouch return; 12842475Snsouch} 12942475Snsouch 13042475Snsouch#endif /* PERIPH_1284 */ 13142475Snsouch 13256455Speterstatic void 13356455Speterppi_identify(driver_t *driver, device_t parent) 13456455Speter{ 13556455Speter 136127189Sguido device_t dev; 137127189Sguido 138127189Sguido dev = device_find_child(parent, "ppi", 0); 139127189Sguido if (!dev) 140127189Sguido BUS_ADD_CHILD(parent, 0, "ppi", -1); 14156455Speter} 14256455Speter 14328219Smsmith/* 14455939Snsouch * ppi_probe() 14528219Smsmith */ 14655939Snsouchstatic int 14755939Snsouchppi_probe(device_t dev) 14828219Smsmith{ 14928219Smsmith struct ppi_data *ppi; 15028219Smsmith 15155939Snsouch /* probe is always ok */ 15255939Snsouch device_set_desc(dev, "Parallel I/O"); 15355939Snsouch 15455939Snsouch ppi = DEVTOSOFTC(dev); 15528219Smsmith bzero(ppi, sizeof(struct ppi_data)); 15628219Smsmith 15755939Snsouch return (0); 15855939Snsouch} 15928219Smsmith 16055939Snsouch/* 16155939Snsouch * ppi_attach() 16255939Snsouch */ 16355939Snsouchstatic int 16455939Snsouchppi_attach(device_t dev) 16555939Snsouch{ 16660194Sn_hibma#ifdef PERIPH_1284 16755939Snsouch uintptr_t irq; 16855939Snsouch int zero = 0; 16955939Snsouch struct ppi_data *ppi = DEVTOSOFTC(dev); 17028219Smsmith 17155939Snsouch /* retrive the irq */ 17255939Snsouch BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq); 17328219Smsmith 17455939Snsouch /* declare our interrupt handler */ 17555939Snsouch ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, 17655939Snsouch &zero, irq, irq, 1, RF_ACTIVE); 17760194Sn_hibma#endif /* PERIPH_1284 */ 17828219Smsmith 17955939Snsouch make_dev(&ppi_cdevsw, device_get_unit(dev), /* XXX cleanup */ 18055939Snsouch UID_ROOT, GID_WHEEL, 18155939Snsouch 0600, "ppi%d", device_get_unit(dev)); 18228219Smsmith 18355939Snsouch return (0); 18428219Smsmith} 18528219Smsmith 18660194Sn_hibma#ifdef PERIPH_1284 18742475Snsouch/* 18842475Snsouch * Cable 18942475Snsouch * ----- 19042475Snsouch * 19142475Snsouch * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 19242475Snsouch * 19342475Snsouch * nStrobe <-> nAck 1 <-> 10 19442475Snsouch * nAutofd <-> Busy 11 <-> 14 19542475Snsouch * nSelectin <-> Select 17 <-> 13 19642475Snsouch * nInit <-> nFault 15 <-> 16 19742475Snsouch * 19842475Snsouch */ 19928219Smsmithstatic void 20055939Snsouchppiintr(void *arg) 20128219Smsmith{ 20255939Snsouch device_t ppidev = (device_t)arg; 20355939Snsouch device_t ppbus = device_get_parent(ppidev); 20455939Snsouch struct ppi_data *ppi = DEVTOSOFTC(ppidev); 20542475Snsouch 20655939Snsouch ppi_disable_intr(ppidev); 20742475Snsouch 20855939Snsouch switch (ppb_1284_get_state(ppbus)) { 20942475Snsouch 210108470Sschweikh /* accept IEEE1284 negotiation then wakeup a waiting process to 211108470Sschweikh * continue negotiation at process level */ 21242475Snsouch case PPB_FORWARD_IDLE: 21342475Snsouch /* Event 1 */ 21455939Snsouch if ((ppb_rstr(ppbus) & (SELECT | nBUSY)) == 21542475Snsouch (SELECT | nBUSY)) { 216108470Sschweikh /* IEEE1284 negotiation */ 21742475Snsouch#ifdef DEBUG_1284 21842475Snsouch printf("N"); 21942475Snsouch#endif 22042475Snsouch 22142475Snsouch /* Event 2 - prepare for reading the ext. value */ 22255939Snsouch ppb_wctr(ppbus, (PCD | STROBE | nINIT) & ~SELECTIN); 22342475Snsouch 22455939Snsouch ppb_1284_set_state(ppbus, PPB_NEGOCIATION); 22542475Snsouch 22642475Snsouch } else { 22742475Snsouch#ifdef DEBUG_1284 22855939Snsouch printf("0x%x", ppb_rstr(ppbus)); 22942475Snsouch#endif 23055939Snsouch ppb_peripheral_terminate(ppbus, PPB_DONTWAIT); 23142475Snsouch break; 23242475Snsouch } 23342475Snsouch 234108470Sschweikh /* wake up any process waiting for negotiation from 23542475Snsouch * remote master host */ 23642475Snsouch 23742475Snsouch /* XXX should set a variable to warn the process about 23842475Snsouch * the interrupt */ 23942475Snsouch 24042475Snsouch wakeup(ppi); 24142475Snsouch break; 24242475Snsouch default: 24342475Snsouch#ifdef DEBUG_1284 24455977Speter printf("?%d", ppb_1284_get_state(ppbus)); 24542475Snsouch#endif 24655939Snsouch ppb_1284_set_state(ppbus, PPB_FORWARD_IDLE); 24755939Snsouch ppb_set_mode(ppbus, PPB_COMPATIBLE); 24842475Snsouch break; 24942475Snsouch } 25042475Snsouch 25155939Snsouch ppi_enable_intr(ppidev); 25242475Snsouch 25328219Smsmith return; 25428219Smsmith} 25560194Sn_hibma#endif /* PERIPH_1284 */ 25628219Smsmith 25728219Smsmithstatic int 25883366Sjulianppiopen(dev_t dev, int flags, int fmt, struct thread *td) 25928219Smsmith{ 26028257Smsmith u_int unit = minor(dev); 26155939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 26255939Snsouch device_t ppidev = UNITODEVICE(unit); 26355939Snsouch device_t ppbus = device_get_parent(ppidev); 26432178Smsmith int res; 26528257Smsmith 26655939Snsouch if (!ppi) 26728257Smsmith return (ENXIO); 26828257Smsmith 26942475Snsouch if (!(ppi->ppi_flags & HAVE_PPBUS)) { 27055939Snsouch if ((res = ppb_request_bus(ppbus, ppidev, 27142475Snsouch (flags & O_NONBLOCK) ? PPB_DONTWAIT : 27242475Snsouch (PPB_WAIT | PPB_INTR)))) 27332178Smsmith return (res); 27428257Smsmith 27542475Snsouch ppi->ppi_flags |= HAVE_PPBUS; 27655939Snsouch 27760194Sn_hibma#ifdef PERIPH_1284 27860194Sn_hibma if (ppi->intr_resource) { 27960194Sn_hibma /* register our interrupt handler */ 28060194Sn_hibma BUS_SETUP_INTR(device_get_parent(ppidev), ppidev, ppi->intr_resource, 28160194Sn_hibma INTR_TYPE_TTY, ppiintr, dev, &ppi->intr_cookie); 28260194Sn_hibma } 28360194Sn_hibma#endif /* PERIPH_1284 */ 28442475Snsouch } 28542475Snsouch ppi->ppi_count += 1; 28642475Snsouch 28732178Smsmith return (0); 28828219Smsmith} 28928219Smsmith 29028219Smsmithstatic int 29183366Sjulianppiclose(dev_t dev, int flags, int fmt, struct thread *td) 29228219Smsmith{ 29332178Smsmith u_int unit = minor(dev); 29455939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 29555939Snsouch device_t ppidev = UNITODEVICE(unit); 29655939Snsouch device_t ppbus = device_get_parent(ppidev); 29732178Smsmith 29842475Snsouch ppi->ppi_count --; 29942475Snsouch if (!ppi->ppi_count) { 30042475Snsouch 30142475Snsouch#ifdef PERIPH_1284 30255939Snsouch switch (ppb_1284_get_state(ppbus)) { 30342475Snsouch case PPB_PERIPHERAL_IDLE: 30455939Snsouch ppb_peripheral_terminate(ppbus, 0); 30542475Snsouch break; 30642475Snsouch case PPB_REVERSE_IDLE: 30742475Snsouch case PPB_EPP_IDLE: 30842475Snsouch case PPB_ECP_FORWARD_IDLE: 30942475Snsouch default: 31055939Snsouch ppb_1284_terminate(ppbus); 31142475Snsouch break; 31242475Snsouch } 31342475Snsouch#endif /* PERIPH_1284 */ 31442475Snsouch 31555939Snsouch /* unregistration of interrupt forced by release */ 31655939Snsouch ppb_release_bus(ppbus, ppidev); 31755939Snsouch 31842475Snsouch ppi->ppi_flags &= ~HAVE_PPBUS; 31942475Snsouch } 32042475Snsouch 32132178Smsmith return (0); 32228219Smsmith} 32328219Smsmith 32442475Snsouch/* 32542475Snsouch * ppiread() 32642475Snsouch * 32742475Snsouch * IEEE1284 compliant read. 32842475Snsouch * 329108470Sschweikh * First, try negotiation to BYTE then NIBBLE mode 33042475Snsouch * If no data is available, wait for it otherwise transfer as much as possible 33142475Snsouch */ 33228219Smsmithstatic int 33342475Snsouchppiread(dev_t dev, struct uio *uio, int ioflag) 33442475Snsouch{ 33542475Snsouch#ifdef PERIPH_1284 33642475Snsouch u_int unit = minor(dev); 33755939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 33855939Snsouch device_t ppidev = UNITODEVICE(unit); 33955939Snsouch device_t ppbus = device_get_parent(ppidev); 34042475Snsouch int len, error = 0; 34142475Snsouch 34255939Snsouch switch (ppb_1284_get_state(ppbus)) { 34342475Snsouch case PPB_PERIPHERAL_IDLE: 34455939Snsouch ppb_peripheral_terminate(ppbus, 0); 345102412Scharnier /* FALLTHROUGH */ 34642475Snsouch 34742475Snsouch case PPB_FORWARD_IDLE: 348108470Sschweikh /* if can't negotiate NIBBLE mode then try BYTE mode, 34942475Snsouch * the peripheral may be a computer 35042475Snsouch */ 35155939Snsouch if ((ppb_1284_negociate(ppbus, 35242475Snsouch ppi->ppi_mode = PPB_NIBBLE, 0))) { 35342475Snsouch 35442475Snsouch /* XXX Wait 2 seconds to let the remote host some 35542475Snsouch * time to terminate its interrupt 35642475Snsouch */ 35742475Snsouch tsleep(ppi, PPBPRI, "ppiread", 2*hz); 35842475Snsouch 35955939Snsouch if ((error = ppb_1284_negociate(ppbus, 36042475Snsouch ppi->ppi_mode = PPB_BYTE, 0))) 36142475Snsouch return (error); 36242475Snsouch } 36342475Snsouch break; 36442475Snsouch 36542475Snsouch case PPB_REVERSE_IDLE: 36642475Snsouch case PPB_EPP_IDLE: 36742475Snsouch case PPB_ECP_FORWARD_IDLE: 36842475Snsouch default: 36942475Snsouch break; 37042475Snsouch } 37142475Snsouch 37242475Snsouch#ifdef DEBUG_1284 37342475Snsouch printf("N"); 37442475Snsouch#endif 37542475Snsouch /* read data */ 37642475Snsouch len = 0; 37742475Snsouch while (uio->uio_resid) { 37855939Snsouch if ((error = ppb_1284_read(ppbus, ppi->ppi_mode, 37942475Snsouch ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 38042475Snsouch &len))) { 38142475Snsouch goto error; 38242475Snsouch } 38342475Snsouch 38442475Snsouch if (!len) 38542475Snsouch goto error; /* no more data */ 38642475Snsouch 38742475Snsouch#ifdef DEBUG_1284 38842475Snsouch printf("d"); 38942475Snsouch#endif 39042475Snsouch if ((error = uiomove(ppi->ppi_buffer, len, uio))) 39142475Snsouch goto error; 39242475Snsouch } 39342475Snsouch 39442475Snsoucherror: 39542475Snsouch 39642475Snsouch#else /* PERIPH_1284 */ 39742475Snsouch int error = ENODEV; 39842475Snsouch#endif 39942475Snsouch 40042475Snsouch return (error); 40142475Snsouch} 40242475Snsouch 40342475Snsouch/* 40442475Snsouch * ppiwrite() 40542475Snsouch * 40642475Snsouch * IEEE1284 compliant write 40742475Snsouch * 40842475Snsouch * Actually, this is the peripheral side of a remote IEEE1284 read 40942475Snsouch * 410108470Sschweikh * The first part of the negotiation (IEEE1284 device detection) is 41142475Snsouch * done at interrupt level, then the remaining is done by the writing 41242475Snsouch * process 41342475Snsouch * 414108470Sschweikh * Once negotiation done, transfer data 41542475Snsouch */ 41642475Snsouchstatic int 41742475Snsouchppiwrite(dev_t dev, struct uio *uio, int ioflag) 41842475Snsouch{ 41942475Snsouch#ifdef PERIPH_1284 42042475Snsouch u_int unit = minor(dev); 42155939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 42255939Snsouch device_t ppidev = UNITODEVICE(unit); 42355939Snsouch device_t ppbus = device_get_parent(ppidev); 42442475Snsouch int len, error = 0, sent; 42542475Snsouch 42642475Snsouch#if 0 42742475Snsouch int ret; 42842475Snsouch 42942475Snsouch #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 43042475Snsouch #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 43142475Snsouch 43242475Snsouch struct ppb_microseq msq[] = { 43342475Snsouch { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 43442475Snsouch MS_RET(0) 43542475Snsouch }; 43642475Snsouch 437108470Sschweikh /* negotiate ECP mode */ 43855939Snsouch if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) { 439108470Sschweikh printf("ppiwrite: ECP negotiation failed\n"); 44042475Snsouch } 44142475Snsouch 44242475Snsouch while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 44342475Snsouch uiomove(ppi->ppi_buffer, len, uio); 44442475Snsouch 44542475Snsouch ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 44642475Snsouch 44755939Snsouch error = ppb_MS_microseq(ppbus, msq, &ret); 44842475Snsouch } 44942475Snsouch#endif 45042475Snsouch 45142475Snsouch /* we have to be peripheral to be able to send data, so 45242475Snsouch * wait for the appropriate state 45342475Snsouch */ 45455957Snsouch if (ppb_1284_get_state(ppbus) < PPB_PERIPHERAL_NEGOCIATION) 45555939Snsouch ppb_1284_terminate(ppbus); 45642475Snsouch 45755957Snsouch while (ppb_1284_get_state(ppbus) != PPB_PERIPHERAL_IDLE) { 45842475Snsouch /* XXX should check a variable before sleeping */ 45942475Snsouch#ifdef DEBUG_1284 46042475Snsouch printf("s"); 46142475Snsouch#endif 46242475Snsouch 46355939Snsouch ppi_enable_intr(ppidev); 46442475Snsouch 465108470Sschweikh /* sleep until IEEE1284 negotiation starts */ 46642475Snsouch error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 46742475Snsouch 46842475Snsouch switch (error) { 46942475Snsouch case 0: 470108470Sschweikh /* negotiate peripheral side with BYTE mode */ 47155939Snsouch ppb_peripheral_negociate(ppbus, PPB_BYTE, 0); 47242475Snsouch break; 47342475Snsouch case EWOULDBLOCK: 47442475Snsouch break; 47542475Snsouch default: 47642475Snsouch goto error; 47742475Snsouch } 47842475Snsouch } 47942475Snsouch#ifdef DEBUG_1284 48042475Snsouch printf("N"); 48142475Snsouch#endif 48242475Snsouch 483108470Sschweikh /* negotiation done, write bytes to master host */ 48443301Sdillon while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { 48542475Snsouch uiomove(ppi->ppi_buffer, len, uio); 48655939Snsouch if ((error = byte_peripheral_write(ppbus, 48742475Snsouch ppi->ppi_buffer, len, &sent))) 48842475Snsouch goto error; 48942475Snsouch#ifdef DEBUG_1284 49042475Snsouch printf("d"); 49142475Snsouch#endif 49242475Snsouch } 49342475Snsouch 49442475Snsoucherror: 49542475Snsouch 49642475Snsouch#else /* PERIPH_1284 */ 49742475Snsouch int error = ENODEV; 49842475Snsouch#endif 49942475Snsouch 50042475Snsouch return (error); 50142475Snsouch} 50242475Snsouch 50342475Snsouchstatic int 50483366Sjulianppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 50528219Smsmith{ 50632178Smsmith u_int unit = minor(dev); 50755939Snsouch device_t ppidev = UNITODEVICE(unit); 50855939Snsouch device_t ppbus = device_get_parent(ppidev); 50932178Smsmith int error = 0; 51032178Smsmith u_int8_t *val = (u_int8_t *)data; 51132178Smsmith 51232178Smsmith switch (cmd) { 51332178Smsmith 51432178Smsmith case PPIGDATA: /* get data register */ 51555939Snsouch *val = ppb_rdtr(ppbus); 51632178Smsmith break; 51732178Smsmith case PPIGSTATUS: /* get status bits */ 51855939Snsouch *val = ppb_rstr(ppbus); 51932178Smsmith break; 52032178Smsmith case PPIGCTRL: /* get control bits */ 52155939Snsouch *val = ppb_rctr(ppbus); 52232178Smsmith break; 52343433Snsouch case PPIGEPPD: /* get EPP data bits */ 52455939Snsouch *val = ppb_repp_D(ppbus); 52532178Smsmith break; 52632178Smsmith case PPIGECR: /* get ECP bits */ 52755939Snsouch *val = ppb_recr(ppbus); 52832178Smsmith break; 52932178Smsmith case PPIGFIFO: /* read FIFO */ 53055939Snsouch *val = ppb_rfifo(ppbus); 53132178Smsmith break; 53232178Smsmith case PPISDATA: /* set data register */ 53355939Snsouch ppb_wdtr(ppbus, *val); 53432178Smsmith break; 53532178Smsmith case PPISSTATUS: /* set status bits */ 53655939Snsouch ppb_wstr(ppbus, *val); 53732178Smsmith break; 53832178Smsmith case PPISCTRL: /* set control bits */ 53955939Snsouch ppb_wctr(ppbus, *val); 54032178Smsmith break; 54143433Snsouch case PPISEPPD: /* set EPP data bits */ 54255939Snsouch ppb_wepp_D(ppbus, *val); 54332178Smsmith break; 54432178Smsmith case PPISECR: /* set ECP bits */ 54555939Snsouch ppb_wecr(ppbus, *val); 54632178Smsmith break; 54732178Smsmith case PPISFIFO: /* write FIFO */ 54855939Snsouch ppb_wfifo(ppbus, *val); 54932178Smsmith break; 55043433Snsouch case PPIGEPPA: /* get EPP address bits */ 55155939Snsouch *val = ppb_repp_A(ppbus); 55243433Snsouch break; 55343433Snsouch case PPISEPPA: /* set EPP address bits */ 55455939Snsouch ppb_wepp_A(ppbus, *val); 55543433Snsouch break; 55632178Smsmith default: 55732178Smsmith error = ENOTTY; 55832178Smsmith break; 55932178Smsmith } 56032178Smsmith 56132178Smsmith return (error); 56228219Smsmith} 56328219Smsmith 56456455Speterstatic device_method_t ppi_methods[] = { 56556455Speter /* device interface */ 56656455Speter DEVMETHOD(device_identify, ppi_identify), 56756455Speter DEVMETHOD(device_probe, ppi_probe), 56856455Speter DEVMETHOD(device_attach, ppi_attach), 56956455Speter 57056455Speter { 0, 0 } 57156455Speter}; 57256455Speter 57356455Speterstatic driver_t ppi_driver = { 57456455Speter "ppi", 57556455Speter ppi_methods, 57656455Speter sizeof(struct ppi_data), 57756455Speter}; 57855939SnsouchDRIVER_MODULE(ppi, ppbus, ppi_driver, ppi_devclass, 0, 0); 579