ppb_1284.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
/*- * Copyright (c) 1997 Nicolas Souchu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	$Id: ppb_1284.c,v 1.8 1999/01/14 21:38:16 nsouch Exp $ * *//* * General purpose routines for the IEEE1284-1994 Standard */#include "opt_ppb_1284.h"#include <sys/param.h>#include <sys/systm.h>#include <machine/clock.h>#include <dev/ppbus/ppbconf.h>#include <dev/ppbus/ppb_1284.h>/* * do_1284_wait() * * Wait for the peripherial up to 40ms */static intdo_1284_wait(struct ppb_device *dev, char mask, char status){	return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR | PPB_POLL));}static intdo_peripheral_wait(struct ppb_device *dev, char mask, char status){	return (ppb_poll_device(dev, 100, mask, status, PPB_NOINTR | PPB_POLL));}#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)/* * ppb_1284_reset_error() * * Unconditionaly reset the error field */static intppb_1284_reset_error(struct ppb_device *dev, int state){	dev->ppb->error = PPB_NO_ERROR;	dev->ppb->state = state;	return (0);}/* * ppb_1284_get_state() * * Get IEEE1284 state */static intppb_1284_get_state(struct ppb_device *dev){        return (dev->ppb->state);}/* * ppb_1284_set_state() * * Change IEEE1284 state if no error occured */static intppb_1284_set_state(struct ppb_device *dev, int state){	/* call ppb_1284_reset_error() if you absolutly want to change	 * the state from PPB_ERROR to another */	if ((dev->ppb->state != PPB_ERROR) &&			(dev->ppb->error == PPB_NO_ERROR)) {		dev->ppb->state = state;		dev->ppb->error = PPB_NO_ERROR;	}	return (0);}static intppb_1284_set_error(struct ppb_device *dev, int error, int event){	/* do not accumulate errors */	if ((dev->ppb->error == PPB_NO_ERROR) &&			(dev->ppb->state != PPB_ERROR)) {		dev->ppb->error = error;		dev->ppb->state = PPB_ERROR;	}#ifdef DEBUG_1284	printf("ppb1284: error=%d status=0x%x event=%d\n", error,		ppb_rstr(dev) & 0xff, event);#endif	return (0);}/* * ppb_request_mode() * * Converts mode+options into ext. value */static intppb_request_mode(int mode, int options){	int request_mode = 0;	if (options & PPB_EXTENSIBILITY_LINK) {		request_mode = EXT_LINK_1284_NORMAL;	} else {		switch (mode) {		case PPB_NIBBLE:			request_mode = (options & PPB_REQUEST_ID) ?					NIBBLE_1284_REQUEST_ID :					NIBBLE_1284_NORMAL;			break;		case PPB_PS2:			request_mode = (options & PPB_REQUEST_ID) ?					BYTE_1284_REQUEST_ID :					BYTE_1284_NORMAL;			break;		case PPB_ECP:			if (options & PPB_USE_RLE)				request_mode = (options & PPB_REQUEST_ID) ?					ECP_1284_RLE_REQUEST_ID :					ECP_1284_RLE;			else				request_mode = (options & PPB_REQUEST_ID) ?					ECP_1284_REQUEST_ID :					ECP_1284_NORMAL;			break;		case PPB_EPP:			request_mode = EPP_1284_NORMAL;			break;		default:			panic("%s: unsupported mode %d\n", __FUNCTION__, mode);		}	}	return (request_mode);}/* * ppb_peripheral_negociate() * * Negociate the peripheral side */intppb_peripheral_negociate(struct ppb_device *dev, int mode, int options){	int spin, request_mode, error = 0;	char r;	ppb_set_mode(dev, PPB_COMPATIBLE);	ppb_1284_set_state(dev, PPB_PERIPHERAL_NEGOCIATION);	/* compute ext. value */	request_mode = ppb_request_mode(mode, options);	/* wait host */	spin = 10;	while (spin-- && (ppb_rstr(dev) & nBUSY))		DELAY(1);	/* check termination */	if (!(ppb_rstr(dev) & SELECT) || !spin) {		error = ENODEV;		goto error;	}	/* Event 4 - read ext. value */	r = ppb_rdtr(dev);	/* nibble mode is not supported */	if ((r == (char)request_mode) ||			(r == NIBBLE_1284_NORMAL)) {		/* Event 5 - restore direction bit, no data avail */		ppb_wctr(dev, (STROBE | nINIT) & ~(SELECTIN));		DELAY(1);		/* Event 6 */		ppb_wctr(dev, (nINIT) & ~(SELECTIN | STROBE));		if (r == NIBBLE_1284_NORMAL) {#ifdef DEBUG_1284			printf("R");#endif			ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4);			error = EINVAL;			goto error;		} else {			ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE);			switch (r) {			case BYTE_1284_NORMAL:				ppb_set_mode(dev, PPB_BYTE);				break;			default:				break;			}#ifdef DEBUG_1284			printf("A");#endif			/* negociation succeeds */		}	} else {		/* Event 5 - mode not supported */		ppb_wctr(dev, SELECTIN);		DELAY(1);		/* Event 6 */		ppb_wctr(dev, (SELECTIN) & ~(STROBE | nINIT));		ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4);#ifdef DEBUG_1284		printf("r");#endif		error = EINVAL;		goto error;	}	return (0);error:	ppb_peripheral_terminate(dev, PPB_WAIT);	return (error);}/* * ppb_peripheral_terminate() * * Terminate peripheral transfer side * * Always return 0 in compatible mode */intppb_peripheral_terminate(struct ppb_device *dev, int how){	int error = 0;#ifdef DEBUG_1284	printf("t");#endif	ppb_1284_set_state(dev, PPB_PERIPHERAL_TERMINATION);	/* Event 22 - wait up to host response time (1s) */	if ((error = do_peripheral_wait(dev, SELECT | nBUSY, 0))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 22);		goto error;	}	/* Event 24 */        ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));	/* Event 25 - wait up to host response time (1s) */	if ((error = do_peripheral_wait(dev, nBUSY, nBUSY))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 25);		goto error;	}	/* Event 26 */        ppb_wctr(dev, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));	DELAY(1);	/* Event 27 */        ppb_wctr(dev, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED));	/* Event 28 - wait up to host response time (1s) */	if ((error = do_peripheral_wait(dev, nBUSY, 0))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 28);		goto error;	}	error:	ppb_set_mode(dev, PPB_COMPATIBLE);	ppb_1284_set_state(dev, PPB_FORWARD_IDLE);	return (0);}/* * byte_peripheral_outbyte() * * Write 1 byte in BYTE mode */static intbyte_peripheral_outbyte(struct ppb_device *dev, char *buffer, int last){	int error = 0;	/* Event 7 */	if ((error = do_1284_wait(dev, nBUSY, nBUSY))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 7);		goto error;	}	/* check termination */	if (!(ppb_rstr(dev) & SELECT)) {		ppb_peripheral_terminate(dev, PPB_WAIT);		goto error;	}	/* Event 15 - put byte on data lines */#ifdef DEBUG_1284	printf("B");#endif	ppb_wdtr(dev, *buffer);	/* Event 9 */	ppb_wctr(dev, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN));	/* Event 10 - wait data read */	if ((error = do_peripheral_wait(dev, nBUSY, 0))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 16);		goto error;	}	/* Event 11 */	if (!last) {		ppb_wctr(dev, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN));	} else {		ppb_wctr(dev, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED));	}#if 0	/* Event 16 - wait strobe */	if ((error = do_peripheral_wait(dev, nACK | nBUSY, 0))) {		ppb_1284_set_error(dev, PPB_TIMEOUT, 16);		goto error;	}#endif	/* check termination */	if (!(ppb_rstr(dev) & SELECT)) {		ppb_peripheral_terminate(dev, PPB_WAIT);		goto error;	}error:	return (error);}/* * byte_peripheral_write() * * Write n bytes in BYTE mode */intbyte_peripheral_write(struct ppb_device *dev, char *buffer, int len, int *sent){	int error = 0, i;	char r;	ppb_1284_set_state(dev, PPB_PERIPHERAL_TRANSFER);	/* wait forever, the remote host is master and should initiate	 * termination	 */	for (i=0; i<len; i++) {		/* force remote nFAULT low to release the remote waiting		 * process, if any		 */		r = ppb_rctr(dev);		ppb_wctr(dev, r & ~nINIT);#ifdef DEBUG_1284		printf("y");#endif		/* Event 7 */		error = ppb_poll_device(dev, PPB_FOREVER, nBUSY, nBUSY,					PPB_INTR);		if (error && error != EWOULDBLOCK)			goto error;#ifdef DEBUG_1284		printf("b");#endif		if ((error = byte_peripheral_outbyte(dev, buffer+i, (i == len-1))))			goto error;	}error:	if (!error)		ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE);	*sent = i;	return (error);}/* * byte_1284_inbyte() * * Read 1 byte in BYTE mode */int

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?