📄 mbxlptdrv.c
字号:
/* mbxLptDrv.c - parallel chip device driver for MBX BSP *//* Copyright 1984-1998 Wind River Systems, Inc. *//* Copyright 1997,1998 Motorola, Inc., All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01e,08may98,map fixed interrupt handling.01d,31mar98,map removed ref to N_MBX_LPT_CHANNELS.01c,24mar98,map code cleanup01b,21nov97,rhk WRS code review cleanup01a,22may97,dmw Port to MBX, from baseline, version 01e.*//*DESCRIPTIONThis is the driver for the parallel port on the MBX.MBX currently supports only 1 LPT port.USER-CALLABLE ROUTINESMost of the routines in this driver are accessible only through the I/Osystem. However, two routines must be called directly: lptDrv() toinitialize the driver, and lptDevCreate() to create devices.There are one other callable routines: lptShow() to show statistics.The argument to lptShow() is a channel number, 0 to 2.Before the driver can be used, it must be initialized by calling lptDrv().This routine should be called exactly once, before any reads, writes, orcalls to lptDevCreate(). Normally, it is called from usrRoot() inusrConfig.c. The first argument to lptDrv() is a number of channels,0 to 2. The second argument is a pointer to the resource table.Definitions of members of the resource table structure are:.CS int ioBase; /@ IO base address @/ int intVector; /@ interrupt vector number @/ int intLevel; /@ interrupt level @/ BOOL autofeed; /@ TRUE if enable autofeed @/ int busyWait; /@ loop count for BUSY wait @/ int strobeWait; /@ loop count for STROBE wait @/ int retryCnt; /@ retry count @/ int timeout; /@ timeout second for syncSem @/.CEIOCTL FUNCTIONSThis driver responds to two functions: LPT_SETCONTROL and LPT_GETSTATUS.The argument for LPT_SETCONTROL is a value of the control register.The argument for LPT_GETSTATUS is a integer pointer where a value of thestatus register is stored.SEE ALSO:.pG "I/O System"*/#include "vxWorks.h"#include "taskLib.h"#include "blkIo.h"#include "ioLib.h"#include "iosLib.h"#include "memLib.h"#include "stdlib.h"#include "errnoLib.h"#include "stdio.h"#include "string.h"#include "private/semLibP.h"#include "intLib.h"#include "iv.h"#include "wdLib.h"#include "sysLib.h"#include "drv/multi/ppc860Siu.h"#include "drv/multi/ppc860Cpm.h"#include "drv/sio/ppc860Sio.h"#include "mbx800.h"#include "sys/fcntlcom.h"#include "mbxLptDrv.h"#if defined(INCLUDE_LPT)/* defines *//* imports *//* Imports (and forward references) for MBX8xx PIP Parallel Port. */IMPORT UINT vxImmrGet();IMPORT BOOL sysQspanPresent;IMPORT void pipCcr(); /* execute channel command */IMPORT void lptShow();/* Imports for MBX8xx FDC Parallel Port. */IMPORT UCHAR sysInByte (UINT32);IMPORT void sysOutByte (UINT32, UINT8);typedef struct pipTransmitBd { UINT16 bdCsr; /* Control and Status Register */ UINT16 dataLen; /* Data length in bytes */ UINT8 *pData; /* TX Data Pointer */ } PIP_TXBD;/* globals */STATUS lptDrvNum; /* driver number assigned to this driver *//* locals */LOCAL LPT_DRV lptDrvData [N_LPT_CHANNELS];LOCAL LPT_DEV lptDevData [N_LPT_CHANNELS];UINT8 debugBuf[BUFF_SIZE];/* forward declarations */LOCAL int lptOpen (LPT_DEV *pDev, char *name, int mode);LOCAL int lptRead (LPT_DEV *pDev, char *pBuf, int size);LOCAL int lptWrite (LPT_DEV *pDev, char *pBuf, int size);LOCAL STATUS lptIoctl (LPT_DEV *pDev, int function, int arg);LOCAL void lptIntr (LPT_DEV *pDev);LOCAL void lptInit (LPT_DRV *pDev);LOCAL UINT pipIoctl (UINT ioctlflg, UINT pReg, UINT size, UINT wdata1, UINT wdata2);/********************************************************************************* syncdata - synchronizes data read/write operations.** This routine synchronizes data read/write operations. It executes* the following assembly instructions: 'isync', 'eieio', 'sync'.** RETURNS: none.*/LOCAL void syncdata ( ) { __asm__(" isync"); __asm__(" eieio"); __asm__(" sync"); }/********************************************************************************* lptIntrInit - initialize the interrupt handlers for the LPT driver** This routine sets up interrupt vectors of the LPT ports.** This routine should be called exactly once, before any reads, writes,* or calls to lptDevCreate(). Normally, it is called by usrRoot()* in usrConfig.c.** RETURNS: OK, or ERROR if the interrupts for the driver cannot be installed.** SEE ALSO: lptDevCreate()*/LOCAL STATUS lptIntrInit ( LPT_DEV *pDev ) { UINT immrVal = vxImmrGet (); (void) intConnect (INUM_TO_IVEC (pDev->intVector), (VOIDFUNCPTR)lptIntr, (int)pDev); if (sysQspanPresent) intEnable (pDev->intLevel); /* unmask the interrupt */ else { /* Enable Interrupts at CPM Level from SMC2/PIP */ *CIMR(immrVal) |= CIMR_SMC2_PIP; } return (OK); }/********************************************************************************* pipOutInt - Integer out function for PIP. ** This runtime registered function performs a 32 bit write to the* PIP module.** RETURNS: none**/LOCAL void pipOutInt ( UINT32 pReg, UINT32 data ) { PIP_WRITE(*((UINT32 *)(pReg)),data); }/********************************************************************************* pipInInt - Integer in function for PIP. ** This runtime registered function performs a 32 bit read from the* PIP module.** RETURNS: A 32 bit value from location at pReg.**/LOCAL UINT32 pipInInt ( UINT32 pReg ) { return (PIP_READ(*((UINT32 *)(pReg)))); }/********************************************************************************* lptDrv - initialize the LPT driver** This routine initializes the LPT driver, sets up interrupt vectors,* and performs hardware initialization of the LPT ports.** MBX will only support one LPT port, for now.** This routine should be called exactly once, before any reads, writes,* or calls to lptDevCreate(). Normally, it is called by usrRoot()* in usrConfig.c.** RETURNS: OK, or ERROR if the driver cannot be installed.** SEE ALSO: lptDevCreate()*/STATUS lptDrv ( int channel, /* LPT channels */ LPT_RESOURCE *pResource /* LPT resources */ ) { LPT_DRV *pDrv; UINT immrVal = vxImmrGet (); /* check if driver already installed */ if (lptDrvNum > 0) return (OK); if (channel > N_LPT_CHANNELS) return (ERROR); channel = N_LPT_CHANNELS - 1; pDrv = &(lptDrvData[channel]); pDrv->pDev = &(lptDevData[channel]); pDrv->pDev->instance = channel; pDrv->pDev->created = FALSE; pDrv->pDev->autofeed = pResource->autofeed; pDrv->pDev->inservice = FALSE; if (sysQspanPresent) { pDrv->data = (UINT32)LPT_DATA (pResource->ioBase); pDrv->stat = (UINT32)LPT_STAT (pResource->ioBase); pDrv->ctrl = (UINT32)LPT_CTRL (pResource->ioBase); pDrv->lptRegRead = (UINT32(*)())sysInByte; pDrv->lptRegWrite = (void(*)())sysOutByte; pDrv->ackValue = S_NOACK; pDrv->busyValue = (S_SELECT|S_NODERR|S_NOBUSY); pDrv->busyMask = S_MASK; pDrv->pDev->intVector = pResource->intVector; pDrv->pDev->intLevel = pResource->intLevel; } else { pDrv->data = (UINT32)(PBDAT(immrVal)); pDrv->stat = (UINT32)(PBDAT(immrVal)); pDrv->ctrl = (UINT32)(PBDAT(immrVal)); pDrv->lptRegRead = pipInInt; pDrv->lptRegWrite = pipOutInt; pDrv->ackValue = CPM_PIP_ACK; pDrv->busyValue = CPM_PIP_ACK; pDrv->busyMask = (CPM_PIP_ACK|CPM_PIP_BSY); pDrv->pDev->intVector = IVEC_TO_INUM (IV_SMC2_PIP); pDrv->pDev->intLevel = IVEC_TO_ILVL (IV_SMC2_PIP); } pDrv->pDev->intCnt = 0; pDrv->pDev->charsPrinted = 0; pDrv->pDev->retryCnt = pResource->retryCnt; pDrv->busyWait = pResource->busyWait; pDrv->strobeWait = pResource->strobeWait; pDrv->pDev->timeout = pResource->timeout; semBInit (&pDrv->syncSem, SEM_Q_FIFO, SEM_EMPTY); semMInit (&pDrv->muteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); lptIntrInit (pDrv->pDev); lptInit (pDrv); lptDrvNum = iosDrvInstall (lptOpen, (FUNCPTR) NULL, lptOpen, (FUNCPTR) NULL, lptRead, lptWrite, lptIoctl); return (lptDrvNum == ERROR ? ERROR : OK); }/********************************************************************************* lptDevCreate - create a device for an LPT port** This routine creates a device for a specified LPT port. Each port* to be used should have exactly one device associated with it by calling* this routine.** For instance, to create the device `/lpt/0', the proper call would be:* .CS* lptDevCreate ("/lpt/0", 0);* .CE** RETURNS: OK, or ERROR if the driver is not installed, the channel is* invalid, or the device already exists.** SEE ALSO: lptDrv()*/STATUS lptDevCreate ( char *name, /* name to use for this device */ int channel /* physical channel for this device (0 - 2) */ ) { if (channel > N_LPT_CHANNELS - 1) return (ERROR); if (lptDrvNum <= 0) { errnoSet (S_ioLib_NO_DRIVER); return (ERROR); } /* if this device already exists, don't create it */ if (lptDevData[channel].created) return (ERROR); /* mark the device as created, and add the device to the I/O system */ lptDevData[channel].created = TRUE; return (iosDevAdd (&lptDevData[channel].devHdr, name, lptDrvNum)); }/********************************************************************************* lptOpen - open file to LPT** This routine returns the pointer to the lpt device data. This * routine would be modified if multiple printer devices were supported* and the name would be parsed, returning a pointer or NULL.** RETURNS: the pointer to the lpt device data.**/LOCAL int lptOpen ( LPT_DEV *pDev, char *name, int mode ) { return ((int) &lptDevData[0]); }/********************************************************************************* lptRead - read from the port.** Read from the port.** RETURNS: ERROR.*/LOCAL int lptRead ( LPT_DEV *pDev, char *pBuf, int size ) { return (ERROR); }/********************************************************************************* lptBusyBits - returns busy status from printer port.** RETURNS: Busy bits depending on MBX8xx implemantaion.**/LOCAL int lptBusyBits ( LPT_DRV *pDrv ) { return ((pDrv->lptRegRead (pDrv->stat) & pDrv->busyMask) != (pDrv->busyValue)); }/********************************************************************************* lptBusy - returns busy status from printer port.** Read status and wait until not busy or retry expires.** RETURNS: OK/ERROR.*/LOCAL STATUS lptBusy ( LPT_DRV *pDrv ) { BOOL giveup = FALSE; int retry; int wait; retry = 0; while (lptBusyBits(pDrv)) { if (retry++ > pDrv->pDev->retryCnt) { if (giveup) { errnoSet (S_ioLib_DEVICE_ERROR); semGive (&pDrv->muteSem); return (ERROR); } else { lptInit (pDrv); giveup = TRUE; } } wait = 0; while (wait != pDrv->busyWait) { taskDelay (sysClkRateGet () >> 10); wait++; } } return (OK); }/********************************************************************************* lptStrobe - Enable/Disable strobe depending on MBX8xx implemantaion.** This function performs the Enable/Disable strobe depending on MBX8xx * implemantaion.** RETURNS: none**/LOCAL void lptStrobe ( LPT_DRV *pDrv, BOOL enable ) { if (!sysQspanPresent) { if (enable) PIP_AND(*((UINT32 *)(pDrv->ctrl)),~CPM_PIP_STB); else PIP_OR(*((UINT32 *)(pDrv->ctrl)),CPM_PIP_STB); } else { if (enable) pDrv->lptRegWrite(pDrv->ctrl, pDrv->lptRegRead(pDrv->ctrl) | C_STROBE); else pDrv->lptRegWrite(pDrv->ctrl, pDrv->lptRegRead(pDrv->ctrl) & ~C_STROBE); } }/********************************************************************************* lptWrite - write to the port.** This routine is responsible for writing the requested number of bytes in* the buffer pointed to by pBuf out to the parallel port. If the board is* an entry level model ( no QSPAN present ) this routine will write the* data to the Parallel Interface Port (PIP) on the CPM. If the QSPAN chip* is present, it will write the data out via the parallel port on the Super* I/O chip.** RETURNS: The number of bytes written, or ERROR if the command didn't succeed.*/LOCAL int lptWrite ( LPT_DEV *pDev, char *pBuf, int size ) { LPT_DRV *pDrv = &lptDrvData[pDev->instance]; UINT immrVal = vxImmrGet (); PIP_TXBD *tx = (PIP_TXBD *) PIP_PARARAM; /* TX BD base addr */ UINT32 ackWait = ACK_TOUT; UINT32 rdata; int byteCnt = 0; int retry, wait, done = FALSE; if (size == 0) return (size); semTake (&pDrv->muteSem, WAIT_FOREVER); /* Check for printer busy. */ if (lptBusy(pDrv)) return (ERROR); retry = 0; if (!sysQspanPresent) { /* Output users static buffer via the PIP function. */ while (!done) { tx->pData = (UINT8 *)pBuf; tx->bdCsr |= 0x8000; /* Set BD Ready to Transmit */ if (size < MAX_PIP_CHARS) { tx->dataLen = size; /* load size */ done = TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -