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 + -
显示快捷键?