1ed381522SMike Smith /*- 26f34dba9SMike Smith * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith 3ed381522SMike Smith * All rights reserved. 4ed381522SMike Smith * 5ed381522SMike Smith * Redistribution and use in source and binary forms, with or without 6ed381522SMike Smith * modification, are permitted provided that the following conditions 7ed381522SMike Smith * are met: 8ed381522SMike Smith * 1. Redistributions of source code must retain the above copyright 9ed381522SMike Smith * notice, this list of conditions and the following disclaimer. 10ed381522SMike Smith * 2. Redistributions in binary form must reproduce the above copyright 11ed381522SMike Smith * notice, this list of conditions and the following disclaimer in the 12ed381522SMike Smith * documentation and/or other materials provided with the distribution. 13ed381522SMike Smith * 14ed381522SMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ed381522SMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ed381522SMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ed381522SMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ed381522SMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ed381522SMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ed381522SMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ed381522SMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ed381522SMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ed381522SMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ed381522SMike Smith * SUCH DAMAGE. 25ed381522SMike Smith * 26bc35c174SNicolas Souchu * $Id: ppi.c,v 1.8 1998/12/07 21:58:16 archie Exp $ 27ed381522SMike Smith * 28ed381522SMike Smith */ 29e51b0386SMike Smith #include "ppi.h" 30e51b0386SMike Smith 31e51b0386SMike Smith #if NPPI > 0 32e51b0386SMike Smith 33ed381522SMike Smith #include <sys/param.h> 34ed381522SMike Smith #include <sys/systm.h> 35ed381522SMike Smith #include <sys/conf.h> 36ed381522SMike Smith #include <sys/kernel.h> 37bc35c174SNicolas Souchu #include <sys/uio.h> 38ed381522SMike Smith #include <sys/malloc.h> 396f34dba9SMike Smith #include <sys/fcntl.h> 40ed381522SMike Smith 41bc35c174SNicolas Souchu #include <machine/clock.h> 42bc35c174SNicolas Souchu 43ed381522SMike Smith #include <dev/ppbus/ppbconf.h> 44bc35c174SNicolas Souchu #include <dev/ppbus/ppb_msq.h> 45bc35c174SNicolas Souchu 46bc35c174SNicolas Souchu #include "opt_ppb_1284.h" 47bc35c174SNicolas Souchu 48bc35c174SNicolas Souchu #ifdef PERIPH_1284 49bc35c174SNicolas Souchu #include <dev/ppbus/ppb_1284.h> 50bc35c174SNicolas Souchu #endif 51bc35c174SNicolas Souchu 526f34dba9SMike Smith #include <dev/ppbus/ppi.h> 536f34dba9SMike Smith 54bc35c174SNicolas Souchu #define BUFSIZE 512 55ed381522SMike Smith 56e51b0386SMike Smith struct ppi_data { 57e51b0386SMike Smith 58e51b0386SMike Smith int ppi_unit; 596f34dba9SMike Smith int ppi_flags; 606f34dba9SMike Smith #define HAVE_PPBUS (1<<0) 61bc35c174SNicolas Souchu #define HAD_PPBUS (1<<1) 62bc35c174SNicolas Souchu 63bc35c174SNicolas Souchu int ppi_count; 64bc35c174SNicolas Souchu int ppi_mode; /* IEEE1284 mode */ 65bc35c174SNicolas Souchu char ppi_buffer[BUFSIZE]; 66e51b0386SMike Smith 67e51b0386SMike Smith struct ppb_device ppi_dev; 68e51b0386SMike Smith }; 69e51b0386SMike Smith 70ed381522SMike Smith #define MAXPPI 8 /* XXX not much better! */ 71e51b0386SMike Smith static int nppi = 0; 72ed381522SMike Smith static struct ppi_data *ppidata[MAXPPI]; 73ed381522SMike Smith 74ed381522SMike Smith /* 75ed381522SMike Smith * Make ourselves visible as a ppbus driver 76ed381522SMike Smith */ 77ed381522SMike Smith 78ed381522SMike Smith static struct ppb_device *ppiprobe(struct ppb_data *ppb); 79ed381522SMike Smith static int ppiattach(struct ppb_device *dev); 80ed381522SMike Smith static void ppiintr(int unit); 81ed381522SMike Smith 82ed381522SMike Smith static struct ppb_driver ppidriver = { 83ed381522SMike Smith ppiprobe, ppiattach, "ppi" 84ed381522SMike Smith }; 85ed381522SMike Smith DATA_SET(ppbdriver_set, ppidriver); 86ed381522SMike Smith 87ed381522SMike Smith static d_open_t ppiopen; 88ed381522SMike Smith static d_close_t ppiclose; 89ed381522SMike Smith static d_ioctl_t ppiioctl; 90bc35c174SNicolas Souchu static d_write_t ppiwrite; 91bc35c174SNicolas Souchu static d_read_t ppiread; 92ed381522SMike Smith 934f013cf5SMike Smith #define CDEV_MAJOR 82 94ed381522SMike Smith static struct cdevsw ppi_cdevsw = 95bc35c174SNicolas Souchu { ppiopen, ppiclose, ppiread, ppiwrite, /* 82 */ 96ed381522SMike Smith ppiioctl, nullstop, nullreset, nodevtotty, 97ed381522SMike Smith seltrue, nommap, nostrat, "ppi", NULL, -1 }; 98ed381522SMike Smith 99bc35c174SNicolas Souchu #ifdef PERIPH_1284 100bc35c174SNicolas Souchu 101bc35c174SNicolas Souchu static void 102bc35c174SNicolas Souchu ppi_enable_intr(struct ppi_data *ppi) 103bc35c174SNicolas Souchu { 104bc35c174SNicolas Souchu char r; 105bc35c174SNicolas Souchu 106bc35c174SNicolas Souchu r = ppb_rctr(&ppi->ppi_dev); 107bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, r | IRQENABLE); 108bc35c174SNicolas Souchu 109bc35c174SNicolas Souchu return; 110bc35c174SNicolas Souchu } 111bc35c174SNicolas Souchu 112bc35c174SNicolas Souchu static void 113bc35c174SNicolas Souchu ppi_disable_intr(struct ppi_data *ppi) 114bc35c174SNicolas Souchu { 115bc35c174SNicolas Souchu char r; 116bc35c174SNicolas Souchu 117bc35c174SNicolas Souchu r = ppb_rctr(&ppi->ppi_dev); 118bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE); 119bc35c174SNicolas Souchu 120bc35c174SNicolas Souchu return; 121bc35c174SNicolas Souchu } 122bc35c174SNicolas Souchu 123bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 124bc35c174SNicolas Souchu 125ed381522SMike Smith /* 126ed381522SMike Smith * ppiprobe() 127ed381522SMike Smith */ 128ed381522SMike Smith static struct ppb_device * 129ed381522SMike Smith ppiprobe(struct ppb_data *ppb) 130ed381522SMike Smith { 131ed381522SMike Smith struct ppi_data *ppi; 132ed381522SMike Smith 133ed381522SMike Smith ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data), 134ed381522SMike Smith M_TEMP, M_NOWAIT); 135ed381522SMike Smith if (!ppi) { 136ed381522SMike Smith printf("ppi: cannot malloc!\n"); 137ed381522SMike Smith return 0; 138ed381522SMike Smith } 139ed381522SMike Smith bzero(ppi, sizeof(struct ppi_data)); 140ed381522SMike Smith 141ed381522SMike Smith ppidata[nppi] = ppi; 142ed381522SMike Smith 143ed381522SMike Smith /* 144ed381522SMike Smith * ppi dependent initialisation. 145ed381522SMike Smith */ 146ed381522SMike Smith ppi->ppi_unit = nppi; 147ed381522SMike Smith 148ed381522SMike Smith /* 149ed381522SMike Smith * ppbus dependent initialisation. 150ed381522SMike Smith */ 151ed381522SMike Smith ppi->ppi_dev.id_unit = ppi->ppi_unit; 152ed381522SMike Smith ppi->ppi_dev.ppb = ppb; 153ed381522SMike Smith ppi->ppi_dev.intr = ppiintr; 154ed381522SMike Smith 155ed381522SMike Smith /* Ok, go to next device on next probe */ 156ed381522SMike Smith nppi ++; 157ed381522SMike Smith 158ed381522SMike Smith return &ppi->ppi_dev; 159ed381522SMike Smith } 160ed381522SMike Smith 161ed381522SMike Smith static int 162ed381522SMike Smith ppiattach(struct ppb_device *dev) 163ed381522SMike Smith { 164ed381522SMike Smith /* 165ed381522SMike Smith * Report ourselves 166ed381522SMike Smith */ 167ed381522SMike Smith printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 168ed381522SMike Smith dev->id_unit, dev->ppb->ppb_link->adapter_unit); 169ed381522SMike Smith 170ed381522SMike Smith return (1); 171ed381522SMike Smith } 172ed381522SMike Smith 173bc35c174SNicolas Souchu /* 174bc35c174SNicolas Souchu * Cable 175bc35c174SNicolas Souchu * ----- 176bc35c174SNicolas Souchu * 177bc35c174SNicolas Souchu * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 178bc35c174SNicolas Souchu * 179bc35c174SNicolas Souchu * nStrobe <-> nAck 1 <-> 10 180bc35c174SNicolas Souchu * nAutofd <-> Busy 11 <-> 14 181bc35c174SNicolas Souchu * nSelectin <-> Select 17 <-> 13 182bc35c174SNicolas Souchu * nInit <-> nFault 15 <-> 16 183bc35c174SNicolas Souchu * 184bc35c174SNicolas Souchu */ 185ed381522SMike Smith static void 186ed381522SMike Smith ppiintr(int unit) 187ed381522SMike Smith { 188bc35c174SNicolas Souchu #ifdef PERIPH_1284 189bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 190bc35c174SNicolas Souchu 191bc35c174SNicolas Souchu ppi_disable_intr(ppi); 192bc35c174SNicolas Souchu 193bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 194bc35c174SNicolas Souchu 195bc35c174SNicolas Souchu /* accept IEEE1284 negociation then wakeup an waiting process to 196bc35c174SNicolas Souchu * continue negociation at process level */ 197bc35c174SNicolas Souchu case PPB_FORWARD_IDLE: 198bc35c174SNicolas Souchu /* Event 1 */ 199bc35c174SNicolas Souchu if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) == 200bc35c174SNicolas Souchu (SELECT | nBUSY)) { 201bc35c174SNicolas Souchu /* IEEE1284 negociation */ 202bc35c174SNicolas Souchu #ifdef DEBUG_1284 203bc35c174SNicolas Souchu printf("N"); 204bc35c174SNicolas Souchu #endif 205bc35c174SNicolas Souchu 206bc35c174SNicolas Souchu /* Event 2 - prepare for reading the ext. value */ 207bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN); 208bc35c174SNicolas Souchu 209bc35c174SNicolas Souchu ppi->ppi_dev.ppb->state = PPB_NEGOCIATION; 210bc35c174SNicolas Souchu 211bc35c174SNicolas Souchu } else { 212bc35c174SNicolas Souchu #ifdef DEBUG_1284 213bc35c174SNicolas Souchu printf("0x%x", ppb_rstr(&ppi->ppi_dev)); 214bc35c174SNicolas Souchu #endif 215bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT); 216bc35c174SNicolas Souchu break; 217bc35c174SNicolas Souchu } 218bc35c174SNicolas Souchu 219bc35c174SNicolas Souchu /* wake up any process waiting for negociation from 220bc35c174SNicolas Souchu * remote master host */ 221bc35c174SNicolas Souchu 222bc35c174SNicolas Souchu /* XXX should set a variable to warn the process about 223bc35c174SNicolas Souchu * the interrupt */ 224bc35c174SNicolas Souchu 225bc35c174SNicolas Souchu wakeup(ppi); 226bc35c174SNicolas Souchu break; 227bc35c174SNicolas Souchu default: 228bc35c174SNicolas Souchu #ifdef DEBUG_1284 229bc35c174SNicolas Souchu printf("?%d", ppi->ppi_dev.ppb->state); 230bc35c174SNicolas Souchu #endif 231bc35c174SNicolas Souchu ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE; 232bc35c174SNicolas Souchu ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE); 233bc35c174SNicolas Souchu break; 234bc35c174SNicolas Souchu } 235bc35c174SNicolas Souchu 236bc35c174SNicolas Souchu ppi_enable_intr(ppi); 237bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 238bc35c174SNicolas Souchu 239ed381522SMike Smith return; 240ed381522SMike Smith } 241ed381522SMike Smith 242ed381522SMike Smith static int 243ed381522SMike Smith ppiopen(dev_t dev, int flags, int fmt, struct proc *p) 244ed381522SMike Smith { 245e51b0386SMike Smith u_int unit = minor(dev); 2466f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 2476f34dba9SMike Smith int res; 248e51b0386SMike Smith 249e51b0386SMike Smith if (unit >= nppi) 250e51b0386SMike Smith return (ENXIO); 251e51b0386SMike Smith 252bc35c174SNicolas Souchu if (!(ppi->ppi_flags & HAVE_PPBUS)) { 253bc35c174SNicolas Souchu if ((res = ppb_request_bus(&ppi->ppi_dev, 254bc35c174SNicolas Souchu (flags & O_NONBLOCK) ? PPB_DONTWAIT : 255bc35c174SNicolas Souchu (PPB_WAIT | PPB_INTR)))) 2566f34dba9SMike Smith return (res); 257e51b0386SMike Smith 2586f34dba9SMike Smith ppi->ppi_flags |= HAVE_PPBUS; 259bc35c174SNicolas Souchu } 260bc35c174SNicolas Souchu ppi->ppi_count += 1; 261bc35c174SNicolas Souchu 2626f34dba9SMike Smith return (0); 263ed381522SMike Smith } 264ed381522SMike Smith 265ed381522SMike Smith static int 266ed381522SMike Smith ppiclose(dev_t dev, int flags, int fmt, struct proc *p) 267ed381522SMike Smith { 2686f34dba9SMike Smith u_int unit = minor(dev); 2696f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 2706f34dba9SMike Smith 271bc35c174SNicolas Souchu ppi->ppi_count --; 272bc35c174SNicolas Souchu if (!ppi->ppi_count) { 273bc35c174SNicolas Souchu 274bc35c174SNicolas Souchu #ifdef PERIPH_1284 275bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 276bc35c174SNicolas Souchu case PPB_PERIPHERAL_IDLE: 277bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, 0); 278bc35c174SNicolas Souchu break; 279bc35c174SNicolas Souchu case PPB_REVERSE_IDLE: 280bc35c174SNicolas Souchu case PPB_EPP_IDLE: 281bc35c174SNicolas Souchu case PPB_ECP_FORWARD_IDLE: 282bc35c174SNicolas Souchu default: 283bc35c174SNicolas Souchu ppb_1284_terminate(&ppi->ppi_dev); 284bc35c174SNicolas Souchu break; 285bc35c174SNicolas Souchu } 286bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 287bc35c174SNicolas Souchu 2886f34dba9SMike Smith ppb_release_bus(&ppi->ppi_dev); 2896f34dba9SMike Smith ppi->ppi_flags &= ~HAVE_PPBUS; 290bc35c174SNicolas Souchu } 291bc35c174SNicolas Souchu 2926f34dba9SMike Smith return (0); 293ed381522SMike Smith } 294ed381522SMike Smith 295bc35c174SNicolas Souchu /* 296bc35c174SNicolas Souchu * ppiread() 297bc35c174SNicolas Souchu * 298bc35c174SNicolas Souchu * IEEE1284 compliant read. 299bc35c174SNicolas Souchu * 300bc35c174SNicolas Souchu * First, try negociation to BYTE then NIBBLE mode 301bc35c174SNicolas Souchu * If no data is available, wait for it otherwise transfer as much as possible 302bc35c174SNicolas Souchu */ 303bc35c174SNicolas Souchu static int 304bc35c174SNicolas Souchu ppiread(dev_t dev, struct uio *uio, int ioflag) 305bc35c174SNicolas Souchu { 306bc35c174SNicolas Souchu #ifdef PERIPH_1284 307bc35c174SNicolas Souchu u_int unit = minor(dev); 308bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 309bc35c174SNicolas Souchu int len, error = 0; 310bc35c174SNicolas Souchu 311bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 312bc35c174SNicolas Souchu case PPB_PERIPHERAL_IDLE: 313bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, 0); 314bc35c174SNicolas Souchu /* fall throught */ 315bc35c174SNicolas Souchu 316bc35c174SNicolas Souchu case PPB_FORWARD_IDLE: 317bc35c174SNicolas Souchu /* if can't negociate NIBBLE mode then try BYTE mode, 318bc35c174SNicolas Souchu * the peripheral may be a computer 319bc35c174SNicolas Souchu */ 320bc35c174SNicolas Souchu if ((ppb_1284_negociate(&ppi->ppi_dev, 321bc35c174SNicolas Souchu ppi->ppi_mode = PPB_NIBBLE, 0))) { 322bc35c174SNicolas Souchu 323bc35c174SNicolas Souchu /* XXX Wait 2 seconds to let the remote host some 324bc35c174SNicolas Souchu * time to terminate its interrupt 325bc35c174SNicolas Souchu */ 326bc35c174SNicolas Souchu tsleep(ppi, PPBPRI, "ppiread", 2*hz); 327bc35c174SNicolas Souchu 328bc35c174SNicolas Souchu if ((error = ppb_1284_negociate(&ppi->ppi_dev, 329bc35c174SNicolas Souchu ppi->ppi_mode = PPB_BYTE, 0))) 330bc35c174SNicolas Souchu return (error); 331bc35c174SNicolas Souchu } 332bc35c174SNicolas Souchu break; 333bc35c174SNicolas Souchu 334bc35c174SNicolas Souchu case PPB_REVERSE_IDLE: 335bc35c174SNicolas Souchu case PPB_EPP_IDLE: 336bc35c174SNicolas Souchu case PPB_ECP_FORWARD_IDLE: 337bc35c174SNicolas Souchu default: 338bc35c174SNicolas Souchu break; 339bc35c174SNicolas Souchu } 340bc35c174SNicolas Souchu 341bc35c174SNicolas Souchu #ifdef DEBUG_1284 342bc35c174SNicolas Souchu printf("N"); 343bc35c174SNicolas Souchu #endif 344bc35c174SNicolas Souchu /* read data */ 345bc35c174SNicolas Souchu len = 0; 346bc35c174SNicolas Souchu while (uio->uio_resid) { 347bc35c174SNicolas Souchu if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode, 348bc35c174SNicolas Souchu ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 349bc35c174SNicolas Souchu &len))) { 350bc35c174SNicolas Souchu goto error; 351bc35c174SNicolas Souchu } 352bc35c174SNicolas Souchu 353bc35c174SNicolas Souchu if (!len) 354bc35c174SNicolas Souchu goto error; /* no more data */ 355bc35c174SNicolas Souchu 356bc35c174SNicolas Souchu #ifdef DEBUG_1284 357bc35c174SNicolas Souchu printf("d"); 358bc35c174SNicolas Souchu #endif 359bc35c174SNicolas Souchu if ((error = uiomove(ppi->ppi_buffer, len, uio))) 360bc35c174SNicolas Souchu goto error; 361bc35c174SNicolas Souchu } 362bc35c174SNicolas Souchu 363bc35c174SNicolas Souchu error: 364bc35c174SNicolas Souchu 365bc35c174SNicolas Souchu #else /* PERIPH_1284 */ 366bc35c174SNicolas Souchu int error = ENODEV; 367bc35c174SNicolas Souchu #endif 368bc35c174SNicolas Souchu 369bc35c174SNicolas Souchu return (error); 370bc35c174SNicolas Souchu } 371bc35c174SNicolas Souchu 372bc35c174SNicolas Souchu /* 373bc35c174SNicolas Souchu * ppiwrite() 374bc35c174SNicolas Souchu * 375bc35c174SNicolas Souchu * IEEE1284 compliant write 376bc35c174SNicolas Souchu * 377bc35c174SNicolas Souchu * Actually, this is the peripheral side of a remote IEEE1284 read 378bc35c174SNicolas Souchu * 379bc35c174SNicolas Souchu * The first part of the negociation (IEEE1284 device detection) is 380bc35c174SNicolas Souchu * done at interrupt level, then the remaining is done by the writing 381bc35c174SNicolas Souchu * process 382bc35c174SNicolas Souchu * 383bc35c174SNicolas Souchu * Once negociation done, transfer data 384bc35c174SNicolas Souchu */ 385bc35c174SNicolas Souchu static int 386bc35c174SNicolas Souchu ppiwrite(dev_t dev, struct uio *uio, int ioflag) 387bc35c174SNicolas Souchu { 388bc35c174SNicolas Souchu #ifdef PERIPH_1284 389bc35c174SNicolas Souchu u_int unit = minor(dev); 390bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 391bc35c174SNicolas Souchu struct ppb_data *ppb = ppi->ppi_dev.ppb; 392bc35c174SNicolas Souchu int len, error = 0, sent; 393bc35c174SNicolas Souchu 394bc35c174SNicolas Souchu #if 0 395bc35c174SNicolas Souchu int ret; 396bc35c174SNicolas Souchu 397bc35c174SNicolas Souchu #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 398bc35c174SNicolas Souchu #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 399bc35c174SNicolas Souchu 400bc35c174SNicolas Souchu struct ppb_microseq msq[] = { 401bc35c174SNicolas Souchu { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 402bc35c174SNicolas Souchu MS_RET(0) 403bc35c174SNicolas Souchu }; 404bc35c174SNicolas Souchu 405bc35c174SNicolas Souchu /* negociate ECP mode */ 406bc35c174SNicolas Souchu if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) { 407bc35c174SNicolas Souchu printf("ppiwrite: ECP negociation failed\n"); 408bc35c174SNicolas Souchu } 409bc35c174SNicolas Souchu 410bc35c174SNicolas Souchu while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 411bc35c174SNicolas Souchu uiomove(ppi->ppi_buffer, len, uio); 412bc35c174SNicolas Souchu 413bc35c174SNicolas Souchu ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 414bc35c174SNicolas Souchu 415bc35c174SNicolas Souchu error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret); 416bc35c174SNicolas Souchu } 417bc35c174SNicolas Souchu #endif 418bc35c174SNicolas Souchu 419bc35c174SNicolas Souchu /* we have to be peripheral to be able to send data, so 420bc35c174SNicolas Souchu * wait for the appropriate state 421bc35c174SNicolas Souchu */ 422bc35c174SNicolas Souchu if (ppb->state < PPB_PERIPHERAL_NEGOCIATION) 423bc35c174SNicolas Souchu ppb_1284_terminate(&ppi->ppi_dev); 424bc35c174SNicolas Souchu 425bc35c174SNicolas Souchu while (ppb->state != PPB_PERIPHERAL_IDLE) { 426bc35c174SNicolas Souchu /* XXX should check a variable before sleeping */ 427bc35c174SNicolas Souchu #ifdef DEBUG_1284 428bc35c174SNicolas Souchu printf("s"); 429bc35c174SNicolas Souchu #endif 430bc35c174SNicolas Souchu 431bc35c174SNicolas Souchu ppi_enable_intr(ppi); 432bc35c174SNicolas Souchu 433bc35c174SNicolas Souchu /* sleep until IEEE1284 negociation starts */ 434bc35c174SNicolas Souchu error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 435bc35c174SNicolas Souchu 436bc35c174SNicolas Souchu switch (error) { 437bc35c174SNicolas Souchu case 0: 438bc35c174SNicolas Souchu /* negociate peripheral side with BYTE mode */ 439bc35c174SNicolas Souchu ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0); 440bc35c174SNicolas Souchu break; 441bc35c174SNicolas Souchu case EWOULDBLOCK: 442bc35c174SNicolas Souchu break; 443bc35c174SNicolas Souchu default: 444bc35c174SNicolas Souchu goto error; 445bc35c174SNicolas Souchu } 446bc35c174SNicolas Souchu } 447bc35c174SNicolas Souchu #ifdef DEBUG_1284 448bc35c174SNicolas Souchu printf("N"); 449bc35c174SNicolas Souchu #endif 450bc35c174SNicolas Souchu 451bc35c174SNicolas Souchu /* negociation done, write bytes to master host */ 452bc35c174SNicolas Souchu while (len = min(uio->uio_resid, BUFSIZE)) { 453bc35c174SNicolas Souchu uiomove(ppi->ppi_buffer, len, uio); 454bc35c174SNicolas Souchu if ((error = byte_peripheral_write(&ppi->ppi_dev, 455bc35c174SNicolas Souchu ppi->ppi_buffer, len, &sent))) 456bc35c174SNicolas Souchu goto error; 457bc35c174SNicolas Souchu #ifdef DEBUG_1284 458bc35c174SNicolas Souchu printf("d"); 459bc35c174SNicolas Souchu #endif 460bc35c174SNicolas Souchu } 461bc35c174SNicolas Souchu 462bc35c174SNicolas Souchu error: 463bc35c174SNicolas Souchu 464bc35c174SNicolas Souchu #else /* PERIPH_1284 */ 465bc35c174SNicolas Souchu int error = ENODEV; 466bc35c174SNicolas Souchu #endif 467bc35c174SNicolas Souchu 468bc35c174SNicolas Souchu return (error); 469bc35c174SNicolas Souchu } 470bc35c174SNicolas Souchu 471ed381522SMike Smith static int 472ecbb00a2SDoug Rabson ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 473ed381522SMike Smith { 4746f34dba9SMike Smith u_int unit = minor(dev); 4756f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 4766f34dba9SMike Smith int error = 0; 4776f34dba9SMike Smith u_int8_t *val = (u_int8_t *)data; 4786f34dba9SMike Smith 4796f34dba9SMike Smith switch (cmd) { 4806f34dba9SMike Smith 4816f34dba9SMike Smith case PPIGDATA: /* get data register */ 4826f34dba9SMike Smith *val = ppb_rdtr(&ppi->ppi_dev); 4836f34dba9SMike Smith break; 4846f34dba9SMike Smith case PPIGSTATUS: /* get status bits */ 4856f34dba9SMike Smith *val = ppb_rstr(&ppi->ppi_dev); 4866f34dba9SMike Smith break; 4876f34dba9SMike Smith case PPIGCTRL: /* get control bits */ 4886f34dba9SMike Smith *val = ppb_rctr(&ppi->ppi_dev); 4896f34dba9SMike Smith break; 4906f34dba9SMike Smith case PPIGEPP: /* get EPP bits */ 4916f34dba9SMike Smith *val = ppb_repp(&ppi->ppi_dev); 4926f34dba9SMike Smith break; 4936f34dba9SMike Smith case PPIGECR: /* get ECP bits */ 4946f34dba9SMike Smith *val = ppb_recr(&ppi->ppi_dev); 4956f34dba9SMike Smith break; 4966f34dba9SMike Smith case PPIGFIFO: /* read FIFO */ 4976f34dba9SMike Smith *val = ppb_rfifo(&ppi->ppi_dev); 4986f34dba9SMike Smith break; 4996f34dba9SMike Smith 5006f34dba9SMike Smith case PPISDATA: /* set data register */ 5016f34dba9SMike Smith ppb_wdtr(&ppi->ppi_dev, *val); 5026f34dba9SMike Smith break; 5036f34dba9SMike Smith case PPISSTATUS: /* set status bits */ 5046f34dba9SMike Smith ppb_wstr(&ppi->ppi_dev, *val); 5056f34dba9SMike Smith break; 5066f34dba9SMike Smith case PPISCTRL: /* set control bits */ 5076f34dba9SMike Smith ppb_wctr(&ppi->ppi_dev, *val); 5086f34dba9SMike Smith break; 5096f34dba9SMike Smith case PPISEPP: /* set EPP bits */ 5106f34dba9SMike Smith ppb_wepp(&ppi->ppi_dev, *val); 5116f34dba9SMike Smith break; 5126f34dba9SMike Smith case PPISECR: /* set ECP bits */ 5136f34dba9SMike Smith ppb_wecr(&ppi->ppi_dev, *val); 5146f34dba9SMike Smith break; 5156f34dba9SMike Smith case PPISFIFO: /* write FIFO */ 5166f34dba9SMike Smith ppb_wfifo(&ppi->ppi_dev, *val); 5176f34dba9SMike Smith break; 5186f34dba9SMike Smith default: 5196f34dba9SMike Smith error = ENOTTY; 5206f34dba9SMike Smith break; 5216f34dba9SMike Smith } 5226f34dba9SMike Smith 5236f34dba9SMike Smith return (error); 524ed381522SMike Smith } 525ed381522SMike Smith 526e51b0386SMike Smith #ifdef PPI_MODULE 527e51b0386SMike Smith 528e51b0386SMike Smith MOD_DEV(ppi, LM_DT_CHAR, CDEV_MAJOR, &ppi_cdevsw); 529e51b0386SMike Smith 530e51b0386SMike Smith static int 531e51b0386SMike Smith ppi_load(struct lkm_table *lkmtp, int cmd) 532e51b0386SMike Smith { 533e51b0386SMike Smith struct ppb_data *ppb; 534e51b0386SMike Smith struct ppb_device *dev; 535e51b0386SMike Smith int i; 536e51b0386SMike Smith 537e51b0386SMike Smith for (ppb = ppb_next_bus(NULL); ppb; ppb = ppb_next_bus(ppb)) { 538e51b0386SMike Smith 539e51b0386SMike Smith dev = ppiprobe(ppb); 540e51b0386SMike Smith ppiattach(dev); 541e51b0386SMike Smith 542e51b0386SMike Smith ppb_attach_device(dev); 543e51b0386SMike Smith } 544e51b0386SMike Smith 545e51b0386SMike Smith return (0); 546e51b0386SMike Smith } 547e51b0386SMike Smith 548e51b0386SMike Smith static int 549e51b0386SMike Smith ppi_unload(struct lkm_table *lkmtp, int cmd) 550e51b0386SMike Smith { 551e51b0386SMike Smith int i; 552e51b0386SMike Smith 553e51b0386SMike Smith for (i = nppi-1; i > 0; i--) { 554e51b0386SMike Smith ppb_remove_device(&ppidata[i]->ppi_dev); 555e51b0386SMike Smith free(ppidata[i], M_TEMP); 556e51b0386SMike Smith } 557e51b0386SMike Smith 558e51b0386SMike Smith return (0); 559e51b0386SMike Smith } 560e51b0386SMike Smith 561e51b0386SMike Smith int 562e51b0386SMike Smith ppi_mod(struct lkm_table *lkmtp, int cmd, int ver) 563e51b0386SMike Smith { 564e51b0386SMike Smith DISPATCH(lkmtp, cmd, ver, ppi_load, ppi_unload, lkm_nullcmd); 565e51b0386SMike Smith } 566e51b0386SMike Smith 567e51b0386SMike Smith #endif /* PPI_MODULE */ 568e51b0386SMike Smith 569ed381522SMike Smith static ppi_devsw_installed = 0; 570ed381522SMike Smith 571ed381522SMike Smith static void ppi_drvinit(void *unused) 572ed381522SMike Smith { 573ed381522SMike Smith dev_t dev; 574ed381522SMike Smith 575ed381522SMike Smith if (!ppi_devsw_installed ) { 576ed381522SMike Smith dev = makedev(CDEV_MAJOR, 0); 577ed381522SMike Smith cdevsw_add(&dev, &ppi_cdevsw, NULL); 578ed381522SMike Smith ppi_devsw_installed = 1; 579ed381522SMike Smith } 580ed381522SMike Smith } 581ed381522SMike Smith 582ed381522SMike Smith SYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL) 583e51b0386SMike Smith 584e51b0386SMike Smith #endif /* NPPI */ 585