/************************************************************************* * * Copyright (c) 1995-1998 Workbit Corporation * * Module Name: * * nin.c * * Abstract: * * Definitions for the Ninja SCSI-3 CARD * ****************************************************************************/ #include "nin.h" /*#define DBG 1 *//* for debug*/ #define USE_INTENTRY #define USE_IRQ_MASK #define USE_DISCONECT #include #ifdef KERNEL /* don't laugh.. look for main() */ #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* KERNEL */ #include #include #include #ifdef KERNEL #include #else /*KERNEL */ #define NAHA 1 #endif /*KERNEL */ #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) /* #include "scsi.h" */ #define BASE_PORT 0x180 #define NUMBR_PORTS 0x10 #define BASE_WIDTH 0x10 #define SCSI_PORT 0x0 /********************************************************/ /* Input status bit definitions.*/ /********************************************************/ #define S_ATN 0x80 #define S_SELECT 0x40 #define S_REQUEST 0x20 /* Request line from SCSI bus*/ #define S_ACK 0x10 /* Acknowlege line from SCSI bus*/ #define S_BUSY 0x08 /* Busy line from SCSI bus*/ #define S_CD 0x04 /* Command/Data line from SCSI bus*/ #define S_IO 0x02 /* Input/Output line from SCSI bus*/ #define S_MESSAGE 0x01 /* Message line from SCSI bus*/ /********************************************************/ /* Useful Bus Monitor status combinations.*/ /********************************************************/ #define BM_BUS_FREE 0 #define BM_COMMAND ( S_BUSY | S_CD | S_REQUEST ) #define BM_MESSAGE_IN ( S_BUSY | S_MESSAGE | S_IO | S_CD | S_REQUEST ) #define BM_MESSAGE_OUT ( S_BUSY | S_MESSAGE | S_CD | S_REQUEST ) #define BM_DATA_IN ( S_BUSY | S_IO | S_REQUEST ) #define BM_DATA_OUT ( S_BUSY | S_REQUEST ) #define BM_STATUS ( S_BUSY | S_IO | S_CD | S_REQUEST ) #define BM_RESELECT ( S_SELECT | S_IO ) #define BP_COMMAND ( S_CD ) #define BP_MESSAGE_IN ( S_MESSAGE | S_IO | S_CD ) #define BP_MESSAGE_OUT ( S_MESSAGE | S_CD ) #define BP_DATA_IN ( S_IO ) #define BP_DATA_OUT ( 0 ) #define BP_STATUS ( S_IO | S_CD ) /********************************************************/ /* SCSI bus status codes.*/ /********************************************************/ /* Status Byte in scsiall.h*/ #define SCSI_CONDITION_MET 0x04 #define SCSI_INTERMEDIATE_COND_MET 0x14 #define SCSI_RESERVATION_CONFLICT 0x18 #define SCSI_COMMAND_TERMINATED 0x22 #define MSG_IDENTIFYFLAG_WITH_DISCON 0XC0 /********************************************************/ /* SCSI Extended Message Lengths*/ /********************************************************/ #define SCSIMESS_MODIFY_DATA_LENGTH 5 #define SCSIMESS_SYNCH_DATA_LENGTH 3 #define SCSIMESS_WIDE_DATA_LENGTH 2 /********************************************************/ /* SCSI Extended Message operation codes*/ /********************************************************/ #define SCSIMESS_MODIFY_DATA_POINTER 0X00 #define SCSIMESS_SYNCHRONOUS_DATA_REQ 0X01 #define SCSIMESS_WIDE_DATA_REQUEST 0X03 typedef struct _SCSI_EXMSG { u_char InitialMessageCode; u_char MessageLength; u_char MessageType; union _EXTENDED_ARGUMENTS { struct { u_char modifier[4]; } MODIFY; struct { u_char TransferPeriod; u_char ReqAckOffset; } SYNCS; struct{ u_char Width; } WIDE; }ExArg; }SCSI_EXMSG, *PSCSI_EXMSG; /********************************************************/ /* Status mask for bus phase.*/ /********************************************************/ #define S_PHASE_MASK ((u_char) 0x3f) /********************************************************/ /* SCSI source identifier for host system.*/ /********************************************************/ #define SCSI_INITIATOR_ID 7 #define SCSI_IDT_VECTOR 5 /********************************************************/ /* Various timeout values (in microseconds).*/ /********************************************************/ #define REQUEST_SPIN_WAIT 40000 /* Wait for target to assert REQUEST*/ #define RESET_HOLD_TIME 25 /* Time to hold RESET line to reset bus*/ #define RESET_RECOVER_TIME 2500000 #define BUS_FREE_DELAY 100000 /* Wait for BUS_FREE condition*/ /********************************************************/ /* Number of adapters this driver will support.*/ /********************************************************/ #define MAX_ADAPTERS 1 /********************************************************/ /* Limit transfer length to 64 Kbytes*/ /* */ #define MAX_TRANSFER_LENGTH ( 64 * 1024 ) #ifdef DBG long INT_POLL_SEL = 10; long INT_POLL_IRQ = 10; #else #define INT_POLL_SEL 10 #define INT_POLL_IRQ 10 #endif typedef struct _IRQ_STATUS { /* #0*/ u_char ScsiIrqStatus : 1; u_char ExtIrqStatus : 1; u_char TimerIrqStatus : 1; u_char FifoIrqStatus : 1; u_char ScsiIrqMask : 1; u_char ExtIrqMask : 1; u_char TimerIrqMask : 1; u_char FifoIrqMask : 1; } IRQ_STATUS, *PIRQ_STATUS; typedef struct _IRQ_CONTROLP { /* #0*/ u_char ReselctIrqClear : 1; u_char PhaseChgIrqClear : 1; u_char TimerIrqClear : 1; u_char FifoIrqClear : 1; u_char ScsiIrqMask : 1; u_char ExtIrqMask : 1; u_char TimerIrqMask : 1; u_char FifoIrqMask : 1; } IRQ_CONTROLP, *PIRQ_CONTROLP; typedef struct _IF_SELECT { /* #1*/ u_char IFSelect : 1; u_char Reserved3 : 1; u_char RegSelect : 1; u_char Reserved2 : 5; } IF_SELECT, *PIF_SELECT; typedef struct _FIFO_STATUS { /* #1*/ u_char ChipRev : 4; u_char ChipId : 3; u_char FifoFullEmpty : 1; } FIFO_STATUS, *PFIFO_STATUS; typedef struct _EXT_BUS_CONTROL { /* index 10h*/ u_char Reserved0 : 4; u_char IOMapConfigration : 1; u_char ExrdyContrl : 1; u_char IrqLevel : 1; u_char Reserved1 : 1; } EXT_BUS_CONTROL, *PEXT_BUS_CONTROL; typedef struct CLOCK_DIV { /* index 11h*/ u_char ClkDivider : 2; u_char Reserved6 : 6; } CLOCK_DIV, *PCLOCK_DIV; typedef struct _TermPwrControl { /* index 13*/ u_char TermPowerOn : 1; u_char Reserved7 : 7; } TermPwrControl, *PTermPwrControl; typedef struct _SCSI_IRQ_MODE { /* index 15*/ u_char ScsiPhaseChangeEi : 1; u_char Reserved8 : 3; u_char ReselectIrqEi : 1; u_char FifoIrqEi : 1; u_char ScsiResetIrqEi : 1; u_char Reserved75 : 1; } SCSI_IRQ_MODE, *PSCSI_IRQ_MODE; typedef struct _IRQ_PHASE_SENSE { /* index 16*/ u_char LatchMSG : 1; u_char LatchI_O : 1; u_char LatchC_D : 1; u_char LatchBusFree : 1; u_char PhaseChgIrq : 1; u_char ReselectIrq : 1; u_char FifoIrq : 1; u_char ScsiResetIrq : 1; } IRQ_PHASE_SENSE, *PIRQ_PHASE_SENSE; typedef struct SCSI_BUS_CONTROL { /* index 18*/ u_char ScsiSel : 1; u_char ScsiRst : 1; u_char ScsiDataOutEnb : 1; u_char ScsiATN : 1; u_char ScsiACK : 1; u_char ScsiBSY : 1; u_char AutoDirection : 1; u_char AckEnb : 1; } SCSI_BUS_CONTROL, *PSCSI_BUS_CONTROL; typedef struct _SCSI_BUS_MONITOR { /* index 19*/ u_char Scsi_MSG : 1; u_char Scsi_I_O : 1; u_char Scsi_C_D : 1; u_char Scsi_BSY : 1; u_char Scsi_ACK : 1; u_char Scsi_REQ : 1; u_char Scsi_SEL : 1; u_char Scsi_ATN : 1; } SCSI_BUS_MONITOR, *PSCSI_BUS_MONITOR; typedef struct _SET_ARBIT { /* index 1a*/ u_char ArbitGo : 1; u_char ArbitFlagClear : 1; u_char Reserved10 : 6; } SET_ARBIT,*PSET_ARBIT; typedef struct _ARBIT_STATUS { /* index 1a*/ u_char ArbitGoStatus : 1; u_char ArbitWin : 1; u_char ArbitFail : 1; u_char ReselectFlag : 1; u_char Reserved11 : 4; } ARBIT_STATUS, *PARBIT_STATUS; typedef struct _PARITY_CONTROL { /* index 1b*/ u_char ParityCheckEnable : 1; u_char ParityErrorClear : 1; u_char Reserved12 : 6; } PARITY_CONTROL, *PPARITY_CONTROL; typedef struct _PARITY_STATUS { /* index 1b*/ u_char Reserved15 : 1; /* same as PARITY_CONTROL*/ u_char ParityError : 1; u_char Reserved14 : 2; u_char ReadSource : 2; u_char Reserved13 : 2; } PARITY_STATUS, *PPARITY_STATUS; typedef struct _COMMAND_CONTROL { /* index 1c*/ u_char ClrCommandPointer : 1; u_char AutoCommandGo : 1; u_char Reserved16 : 6; } COMMAND_CONTROL, *PCOMMAND_CONTROL; typedef struct _POINTER_CLEAR { /* index 1e*/ u_char PointerClear : 1; u_char AckCounterClear : 1; u_char ReqCounterClear : 1; u_char HostCounterClear : 1; u_char ReadSourceSet : 2; u_char Reserved17 : 2; } POINTER_CLEAR, *PPOINTER_CLEAR; typedef struct _TRANSFER_MODE { /* index 20*/ u_char MemMap8 : 1; u_char MemMap16_32 : 1; u_char AdrData24 : 1; u_char AdrData32 : 1; u_char IO8 : 1; u_char IO16_32 : 1; u_char TransferGo : 1; u_char FifoTest_Braind : 1; } TRANSFER_MODE, *PTRANSFER_MODE; typedef struct _SYNC_REG { /* index 21*/ u_char SyncOffset : 4; u_char SyncPeriod : 4; } SYNC_REG, *PSYNC_REG; typedef struct _SCAM_CONTROL { /* index 24*/ u_char ScamMSG : 1; u_char ScamI_O : 1; u_char ScamC_D : 1; u_char ScamBSY : 1; u_char ScamSEL : 1; u_char ScamXferOn : 1; u_char Reserved18 : 2; } SCAM_CONTROL, *PSCAM_CONTROL; typedef struct _OTHER_CONTROL { /* index 26*/ u_char TplRomWriteEnable : 1; u_char TermPwrOut : 1; u_char TermPwrSence : 1; u_char Reserved19 : 5; } OTHER_CONTROL, *POTHER_CONTROL; typedef struct _ACK_WIDTH { /* index 27*/ u_char AckPulse : 2; u_char Reserved20 : 6; } ACK_WIDTH, *PACK_WIDTH; typedef struct _CHECK_SUM_CONTROL { /* index 2c*/ u_char CheckSumClear : 1; u_char ReadPointerClear : 1; u_char Reserved21 : 6; } CHECK_SUM_CONTROL, *PCHECK_SUM_CONTROL; #define IN #define OUT #define IRQCONTROL 0 #define IRQSTATUS 0 #define IFSELECT 1 #define FIFOSTATUS 0x1 #define INDEXREG 0x2 #define DATAREG 0x3 #define FIFODATA 0x4 #define FIFODATA1 0x5 #define FIFODATA2 0x6 #define FIFODATA3 0x7 #define WFIFODATA 0x4 #define EXTBUSCTRL 0x10 #define CLOCKDIV 0x11 #define TERMPWRCTRL 0x13 #define SCSIIRQMODE 0x15 #define IRQPHASESENCE 0x16 #define TIMERCOUNT 0x17 #define SCSIBUSCTRL 0x18 #define SCSIBUSMON 0x19 #define SETARBIT 0x1A #define ARBITSTATUS 0x1A #define PARITYCTRL 0x1B #define PARITYSTATUS 0x1B #define COMMANDCTRL 0x1C #define RESELECTID 0x1C #define COMMANDDATA 0x1D #define POINTERCLR 0x1E #define TRANSFERCOUNT 0x1E /* #define Reserved3*/ #define TRANSFERMODE 0x20 #define SYNCREG 0x21 #define SCSIDATALATCH 0x22 #define SCSIDATAIN 0x22 #define SCSIDATAWITHACK 0x23 #define SCAMCONTROL 0x24 #define SCAMSTATUS 0x24 #define SCAMDATA 0x25 #define OTHERCONTROL 0x26 #define ACKWIDTH 0x27 #define CLRTESTPNT 0x28 #define ACKCNTLD 0x29 #define REQCNTLD 0x2A #define HSTCNTLD 0x2B #define CHECKSUM 0x2C #define SCSI_IRQ_CONTROL(BASE,VALUE) \ outb((BASE+IRQCONTROL), VALUE) #define SCSI_IRQ_MONITOR(BASE) \ inb(BASE+IRQCONTROL) #define SCSI_IF_SELECT(BASE, VALUE) \ outb((BASE+IFSELECT), VALUE) #define SCSI_FIFO_STATUS(BASE) \ inb((BASE+FIFOSTATUS)) #define SCSI_READ_FIFO(BASE,BUFFER,COUNT) \ insb((BASE+FIFODATA), (u_char *)BUFFER, COUNT) #define SCSI_WRITE_FIFO(BASE,BUFFER,COUNT) \ outsb((BASE+FIFODATA), (u_char *)BUFFER, COUNT) #define SCSI_READ_FIFOW(BASE,BUFFER,COUNT) \ insw((BASE+WFIFODATA), (u_int32_t *)BUFFER, (COUNT >> 1)) #define SCSI_WRITE_FIFOW(BASE,BUFFER,COUNT) \ outsw((BASE+WFIFODATA ), (u_int32_t *)BUFFER, (COUNT >> 1)) #define SCSI_READ_FIFOD(BASE,BUFFER,COUNT) \ insl((BASE+WFIFODATA), BUFFER, (COUNT >> 2)) #define SCSI_WRITE_FIFOD(BASE,BUFFER,COUNT) \ outsl((BASE+WFIFODATA ), BUFFER, (COUNT >> 2)) #define SCSI_READ(ChipAddr,Register) ( \ outb(ChipAddr+INDEXREG,Register),\ inb(ChipAddr+DATAREG)\ ) #define SCSI_WRITE(ChipAddr,Register,Value) { \ outb(ChipAddr+INDEXREG,Register),\ outb(ChipAddr+DATAREG,Value);\ } #define READ_XFER_CNT 512 #define WRITE_BURST_CNT 512 /*64*/ #define WRITE_SPOT_CNT 512 #define ASYNCHRONOUS_OFFSET 0 #define ASYNCHRONOUS_PERIOD 0 #define SYNCHRONOUS_OFFSET 15 #ifdef ULTRA #define SYNCHRONOUS_PERIOD 0x0c #else #define SYNCHRONOUS_PERIOD 0x19 #endif #define SYNCHRONOUS_PERIOD_10M 0x19 #define SYNCHRONOUS_PERIOD_20M 0x0c typedef struct _SYNC_TABLE { u_char StartPeriod; u_char EndPeriod; u_char TransferPeriod; u_char AckWidth; } SYNC_TABLE, *PSYNC_TABLE; #ifndef NT_INST /* for PC CARD*/ typedef struct _PWRENTRY { u_char PowerLevel; u_char ValidSignals; } PWRENTRY; typedef struct _ACHARTBL { char AdpCaps; long ActiveHigh; long ActiveLow; } ACHARTBL; typedef struct _AINQADAPTOR { char wBufferLength; char wDataLength; ACHARTBL CharTable; char wNumPwrEntries; PWRENTRY PwrEntry; } AINQADAPTOR; #endif typedef struct _SG_TABLE { u_long BlockCount; u_long BufferAddress; } SG_TABLE, *PSG_TABLE; typedef struct _FIFO_TEST { u_char XferMode; u_char Rate; } FIFO_TEST; typedef FIFO_TEST *PFIFO_TEST; typedef struct _FAST_MODE { u_char XferMode; u_char Rate; u_char PcicTiming; u_char MemorySpeed; } FAST_MODE; typedef FAST_MODE *PFAST_MODE; /********************************************************/ /* Logical Unit states.*/ /********************************************************/ typedef enum _SCSI_STATE { SC_UNDETERMINED, SC_SELECT, SC_COMMAND, SC_DATA, SC_STATUS, SC_MSG_IN, SC_MSG_OUT, SC_COMPLETE, SC_COMPLETE_OK, SC_BUSFREE, SC_DISCONNECT, SC_RESELECT } SCSI_STATE, *PSCSI_STATE; /* #pragma pack(4) */ /********************************************************/ /* Logical Unit extension*/ /********************************************************/ typedef struct _SPECIFIC_LU_EXTENSION { SCSI_STATE LuState; /* State information.*/ char *SavedDataPointer; /* Current data pointer.*/ u_long SavedDataLength; /* Current data lenght.*/ struct scsi_xfer *ActiveLuRequest; /* Active Srb for this LUN.*/ u_long PhaseWaitCounter; u_long TransferedLength; u_long AckCounter; u_long HostCounter; void (*pXferRead)__P(( u_int,char *Buffer, size_t Length)); void (*pXferWrite)__P(( u_int, char *Buffer, size_t Length)); /* SG_TABLE SG_LIST[18]; */ u_long SG_Count; } SPECIFIC_LU_EXTENSION, *PSPECIFIC_LU_EXTENSION; /********************************************************/ /*define adapter type*/ /********************************************************/ #define OPT_NON_DISCONECT 0x0001 #define OPT_TUNEUP_DI 0x0002 #define OPT_PCIC_SPEED 0x0004 #define OPT_MMIO_SPEED 0x0008 #define OPT_NO_ATN 0x0010 /********************************************************/ /* specific per target controller information.*/ /********************************************************/ typedef struct _SPECIFIC_TARGET_EXTENSION { u_char TargetFlags; u_char SynchronousPeriod; u_char SynchronousOffset; u_char AckWidth; } SPECIFIC_TARGET_EXTENSION, *PSPECIFIC_TARGET_EXTENSION; /********************************************************/ /* Define target controller specific flags.*/ /********************************************************/ #define PD_SYNCHRONOUS_NEGOTIATION_DONE 0x0001 #define PD_DO_NOT_NEGOTIATE 0x0002 #define PD_SYNCHRONOUS_TRANSFER_SENT 0X0004 #define PD_SYNCHRONOUS_TRANSFER_SENT 0X0004 #ifdef ULTRA static SYNC_TABLE SyncTable[] = {{0x0c,0x0c,0x1,0}, /* 20MB 50ns*/ {0x19,0x19,0x3,1}, /* 10MB 100ns*/ {0x1a,0x25,0x5,2}, /* 7.5MB 150ns*/ {0x26,0x32,0x7,3}}; /* 5MB 200ns*/ #define SYNC_TABLE_MAX 4 #else static SYNC_TABLE SyncTable[] = {{0x19,0x19,0x1,0}, /* 10MB 100ns*/ {0x1a,0x25,0x2,0}, /* 7.5MB 150ns*/ {0x26,0x32,0x3,1}}; /* 5MB 200ns*/ #define SYNC_TABLE_MAX 3 #endif /* ----- OREASAMA ---------------------------------------------------*/ #if DBG /********************************************************/ /* Globals and externals used for debugging.*/ /********************************************************/ /********************************************************/ /* Ns3Debug affects which debug prints are enabled:*/ /********************************************************/ /* 0x001 Arbitration and selection*/ /* 0x002 Command, status*/ /* 0x004 Data transfer*/ /* 0x008 Message in*/ /* 0x010 Miniport entry points and completion*/ /* 0x020 Initialization and interrupt*/ /* 0x040 StatusCheck and WaitForRequest*/ /* 0x080 Control register manipulation*/ /* 0x100 Completion*/ /* 0x200 Phase info*/ /* 0x400 Temporary*/ /* 0x800 Panic*/ /********************************************************/ /* ORESAMA u_long Ns3Debug = ( 0x7f );*/ u_long Ns3Debug = ( 0xfff );/* ORESAMA MUST DELETE AFTER DEBUG*/ #define Ns3DebugPrint(MASK, ARGS) \ if (MASK & Ns3Debug) { \ printf ARGS; \ } #else #define Ns3DebugPrint(MASK, ARGS) #endif /********************************************************/ /* Device extension*/ /********************************************************/ struct _SPECIFIC_DEVICE_EXTENSION; typedef struct _SPECIFIC_DEVICE_EXTENSION nin_softc, *pnin_softc; /*typedef struct _SPECIFIC_DEVICE_EXTENSION */ struct _SPECIFIC_DEVICE_EXTENSION { SCSI_STATE ScsiState; char *CurDataPointer; /* Current pointer for active LUN.*/ u_long CurDataLength; /* Bytes left to xfer to this LUN.*/ PSPECIFIC_LU_EXTENSION ActiveLogicalUnit; /* Currently active LUN.*/ u_char PathId; boolean InterruptPending; /* Waiting for interrupt.*/ boolean DmaPending; /* Waiting for DMA setup.*/ u_char DeviceType[8]; /* inquiry data save*/ SPECIFIC_TARGET_EXTENSION TargetState[8]; u_char TimerCycle; u_char TimerCount; u_char TransferMode; boolean Write24BitEnable; u_char MessageBuffer[8]; u_long MessageCount; u_char Pcic3a[6]; u_long SmitBuffer; u_char TargetId; u_char TargetLun; /* LUN for reselection*/ u_char IrqMaskData; u_char ScsiPrePhase; u_short AdapterOption; void (*pXferRead)__P(( u_int,char *Buffer, size_t Length)); void (*pXferWrite)__P(( u_int, char *Buffer, size_t Length)); FIFO_TEST CanTransMode[6]; /* can transfer-mode*/ boolean IntWait; /* wait in int-routine?*/ boolean ScsiCable; /* funny cable ? or FifoTest all NG*/ u_long SSEntry; /* Socket Service Entry Point*/ u_char WindowHandle; /* Socket memory-win-handle*/ u_char PcicSpeed[2]; #ifdef ULTRA u_char SynchronousPeriod; #endif struct scsi_link sc_link; /* prototype for subdevs 0414 */ boolean gone; int BaseAddress; /* Port address of adapter.*/ int slot; /* Slot number (slot.h)*/ int PcicSlot; /* Slot number (slot.h)*/ int unit; }; int ninja3_precommand( PSPECIFIC_LU_EXTENSION *luExt, pnin_softc devExt, struct scsi_xfer * Srb); int ninja3_queuecommand( struct scsi_xfer * cmd, void (*done) (struct scsi_xfer *)); u_long Ns3FindAdapter(int unit); boolean Ns3Initialize(int unit); u_char Ns3FifoTest( int unit,IN PFIFO_TEST pTestMode); void Ns3ResetScsiBus( pnin_softc DevExt ); void Ns3MakeTestPat ( IN int unit, IN u_short TestPat, IN u_short * TestSave, IN u_short * wTestSum, IN u_char * bTestSum); void Ns3PcicTimingRest( int unit ); void Ns3PcicTimingSave( int unit ); PSPECIFIC_LU_EXTENSION ScsiPortGetLogicalUnit(u_int8_t TargetId,u_int8_t Lun); void ScsiPortFreeLogicalUnit(u_int8_t TargetId,u_int8_t Lun); void Ns3StartExecution( IN pnin_softc DevExt, IN PSPECIFIC_LU_EXTENSION LuExtension, IN struct scsi_xfer *Srb ); void Ns3IrqPolling ( int unit ); /*void ninintr( int unit );*/ boolean Ns3Select( IN pnin_softc DevExt , struct scsi_xfer *srb); void nin_done( IN pnin_softc DevExt, IN int err_code ); void Ns3SetTransferMode( IN pnin_softc DevExt ); void Ns3RunPhase( IN pnin_softc DevExt, IN IRQ_PHASE_SENSE IrqPhase ); void Ns3DataInPhase( IN pnin_softc DevExt ); void Ns3DataOutPhase( IN pnin_softc DevExt ); void Ns3SendCDB( IN pnin_softc DevExt ); void Ns3MessageOut( IN pnin_softc DevExt ); void Ns3MessageIn( IN pnin_softc DevExt ); void Ns3Status( IN pnin_softc DevExt ); boolean Ns3WaitForAckOff( pnin_softc DevExt ); boolean Ns3WaitForReqOff( pnin_softc DevExt ); void pio8_datain (IN u_int, char * ,size_t ); void pio8_dataout (IN u_int, char * ,size_t ); void pio32_datain (IN u_int, char * ,size_t ); /* void pio32_dataout (IN int DevExt , u_long Buffer, u_long Length ); */ void pio32_dataout (IN u_int BaseAddress , char *Buffer, size_t Length ); u_long read_ack_count ( IN pnin_softc DevExt ); void Ns3BurstRead( IN pnin_softc DevExt ); void Ns3BurstWrite( IN pnin_softc DevExt ); void Ns3SpotRead ( IN pnin_softc DevExt ); void Ns3SpotWrite ( IN pnin_softc DevExt ); void Ns3SlowRead ( IN pnin_softc DevExt ); void Ns3SlowWrite ( IN pnin_softc DevExt ); boolean Ns3ProcessReselection( IN pnin_softc DevExt ); boolean Ns3MessageDecode( IN pnin_softc DevExt ); boolean Ns3DecodeSynchronousRequest( IN pnin_softc DevExt, PSPECIFIC_TARGET_EXTENSION TargetState, IN u_char TargetID, IN boolean ResponseExpected ); /*------------------------------------------------------------------------*/ /* #define NNIN 2 */ #if NNIN > 0 /* NCRD -> NNIN*/ #include #include #include #include /* * PC-Card (PCMCIA) specific code. */ static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ static void nin_unload(struct pccard_devinfo *); /* Disable driver */ static void nin_suspend(struct pccard_devinfo *); /* Suspend driver */ static int nin_crdinit(struct pccard_devinfo *); /* init device */ int nin_attach(struct isa_device *dev); int nin_probe(struct isa_device *dev); static int32_t nin_scsi_cmd __P((struct scsi_xfer *)); static void nin_minphys(struct buf *bp); static u_int32_t nin_adapter_info(int unit); static nin_softc nin_data[NNIN]; static struct pccard_device pcc_nin_info = { "nin", nin_crdinit, /* attach probe */ nin_unload, /* */ /* nin_suspend,*/ /* */ card_intr, /* interrupt*/ 0, /* Attributes - presently unused */ &bio_imask /* Interrupt mask for device */ }; DATA_SET(pccarddrv_set, pcc_nin_info); #ifdef KERNEL static struct scsi_adapter nin_switch = { nin_scsi_cmd, nin_minphys, 0, 0, nin_adapter_info, "nin", { 0, 0 } }; /* the below structure is so we have a default dev struct for out link struct */ static struct scsi_device nin_dev = { NULL, /* Use default error handler */ NULL, /* have a queue, served by this */ NULL, /* have no async handler */ NULL, /* Use default 'done' routine */ "nin", 0, { 0, 0 } }; struct isa_driver nindriver = { nin_probe, nin_attach, "nin" }; static int nin_unit = 0; static u_int32_t TestPat[] = { 0,0xffff,0x55aa,0xaa55,0x0011,0xffee,0x0001,0x00ff}; static PSPECIFIC_LU_EXTENSION table[8][10]; static u_char TestLoad[64]; static u_char TestSave[64]; static FIFO_TEST DefaultOk[6] = { { 0x4,0}, /* 24bit*/ { 0x2,0}, /* Mem32*/ { 0x20,0}, /* IO32*/ { 0x1,0}, /* MEM8*/ { 0x10,0}, /* IO8*/ { 0,0}}; /* test priority */ static FIFO_TEST FifoTestResult[3][4][6]; FAST_MODE FastestMode[4*3*6]; #endif /* KERNEL */ /* * Called when a power down is requested. Shuts down the * device and configures the device as unavailable (but * still loaded...). A resume is done by calling * wlpcrdinit with first=0. This is called when the user suspends * the system, or the APM code suspends the system. */ static void nin_suspend(struct pccard_devinfo *dp) { pnin_softc sc = &nin_data[dp->isahd.id_unit]; Ns3DebugPrint(0x10,("nin%d: suspending\n", dp->isahd.id_unit)); sc->gone = 1; } /* * Initialize the device */ static int nin_crdinit(struct pccard_devinfo *dp) { /* struct nin_softc *sc = &nin_softc[dp->isahd.id_unit]; */ pnin_softc sc = &nin_data[dp->isahd.id_unit]; /* validate unit number. */ { /* if (first == 0) resume*/ /* unit-num is max(NNIN) -> end*/ if (dp->isahd.id_unit >= NNIN) { Ns3DebugPrint(0x10,("nin_crdinit:ENODEV\n")); /* ORE*/ return(ENODEV); } /* * Probe the device. If a value is returned, the * device was found at the location. */ sc->gone = 0; /* Set slot-num for PCIC*/ sc->PcicSlot = dp->slt->slotnum; if (nin_probe(&dp->isahd)==0){ Ns3DebugPrint(0x10,("nin_crdinit:ENXIO\n")); return(ENXIO); } if (nin_attach(&dp->isahd)==0) { Ns3DebugPrint(0x10,("nin_crdinit:ENXIO\n")); return(ENXIO); } } /* * XXX TODO: * If it was initialized before, the device structure * should also be initialized. We should * reset (and possibly restart) the hardware, but * I am not sure of the best way to do this... */ return(0); } /* * nin_unload - unload the driver and clear the table. * XXX TODO: */ static void nin_unload(struct pccard_devinfo *dp) { /* struct nin_softc *sc = &nin_softc[dp->isahd.id_unit]; */ pnin_softc sc = &nin_data[dp->isahd.id_unit]; sc->gone = 1; Ns3DebugPrint(0x10,("nin%d: unload\n", dp->isahd.id_unit)); } /* * card_intr - Shared interrupt called from * front end of PC-Card handler. */ static int card_intr(struct pccard_devinfo *dp) { /* call interrupt proc*/ ninintr(dp->isahd.id_unit); return(1); } #endif /* NCRD > 0 */ int nin_probe(struct isa_device *dev) { u_char ChipId; /* unit_num is too much*/ if(nin_unit > NNIN) { return 0; } dev->id_unit = nin_unit; /* XXX WRONG! */ nin_data[nin_unit].BaseAddress = dev->id_iobase; ChipId = inb(nin_data[nin_unit].BaseAddress+FIFOSTATUS); Ns3DebugPrint(0x10,("nin_probe:BaseAddress[%x],irq[%x],ChipId[%x]\n",nin_data[nin_unit].BaseAddress,dev->id_irq,ChipId)); if (ChipId < 0x11 || 0x1f < ChipId) { return 0; } Ns3FindAdapter(nin_unit); if( !Ns3Initialize(nin_unit) ) { return 0; } nin_unit++; return 8; } int nin_attach(struct isa_device *dev) { int masunit; static u_long versprobe=0; /* max 32 controllers */ int unit = dev->id_unit; struct scsibus_data *scbus; nin_data[unit].sc_link.adapter_unit = unit; nin_data[unit].sc_link.adapter_targ = 7; /* adapter's scsi id*/ nin_data[unit].sc_link.adapter = &nin_switch; nin_data[unit].sc_link.device = &nin_dev; nin_data[unit].sc_link.adapter_softc = &(nin_data[unit]); /* nin[unit].sc_link.flags = SDEV_BOUNCE; */ /* * Prepare the scsibus_data area for the upperlevel * scsi code. */ scbus = scsi_alloc_bus(); if(!scbus) return 0; /*scbus->maxtarg = 7;*/ scbus->maxlun = 3; scbus->adapter_link = &nin_data[unit].sc_link; scsi_attachdevs(scbus); return 1; } /* ----------------------------------------------------------- */ void nin_minphys(struct buf *bp) { #define DEFAULT_FIFOMAX 0x10000 if(bp->b_bcount > DEFAULT_FIFOMAX) { bp->b_bcount = DEFAULT_FIFOMAX; } } /* * Return some information to the caller about * the adapter and its capabilities. */ u_int32_t nin_adapter_info(int unit) { /* max number of request per device */ return 1; } /* return (2); * 2 outstanding requests at a time per device */ /* // Ns3FindAdapter */ u_long Ns3FindAdapter(int unit) { int baseAddress; /* PSCSI_REGISTER baseAddress; */ u_long status; u_char * ioSpace,memSpace; u_char switches; u_long mmioBase; u_long UseRegisterBuffer = 0; TRANSFER_MODE xferMode; u_long FifoMax = 0x10000; u_char dataByte; #ifdef ULTRA u_char OptSyncPeriod #endif pnin_softc DevExt = &(nin_data[unit]); Ns3DebugPrint(0x20, ( "FindAdapter Entered...\n")); *((u_char *)&xferMode) = 0; xferMode.MemMap8 = 1; xferMode.MemMap16_32 = 1; xferMode.AdrData24 = 1; xferMode.IO16_32 = 1; xferMode.IO8 = 1; baseAddress = DevExt->BaseAddress; /* Get I/O addr*/ FifoMax = 0x10000; /* Determine IRQ*/ /* Note: In future release of NT (after .404 March Beta), this value*/ /* can be returned as 0 and NT will assume we are polling and won't*/ /* reserve an IRQ for us. Until then, we need to give him something.*/ /* See Note Above*/ DevExt->SSEntry = 0; xferMode.MemMap16_32 = 0; xferMode.AdrData24 = 0; xferMode.MemMap8 = 0; DevExt->TransferMode= *(u_char *)&xferMode; /* Set default-trans-mode*/ (*(u_char *)&xferMode) = 0; xferMode.FifoTest_Braind = 0; xferMode.TransferGo = 0; xferMode.IO16_32 = 1; /* TransferModeSet & TEST MODE OFF */ SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); DevExt->pXferRead = pio32_datain; DevExt->pXferWrite = pio32_dataout; return TRUE; } /* end Ns3FindAdapter()*/ PSPECIFIC_LU_EXTENSION ScsiPortGetLogicalUnit(u_int8_t TargetId,u_int8_t Lun) { int flags; flags = splbio(); if (!table[TargetId][Lun]) { table[TargetId][Lun] = malloc(sizeof(SPECIFIC_LU_EXTENSION), M_DEVBUF, M_NOWAIT); } splx(flags); return table[TargetId][Lun]; } void ScsiPortFreeLogicalUnit(u_int8_t TargetId,u_int8_t Lun) { int flags; flags = splbio(); if((TargetId >= 7)||(Lun >= 8)) { Ns3DebugPrint(0x10,( "ScsiPortFreeLogicalUnit:ID[%x] Lun[%x]\n", TargetId,Lun)); splx(flags); return; } if (table[TargetId][Lun]) { /* 1105 free( table[TargetId][Lun] , M_DEVBUF); table[TargetId][Lun] = 0; 1105 */ } splx(flags); } u_char Ns3FifoTest( int unit,IN PFIFO_TEST pTestMode) { TRANSFER_MODE saveMode; saveMode.TransferGo = 1; saveMode.FifoTest_Braind = 0; saveMode.MemMap8 = 0; saveMode.AdrData24 = 0; saveMode.MemMap16_32 = 0; saveMode.IO8 = 0; saveMode.IO16_32 = 1; return(*((u_char *)(&saveMode))); } void Ns3ResetScsiBus( pnin_softc DevExt ) { PSPECIFIC_TARGET_EXTENSION targetState; u_long i; unsigned long flags; u_char dataByte; int baseAddress = DevExt->BaseAddress; if (DevExt->DmaPending == TRUE) { DevExt->DmaPending = FALSE; } DevExt->InterruptPending = FALSE; Ns3DebugPrint(0x10, ( "Ns3ResetScsiBus ")); SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ all Mssk & clear*/ /*****************/ /* RESET SCSI bus.*/ /******************/ dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 1; SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* SCSI RST On !*/ DELAY(RESET_HOLD_TIME); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 0; SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* SCSI RST Off !*/ /* dummy read for SCSI RST IRQ/Phase Change */ for ( i= 0; i < 5; i++) { SCSI_READ(baseAddress,IRQPHASESENCE); } /* Set unsyncronus 5MB*/ for (i = 0; i < 7; i++) { targetState = &DevExt->TargetState[i]; /* Get pointer*/ targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; } SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ mask & clear*/ DevExt->IrqMaskData = 0xff; DELAY(RESET_RECOVER_TIME); } int ninja3_precommand( PSPECIFIC_LU_EXTENSION *luExt, pnin_softc devExt, struct scsi_xfer * Srb) { /* ** Determine the logical unit that this request is for. */ (*luExt) = ScsiPortGetLogicalUnit( /* devExt->PathId, */ Srb->sc_link->target, Srb->sc_link->lun); if( !(*luExt) ) { Srb->error = XS_DRIVER_STUFFUP; return FALSE; /*TRY_AGAIN_LATER;*/ } /* ** Setup the context for this target/lun. */ (*luExt)->ActiveLuRequest = Srb; (*luExt)->SavedDataPointer = Srb->data; (*luExt)->SavedDataLength = Srb->datalen; (*luExt)->PhaseWaitCounter = 0; devExt->ScsiState = SC_SELECT; return TRUE; } /*ninja3_precommand end*/ void nin_timeout (void *arg); void nin_timeout (void *arg) { pnin_softc DevExt= (pnin_softc) arg; struct scsi_xfer *Srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; int x = splbio (); if (! (Srb->flags & SCSI_NOMASK)) printf ("nin%d/%d/%d (%s%d) timed out\n", Srb->sc_link->adapter_unit, Srb->sc_link->target, Srb->sc_link->lun, Srb->sc_link->device->name, Srb->sc_link->dev_unit); Ns3ResetScsiBus (DevExt); Srb->error = XS_TIMEOUT; Srb->retries = 0; nin_done(DevExt,XS_TIMEOUT); splx (x); } int nin_scsi_cmd(struct scsi_xfer * Srb) { int x = 0; int flags = Srb->flags; static PSPECIFIC_LU_EXTENSION luExtension; struct scsi_link *sc_link = Srb->sc_link; pnin_softc deviceExtension = (pnin_softc)sc_link->adapter_softc; Ns3DebugPrint (0x10,("nin %d/%d command 0x%x ",Srb->sc_link->target, Srb->sc_link->lun, Srb->cmd->opcode)); if (flags & SCSI_RESET) { Ns3DebugPrint(0x10, ( "nin_scsi_cmd: Reset Bus.\n")); /* Reset Ns3 and SCSI bus.*/ Ns3ResetScsiBus( deviceExtension ); return COMPLETE; } if( !ninja3_precommand(&luExtension,deviceExtension,Srb) ) { return TRY_AGAIN_LATER; } if(!Srb) { Ns3DebugPrint(0x008, ("ninja3_precommand srb = null!!!! \n\n\n")); return FALSE; } if (! (flags & SCSI_NOMASK)) x = splbio (); /* Initiate a SCSI request. */ Ns3StartExecution(deviceExtension, luExtension, Srb); if ( Ns3Select(deviceExtension,Srb) ) Ns3IrqPolling ( deviceExtension->unit ); // Usually return SUCCESSFULLY QUEUED. if (! (flags & SCSI_NOMASK)) { splx (x); /* 1107 */ if (Srb->flags & ITSDONE) { Ns3DebugPrint (0x10,("nin_scsi_cmd SUCCESSFULLY_QUEUED\n")); return (SUCCESSFULLY_QUEUED); } Ns3DebugPrint (0x10,("call timeout\n")); timeout (nin_timeout, (caddr_t)deviceExtension, (Srb->timeout * hz) / 1000); Ns3DebugPrint (0x10,("nin%d/%d/%d command queued\n", Srb->sc_link->adapter_unit, Srb->sc_link->target, Srb->sc_link->lun)); Ns3DebugPrint (0x10,("nin_scsi_cmd SUCCESSFULLY_QUEUED\n")); return (SUCCESSFULLY_QUEUED); } return (Srb->error ? HAD_ERROR : COMPLETE); /* * return values for scsi_cmd() #define SUCCESSFULLY_QUEUED 0 #define TRY_AGAIN_LATER 1 #define COMPLETE 2 #define HAD_ERROR 3 // do not use this, use COMPLETE #define ESCAPE_NOT_SUPPORTED 4 */ } /* end nin_scsi_cmd()*/ /* // Routine Name: // // Ns3StartExecution // // Routine Description: // // This routine will start the execution of a SCSI request. // // Arguments: // // DevExt - Device adapter context pointer. // LuExtension - The logical unit specific information. // Srb - The Srb command to execute. // // Return Value: // // None. // //----------------------------------------------------------------------- */ void Ns3StartExecution( IN pnin_softc DevExt, IN PSPECIFIC_LU_EXTENSION LuExtension, IN struct scsi_xfer *Srb ) { PSPECIFIC_TARGET_EXTENSION targetState; if ((Srb->cmd->bytes[0] >> 5) != Srb->sc_link->lun) { Srb->cmd->bytes[0] &= 0x1f; Srb->cmd->bytes[0] |= (Srb->sc_link->lun << 5); } DevExt->TargetId = Srb->sc_link->target; /* Setup the context for this adapter. */ DevExt->ActiveLogicalUnit = LuExtension; DevExt->CurDataPointer = DevExt->ActiveLogicalUnit->SavedDataPointer; DevExt->CurDataLength = DevExt->ActiveLogicalUnit->SavedDataLength; /* Set TargetState Ns3MessageDecode */ DevExt->TargetId = Srb->sc_link->target; targetState = &DevExt->TargetState[Srb->sc_link->target]; /* // // Create the identify command. // */ /* NOT supported DISCONECT */ if ( /* (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) || */ (DevExt->AdapterOption & OPT_NON_DISCONECT) ) { DevExt->MessageBuffer[0] = MSG_IDENTIFYFLAG | Srb->sc_link->lun; } else { DevExt->MessageBuffer[0] = MSG_IDENTIFYFLAG_WITH_DISCON | Srb->sc_link->lun; } DevExt->MessageCount = 1; /* // Make SyncMessage if donot Sync Nego */ if (!(targetState->TargetFlags & PD_SYNCHRONOUS_NEGOTIATION_DONE ) && !(targetState->TargetFlags & PD_DO_NOT_NEGOTIATE) && (Srb->cmd->opcode != INQUIRY) /* INQUIRY:Don't Sync Nego */ ) { /* Sync message exchange [sync]*/ DevExt->MessageCount = 6; /* extended message out */ DevExt->MessageBuffer[1] = MSG_EXTENDED; /* length */ DevExt->MessageBuffer[2] = MSG_EXT_SDTR_LEN; /* extended message out command */ DevExt->MessageBuffer[3] = SCSIMESS_SYNCHRONOUS_DATA_REQ; #ifdef ULTRA DevExt->MessageBuffer[4] = DevExt->SynchronousPeriod; #else /* Transfer interval 100n = 10M ByteS */ DevExt->MessageBuffer[4] = SYNCHRONOUS_PERIOD; #endif DevExt->MessageBuffer[5] = SYNCHRONOUS_OFFSET; targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE | PD_SYNCHRONOUS_TRANSFER_SENT; DevExt->MessageCount = 1; } } /* end Ns3StartExecution()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3IrqPolling // // Routine Description: // // Interrupt Polling // /// //-----------------------------------------------------------------------*/ void Ns3IrqPolling ( int unit ) { pnin_softc DevExt = &(nin_data[unit]); int i; i = INT_POLL_SEL; while (i > 0 ) { if ( SCSI_IRQ_MONITOR(DevExt->BaseAddress) & 0xb ) { ninintr( unit ); break; } /* loop interval 530CS-133MHz : 4.5us */ DELAY(5); /* DELAY -> DELAY */ i--; } /* Timer IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 1; /* SCSI IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; SCSI_IRQ_CONTROL(DevExt->BaseAddress, DevExt->IrqMaskData); Ns3DebugPrint (0x10,("-- Ns3IrqPolling ends -- ")); } /* //----------------------------------------------------------------------- // Routine Name: // // ninintr // // Routine Description: // // This routine handles the interrupts for the Ns3. The intention is to // quickly determine the cause of the interrupt, clear the interrupt, and // setup to process the SCSI command that is affected by the // interrupt. // // Arguments: // // Context - Device adapter context pointer. // // Return Value: // // TRUE indicates that the interrupt was from this Ns3 adapter, // FALSE indicates that this interrupt was NOT from us. // //----------------------------------------------------------------------- // boolean -> void */ void ninintr( int unit ) { long i; pnin_softc DevExt = &(nin_data[unit]); int baseAddress = DevExt->BaseAddress; IRQ_STATUS IntIrqStatus; IRQ_PHASE_SENSE IntIrqPhase; unsigned char dataByte; char TargetId; PSPECIFIC_TARGET_EXTENSION targetState; *((unsigned char *) &IntIrqStatus) = SCSI_IRQ_MONITOR(baseAddress); dataByte = 0; ((PIRQ_CONTROLP)&dataByte)->ExtIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->TimerIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->ScsiIrqMask = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); /* // IRQ All mask*/ IntEntry: /* from nin_unload */ if(DevExt->gone) { nin_done(DevExt, XS_DRIVER_STUFFUP); DevExt->ScsiState = SC_BUSFREE; DevExt->IntWait = FALSE; return; // TRUE; } if ( *((unsigned char *) &IntIrqStatus) == 0xff ) { nin_done(DevExt, FALSE/*SRB_STATUS_NO_DEVICE*/); DevExt->ScsiState = SC_BUSFREE; DevExt->IntWait = FALSE; return; /* TRUE;*/ } DevExt->InterruptPending = FALSE; /* // --- Timer interrupt? --- */ if ( IntIrqStatus.TimerIrqStatus ) { dataByte = 0xf0; ((PIRQ_CONTROLP)&dataByte)->TimerIrqClear = 1; /* Timer IRQ Clear*/ SCSI_IRQ_CONTROL(DevExt->BaseAddress, dataByte); if ( DevExt->TimerCount != 0 ) { /* Next TIMER START*/ SCSI_WRITE(DevExt->BaseAddress, TIMERCOUNT, DevExt->TimerCycle); DevExt->TimerCount--; } } /* // ---- SCSI IRQ ? ---- */ if ( IntIrqStatus.ScsiIrqStatus ) { *((unsigned char *)&IntIrqPhase) = SCSI_READ(baseAddress, IRQPHASESENCE); /* //---- ReSelection IRQ ? ---- */ if (IntIrqPhase.ReselectIrq) { TargetId =(unsigned char)(SCSI_READ(baseAddress, RESELECTID) & 0x7f); i = 0xffffffff; while ( TargetId > 0 ) { i++; TargetId = TargetId >> 1; } DevExt->TargetId = i; DevExt->TargetLun = DevExt->ActiveLogicalUnit->ActiveLuRequest->sc_link->lun; do { dataByte = SCSI_READ(baseAddress, SCSIBUSMON); } while ( ((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_SEL ); /* SEL off ?*/ dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiBSY = 0; /* BUSY Off !*/ SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; /* AckEnb , AutoDirection ON !*/ ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; /* ( Not same time in BUSY off)*/ SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* set Sync-parameter*/ targetState = &DevExt->TargetState[DevExt->TargetId]; dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; SCSI_WRITE(baseAddress, SYNCREG,dataByte); SCSI_WRITE(baseAddress, ACKWIDTH, targetState->AckWidth); /* Clear transfer clear*/ dataByte = 0; ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; ((PPOINTER_CLEAR)&dataByte)->AckCounterClear = 1; ((PPOINTER_CLEAR)&dataByte)->ReqCounterClear = 1; ((PPOINTER_CLEAR)&dataByte)->HostCounterClear = 1; SCSI_WRITE(baseAddress, POINTERCLR, dataByte); /* LUN isn't defined, not use LunExtension... wait for Message IN */ DevExt->ScsiState = SC_RESELECT; goto IntEnd; } /* --- SCSI RESET Irq ?---- */ if ( IntIrqPhase.ScsiResetIrq ) { /* Set unsync 5mb */ for (i = 0; i < 7; i++) { targetState = &DevExt->TargetState[i]; targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; } goto IntEnd; } /* --- Phase Change Interrupt ? --- */ if ( IntIrqPhase.PhaseChgIrq ) { Ns3RunPhase(DevExt, IntIrqPhase ); goto IntEnd; } } /* ---- FIFO Interrupt ? ---- */ if ( IntIrqStatus.FifoIrqStatus ) { /* Interrupt Clear*/ *((unsigned char *) &IntIrqPhase) = SCSI_READ(baseAddress, IRQPHASESENCE); /* Still nokori ga aru ?*/ if ( DevExt->CurDataLength ) { /* before Phase*/ if ( DevExt->ScsiPrePhase == BP_DATA_IN) Ns3DataInPhase(DevExt); else if (DevExt->ScsiPrePhase == BP_DATA_OUT) Ns3DataOutPhase(DevExt); } /*PhaseChange same time に発生 ?*/ if ( IntIrqPhase.PhaseChgIrq ) { Ns3RunPhase(DevExt, IntIrqPhase ); } goto IntEnd; } IntEnd: #ifdef USE_INTENTRY if ( !DevExt->IntWait ) { *((unsigned char *) &IntIrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( *((unsigned char *)&IntIrqStatus) & 0xf ) { goto IntEntry;/* INT */ } } else { int polltimes; polltimes = INT_POLL_IRQ * 10000; for ( i = 0; i< polltimes; i++) { *((unsigned char *)&IntIrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( *((unsigned char *)&IntIrqStatus) & 0x0f ) { goto IntEntry;/* INT */ /* l.434 */ } } } #endif /* USE_INTENTRY */ /* --- Reverse IRQ MASK MODE ---- */ SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); DevExt->IntWait = TRUE; Ns3DebugPrint(0x10,( "ninintr out -----------\n")); return ; /* TRUE;*/ } /* end ninintr()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3Select // // Routine Description: // // Perform selection process on SCSI bus. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // TRUE : Select Success /// //----------------------------------------------------------------------- */ boolean Ns3Select( IN pnin_softc DevExt ,struct scsi_xfer *srb) { PSPECIFIC_TARGET_EXTENSION targetState; int i; int baseAddress = DevExt->BaseAddress; unsigned char cdbLength = srb->cmdlen; u_char *cdb = &(srb->cmd->opcode); unsigned char BusyByte, dataByte, AtnByte; AtnByte = 0; ((PSCSI_BUS_CONTROL)&AtnByte)->ScsiATN = 1; if ( DevExt->AdapterOption & OPT_NO_ATN ) ((PSCSI_BUS_CONTROL)&AtnByte)->ScsiATN = 0; /* --- Didable all interrupt */ dataByte = 0; ((PIRQ_CONTROLP)&dataByte)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->TimerIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->ExtIrqMask = 1; ((PIRQ_CONTROLP)&dataByte)->ScsiIrqMask = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); DevExt->IrqMaskData = dataByte; /* --- CDB -> COMMAND FIFO --- INITIATOR -> target */ dataByte = 0; ((PCOMMAND_CONTROL)&dataByte)->ClrCommandPointer = 1; SCSI_WRITE(baseAddress,COMMANDCTRL, dataByte); /* CDB FIFO counter Clear*/ /* cdbLength--; cdbLength - 1 */ while (cdbLength > 0) { Ns3DebugPrint(0x10,( "[%x]",*cdb)); SCSI_WRITE(baseAddress, COMMANDDATA, *cdb++); cdbLength--; } /* --- Start Arbitration for Get Bus--- */ dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitGo = 1; SCSI_WRITE(baseAddress, SETARBIT, dataByte); /* Start Arbitration */ DELAY(300); /* 1104 delete after */ dataByte = 0; i=0; while (!( ((PARBIT_STATUS)&dataByte)->ArbitWin || ((PARBIT_STATUS)&dataByte)->ArbitFail ) ) { dataByte = SCSI_READ(baseAddress, ARBITSTATUS); /* Get bus? */ DELAY(1); i++; if(100000 < i){ Ns3DebugPrint(0x10,( "(;_;)[%x] -X-",dataByte)); ((PARBIT_STATUS)&dataByte)->ArbitFail = 1; break; } } if ( ((PARBIT_STATUS)&dataByte)->ArbitFail ) { /* ...I'm looser */ Ns3DebugPrint(0x10,( " Faild [%x](;_;) -- ",dataByte)); dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(baseAddress, SETARBIT, dataByte);/* Arbitration flg Clear*/ DevExt->ScsiState = SC_BUSFREE; /* 1112 nin_done(DevExt, XS_SELTIMEOUT); */ nin_done(DevExt, XS_TIMEOUT); /* Timer IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 0; /* SCSI IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); return(FALSE); } /* Win !*/ DELAY(2); /*----- selection phase -----*/ dataByte = (1 << SCSI_INITIATOR_ID) | (1 << (srb->sc_link->target)); /* set initiator ID + target ID */ SCSI_WRITE(baseAddress, SCSIDATALATCH, dataByte); dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiSel = 1; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiBSY = 1; dataByte |= AtnByte; SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* put SEL + Busy + ATN*/ DELAY(3); /*DELEY ScsiPortStallExecution(1); wait 1.2us*/ ((PSCSI_BUS_CONTROL)&dataByte)->ScsiDataOutEnb = 1; SCSI_WRITE(baseAddress,SCSIBUSCTRL , dataByte); /* enable ID out */ dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(baseAddress, SETARBIT, dataByte); /* Arbitration flag Clear*/ DELAY(2); dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiSel = 1; dataByte |= AtnByte; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiDataOutEnb = 1; SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* Busy off*/ DevExt->TimerCount = 250; DevExt->TimerCycle = 1000/51; SCSI_WRITE(baseAddress, TIMERCOUNT, 1000/51); /* 1msec TIMER START*/ do { BusyByte = SCSI_READ(baseAddress, SCSIBUSMON); if ( ((PSCSI_BUS_MONITOR)&BusyByte)->Scsi_BSY ) { /*? (busy)*/ break; } dataByte = SCSI_IRQ_MONITOR(baseAddress); if ( ((PIRQ_STATUS)&dataByte)->TimerIrqStatus ) { SCSI_IRQ_CONTROL(baseAddress, dataByte); DevExt->TimerCount--; SCSI_WRITE(baseAddress, TIMERCOUNT, 1000/51);/* 1msec TIMER START*/ } } while ( DevExt->TimerCount != 0 ); dataByte = SCSI_IRQ_MONITOR(baseAddress) & 0xf0; ((PIRQ_CONTROLP)&dataByte)->TimerIrqClear = 1; /* Clear Timer IRQ*/ SCSI_IRQ_CONTROL(baseAddress, dataByte); DevExt->TimerCount = 0; if ( ! (((PSCSI_BUS_MONITOR)&BusyByte)->Scsi_BSY) ) { /* ----- None... ----- */ SCSI_WRITE(baseAddress, SCSIBUSCTRL, 0); /* SEL Off*/ DevExt->ScsiState = SC_BUSFREE; nin_done(DevExt, XS_SELTIMEOUT/*SRB_STATUS_NO_DEVICE*/); /* Timer IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 0; /* SCSI IRQ Enable*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); Ns3DebugPrint (0x10,("-- Ns3Select FALSE ends -- ")); return(FALSE); } /* //--- Success Selection --- */ dataByte = 0; dataByte |= AtnByte; SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* SEL off*/ DevExt->TimerCount = 0; SCSI_WRITE(baseAddress, TIMERCOUNT, 0); /* Timer stop */ SCSI_WRITE(baseAddress, TIMERCOUNT, 0); /* Timer stop needs 2times */ /*AutoDirec / ACK Enable (Not same time in SEL off ...) */ ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); targetState = &DevExt->TargetState[srb->sc_link->target]; /* set sync parameter*/ dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; SCSI_WRITE(baseAddress, SYNCREG,dataByte); SCSI_WRITE(baseAddress, ACKWIDTH, targetState->AckWidth); Ns3SetTransferMode( DevExt ); DevExt->ScsiState = SC_SELECT; /* Adapter ready for next request. */ Ns3DebugPrint(0x01,( "Ns3Select: Select ATN OK. ID = %x ", DevExt->TargetId)); DELAY(50); DevExt->IntWait = TRUE; Ns3DebugPrint (0x10,("-- Ns3Select ends -- ")); return(TRUE); } /* end Ns3Select()*/ boolean Ns3Initialize(int unit) { pnin_softc DevExt = &(nin_data[unit]); u_long i; u_long FifoMax = 0x10000; u_char dataByte; TRANSFER_MODE xferMode; int baseAddress = DevExt->BaseAddress; u_char DefaultXfer = 0; DevExt->unit = unit; DevExt->BaseAddress = baseAddress; #ifndef USE_DISCONECT DevExt->AdapterOption = OPT_NON_DISCONECT; #endif /* USE_DISCONECT */ *((u_char *)&xferMode) = 0; xferMode.MemMap8 = 0; xferMode.MemMap16_32 = 0; xferMode.AdrData24 = 0; xferMode.IO16_32 = 0; xferMode.IO8 = 1; FifoMax = 0x10000; DevExt->SSEntry = 0; xferMode.MemMap16_32 = 0; xferMode.AdrData24 = 0; xferMode.MemMap8 = 0; DevExt->TransferMode= *(u_char *)&xferMode; /* Set default-trans-mode*/ (*(u_char *)&xferMode) = 0; xferMode.FifoTest_Braind = 0; xferMode.TransferGo = 0; /* TransferModeSet & TEST MODE OFF */ SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); #ifdef USE_32BITTRANSFER DevExt->pXferRead = pio32_datain; DevExt->pXferWrite = pio32_dataout; #else DevExt->pXferRead = pio8_datain; DevExt->pXferWrite = pio8_dataout; #endif /* USE_32BITTRANSFER */ /* if hang-up any Phase and reset、then Busfree Interrupt*/ SCSI_WRITE(baseAddress, SCSIIRQMODE, 0); /* SCSI IRQ ALL DISABLE*/ SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ all Mssk & clear */ #ifdef ULTRA SCSI_WRITE(baseAddress, CLOCKDIV , 2); /* 40MHz */ #else SCSI_WRITE(baseAddress, CLOCKDIV , 1); /* 20MHz */ #endif dataByte = 0; ((PSCSI_IRQ_MODE)&dataByte)->ScsiResetIrqEi = 1; ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; /* Disable FIFO IRQ*/ ((PSCSI_IRQ_MODE)&dataByte)->ReselectIrqEi = 1; ((PSCSI_IRQ_MODE)&dataByte)->ScsiPhaseChangeEi = 1; SCSI_WRITE(baseAddress, SCSIIRQMODE, dataByte); SCSI_WRITE(baseAddress, PARITYCTRL , 0); /* Parity Disable*/ SCSI_WRITE(baseAddress, POINTERCLR , 0xf); /* All Pointer Clear*/ dataByte = 0; ((PIF_SELECT)&dataByte)->RegSelect = 1; SCSI_IF_SELECT(baseAddress, dataByte); /* FIFO Status Read set*/ /********************************************************/ /* Reset Ns3 and SCSI bus.*/ /********************************************************/ DevExt->InterruptPending = FALSE; DevExt->DmaPending = FALSE; /*Terminator Off !*/ SCSI_WRITE(baseAddress, TERMPWRCTRL, 0); /* Terminator Off !*/ dataByte = SCSI_READ(baseAddress, OTHERCONTROL); if ( ! ((POTHER_CONTROL)&dataByte)->TermPwrSence ) /* Term Power ?;*/ SCSI_WRITE(baseAddress, TERMPWRCTRL, 1); /* Terminator ON !*/ /********************************************************/ /*--- SCSI BUS RESET ---*/ /********************************************************/ Ns3ResetScsiBus( DevExt ); /********************************************************/ /*--- Cable Check ---*/ /********************************************************/ DevExt->ScsiCable = TRUE; if ( (SCSI_READ(baseAddress,SCSIDATAIN)) || (SCSI_READ(baseAddress,SCSIBUSMON)) ) { DevExt->ScsiCable = FALSE; SCSI_WRITE(baseAddress, TERMPWRCTRL, 0); /* Terminator Off !*/ } *(u_char *)&xferMode = DevExt->TransferMode; /********************************************************/ /* Can TransferMode Clear*/ /********************************************************/ for ( i = 0; i < 6; i++ ) { DevExt->CanTransMode[i] = DefaultOk[i]; } /********************************************************/ /* At first, Test for TransferMode in default */ /********************************************************/ DefaultXfer = Ns3FifoTest( unit,&DevExt->CanTransMode[0]); xferMode =(*(PTRANSFER_MODE)&DefaultXfer); DevExt->TransferMode= *(u_char *)&xferMode; /* TransferModeSet & TEST MODE OFF */ SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); if ( xferMode.IO16_32 ) { DevExt->pXferRead = pio32_datain; DevExt->pXferWrite = pio32_dataout; } else if ( xferMode.IO8 ) { DevExt->pXferRead = pio8_datain; DevExt->pXferWrite = pio8_dataout; } SCSI_WRITE(baseAddress, CLOCKDIV , 2); return TRUE; } /* end Ns3Initialize()*/ /* //----------------------------------------------------------------------- // Routine Name: // nin_done // // Routine Description: // // This routine will perform any clean up operations for the Srb // and notify the ScsiPort driver of completion. // //----------------------------------------------------------------------- */ void nin_done( IN pnin_softc DevExt, IN int err_code ) { struct scsi_xfer *srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; ScsiPortFreeLogicalUnit( srb->sc_link->target, srb->sc_link->lun); untimeout (nin_timeout, (caddr_t) DevExt); srb->error = err_code; srb->flags |= ITSDONE; scsi_done(srb); } /* end nin_done()*/ /* //---------------------------------------------------------------------------- // Set transger mode & ruotine //---------------------------------------------------------------------------- */ void Ns3SetTransferMode( IN pnin_softc DevExt ) { PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; unsigned char dataByte; LuExtension->pXferRead = DevExt->pXferRead; LuExtension->pXferWrite = DevExt->pXferWrite; /* FIFOTest & Option Set TransferMode*/ dataByte = DevExt->TransferMode; ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 1; /* Set transfer mode*/ SCSI_WRITE(DevExt->BaseAddress, TRANSFERMODE, dataByte); } /* //----------------------------------------------------------------------- // read FIFO // //----------------------------------------------------------------------- */ unsigned long read_ack_count ( IN pnin_softc DevExt ) { int baseAddress = DevExt->BaseAddress; unsigned char dataByte; unsigned char CountL,CountM, CountH; unsigned long Count, Counter; dataByte = 0; ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; SCSI_WRITE(baseAddress, POINTERCLR, dataByte); /* ACK counter read set*/ CountL = inb(baseAddress+DATAREG); CountM = inb(baseAddress+DATAREG); CountH = inb(baseAddress+DATAREG); Counter = (unsigned long)( CountH*65536 + CountM*256 + CountL); /* Check Card */ if ( Counter == 0xffffff ) return (0); /* Counter value at Disconnect */ Count = Counter + DevExt->ActiveLogicalUnit->AckCounter; Count -= DevExt->ActiveLogicalUnit->TransferedLength; return ( Count ); } /* //----------------------------------------------------------------------- // TransferRoutine // //----------------------------------------------------------------------- // */ /* --- PIO 32bit DataInTransfer ---- */ void pio32_datain (IN u_int BaseAddress , char *Buffer, size_t Length ) { if ( Length & 0x3 ) { Ns3DebugPrint(0x01,( "SCSI_READ_FIFOW [%x] (%x)byte", Buffer , Length)); SCSI_READ_FIFOW(BaseAddress, Buffer , Length); } else { SCSI_READ_FIFOD(BaseAddress, Buffer , Length); } } /* --- PIO 32bit DataOutTransfer pXferWrite() ---- */ void pio32_dataout (IN u_int BaseAddress , char *Buffer, size_t Length ) { if ( Length & 0x3 ) { SCSI_WRITE_FIFOW(BaseAddress, Buffer , Length); } else { SCSI_WRITE_FIFOD(BaseAddress, Buffer , Length); } } /* --- PIO 8bit DataInTransfer ---- */ void pio8_datain (IN u_int BaseAddress , char *Buffer, size_t Length ) { SCSI_READ_FIFO(BaseAddress, Buffer , Length); } /* --- PIO 8bit DataOutTransfer ---- */ void pio8_dataout (IN u_int BaseAddress , char *Buffer, size_t Length ) { SCSI_WRITE_FIFO(BaseAddress, Buffer , Length); } void Ns3BurstRead( IN pnin_softc DevExt ) { int flags; u_long Length; IRQ_STATUS IrqStatus; FIFO_STATUS FifoStatus; uint baseAddress = DevExt->BaseAddress; PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; while( DevExt->CurDataLength > 0 ) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) { break; /** PhaseChange ? ***/ } *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty ) { Length = DevExt->CurDataLength; /* change maxmum transfer size*/ if ( Length > READ_XFER_CNT) Length = READ_XFER_CNT; /* Call for TransferRoutine */ (*LuExtension->pXferRead)( baseAddress, DevExt->CurDataPointer, Length ); flags = splbio(); DevExt->CurDataPointer += Length; DevExt->CurDataLength -= Length; DevExt->ActiveLogicalUnit->TransferedLength += Length; splx(flags); } } /* See now,but PhaseChange */ *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); /* Stop PhaseChange interrupt */ if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ if ( DevExt->CurDataLength > 0) { Length = read_ack_count(DevExt); if (!(Length & 0x80000000)) { /* +[v0.32]*/ (*LuExtension->pXferRead)( baseAddress, DevExt->CurDataPointer, Length ); } flags = splbio(); DevExt->CurDataPointer += Length; DevExt->CurDataLength -= Length; DevExt->ActiveLogicalUnit->TransferedLength += Length; splx(flags); } } DevExt->ScsiState = SC_DATA; } /* //----------------------------------------------------------------------- // blind write // //----------------------------------------------------------------------- */ void Ns3BurstWrite( IN pnin_softc DevExt ) { u_long Length; IRQ_STATUS IrqStatus; FIFO_STATUS FifoStatus; int baseAddress = DevExt->BaseAddress; PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; int flags; while( DevExt->CurDataLength > 0 ) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty) { Length = DevExt->CurDataLength; /* change maximum transfer number*/ if ( Length > WRITE_BURST_CNT) Length = WRITE_BURST_CNT; /* Call for TransferRoutine */ (*LuExtension->pXferWrite)( baseAddress, DevExt->CurDataPointer, Length ); flags = splbio(); DevExt->CurDataPointer += Length; DevExt->CurDataLength -= Length; DevExt->ActiveLogicalUnit->TransferedLength += Length ; splx(flags); } } /* See now,but PhaseChange after sending */ *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); /* remain data inFIFO at PhaseChange */ if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ if ( (Length = read_ack_count(DevExt)) ) { /* Length is Minus*/ flags = splbio(); DevExt->CurDataPointer += Length; DevExt->CurDataLength -= Length; /* pointerwomodosu*/ DevExt->ActiveLogicalUnit->TransferedLength += Length ; splx(flags); } } DevExt->ScsiState = SC_DATA; } /* //----------------------------------------------------------------------- // spot read // //----------------------------------------------------------------------- */ void Ns3SpotRead ( IN pnin_softc DevExt ) { u_char dataByte; int baseAddress = DevExt->BaseAddress; IRQ_STATUS IrqStatus; FIFO_STATUS FifoStatus; u_long FifoCount; long LoopCount = 0; u_char ScsiPhase; long i; int flags; PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; ScsiPhase = SCSI_READ(baseAddress, SCSIBUSMON) & 0x7; if ( ScsiPhase == BP_DATA_IN ) { if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; /* FIFO IRQ Enable*/ SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* Release FIFO IRQ MASK */ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; } while (LoopCount == 0) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty ) { dataByte = 0xf0; ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ /* Read FIFO */ FifoCount = read_ack_count( DevExt ) & 0xfffffe; /* Call for TransferRoutine */ (*LuExtension->pXferRead)( baseAddress, DevExt->CurDataPointer, FifoCount ); flags = splbio(); DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer += FifoCount; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; LoopCount++; DevExt->IntWait = FALSE; splx(flags); for ( i = 0; i< INT_POLL_IRQ ; i++) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty ) { /* FIFO FULL */ LoopCount = 0; /* One moer*/ break; } DELAY(2);/*ScsiPortStallExecution(2);*/ } } } } else { /* other phase*/ FifoCount = read_ack_count( DevExt ); /* Get FIFOremain*/ (*LuExtension->pXferRead)( baseAddress, DevExt->CurDataPointer, FifoCount ); flags = splbio(); DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer += FifoCount; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; splx(flags); dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* Disable FIFO IRQ */ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* FIFO IRQ MASK*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; DevExt->IntWait = TRUE; return; } /* Stoped in PhaseChange */ if ( IrqStatus.ScsiIrqStatus && ( FifoCount = read_ack_count(DevExt))) { (*LuExtension->pXferRead)( baseAddress, DevExt->CurDataPointer, FifoCount ); flags = splbio(); DevExt->CurDataPointer += FifoCount; DevExt->CurDataLength -= FifoCount; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount; splx(flags); dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* Disable FIFO IRQ */ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* FIFO IRQ MASK*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; DevExt->IntWait = TRUE; } DevExt->ScsiState = SC_DATA; /* Wait for next FifoFull */ } /* //----------------------------------------------------------------------- // //----------------------------------------------------------------------- */ void Ns3SpotWrite ( IN pnin_softc DevExt ) { int flags; u_char dataByte; int baseAddress = DevExt->BaseAddress; IRQ_STATUS IrqStatus; FIFO_STATUS FifoStatus; u_long FifoCount; long LoopCount = 0; long i; PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* FIFO IRQ Enable*/ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* Release FIFO IRQ MASK */ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; } while (LoopCount == 0) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) { break; /* PhaseChange ?*/ } *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty) { dataByte = 0xf0; ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ FifoCount = WRITE_SPOT_CNT; if ( DevExt->CurDataLength < WRITE_SPOT_CNT ){ FifoCount = DevExt->CurDataLength; } /* Call for TransferRoutine */ (*LuExtension->pXferWrite)( baseAddress, DevExt->CurDataPointer, FifoCount ); flags = splbio(); DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer += FifoCount;; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; splx(flags); if ( DevExt->CurDataLength == 0 ) { DevExt->IntWait = TRUE; break; } LoopCount++; DevExt->IntWait = FALSE; for ( i = 0; i< INT_POLL_IRQ ; i++) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if ( IrqStatus.ScsiIrqStatus ) { break; /* PhaseChange ?*/ } *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty ) { /* if FIFO Empty*/ LoopCount = 0; /* Once more*/ break; } DELAY(2); /* ScsiPortStallExecution(2); */ } } } if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ DevExt->IntWait = TRUE; } DevExt->ScsiState = SC_DATA; /* Next FifoEmpty Wait*/ } /* //----------------------------------------------------------------------- // Slow Read // //----------------------------------------------------------------------- */ void Ns3SlowRead ( IN pnin_softc DevExt ) { int flags; char *Buffer = DevExt->CurDataPointer; u_char dataByte; int baseAddress = DevExt->BaseAddress; IRQ_STATUS IrqStatus; FIFO_STATUS FifoStatus; u_long FifoCount; long LoopCount = 0; u_char ScsiPhase; dataByte = 0; ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; ((PTRANSFER_MODE)&dataByte)->IO8 = 1; ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); /* Set Transfer Mode*/ ScsiPhase = SCSI_READ(baseAddress, SCSIBUSMON) & 0x7; if ( ScsiPhase == BP_DATA_IN ) { if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* FIFO IRQ Enable*/ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* Release FIFO IRQ MASK*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; } while (LoopCount == 0) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty ) { /* FIFO FULL?*/ dataByte = 0xf0; ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); /* Clear IRQ*/ } if ( FifoStatus.FifoFullEmpty || IrqStatus.ScsiIrqStatus) { FifoCount = read_ack_count( DevExt );/* Get FIFO remain*/ SCSI_READ_FIFO( baseAddress, Buffer, FifoCount ); flags = splbio(); Buffer += FifoCount; DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer = Buffer; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; LoopCount++; splx(flags); } } } else { /* otheer Phase*/ FifoCount = read_ack_count( DevExt ); /* read FIFO remain*/ SCSI_READ_FIFO( baseAddress, Buffer, FifoCount ); flags = splbio(); Buffer += FifoCount; DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer = Buffer; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; splx(flags); return; } DevExt->ScsiState = SC_DATA; /* Wait for next FifoFull */ } /* //----------------------------------------------------------------------- // //----------------------------------------------------------------------- */ void Ns3SlowWrite ( IN pnin_softc DevExt ) { char* Buffer = DevExt->CurDataPointer; u_char dataByte; int baseAddress = DevExt->BaseAddress; FIFO_STATUS FifoStatus; u_long FifoCount; int flags; dataByte = 0; ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; ((PTRANSFER_MODE)&dataByte)->IO8 = 1; ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); /* TransferModeSet*/ if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* FIFO IRQ Enable*/ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* Enable FIFO IRQ MAS K*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; } *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); if ( FifoStatus.FifoFullEmpty) { dataByte = 0xf0; ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ FifoCount = 32; if ( DevExt->CurDataLength < 32 ) FifoCount = DevExt->CurDataLength; SCSI_WRITE_FIFO ( baseAddress, Buffer, FifoCount ); flags = splbio(); Buffer += FifoCount; DevExt->CurDataLength -= FifoCount ; DevExt->CurDataPointer = Buffer; DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; splx(flags); } DevExt->ScsiState = SC_DATA; /* Wait for Next FifoEmpty*/ } /* //----------------------------------------------------------------------- // Routine Name: // // Ns3RunPhase // // Routine Description: // // This routine runs through the bus phases until some type of completion // indication is received. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // None. // //----------------------------------------------------------------------- */ void Ns3RunPhase( IN pnin_softc DevExt, IN IRQ_PHASE_SENSE IrqPhase ) { int baseAddress = DevExt->BaseAddress; u_char dataByte; u_long Count; PSPECIFIC_TARGET_EXTENSION targetState; int flags; /* slow transfer proc*/ if ( IrqPhase.PhaseChgIrq && ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask == 0 ) { /* still ?*/ if ( (Count = read_ack_count(DevExt)) ) { if ( DevExt->ScsiPrePhase == BP_DATA_IN) {/* prvious phase*/ Ns3DataInPhase(DevExt); }else { flags = splbio(); DevExt->CurDataLength -= Count; /* back pointer*/ DevExt->CurDataPointer += Count; /* Number of transfer-length */ DevExt->ActiveLogicalUnit->TransferedLength += Count; splx(flags); } } dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); /* FIFO IRQ desable*/ ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); /* FIFO IRQ MASK*/ ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; } /* //--- BUS FREE ( DISCONNETCT ) ? ---- */ /*interrput in BusFree*/ if ( IrqPhase.LatchBusFree ) { /* trans-mode is FIFOtest/option*/ dataByte = DevExt->TransferMode; ((PTRANSFER_MODE)&dataByte)->TransferGo = 0; ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; /* TransferModeSet*/ SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); /* Save AckCounter*/ DevExt->ActiveLogicalUnit->AckCounter = DevExt->ActiveLogicalUnit->TransferedLength; if ( DevExt->ScsiState == SC_COMPLETE ) { nin_done(DevExt, XS_NOERROR/*SRB_STATUS_NO_DEVICE*/); DevExt->ScsiState = SC_BUSFREE; DevExt->IntWait = FALSE; return; } else if (DevExt->ScsiState == SC_DISCONNECT ) { DevExt->ScsiState = SC_BUSFREE; return; } targetState = &DevExt->TargetState[DevExt ->TargetId]; if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } DevExt->ScsiState = SC_BUSFREE; return; } if(!DevExt->ActiveLogicalUnit->ActiveLuRequest) { return; } /* 1016 */ (*(u_char *)&IrqPhase) &= 0x7; DevExt->ScsiPrePhase = (*(u_char *)&IrqPhase); switch (DevExt->ScsiPrePhase) { case BP_COMMAND: Ns3SendCDB(DevExt); /*Start commans phase*/ break; case BP_DATA_IN: Ns3DataInPhase(DevExt); /* Start data phase*/ break; case BP_DATA_OUT: Ns3DataOutPhase(DevExt); /* Start data phase*/ break; case BP_STATUS: Ns3Status(DevExt); break; case BP_MESSAGE_IN: Ns3MessageIn(DevExt); break; case BP_MESSAGE_OUT: Ns3MessageOut(DevExt); break; default: DevExt->ScsiState = SC_COMPLETE; break; } } /* end Ns3RunPhase()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3DataInPhase // // Routine Description: // // This routine sets the DmaPending flag in the device extension, // calls the OS-specific driver to set up the system DMA chip, // and returns. Control is received again in DmaStarted when the DMA // setup is complete. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // TRUE if DMA started // FALSE if missed request // //----------------------------------------------------------------------- */ void Ns3DataInPhase( IN pnin_softc DevExt ) { u_char targetId = DevExt->TargetId; u_char devType; /* u_long TransferLength = DevExt->CurDataLength;*/ DevExt->InterruptPending = FALSE; /* flag clear*/ DevExt->DmaPending = TRUE; devType = DevExt->DeviceType[targetId]; /*1014*/ if (!DevExt) { Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt NULL\n")); return; } if (!(DevExt->ActiveLogicalUnit) ) { Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt->ActiveLogicalUnit NULL\n")); return; } if (!(DevExt->ActiveLogicalUnit->ActiveLuRequest) ) { Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt->ActiveLogicalUnit->ActiveLuRequest NULL\n")); return; } if (( DevExt->ActiveLogicalUnit-> ActiveLuRequest->datalen < 0x100 ) || ( DevExt->ActiveLogicalUnit-> ActiveLuRequest->datalen & 0x33 ) ) { Ns3SlowRead ( DevExt ); /* Not divaid less than 256, */ return; } switch ( devType ) { case 0: case 5: Ns3BurstRead( DevExt ); break; default: Ns3SpotRead ( DevExt ); break; } } /* end Ns3DataInPhase()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3DataOutPhase // // Routine Description: // // This routine sets the DmaPending flag in the device extension, // calls the OS-specific driver to set up the system DMA chip, // and returns. Control is received again in DmaStarted when the DMA // setup is complete. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // TRUE if DMA started // FALSE if missed request // //----------------------------------------------------------------------- */ void Ns3DataOutPhase( IN pnin_softc DevExt ) { u_char targetId = DevExt->TargetId; u_char devType; u_char dataByte; if(!DevExt) { Ns3DebugPrint(0x10,( "Ns3DataOutPhase DevExt=NULL!\n")); return; } if(!DevExt->ActiveLogicalUnit) { Ns3DebugPrint(0x10,( "Ns3DataOutPhase ActiveLogicalUnit=NULL!\n")); return; } if(!DevExt->ActiveLogicalUnit->ActiveLuRequest) { Ns3DebugPrint(0x10,( "Ns3DataOutPhase ActiveLuRequest=NULL!\n")); return; } DevExt->InterruptPending = FALSE; /* flag clear*/ DevExt->DmaPending = TRUE; devType = DevExt->DeviceType[targetId]; if ( (DevExt->ActiveLogicalUnit-> ActiveLuRequest->datalen < 0x100) || (DevExt->ActiveLogicalUnit-> ActiveLuRequest->datalen & 3) ) { Ns3SlowWrite ( DevExt ); /* Smaller than 256 or x/4 != 0 ? */ return; } dataByte = DevExt->TransferMode; /* Set TransferMode in FIFOTest / Option */ /* munya.. */ Ns3SpotWrite ( DevExt ); } /* end Ns3DataOutPhase()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3SendCDB // // Routine Description: // // Send the SCSI Command Descriptor Block (CDB) to the indicated target/lun. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- */ void Ns3SendCDB( IN pnin_softc DevExt ) { int baseAddress = DevExt->BaseAddress; u_char dataByte; dataByte = SCSI_READ(baseAddress, SCSIBUSMON); if ( ((PSCSI_BUS_MONITOR)&dataByte)->Scsi_ATN ) { /* Still ATN ?*/ /* SCSI-1 Device */ dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* ATN off*/ } /* Clear transfer counter*/ dataByte = 0; ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; ((PPOINTER_CLEAR)&dataByte)->AckCounterClear = 1; ((PPOINTER_CLEAR)&dataByte)->ReqCounterClear = 1; ((PPOINTER_CLEAR)&dataByte)->HostCounterClear = 1; SCSI_WRITE(baseAddress, POINTERCLR, dataByte); DevExt->ActiveLogicalUnit->AckCounter = 0; DevExt->ActiveLogicalUnit->HostCounter = 0; /* send CDB*/ dataByte = 0; ((PCOMMAND_CONTROL)&dataByte)->AutoCommandGo = 1; ((PCOMMAND_CONTROL)&dataByte)->ClrCommandPointer = 1; SCSI_WRITE(baseAddress, COMMANDCTRL, dataByte); DevExt->ScsiState = SC_UNDETERMINED; /* // Set up the running data pointer info for a possible data transfer. */ DevExt->CurDataPointer = DevExt->ActiveLogicalUnit->SavedDataPointer; DevExt->CurDataLength = DevExt->ActiveLogicalUnit->SavedDataLength; DevExt->ActiveLogicalUnit->TransferedLength = 0; /* Enable Interrupt */ DevExt->InterruptPending = TRUE; } /* end Ns3SendCDB()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3MessageOut // // Routine Description: // // This routine will sent the message to the target. // //----------------------------------------------------------------------- */ void Ns3MessageOut( IN pnin_softc DevExt ) { int baseAddress = DevExt->BaseAddress; u_char dataByte; u_char * msg = &DevExt->MessageBuffer[0]; IRQ_STATUS IrqStatus; /* MessageOut,NoOperation*/ if ( DevExt->MessageCount == 0 ) { DevExt->MessageBuffer[0] = MSG_NOOP; /* MSG_NOOP 0x08 */ DevExt->MessageCount = 1; } do { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); if (IrqStatus.ScsiIrqStatus) { break; } dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; if ( dataByte == BM_MESSAGE_OUT ) { if ( DevExt->MessageCount == 1) { /* last byte ?*/ dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; /* ATN Off !*/ SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); } /* message output*/ SCSI_WRITE(baseAddress ,SCSIDATAWITHACK, *msg); Ns3WaitForAckOff(DevExt); msg++; DevExt->MessageCount--; } } while ( DevExt->MessageCount != 0 ); /* phase change. Off ATN */ if ( IrqStatus.ScsiIrqStatus && DevExt->MessageCount != 0) { dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ATN Off !*/ } DevExt->ScsiState = SC_UNDETERMINED; } /* end Ns3MessageOut()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3MessageIn // // Routine Description: // // This routine will receive the message from the target. // //----------------------------------------------------------------------- */ void Ns3MessageIn( IN pnin_softc DevExt ) { PSPECIFIC_LU_EXTENSION luExtension; struct scsi_xfer * srb; int baseAddress = DevExt->BaseAddress; u_char * msg = &DevExt->MessageBuffer[0]; u_char dataByte; IRQ_STATUS IrqStatus; u_long MessageCount = 0; boolean NegAck = TRUE; PSPECIFIC_TARGET_EXTENSION targetState; DevExt->MessageCount = 0; luExtension = DevExt->ActiveLogicalUnit; if ( luExtension ) { /* reselection = NULL*/ srb = luExtension->ActiveLuRequest; targetState = &DevExt->TargetState[srb ->sc_link->target]; } else { return; } /* // --- message first byte // read Ninja */ dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; /* message in phase? is &req?*/ if ( dataByte == BM_MESSAGE_IN ) { /* read msg byte*/ *msg = SCSI_READ(baseAddress, SCSIDATAIN); /* srb->SCp.Message = *msg;*/ dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK On !*/ /* if return value is FALSE? */ Ns3WaitForReqOff(DevExt); /* REQ off ?*/ /* //--- Identify Message ? ---- */ if ( *msg & MSG_IDENTIFYFLAG ) {/* 0x80 = MSG_IDENTIFYFLAG ? */ DevExt->TargetLun = *msg & 0xf; /* now reselecting?*/ if ( DevExt->ScsiState == SC_RESELECT ) { Ns3ProcessReselection(DevExt); } } else { DevExt->ScsiState = SC_UNDETERMINED; switch ( *msg ) { case MSG_CMDCOMPLETE : DevExt->ScsiState = SC_COMPLETE; break; case MSG_DISCONNECT : /* srb->device->disconnect = 1;*/ DevExt->ScsiState = SC_DISCONNECT; dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK off !*/ return; break; case MSG_SAVEDATAPOINTER : MessageCount = 1; /* Wait DISCONNECT msg*/ DevExt->ScsiState = SC_DISCONNECT; luExtension->SavedDataPointer = DevExt->CurDataPointer; luExtension->SavedDataLength = DevExt->CurDataLength; break; case MSG_RESTOREPOINTERS: DevExt->CurDataPointer = luExtension->SavedDataPointer; DevExt->CurDataLength = luExtension->SavedDataLength; break; case MSG_EXTENDED : MessageCount = 6; /* max-len ext-msg*/ if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) MessageCount = 4; NegAck = FALSE; /* Not NEG ACK at last byte*/ break; case MSG_MESSAGE_REJECT: Ns3DebugPrint(0x008, ("MSG_MESSAGE_REJECT\n")); if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } break; } } dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK Off !*/ msg++; DevExt->MessageCount ++; } /********************************************************/ /* --- get next-message*/ *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); while ( !(IrqStatus.ScsiIrqStatus)) { /* still phase-chg*/ dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; /* no next-msg & control-line not message-in*/ /*-[v0.50] for OLY MO*/ /* if ((MessageCount == 0) && ((dataByte & 0x7) != BP_MESSAGE_IN) )*/ /* break;*/ /* Is mgs-in phase & req ?*/ if ( dataByte == BM_MESSAGE_IN ) { *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); /*if PhaseChange here,maybe Reselection Message*/ if ( IrqStatus.ScsiIrqStatus ) break; *msg = SCSI_READ(baseAddress, SCSIDATAIN);/* read msg-byte */ if ( *msg == MSG_DISCONNECT ) { Ns3DebugPrint(0x008, ("MsgIn:msg == MSG_DISCONNECT\n")); /* srb->device->disconnect = 1;*/ DevExt->ScsiState = SC_DISCONNECT; } dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK On !*/ /* if return value is FALSE? */ Ns3WaitForReqOff(DevExt); /* REQ Off ?*/ if ( ( MessageCount != 1) || ( MessageCount == 1 && NegAck )) { dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte);/* ACK Off !*/ } msg++; DevExt->MessageCount ++; if ( MessageCount != 0 ) MessageCount--; /* if Neg ACK at last Byte Mod, finish*/ if ( MessageCount == 0 && !NegAck ) break; } *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); } /* while ( !(IrqStatus.ScsiIrqStatus)); wait for PhaseChange */ if (DevExt->MessageBuffer[0] == MSG_EXT_SDTR ) { dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; /* ACK Off !*/ if (Ns3MessageDecode( DevExt )) /* Is Message after Decode*/ ((PSCSI_BUS_CONTROL)&dataByte)->ScsiATN = 1; /* ATN On !*/ SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); } } /* end Ns3MessageIn()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3Status // // Routine Description: // // This routine will obtain the status from the target. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- */ void Ns3Status( IN pnin_softc DevExt ) { u_char status; /* u_char srbStatus;*/ u_char dataByte; struct scsi_xfer *srb ; /*= DevExt->ActiveLogicalUnit->ActiveLuRequest;*/ int baseAddress = DevExt->BaseAddress; if(!DevExt->ActiveLogicalUnit) { /* panic("Ns3Status:DevExt->ActiveLogicalUnit == NULL[1]");*/ Ns3DebugPrint(0x008, ("Ns3Status:DevExt->ActiveLogicalUnit == NULL \n")); return; } srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; if(!srb) { Ns3DebugPrint(0x008, ("Ns3Status srb = null!! \n")); return; } dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; if ( dataByte == BM_STATUS ) { /* Is Status Phase &req ?*/ status = SCSI_READ(baseAddress, SCSIDATAWITHACK);/* read Status byte*/ /* srb->SCp.Status = status;*/ switch (status) { case SCSI_CONDITION_MET: /* srb->flags |= WAS_SENSE;*/ case SCSI_OK: case SCSI_INTERM: case SCSI_INTERMEDIATE_COND_MET: if ( (srb->cmd) && /* this line added at 1014 */ (srb->cmd->opcode == 0x12) && (srb->sc_link->lun == 0) ){ /* !! */ DevExt->DeviceType[srb->sc_link->target] = *(u_char *)(srb->data); if ( DevExt->DeviceType[srb->sc_link->target] == 6 || /*+[v1.02]*/ DevExt->DeviceType[srb->sc_link->target] == 3) { PSPECIFIC_TARGET_EXTENSION targetState; targetState = &DevExt-> TargetState[srb->sc_link->target]; targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; } } srb->datalen = /*datalen = srb->DataTransferLength = */ DevExt->ActiveLogicalUnit->TransferedLength ; /* srbStatus = SRB_STATUS_SUCCESS;*/ break; case SCSI_CHECK: case SCSI_COMMAND_TERMINATED: /* srbStatus = SRB_STATUS_ERROR;*/ break; case SCSI_BUSY: case SCSI_RESERVATION_CONFLICT: case SCSI_QUEUE_FULL: default: /* srbStatus = SRB_STATUS_BUSY;*/ break; } Ns3WaitForAckOff(DevExt); /********************************************************/ /* If some error condition already occurred (e.g., parity error), we'll*/ /* let that one take priority.*/ /********************************************************/ /* if (srb->SrbStatus == SRB_STATUS_PENDING) srb->SrbStatus = srbStatus; */ } /* if BM_STATUS*/ DevExt->ScsiState = SC_UNDETERMINED; } /* end Ns3Status()*/ /* //----------------------------------------------------------------------- // Routine Name: // Ns3WaitForAckOff // // Routine Description: // Spin checking the status of the Ns3 adapter until it indicates that // the SCSI ACK line is Low // // Return Value: // TRUE - indicates that the SCSI REQUEST line was Negated in time. // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST // line. //----------------------------------------------------------------------- */ boolean Ns3WaitForAckOff( pnin_softc DevExt ) { int baseAddress = DevExt->BaseAddress; u_long spinCount = REQUEST_SPIN_WAIT; u_char dataByte; do { dataByte = SCSI_READ(baseAddress, SCSIBUSMON); if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_ACK ) {/* ACK Off ?*/ return TRUE; } DELAY(2); } while (spinCount--); nin_done(DevExt, XS_TIMEOUT); return FALSE; } /* end Ns3WaitForAckOff()*/ /* //----------------------------------------------------------------------- // Routine Name: // // Ns3WaitForReqOff // // Routine Description: // // Spin checking the status of the Ns3 adapter until it indicates that // the SCSI REQUEST line is high. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // TRUE - indicates that the SCSI REQUEST line was asserted in time. // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST // line. //----------------------------------------------------------------------- */ boolean Ns3WaitForReqOff( pnin_softc DevExt ) { int baseAddress = DevExt->BaseAddress; u_long spinCount = REQUEST_SPIN_WAIT; u_char dataByte; do { dataByte = SCSI_READ(baseAddress, SCSIBUSMON); if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_REQ ) /* REQ Off ?*/ return TRUE; } while (spinCount--); /* must call scsi_done()? */ Ns3DebugPrint(0x04, ("TIMEOUT\n")); nin_done(DevExt, XS_TIMEOUT); return FALSE; } /* end Ns3WaitForReqOff()*/ /* //----------------------------------------------------------------------------- // RESELECTION //----------------------------------------------------------------------------- */ boolean Ns3ProcessReselection( IN pnin_softc DevExt ) { /* u_char pathId = 0;*/ PSPECIFIC_LU_EXTENSION luExtension; struct scsi_xfer *srb; PSPECIFIC_TARGET_EXTENSION targetState; int baseAddress = DevExt->BaseAddress; u_char dataByte; targetState = &DevExt->TargetState[DevExt->TargetId]; /********************************************************/ /* Get the specific logical unit extension.*/ /********************************************************/ luExtension = ScsiPortGetLogicalUnit(/*DevExt,pathId,*/ DevExt->TargetId, /* DevExt->sc_link.target,//argetId,*/ DevExt->TargetLun); /* sc_link.lun ->TargetLun );*/ DevExt->ActiveLogicalUnit = luExtension; if (!luExtension || !luExtension->ActiveLuRequest) { /* SP_INVALID_RESELECTION ErrorCode,*/ Ns3DebugPrint(0x10,( "Reselection Failed.\n")); /* // Send an abort message. Put the message-in the buffer, set the // state, indicate that a disconnect is expected after this, and // set the attention signal. */ DevExt->MessageBuffer[0] = MSG_ABORT; DevExt->MessageCount = 1; /* // // The target and logical unit specified are not valid. A // MESSAGE REJECT message has been set up. Set ATN and accept the // message. // */ dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); /* ATN ON !-> send-mdg mode*/ ((PSCSI_BUS_CONTROL)&dataByte)->ScsiATN = 1; /* ACK Off !*/ ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); nin_done(DevExt,XS_BUSY); return(FALSE); } Ns3DebugPrint(0x10,( "Ns3ProResel: Resel Start ID=%d\n", DevExt->TargetId)); srb = luExtension->ActiveLuRequest; Ns3SetTransferMode( DevExt ); /* TransferModeSet*/ /* // // A reselection has been completed. Set the active logical unit, // restore the active data pointer, set the state. // In addition, any adapter flags set by a pending select must be // cleared using the disconnect mask. // */ DevExt->CurDataPointer = luExtension->SavedDataPointer; DevExt->CurDataLength = luExtension->SavedDataLength; DevExt->MessageCount = 0; dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; /* ACK Off !*/ SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); return(TRUE); } boolean Ns3MessageDecode( IN pnin_softc DevExt ) { struct scsi_xfer *srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; PSPECIFIC_TARGET_EXTENSION targetState = &DevExt->TargetState[srb ->sc_link->target]; PSCSI_EXMSG exMsg; long offset; long i; int flags; exMsg = (PSCSI_EXMSG)DevExt->MessageBuffer; switch (exMsg->MessageType) { case SCSIMESS_MODIFY_DATA_POINTER: /********************************************************/ /* Verify the message length.*/ /********************************************************/ if (exMsg->MessageLength != SCSIMESS_MODIFY_DATA_LENGTH) { /********************************************************/ /* Reject the message.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } /********************************************************/ /* Calculate the modification to be added to the data pointer.*/ /********************************************************/ offset = 0; for (i = 0; i < 4; i++) { /* ???? offset << 8;*/ offset += exMsg->ExArg.MODIFY.modifier[i]; } /********************************************************/ /* Verify that the new data pointer is still within the range*/ /* of the buffer.*/ /********************************************************/ if (DevExt->CurDataLength - offset > /* srb->DataTransferLength ||*/ srb->datalen ||/*srb->datalen ||*/ ((long) DevExt->CurDataLength - offset) < 0 ) { /********************************************************/ /* The new pointer is not valid, so reject the message.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } /********************************************************/ /* Everything has checked out, so update the pointer.*/ /********************************************************/ flags = splbio(); DevExt->CurDataPointer += offset; DevExt->CurDataLength -= offset; splx(flags); /********************************************************/ /* Everything is ok, so accept the message as is.*/ /********************************************************/ DevExt->MessageCount = 0; DevExt->ScsiState = SC_COMPLETE_OK; /*MessageAccepted;*/ return(FALSE); case SCSIMESS_SYNCHRONOUS_DATA_REQ: /********************************************************/ /* A SYNCHRONOUS DATA TRANSFER REQUEST message was received.*/ /* Make sure the length is correct.*/ /********************************************************/ if ( exMsg->MessageLength != SCSIMESS_SYNCH_DATA_LENGTH) { /********************************************************/ /* The length is invalid reject the message.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } /********************************************************/ /* If synchrouns negotiation has been disabled for this request,*/ /* then reject any synchronous messages; however, when synchronous*/ /* transfers are allowed then a new attempt can be made.*/ /********************************************************/ if (srb != NULL && !(targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) /* && srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER*/ ) { /********************************************************/ /* Reject the synchronous transfer message since synchonrous*/ /* transfers are not desired at this time.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } /********************************************************/ /* Call WdDecodeSynchronousMessage to decode the message and*/ /* formulate a response if necessary.*/ /* NcrDecodeSynchronousRequest will return FALSE if the*/ /* message is not accepable and should be rejected.*/ /********************************************************/ if (!Ns3DecodeSynchronousRequest( DevExt, targetState, srb->sc_link->target, (boolean)!(targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) )) { /********************************************************/ /* Indicate that a negotiation has been done in the logical*/ /* unit and clear the negotiation flags.*/ /********************************************************/ targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags &=~(PD_SYNCHRONOUS_TRANSFER_SENT); /********************************************************/ /* The message was not acceptable so send a MESSAGE_REJECT.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } /********************************************************/ /* If a reponse was expected, then set the state for a message-out.*/ /* Otherwise, NcrDecodeSynchronousRequest has put a reponse*/ /* in the message buffer to be returned to the target.*/ /********************************************************/ if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT){ /********************************************************/ /* We initiated the negotiation, so no response is necessary.*/ /********************************************************/ targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; return(FALSE); } /********************************************************/ /* Set up the state to send the reponse. The message count is*/ /* still correct.*/ /********************************************************/ DevExt->ScsiState = SC_MSG_OUT;/* MessageOut;*/ targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; return(TRUE); case SCSIMESS_WIDE_DATA_REQUEST: /********************************************************/ /* A WIDE DATA TRANSFER REQUEST message was received.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); default: /********************************************************/ /* This is an unknown or illegal message, so send message REJECT.*/ /********************************************************/ DevExt->MessageCount = 1; DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } } /* //----------------------------------------------------------------------------- // SYNCHRONOUS_DATA_REQ // //Routine Description: Ns3DecodeSynchronousRequest // // This function decodes the synchronous data transfer request message from // the target. It will update the synchronous message in the buffer and the // synchronous transfer parameters in the logical unit extension. These // parameters are specific for the WD 53C9X protocol chip. The updated // message in the device extension message buffer might be returned to the // target. // // This function should be called before the final byte of the message is // accepted from the SCSI bus. // //Arguments: // // DevExt - Supplies a pointer to the adapter-specific device // extension. // // LuExtension - Supplies a pointer to the logical unit's device extension. // The synchronous transfer fields are updated in this structure to // reflect the new parameter in the message. // // ResponseExpected - When set, indicates that the target initiated the // negotiation and that it expects a response. // //Return Value: // // TRUE - Returned if the request is acceptable. // // FALSE - Returned if the request should be rejected and a synchronous // transfer should be used. // //----------------------------------------------------------------------------- */ boolean Ns3DecodeSynchronousRequest( IN pnin_softc DevExt, PSPECIFIC_TARGET_EXTENSION TargetState, IN u_char TargetID, IN boolean ResponseExpected ) { PSCSI_EXMSG exMsg; long period; long i; u_char dataByte; exMsg = (PSCSI_EXMSG) DevExt->MessageBuffer; /********************************************************/ /* Determine the transfer offset. It is the minimum of the SCSI protocol*/ /* chip's maximum offset and the requested offset.*/ /********************************************************/ if (exMsg->ExArg.SYNCS.ReqAckOffset > SYNCHRONOUS_OFFSET) { if (!ResponseExpected) { /********************************************************/ /* The negotiation failed for some reason, fall back to*/ /* asynchronous data transfer.*/ /********************************************************/ TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; return(FALSE); } exMsg->ExArg.SYNCS.ReqAckOffset = SYNCHRONOUS_OFFSET; TargetState->SynchronousOffset = SYNCHRONOUS_OFFSET; } else { TargetState->SynchronousOffset = exMsg->ExArg.SYNCS.ReqAckOffset; } /********************************************************/ /* If the offset requests asynchronous transfers then set the default*/ /* period and return.*/ /********************************************************/ if (exMsg->ExArg.SYNCS.ReqAckOffset == ASYNCHRONOUS_OFFSET) { TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->AckWidth = 0; return(TRUE); } /********************************************************/ /* Check to see if the period is less than the SCSI protocol chip can*/ /* use. If it is then update the message with our minimum and return.*/ /********************************************************/ if (exMsg->ExArg.SYNCS.TransferPeriod < SYNCHRONOUS_PERIOD ) { if (!ResponseExpected) { /********************************************************/ /* The negotiation failed for some reason, fall back to*/ /* asynchronous data transfer.*/ /********************************************************/ TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; return(FALSE); } exMsg->ExArg.SYNCS.TransferPeriod = SYNCHRONOUS_PERIOD; } period = exMsg->ExArg.SYNCS.TransferPeriod; for ( i=0; i= SyncTable[i].StartPeriod) && (period <= SyncTable[i].EndPeriod) ) break; } if (i >= SYNC_TABLE_MAX) { /********************************************************/ /* The requested transfer period is too long for the SCSI protocol*/ /* chip. Fall back to synchronous and reject the request.*/ /********************************************************/ TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; return(FALSE); } else { TargetState->SynchronousPeriod = SyncTable[i].TransferPeriod; TargetState->AckWidth = SyncTable[i].AckWidth; } /********************************************************/ /* Set the synchronous data transfer parameter registers*/ /* to the new values. These must be set before a data transfer*/ /* is started. If a response message is received then the parameters*/ /* must be reset.*/ /********************************************************/ dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = TargetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = TargetState->SynchronousOffset; SCSI_WRITE( DevExt->BaseAddress, ACKWIDTH,TargetState->AckWidth); SCSI_WRITE( DevExt->BaseAddress, SYNCREG ,dataByte); return(TRUE); }