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 ---