ppi.c revision 43433
128219Smsmith/*- 232178Smsmith * Copyright (c) 1997, 1998 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 * 2643433Snsouch * $Id: ppi.c,v 1.10 1999/01/27 21:49:53 dillon Exp $ 2728219Smsmith * 2828219Smsmith */ 2928257Smsmith#include "ppi.h" 3028257Smsmith 3128257Smsmith#if NPPI > 0 3228257Smsmith 3328219Smsmith#include <sys/param.h> 3428219Smsmith#include <sys/systm.h> 3528219Smsmith#include <sys/conf.h> 3628219Smsmith#include <sys/kernel.h> 3742475Snsouch#include <sys/uio.h> 3828219Smsmith#include <sys/malloc.h> 3932178Smsmith#include <sys/fcntl.h> 4028219Smsmith 4142475Snsouch#include <machine/clock.h> 4242475Snsouch 4328219Smsmith#include <dev/ppbus/ppbconf.h> 4442475Snsouch#include <dev/ppbus/ppb_msq.h> 4542475Snsouch 4642475Snsouch#include "opt_ppb_1284.h" 4742475Snsouch 4842475Snsouch#ifdef PERIPH_1284 4942475Snsouch#include <dev/ppbus/ppb_1284.h> 5042475Snsouch#endif 5142475Snsouch 5232178Smsmith#include <dev/ppbus/ppi.h> 5328219Smsmith 5442475Snsouch#define BUFSIZE 512 5532178Smsmith 5628257Smsmithstruct ppi_data { 5728257Smsmith 5832178Smsmith int ppi_unit; 5932178Smsmith int ppi_flags; 6032178Smsmith#define HAVE_PPBUS (1<<0) 6142475Snsouch#define HAD_PPBUS (1<<1) 6228257Smsmith 6342475Snsouch int ppi_count; 6442475Snsouch int ppi_mode; /* IEEE1284 mode */ 6542475Snsouch char ppi_buffer[BUFSIZE]; 6642475Snsouch 6732178Smsmith struct ppb_device ppi_dev; 6828257Smsmith}; 6928257Smsmith 7032178Smsmith#define MAXPPI 8 /* XXX not much better! */ 7132178Smsmithstatic int nppi = 0; 7232178Smsmithstatic struct ppi_data *ppidata[MAXPPI]; 7328219Smsmith 7428219Smsmith/* 7528219Smsmith * Make ourselves visible as a ppbus driver 7628219Smsmith */ 7728219Smsmith 7828219Smsmithstatic struct ppb_device *ppiprobe(struct ppb_data *ppb); 7928219Smsmithstatic int ppiattach(struct ppb_device *dev); 8028219Smsmithstatic void ppiintr(int unit); 8128219Smsmith 8228219Smsmithstatic struct ppb_driver ppidriver = { 8328219Smsmith ppiprobe, ppiattach, "ppi" 8428219Smsmith}; 8528219SmsmithDATA_SET(ppbdriver_set, ppidriver); 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 9328261Smsmith#define CDEV_MAJOR 82 9428219Smsmithstatic struct cdevsw ppi_cdevsw = 9542475Snsouch { ppiopen, ppiclose, ppiread, ppiwrite, /* 82 */ 9628219Smsmith ppiioctl, nullstop, nullreset, nodevtotty, 9728219Smsmith seltrue, nommap, nostrat, "ppi", NULL, -1 }; 9828219Smsmith 9942475Snsouch#ifdef PERIPH_1284 10042475Snsouch 10142475Snsouchstatic void 10242475Snsouchppi_enable_intr(struct ppi_data *ppi) 10342475Snsouch{ 10442475Snsouch char r; 10542475Snsouch 10642475Snsouch r = ppb_rctr(&ppi->ppi_dev); 10742475Snsouch ppb_wctr(&ppi->ppi_dev, r | IRQENABLE); 10842475Snsouch 10942475Snsouch return; 11042475Snsouch} 11142475Snsouch 11242475Snsouchstatic void 11342475Snsouchppi_disable_intr(struct ppi_data *ppi) 11442475Snsouch{ 11542475Snsouch char r; 11642475Snsouch 11742475Snsouch r = ppb_rctr(&ppi->ppi_dev); 11842475Snsouch ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE); 11942475Snsouch 12042475Snsouch return; 12142475Snsouch} 12242475Snsouch 12342475Snsouch#endif /* PERIPH_1284 */ 12442475Snsouch 12528219Smsmith/* 12628219Smsmith * ppiprobe() 12728219Smsmith */ 12828219Smsmithstatic struct ppb_device * 12928219Smsmithppiprobe(struct ppb_data *ppb) 13028219Smsmith{ 13128219Smsmith struct ppi_data *ppi; 13228219Smsmith 13328219Smsmith ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data), 13428219Smsmith M_TEMP, M_NOWAIT); 13528219Smsmith if (!ppi) { 13628219Smsmith printf("ppi: cannot malloc!\n"); 13728219Smsmith return 0; 13828219Smsmith } 13928219Smsmith bzero(ppi, sizeof(struct ppi_data)); 14028219Smsmith 14128219Smsmith ppidata[nppi] = ppi; 14228219Smsmith 14328219Smsmith /* 14428219Smsmith * ppi dependent initialisation. 14528219Smsmith */ 14628219Smsmith ppi->ppi_unit = nppi; 14728219Smsmith 14828219Smsmith /* 14928219Smsmith * ppbus dependent initialisation. 15028219Smsmith */ 15128219Smsmith ppi->ppi_dev.id_unit = ppi->ppi_unit; 15228219Smsmith ppi->ppi_dev.ppb = ppb; 15328219Smsmith ppi->ppi_dev.intr = ppiintr; 15428219Smsmith 15528219Smsmith /* Ok, go to next device on next probe */ 15628219Smsmith nppi ++; 15728219Smsmith 15828219Smsmith return &ppi->ppi_dev; 15928219Smsmith} 16028219Smsmith 16128219Smsmithstatic int 16228219Smsmithppiattach(struct ppb_device *dev) 16328219Smsmith{ 16428219Smsmith /* 16528219Smsmith * Report ourselves 16628219Smsmith */ 16728219Smsmith printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 16828219Smsmith dev->id_unit, dev->ppb->ppb_link->adapter_unit); 16928219Smsmith 17028219Smsmith return (1); 17128219Smsmith} 17228219Smsmith 17342475Snsouch/* 17442475Snsouch * Cable 17542475Snsouch * ----- 17642475Snsouch * 17742475Snsouch * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 17842475Snsouch * 17942475Snsouch * nStrobe <-> nAck 1 <-> 10 18042475Snsouch * nAutofd <-> Busy 11 <-> 14 18142475Snsouch * nSelectin <-> Select 17 <-> 13 18242475Snsouch * nInit <-> nFault 15 <-> 16 18342475Snsouch * 18442475Snsouch */ 18528219Smsmithstatic void 18628219Smsmithppiintr(int unit) 18728219Smsmith{ 18842475Snsouch#ifdef PERIPH_1284 18942475Snsouch struct ppi_data *ppi = ppidata[unit]; 19042475Snsouch 19142475Snsouch ppi_disable_intr(ppi); 19242475Snsouch 19342475Snsouch switch (ppi->ppi_dev.ppb->state) { 19442475Snsouch 19542475Snsouch /* accept IEEE1284 negociation then wakeup an waiting process to 19642475Snsouch * continue negociation at process level */ 19742475Snsouch case PPB_FORWARD_IDLE: 19842475Snsouch /* Event 1 */ 19942475Snsouch if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) == 20042475Snsouch (SELECT | nBUSY)) { 20142475Snsouch /* IEEE1284 negociation */ 20242475Snsouch#ifdef DEBUG_1284 20342475Snsouch printf("N"); 20442475Snsouch#endif 20542475Snsouch 20642475Snsouch /* Event 2 - prepare for reading the ext. value */ 20742475Snsouch ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN); 20842475Snsouch 20942475Snsouch ppi->ppi_dev.ppb->state = PPB_NEGOCIATION; 21042475Snsouch 21142475Snsouch } else { 21242475Snsouch#ifdef DEBUG_1284 21342475Snsouch printf("0x%x", ppb_rstr(&ppi->ppi_dev)); 21442475Snsouch#endif 21542475Snsouch ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT); 21642475Snsouch break; 21742475Snsouch } 21842475Snsouch 21942475Snsouch /* wake up any process waiting for negociation from 22042475Snsouch * remote master host */ 22142475Snsouch 22242475Snsouch /* XXX should set a variable to warn the process about 22342475Snsouch * the interrupt */ 22442475Snsouch 22542475Snsouch wakeup(ppi); 22642475Snsouch break; 22742475Snsouch default: 22842475Snsouch#ifdef DEBUG_1284 22942475Snsouch printf("?%d", ppi->ppi_dev.ppb->state); 23042475Snsouch#endif 23142475Snsouch ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE; 23242475Snsouch ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE); 23342475Snsouch break; 23442475Snsouch } 23542475Snsouch 23642475Snsouch ppi_enable_intr(ppi); 23742475Snsouch#endif /* PERIPH_1284 */ 23842475Snsouch 23928219Smsmith return; 24028219Smsmith} 24128219Smsmith 24228219Smsmithstatic int 24328219Smsmithppiopen(dev_t dev, int flags, int fmt, struct proc *p) 24428219Smsmith{ 24528257Smsmith u_int unit = minor(dev); 24632178Smsmith struct ppi_data *ppi = ppidata[unit]; 24732178Smsmith int res; 24828257Smsmith 24928257Smsmith if (unit >= nppi) 25028257Smsmith return (ENXIO); 25128257Smsmith 25242475Snsouch if (!(ppi->ppi_flags & HAVE_PPBUS)) { 25342475Snsouch if ((res = ppb_request_bus(&ppi->ppi_dev, 25442475Snsouch (flags & O_NONBLOCK) ? PPB_DONTWAIT : 25542475Snsouch (PPB_WAIT | PPB_INTR)))) 25632178Smsmith return (res); 25728257Smsmith 25842475Snsouch ppi->ppi_flags |= HAVE_PPBUS; 25942475Snsouch } 26042475Snsouch ppi->ppi_count += 1; 26142475Snsouch 26232178Smsmith return (0); 26328219Smsmith} 26428219Smsmith 26528219Smsmithstatic int 26628219Smsmithppiclose(dev_t dev, int flags, int fmt, struct proc *p) 26728219Smsmith{ 26832178Smsmith u_int unit = minor(dev); 26932178Smsmith struct ppi_data *ppi = ppidata[unit]; 27032178Smsmith 27142475Snsouch ppi->ppi_count --; 27242475Snsouch if (!ppi->ppi_count) { 27342475Snsouch 27442475Snsouch#ifdef PERIPH_1284 27542475Snsouch switch (ppi->ppi_dev.ppb->state) { 27642475Snsouch case PPB_PERIPHERAL_IDLE: 27742475Snsouch ppb_peripheral_terminate(&ppi->ppi_dev, 0); 27842475Snsouch break; 27942475Snsouch case PPB_REVERSE_IDLE: 28042475Snsouch case PPB_EPP_IDLE: 28142475Snsouch case PPB_ECP_FORWARD_IDLE: 28242475Snsouch default: 28342475Snsouch ppb_1284_terminate(&ppi->ppi_dev); 28442475Snsouch break; 28542475Snsouch } 28642475Snsouch#endif /* PERIPH_1284 */ 28742475Snsouch 28832178Smsmith ppb_release_bus(&ppi->ppi_dev); 28942475Snsouch ppi->ppi_flags &= ~HAVE_PPBUS; 29042475Snsouch } 29142475Snsouch 29232178Smsmith return (0); 29328219Smsmith} 29428219Smsmith 29542475Snsouch/* 29642475Snsouch * ppiread() 29742475Snsouch * 29842475Snsouch * IEEE1284 compliant read. 29942475Snsouch * 30042475Snsouch * First, try negociation to BYTE then NIBBLE mode 30142475Snsouch * If no data is available, wait for it otherwise transfer as much as possible 30242475Snsouch */ 30328219Smsmithstatic int 30442475Snsouchppiread(dev_t dev, struct uio *uio, int ioflag) 30542475Snsouch{ 30642475Snsouch#ifdef PERIPH_1284 30742475Snsouch u_int unit = minor(dev); 30842475Snsouch struct ppi_data *ppi = ppidata[unit]; 30942475Snsouch int len, error = 0; 31042475Snsouch 31142475Snsouch switch (ppi->ppi_dev.ppb->state) { 31242475Snsouch case PPB_PERIPHERAL_IDLE: 31342475Snsouch ppb_peripheral_terminate(&ppi->ppi_dev, 0); 31442475Snsouch /* fall throught */ 31542475Snsouch 31642475Snsouch case PPB_FORWARD_IDLE: 31742475Snsouch /* if can't negociate NIBBLE mode then try BYTE mode, 31842475Snsouch * the peripheral may be a computer 31942475Snsouch */ 32042475Snsouch if ((ppb_1284_negociate(&ppi->ppi_dev, 32142475Snsouch ppi->ppi_mode = PPB_NIBBLE, 0))) { 32242475Snsouch 32342475Snsouch /* XXX Wait 2 seconds to let the remote host some 32442475Snsouch * time to terminate its interrupt 32542475Snsouch */ 32642475Snsouch tsleep(ppi, PPBPRI, "ppiread", 2*hz); 32742475Snsouch 32842475Snsouch if ((error = ppb_1284_negociate(&ppi->ppi_dev, 32942475Snsouch ppi->ppi_mode = PPB_BYTE, 0))) 33042475Snsouch return (error); 33142475Snsouch } 33242475Snsouch break; 33342475Snsouch 33442475Snsouch case PPB_REVERSE_IDLE: 33542475Snsouch case PPB_EPP_IDLE: 33642475Snsouch case PPB_ECP_FORWARD_IDLE: 33742475Snsouch default: 33842475Snsouch break; 33942475Snsouch } 34042475Snsouch 34142475Snsouch#ifdef DEBUG_1284 34242475Snsouch printf("N"); 34342475Snsouch#endif 34442475Snsouch /* read data */ 34542475Snsouch len = 0; 34642475Snsouch while (uio->uio_resid) { 34742475Snsouch if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode, 34842475Snsouch ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 34942475Snsouch &len))) { 35042475Snsouch goto error; 35142475Snsouch } 35242475Snsouch 35342475Snsouch if (!len) 35442475Snsouch goto error; /* no more data */ 35542475Snsouch 35642475Snsouch#ifdef DEBUG_1284 35742475Snsouch printf("d"); 35842475Snsouch#endif 35942475Snsouch if ((error = uiomove(ppi->ppi_buffer, len, uio))) 36042475Snsouch goto error; 36142475Snsouch } 36242475Snsouch 36342475Snsoucherror: 36442475Snsouch 36542475Snsouch#else /* PERIPH_1284 */ 36642475Snsouch int error = ENODEV; 36742475Snsouch#endif 36842475Snsouch 36942475Snsouch return (error); 37042475Snsouch} 37142475Snsouch 37242475Snsouch/* 37342475Snsouch * ppiwrite() 37442475Snsouch * 37542475Snsouch * IEEE1284 compliant write 37642475Snsouch * 37742475Snsouch * Actually, this is the peripheral side of a remote IEEE1284 read 37842475Snsouch * 37942475Snsouch * The first part of the negociation (IEEE1284 device detection) is 38042475Snsouch * done at interrupt level, then the remaining is done by the writing 38142475Snsouch * process 38242475Snsouch * 38342475Snsouch * Once negociation done, transfer data 38442475Snsouch */ 38542475Snsouchstatic int 38642475Snsouchppiwrite(dev_t dev, struct uio *uio, int ioflag) 38742475Snsouch{ 38842475Snsouch#ifdef PERIPH_1284 38942475Snsouch u_int unit = minor(dev); 39042475Snsouch struct ppi_data *ppi = ppidata[unit]; 39142475Snsouch struct ppb_data *ppb = ppi->ppi_dev.ppb; 39242475Snsouch int len, error = 0, sent; 39342475Snsouch 39442475Snsouch#if 0 39542475Snsouch int ret; 39642475Snsouch 39742475Snsouch #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 39842475Snsouch #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 39942475Snsouch 40042475Snsouch struct ppb_microseq msq[] = { 40142475Snsouch { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 40242475Snsouch MS_RET(0) 40342475Snsouch }; 40442475Snsouch 40542475Snsouch /* negociate ECP mode */ 40642475Snsouch if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) { 40742475Snsouch printf("ppiwrite: ECP negociation failed\n"); 40842475Snsouch } 40942475Snsouch 41042475Snsouch while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 41142475Snsouch uiomove(ppi->ppi_buffer, len, uio); 41242475Snsouch 41342475Snsouch ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 41442475Snsouch 41542475Snsouch error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret); 41642475Snsouch } 41742475Snsouch#endif 41842475Snsouch 41942475Snsouch /* we have to be peripheral to be able to send data, so 42042475Snsouch * wait for the appropriate state 42142475Snsouch */ 42242475Snsouch if (ppb->state < PPB_PERIPHERAL_NEGOCIATION) 42342475Snsouch ppb_1284_terminate(&ppi->ppi_dev); 42442475Snsouch 42542475Snsouch while (ppb->state != PPB_PERIPHERAL_IDLE) { 42642475Snsouch /* XXX should check a variable before sleeping */ 42742475Snsouch#ifdef DEBUG_1284 42842475Snsouch printf("s"); 42942475Snsouch#endif 43042475Snsouch 43142475Snsouch ppi_enable_intr(ppi); 43242475Snsouch 43342475Snsouch /* sleep until IEEE1284 negociation starts */ 43442475Snsouch error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 43542475Snsouch 43642475Snsouch switch (error) { 43742475Snsouch case 0: 43842475Snsouch /* negociate peripheral side with BYTE mode */ 43942475Snsouch ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0); 44042475Snsouch break; 44142475Snsouch case EWOULDBLOCK: 44242475Snsouch break; 44342475Snsouch default: 44442475Snsouch goto error; 44542475Snsouch } 44642475Snsouch } 44742475Snsouch#ifdef DEBUG_1284 44842475Snsouch printf("N"); 44942475Snsouch#endif 45042475Snsouch 45142475Snsouch /* negociation done, write bytes to master host */ 45243301Sdillon while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { 45342475Snsouch uiomove(ppi->ppi_buffer, len, uio); 45442475Snsouch if ((error = byte_peripheral_write(&ppi->ppi_dev, 45542475Snsouch ppi->ppi_buffer, len, &sent))) 45642475Snsouch goto error; 45742475Snsouch#ifdef DEBUG_1284 45842475Snsouch printf("d"); 45942475Snsouch#endif 46042475Snsouch } 46142475Snsouch 46242475Snsoucherror: 46342475Snsouch 46442475Snsouch#else /* PERIPH_1284 */ 46542475Snsouch int error = ENODEV; 46642475Snsouch#endif 46742475Snsouch 46842475Snsouch return (error); 46942475Snsouch} 47042475Snsouch 47142475Snsouchstatic int 47236735Sdfrppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 47328219Smsmith{ 47432178Smsmith u_int unit = minor(dev); 47532178Smsmith struct ppi_data *ppi = ppidata[unit]; 47632178Smsmith int error = 0; 47732178Smsmith u_int8_t *val = (u_int8_t *)data; 47832178Smsmith 47932178Smsmith switch (cmd) { 48032178Smsmith 48132178Smsmith case PPIGDATA: /* get data register */ 48232178Smsmith *val = ppb_rdtr(&ppi->ppi_dev); 48332178Smsmith break; 48432178Smsmith case PPIGSTATUS: /* get status bits */ 48532178Smsmith *val = ppb_rstr(&ppi->ppi_dev); 48632178Smsmith break; 48732178Smsmith case PPIGCTRL: /* get control bits */ 48832178Smsmith *val = ppb_rctr(&ppi->ppi_dev); 48932178Smsmith break; 49043433Snsouch case PPIGEPPD: /* get EPP data bits */ 49143433Snsouch *val = ppb_repp_D(&ppi->ppi_dev); 49232178Smsmith break; 49332178Smsmith case PPIGECR: /* get ECP bits */ 49432178Smsmith *val = ppb_recr(&ppi->ppi_dev); 49532178Smsmith break; 49632178Smsmith case PPIGFIFO: /* read FIFO */ 49732178Smsmith *val = ppb_rfifo(&ppi->ppi_dev); 49832178Smsmith break; 49932178Smsmith 50032178Smsmith case PPISDATA: /* set data register */ 50132178Smsmith ppb_wdtr(&ppi->ppi_dev, *val); 50232178Smsmith break; 50332178Smsmith case PPISSTATUS: /* set status bits */ 50432178Smsmith ppb_wstr(&ppi->ppi_dev, *val); 50532178Smsmith break; 50632178Smsmith case PPISCTRL: /* set control bits */ 50732178Smsmith ppb_wctr(&ppi->ppi_dev, *val); 50832178Smsmith break; 50943433Snsouch case PPISEPPD: /* set EPP data bits */ 51043433Snsouch ppb_wepp_D(&ppi->ppi_dev, *val); 51132178Smsmith break; 51232178Smsmith case PPISECR: /* set ECP bits */ 51332178Smsmith ppb_wecr(&ppi->ppi_dev, *val); 51432178Smsmith break; 51532178Smsmith case PPISFIFO: /* write FIFO */ 51632178Smsmith ppb_wfifo(&ppi->ppi_dev, *val); 51732178Smsmith break; 51843433Snsouch 51943433Snsouch case PPIGEPPA: /* get EPP address bits */ 52043433Snsouch *val = ppb_repp_A(&ppi->ppi_dev); 52143433Snsouch break; 52243433Snsouch case PPISEPPA: /* set EPP address bits */ 52343433Snsouch ppb_wepp_A(&ppi->ppi_dev, *val); 52443433Snsouch break; 52532178Smsmith default: 52632178Smsmith error = ENOTTY; 52732178Smsmith break; 52832178Smsmith } 52932178Smsmith 53032178Smsmith return (error); 53128219Smsmith} 53228219Smsmith 53328257Smsmith#ifdef PPI_MODULE 53428257Smsmith 53528257SmsmithMOD_DEV(ppi, LM_DT_CHAR, CDEV_MAJOR, &ppi_cdevsw); 53628257Smsmith 53728257Smsmithstatic int 53828257Smsmithppi_load(struct lkm_table *lkmtp, int cmd) 53928257Smsmith{ 54028257Smsmith struct ppb_data *ppb; 54128257Smsmith struct ppb_device *dev; 54228257Smsmith int i; 54328257Smsmith 54428257Smsmith for (ppb = ppb_next_bus(NULL); ppb; ppb = ppb_next_bus(ppb)) { 54528257Smsmith 54628257Smsmith dev = ppiprobe(ppb); 54728257Smsmith ppiattach(dev); 54828257Smsmith 54928257Smsmith ppb_attach_device(dev); 55028257Smsmith } 55128257Smsmith 55228257Smsmith return (0); 55328257Smsmith} 55428257Smsmith 55528257Smsmithstatic int 55628257Smsmithppi_unload(struct lkm_table *lkmtp, int cmd) 55728257Smsmith{ 55828257Smsmith int i; 55928257Smsmith 56028257Smsmith for (i = nppi-1; i > 0; i--) { 56128257Smsmith ppb_remove_device(&ppidata[i]->ppi_dev); 56228257Smsmith free(ppidata[i], M_TEMP); 56328257Smsmith } 56428257Smsmith 56528257Smsmith return (0); 56628257Smsmith} 56728257Smsmith 56828257Smsmithint 56928257Smsmithppi_mod(struct lkm_table *lkmtp, int cmd, int ver) 57028257Smsmith{ 57128257Smsmith DISPATCH(lkmtp, cmd, ver, ppi_load, ppi_unload, lkm_nullcmd); 57228257Smsmith} 57328257Smsmith 57428257Smsmith#endif /* PPI_MODULE */ 57528257Smsmith 57628219Smsmithstatic ppi_devsw_installed = 0; 57728219Smsmith 57828257Smsmithstatic void ppi_drvinit(void *unused) 57928219Smsmith{ 58028219Smsmith dev_t dev; 58128219Smsmith 58228257Smsmith if (!ppi_devsw_installed ) { 58328219Smsmith dev = makedev(CDEV_MAJOR, 0); 58428219Smsmith cdevsw_add(&dev, &ppi_cdevsw, NULL); 58528219Smsmith ppi_devsw_installed = 1; 58628219Smsmith } 58728219Smsmith} 58828219Smsmith 58928257SmsmithSYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL) 59028257Smsmith 59128257Smsmith#endif /* NPPI */ 592