ppb_1284.c revision 67164
1157642Sps/*-
2265918Sdavidcs * Copyright (c) 1997 Nicolas Souchu
3157642Sps * All rights reserved.
4157642Sps *
5157642Sps * Redistribution and use in source and binary forms, with or without
6157642Sps * modification, are permitted provided that the following conditions
7157642Sps * are met:
8157642Sps * 1. Redistributions of source code must retain the above copyright
9157642Sps *    notice, this list of conditions and the following disclaimer.
10157642Sps * 2. Redistributions in binary form must reproduce the above copyright
11157642Sps *    notice, this list of conditions and the following disclaimer in the
12157642Sps *    documentation and/or other materials provided with the distribution.
13157642Sps *
14157642Sps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15157642Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16157642Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17157642Sps * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18157642Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19157642Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20157642Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21157642Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22157642Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23157642Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24157642Sps * SUCH DAMAGE.
25157642Sps *
26157642Sps * $FreeBSD: head/sys/dev/ppbus/ppb_1284.c 67164 2000-10-15 14:19:01Z phk $
27157642Sps *
28189325Sdavidch */
29189325Sdavidch
30157642Sps/*
31157642Sps * General purpose routines for the IEEE1284-1994 Standard
32157642Sps */
33157642Sps
34157642Sps#include "opt_ppb_1284.h"
35157642Sps
36157642Sps#include <sys/param.h>
37157642Sps#include <sys/systm.h>
38157642Sps#include <sys/bus.h>
39157642Sps
40157642Sps
41157642Sps#include <dev/ppbus/ppbconf.h>
42157642Sps#include <dev/ppbus/ppb_1284.h>
43169632Sdavidch
44169632Sdavidch#include "ppbus_if.h"
45157642Sps
46157642Sps#include <dev/ppbus/ppbio.h>
47157642Sps
48157642Sps#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
49157642Sps
50157642Sps/*
51157642Sps * do_1284_wait()
52157642Sps *
53157642Sps * Wait for the peripherial up to 40ms
54157642Sps */
55169632Sdavidchstatic int
56157642Spsdo_1284_wait(device_t bus, char mask, char status)
57169632Sdavidch{
58169632Sdavidch	return (ppb_poll_bus(bus, 4, mask, status, PPB_NOINTR | PPB_POLL));
59169632Sdavidch}
60170392Sdavidch
61157642Spsstatic int
62157642Spsdo_peripheral_wait(device_t bus, char mask, char status)
63157642Sps{
64157642Sps	return (ppb_poll_bus(bus, 100, mask, status, PPB_NOINTR | PPB_POLL));
65157642Sps}
66157642Sps
67157642Sps#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)
68157642Sps
69157642Sps/*
70157642Sps * ppb_1284_reset_error()
71157642Sps *
72157642Sps * Unconditionaly reset the error field
73157642Sps */
74157642Spsstatic int
75157642Spsppb_1284_reset_error(device_t bus, int state)
76157642Sps{
77157642Sps	struct ppb_data *ppb = DEVTOSOFTC(bus);
78157642Sps
79157642Sps	ppb->error = PPB_NO_ERROR;
80206268Sdavidch	ppb->state = state;
81206268Sdavidch
82206268Sdavidch	return (0);
83157642Sps}
84157642Sps
85157642Sps/*
86157642Sps * ppb_1284_get_state()
87157642Sps *
88157642Sps * Get IEEE1284 state
89157642Sps */
90157642Spsint
91178132Sdavidchppb_1284_get_state(device_t bus)
92178132Sdavidch{
93206268Sdavidch        return (DEVTOSOFTC(bus)->state);
94206268Sdavidch}
95206268Sdavidch
96206268Sdavidch/*
97206268Sdavidch * ppb_1284_set_state()
98206268Sdavidch *
99206268Sdavidch * Change IEEE1284 state if no error occured
100206268Sdavidch */
101206268Sdavidchint
102206268Sdavidchppb_1284_set_state(device_t bus, int state)
103206268Sdavidch{
104206268Sdavidch	struct ppb_data *ppb = DEVTOSOFTC(bus);
105206268Sdavidch
106206268Sdavidch	/* call ppb_1284_reset_error() if you absolutly want to change
107206268Sdavidch	 * the state from PPB_ERROR to another */
108206268Sdavidch	if ((ppb->state != PPB_ERROR) &&
109206268Sdavidch			(ppb->error == PPB_NO_ERROR)) {
110206268Sdavidch		ppb->state = state;
111206268Sdavidch		ppb->error = PPB_NO_ERROR;
112206268Sdavidch	}
113206268Sdavidch
114206268Sdavidch	return (0);
115206268Sdavidch}
116206268Sdavidch
117206268Sdavidchstatic int
118206268Sdavidchppb_1284_set_error(device_t bus, int error, int event)
119206268Sdavidch{
120206268Sdavidch	struct ppb_data *ppb = DEVTOSOFTC(bus);
121206268Sdavidch
122206268Sdavidch	/* do not accumulate errors */
123206268Sdavidch	if ((ppb->error == PPB_NO_ERROR) &&
124206268Sdavidch			(ppb->state != PPB_ERROR)) {
125178132Sdavidch		ppb->error = error;
126178132Sdavidch		ppb->state = PPB_ERROR;
127179771Sdavidch	}
128179771Sdavidch
129206268Sdavidch#ifdef DEBUG_1284
130206268Sdavidch	printf("ppb1284: error=%d status=0x%x event=%d\n", error,
131206268Sdavidch		ppb_rstr(bus) & 0xff, event);
132206268Sdavidch#endif
133206268Sdavidch
134206268Sdavidch	return (0);
135206268Sdavidch}
136206268Sdavidch
137206268Sdavidch/*
138206268Sdavidch * ppb_request_mode()
139206268Sdavidch *
140206268Sdavidch * Converts mode+options into ext. value
141206268Sdavidch */
142206268Sdavidchstatic int
143206268Sdavidchppb_request_mode(int mode, int options)
144206268Sdavidch{
145179771Sdavidch	int request_mode = 0;
146178132Sdavidch
147179771Sdavidch	if (options & PPB_EXTENSIBILITY_LINK) {
148179771Sdavidch		request_mode = EXT_LINK_1284_NORMAL;
149206268Sdavidch
150206268Sdavidch	} else {
151206268Sdavidch		switch (mode) {
152206268Sdavidch		case PPB_NIBBLE:
153206268Sdavidch			request_mode = (options & PPB_REQUEST_ID) ?
154206268Sdavidch					NIBBLE_1284_REQUEST_ID :
155206268Sdavidch					NIBBLE_1284_NORMAL;
156206268Sdavidch			break;
157206268Sdavidch		case PPB_PS2:
158206268Sdavidch			request_mode = (options & PPB_REQUEST_ID) ?
159206268Sdavidch					BYTE_1284_REQUEST_ID :
160206268Sdavidch					BYTE_1284_NORMAL;
161206268Sdavidch			break;
162206268Sdavidch		case PPB_ECP:
163206268Sdavidch			if (options & PPB_USE_RLE)
164206268Sdavidch				request_mode = (options & PPB_REQUEST_ID) ?
165179771Sdavidch					ECP_1284_RLE_REQUEST_ID :
166179771Sdavidch					ECP_1284_RLE;
167179771Sdavidch			else
168179771Sdavidch				request_mode = (options & PPB_REQUEST_ID) ?
169206268Sdavidch					ECP_1284_REQUEST_ID :
170206268Sdavidch					ECP_1284_NORMAL;
171206268Sdavidch			break;
172206268Sdavidch		case PPB_EPP:
173206268Sdavidch			request_mode = EPP_1284_NORMAL;
174206268Sdavidch			break;
175206268Sdavidch		default:
176206268Sdavidch			panic("%s: unsupported mode %d\n", __FUNCTION__, mode);
177206268Sdavidch		}
178206268Sdavidch	}
179206268Sdavidch
180206268Sdavidch	return (request_mode);
181206268Sdavidch}
182206268Sdavidch
183206268Sdavidch/*
184206268Sdavidch * ppb_peripheral_negociate()
185179771Sdavidch *
186179771Sdavidch * Negociate the peripheral side
187179771Sdavidch */
188179771Sdavidchint
189206268Sdavidchppb_peripheral_negociate(device_t bus, int mode, int options)
190206268Sdavidch{
191206268Sdavidch	int spin, request_mode, error = 0;
192206268Sdavidch	char r;
193206268Sdavidch
194206268Sdavidch	ppb_set_mode(bus, PPB_COMPATIBLE);
195206268Sdavidch	ppb_1284_set_state(bus, PPB_PERIPHERAL_NEGOCIATION);
196206268Sdavidch
197206268Sdavidch	/* compute ext. value */
198206268Sdavidch	request_mode = ppb_request_mode(mode, options);
199206268Sdavidch
200206268Sdavidch	/* wait host */
201206268Sdavidch	spin = 10;
202206268Sdavidch	while (spin-- && (ppb_rstr(bus) & nBUSY))
203206268Sdavidch		DELAY(1);
204206268Sdavidch
205179771Sdavidch	/* check termination */
206179771Sdavidch	if (!(ppb_rstr(bus) & SELECT) || !spin) {
207179771Sdavidch		error = ENODEV;
208179771Sdavidch		goto error;
209206268Sdavidch	}
210206268Sdavidch
211206268Sdavidch	/* Event 4 - read ext. value */
212206268Sdavidch	r = ppb_rdtr(bus);
213206268Sdavidch
214206268Sdavidch	/* nibble mode is not supported */
215206268Sdavidch	if ((r == (char)request_mode) ||
216206268Sdavidch			(r == NIBBLE_1284_NORMAL)) {
217206268Sdavidch
218206268Sdavidch		/* Event 5 - restore direction bit, no data avail */
219206268Sdavidch		ppb_wctr(bus, (STROBE | nINIT) & ~(SELECTIN));
220206268Sdavidch		DELAY(1);
221206268Sdavidch
222206268Sdavidch		/* Event 6 */
223206268Sdavidch		ppb_wctr(bus, (nINIT) & ~(SELECTIN | STROBE));
224206268Sdavidch
225179771Sdavidch		if (r == NIBBLE_1284_NORMAL) {
226179771Sdavidch#ifdef DEBUG_1284
227179771Sdavidch			printf("R");
228179771Sdavidch#endif
229206268Sdavidch			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);
230206268Sdavidch			error = EINVAL;
231206268Sdavidch			goto error;
232206268Sdavidch		} else {
233206268Sdavidch			ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE);
234206268Sdavidch			switch (r) {
235206268Sdavidch			case BYTE_1284_NORMAL:
236206268Sdavidch				ppb_set_mode(bus, PPB_BYTE);
237179771Sdavidch				break;
238179771Sdavidch			default:
239179771Sdavidch				break;
240179771Sdavidch			}
241206268Sdavidch#ifdef DEBUG_1284
242206268Sdavidch			printf("A");
243206268Sdavidch#endif
244206268Sdavidch			/* negociation succeeds */
245206268Sdavidch		}
246206268Sdavidch	} else {
247206268Sdavidch		/* Event 5 - mode not supported */
248206268Sdavidch		ppb_wctr(bus, SELECTIN);
249206268Sdavidch		DELAY(1);
250206268Sdavidch
251206268Sdavidch		/* Event 6 */
252206268Sdavidch		ppb_wctr(bus, (SELECTIN) & ~(STROBE | nINIT));
253206268Sdavidch		ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);
254206268Sdavidch
255206268Sdavidch#ifdef DEBUG_1284
256206268Sdavidch		printf("r");
257179771Sdavidch#endif
258179771Sdavidch		error = EINVAL;
259179771Sdavidch		goto error;
260179771Sdavidch	}
261206268Sdavidch
262206268Sdavidch	return (0);
263206268Sdavidch
264206268Sdavidcherror:
265206268Sdavidch	ppb_peripheral_terminate(bus, PPB_WAIT);
266206268Sdavidch	return (error);
267206268Sdavidch}
268206268Sdavidch
269206268Sdavidch/*
270206268Sdavidch * ppb_peripheral_terminate()
271206268Sdavidch *
272206268Sdavidch * Terminate peripheral transfer side
273179771Sdavidch *
274206268Sdavidch * Always return 0 in compatible mode
275206268Sdavidch */
276206268Sdavidchint
277179771Sdavidchppb_peripheral_terminate(device_t bus, int how)
278179771Sdavidch{
279207411Sdavidch	int error = 0;
280207411Sdavidch
281206268Sdavidch#ifdef DEBUG_1284
282206268Sdavidch	printf("t");
283206268Sdavidch#endif
284206268Sdavidch
285206268Sdavidch	ppb_1284_set_state(bus, PPB_PERIPHERAL_TERMINATION);
286179771Sdavidch
287157642Sps	/* Event 22 - wait up to host response time (1s) */
288157642Sps	if ((error = do_peripheral_wait(bus, SELECT | nBUSY, 0))) {
289179771Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 22);
290179771Sdavidch		goto error;
291206268Sdavidch	}
292206268Sdavidch
293206268Sdavidch	/* Event 24 */
294206268Sdavidch        ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
295206268Sdavidch
296206268Sdavidch	/* Event 25 - wait up to host response time (1s) */
297218423Sdavidch	if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) {
298206268Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 25);
299218423Sdavidch		goto error;
300218423Sdavidch	}
301218423Sdavidch
302206268Sdavidch	/* Event 26 */
303206268Sdavidch        ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));
304218423Sdavidch	DELAY(1);
305157642Sps	/* Event 27 */
306206268Sdavidch        ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED));
307157642Sps
308218423Sdavidch	/* Event 28 - wait up to host response time (1s) */
309206268Sdavidch	if ((error = do_peripheral_wait(bus, nBUSY, 0))) {
310206268Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 28);
311206268Sdavidch		goto error;
312206268Sdavidch	}
313206268Sdavidch
314157642Spserror:
315206268Sdavidch	ppb_set_mode(bus, PPB_COMPATIBLE);
316157642Sps	ppb_1284_set_state(bus, PPB_FORWARD_IDLE);
317206268Sdavidch
318206268Sdavidch	return (0);
319206268Sdavidch}
320206268Sdavidch
321218423Sdavidch/*
322157642Sps * byte_peripheral_outbyte()
323206268Sdavidch *
324206268Sdavidch * Write 1 byte in BYTE mode
325206268Sdavidch */
326206268Sdavidchstatic int
327218423Sdavidchbyte_peripheral_outbyte(device_t bus, char *buffer, int last)
328157642Sps{
329206268Sdavidch	int error = 0;
330206268Sdavidch
331206268Sdavidch	/* Event 7 */
332206268Sdavidch	if ((error = do_1284_wait(bus, nBUSY, nBUSY))) {
333218423Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 7);
334157642Sps		goto error;
335206268Sdavidch	}
336206268Sdavidch
337206268Sdavidch	/* check termination */
338206268Sdavidch	if (!(ppb_rstr(bus) & SELECT)) {
339218423Sdavidch		ppb_peripheral_terminate(bus, PPB_WAIT);
340157642Sps		goto error;
341218423Sdavidch	}
342218423Sdavidch
343206268Sdavidch	/* Event 15 - put byte on data lines */
344206268Sdavidch#ifdef DEBUG_1284
345206268Sdavidch	printf("B");
346157642Sps#endif
347206268Sdavidch	ppb_wdtr(bus, *buffer);
348206268Sdavidch
349206268Sdavidch	/* Event 9 */
350206268Sdavidch	ppb_wctr(bus, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN));
351206268Sdavidch
352157642Sps	/* Event 10 - wait data read */
353206268Sdavidch	if ((error = do_peripheral_wait(bus, nBUSY, 0))) {
354206268Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 16);
355218423Sdavidch		goto error;
356218423Sdavidch	}
357206268Sdavidch
358170810Sdavidch	/* Event 11 */
359206268Sdavidch	if (!last) {
360206268Sdavidch		ppb_wctr(bus, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN));
361206268Sdavidch	} else {
362206268Sdavidch		ppb_wctr(bus, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED));
363206268Sdavidch	}
364170810Sdavidch
365206268Sdavidch#if 0
366206268Sdavidch	/* Event 16 - wait strobe */
367218423Sdavidch	if ((error = do_peripheral_wait(bus, nACK | nBUSY, 0))) {
368218423Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 16);
369218423Sdavidch		goto error;
370170810Sdavidch	}
371206268Sdavidch#endif
372206268Sdavidch
373218423Sdavidch	/* check termination */
374218423Sdavidch	if (!(ppb_rstr(bus) & SELECT)) {
375206268Sdavidch		ppb_peripheral_terminate(bus, PPB_WAIT);
376179771Sdavidch		goto error;
377206268Sdavidch	}
378206268Sdavidch
379218423Sdavidcherror:
380218423Sdavidch	return (error);
381206268Sdavidch}
382179771Sdavidch
383206268Sdavidch/*
384206268Sdavidch * byte_peripheral_write()
385206268Sdavidch *
386206268Sdavidch * Write n bytes in BYTE mode
387218423Sdavidch */
388170810Sdavidchint
389206268Sdavidchbyte_peripheral_write(device_t bus, char *buffer, int len, int *sent)
390206268Sdavidch{
391218423Sdavidch	int error = 0, i;
392218423Sdavidch	char r;
393206268Sdavidch
394170810Sdavidch	ppb_1284_set_state(bus, PPB_PERIPHERAL_TRANSFER);
395218423Sdavidch
396218423Sdavidch	/* wait forever, the remote host is master and should initiate
397218423Sdavidch	 * termination
398206268Sdavidch	 */
399206268Sdavidch	for (i=0; i<len; i++) {
400218423Sdavidch		/* force remote nFAULT low to release the remote waiting
401157642Sps		 * process, if any
402206268Sdavidch		 */
403206268Sdavidch		r = ppb_rctr(bus);
404206268Sdavidch		ppb_wctr(bus, r & ~nINIT);
405206268Sdavidch
406157642Sps#ifdef DEBUG_1284
407157642Sps		printf("y");
408157642Sps#endif
409157642Sps		/* Event 7 */
410206268Sdavidch		error = ppb_poll_bus(bus, PPB_FOREVER, nBUSY, nBUSY,
411206268Sdavidch					PPB_INTR);
412206268Sdavidch
413157642Sps		if (error && error != EWOULDBLOCK)
414157642Sps			goto error;
415178132Sdavidch
416206268Sdavidch#ifdef DEBUG_1284
417206268Sdavidch		printf("b");
418206268Sdavidch#endif
419178132Sdavidch		if ((error = byte_peripheral_outbyte(bus, buffer+i, (i == len-1))))
420178132Sdavidch			goto error;
421157642Sps	}
422206268Sdavidcherror:
423206268Sdavidch	if (!error)
424206268Sdavidch		ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE);
425157642Sps
426157642Sps	*sent = i;
427157642Sps	return (error);
428206268Sdavidch}
429206268Sdavidch
430206268Sdavidch/*
431157642Sps * byte_1284_inbyte()
432157642Sps *
433157642Sps * Read 1 byte in BYTE mode
434207411Sdavidch */
435206268Sdavidchint
436206268Sdavidchbyte_1284_inbyte(device_t bus, char *buffer)
437157642Sps{
438157642Sps	int error = 0;
439157642Sps
440206268Sdavidch	/* Event 7 - ready to take data (nAUTO low) */
441206268Sdavidch	ppb_wctr(bus, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
442206268Sdavidch
443157642Sps	/* Event 9 - peripheral set nAck low */
444157642Sps	if ((error = do_1284_wait(bus, nACK, 0))) {
445179771Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 9);
446206268Sdavidch		goto error;
447179771Sdavidch	}
448179771Sdavidch
449179771Sdavidch	/* read the byte */
450206268Sdavidch	*buffer = ppb_rdtr(bus);
451179771Sdavidch
452179771Sdavidch	/* Event 10 - data received, can't accept more */
453179771Sdavidch	ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
454206268Sdavidch
455206268Sdavidch	/* Event 11 - peripheral ack */
456179771Sdavidch	if ((error = do_1284_wait(bus, nACK, nACK))) {
457179771Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 11);
458179771Sdavidch		goto error;
459179771Sdavidch	}
460179771Sdavidch
461179771Sdavidch	/* Event 16 - strobe */
462157642Sps	ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
463157642Sps	DELAY(3);
464157642Sps	ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
465157642Sps
466157642Spserror:
467157642Sps	return (error);
468157642Sps}
469157642Sps
470157642Sps/*
471157642Sps * nibble_1284_inbyte()
472157642Sps *
473157642Sps * Read 1 byte in NIBBLE mode
474157642Sps */
475206268Sdavidchint
476206268Sdavidchnibble_1284_inbyte(device_t bus, char *buffer)
477206268Sdavidch{
478206268Sdavidch	char nibble[2];
479206268Sdavidch	int i, error;
480206268Sdavidch
481206268Sdavidch	for (i = 0; i < 2; i++) {
482206268Sdavidch
483206268Sdavidch		/* Event 7 - ready to take data (nAUTO low) */
484206268Sdavidch		ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
485206268Sdavidch
486206268Sdavidch		/* Event 8 - peripheral writes the first nibble */
487206268Sdavidch
488206268Sdavidch		/* Event 9 - peripheral set nAck low */
489206268Sdavidch		if ((error = do_1284_wait(bus, nACK, 0))) {
490206268Sdavidch			ppb_1284_set_error(bus, PPB_TIMEOUT, 9);
491206268Sdavidch			goto error;
492206268Sdavidch		}
493206268Sdavidch
494206268Sdavidch		/* read nibble */
495206268Sdavidch		nibble[i] = ppb_rstr(bus);
496206268Sdavidch
497206268Sdavidch		/* Event 10 - ack, nibble received */
498206268Sdavidch		ppb_wctr(bus, nINIT & ~(AUTOFEED | STROBE | SELECTIN));
499206268Sdavidch
500206268Sdavidch		/* Event 11 - wait ack from peripherial */
501206268Sdavidch		if ((error = do_1284_wait(bus, nACK, nACK))) {
502206268Sdavidch			ppb_1284_set_error(bus, PPB_TIMEOUT, 11);
503206268Sdavidch			goto error;
504206268Sdavidch		}
505206268Sdavidch	}
506206268Sdavidch
507206268Sdavidch	*buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) |
508206268Sdavidch				(nibble2char(nibble[0]) & 0x0f);
509206268Sdavidch
510206268Sdavidcherror:
511206268Sdavidch	return (error);
512179771Sdavidch}
513179771Sdavidch
514157642Sps/*
515157642Sps * spp_1284_read()
516157642Sps *
517178132Sdavidch * Read in IEEE1284 NIBBLE/BYTE mode
518176448Sdavidch */
519157642Spsint
520157642Spsspp_1284_read(device_t bus, int mode, char *buffer, int max, int *read)
521157642Sps{
522179771Sdavidch	int error = 0, len = 0;
523179771Sdavidch	int terminate_after_transfer = 1;
524179771Sdavidch	int state;
525179771Sdavidch
526157642Sps	*read = len = 0;
527157642Sps
528157642Sps	state = ppb_1284_get_state(bus);
529157642Sps
530157642Sps	switch (state) {
531157642Sps	case PPB_FORWARD_IDLE:
532179771Sdavidch		if ((error = ppb_1284_negociate(bus, mode, 0)))
533157642Sps			return (error);
534157642Sps		break;
535157642Sps
536185162Skmacy	case PPB_REVERSE_IDLE:
537185162Skmacy		terminate_after_transfer = 0;
538182293Sdavidch		break;
539182293Sdavidch
540182293Sdavidch	default:
541182293Sdavidch		ppb_1284_terminate(bus);
542182293Sdavidch		if ((error = ppb_1284_negociate(bus, mode, 0)))
543182293Sdavidch			return (error);
544182293Sdavidch		break;
545182293Sdavidch	}
546182293Sdavidch
547185162Skmacy	while ((len < max) && !(ppb_rstr(bus) & (nFAULT))) {
548157642Sps
549157642Sps		ppb_1284_set_state(bus, PPB_REVERSE_TRANSFER);
550157642Sps
551157642Sps#ifdef DEBUG_1284
552157642Sps		printf("B");
553206268Sdavidch#endif
554206268Sdavidch
555206268Sdavidch		switch (mode) {
556206268Sdavidch		case PPB_NIBBLE:
557206268Sdavidch			/* read a byte, error means no more data */
558206268Sdavidch			if (nibble_1284_inbyte(bus, buffer+len))
559206268Sdavidch				goto end_while;
560157642Sps			break;
561206268Sdavidch		case PPB_BYTE:
562157642Sps			if (byte_1284_inbyte(bus, buffer+len))
563206268Sdavidch				goto end_while;
564157642Sps			break;
565157642Sps		default:
566157642Sps			error = EINVAL;
567206268Sdavidch			goto end_while;
568206268Sdavidch		}
569206268Sdavidch		len ++;
570206268Sdavidch	}
571157642Spsend_while:
572206268Sdavidch
573206268Sdavidch	if (!error)
574206268Sdavidch		ppb_1284_set_state(bus, PPB_REVERSE_IDLE);
575206268Sdavidch
576157642Sps	*read = len;
577206268Sdavidch
578206268Sdavidch	if (terminate_after_transfer || error)
579157642Sps		ppb_1284_terminate(bus);
580206268Sdavidch
581206268Sdavidch	return (error);
582206268Sdavidch}
583206268Sdavidch
584206268Sdavidch/*
585206268Sdavidch * ppb_1284_read_id()
586206268Sdavidch *
587206268Sdavidch */
588206268Sdavidchint
589206268Sdavidchppb_1284_read_id(device_t bus, int mode, char *buffer,
590206268Sdavidch		int max, int *read)
591206268Sdavidch{
592206268Sdavidch	int error = 0;
593206268Sdavidch
594206268Sdavidch	/* fill the buffer with 0s */
595157642Sps	bzero(buffer, max);
596157642Sps
597157642Sps	switch (mode) {
598157642Sps	case PPB_NIBBLE:
599206268Sdavidch	case PPB_ECP:
600157642Sps		if ((error = ppb_1284_negociate(bus, PPB_NIBBLE, PPB_REQUEST_ID)))
601157642Sps			return (error);
602157642Sps		error = spp_1284_read(bus, PPB_NIBBLE, buffer, max, read);
603157642Sps		break;
604157642Sps	case PPB_BYTE:
605157642Sps		if ((error = ppb_1284_negociate(bus, PPB_BYTE, PPB_REQUEST_ID)))
606157642Sps			return (error);
607157642Sps		error = spp_1284_read(bus, PPB_BYTE, buffer, max, read);
608157642Sps		break;
609157642Sps	default:
610157642Sps		panic("%s: unsupported mode %d\n", __FUNCTION__, mode);
611157642Sps	}
612157642Sps
613157642Sps	ppb_1284_terminate(bus);
614206268Sdavidch	return (error);
615206268Sdavidch}
616206268Sdavidch
617206268Sdavidch/*
618248036Smarius * ppb_1284_read()
619157642Sps *
620157642Sps * IEEE1284 read
621157642Sps */
622157642Spsint
623157642Spsppb_1284_read(device_t bus, int mode, char *buffer,
624157642Sps		int max, int *read)
625157642Sps{
626157642Sps	int error = 0;
627157642Sps
628157642Sps	switch (mode) {
629157642Sps	case PPB_NIBBLE:
630157642Sps	case PPB_BYTE:
631157642Sps		error = spp_1284_read(bus, mode, buffer, max, read);
632157642Sps		break;
633157642Sps	default:
634157642Sps		return (EINVAL);
635157642Sps	}
636157642Sps
637157642Sps	return (error);
638157642Sps}
639157642Sps
640157642Sps/*
641157642Sps * ppb_1284_negociate()
642157642Sps *
643157642Sps * IEEE1284 negociation phase
644157642Sps *
645157642Sps * Normal nibble mode or request device id mode (see ppb_1284.h)
646157642Sps *
647157642Sps * After negociation, nFAULT is low if data is available
648157642Sps */
649157642Spsint
650157642Spsppb_1284_negociate(device_t bus, int mode, int options)
651157642Sps{
652157642Sps	int error;
653157642Sps	int request_mode;
654157642Sps
655157642Sps#ifdef DEBUG_1284
656157642Sps	printf("n");
657157642Sps#endif
658157642Sps
659157642Sps	if (ppb_1284_get_state(bus) >= PPB_PERIPHERAL_NEGOCIATION)
660206268Sdavidch		ppb_peripheral_terminate(bus, PPB_WAIT);
661206268Sdavidch
662206268Sdavidch	if (ppb_1284_get_state(bus) != PPB_FORWARD_IDLE)
663206268Sdavidch		ppb_1284_terminate(bus);
664206268Sdavidch
665157642Sps#ifdef DEBUG_1284
666206268Sdavidch	printf("%d", mode);
667157642Sps#endif
668157642Sps
669206268Sdavidch	/* ensure the host is in compatible mode */
670206268Sdavidch	ppb_set_mode(bus, PPB_COMPATIBLE);
671157642Sps
672206268Sdavidch	/* reset error to catch the actual negociation error */
673206268Sdavidch	ppb_1284_reset_error(bus, PPB_FORWARD_IDLE);
674206268Sdavidch
675206268Sdavidch	/* calculate ext. value */
676157642Sps	request_mode = ppb_request_mode(mode, options);
677157642Sps
678206268Sdavidch	/* default state */
679157642Sps	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
680157642Sps	DELAY(1);
681206268Sdavidch
682157642Sps	/* enter negociation phase */
683157642Sps	ppb_1284_set_state(bus, PPB_NEGOCIATION);
684206268Sdavidch
685206268Sdavidch	/* Event 0 - put the exten. value on the data lines */
686179771Sdavidch	ppb_wdtr(bus, request_mode);
687206268Sdavidch
688179771Sdavidch#ifdef PERIPH_1284
689206268Sdavidch	/* request remote host attention */
690206268Sdavidch        ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
691157642Sps        DELAY(1);
692206268Sdavidch        ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN));
693206268Sdavidch#else
694206268Sdavidch	DELAY(1);
695157642Sps
696206268Sdavidch#endif /* !PERIPH_1284 */
697157642Sps
698157642Sps	/* Event 1 - enter IEEE1284 mode */
699157642Sps	ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
700157642Sps
701157642Sps#ifdef PERIPH_1284
702157642Sps	/* ignore the PError line, wait a bit more, remote host's
703157642Sps	 * interrupts don't respond fast enough */
704179771Sdavidch	if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT,
705179771Sdavidch				SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) {
706206268Sdavidch                ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
707179771Sdavidch                error = ENODEV;
708157642Sps                goto error;
709157642Sps        }
710157642Sps#else
711157642Sps	/* Event 2 - trying IEEE1284 dialog */
712248036Smarius	if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT,
713157642Sps			PERROR  | SELECT | nFAULT)) {
714157642Sps		ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
715157642Sps		error = ENODEV;
716157642Sps		goto error;
717157642Sps	}
718157642Sps#endif /* !PERIPH_1284 */
719157642Sps
720157642Sps	/* Event 3 - latch the ext. value to the peripheral */
721157642Sps	ppb_wctr(bus, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
722179771Sdavidch	DELAY(1);
723157642Sps
724157642Sps	/* Event 4 - IEEE1284 device recognized */
725179771Sdavidch	ppb_wctr(bus, nINIT & ~(SELECTIN | AUTOFEED | STROBE));
726157642Sps
727157642Sps	/* Event 6 - waiting for status lines */
728157642Sps	if (do_1284_wait(bus, nACK, nACK)) {
729179771Sdavidch		ppb_1284_set_error(bus, PPB_TIMEOUT, 6);
730157642Sps		error = EBUSY;
731157642Sps		goto error;
732157642Sps	}
733157642Sps
734179771Sdavidch	/* Event 7 - quering result consider nACK not to misunderstand
735157642Sps	 * a remote computer terminate sequence */
736206268Sdavidch	if (options & PPB_EXTENSIBILITY_LINK) {
737157642Sps
738157642Sps		/* XXX not fully supported yet */
739206268Sdavidch		ppb_1284_terminate(bus);
740157642Sps		return (0);
741157642Sps
742206268Sdavidch	}
743206268Sdavidch	if (request_mode == NIBBLE_1284_NORMAL) {
744206268Sdavidch		if (do_1284_wait(bus, nACK | SELECT, nACK)) {
745206268Sdavidch			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
746206268Sdavidch			error = ENODEV;
747157642Sps			goto error;
748206268Sdavidch		}
749206268Sdavidch	} else {
750206268Sdavidch		if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) {
751157642Sps			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
752170810Sdavidch			error = ENODEV;
753170810Sdavidch			goto error;
754157642Sps		}
755206268Sdavidch	}
756206268Sdavidch
757206268Sdavidch	switch (mode) {
758206268Sdavidch	case PPB_NIBBLE:
759206268Sdavidch	case PPB_PS2:
760157642Sps		/* enter reverse idle phase */
761206268Sdavidch		ppb_1284_set_state(bus, PPB_REVERSE_IDLE);
762157642Sps		break;
763157642Sps	case PPB_ECP:
764157642Sps		/* negociation ok, now setup the communication */
765157642Sps		ppb_1284_set_state(bus, PPB_SETUP);
766157642Sps		ppb_wctr(bus, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE));
767206268Sdavidch
768206268Sdavidch#ifdef PERIPH_1284
769157642Sps		/* ignore PError line */
770157642Sps		if (do_1284_wait(bus, nACK | SELECT | nBUSY,
771206268Sdavidch                                        nACK | SELECT | nBUSY)) {
772157642Sps                        ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
773206268Sdavidch                        error = ENODEV;
774157642Sps                        goto error;
775157642Sps                }
776157642Sps#else
777157642Sps		if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY,
778157642Sps					nACK | SELECT | PERROR | nBUSY)) {
779206268Sdavidch			ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
780157642Sps			error = ENODEV;
781206268Sdavidch			goto error;
782157642Sps		}
783157642Sps#endif /* !PERIPH_1284 */
784157642Sps
785157642Sps		/* ok, the host enters the ForwardIdle state */
786157642Sps		ppb_1284_set_state(bus, PPB_ECP_FORWARD_IDLE);
787157642Sps		break;
788157642Sps	case PPB_EPP:
789157642Sps		ppb_1284_set_state(bus, PPB_EPP_IDLE);
790157642Sps		break;
791157642Sps
792157642Sps	default:
793157642Sps		panic("%s: unknown mode (%d)!", __FUNCTION__, mode);
794157642Sps	}
795157642Sps	ppb_set_mode(bus, mode);
796157642Sps
797157642Sps	return (0);
798157642Sps
799157642Spserror:
800157642Sps	ppb_1284_terminate(bus);
801157642Sps
802157642Sps	return (error);
803157642Sps}
804157642Sps
805157642Sps/*
806157642Sps * ppb_1284_terminate()
807157642Sps *
808171667Sdavidch * IEEE1284 termination phase, return code should ignored since the host
809235818Syongari * is _always_ in compatible mode after ppb_1284_terminate()
810235818Syongari */
811235818Syongariint
812235818Syongarippb_1284_terminate(device_t bus)
813235818Syongari{
814235818Syongari
815235818Syongari#ifdef DEBUG_1284
816235818Syongari	printf("T");
817235818Syongari#endif
818235818Syongari
819235818Syongari	/* do not reset error here to keep the error that
820235818Syongari	 * may occured before the ppb_1284_terminate() call */
821235818Syongari	ppb_1284_set_state(bus, PPB_TERMINATION);
822235818Syongari
823235818Syongari#ifdef PERIPH_1284
824235818Syongari	/* request remote host attention */
825235818Syongari        ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED));
826171667Sdavidch        DELAY(1);
827171667Sdavidch#endif /* PERIPH_1284 */
828157642Sps
829157642Sps	/* Event 22 - set nSelectin low and nAutoFeed high */
830157642Sps	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
831157642Sps
832157642Sps	/* Event 24 - waiting for peripheral, Xflag ignored */
833157642Sps	if (do_1284_wait(bus, nACK | nBUSY | nFAULT, nFAULT)) {
834157642Sps		ppb_1284_set_error(bus, PPB_TIMEOUT, 24);
835157642Sps		goto error;
836157642Sps	}
837157642Sps
838157642Sps	/* Event 25 - set nAutoFd low */
839157642Sps	ppb_wctr(bus, (nINIT | SELECTIN | AUTOFEED) & ~STROBE);
840157642Sps
841157642Sps	/* Event 26 - compatible mode status is set */
842157642Sps
843157642Sps	/* Event 27 - peripheral set nAck high */
844157642Sps	if (do_1284_wait(bus, nACK, nACK)) {
845157642Sps		ppb_1284_set_error(bus, PPB_TIMEOUT, 27);
846157642Sps	}
847157642Sps
848157642Sps	/* Event 28 - end termination, return to idle phase */
849157642Sps	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
850157642Sps
851157642Spserror:
852157642Sps	/* return to compatible mode */
853157642Sps	ppb_set_mode(bus, PPB_COMPATIBLE);
854157642Sps	ppb_1284_set_state(bus, PPB_FORWARD_IDLE);
855206268Sdavidch
856157642Sps	return (0);
857206268Sdavidch}
858157642Sps