ppi.c revision 56455
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 56455 2000-01-23 14:41:04Z peter $ 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 7155939Snsouch struct resource *intr_resource; /* interrupt resource */ 7255939Snsouch void *intr_cookie; /* interrupt registration cookie */ 7328257Smsmith}; 7428257Smsmith 7555939Snsouch#define DEVTOSOFTC(dev) \ 7655939Snsouch ((struct ppi_data *)device_get_softc(dev)) 7755939Snsouch#define UNITOSOFTC(unit) \ 7855939Snsouch ((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit))) 7955939Snsouch#define UNITODEVICE(unit) \ 8055939Snsouch (devclass_get_device(ppi_devclass, (unit))) 8128219Smsmith 8255939Snsouchstatic devclass_t ppi_devclass; 8328219Smsmith 8428219Smsmithstatic d_open_t ppiopen; 8528219Smsmithstatic d_close_t ppiclose; 8628219Smsmithstatic d_ioctl_t ppiioctl; 8742475Snsouchstatic d_write_t ppiwrite; 8842475Snsouchstatic d_read_t ppiread; 8928219Smsmith 9028261Smsmith#define CDEV_MAJOR 82 9147625Sphkstatic struct cdevsw ppi_cdevsw = { 9247625Sphk /* open */ ppiopen, 9347625Sphk /* close */ ppiclose, 9447625Sphk /* read */ ppiread, 9547625Sphk /* write */ ppiwrite, 9647625Sphk /* ioctl */ ppiioctl, 9747625Sphk /* poll */ nopoll, 9847625Sphk /* mmap */ nommap, 9947625Sphk /* strategy */ nostrategy, 10047625Sphk /* name */ "ppi", 10147625Sphk /* maj */ CDEV_MAJOR, 10247625Sphk /* dump */ nodump, 10347625Sphk /* psize */ nopsize, 10447625Sphk /* flags */ 0, 10547625Sphk /* bmaj */ -1 10647625Sphk}; 10728219Smsmith 10842475Snsouch#ifdef PERIPH_1284 10942475Snsouch 11042475Snsouchstatic void 11155939Snsouchppi_enable_intr(device_t ppidev) 11242475Snsouch{ 11342475Snsouch char r; 11455939Snsouch device_t ppbus = device_get_parent(ppidev); 11542475Snsouch 11655939Snsouch r = ppb_rctr(ppbus); 11755939Snsouch ppb_wctr(ppbus, r | IRQENABLE); 11842475Snsouch 11942475Snsouch return; 12042475Snsouch} 12142475Snsouch 12242475Snsouchstatic void 12355939Snsouchppi_disable_intr(device_t ppidev) 12442475Snsouch{ 12542475Snsouch char r; 12655939Snsouch device_t ppbus = device_get_parent(ppidev); 12742475Snsouch 12855939Snsouch r = ppb_rctr(ppbus); 12955939Snsouch ppb_wctr(ppbus, r & ~IRQENABLE); 13042475Snsouch 13142475Snsouch return; 13242475Snsouch} 13342475Snsouch 13442475Snsouch#endif /* PERIPH_1284 */ 13542475Snsouch 13656455Speterstatic void 13756455Speterppi_identify(driver_t *driver, device_t parent) 13856455Speter{ 13956455Speter 14056455Speter BUS_ADD_CHILD(parent, 0, "ppi", 0); 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{ 16655939Snsouch uintptr_t irq; 16755939Snsouch int zero = 0; 16855939Snsouch struct ppi_data *ppi = DEVTOSOFTC(dev); 16928219Smsmith 17055939Snsouch /* retrive the irq */ 17155939Snsouch BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq); 17228219Smsmith 17355939Snsouch /* declare our interrupt handler */ 17455939Snsouch ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, 17555939Snsouch &zero, irq, irq, 1, RF_ACTIVE); 17628219Smsmith 17755939Snsouch make_dev(&ppi_cdevsw, device_get_unit(dev), /* XXX cleanup */ 17855939Snsouch UID_ROOT, GID_WHEEL, 17955939Snsouch 0600, "ppi%d", device_get_unit(dev)); 18028219Smsmith 18155939Snsouch return (0); 18228219Smsmith} 18328219Smsmith 18442475Snsouch/* 18542475Snsouch * Cable 18642475Snsouch * ----- 18742475Snsouch * 18842475Snsouch * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 18942475Snsouch * 19042475Snsouch * nStrobe <-> nAck 1 <-> 10 19142475Snsouch * nAutofd <-> Busy 11 <-> 14 19242475Snsouch * nSelectin <-> Select 17 <-> 13 19342475Snsouch * nInit <-> nFault 15 <-> 16 19442475Snsouch * 19542475Snsouch */ 19628219Smsmithstatic void 19755939Snsouchppiintr(void *arg) 19828219Smsmith{ 19942475Snsouch#ifdef PERIPH_1284 20055939Snsouch device_t ppidev = (device_t)arg; 20155939Snsouch device_t ppbus = device_get_parent(ppidev); 20255939Snsouch struct ppi_data *ppi = DEVTOSOFTC(ppidev); 20342475Snsouch 20455939Snsouch ppi_disable_intr(ppidev); 20542475Snsouch 20655939Snsouch switch (ppb_1284_get_state(ppbus)) { 20742475Snsouch 20842475Snsouch /* accept IEEE1284 negociation then wakeup an waiting process to 20942475Snsouch * continue negociation at process level */ 21042475Snsouch case PPB_FORWARD_IDLE: 21142475Snsouch /* Event 1 */ 21255939Snsouch if ((ppb_rstr(ppbus) & (SELECT | nBUSY)) == 21342475Snsouch (SELECT | nBUSY)) { 21442475Snsouch /* IEEE1284 negociation */ 21542475Snsouch#ifdef DEBUG_1284 21642475Snsouch printf("N"); 21742475Snsouch#endif 21842475Snsouch 21942475Snsouch /* Event 2 - prepare for reading the ext. value */ 22055939Snsouch ppb_wctr(ppbus, (PCD | STROBE | nINIT) & ~SELECTIN); 22142475Snsouch 22255939Snsouch ppb_1284_set_state(ppbus, PPB_NEGOCIATION); 22342475Snsouch 22442475Snsouch } else { 22542475Snsouch#ifdef DEBUG_1284 22655939Snsouch printf("0x%x", ppb_rstr(ppbus)); 22742475Snsouch#endif 22855939Snsouch ppb_peripheral_terminate(ppbus, PPB_DONTWAIT); 22942475Snsouch break; 23042475Snsouch } 23142475Snsouch 23242475Snsouch /* wake up any process waiting for negociation from 23342475Snsouch * remote master host */ 23442475Snsouch 23542475Snsouch /* XXX should set a variable to warn the process about 23642475Snsouch * the interrupt */ 23742475Snsouch 23842475Snsouch wakeup(ppi); 23942475Snsouch break; 24042475Snsouch default: 24142475Snsouch#ifdef DEBUG_1284 24255977Speter printf("?%d", ppb_1284_get_state(ppbus)); 24342475Snsouch#endif 24455939Snsouch ppb_1284_set_state(ppbus, PPB_FORWARD_IDLE); 24555939Snsouch ppb_set_mode(ppbus, PPB_COMPATIBLE); 24642475Snsouch break; 24742475Snsouch } 24842475Snsouch 24955939Snsouch ppi_enable_intr(ppidev); 25042475Snsouch#endif /* PERIPH_1284 */ 25142475Snsouch 25228219Smsmith return; 25328219Smsmith} 25428219Smsmith 25528219Smsmithstatic int 25628219Smsmithppiopen(dev_t dev, int flags, int fmt, struct proc *p) 25728219Smsmith{ 25828257Smsmith u_int unit = minor(dev); 25955939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 26055939Snsouch device_t ppidev = UNITODEVICE(unit); 26155939Snsouch device_t ppbus = device_get_parent(ppidev); 26232178Smsmith int res; 26328257Smsmith 26455939Snsouch if (!ppi) 26528257Smsmith return (ENXIO); 26628257Smsmith 26742475Snsouch if (!(ppi->ppi_flags & HAVE_PPBUS)) { 26855939Snsouch if ((res = ppb_request_bus(ppbus, ppidev, 26942475Snsouch (flags & O_NONBLOCK) ? PPB_DONTWAIT : 27042475Snsouch (PPB_WAIT | PPB_INTR)))) 27132178Smsmith return (res); 27228257Smsmith 27342475Snsouch ppi->ppi_flags |= HAVE_PPBUS; 27455939Snsouch 27555939Snsouch /* register our interrupt handler */ 27655939Snsouch BUS_SETUP_INTR(device_get_parent(ppidev), ppidev, ppi->intr_resource, 27755939Snsouch INTR_TYPE_TTY, ppiintr, dev, &ppi->intr_cookie); 27842475Snsouch } 27942475Snsouch ppi->ppi_count += 1; 28042475Snsouch 28132178Smsmith return (0); 28228219Smsmith} 28328219Smsmith 28428219Smsmithstatic int 28528219Smsmithppiclose(dev_t dev, int flags, int fmt, struct proc *p) 28628219Smsmith{ 28732178Smsmith u_int unit = minor(dev); 28855939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 28955939Snsouch device_t ppidev = UNITODEVICE(unit); 29055939Snsouch device_t ppbus = device_get_parent(ppidev); 29132178Smsmith 29242475Snsouch ppi->ppi_count --; 29342475Snsouch if (!ppi->ppi_count) { 29442475Snsouch 29542475Snsouch#ifdef PERIPH_1284 29655939Snsouch switch (ppb_1284_get_state(ppbus)) { 29742475Snsouch case PPB_PERIPHERAL_IDLE: 29855939Snsouch ppb_peripheral_terminate(ppbus, 0); 29942475Snsouch break; 30042475Snsouch case PPB_REVERSE_IDLE: 30142475Snsouch case PPB_EPP_IDLE: 30242475Snsouch case PPB_ECP_FORWARD_IDLE: 30342475Snsouch default: 30455939Snsouch ppb_1284_terminate(ppbus); 30542475Snsouch break; 30642475Snsouch } 30742475Snsouch#endif /* PERIPH_1284 */ 30842475Snsouch 30955939Snsouch /* unregistration of interrupt forced by release */ 31055939Snsouch ppb_release_bus(ppbus, ppidev); 31155939Snsouch 31242475Snsouch ppi->ppi_flags &= ~HAVE_PPBUS; 31342475Snsouch } 31442475Snsouch 31532178Smsmith return (0); 31628219Smsmith} 31728219Smsmith 31842475Snsouch/* 31942475Snsouch * ppiread() 32042475Snsouch * 32142475Snsouch * IEEE1284 compliant read. 32242475Snsouch * 32342475Snsouch * First, try negociation to BYTE then NIBBLE mode 32442475Snsouch * If no data is available, wait for it otherwise transfer as much as possible 32542475Snsouch */ 32628219Smsmithstatic int 32742475Snsouchppiread(dev_t dev, struct uio *uio, int ioflag) 32842475Snsouch{ 32942475Snsouch#ifdef PERIPH_1284 33042475Snsouch u_int unit = minor(dev); 33155939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 33255939Snsouch device_t ppidev = UNITODEVICE(unit); 33355939Snsouch device_t ppbus = device_get_parent(ppidev); 33442475Snsouch int len, error = 0; 33542475Snsouch 33655939Snsouch switch (ppb_1284_get_state(ppbus)) { 33742475Snsouch case PPB_PERIPHERAL_IDLE: 33855939Snsouch ppb_peripheral_terminate(ppbus, 0); 33942475Snsouch /* fall throught */ 34042475Snsouch 34142475Snsouch case PPB_FORWARD_IDLE: 34242475Snsouch /* if can't negociate NIBBLE mode then try BYTE mode, 34342475Snsouch * the peripheral may be a computer 34442475Snsouch */ 34555939Snsouch if ((ppb_1284_negociate(ppbus, 34642475Snsouch ppi->ppi_mode = PPB_NIBBLE, 0))) { 34742475Snsouch 34842475Snsouch /* XXX Wait 2 seconds to let the remote host some 34942475Snsouch * time to terminate its interrupt 35042475Snsouch */ 35142475Snsouch tsleep(ppi, PPBPRI, "ppiread", 2*hz); 35242475Snsouch 35355939Snsouch if ((error = ppb_1284_negociate(ppbus, 35442475Snsouch ppi->ppi_mode = PPB_BYTE, 0))) 35542475Snsouch return (error); 35642475Snsouch } 35742475Snsouch break; 35842475Snsouch 35942475Snsouch case PPB_REVERSE_IDLE: 36042475Snsouch case PPB_EPP_IDLE: 36142475Snsouch case PPB_ECP_FORWARD_IDLE: 36242475Snsouch default: 36342475Snsouch break; 36442475Snsouch } 36542475Snsouch 36642475Snsouch#ifdef DEBUG_1284 36742475Snsouch printf("N"); 36842475Snsouch#endif 36942475Snsouch /* read data */ 37042475Snsouch len = 0; 37142475Snsouch while (uio->uio_resid) { 37255939Snsouch if ((error = ppb_1284_read(ppbus, ppi->ppi_mode, 37342475Snsouch ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 37442475Snsouch &len))) { 37542475Snsouch goto error; 37642475Snsouch } 37742475Snsouch 37842475Snsouch if (!len) 37942475Snsouch goto error; /* no more data */ 38042475Snsouch 38142475Snsouch#ifdef DEBUG_1284 38242475Snsouch printf("d"); 38342475Snsouch#endif 38442475Snsouch if ((error = uiomove(ppi->ppi_buffer, len, uio))) 38542475Snsouch goto error; 38642475Snsouch } 38742475Snsouch 38842475Snsoucherror: 38942475Snsouch 39042475Snsouch#else /* PERIPH_1284 */ 39142475Snsouch int error = ENODEV; 39242475Snsouch#endif 39342475Snsouch 39442475Snsouch return (error); 39542475Snsouch} 39642475Snsouch 39742475Snsouch/* 39842475Snsouch * ppiwrite() 39942475Snsouch * 40042475Snsouch * IEEE1284 compliant write 40142475Snsouch * 40242475Snsouch * Actually, this is the peripheral side of a remote IEEE1284 read 40342475Snsouch * 40442475Snsouch * The first part of the negociation (IEEE1284 device detection) is 40542475Snsouch * done at interrupt level, then the remaining is done by the writing 40642475Snsouch * process 40742475Snsouch * 40842475Snsouch * Once negociation done, transfer data 40942475Snsouch */ 41042475Snsouchstatic int 41142475Snsouchppiwrite(dev_t dev, struct uio *uio, int ioflag) 41242475Snsouch{ 41342475Snsouch#ifdef PERIPH_1284 41442475Snsouch u_int unit = minor(dev); 41555939Snsouch struct ppi_data *ppi = UNITOSOFTC(unit); 41655939Snsouch device_t ppidev = UNITODEVICE(unit); 41755939Snsouch device_t ppbus = device_get_parent(ppidev); 41842475Snsouch int len, error = 0, sent; 41942475Snsouch 42042475Snsouch#if 0 42142475Snsouch int ret; 42242475Snsouch 42342475Snsouch #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 42442475Snsouch #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 42542475Snsouch 42642475Snsouch struct ppb_microseq msq[] = { 42742475Snsouch { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 42842475Snsouch MS_RET(0) 42942475Snsouch }; 43042475Snsouch 43142475Snsouch /* negociate ECP mode */ 43255939Snsouch if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) { 43342475Snsouch printf("ppiwrite: ECP negociation failed\n"); 43442475Snsouch } 43542475Snsouch 43642475Snsouch while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 43742475Snsouch uiomove(ppi->ppi_buffer, len, uio); 43842475Snsouch 43942475Snsouch ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 44042475Snsouch 44155939Snsouch error = ppb_MS_microseq(ppbus, msq, &ret); 44242475Snsouch } 44342475Snsouch#endif 44442475Snsouch 44542475Snsouch /* we have to be peripheral to be able to send data, so 44642475Snsouch * wait for the appropriate state 44742475Snsouch */ 44855957Snsouch if (ppb_1284_get_state(ppbus) < PPB_PERIPHERAL_NEGOCIATION) 44955939Snsouch ppb_1284_terminate(ppbus); 45042475Snsouch 45155957Snsouch while (ppb_1284_get_state(ppbus) != PPB_PERIPHERAL_IDLE) { 45242475Snsouch /* XXX should check a variable before sleeping */ 45342475Snsouch#ifdef DEBUG_1284 45442475Snsouch printf("s"); 45542475Snsouch#endif 45642475Snsouch 45755939Snsouch ppi_enable_intr(ppidev); 45842475Snsouch 45942475Snsouch /* sleep until IEEE1284 negociation starts */ 46042475Snsouch error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 46142475Snsouch 46242475Snsouch switch (error) { 46342475Snsouch case 0: 46442475Snsouch /* negociate peripheral side with BYTE mode */ 46555939Snsouch ppb_peripheral_negociate(ppbus, PPB_BYTE, 0); 46642475Snsouch break; 46742475Snsouch case EWOULDBLOCK: 46842475Snsouch break; 46942475Snsouch default: 47042475Snsouch goto error; 47142475Snsouch } 47242475Snsouch } 47342475Snsouch#ifdef DEBUG_1284 47442475Snsouch printf("N"); 47542475Snsouch#endif 47642475Snsouch 47742475Snsouch /* negociation done, write bytes to master host */ 47843301Sdillon while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { 47942475Snsouch uiomove(ppi->ppi_buffer, len, uio); 48055939Snsouch if ((error = byte_peripheral_write(ppbus, 48142475Snsouch ppi->ppi_buffer, len, &sent))) 48242475Snsouch goto error; 48342475Snsouch#ifdef DEBUG_1284 48442475Snsouch printf("d"); 48542475Snsouch#endif 48642475Snsouch } 48742475Snsouch 48842475Snsoucherror: 48942475Snsouch 49042475Snsouch#else /* PERIPH_1284 */ 49142475Snsouch int error = ENODEV; 49242475Snsouch#endif 49342475Snsouch 49442475Snsouch return (error); 49542475Snsouch} 49642475Snsouch 49742475Snsouchstatic int 49836735Sdfrppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 49928219Smsmith{ 50032178Smsmith u_int unit = minor(dev); 50155939Snsouch device_t ppidev = UNITODEVICE(unit); 50255939Snsouch device_t ppbus = device_get_parent(ppidev); 50332178Smsmith int error = 0; 50432178Smsmith u_int8_t *val = (u_int8_t *)data; 50532178Smsmith 50632178Smsmith switch (cmd) { 50732178Smsmith 50832178Smsmith case PPIGDATA: /* get data register */ 50955939Snsouch *val = ppb_rdtr(ppbus); 51032178Smsmith break; 51132178Smsmith case PPIGSTATUS: /* get status bits */ 51255939Snsouch *val = ppb_rstr(ppbus); 51332178Smsmith break; 51432178Smsmith case PPIGCTRL: /* get control bits */ 51555939Snsouch *val = ppb_rctr(ppbus); 51632178Smsmith break; 51743433Snsouch case PPIGEPPD: /* get EPP data bits */ 51855939Snsouch *val = ppb_repp_D(ppbus); 51932178Smsmith break; 52032178Smsmith case PPIGECR: /* get ECP bits */ 52155939Snsouch *val = ppb_recr(ppbus); 52232178Smsmith break; 52332178Smsmith case PPIGFIFO: /* read FIFO */ 52455939Snsouch *val = ppb_rfifo(ppbus); 52532178Smsmith break; 52632178Smsmith case PPISDATA: /* set data register */ 52755939Snsouch ppb_wdtr(ppbus, *val); 52832178Smsmith break; 52932178Smsmith case PPISSTATUS: /* set status bits */ 53055939Snsouch ppb_wstr(ppbus, *val); 53132178Smsmith break; 53232178Smsmith case PPISCTRL: /* set control bits */ 53355939Snsouch ppb_wctr(ppbus, *val); 53432178Smsmith break; 53543433Snsouch case PPISEPPD: /* set EPP data bits */ 53655939Snsouch ppb_wepp_D(ppbus, *val); 53732178Smsmith break; 53832178Smsmith case PPISECR: /* set ECP bits */ 53955939Snsouch ppb_wecr(ppbus, *val); 54032178Smsmith break; 54132178Smsmith case PPISFIFO: /* write FIFO */ 54255939Snsouch ppb_wfifo(ppbus, *val); 54332178Smsmith break; 54443433Snsouch case PPIGEPPA: /* get EPP address bits */ 54555939Snsouch *val = ppb_repp_A(ppbus); 54643433Snsouch break; 54743433Snsouch case PPISEPPA: /* set EPP address bits */ 54855939Snsouch ppb_wepp_A(ppbus, *val); 54943433Snsouch break; 55032178Smsmith default: 55132178Smsmith error = ENOTTY; 55232178Smsmith break; 55332178Smsmith } 55432178Smsmith 55532178Smsmith return (error); 55628219Smsmith} 55728219Smsmith 55856455Speterstatic device_method_t ppi_methods[] = { 55956455Speter /* device interface */ 56056455Speter DEVMETHOD(device_identify, ppi_identify), 56156455Speter DEVMETHOD(device_probe, ppi_probe), 56256455Speter DEVMETHOD(device_attach, ppi_attach), 56356455Speter 56456455Speter { 0, 0 } 56556455Speter}; 56656455Speter 56756455Speterstatic driver_t ppi_driver = { 56856455Speter "ppi", 56956455Speter ppi_methods, 57056455Speter sizeof(struct ppi_data), 57156455Speter}; 57255939SnsouchDRIVER_MODULE(ppi, ppbus, ppi_driver, ppi_devclass, 0, 0); 573