⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppi.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
字号:
/*- * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith * 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: ppi.c,v 1.9 1999/01/10 12:04:55 nsouch Exp $ * */#include "ppi.h"#if NPPI > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/conf.h>#include <sys/kernel.h>#include <sys/uio.h>#include <sys/malloc.h>#include <sys/fcntl.h>#include <machine/clock.h>#include <dev/ppbus/ppbconf.h>#include <dev/ppbus/ppb_msq.h>#include "opt_ppb_1284.h"#ifdef PERIPH_1284#include <dev/ppbus/ppb_1284.h>#endif#include <dev/ppbus/ppi.h>#define BUFSIZE		512struct ppi_data {    int		ppi_unit;    int		ppi_flags;#define HAVE_PPBUS	(1<<0)#define HAD_PPBUS	(1<<1)    int		ppi_count;    int		ppi_mode;			/* IEEE1284 mode */    char	ppi_buffer[BUFSIZE];    struct ppb_device ppi_dev;};#define MAXPPI		8			/* XXX not much better! */static int 		nppi = 0;static struct ppi_data	*ppidata[MAXPPI];/* * Make ourselves visible as a ppbus driver */static struct ppb_device	*ppiprobe(struct ppb_data *ppb);static int			ppiattach(struct ppb_device *dev);static void			ppiintr(int unit);static struct ppb_driver ppidriver = {    ppiprobe, ppiattach, "ppi"};DATA_SET(ppbdriver_set, ppidriver);static	d_open_t	ppiopen;static	d_close_t	ppiclose;static	d_ioctl_t	ppiioctl;static	d_write_t	ppiwrite;static	d_read_t	ppiread;#define CDEV_MAJOR 82static struct cdevsw ppi_cdevsw = 	{ ppiopen,	ppiclose,	ppiread,	ppiwrite,	/* 82 */	  ppiioctl,	nullstop,	nullreset,	nodevtotty,	  seltrue,	nommap,		nostrat,	"ppi",	NULL,	-1 };#ifdef PERIPH_1284static voidppi_enable_intr(struct ppi_data *ppi){	char r;	r = ppb_rctr(&ppi->ppi_dev);	ppb_wctr(&ppi->ppi_dev, r | IRQENABLE);	return;}static voidppi_disable_intr(struct ppi_data *ppi){	char r;	r = ppb_rctr(&ppi->ppi_dev);	ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE);	return;}#endif /* PERIPH_1284 *//* * ppiprobe() */static struct ppb_device *ppiprobe(struct ppb_data *ppb){	struct ppi_data *ppi;	ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data),							M_TEMP, M_NOWAIT);	if (!ppi) {		printf("ppi: cannot malloc!\n");		return 0;	}	bzero(ppi, sizeof(struct ppi_data));	ppidata[nppi] = ppi;	/*	 * ppi dependent initialisation.	 */	ppi->ppi_unit = nppi;	/*	 * ppbus dependent initialisation.	 */	ppi->ppi_dev.id_unit = ppi->ppi_unit;	ppi->ppi_dev.ppb = ppb;	ppi->ppi_dev.intr = ppiintr;	/* Ok, go to next device on next probe */	nppi ++;	return &ppi->ppi_dev;}static intppiattach(struct ppb_device *dev){	/*	 * Report ourselves	 */	printf("ppi%d: <generic parallel i/o> on ppbus %d\n",	       dev->id_unit, dev->ppb->ppb_link->adapter_unit);	return (1);}/* * Cable * ----- * * Use an IEEE1284 compliant (DB25/DB25) cable with the following tricks: * * nStrobe   <-> nAck		1  <-> 10 * nAutofd   <-> Busy		11 <-> 14 * nSelectin <-> Select		17 <-> 13 * nInit     <-> nFault		15 <-> 16 * */static voidppiintr(int unit){#ifdef PERIPH_1284	struct ppi_data *ppi = ppidata[unit];	ppi_disable_intr(ppi);	switch (ppi->ppi_dev.ppb->state) {	/* accept IEEE1284 negociation then wakeup an waiting process to	 * continue negociation at process level */	case PPB_FORWARD_IDLE:		/* Event 1 */		if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) ==							(SELECT | nBUSY)) {			/* IEEE1284 negociation */#ifdef DEBUG_1284			printf("N");#endif			/* Event 2 - prepare for reading the ext. value */			ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN);			ppi->ppi_dev.ppb->state = PPB_NEGOCIATION;		} else {#ifdef DEBUG_1284			printf("0x%x", ppb_rstr(&ppi->ppi_dev));#endif			ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT);			break;		}		/* wake up any process waiting for negociation from		 * remote master host */		/* XXX should set a variable to warn the process about		 * the interrupt */		wakeup(ppi);		break;	default:#ifdef DEBUG_1284		printf("?%d", ppi->ppi_dev.ppb->state);#endif		ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE;		ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE);		break;	}	ppi_enable_intr(ppi);#endif /* PERIPH_1284 */	return;}static intppiopen(dev_t dev, int flags, int fmt, struct proc *p){	u_int unit = minor(dev);	struct ppi_data *ppi = ppidata[unit];	int res;	if (unit >= nppi)		return (ENXIO);	if (!(ppi->ppi_flags & HAVE_PPBUS)) {		if ((res = ppb_request_bus(&ppi->ppi_dev,			(flags & O_NONBLOCK) ? PPB_DONTWAIT :						(PPB_WAIT | PPB_INTR))))			return (res);		ppi->ppi_flags |= HAVE_PPBUS;	}	ppi->ppi_count += 1;	return (0);}static intppiclose(dev_t dev, int flags, int fmt, struct proc *p){	u_int unit = minor(dev);	struct ppi_data *ppi = ppidata[unit];	ppi->ppi_count --;	if (!ppi->ppi_count) {#ifdef PERIPH_1284		switch (ppi->ppi_dev.ppb->state) {		case PPB_PERIPHERAL_IDLE:			ppb_peripheral_terminate(&ppi->ppi_dev, 0);			break;		case PPB_REVERSE_IDLE:		case PPB_EPP_IDLE:		case PPB_ECP_FORWARD_IDLE:		default:			ppb_1284_terminate(&ppi->ppi_dev);			break;		}#endif /* PERIPH_1284 */		ppb_release_bus(&ppi->ppi_dev);		ppi->ppi_flags &= ~HAVE_PPBUS;	}	return (0);}/* * ppiread() * * IEEE1284 compliant read. * * First, try negociation to BYTE then NIBBLE mode * If no data is available, wait for it otherwise transfer as much as possible */static intppiread(dev_t dev, struct uio *uio, int ioflag){#ifdef PERIPH_1284	u_int unit = minor(dev);	struct ppi_data *ppi = ppidata[unit];	int len, error = 0;	switch (ppi->ppi_dev.ppb->state) {	case PPB_PERIPHERAL_IDLE:		ppb_peripheral_terminate(&ppi->ppi_dev, 0);		/* fall throught */	case PPB_FORWARD_IDLE:		/* if can't negociate NIBBLE mode then try BYTE mode,		 * the peripheral may be a computer		 */		if ((ppb_1284_negociate(&ppi->ppi_dev,			ppi->ppi_mode = PPB_NIBBLE, 0))) {			/* XXX Wait 2 seconds to let the remote host some			 * time to terminate its interrupt			 */			tsleep(ppi, PPBPRI, "ppiread", 2*hz);						if ((error = ppb_1284_negociate(&ppi->ppi_dev,				ppi->ppi_mode = PPB_BYTE, 0)))				return (error);		}		break;	case PPB_REVERSE_IDLE:	case PPB_EPP_IDLE:	case PPB_ECP_FORWARD_IDLE:	default:		break;	}#ifdef DEBUG_1284	printf("N");#endif	/* read data */	len = 0;	while (uio->uio_resid) {		if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode,			ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid),			&len))) {			goto error;		}		if (!len)			goto error;		/* no more data */#ifdef DEBUG_1284		printf("d");#endif		if ((error = uiomove(ppi->ppi_buffer, len, uio)))			goto error;	}error:#else /* PERIPH_1284 */	int error = ENODEV;#endif	return (error);}/* * ppiwrite() * * IEEE1284 compliant write * * Actually, this is the peripheral side of a remote IEEE1284 read * * The first part of the negociation (IEEE1284 device detection) is * done at interrupt level, then the remaining is done by the writing * process * * Once negociation done, transfer data */static intppiwrite(dev_t dev, struct uio *uio, int ioflag){#ifdef PERIPH_1284	u_int unit = minor(dev);	struct ppi_data *ppi = ppidata[unit];	struct ppb_data *ppb = ppi->ppi_dev.ppb;	int len, error = 0, sent;#if 0	int ret;	#define ADDRESS		MS_PARAM(0, 0, MS_TYP_PTR)	#define LENGTH		MS_PARAM(0, 1, MS_TYP_INT)	struct ppb_microseq msq[] = {		  { MS_OP_PUT, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } },		  MS_RET(0)	};	/* negociate ECP mode */	if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) {		printf("ppiwrite: ECP negociation failed\n");	}	while (!error && (len = min(uio->uio_resid, BUFSIZE))) {		uiomove(ppi->ppi_buffer, len, uio);		ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len);		error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret);	}#endif	/* we have to be peripheral to be able to send data, so	 * wait for the appropriate state	 */	if (ppb->state < PPB_PERIPHERAL_NEGOCIATION)		ppb_1284_terminate(&ppi->ppi_dev);	while (ppb->state != PPB_PERIPHERAL_IDLE) {		/* XXX should check a variable before sleeping */#ifdef DEBUG_1284		printf("s");#endif		ppi_enable_intr(ppi);		/* sleep until IEEE1284 negociation starts */		error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0);		switch (error) {		case 0:			/* negociate peripheral side with BYTE mode */			ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0);			break;		case EWOULDBLOCK:			break;		default:			goto error;		}	}#ifdef DEBUG_1284	printf("N");#endif	/* negociation done, write bytes to master host */	while (len = min(uio->uio_resid, BUFSIZE)) {		uiomove(ppi->ppi_buffer, len, uio);		if ((error = byte_peripheral_write(&ppi->ppi_dev,						ppi->ppi_buffer, len, &sent)))			goto error;#ifdef DEBUG_1284		printf("d");#endif	}error:#else /* PERIPH_1284 */	int error = ENODEV;#endif	return (error);}static intppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p){	u_int unit = minor(dev);	struct ppi_data *ppi = ppidata[unit];	int error = 0;	u_int8_t *val = (u_int8_t *)data;	switch (cmd) {	case PPIGDATA:			/* get data register */		*val = ppb_rdtr(&ppi->ppi_dev);		break;	case PPIGSTATUS:		/* get status bits */		*val = ppb_rstr(&ppi->ppi_dev);		break;	case PPIGCTRL:			/* get control bits */		*val = ppb_rctr(&ppi->ppi_dev);		break;	case PPIGEPP:			/* get EPP bits */		*val = ppb_repp(&ppi->ppi_dev);		break;	case PPIGECR:			/* get ECP bits */		*val = ppb_recr(&ppi->ppi_dev);		break;	case PPIGFIFO:			/* read FIFO */		*val = ppb_rfifo(&ppi->ppi_dev);		break;	case PPISDATA:			/* set data register */		ppb_wdtr(&ppi->ppi_dev, *val);		break;	case PPISSTATUS:		/* set status bits */		ppb_wstr(&ppi->ppi_dev, *val);		break;	case PPISCTRL:			/* set control bits */		ppb_wctr(&ppi->ppi_dev, *val);		break;	case PPISEPP:			/* set EPP bits */		ppb_wepp(&ppi->ppi_dev, *val);		break;	case PPISECR:			/* set ECP bits */		ppb_wecr(&ppi->ppi_dev, *val);		break;	case PPISFIFO:			/* write FIFO */		ppb_wfifo(&ppi->ppi_dev, *val);		break;	default:		error = ENOTTY;		break;	}    	return (error);}#ifdef PPI_MODULEMOD_DEV(ppi, LM_DT_CHAR, CDEV_MAJOR, &ppi_cdevsw);static intppi_load(struct lkm_table *lkmtp, int cmd){	struct ppb_data *ppb;	struct ppb_device *dev;	int i;	for (ppb = ppb_next_bus(NULL); ppb; ppb = ppb_next_bus(ppb)) {		dev = ppiprobe(ppb);		ppiattach(dev);		ppb_attach_device(dev);	}	return (0);}static intppi_unload(struct lkm_table *lkmtp, int cmd){	int i;	for (i = nppi-1; i > 0; i--) {		ppb_remove_device(&ppidata[i]->ppi_dev);		free(ppidata[i], M_TEMP);	}	return (0);}intppi_mod(struct lkm_table *lkmtp, int cmd, int ver){	DISPATCH(lkmtp, cmd, ver, ppi_load, ppi_unload, lkm_nullcmd);}#endif /* PPI_MODULE */static ppi_devsw_installed = 0;static void ppi_drvinit(void *unused){	dev_t dev;	if (!ppi_devsw_installed ) {		dev = makedev(CDEV_MAJOR, 0);		cdevsw_add(&dev, &ppi_cdevsw, NULL);		ppi_devsw_installed = 1;    	}}SYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL)#endif /* NPPI */

⌨️ 快捷键说明

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