📄 ncr710lib2.c
字号:
ncr710IdentThreadInit ((NCR710_THREAD *) pScsiCtrl->pIdentThread); /* spawn SCSI manager - use generic code from "scsiLib.c" */ pScsiCtrl->scsiMgrId = taskSpawn (ncr710ScsiTaskName, ncr710ScsiTaskPriority, ncr710ScsiTaskOptions, ncr710ScsiTaskStackSize, (FUNCPTR) scsiMgr, (int) pSiop, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (pScsiCtrl->scsiMgrId == ERROR) { SCSI_MSG ("ncr710CtrlCreateScsi2: can't spawn SCSI manager task\n", 0, 0, 0, 0, 0, 0); goto failed; } return (pSiop);failed: if (pSiop->singleStepSem != NULL) (void) semDelete (pSiop->singleStepSem); (void) cacheDmaFree ((char *) pSiop); return (NULL); }/********************************************************************************* ncr710CtrlInitScsi2 - initialize a control structure for the NCR 53C710 SIOP** This routine initializes an SIOP structure after the structure is created* with ncr710CtrlCreateScsi2(). This structure must be initialized before the* SIOP can be used. It may be called more than once if needed; however,* it must only be called while there is no activity on the SCSI interface.** A detailed description of the input parameters follows:* .iP <pSiop>* a pointer to the NCR_710_SCSI_CTRL structure created with* ncr710CtrlCreateScsi2().* .iP <scsiCtrlBusId>* the SCSI bus ID of the SIOP. Its value is somewhat arbitrary: seven (7),* or highest priority, is conventional. The value must be in the range 0 - 7.* .iP <scsiPriority>* this parameter is ignored. All SCSI I/O is now done in the context of* the SCSI manager task; if necessary, the priority of the manager task may be* changed using taskPrioritySet() or by setting the value of the global* variable `ncr710ScsiTaskPriority' before calling ncr710CtrlCreateScsi2().* .LP** RETURNS: OK, or ERROR if the parameters are out of range.** SEE ALSO: ncr710CtrlCreateScsi2()*/STATUS ncr710CtrlInitScsi2 ( FAST NCR_710_SCSI_CTRL *pSiop, /* ptr to SIOP struct */ int scsiCtrlBusId, /* SCSI bus ID of this SIOP */ int scsiPriority /* task priority when doing SCSI I/O */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; /* * Validate parameters */ if (pSiop == (SIOP *)NULL) return (ERROR); /* * Validate and set bus ID */ if (scsiCtrlBusId < SCSI_MIN_BUS_ID || scsiCtrlBusId > SCSI_MAX_BUS_ID) return (ERROR); pScsiCtrl->scsiCtrlBusId = scsiCtrlBusId; /* * Initialise the SIOP */ ncr710HwInit (pSiop); ncr710ScriptStart (pSiop, (NCR710_THREAD *) pScsiCtrl->pIdentThread, NCR710_SCRIPT_WAIT); pSiop->state = NCR710_STATE_PASSIVE; return (OK); }/********************************************************************************* ncr710HwInit - initialize the SIOP chip to a known state** This routine puts the SIOP into a known quiescent state. Because the value* of some registers depend upon the hardware implementation of the chip you * may have to use ncr710SetHwRegister() to adjust them.** This routine does not touch the bits in registers that are set by * the ncr710SetHwRegister() routine.** See the NCR 53C710 Data Manual for fuller details of the registers* programmed by this routine.** SEE ALSO * ncr710SetHwRegister()** NOMANUAL*/LOCAL void ncr710HwInit ( FAST SIOP *pSiop /* ptr to an SIOP info structure */ ) { UINT clkPeriod; /* * Software reset the SIOP */ *pSiop->pIstat = B_SOFTRST; *pSiop->pIstat = 0; /* * Initialise hardware-dependent registers */ ncr710SetHwRegisterScsi2 (pSiop, &pSiop->hwRegs); /* * DMA mode, control and watchdog timer registers * * Use manual start and NCR 53C700 compatibility mode. * Set clock conversion factor (the clkPeriod has been checked in * "ncr710CtrlCreate()") and save async clock period for use by * "ncr710XferParamsCvt()". Disable the watchdog timer. */ *pSiop->pDwt = 0; *pSiop->pDmode |= B_MAN; *pSiop->pDcntl |= B_COM; clkPeriod = pSiop->clkPeriod; if (clkPeriod >= NCR710_25MHZ) /* 16.67 - 25.00 MHz */ { *pSiop->pDcntl |= NCR710_16MHZ_DIV; pSiop->asyncClkPeriod = clkPeriod; } else if (clkPeriod >= NCR710_3750MHZ) /* 25.01 - 37.50 MHz */ { *pSiop->pDcntl |= NCR710_25MHZ_DIV; pSiop->asyncClkPeriod = clkPeriod * 3 / 2; } else if (clkPeriod >= NCR710_50MHZ) /* 37.51 - 50.00 MHz */ { *pSiop->pDcntl |= NCR710_50MHZ_DIV; pSiop->asyncClkPeriod = clkPeriod * 2; } else /* (clkPeriod >= NCR710_6666MHZ) */ /* 50.01 - 66.67 MHz */ { *pSiop->pDcntl |= NCR710_66MHZ_DIV; pSiop->asyncClkPeriod = clkPeriod * 3; } /* * SCSI control registers * * If disconnect/reconnect is enabled, use full arbitration. * Always generate parity; check for parity if required to do so. * Set slow cable mode if specified. */ *pSiop->pScntl0 = B_EPG; *pSiop->pScntl1 = 0; if (pSiop->scsiCtrl.disconnect) { *pSiop->pScntl0 |= (B_ARB1 | B_ARB0); *pSiop->pScntl1 |= B_ESR; } if (pSiop->parityCheckEnbl) *pSiop->pScntl0 |= B_EPC; if (pSiop->slowCableMode) *pSiop->pScntl1 |= B_EXC; /* * Chip test registers * * Enable active negation (needed for fast SCSI) */ *pSiop->pCtest0 = B_EAN; /* * Set own SCSI bus ID (checked in "ncr710CtrlInit()") */ *pSiop->pScid = (1 << pSiop->scsiCtrl.scsiCtrlBusId); /* * Enable relevant SCSI and DMA interrupts (see "ncr710EventTypeGet()") * * Note: in target mode the phase mismatch interrupt (B_MA) is used to * signal assertion of ATN. Currently we cannot handle this either in * this library or in the script. Therefore, the script automatically * disables this interrupt in target mode and enables it (for phase * mismatch) in initiator mode. Also see "ncr710EventTypeGet()". */ *pSiop->pSien = (B_STO | B_SGE | B_UDC | B_RSTE | B_PAR); *pSiop->pDien = (B_BF | B_ABT | B_SIR | B_WTD | B_IID); }/********************************************************************************* ncr710SetHwRegisterScsi2 - set hardware-dependent registers for the NCR 53C710** This routine sets up the registers used in the hardware* implementation of the chip. Typically, this routine is called by * the sysScsiInit() routine from the BSP. ** The input parameters are as follows:* .iP <pSiop> 4* a pointer to the NCR_710_SCSI_CTRL structure created with* ncr710CtrlCreateScsi2().* .iP <pHwRegs>* a pointer to a NCR710_HW_REGS structure that is filled with the logical* values 0 or 1 for each bit of each register described below.** This routine includes only the bit registers that can be used to modify * the behavior of the chip. The default configuration used during * ncr710CtlrCreateScsi2() and ncr710CrtlInitScsi2() is * {0,0,0,0,1,0,0,0,0,0,0,0,0,1,0}.**.CS* typedef struct* {* int ctest4Bit7; /@ Host bus multiplex mode @/* int ctest7Bit7; /@ Disable/enable burst cache capability @/* int ctest7Bit6; /@ Snoop control bit1 @/* int ctest7Bit5; /@ Snoop control bit0 @/* int ctest7Bit1; /@ invert tt1 pin (sync bus host mode only)@/* int ctest7Bit0; /@ enable differential scsi bus capability@/* int ctest8Bit0; /@ Set snoop pins mode @/* int dmodeBit7; /@ Burst Length transfer bit 1 @/* int dmodeBit6; /@ Burst Length transfer bit 0 @/* int dmodeBit5; /@ Function code bit FC2 @/* int dmodeBit4; /@ Function code bit FC1 @/* int dmodeBit3; /@ Program data bit (FC0) @/* int dmodeBit1; /@ user programmable transfer type @/* int dcntlBit5; /@ Enable Ack pin @/* int dcntlBit1; /@ Enable fast arbitration on host port @/* } NCR710_HW_REGS;**.CE* For a more detailed explanation of the register bits, refer to the* .I "NCR 53C710 SCSI I/O Processor Programming Guide."** NOTE* Because this routine writes to the chip registers you cannot use it* if there is any SCSI bus activity.** RETURNS: OK, or ERROR if any input parameter is NULL.** SEE ALSO: ncr710CtrlCreateScsi2(), * .I "NCR 53C710 SCSI I/O Processor Programming Guide"*/STATUS ncr710SetHwRegisterScsi2 ( FAST SIOP *pSiop, /* pointer to SIOP info */ NCR710_HW_REGS *pHwRegs /* pointer to a NCR710_HW_REGS info */ ) { /* check input parameters */ if ((pSiop == NULL) || (pHwRegs == NULL)) return (ERROR); /* fill the SIOP structure with new parameters */ bcopy ((char *)pHwRegs, (char *) &pSiop->hwRegs, sizeof(NCR710_HW_REGS)); /* Set each bit register to the new value */ /* This bit must be set first else the chip will not anwser to a slave * access in some hardware implementations. */ ((pHwRegs->dcntlBit5) ? (*pSiop->pDcntl = B_EA) : (*pSiop->pDcntl = 0)); ((pHwRegs->ctest4Bit7) ? (*pSiop->pCtest4 |= B_MUX) : (*pSiop->pCtest4 &= ~B_MUX)); ((pHwRegs->ctest7Bit7) ? (*pSiop->pCtest7 |= B_CDIS) : (*pSiop->pCtest7 &= ~B_CDIS)); ((pHwRegs->ctest7Bit6) ? (*pSiop->pCtest7 |= B_SC1) : (*pSiop->pCtest7 &= ~B_SC1)); ((pHwRegs->ctest7Bit5) ? (*pSiop->pCtest7 |= B_SC0) : (*pSiop->pCtest7 &= ~B_SC0)); ((pHwRegs->ctest7Bit1) ? (*pSiop->pCtest7 |= B_TT1) : (*pSiop->pCtest7 &= ~B_TT1)); ((pHwRegs->ctest7Bit0) ? (*pSiop->pCtest7 |= B_DIFF) : (*pSiop->pCtest7 &= ~B_DIFF)); ((pHwRegs->ctest8Bit0) ? (*pSiop->pCtest8 |= B_SM) : (*pSiop->pCtest8 &= ~B_SM)); ((pHwRegs->dmodeBit7) ? (*pSiop->pDmode |= B_BL1) : (*pSiop->pDmode &= ~B_BL1)); ((pHwRegs->dmodeBit6) ? (*pSiop->pDmode |= B_BL0) : (*pSiop->pDmode &= ~B_BL0)); ((pHwRegs->dmodeBit5) ? (*pSiop->pDmode |= B_FC2) : (*pSiop->pDmode &= ~B_FC2)); ((pHwRegs->dmodeBit4) ? (*pSiop->pDmode |= B_FC1) : (*pSiop->pDmode &= ~B_FC1)); ((pHwRegs->dmodeBit3) ? (*pSiop->pDmode |= B_PD) : (*pSiop->pDmode &= ~B_PD)); ((pHwRegs->dmodeBit1) ? (*pSiop->pDmode |= B_U0TT0) : (*pSiop->pDmode &= ~B_U0TT0)); ((pHwRegs->dcntlBit1) ? (*pSiop->pDcntl |= B_FA) : (*pSiop->pDcntl &= ~B_FA)); return (OK); }/********************************************************************************* ncr710ScsiBusControl - miscellaneous low-level SCSI bus control operations** Currently supports only the SCSI_BUS_RESET operation; other operations are* not used explicitly by the driver because they are carried out automatically* by the script program.** NOTE: after the SCSI bus has been reset, the SIOP generates an interrupt* which causes an NCR710_BUS_RESET event to be sent to the SCSI manager.* See "ncr710Intr()".** RETURNS: OK, or ERROR if an invalid operation is requested.** NOMANUAL*/LOCAL STATUS ncr710ScsiBusControl ( SIOP * pSiop, /* ptr to controller info */ int operation /* bitmask for operation(s) to be performed */ ) { if ((operation & ~SCSI_BUS_RESET) != 0) return (ERROR); if (operation & SCSI_BUS_RESET) ncr710ScsiBusReset (pSiop); return (OK); }/********************************************************************************* ncr710ScsiBusReset - assert the RST line on the SCSI bus ** Issue a SCSI Bus Reset command to the NCR 710. This should put all devices* on the SCSI bus in an initial quiescent state.** The bus reset will generate an interrupt which is handled by the normal* ISR (see "ncr710Intr()").** RETURNS: N/A** NOMANUAL*/LOCAL void ncr710ScsiBusReset ( FAST SIOP *pSiop /* ptr to SIOP info */ ) { *pSiop->pScntl1 |= B_RST; taskDelay (2); /* pause for at least 250 us */ *pSiop->pScntl1 &= ~B_RST; }/********************************************************************************* ncr710IntrScsi2 - interrupt service routine for the SIOP** Find the event type corresponding to this interrupt, and carry out any* actions which must be done before the SIOP is re-started. Determine* whether or not the SIOP is connected to the bus (depending on the event* type - see note below). If not, start a client script if possible or* else just make the SIOP wait for something else to happen.** Notify the SCSI manager of a controller event.** NOTE:* The "connected" Boolean tells whether there is a SCSI thread in progress* which must be continued before any other SCSI activity can occur. In* principle, it might seem that reading the appropriate bit in the SIOP's* SCNTL1 register would be better than inferring the value from the interrupt* code.** However, the SCNTL1 register may change between the time the script* completes (generates the interrupt) and the time it is read - for example,* if the SIOP is reselected immediately after generating a DISCONNECTED* interrupt.** Because the action taken by the ISR depends critically on what will happen* in software as a result of the current interrupt, and _not_ on the current* state of the SIOP hardware, if the hardware "connected" bit were used, the* above scenario would cause the ISR to fail to re-start a script when in* fact it should do. The result would be that the SIOP would forever remain
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -