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 * 262447bec8SPoul-Henning Kamp * $Id: ppi.c,v 1.14 1999/05/30 16:51:35 phk 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 944e2f199eSPoul-Henning Kamp static struct cdevsw ppi_cdevsw = { 954e2f199eSPoul-Henning Kamp /* open */ ppiopen, 964e2f199eSPoul-Henning Kamp /* close */ ppiclose, 974e2f199eSPoul-Henning Kamp /* read */ ppiread, 984e2f199eSPoul-Henning Kamp /* write */ ppiwrite, 994e2f199eSPoul-Henning Kamp /* ioctl */ ppiioctl, 1004e2f199eSPoul-Henning Kamp /* stop */ nostop, 1014e2f199eSPoul-Henning Kamp /* reset */ noreset, 1024e2f199eSPoul-Henning Kamp /* devtotty */ nodevtotty, 1034e2f199eSPoul-Henning Kamp /* poll */ nopoll, 1044e2f199eSPoul-Henning Kamp /* mmap */ nommap, 1054e2f199eSPoul-Henning Kamp /* strategy */ nostrategy, 1064e2f199eSPoul-Henning Kamp /* name */ "ppi", 1074e2f199eSPoul-Henning Kamp /* parms */ noparms, 1084e2f199eSPoul-Henning Kamp /* maj */ CDEV_MAJOR, 1094e2f199eSPoul-Henning Kamp /* dump */ nodump, 1104e2f199eSPoul-Henning Kamp /* psize */ nopsize, 1114e2f199eSPoul-Henning Kamp /* flags */ 0, 1124e2f199eSPoul-Henning Kamp /* maxio */ 0, 1134e2f199eSPoul-Henning Kamp /* bmaj */ -1 1144e2f199eSPoul-Henning Kamp }; 115ed381522SMike Smith 116bc35c174SNicolas Souchu #ifdef PERIPH_1284 117bc35c174SNicolas Souchu 118bc35c174SNicolas Souchu static void 119bc35c174SNicolas Souchu ppi_enable_intr(struct ppi_data *ppi) 120bc35c174SNicolas Souchu { 121bc35c174SNicolas Souchu char r; 122bc35c174SNicolas Souchu 123bc35c174SNicolas Souchu r = ppb_rctr(&ppi->ppi_dev); 124bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, r | IRQENABLE); 125bc35c174SNicolas Souchu 126bc35c174SNicolas Souchu return; 127bc35c174SNicolas Souchu } 128bc35c174SNicolas Souchu 129bc35c174SNicolas Souchu static void 130bc35c174SNicolas Souchu ppi_disable_intr(struct ppi_data *ppi) 131bc35c174SNicolas Souchu { 132bc35c174SNicolas Souchu char r; 133bc35c174SNicolas Souchu 134bc35c174SNicolas Souchu r = ppb_rctr(&ppi->ppi_dev); 135bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE); 136bc35c174SNicolas Souchu 137bc35c174SNicolas Souchu return; 138bc35c174SNicolas Souchu } 139bc35c174SNicolas Souchu 140bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 141bc35c174SNicolas Souchu 142ed381522SMike Smith /* 143ed381522SMike Smith * ppiprobe() 144ed381522SMike Smith */ 145ed381522SMike Smith static struct ppb_device * 146ed381522SMike Smith ppiprobe(struct ppb_data *ppb) 147ed381522SMike Smith { 148ed381522SMike Smith struct ppi_data *ppi; 1492447bec8SPoul-Henning Kamp static int once; 1502447bec8SPoul-Henning Kamp 1512447bec8SPoul-Henning Kamp if (!once++) 1522447bec8SPoul-Henning Kamp cdevsw_add(&ppi_cdevsw); 153ed381522SMike Smith 154ed381522SMike Smith ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data), 155ed381522SMike Smith M_TEMP, M_NOWAIT); 156ed381522SMike Smith if (!ppi) { 157ed381522SMike Smith printf("ppi: cannot malloc!\n"); 158ed381522SMike Smith return 0; 159ed381522SMike Smith } 160ed381522SMike Smith bzero(ppi, sizeof(struct ppi_data)); 161ed381522SMike Smith 162ed381522SMike Smith ppidata[nppi] = ppi; 163ed381522SMike Smith 164ed381522SMike Smith /* 165ed381522SMike Smith * ppi dependent initialisation. 166ed381522SMike Smith */ 167ed381522SMike Smith ppi->ppi_unit = nppi; 168ed381522SMike Smith 169ed381522SMike Smith /* 170ed381522SMike Smith * ppbus dependent initialisation. 171ed381522SMike Smith */ 172ed381522SMike Smith ppi->ppi_dev.id_unit = ppi->ppi_unit; 173ed381522SMike Smith ppi->ppi_dev.ppb = ppb; 174ed381522SMike Smith ppi->ppi_dev.intr = ppiintr; 175ed381522SMike Smith 176ed381522SMike Smith /* Ok, go to next device on next probe */ 177ed381522SMike Smith nppi ++; 178ed381522SMike Smith 179ed381522SMike Smith return &ppi->ppi_dev; 180ed381522SMike Smith } 181ed381522SMike Smith 182ed381522SMike Smith static int 183ed381522SMike Smith ppiattach(struct ppb_device *dev) 184ed381522SMike Smith { 185ed381522SMike Smith /* 186ed381522SMike Smith * Report ourselves 187ed381522SMike Smith */ 188ed381522SMike Smith printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 189ed381522SMike Smith dev->id_unit, dev->ppb->ppb_link->adapter_unit); 190ed381522SMike Smith 191ed381522SMike Smith return (1); 192ed381522SMike Smith } 193ed381522SMike Smith 194bc35c174SNicolas Souchu /* 195bc35c174SNicolas Souchu * Cable 196bc35c174SNicolas Souchu * ----- 197bc35c174SNicolas Souchu * 198bc35c174SNicolas Souchu * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 199bc35c174SNicolas Souchu * 200bc35c174SNicolas Souchu * nStrobe <-> nAck 1 <-> 10 201bc35c174SNicolas Souchu * nAutofd <-> Busy 11 <-> 14 202bc35c174SNicolas Souchu * nSelectin <-> Select 17 <-> 13 203bc35c174SNicolas Souchu * nInit <-> nFault 15 <-> 16 204bc35c174SNicolas Souchu * 205bc35c174SNicolas Souchu */ 206ed381522SMike Smith static void 207ed381522SMike Smith ppiintr(int unit) 208ed381522SMike Smith { 209bc35c174SNicolas Souchu #ifdef PERIPH_1284 210bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 211bc35c174SNicolas Souchu 212bc35c174SNicolas Souchu ppi_disable_intr(ppi); 213bc35c174SNicolas Souchu 214bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 215bc35c174SNicolas Souchu 216bc35c174SNicolas Souchu /* accept IEEE1284 negociation then wakeup an waiting process to 217bc35c174SNicolas Souchu * continue negociation at process level */ 218bc35c174SNicolas Souchu case PPB_FORWARD_IDLE: 219bc35c174SNicolas Souchu /* Event 1 */ 220bc35c174SNicolas Souchu if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) == 221bc35c174SNicolas Souchu (SELECT | nBUSY)) { 222bc35c174SNicolas Souchu /* IEEE1284 negociation */ 223bc35c174SNicolas Souchu #ifdef DEBUG_1284 224bc35c174SNicolas Souchu printf("N"); 225bc35c174SNicolas Souchu #endif 226bc35c174SNicolas Souchu 227bc35c174SNicolas Souchu /* Event 2 - prepare for reading the ext. value */ 228bc35c174SNicolas Souchu ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN); 229bc35c174SNicolas Souchu 230bc35c174SNicolas Souchu ppi->ppi_dev.ppb->state = PPB_NEGOCIATION; 231bc35c174SNicolas Souchu 232bc35c174SNicolas Souchu } else { 233bc35c174SNicolas Souchu #ifdef DEBUG_1284 234bc35c174SNicolas Souchu printf("0x%x", ppb_rstr(&ppi->ppi_dev)); 235bc35c174SNicolas Souchu #endif 236bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT); 237bc35c174SNicolas Souchu break; 238bc35c174SNicolas Souchu } 239bc35c174SNicolas Souchu 240bc35c174SNicolas Souchu /* wake up any process waiting for negociation from 241bc35c174SNicolas Souchu * remote master host */ 242bc35c174SNicolas Souchu 243bc35c174SNicolas Souchu /* XXX should set a variable to warn the process about 244bc35c174SNicolas Souchu * the interrupt */ 245bc35c174SNicolas Souchu 246bc35c174SNicolas Souchu wakeup(ppi); 247bc35c174SNicolas Souchu break; 248bc35c174SNicolas Souchu default: 249bc35c174SNicolas Souchu #ifdef DEBUG_1284 250bc35c174SNicolas Souchu printf("?%d", ppi->ppi_dev.ppb->state); 251bc35c174SNicolas Souchu #endif 252bc35c174SNicolas Souchu ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE; 253bc35c174SNicolas Souchu ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE); 254bc35c174SNicolas Souchu break; 255bc35c174SNicolas Souchu } 256bc35c174SNicolas Souchu 257bc35c174SNicolas Souchu ppi_enable_intr(ppi); 258bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 259bc35c174SNicolas Souchu 260ed381522SMike Smith return; 261ed381522SMike Smith } 262ed381522SMike Smith 263ed381522SMike Smith static int 264ed381522SMike Smith ppiopen(dev_t dev, int flags, int fmt, struct proc *p) 265ed381522SMike Smith { 266e51b0386SMike Smith u_int unit = minor(dev); 2676f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 2686f34dba9SMike Smith int res; 269e51b0386SMike Smith 270e51b0386SMike Smith if (unit >= nppi) 271e51b0386SMike Smith return (ENXIO); 272e51b0386SMike Smith 273bc35c174SNicolas Souchu if (!(ppi->ppi_flags & HAVE_PPBUS)) { 274bc35c174SNicolas Souchu if ((res = ppb_request_bus(&ppi->ppi_dev, 275bc35c174SNicolas Souchu (flags & O_NONBLOCK) ? PPB_DONTWAIT : 276bc35c174SNicolas Souchu (PPB_WAIT | PPB_INTR)))) 2776f34dba9SMike Smith return (res); 278e51b0386SMike Smith 2796f34dba9SMike Smith ppi->ppi_flags |= HAVE_PPBUS; 280bc35c174SNicolas Souchu } 281bc35c174SNicolas Souchu ppi->ppi_count += 1; 282bc35c174SNicolas Souchu 2836f34dba9SMike Smith return (0); 284ed381522SMike Smith } 285ed381522SMike Smith 286ed381522SMike Smith static int 287ed381522SMike Smith ppiclose(dev_t dev, int flags, int fmt, struct proc *p) 288ed381522SMike Smith { 2896f34dba9SMike Smith u_int unit = minor(dev); 2906f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 2916f34dba9SMike Smith 292bc35c174SNicolas Souchu ppi->ppi_count --; 293bc35c174SNicolas Souchu if (!ppi->ppi_count) { 294bc35c174SNicolas Souchu 295bc35c174SNicolas Souchu #ifdef PERIPH_1284 296bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 297bc35c174SNicolas Souchu case PPB_PERIPHERAL_IDLE: 298bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, 0); 299bc35c174SNicolas Souchu break; 300bc35c174SNicolas Souchu case PPB_REVERSE_IDLE: 301bc35c174SNicolas Souchu case PPB_EPP_IDLE: 302bc35c174SNicolas Souchu case PPB_ECP_FORWARD_IDLE: 303bc35c174SNicolas Souchu default: 304bc35c174SNicolas Souchu ppb_1284_terminate(&ppi->ppi_dev); 305bc35c174SNicolas Souchu break; 306bc35c174SNicolas Souchu } 307bc35c174SNicolas Souchu #endif /* PERIPH_1284 */ 308bc35c174SNicolas Souchu 3096f34dba9SMike Smith ppb_release_bus(&ppi->ppi_dev); 3106f34dba9SMike Smith ppi->ppi_flags &= ~HAVE_PPBUS; 311bc35c174SNicolas Souchu } 312bc35c174SNicolas Souchu 3136f34dba9SMike Smith return (0); 314ed381522SMike Smith } 315ed381522SMike Smith 316bc35c174SNicolas Souchu /* 317bc35c174SNicolas Souchu * ppiread() 318bc35c174SNicolas Souchu * 319bc35c174SNicolas Souchu * IEEE1284 compliant read. 320bc35c174SNicolas Souchu * 321bc35c174SNicolas Souchu * First, try negociation to BYTE then NIBBLE mode 322bc35c174SNicolas Souchu * If no data is available, wait for it otherwise transfer as much as possible 323bc35c174SNicolas Souchu */ 324bc35c174SNicolas Souchu static int 325bc35c174SNicolas Souchu ppiread(dev_t dev, struct uio *uio, int ioflag) 326bc35c174SNicolas Souchu { 327bc35c174SNicolas Souchu #ifdef PERIPH_1284 328bc35c174SNicolas Souchu u_int unit = minor(dev); 329bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 330bc35c174SNicolas Souchu int len, error = 0; 331bc35c174SNicolas Souchu 332bc35c174SNicolas Souchu switch (ppi->ppi_dev.ppb->state) { 333bc35c174SNicolas Souchu case PPB_PERIPHERAL_IDLE: 334bc35c174SNicolas Souchu ppb_peripheral_terminate(&ppi->ppi_dev, 0); 335bc35c174SNicolas Souchu /* fall throught */ 336bc35c174SNicolas Souchu 337bc35c174SNicolas Souchu case PPB_FORWARD_IDLE: 338bc35c174SNicolas Souchu /* if can't negociate NIBBLE mode then try BYTE mode, 339bc35c174SNicolas Souchu * the peripheral may be a computer 340bc35c174SNicolas Souchu */ 341bc35c174SNicolas Souchu if ((ppb_1284_negociate(&ppi->ppi_dev, 342bc35c174SNicolas Souchu ppi->ppi_mode = PPB_NIBBLE, 0))) { 343bc35c174SNicolas Souchu 344bc35c174SNicolas Souchu /* XXX Wait 2 seconds to let the remote host some 345bc35c174SNicolas Souchu * time to terminate its interrupt 346bc35c174SNicolas Souchu */ 347bc35c174SNicolas Souchu tsleep(ppi, PPBPRI, "ppiread", 2*hz); 348bc35c174SNicolas Souchu 349bc35c174SNicolas Souchu if ((error = ppb_1284_negociate(&ppi->ppi_dev, 350bc35c174SNicolas Souchu ppi->ppi_mode = PPB_BYTE, 0))) 351bc35c174SNicolas Souchu return (error); 352bc35c174SNicolas Souchu } 353bc35c174SNicolas Souchu break; 354bc35c174SNicolas Souchu 355bc35c174SNicolas Souchu case PPB_REVERSE_IDLE: 356bc35c174SNicolas Souchu case PPB_EPP_IDLE: 357bc35c174SNicolas Souchu case PPB_ECP_FORWARD_IDLE: 358bc35c174SNicolas Souchu default: 359bc35c174SNicolas Souchu break; 360bc35c174SNicolas Souchu } 361bc35c174SNicolas Souchu 362bc35c174SNicolas Souchu #ifdef DEBUG_1284 363bc35c174SNicolas Souchu printf("N"); 364bc35c174SNicolas Souchu #endif 365bc35c174SNicolas Souchu /* read data */ 366bc35c174SNicolas Souchu len = 0; 367bc35c174SNicolas Souchu while (uio->uio_resid) { 368bc35c174SNicolas Souchu if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode, 369bc35c174SNicolas Souchu ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 370bc35c174SNicolas Souchu &len))) { 371bc35c174SNicolas Souchu goto error; 372bc35c174SNicolas Souchu } 373bc35c174SNicolas Souchu 374bc35c174SNicolas Souchu if (!len) 375bc35c174SNicolas Souchu goto error; /* no more data */ 376bc35c174SNicolas Souchu 377bc35c174SNicolas Souchu #ifdef DEBUG_1284 378bc35c174SNicolas Souchu printf("d"); 379bc35c174SNicolas Souchu #endif 380bc35c174SNicolas Souchu if ((error = uiomove(ppi->ppi_buffer, len, uio))) 381bc35c174SNicolas Souchu goto error; 382bc35c174SNicolas Souchu } 383bc35c174SNicolas Souchu 384bc35c174SNicolas Souchu error: 385bc35c174SNicolas Souchu 386bc35c174SNicolas Souchu #else /* PERIPH_1284 */ 387bc35c174SNicolas Souchu int error = ENODEV; 388bc35c174SNicolas Souchu #endif 389bc35c174SNicolas Souchu 390bc35c174SNicolas Souchu return (error); 391bc35c174SNicolas Souchu } 392bc35c174SNicolas Souchu 393bc35c174SNicolas Souchu /* 394bc35c174SNicolas Souchu * ppiwrite() 395bc35c174SNicolas Souchu * 396bc35c174SNicolas Souchu * IEEE1284 compliant write 397bc35c174SNicolas Souchu * 398bc35c174SNicolas Souchu * Actually, this is the peripheral side of a remote IEEE1284 read 399bc35c174SNicolas Souchu * 400bc35c174SNicolas Souchu * The first part of the negociation (IEEE1284 device detection) is 401bc35c174SNicolas Souchu * done at interrupt level, then the remaining is done by the writing 402bc35c174SNicolas Souchu * process 403bc35c174SNicolas Souchu * 404bc35c174SNicolas Souchu * Once negociation done, transfer data 405bc35c174SNicolas Souchu */ 406bc35c174SNicolas Souchu static int 407bc35c174SNicolas Souchu ppiwrite(dev_t dev, struct uio *uio, int ioflag) 408bc35c174SNicolas Souchu { 409bc35c174SNicolas Souchu #ifdef PERIPH_1284 410bc35c174SNicolas Souchu u_int unit = minor(dev); 411bc35c174SNicolas Souchu struct ppi_data *ppi = ppidata[unit]; 412bc35c174SNicolas Souchu struct ppb_data *ppb = ppi->ppi_dev.ppb; 413bc35c174SNicolas Souchu int len, error = 0, sent; 414bc35c174SNicolas Souchu 415bc35c174SNicolas Souchu #if 0 416bc35c174SNicolas Souchu int ret; 417bc35c174SNicolas Souchu 418bc35c174SNicolas Souchu #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 419bc35c174SNicolas Souchu #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 420bc35c174SNicolas Souchu 421bc35c174SNicolas Souchu struct ppb_microseq msq[] = { 422bc35c174SNicolas Souchu { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 423bc35c174SNicolas Souchu MS_RET(0) 424bc35c174SNicolas Souchu }; 425bc35c174SNicolas Souchu 426bc35c174SNicolas Souchu /* negociate ECP mode */ 427bc35c174SNicolas Souchu if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) { 428bc35c174SNicolas Souchu printf("ppiwrite: ECP negociation failed\n"); 429bc35c174SNicolas Souchu } 430bc35c174SNicolas Souchu 431bc35c174SNicolas Souchu while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 432bc35c174SNicolas Souchu uiomove(ppi->ppi_buffer, len, uio); 433bc35c174SNicolas Souchu 434bc35c174SNicolas Souchu ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 435bc35c174SNicolas Souchu 436bc35c174SNicolas Souchu error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret); 437bc35c174SNicolas Souchu } 438bc35c174SNicolas Souchu #endif 439bc35c174SNicolas Souchu 440bc35c174SNicolas Souchu /* we have to be peripheral to be able to send data, so 441bc35c174SNicolas Souchu * wait for the appropriate state 442bc35c174SNicolas Souchu */ 443bc35c174SNicolas Souchu if (ppb->state < PPB_PERIPHERAL_NEGOCIATION) 444bc35c174SNicolas Souchu ppb_1284_terminate(&ppi->ppi_dev); 445bc35c174SNicolas Souchu 446bc35c174SNicolas Souchu while (ppb->state != PPB_PERIPHERAL_IDLE) { 447bc35c174SNicolas Souchu /* XXX should check a variable before sleeping */ 448bc35c174SNicolas Souchu #ifdef DEBUG_1284 449bc35c174SNicolas Souchu printf("s"); 450bc35c174SNicolas Souchu #endif 451bc35c174SNicolas Souchu 452bc35c174SNicolas Souchu ppi_enable_intr(ppi); 453bc35c174SNicolas Souchu 454bc35c174SNicolas Souchu /* sleep until IEEE1284 negociation starts */ 455bc35c174SNicolas Souchu error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 456bc35c174SNicolas Souchu 457bc35c174SNicolas Souchu switch (error) { 458bc35c174SNicolas Souchu case 0: 459bc35c174SNicolas Souchu /* negociate peripheral side with BYTE mode */ 460bc35c174SNicolas Souchu ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0); 461bc35c174SNicolas Souchu break; 462bc35c174SNicolas Souchu case EWOULDBLOCK: 463bc35c174SNicolas Souchu break; 464bc35c174SNicolas Souchu default: 465bc35c174SNicolas Souchu goto error; 466bc35c174SNicolas Souchu } 467bc35c174SNicolas Souchu } 468bc35c174SNicolas Souchu #ifdef DEBUG_1284 469bc35c174SNicolas Souchu printf("N"); 470bc35c174SNicolas Souchu #endif 471bc35c174SNicolas Souchu 472bc35c174SNicolas Souchu /* negociation done, write bytes to master host */ 473d254af07SMatthew Dillon while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { 474bc35c174SNicolas Souchu uiomove(ppi->ppi_buffer, len, uio); 475bc35c174SNicolas Souchu if ((error = byte_peripheral_write(&ppi->ppi_dev, 476bc35c174SNicolas Souchu ppi->ppi_buffer, len, &sent))) 477bc35c174SNicolas Souchu goto error; 478bc35c174SNicolas Souchu #ifdef DEBUG_1284 479bc35c174SNicolas Souchu printf("d"); 480bc35c174SNicolas Souchu #endif 481bc35c174SNicolas Souchu } 482bc35c174SNicolas Souchu 483bc35c174SNicolas Souchu error: 484bc35c174SNicolas Souchu 485bc35c174SNicolas Souchu #else /* PERIPH_1284 */ 486bc35c174SNicolas Souchu int error = ENODEV; 487bc35c174SNicolas Souchu #endif 488bc35c174SNicolas Souchu 489bc35c174SNicolas Souchu return (error); 490bc35c174SNicolas Souchu } 491bc35c174SNicolas Souchu 492ed381522SMike Smith static int 493ecbb00a2SDoug Rabson ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 494ed381522SMike Smith { 4956f34dba9SMike Smith u_int unit = minor(dev); 4966f34dba9SMike Smith struct ppi_data *ppi = ppidata[unit]; 4976f34dba9SMike Smith int error = 0; 4986f34dba9SMike Smith u_int8_t *val = (u_int8_t *)data; 4996f34dba9SMike Smith 5006f34dba9SMike Smith switch (cmd) { 5016f34dba9SMike Smith 5026f34dba9SMike Smith case PPIGDATA: /* get data register */ 5036f34dba9SMike Smith *val = ppb_rdtr(&ppi->ppi_dev); 5046f34dba9SMike Smith break; 5056f34dba9SMike Smith case PPIGSTATUS: /* get status bits */ 5066f34dba9SMike Smith *val = ppb_rstr(&ppi->ppi_dev); 5076f34dba9SMike Smith break; 5086f34dba9SMike Smith case PPIGCTRL: /* get control bits */ 5096f34dba9SMike Smith *val = ppb_rctr(&ppi->ppi_dev); 5106f34dba9SMike Smith break; 51120240fa3SNicolas Souchu case PPIGEPPD: /* get EPP data bits */ 51220240fa3SNicolas Souchu *val = ppb_repp_D(&ppi->ppi_dev); 5136f34dba9SMike Smith break; 5146f34dba9SMike Smith case PPIGECR: /* get ECP bits */ 5156f34dba9SMike Smith *val = ppb_recr(&ppi->ppi_dev); 5166f34dba9SMike Smith break; 5176f34dba9SMike Smith case PPIGFIFO: /* read FIFO */ 5186f34dba9SMike Smith *val = ppb_rfifo(&ppi->ppi_dev); 5196f34dba9SMike Smith break; 5206f34dba9SMike Smith 5216f34dba9SMike Smith case PPISDATA: /* set data register */ 5226f34dba9SMike Smith ppb_wdtr(&ppi->ppi_dev, *val); 5236f34dba9SMike Smith break; 5246f34dba9SMike Smith case PPISSTATUS: /* set status bits */ 5256f34dba9SMike Smith ppb_wstr(&ppi->ppi_dev, *val); 5266f34dba9SMike Smith break; 5276f34dba9SMike Smith case PPISCTRL: /* set control bits */ 5286f34dba9SMike Smith ppb_wctr(&ppi->ppi_dev, *val); 5296f34dba9SMike Smith break; 53020240fa3SNicolas Souchu case PPISEPPD: /* set EPP data bits */ 53120240fa3SNicolas Souchu ppb_wepp_D(&ppi->ppi_dev, *val); 5326f34dba9SMike Smith break; 5336f34dba9SMike Smith case PPISECR: /* set ECP bits */ 5346f34dba9SMike Smith ppb_wecr(&ppi->ppi_dev, *val); 5356f34dba9SMike Smith break; 5366f34dba9SMike Smith case PPISFIFO: /* write FIFO */ 5376f34dba9SMike Smith ppb_wfifo(&ppi->ppi_dev, *val); 5386f34dba9SMike Smith break; 53920240fa3SNicolas Souchu 54020240fa3SNicolas Souchu case PPIGEPPA: /* get EPP address bits */ 54120240fa3SNicolas Souchu *val = ppb_repp_A(&ppi->ppi_dev); 54220240fa3SNicolas Souchu break; 54320240fa3SNicolas Souchu case PPISEPPA: /* set EPP address bits */ 54420240fa3SNicolas Souchu ppb_wepp_A(&ppi->ppi_dev, *val); 54520240fa3SNicolas Souchu break; 5466f34dba9SMike Smith default: 5476f34dba9SMike Smith error = ENOTTY; 5486f34dba9SMike Smith break; 5496f34dba9SMike Smith } 5506f34dba9SMike Smith 5516f34dba9SMike Smith return (error); 552ed381522SMike Smith } 553ed381522SMike Smith 554e51b0386SMike Smith #endif /* NPPI */ 555