ppi.c (f1d19042b082d95f07a0027e596ba2405aa8a9a5) | ppi.c (bc35c17446fab005a7e11b67b9004736f1c8498b) |
---|---|
1/*- 2 * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $Id: ppi.c,v 1.7 1998/06/07 17:09:49 dfr Exp $ | 26 * $Id: ppi.c,v 1.8 1998/12/07 21:58:16 archie Exp $ |
27 * 28 */ 29#include "ppi.h" 30 31#if NPPI > 0 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/conf.h> 36#include <sys/kernel.h> | 27 * 28 */ 29#include "ppi.h" 30 31#if NPPI > 0 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/conf.h> 36#include <sys/kernel.h> |
37#include <sys/uio.h> |
|
37#include <sys/malloc.h> 38#include <sys/fcntl.h> 39 | 38#include <sys/malloc.h> 39#include <sys/fcntl.h> 40 |
41#include <machine/clock.h> 42 |
|
40#include <dev/ppbus/ppbconf.h> | 43#include <dev/ppbus/ppbconf.h> |
44#include <dev/ppbus/ppb_msq.h> 45 46#include "opt_ppb_1284.h" 47 48#ifdef PERIPH_1284 49#include <dev/ppbus/ppb_1284.h> 50#endif 51 |
|
41#include <dev/ppbus/ppi.h> 42 | 52#include <dev/ppbus/ppi.h> 53 |
54#define BUFSIZE 512 |
|
43 44struct ppi_data { 45 46 int ppi_unit; 47 int ppi_flags; 48#define HAVE_PPBUS (1<<0) | 55 56struct ppi_data { 57 58 int ppi_unit; 59 int ppi_flags; 60#define HAVE_PPBUS (1<<0) |
61#define HAD_PPBUS (1<<1) |
|
49 | 62 |
63 int ppi_count; 64 int ppi_mode; /* IEEE1284 mode */ 65 char ppi_buffer[BUFSIZE]; 66 |
|
50 struct ppb_device ppi_dev; 51}; 52 53#define MAXPPI 8 /* XXX not much better! */ 54static int nppi = 0; 55static struct ppi_data *ppidata[MAXPPI]; 56 57/* --- 7 unchanged lines hidden (view full) --- 65static struct ppb_driver ppidriver = { 66 ppiprobe, ppiattach, "ppi" 67}; 68DATA_SET(ppbdriver_set, ppidriver); 69 70static d_open_t ppiopen; 71static d_close_t ppiclose; 72static d_ioctl_t ppiioctl; | 67 struct ppb_device ppi_dev; 68}; 69 70#define MAXPPI 8 /* XXX not much better! */ 71static int nppi = 0; 72static struct ppi_data *ppidata[MAXPPI]; 73 74/* --- 7 unchanged lines hidden (view full) --- 82static struct ppb_driver ppidriver = { 83 ppiprobe, ppiattach, "ppi" 84}; 85DATA_SET(ppbdriver_set, ppidriver); 86 87static d_open_t ppiopen; 88static d_close_t ppiclose; 89static d_ioctl_t ppiioctl; |
90static d_write_t ppiwrite; 91static d_read_t ppiread; |
|
73 74#define CDEV_MAJOR 82 75static struct cdevsw ppi_cdevsw = | 92 93#define CDEV_MAJOR 82 94static struct cdevsw ppi_cdevsw = |
76 { ppiopen, ppiclose, noread, nowrite, /* 82 */ | 95 { ppiopen, ppiclose, ppiread, ppiwrite, /* 82 */ |
77 ppiioctl, nullstop, nullreset, nodevtotty, 78 seltrue, nommap, nostrat, "ppi", NULL, -1 }; 79 | 96 ppiioctl, nullstop, nullreset, nodevtotty, 97 seltrue, nommap, nostrat, "ppi", NULL, -1 }; 98 |
99#ifdef PERIPH_1284 100 101static void 102ppi_enable_intr(struct ppi_data *ppi) 103{ 104 char r; 105 106 r = ppb_rctr(&ppi->ppi_dev); 107 ppb_wctr(&ppi->ppi_dev, r | IRQENABLE); 108 109 return; 110} 111 112static void 113ppi_disable_intr(struct ppi_data *ppi) 114{ 115 char r; 116 117 r = ppb_rctr(&ppi->ppi_dev); 118 ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE); 119 120 return; 121} 122 123#endif /* PERIPH_1284 */ 124 |
|
80/* 81 * ppiprobe() 82 */ 83static struct ppb_device * 84ppiprobe(struct ppb_data *ppb) 85{ 86 struct ppi_data *ppi; 87 --- 32 unchanged lines hidden (view full) --- 120 * Report ourselves 121 */ 122 printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 123 dev->id_unit, dev->ppb->ppb_link->adapter_unit); 124 125 return (1); 126} 127 | 125/* 126 * ppiprobe() 127 */ 128static struct ppb_device * 129ppiprobe(struct ppb_data *ppb) 130{ 131 struct ppi_data *ppi; 132 --- 32 unchanged lines hidden (view full) --- 165 * Report ourselves 166 */ 167 printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 168 dev->id_unit, dev->ppb->ppb_link->adapter_unit); 169 170 return (1); 171} 172 |
173/* 174 * Cable 175 * ----- 176 * 177 * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: 178 * 179 * nStrobe <-> nAck 1 <-> 10 180 * nAutofd <-> Busy 11 <-> 14 181 * nSelectin <-> Select 17 <-> 13 182 * nInit <-> nFault 15 <-> 16 183 * 184 */ |
|
128static void 129ppiintr(int unit) 130{ | 185static void 186ppiintr(int unit) 187{ |
188#ifdef PERIPH_1284 189 struct ppi_data *ppi = ppidata[unit]; 190 191 ppi_disable_intr(ppi); 192 193 switch (ppi->ppi_dev.ppb->state) { 194 195 /* accept IEEE1284 negociation then wakeup an waiting process to 196 * continue negociation at process level */ 197 case PPB_FORWARD_IDLE: 198 /* Event 1 */ 199 if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) == 200 (SELECT | nBUSY)) { 201 /* IEEE1284 negociation */ 202#ifdef DEBUG_1284 203 printf("N"); 204#endif 205 206 /* Event 2 - prepare for reading the ext. value */ 207 ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN); 208 209 ppi->ppi_dev.ppb->state = PPB_NEGOCIATION; 210 211 } else { 212#ifdef DEBUG_1284 213 printf("0x%x", ppb_rstr(&ppi->ppi_dev)); 214#endif 215 ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT); 216 break; 217 } 218 219 /* wake up any process waiting for negociation from 220 * remote master host */ 221 222 /* XXX should set a variable to warn the process about 223 * the interrupt */ 224 225 wakeup(ppi); 226 break; 227 default: 228#ifdef DEBUG_1284 229 printf("?%d", ppi->ppi_dev.ppb->state); 230#endif 231 ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE; 232 ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE); 233 break; 234 } 235 236 ppi_enable_intr(ppi); 237#endif /* PERIPH_1284 */ 238 |
|
131 return; 132} 133 134static int 135ppiopen(dev_t dev, int flags, int fmt, struct proc *p) 136{ 137 u_int unit = minor(dev); 138 struct ppi_data *ppi = ppidata[unit]; 139 int res; 140 141 if (unit >= nppi) 142 return (ENXIO); 143 | 239 return; 240} 241 242static int 243ppiopen(dev_t dev, int flags, int fmt, struct proc *p) 244{ 245 u_int unit = minor(dev); 246 struct ppi_data *ppi = ppidata[unit]; 247 int res; 248 249 if (unit >= nppi) 250 return (ENXIO); 251 |
144 if (!(ppi->ppi_flags & HAVE_PPBUS)) 145 if ((res = ppb_request_bus(&ppi->ppi_dev, (flags & O_NONBLOCK) ? PPB_DONTWAIT : (PPB_WAIT | PPB_INTR)))) | 252 if (!(ppi->ppi_flags & HAVE_PPBUS)) { 253 if ((res = ppb_request_bus(&ppi->ppi_dev, 254 (flags & O_NONBLOCK) ? PPB_DONTWAIT : 255 (PPB_WAIT | PPB_INTR)))) |
146 return (res); 147 | 256 return (res); 257 |
148 ppi->ppi_flags |= HAVE_PPBUS; | 258 ppi->ppi_flags |= HAVE_PPBUS; 259 } 260 ppi->ppi_count += 1; 261 |
149 return (0); 150} 151 152static int 153ppiclose(dev_t dev, int flags, int fmt, struct proc *p) 154{ 155 u_int unit = minor(dev); 156 struct ppi_data *ppi = ppidata[unit]; 157 | 262 return (0); 263} 264 265static int 266ppiclose(dev_t dev, int flags, int fmt, struct proc *p) 267{ 268 u_int unit = minor(dev); 269 struct ppi_data *ppi = ppidata[unit]; 270 |
158 if (ppi->ppi_flags & HAVE_PPBUS) | 271 ppi->ppi_count --; 272 if (!ppi->ppi_count) { 273 274#ifdef PERIPH_1284 275 switch (ppi->ppi_dev.ppb->state) { 276 case PPB_PERIPHERAL_IDLE: 277 ppb_peripheral_terminate(&ppi->ppi_dev, 0); 278 break; 279 case PPB_REVERSE_IDLE: 280 case PPB_EPP_IDLE: 281 case PPB_ECP_FORWARD_IDLE: 282 default: 283 ppb_1284_terminate(&ppi->ppi_dev); 284 break; 285 } 286#endif /* PERIPH_1284 */ 287 |
159 ppb_release_bus(&ppi->ppi_dev); | 288 ppb_release_bus(&ppi->ppi_dev); |
160 ppi->ppi_flags &= ~HAVE_PPBUS; | 289 ppi->ppi_flags &= ~HAVE_PPBUS; 290 } 291 |
161 return (0); 162} 163 | 292 return (0); 293} 294 |
295/* 296 * ppiread() 297 * 298 * IEEE1284 compliant read. 299 * 300 * First, try negociation to BYTE then NIBBLE mode 301 * If no data is available, wait for it otherwise transfer as much as possible 302 */ |
|
164static int | 303static int |
304ppiread(dev_t dev, struct uio *uio, int ioflag) 305{ 306#ifdef PERIPH_1284 307 u_int unit = minor(dev); 308 struct ppi_data *ppi = ppidata[unit]; 309 int len, error = 0; 310 311 switch (ppi->ppi_dev.ppb->state) { 312 case PPB_PERIPHERAL_IDLE: 313 ppb_peripheral_terminate(&ppi->ppi_dev, 0); 314 /* fall throught */ 315 316 case PPB_FORWARD_IDLE: 317 /* if can't negociate NIBBLE mode then try BYTE mode, 318 * the peripheral may be a computer 319 */ 320 if ((ppb_1284_negociate(&ppi->ppi_dev, 321 ppi->ppi_mode = PPB_NIBBLE, 0))) { 322 323 /* XXX Wait 2 seconds to let the remote host some 324 * time to terminate its interrupt 325 */ 326 tsleep(ppi, PPBPRI, "ppiread", 2*hz); 327 328 if ((error = ppb_1284_negociate(&ppi->ppi_dev, 329 ppi->ppi_mode = PPB_BYTE, 0))) 330 return (error); 331 } 332 break; 333 334 case PPB_REVERSE_IDLE: 335 case PPB_EPP_IDLE: 336 case PPB_ECP_FORWARD_IDLE: 337 default: 338 break; 339 } 340 341#ifdef DEBUG_1284 342 printf("N"); 343#endif 344 /* read data */ 345 len = 0; 346 while (uio->uio_resid) { 347 if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode, 348 ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), 349 &len))) { 350 goto error; 351 } 352 353 if (!len) 354 goto error; /* no more data */ 355 356#ifdef DEBUG_1284 357 printf("d"); 358#endif 359 if ((error = uiomove(ppi->ppi_buffer, len, uio))) 360 goto error; 361 } 362 363error: 364 365#else /* PERIPH_1284 */ 366 int error = ENODEV; 367#endif 368 369 return (error); 370} 371 372/* 373 * ppiwrite() 374 * 375 * IEEE1284 compliant write 376 * 377 * Actually, this is the peripheral side of a remote IEEE1284 read 378 * 379 * The first part of the negociation (IEEE1284 device detection) is 380 * done at interrupt level, then the remaining is done by the writing 381 * process 382 * 383 * Once negociation done, transfer data 384 */ 385static int 386ppiwrite(dev_t dev, struct uio *uio, int ioflag) 387{ 388#ifdef PERIPH_1284 389 u_int unit = minor(dev); 390 struct ppi_data *ppi = ppidata[unit]; 391 struct ppb_data *ppb = ppi->ppi_dev.ppb; 392 int len, error = 0, sent; 393 394#if 0 395 int ret; 396 397 #define ADDRESS MS_PARAM(0, 0, MS_TYP_PTR) 398 #define LENGTH MS_PARAM(0, 1, MS_TYP_INT) 399 400 struct ppb_microseq msq[] = { 401 { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } }, 402 MS_RET(0) 403 }; 404 405 /* negociate ECP mode */ 406 if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) { 407 printf("ppiwrite: ECP negociation failed\n"); 408 } 409 410 while (!error && (len = min(uio->uio_resid, BUFSIZE))) { 411 uiomove(ppi->ppi_buffer, len, uio); 412 413 ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); 414 415 error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret); 416 } 417#endif 418 419 /* we have to be peripheral to be able to send data, so 420 * wait for the appropriate state 421 */ 422 if (ppb->state < PPB_PERIPHERAL_NEGOCIATION) 423 ppb_1284_terminate(&ppi->ppi_dev); 424 425 while (ppb->state != PPB_PERIPHERAL_IDLE) { 426 /* XXX should check a variable before sleeping */ 427#ifdef DEBUG_1284 428 printf("s"); 429#endif 430 431 ppi_enable_intr(ppi); 432 433 /* sleep until IEEE1284 negociation starts */ 434 error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); 435 436 switch (error) { 437 case 0: 438 /* negociate peripheral side with BYTE mode */ 439 ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0); 440 break; 441 case EWOULDBLOCK: 442 break; 443 default: 444 goto error; 445 } 446 } 447#ifdef DEBUG_1284 448 printf("N"); 449#endif 450 451 /* negociation done, write bytes to master host */ 452 while (len = min(uio->uio_resid, BUFSIZE)) { 453 uiomove(ppi->ppi_buffer, len, uio); 454 if ((error = byte_peripheral_write(&ppi->ppi_dev, 455 ppi->ppi_buffer, len, &sent))) 456 goto error; 457#ifdef DEBUG_1284 458 printf("d"); 459#endif 460 } 461 462error: 463 464#else /* PERIPH_1284 */ 465 int error = ENODEV; 466#endif 467 468 return (error); 469} 470 471static int |
|
165ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 166{ 167 u_int unit = minor(dev); 168 struct ppi_data *ppi = ppidata[unit]; 169 int error = 0; 170 u_int8_t *val = (u_int8_t *)data; 171 172 switch (cmd) { --- 30 unchanged lines hidden (view full) --- 203 ppb_wepp(&ppi->ppi_dev, *val); 204 break; 205 case PPISECR: /* set ECP bits */ 206 ppb_wecr(&ppi->ppi_dev, *val); 207 break; 208 case PPISFIFO: /* write FIFO */ 209 ppb_wfifo(&ppi->ppi_dev, *val); 210 break; | 472ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 473{ 474 u_int unit = minor(dev); 475 struct ppi_data *ppi = ppidata[unit]; 476 int error = 0; 477 u_int8_t *val = (u_int8_t *)data; 478 479 switch (cmd) { --- 30 unchanged lines hidden (view full) --- 510 ppb_wepp(&ppi->ppi_dev, *val); 511 break; 512 case PPISECR: /* set ECP bits */ 513 ppb_wecr(&ppi->ppi_dev, *val); 514 break; 515 case PPISFIFO: /* write FIFO */ 516 ppb_wfifo(&ppi->ppi_dev, *val); 517 break; |
211 | |
212 default: 213 error = ENOTTY; 214 break; 215 } 216 217 return (error); 218} 219 --- 59 unchanged lines hidden --- | 518 default: 519 error = ENOTTY; 520 break; 521 } 522 523 return (error); 524} 525 --- 59 unchanged lines hidden --- |