ppi.c revision 55977
1/*-
2 * Copyright (c) 1997, 1998, 1999 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 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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 * $FreeBSD: head/sys/dev/ppbus/ppi.c 55977 2000-01-14 15:54:45Z peter $
27 *
28 */
29#include "ppi.h"
30
31#if NPPI > 0
32
33#include "opt_ppb_1284.h"
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/module.h>
38#include <sys/bus.h>
39#include <sys/conf.h>
40#include <sys/kernel.h>
41#include <sys/uio.h>
42#include <sys/fcntl.h>
43
44#include <machine/clock.h>
45#include <machine/bus.h>
46#include <machine/resource.h>
47#include <sys/rman.h>
48
49#include <dev/ppbus/ppbconf.h>
50#include <dev/ppbus/ppb_msq.h>
51
52#ifdef PERIPH_1284
53#include <dev/ppbus/ppb_1284.h>
54#endif
55
56#include <dev/ppbus/ppi.h>
57
58#include "ppbus_if.h"
59
60#include <dev/ppbus/ppbio.h>
61
62#define BUFSIZE		512
63
64struct ppi_data {
65
66    int		ppi_unit;
67    int		ppi_flags;
68#define HAVE_PPBUS	(1<<0)
69#define HAD_PPBUS	(1<<1)
70
71    int		ppi_count;
72    int		ppi_mode;			/* IEEE1284 mode */
73    char	ppi_buffer[BUFSIZE];
74
75    struct resource *intr_resource;	/* interrupt resource */
76    void *intr_cookie;			/* interrupt registration cookie */
77};
78
79#define DEVTOSOFTC(dev) \
80	((struct ppi_data *)device_get_softc(dev))
81#define UNITOSOFTC(unit) \
82	((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit)))
83#define UNITODEVICE(unit) \
84	(devclass_get_device(ppi_devclass, (unit)))
85
86static int ppi_probe(device_t);
87static int ppi_attach(device_t);
88static void ppiintr(void *arg);
89
90static devclass_t ppi_devclass;
91
92static device_method_t ppi_methods[] = {
93	/* device interface */
94	DEVMETHOD(device_probe,		ppi_probe),
95	DEVMETHOD(device_attach,	ppi_attach),
96
97	{ 0, 0 }
98};
99
100static driver_t ppi_driver = {
101	"ppi",
102	ppi_methods,
103	sizeof(struct ppi_data),
104};
105
106static	d_open_t	ppiopen;
107static	d_close_t	ppiclose;
108static	d_ioctl_t	ppiioctl;
109static	d_write_t	ppiwrite;
110static	d_read_t	ppiread;
111
112#define CDEV_MAJOR 82
113static struct cdevsw ppi_cdevsw = {
114	/* open */	ppiopen,
115	/* close */	ppiclose,
116	/* read */	ppiread,
117	/* write */	ppiwrite,
118	/* ioctl */	ppiioctl,
119	/* poll */	nopoll,
120	/* mmap */	nommap,
121	/* strategy */	nostrategy,
122	/* name */	"ppi",
123	/* maj */	CDEV_MAJOR,
124	/* dump */	nodump,
125	/* psize */	nopsize,
126	/* flags */	0,
127	/* bmaj */	-1
128};
129
130#ifdef PERIPH_1284
131
132static void
133ppi_enable_intr(device_t ppidev)
134{
135	char r;
136	device_t ppbus = device_get_parent(ppidev);
137
138	r = ppb_rctr(ppbus);
139	ppb_wctr(ppbus, r | IRQENABLE);
140
141	return;
142}
143
144static void
145ppi_disable_intr(device_t ppidev)
146{
147	char r;
148        device_t ppbus = device_get_parent(ppidev);
149
150	r = ppb_rctr(ppbus);
151	ppb_wctr(ppbus, r & ~IRQENABLE);
152
153	return;
154}
155
156#endif /* PERIPH_1284 */
157
158/*
159 * ppi_probe()
160 */
161static int
162ppi_probe(device_t dev)
163{
164	struct ppi_data *ppi;
165	static int once;
166
167	/* probe is always ok */
168	device_set_desc(dev, "Parallel I/O");
169
170	if (!once++)
171		cdevsw_add(&ppi_cdevsw);
172
173	ppi = DEVTOSOFTC(dev);
174	bzero(ppi, sizeof(struct ppi_data));
175
176	return (0);
177}
178
179/*
180 * ppi_attach()
181 */
182static int
183ppi_attach(device_t dev)
184{
185	uintptr_t irq;
186	int zero = 0;
187	struct ppi_data *ppi = DEVTOSOFTC(dev);
188
189	/* retrive the irq */
190	BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq);
191
192	/* declare our interrupt handler */
193	ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
194						&zero, irq, irq, 1, RF_ACTIVE);
195
196	make_dev(&ppi_cdevsw, device_get_unit(dev),	/* XXX cleanup */
197		 UID_ROOT, GID_WHEEL,
198		 0600, "ppi%d", device_get_unit(dev));
199
200	return (0);
201}
202
203/*
204 * Cable
205 * -----
206 *
207 * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks:
208 *
209 * nStrobe   <-> nAck		1  <-> 10
210 * nAutofd   <-> Busy		11 <-> 14
211 * nSelectin <-> Select		17 <-> 13
212 * nInit     <-> nFault		15 <-> 16
213 *
214 */
215static void
216ppiintr(void *arg)
217{
218#ifdef PERIPH_1284
219	device_t ppidev = (device_t)arg;
220        device_t ppbus = device_get_parent(ppidev);
221	struct ppi_data *ppi = DEVTOSOFTC(ppidev);
222
223	ppi_disable_intr(ppidev);
224
225	switch (ppb_1284_get_state(ppbus)) {
226
227	/* accept IEEE1284 negociation then wakeup an waiting process to
228	 * continue negociation at process level */
229	case PPB_FORWARD_IDLE:
230		/* Event 1 */
231		if ((ppb_rstr(ppbus) & (SELECT | nBUSY)) ==
232							(SELECT | nBUSY)) {
233			/* IEEE1284 negociation */
234#ifdef DEBUG_1284
235			printf("N");
236#endif
237
238			/* Event 2 - prepare for reading the ext. value */
239			ppb_wctr(ppbus, (PCD | STROBE | nINIT) & ~SELECTIN);
240
241			ppb_1284_set_state(ppbus, PPB_NEGOCIATION);
242
243		} else {
244#ifdef DEBUG_1284
245			printf("0x%x", ppb_rstr(ppbus));
246#endif
247			ppb_peripheral_terminate(ppbus, PPB_DONTWAIT);
248			break;
249		}
250
251		/* wake up any process waiting for negociation from
252		 * remote master host */
253
254		/* XXX should set a variable to warn the process about
255		 * the interrupt */
256
257		wakeup(ppi);
258		break;
259	default:
260#ifdef DEBUG_1284
261		printf("?%d", ppb_1284_get_state(ppbus));
262#endif
263		ppb_1284_set_state(ppbus, PPB_FORWARD_IDLE);
264		ppb_set_mode(ppbus, PPB_COMPATIBLE);
265		break;
266	}
267
268	ppi_enable_intr(ppidev);
269#endif /* PERIPH_1284 */
270
271	return;
272}
273
274static int
275ppiopen(dev_t dev, int flags, int fmt, struct proc *p)
276{
277	u_int unit = minor(dev);
278	struct ppi_data *ppi = UNITOSOFTC(unit);
279	device_t ppidev = UNITODEVICE(unit);
280        device_t ppbus = device_get_parent(ppidev);
281	int res;
282
283	if (!ppi)
284		return (ENXIO);
285
286	if (!(ppi->ppi_flags & HAVE_PPBUS)) {
287		if ((res = ppb_request_bus(ppbus, ppidev,
288			(flags & O_NONBLOCK) ? PPB_DONTWAIT :
289						(PPB_WAIT | PPB_INTR))))
290			return (res);
291
292		ppi->ppi_flags |= HAVE_PPBUS;
293
294		/* register our interrupt handler */
295		BUS_SETUP_INTR(device_get_parent(ppidev), ppidev, ppi->intr_resource,
296			       INTR_TYPE_TTY, ppiintr, dev, &ppi->intr_cookie);
297	}
298	ppi->ppi_count += 1;
299
300	return (0);
301}
302
303static int
304ppiclose(dev_t dev, int flags, int fmt, struct proc *p)
305{
306	u_int unit = minor(dev);
307	struct ppi_data *ppi = UNITOSOFTC(unit);
308	device_t ppidev = UNITODEVICE(unit);
309        device_t ppbus = device_get_parent(ppidev);
310
311	ppi->ppi_count --;
312	if (!ppi->ppi_count) {
313
314#ifdef PERIPH_1284
315		switch (ppb_1284_get_state(ppbus)) {
316		case PPB_PERIPHERAL_IDLE:
317			ppb_peripheral_terminate(ppbus, 0);
318			break;
319		case PPB_REVERSE_IDLE:
320		case PPB_EPP_IDLE:
321		case PPB_ECP_FORWARD_IDLE:
322		default:
323			ppb_1284_terminate(ppbus);
324			break;
325		}
326#endif /* PERIPH_1284 */
327
328		/* unregistration of interrupt forced by release */
329		ppb_release_bus(ppbus, ppidev);
330
331		ppi->ppi_flags &= ~HAVE_PPBUS;
332	}
333
334	return (0);
335}
336
337/*
338 * ppiread()
339 *
340 * IEEE1284 compliant read.
341 *
342 * First, try negociation to BYTE then NIBBLE mode
343 * If no data is available, wait for it otherwise transfer as much as possible
344 */
345static int
346ppiread(dev_t dev, struct uio *uio, int ioflag)
347{
348#ifdef PERIPH_1284
349	u_int unit = minor(dev);
350	struct ppi_data *ppi = UNITOSOFTC(unit);
351	device_t ppidev = UNITODEVICE(unit);
352        device_t ppbus = device_get_parent(ppidev);
353	int len, error = 0;
354
355	switch (ppb_1284_get_state(ppbus)) {
356	case PPB_PERIPHERAL_IDLE:
357		ppb_peripheral_terminate(ppbus, 0);
358		/* fall throught */
359
360	case PPB_FORWARD_IDLE:
361		/* if can't negociate NIBBLE mode then try BYTE mode,
362		 * the peripheral may be a computer
363		 */
364		if ((ppb_1284_negociate(ppbus,
365			ppi->ppi_mode = PPB_NIBBLE, 0))) {
366
367			/* XXX Wait 2 seconds to let the remote host some
368			 * time to terminate its interrupt
369			 */
370			tsleep(ppi, PPBPRI, "ppiread", 2*hz);
371
372			if ((error = ppb_1284_negociate(ppbus,
373				ppi->ppi_mode = PPB_BYTE, 0)))
374				return (error);
375		}
376		break;
377
378	case PPB_REVERSE_IDLE:
379	case PPB_EPP_IDLE:
380	case PPB_ECP_FORWARD_IDLE:
381	default:
382		break;
383	}
384
385#ifdef DEBUG_1284
386	printf("N");
387#endif
388	/* read data */
389	len = 0;
390	while (uio->uio_resid) {
391		if ((error = ppb_1284_read(ppbus, ppi->ppi_mode,
392			ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid),
393			&len))) {
394			goto error;
395		}
396
397		if (!len)
398			goto error;		/* no more data */
399
400#ifdef DEBUG_1284
401		printf("d");
402#endif
403		if ((error = uiomove(ppi->ppi_buffer, len, uio)))
404			goto error;
405	}
406
407error:
408
409#else /* PERIPH_1284 */
410	int error = ENODEV;
411#endif
412
413	return (error);
414}
415
416/*
417 * ppiwrite()
418 *
419 * IEEE1284 compliant write
420 *
421 * Actually, this is the peripheral side of a remote IEEE1284 read
422 *
423 * The first part of the negociation (IEEE1284 device detection) is
424 * done at interrupt level, then the remaining is done by the writing
425 * process
426 *
427 * Once negociation done, transfer data
428 */
429static int
430ppiwrite(dev_t dev, struct uio *uio, int ioflag)
431{
432#ifdef PERIPH_1284
433	u_int unit = minor(dev);
434	struct ppi_data *ppi = UNITOSOFTC(unit);
435	device_t ppidev = UNITODEVICE(unit);
436        device_t ppbus = device_get_parent(ppidev);
437	int len, error = 0, sent;
438
439#if 0
440	int ret;
441
442	#define ADDRESS		MS_PARAM(0, 0, MS_TYP_PTR)
443	#define LENGTH		MS_PARAM(0, 1, MS_TYP_INT)
444
445	struct ppb_microseq msq[] = {
446		  { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } },
447		  MS_RET(0)
448	};
449
450	/* negociate ECP mode */
451	if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) {
452		printf("ppiwrite: ECP negociation failed\n");
453	}
454
455	while (!error && (len = min(uio->uio_resid, BUFSIZE))) {
456		uiomove(ppi->ppi_buffer, len, uio);
457
458		ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len);
459
460		error = ppb_MS_microseq(ppbus, msq, &ret);
461	}
462#endif
463
464	/* we have to be peripheral to be able to send data, so
465	 * wait for the appropriate state
466	 */
467 	if (ppb_1284_get_state(ppbus) < PPB_PERIPHERAL_NEGOCIATION)
468		ppb_1284_terminate(ppbus);
469
470 	while (ppb_1284_get_state(ppbus) != PPB_PERIPHERAL_IDLE) {
471		/* XXX should check a variable before sleeping */
472#ifdef DEBUG_1284
473		printf("s");
474#endif
475
476		ppi_enable_intr(ppidev);
477
478		/* sleep until IEEE1284 negociation starts */
479		error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0);
480
481		switch (error) {
482		case 0:
483			/* negociate peripheral side with BYTE mode */
484			ppb_peripheral_negociate(ppbus, PPB_BYTE, 0);
485			break;
486		case EWOULDBLOCK:
487			break;
488		default:
489			goto error;
490		}
491	}
492#ifdef DEBUG_1284
493	printf("N");
494#endif
495
496	/* negociation done, write bytes to master host */
497	while ((len = min(uio->uio_resid, BUFSIZE)) != 0) {
498		uiomove(ppi->ppi_buffer, len, uio);
499		if ((error = byte_peripheral_write(ppbus,
500						ppi->ppi_buffer, len, &sent)))
501			goto error;
502#ifdef DEBUG_1284
503		printf("d");
504#endif
505	}
506
507error:
508
509#else /* PERIPH_1284 */
510	int error = ENODEV;
511#endif
512
513	return (error);
514}
515
516static int
517ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
518{
519	u_int unit = minor(dev);
520	device_t ppidev = UNITODEVICE(unit);
521        device_t ppbus = device_get_parent(ppidev);
522	int error = 0;
523	u_int8_t *val = (u_int8_t *)data;
524
525	switch (cmd) {
526
527	case PPIGDATA:			/* get data register */
528		*val = ppb_rdtr(ppbus);
529		break;
530	case PPIGSTATUS:		/* get status bits */
531		*val = ppb_rstr(ppbus);
532		break;
533	case PPIGCTRL:			/* get control bits */
534		*val = ppb_rctr(ppbus);
535		break;
536	case PPIGEPPD:			/* get EPP data bits */
537		*val = ppb_repp_D(ppbus);
538		break;
539	case PPIGECR:			/* get ECP bits */
540		*val = ppb_recr(ppbus);
541		break;
542	case PPIGFIFO:			/* read FIFO */
543		*val = ppb_rfifo(ppbus);
544		break;
545	case PPISDATA:			/* set data register */
546		ppb_wdtr(ppbus, *val);
547		break;
548	case PPISSTATUS:		/* set status bits */
549		ppb_wstr(ppbus, *val);
550		break;
551	case PPISCTRL:			/* set control bits */
552		ppb_wctr(ppbus, *val);
553		break;
554	case PPISEPPD:			/* set EPP data bits */
555		ppb_wepp_D(ppbus, *val);
556		break;
557	case PPISECR:			/* set ECP bits */
558		ppb_wecr(ppbus, *val);
559		break;
560	case PPISFIFO:			/* write FIFO */
561		ppb_wfifo(ppbus, *val);
562		break;
563	case PPIGEPPA:			/* get EPP address bits */
564		*val = ppb_repp_A(ppbus);
565		break;
566	case PPISEPPA:			/* set EPP address bits */
567		ppb_wepp_A(ppbus, *val);
568		break;
569	default:
570		error = ENOTTY;
571		break;
572	}
573
574	return (error);
575}
576
577DRIVER_MODULE(ppi, ppbus, ppi_driver, ppi_devclass, 0, 0);
578
579#endif /* NPPI */
580