ppi.c revision 47625
1178825Sdfr/*- 2178825Sdfr * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith 3178825Sdfr * All rights reserved. 4178825Sdfr * 5178825Sdfr * Redistribution and use in source and binary forms, with or without 6178825Sdfr * modification, are permitted provided that the following conditions 7178825Sdfr * are met: 8178825Sdfr * 1. Redistributions of source code must retain the above copyright 9178825Sdfr * notice, this list of conditions and the following disclaimer. 10178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer in the 12178825Sdfr * documentation and/or other materials provided with the distribution. 13178825Sdfr * 14178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178825Sdfr * SUCH DAMAGE. 25178825Sdfr * 26178825Sdfr * $Id: ppi.c,v 1.13 1999/04/28 10:51:39 dt Exp $ 27178825Sdfr * 28178825Sdfr */ 29178825Sdfr#include "ppi.h" 30178825Sdfr 31178825Sdfr#if NPPI > 0 32178825Sdfr 33178825Sdfr#include <sys/param.h> 34178825Sdfr#include <sys/systm.h> 35178825Sdfr#include <sys/conf.h> 36178825Sdfr#include <sys/kernel.h> 37178825Sdfr#include <sys/uio.h> 38178825Sdfr#include <sys/malloc.h> 39178825Sdfr#include <sys/fcntl.h> 40178825Sdfr 41178825Sdfr#include <machine/clock.h> 42178825Sdfr 43178825Sdfr#include <dev/ppbus/ppbconf.h> 44178825Sdfr#include <dev/ppbus/ppb_msq.h> 45178825Sdfr 46178825Sdfr#include "opt_ppb_1284.h" 47178825Sdfr 48178825Sdfr#ifdef PERIPH_1284 49178825Sdfr#include <dev/ppbus/ppb_1284.h> 50178825Sdfr#endif 51178825Sdfr 52178825Sdfr#include <dev/ppbus/ppi.h> 53178825Sdfr 54178825Sdfr#define BUFSIZE 512 55178825Sdfr 56178825Sdfrstruct ppi_data { 57178825Sdfr 58178825Sdfr int ppi_unit; 59178825Sdfr int ppi_flags; 60178825Sdfr#define HAVE_PPBUS (1<<0) 61178825Sdfr#define HAD_PPBUS (1<<1) 62178825Sdfr 63178825Sdfr int ppi_count; 64178825Sdfr int ppi_mode; /* IEEE1284 mode */ 65178825Sdfr char ppi_buffer[BUFSIZE]; 66178825Sdfr 67178825Sdfr struct ppb_device ppi_dev; 68178825Sdfr}; 69178825Sdfr 70178825Sdfr#define MAXPPI 8 /* XXX not much better! */ 71178825Sdfrstatic int nppi = 0; 72178825Sdfrstatic struct ppi_data *ppidata[MAXPPI]; 73178825Sdfr 74178825Sdfr/* 75178825Sdfr * Make ourselves visible as a ppbus driver 76178825Sdfr */ 77178825Sdfr 78178825Sdfrstatic struct ppb_device *ppiprobe(struct ppb_data *ppb); 79178825Sdfrstatic int ppiattach(struct ppb_device *dev); 80178825Sdfrstatic void ppiintr(int unit); 81178825Sdfr 82178825Sdfrstatic struct ppb_driver ppidriver = { 83178825Sdfr ppiprobe, ppiattach, "ppi" 84178825Sdfr}; 85178825SdfrDATA_SET(ppbdriver_set, ppidriver); 86178825Sdfr 87178825Sdfrstatic d_open_t ppiopen; 88178825Sdfrstatic d_close_t ppiclose; 89178825Sdfrstatic d_ioctl_t ppiioctl; 90178825Sdfrstatic d_write_t ppiwrite; 91178825Sdfrstatic d_read_t ppiread; 92178825Sdfr 93178825Sdfr#define CDEV_MAJOR 82 94178825Sdfrstatic struct cdevsw ppi_cdevsw = { 95178825Sdfr /* open */ ppiopen, 96178825Sdfr /* close */ ppiclose, 97178825Sdfr /* read */ ppiread, 98178825Sdfr /* write */ ppiwrite, 99178825Sdfr /* ioctl */ ppiioctl, 100178825Sdfr /* stop */ nostop, 101178825Sdfr /* reset */ noreset, 102178825Sdfr /* devtotty */ nodevtotty, 103178825Sdfr /* poll */ nopoll, 104178825Sdfr /* mmap */ nommap, 105178825Sdfr /* strategy */ nostrategy, 106178825Sdfr /* name */ "ppi", 107178825Sdfr /* parms */ noparms, 108178825Sdfr /* maj */ CDEV_MAJOR, 109178825Sdfr /* dump */ nodump, 110178825Sdfr /* psize */ nopsize, 111178825Sdfr /* flags */ 0, 112178825Sdfr /* maxio */ 0, 113178825Sdfr /* bmaj */ -1 114178825Sdfr}; 115178825Sdfr 116178825Sdfr#ifdef PERIPH_1284 117178825Sdfr 118178825Sdfrstatic void 119178825Sdfrppi_enable_intr(struct ppi_data *ppi) 120178825Sdfr{ 121178825Sdfr char r; 122178825Sdfr 123178825Sdfr r = ppb_rctr(&ppi->ppi_dev); 124178825Sdfr ppb_wctr(&ppi->ppi_dev, r | IRQENABLE); 125178825Sdfr 126178825Sdfr return; 127178825Sdfr} 128178825Sdfr 129178825Sdfrstatic void 130178825Sdfrppi_disable_intr(struct ppi_data *ppi) 131178825Sdfr{ 132178825Sdfr char r; 133178825Sdfr 134178825Sdfr r = ppb_rctr(&ppi->ppi_dev); 135178825Sdfr ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE); 136178825Sdfr 137178825Sdfr return; 138178825Sdfr} 139178825Sdfr 140178825Sdfr#endif /* PERIPH_1284 */ 141178825Sdfr 142178825Sdfr/* 143178825Sdfr * ppiprobe() 144178825Sdfr */ 145178825Sdfrstatic struct ppb_device * 146178825Sdfrppiprobe(struct ppb_data *ppb) 147178825Sdfr{ 148178825Sdfr struct ppi_data *ppi; 149178825Sdfr 150178825Sdfr ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data), 151178825Sdfr M_TEMP, M_NOWAIT); 152201444Sbrooks if (!ppi) { 153178825Sdfr printf("ppi: cannot malloc!\n"); 154178825Sdfr return 0; 155178825Sdfr } 156178825Sdfr bzero(ppi, sizeof(struct ppi_data)); 157178825Sdfr 158178825Sdfr ppidata[nppi] = ppi; 159178825Sdfr 160178825Sdfr /* 161178825Sdfr * ppi dependent initialisation. 162178825Sdfr */ 163178825Sdfr ppi->ppi_unit = nppi; 164178825Sdfr 165178825Sdfr /* 166178825Sdfr * ppbus dependent initialisation. 167178825Sdfr */ 168178825Sdfr ppi->ppi_dev.id_unit = ppi->ppi_unit; 169178825Sdfr ppi->ppi_dev.ppb = ppb; 170178825Sdfr ppi->ppi_dev.intr = ppiintr; 171178825Sdfr 172178825Sdfr /* Ok, go to next device on next probe */ 173178825Sdfr nppi ++; 174178825Sdfr 175178825Sdfr return &ppi->ppi_dev; 176178825Sdfr} 177178825Sdfr 178178825Sdfrstatic int 179178825Sdfrppiattach(struct ppb_device *dev) 180178825Sdfr{ 181178825Sdfr /* 182178825Sdfr * Report ourselves 183178825Sdfr */ 184178825Sdfr printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 185178825Sdfr dev->id_unit, dev->ppb->ppb_link->adapter_unit); 186178825Sdfr 187178825Sdfr return (1); 188178825Sdfr} 189178825Sdfr 190178825Sdfr/* 191178825Sdfr * Cable 192178825Sdfr * ----- 193178825Sdfr * 194178825Sdfr * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 195178825Sdfr * 196178825Sdfr * nStrobe <-> nAck 1 <-> 10 197178825Sdfr * nAutofd <-> Busy 11 <-> 14 198178825Sdfr * nSelectin <-> Select 17 <-> 13 199178825Sdfr * nInit <-> nFault 15 <-> 16 200178825Sdfr * 201178825Sdfr */ 202178825Sdfrstatic void 203178825Sdfrppiintr(int unit) 204178825Sdfr{ 205178825Sdfr#ifdef PERIPH_1284 206178825Sdfr struct ppi_data *ppi = ppidata[unit]; 207178825Sdfr 208178825Sdfr ppi_disable_intr(ppi); 209178825Sdfr 210178825Sdfr switch (ppi->ppi_dev.ppb->state) { 211178825Sdfr 212178825Sdfr /* accept IEEE1284 negociation then wakeup an waiting process to 213178825Sdfr * continue negociation at process level */ 214178825Sdfr case PPB_FORWARD_IDLE: 215178825Sdfr /* Event 1 */ 216178825Sdfr if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) == 217178825Sdfr (SELECT | nBUSY)) { 218178825Sdfr /* IEEE1284 negociation */ 219178825Sdfr#ifdef DEBUG_1284 220178825Sdfr printf("N"); 221178825Sdfr#endif 222178825Sdfr 223178825Sdfr /* Event 2 - prepare for reading the ext. value */ 224178825Sdfr ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN); 225178825Sdfr 226178825Sdfr ppi->ppi_dev.ppb->state = PPB_NEGOCIATION; 227178825Sdfr 228178825Sdfr } else { 229178825Sdfr#ifdef DEBUG_1284 230178825Sdfr printf("0x%x", ppb_rstr(&ppi->ppi_dev)); 231178825Sdfr#endif 232178825Sdfr ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT); 233178825Sdfr break; 234178825Sdfr } 235178825Sdfr 236178825Sdfr /* wake up any process waiting for negociation from 237178825Sdfr * remote master host */ 238178825Sdfr 239178825Sdfr /* XXX should set a variable to warn the process about 240178825Sdfr * the interrupt */ 241178825Sdfr 242178825Sdfr wakeup(ppi); 243178825Sdfr break; 244178825Sdfr default: 245178825Sdfr#ifdef DEBUG_1284 246178825Sdfr printf("?%d", ppi->ppi_dev.ppb->state); 247178825Sdfr#endif 248178825Sdfr ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE; 249178825Sdfr ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE); 250178825Sdfr break; 251178825Sdfr } 252178825Sdfr 253178825Sdfr ppi_enable_intr(ppi); 254178825Sdfr#endif /* PERIPH_1284 */ 255178825Sdfr 256178825Sdfr return; 257178825Sdfr} 258178825Sdfr 259178825Sdfrstatic int 260178825Sdfrppiopen(dev_t dev, int flags, int fmt, struct proc *p) 261178825Sdfr{ 262178825Sdfr u_int unit = minor(dev); 263178825Sdfr struct ppi_data *ppi = ppidata[unit]; 264178825Sdfr int res; 265178825Sdfr 266178825Sdfr if (unit >= nppi) 267178825Sdfr return (ENXIO); 268178825Sdfr 269178825Sdfr if (!(ppi->ppi_flags & HAVE_PPBUS)) { 270178825Sdfr if ((res = ppb_request_bus(&ppi->ppi_dev, 271178825Sdfr (flags & O_NONBLOCK) ? PPB_DONTWAIT : 272178825Sdfr (PPB_WAIT | PPB_INTR)))) 273178825Sdfr return (res); 274178825Sdfr 275178825Sdfr ppi->ppi_flags |= HAVE_PPBUS; 276178825Sdfr } 277178825Sdfr ppi->ppi_count += 1; 278178825Sdfr 279178825Sdfr return (0); 280178825Sdfr} 281178825Sdfr 282178825Sdfrstatic int 283178825Sdfrppiclose(dev_t dev, int flags, int fmt, struct proc *p) 284178825Sdfr{ 285178825Sdfr u_int unit = minor(dev); 286178825Sdfr struct ppi_data *ppi = ppidata[unit]; 287178825Sdfr 288178825Sdfr ppi->ppi_count --; 289178825Sdfr if (!ppi->ppi_count) { 290178825Sdfr 291178825Sdfr#ifdef PERIPH_1284 292178825Sdfr switch (ppi->ppi_dev.ppb->state) { 293178825Sdfr case PPB_PERIPHERAL_IDLE: 294178825Sdfr ppb_peripheral_terminate(&ppi->ppi_dev, 0); 295178825Sdfr break; 296178825Sdfr case PPB_REVERSE_IDLE: 297178825Sdfr case PPB_EPP_IDLE: 298178825Sdfr case PPB_ECP_FORWARD_IDLE: 299178825Sdfr default: 300178825Sdfr ppb_1284_terminate(&ppi->ppi_dev); 301178825Sdfr break; 302178825Sdfr } 303178825Sdfr#endif /* PERIPH_1284 */ 304178825Sdfr 305178825Sdfr ppb_release_bus(&ppi->ppi_dev); 306178825Sdfr ppi->ppi_flags &= ~HAVE_PPBUS; 307178825Sdfr } 308178825Sdfr 309178825Sdfr return (0); 310178825Sdfr} 311178825Sdfr 312178825Sdfr/* 313178825Sdfr * ppiread() 314178825Sdfr * 315178825Sdfr * IEEE1284 compliant read. 316178825Sdfr * 317178825Sdfr * First, try negociation to BYTE then NIBBLE mode 318178825Sdfr * If no data is available, wait for it otherwise transfer as much as possible 319178825Sdfr */ 320178825Sdfrstatic int 321178825Sdfrppiread(dev_t dev, struct uio *uio, int ioflag) 322178825Sdfr{ 323178825Sdfr#ifdef PERIPH_1284 324178825Sdfr u_int unit = minor(dev); 325178825Sdfr struct ppi_data *ppi = ppidata[unit]; 326178825Sdfr int len, error = 0; 327178825Sdfr 328178825Sdfr switch (ppi->ppi_dev.ppb->state) { 329178825Sdfr case PPB_PERIPHERAL_IDLE: 330178825Sdfr ppb_peripheral_terminate(&ppi->ppi_dev, 0); 331178825Sdfr /* fall throught */ 332178825Sdfr 333178825Sdfr case PPB_FORWARD_IDLE: 334178825Sdfr /* if can't negociate NIBBLE mode then try BYTE mode, 335178825Sdfr * the peripheral may be a computer 336178825Sdfr */ 337178825Sdfr if ((ppb_1284_negociate(&ppi->ppi_dev, 338178825Sdfr ppi->ppi_mode = PPB_NIBBLE, 0))) { 339178825Sdfr 340178825Sdfr /* XXX Wait 2 seconds to let the remote host some 341178825Sdfr * time to terminate its interrupt 342178825Sdfr */ 343178825Sdfr tsleep(ppi, PPBPRI, "ppiread", 2*hz); 344178825Sdfr 345178825Sdfr if ((error = ppb_1284_negociate(&ppi->ppi_dev, 346178825Sdfr ppi->ppi_mode = PPB_BYTE, 0))) 347178825Sdfr return (error); 348178825Sdfr } 349178825Sdfr break; 350178825Sdfr 351178825Sdfr case PPB_REVERSE_IDLE: 352178825Sdfr case PPB_EPP_IDLE: 353178825Sdfr case PPB_ECP_FORWARD_IDLE: 354178825Sdfr default: 355178825Sdfr break; 356178825Sdfr } 357178825Sdfr 358178825Sdfr#ifdef DEBUG_1284 359178825Sdfr printf("N"); 360178825Sdfr#endif 361178825Sdfr /* read data */ 362178825Sdfr len = 0; 363178825Sdfr while (uio->uio_resid) { 364178825Sdfr if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode, 365178825Sdfr ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 366178825Sdfr &len))) { 367178825Sdfr goto error; 368178825Sdfr } 369178825Sdfr 370178825Sdfr if (!len) 371178825Sdfr goto error; /* no more data */ 372178825Sdfr 373178825Sdfr#ifdef DEBUG_1284 374178825Sdfr printf("d"); 375178825Sdfr#endif 376178825Sdfr if ((error = uiomove(ppi->ppi_buffer, len, uio))) 377178825Sdfr goto error; 378178825Sdfr } 379178825Sdfr 380178825Sdfrerror: 381178825Sdfr 382178825Sdfr#else /* PERIPH_1284 */ 383178825Sdfr int error = ENODEV; 384178825Sdfr#endif 385178825Sdfr 386178825Sdfr return (error); 387178825Sdfr} 388178825Sdfr 389178825Sdfr/* 390178825Sdfr * ppiwrite() 391178825Sdfr * 392178825Sdfr * IEEE1284 compliant write 393178825Sdfr * 394178825Sdfr * Actually, this is the peripheral side of a remote IEEE1284 read 395178825Sdfr * 396178825Sdfr * The first part of the negociation (IEEE1284 device detection) is 397178825Sdfr * done at interrupt level, then the remaining is done by the writing 398178825Sdfr * process 399178825Sdfr * 400178825Sdfr * Once negociation done, transfer data 401178825Sdfr */ 402178825Sdfrstatic int 403178825Sdfrppiwrite(dev_t dev, struct uio *uio, int ioflag) 404178825Sdfr{ 405178825Sdfr#ifdef PERIPH_1284 406178825Sdfr u_int unit = minor(dev); 407178825Sdfr struct ppi_data *ppi = ppidata[unit]; 408178825Sdfr struct ppb_data *ppb = ppi->ppi_dev.ppb; 409178825Sdfr int len, error = 0, sent; 410178825Sdfr 411178825Sdfr#if 0 412178825Sdfr int ret; 413178825Sdfr 414178825Sdfr #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 415178825Sdfr #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 416178825Sdfr 417178825Sdfr struct ppb_microseq msq[] = { 418178825Sdfr { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 419178825Sdfr MS_RET(0) 420178825Sdfr }; 421178825Sdfr 422178825Sdfr /* negociate ECP mode */ 423178825Sdfr if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) { 424178825Sdfr printf("ppiwrite: ECP negociation failed\n"); 425178825Sdfr } 426178825Sdfr 427178825Sdfr while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 428178825Sdfr uiomove(ppi->ppi_buffer, len, uio); 429178825Sdfr 430178825Sdfr ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 431178825Sdfr 432178825Sdfr error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret); 433178825Sdfr } 434178825Sdfr#endif 435178825Sdfr 436178825Sdfr /* we have to be peripheral to be able to send data, so 437178825Sdfr * wait for the appropriate state 438178825Sdfr */ 439178825Sdfr if (ppb->state < PPB_PERIPHERAL_NEGOCIATION) 440178825Sdfr ppb_1284_terminate(&ppi->ppi_dev); 441178825Sdfr 442178825Sdfr while (ppb->state != PPB_PERIPHERAL_IDLE) { 443178825Sdfr /* XXX should check a variable before sleeping */ 444178825Sdfr#ifdef DEBUG_1284 445178825Sdfr printf("s"); 446178825Sdfr#endif 447178825Sdfr 448178825Sdfr ppi_enable_intr(ppi); 449178825Sdfr 450178825Sdfr /* sleep until IEEE1284 negociation starts */ 451178825Sdfr error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 452178825Sdfr 453178825Sdfr switch (error) { 454178825Sdfr case 0: 455178825Sdfr /* negociate peripheral side with BYTE mode */ 456178825Sdfr ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0); 457178825Sdfr break; 458178825Sdfr case EWOULDBLOCK: 459178825Sdfr break; 460178825Sdfr default: 461178825Sdfr goto error; 462178825Sdfr } 463178825Sdfr } 464178825Sdfr#ifdef DEBUG_1284 465178825Sdfr printf("N"); 466178825Sdfr#endif 467178825Sdfr 468178825Sdfr /* negociation done, write bytes to master host */ 469178825Sdfr while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { 470178825Sdfr uiomove(ppi->ppi_buffer, len, uio); 471178825Sdfr if ((error = byte_peripheral_write(&ppi->ppi_dev, 472178825Sdfr ppi->ppi_buffer, len, &sent))) 473178825Sdfr goto error; 474178825Sdfr#ifdef DEBUG_1284 475178825Sdfr printf("d"); 476178825Sdfr#endif 477178825Sdfr } 478178825Sdfr 479178825Sdfrerror: 480178825Sdfr 481178825Sdfr#else /* PERIPH_1284 */ 482178825Sdfr int error = ENODEV; 483178825Sdfr#endif 484178825Sdfr 485178825Sdfr return (error); 486178825Sdfr} 487178825Sdfr 488178825Sdfrstatic int 489178825Sdfrppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 490178825Sdfr{ 491178825Sdfr u_int unit = minor(dev); 492178825Sdfr struct ppi_data *ppi = ppidata[unit]; 493178825Sdfr int error = 0; 494178825Sdfr u_int8_t *val = (u_int8_t *)data; 495178825Sdfr 496178825Sdfr switch (cmd) { 497178825Sdfr 498178825Sdfr case PPIGDATA: /* get data register */ 499178825Sdfr *val = ppb_rdtr(&ppi->ppi_dev); 500178825Sdfr break; 501178825Sdfr case PPIGSTATUS: /* get status bits */ 502178825Sdfr *val = ppb_rstr(&ppi->ppi_dev); 503178825Sdfr break; 504178825Sdfr case PPIGCTRL: /* get control bits */ 505178825Sdfr *val = ppb_rctr(&ppi->ppi_dev); 506178825Sdfr break; 507178825Sdfr case PPIGEPPD: /* get EPP data bits */ 508178825Sdfr *val = ppb_repp_D(&ppi->ppi_dev); 509178825Sdfr break; 510178825Sdfr case PPIGECR: /* get ECP bits */ 511178825Sdfr *val = ppb_recr(&ppi->ppi_dev); 512178825Sdfr break; 513178825Sdfr case PPIGFIFO: /* read FIFO */ 514178825Sdfr *val = ppb_rfifo(&ppi->ppi_dev); 515178825Sdfr break; 516178825Sdfr 517178825Sdfr case PPISDATA: /* set data register */ 518178825Sdfr ppb_wdtr(&ppi->ppi_dev, *val); 519178825Sdfr break; 520178825Sdfr case PPISSTATUS: /* set status bits */ 521178825Sdfr ppb_wstr(&ppi->ppi_dev, *val); 522178825Sdfr break; 523178825Sdfr case PPISCTRL: /* set control bits */ 524178825Sdfr ppb_wctr(&ppi->ppi_dev, *val); 525178825Sdfr break; 526178825Sdfr case PPISEPPD: /* set EPP data bits */ 527178825Sdfr ppb_wepp_D(&ppi->ppi_dev, *val); 528178825Sdfr break; 529178825Sdfr case PPISECR: /* set ECP bits */ 530178825Sdfr ppb_wecr(&ppi->ppi_dev, *val); 531178825Sdfr break; 532178825Sdfr case PPISFIFO: /* write FIFO */ 533178825Sdfr ppb_wfifo(&ppi->ppi_dev, *val); 534178825Sdfr break; 535178825Sdfr 536178825Sdfr case PPIGEPPA: /* get EPP address bits */ 537178825Sdfr *val = ppb_repp_A(&ppi->ppi_dev); 538178825Sdfr break; 539178825Sdfr case PPISEPPA: /* set EPP address bits */ 540178825Sdfr ppb_wepp_A(&ppi->ppi_dev, *val); 541178825Sdfr break; 542178825Sdfr default: 543178825Sdfr error = ENOTTY; 544178825Sdfr break; 545178825Sdfr } 546178825Sdfr 547178825Sdfr return (error); 548178825Sdfr} 549178825Sdfr 550178825Sdfrstatic int ppi_devsw_installed; 551178825Sdfr 552178825Sdfrstatic void ppi_drvinit(void *unused) 553178825Sdfr{ 554178825Sdfr dev_t dev; 555178825Sdfr 556178825Sdfr if (!ppi_devsw_installed ) { 557178825Sdfr dev = makedev(CDEV_MAJOR, 0); 558178825Sdfr cdevsw_add(&dev, &ppi_cdevsw, NULL); 559178825Sdfr ppi_devsw_installed = 1; 560178825Sdfr } 561178825Sdfr} 562178825Sdfr 563178825SdfrSYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL) 564178825Sdfr 565178825Sdfr#endif /* NPPI */ 566178825Sdfr