📄 mbxlptdrv.c
字号:
else { tx->dataLen = MAX_PIP_CHARS; /* load size */ size -= MAX_PIP_CHARS; pBuf += MAX_PIP_CHARS; } /* Clear events register */ PIP_WRITE(*SMCE2(immrVal), ~0); /* issue restart transmit command */ pipCcr(CPM_CR_OPCODE_RESTART); /* synchronize all data */ syncdata(); /* Start PIP Transmit */ PIP_OR(*PIPC(immrVal), 0x8000); /* Wait for interrupt (on last character sent). */ if (semTake (&pDrv->syncSem, pDev->timeout * sysClkRateGet () * size) == ERROR) { errnoSet (S_ioLib_DEVICE_ERROR); semGive (&pDrv->muteSem); return (ERROR); } else { pDev->charsPrinted += size; while (lptBusy(pDrv)) /* do nothing */; if (done) { semGive (&pDrv->muteSem); return((PIP_TX(tx->bdCsr)) ? size : ERROR); } } } } else { do { wait = 0; sysOutByte (pDrv->data, *pBuf); /* assert strobe */ lptStrobe(pDrv,STB_ENABLE); /* wait for ACK, negate data strobe */ for(rdata = (UINT32)pDrv->lptRegRead (pDrv->stat), ackWait = ACK_TOUT; (!(rdata & pDrv->ackValue) & ackWait--); rdata = (UINT32)pDrv->lptRegRead(pDrv->stat)); if (ackWait != ACK_TOUT - 1) printf("ACK Failed to occur. Status: %x\r\n", rdata); /* Hold strobe */ while (wait != pDrv->strobeWait) wait++; /* Deassert strobe */ lptStrobe(pDrv,STB_DISABLE); if (semTake (&pDrv->syncSem, pDev->timeout * sysClkRateGet ()) == ERROR) { if (retry++ > pDev->retryCnt) { errnoSet (S_ioLib_DEVICE_ERROR); semGive (&pDrv->muteSem); return (ERROR); } } else { pBuf++; byteCnt++; pDev->charsPrinted++; } } while (byteCnt < size) /* do nothing */; semGive (&pDrv->muteSem); } return (size); }/********************************************************************************* lptIoctl - special device control** This routine handles LPT_SETCONTROL and LPT_GETSTATUS requests.** RETURNS: OK or ERROR if invalid request.*/LOCAL STATUS lptIoctl ( LPT_DEV *pDev, /* device to control */ int function, /* request code */ int arg /* some argument */ ) { LPT_DRV *pDrv = &lptDrvData[pDev->instance]; int status = OK; semTake (&pDrv->muteSem, WAIT_FOREVER); switch (function) { case LPT_SETCONTROL: pDrv->lptRegWrite (pDrv->ctrl, arg); break; case LPT_GETSTATUS: *(int *)arg = pDrv->lptRegRead (pDrv->stat); break; default: (void) errnoSet (S_ioLib_UNKNOWN_REQUEST); status = ERROR; break; } semGive (&pDrv->muteSem); return (status); }/********************************************************************************* lptIntr - handle an interrupt** This routine gets called to handle interrupts.* If there is another character to be transmitted, it sends it. If* not, or if a device has never been created for this channel, just* return.** RETURNS: none.**/LOCAL void lptIntr ( LPT_DEV *pDev ) { UINT immrVal = vxImmrGet (); LPT_DRV *pDrv = &lptDrvData[pDev->instance]; pDev->inservice = TRUE; pDev->intCnt++; pDev->inservice = FALSE; /* Clear PIP(SMC2) events register */ if (!sysQspanPresent) *SMCE2(immrVal) = ~0; semGive (&pDrv->syncSem); }/********************************************************************************* lptInit - initialize the specified LPT port** initialize the specified LPT port.** RETURNS: none.**/LOCAL void lptInit ( LPT_DRV *pDrv ) { UINT immrVal = vxImmrGet (); PIP_TXBD *tx = (PIP_TXBD *)PIP_PARARAM; /* TX BD base addr */ if (!sysQspanPresent) { /* issue stop transmit command */ pipCcr (CPM_CR_OPCODE_STOP); /* issue close receive buffer descriptor command */ pipCcr (CPM_CR_OPCODE_CLOSE); /* * Configure Transmit Buffer Descriptor * * Control and Status Register Settings: * Wrap=1 -- Final BD * Interrupt=1 -- Interrupts Generated * Last=1 -- Last (and only) Buffer Descriptor in Chain * * Data Length: 0 (reset) * */ tx->bdCsr = 0x3800; tx->dataLen = 0; /* Set SMC2 Transmitter Parameter RAM */ PIP_WRITE (*PIP_TBASE (PPC860_DPR_SMC2 (MPC860_DPRAM_BASE (immrVal))), (UINT)tx); /* Set PIP function code register to Moto byte mode */ PIP_WRITE (*PIP_CFCR (PPC860_DPR_SMC2 (MPC860_DPRAM_BASE (immrVal))), 0x15); /* Enable Fault, Sel */ PIP_WRITE (*PIP_SMASK (PPC860_DPR_SMC2 (MPC860_DPRAM_BASE (immrVal))), (1<<3)|(1<<1)); /* negate strobe (no false starts) */ PIP_OR (*PBDAT(immrVal), CPM_PIP_STB); /* Clear data lines */ PIP_AND (*PBDAT(immrVal), ~(0x0000FF00)); /* * configure the port lines (general-purpose I/O) * * inputs: * PB14 (ACK*) * PB28 (F*) * PB29 (PE) * PB30 (SEL) * PB31 (BSY) * outputs: * PB15 (STB*) * PB16-PB23 (DATA) */ PIP_AND (*PBDIR(immrVal), PIP_INPUTS); /* the inputs */ PIP_OR (*PBDIR(immrVal), PIP_OUTPUTS); /* the outputs */ PIP_AND (*PBPAR(immrVal), PIP_GPIO); /* general-purpose I/O */ /* * Configure PIP Timing Parameters Register * Assume Clock Period of 41 ns --> 24 MHz System Clock * According to Centronics Spec: TPAR1=TPAR2 >= 1.0 usec (25) */ PIP_WRITE (*PTPR(immrVal), (25<<8) |25); /* * PIP control register: * all data control and data movement is handled by the * CPU (i.e., host control) */ PIP_WRITE (*PIPC(immrVal), 0x0D); /* issue initialize Tx parameters command */ pipCcr (CPM_CR_OPCODE_INIT_T); /* * clear any previous interrupt status * disable all interrupts (polled mode) */ PIP_WRITE (*SMCE2(immrVal), 0xff); PIP_WRITE (*SMCM2(immrVal), 0x00); /* issue restart transmit command */ pipCcr (CPM_CR_OPCODE_RESTART); /* * Program CPM Command Register: * * INIT Transmit (SMC2) * * NOTE: Always issue this command after programming the PIP PRAM. * * wait for any pending commands to complete */ while (PIP_READ (*CPCR(immrVal)) & CPM_CR_FLG) /* do nothing */; /* issue command */ PIP_OR (*CPCR(immrVal), (CPM_CR_CHANNEL_PIP | (0x2<<8) | (0xd<<4) | CPM_CR_FLG)); /* wait for issued command to complete */ while (PIP_READ (*CPCR(immrVal)) & CPM_CR_FLG) /* do nothing */; /* Enable Interrupt on TX. */ PIP_WRITE (*SMCM2(immrVal), 0x01); } else { pDrv->lptRegWrite (pDrv->ctrl, 0); /* init */ if (pDrv->pDev->autofeed) pDrv->lptRegWrite (pDrv->ctrl, (C_ENABLE | C_NOINIT | C_SELECT | C_AUTOFEED)); else pDrv->lptRegWrite (pDrv->ctrl, (C_ENABLE | C_NOINIT | C_SELECT)); } }/********************************************************************************* pipCcr - execute channel command** This routine to execute a specified channel command. The channel command* register is read prior to execution to verify that there are no outstanding* commands, this is done by waiting for a zero status. The channel command* register is also read after the command execution to insure command* completion prior to returning.* * RETURNS: none*/ void pipCcr ( UINT32 cmd /* command to execute */ ) { UINT32 immrVal = vxImmrGet (); /* wait for any pending commands to complete */ while (PIP_READ (*CPCR(immrVal)) & CPM_CR_FLG) /* do nothing */; /* issue command */ PIP_WRITE(*CPCR (immrVal), (CPM_CR_CHANNEL_PIP | cmd | CPM_CR_FLG)); /* wait for issued command to complete */ while ( PIP_READ( *CPCR(immrVal)) & CPM_CR_FLG) /* do nothing */; return;}/********************************************************************************* lptShow - show LPT statistics** This routine shows statistics for a specified LPT port.** RETURNS: None*/void lptShow ( UINT channel /* channel (0 - 2) */ ) { LPT_DEV *pDev = &lptDevData[channel]; LPT_DRV *pDrv = &lptDrvData[channel]; if (channel > N_LPT_CHANNELS) return; printf ("controlReg = 0x%x\n", pDrv->lptRegRead (pDrv->ctrl)); printf ("statusize = 0x%x\n", pDrv->lptRegRead (pDrv->stat)); printf ("created = %s\n", pDev->created ? "TRUE" : "FALSE"); printf ("autofeed = %s\n", pDev->autofeed ? "TRUE" : "FALSE"); printf ("inservice = %s\n", pDev->inservice ? "TRUE" : "FALSE"); printf ("normalInt = %d\n", pDev->intCnt); printf ("retryCnt = %d\n", pDev->retryCnt); printf ("busyWait (loop) = %d\n", pDrv->busyWait); printf ("strobeWait (loop) = %d\n", pDrv->strobeWait); printf ("timeout (sec) = %d\n", pDev->timeout); printf ("intLevel (IRQ) = %d\n", pDev->intLevel); printf ("charsPrinted = %d\n", pDev->charsPrinted); }/********************************************************************************* pipIoctl - I/O control** This routine performs the specified PIP IO actions.** The parameter `ioctlflg' specifies the type of IO to be performed, and may* be set to any one of the following,** .CS* PIP_IOCTL_W -- write* PIP_IOCTL_R -- read* PIP_IOCTL_O -- read/or/write* PIP_IOCTL_A -- read/and/write* PIP_IOCTL_AO -- read/and/or/write* .CE** Parameter `pReg' specifies the register address, `size' is the register size* in bytes (1, 2, or 4), `wdata1' is the data to write #1 and is not used for* a read operation, `wdata2' is the data to write #2 and is also not used for* a read operation.** RETURNS: data read on a read operation, and zero for non-read.*/LOCAL UINT pipIoctl ( UINT ioctlflg, /* io control flag */ UINT pReg, /* register pointer */ UINT size, /* register size (1/2/4 bytes) */ UINT wdata1, /* write data #1 */ UINT wdata2 /* write data #2 */ ) { UINT rdata; UINT8 *pReg1; UINT16 *pReg2; register UINT*pReg4; rdata = 0; /* make the compiler happy */ switch (size) { case 1: pReg1 = (UINT8 *)pReg; switch (ioctlflg) { case PIP_IOCTL_W: /* write */ *pReg1 = wdata1; break; case PIP_IOCTL_R: /* read */ rdata = *pReg1; break; case PIP_IOCTL_O: /* read/or/write */ *pReg1 |= wdata1; break; case PIP_IOCTL_A: /* read/and/write */ *pReg1 &= wdata1; break; case PIP_IOCTL_AO: /* read/and/or/write */ *pReg1 = (*pReg1 & wdata1) | wdata2; break; } break; case 2: pReg2 = (UINT16 *)pReg; switch (ioctlflg) { case PIP_IOCTL_W: /* write */ *pReg2 = wdata1; break; case PIP_IOCTL_R: /* read */ rdata = *pReg2; break; case PIP_IOCTL_O: /* read/or/write */ *pReg2 |= wdata1; break; case PIP_IOCTL_A: /* read/and/write */ *pReg2 &= wdata1; break; case PIP_IOCTL_AO: /* read/and/or/write */ *pReg2 = (*pReg2 & wdata1) | wdata2; break; } break; case 4: pReg4 = (UINT *)pReg; switch (ioctlflg) { case PIP_IOCTL_W: /* write */ *pReg4 = wdata1; break; case PIP_IOCTL_R: /* read */ rdata = *pReg4; break; case PIP_IOCTL_O: /* read/or/write */ *pReg4 |= wdata1; break; case PIP_IOCTL_A: /* read/and/write */ *pReg4 &= wdata1; break; case PIP_IOCTL_AO: /* read/and/or/write */ *pReg4 = (*pReg4 & wdata1) | wdata2; break; } break; } /* synchronize all data */ syncdata (); return (rdata); }#ifdef DEBUG_LPT/********************************************************************************* lptDebug - PIP/FDC LPT Debug Function** This routine continuously sends all printable characters to printer.**/UINT lptDebug ( UINT channel /* channel (0 - 2) */ ) { UINT8 ii; LPT_DRV *pDrv; pDrv = &(lptDrvData[channel]); FOREVER { /* Fill buffer */ for(ii=0; ii<60; ii++) debugBuf[ii] = ii + 0x41; debugBuf[ii++] = CR; debugBuf[ii++] = NL; lptWrite(pDrv->pDev,debugBuf,62); } return (0); }#endif /* defined(DEBUG_LPT) */#endif /* defined(INCLUDE_LPT) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -