--- linux/drivers/scsi/Makefile.ORIG Wed Oct 30 23:05:58 1996 +++ linux/drivers/scsi/Makefile Fri Dec 6 21:03:09 1996 @@ -177,6 +177,22 @@ endif endif +ifeq ($(CONFIG_SCSI_DC390T),y) +L_OBJS += tmscsim.o +else + ifeq ($(CONFIG_SCSI_DC390T),m) + M_OBJS += tmscsim.o + endif +endif + +ifeq ($(CONFIG_SCSI_DC390W),y) +L_OBJS += tmscsiw.o +else + ifeq ($(CONFIG_SCSI_DC390W),m) + M_OBJS += tmscsiw.o + endif +endif + ifeq ($(CONFIG_SCSI_AM53C974),y) L_OBJS += AM53C974.o else --- linux/drivers/scsi/Config.in.ORIG Wed Feb 5 19:31:55 1997 +++ linux/drivers/scsi/Config.in Mon Jan 20 00:45:21 1997 @@ -70,6 +70,10 @@ dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI fi dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI +if [ "$CONFIG_PCI" = "y" ]; then +dep_tristate 'Tekram DC-390W/U/F (T) SCSI support' CONFIG_SCSI_DC390W $CONFIG_SCSI +dep_tristate 'Tekram DC-390(T) SCSI support' CONFIG_SCSI_DC390T $CONFIG_SCSI +fi dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then --- linux/drivers/scsi/hosts.c.ORIG Wed Nov 13 01:52:39 1996 +++ linux/drivers/scsi/hosts.c Fri Dec 6 21:03:09 1996 @@ -153,6 +153,14 @@ #include "NCR53c406a.h" #endif +#ifdef CONFIG_SCSI_DC390T +#include "dc390.h" +#endif + +#ifdef CONFIG_SCSI_DC390W +#include "dc390w.h" +#endif + #ifdef CONFIG_SCSI_AM53C974 #include "AM53C974.h" #endif @@ -293,6 +301,12 @@ #endif #ifdef CONFIG_SCSI_EATA EATA, +#endif +#ifdef CONFIG_SCSI_DC390W + DC390WUF, +#endif +#ifdef CONFIG_SCSI_DC390T + DC390_T, #endif #ifdef CONFIG_SCSI_AM53C974 AM53C974, --- linux/include/linux/proc_fs.h.ORIG Tue Dec 3 02:23:38 1996 +++ linux/include/linux/proc_fs.h Wed Feb 5 20:15:03 1997 @@ -132,6 +132,8 @@ PROC_SCSI_ULTRASTOR, PROC_SCSI_7000FASST, PROC_SCSI_EATA2X, + PROC_SCSI_DC390WUF, + PROC_SCSI_DC390T, PROC_SCSI_AM53C974, PROC_SCSI_SSC, PROC_SCSI_NCR53C406A, --- linux/Documentation/Configure.help.ORIG Tue Dec 3 02:34:10 1996 +++ linux/Documentation/Configure.help Fri Dec 6 21:03:11 1996 @@ -1664,12 +1664,27 @@ and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. +Tekram DC390W/U/F (T) SCSI support +CONFIG_SCSI_DC390W + This driver supports the Tekram DC390W/U/F (T) PCI SCSI host adapters with + the NCR/Symbios 53c825/875 chips. If you have a DC390 (T) adaptor with the + Am53C974A chip use the DC390(T) driver. + +Tekram DC390(T) SCSI support +CONFIG_SCSI_DC390T + This driver supports the Tekram DC390(T) PCI SCSI Hostadapter with + the Am53C974A chip. If you have a DC390W/U/F adaptor with the NCR/Symbios + chips use the DC390W/U/F driver. + Don't use the AM53/79C974 driver if you select this driver. + AM53/79C974 PCI SCSI support CONFIG_SCSI_AM53C974 This is support for the AM53/79C974 SCSI host adapters. Please read drivers/scsi/README.AM53C974 for details. Also, the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO, is for you. + Use the native DC390 driver if you've got a Tekram DC390(T) PCI-SCSI + host adapter. IOMEGA Parallel Port ZIP drive SCSI support CONFIG_SCSI_PPA --- linux/include/linux/pci.h.ORIG Sat Nov 23 23:29:11 1996 +++ linux/include/linux/pci.h Fri Dec 6 21:03:11 1996 @@ -228,6 +228,7 @@ #define PCI_DEVICE_ID_NCR_53C820 0x0002 #define PCI_DEVICE_ID_NCR_53C825 0x0003 #define PCI_DEVICE_ID_NCR_53C815 0x0004 +#define PCI_DEVICE_ID_NCR_53C875 0x000f #define PCI_VENDOR_ID_ATI 0x1002 #define PCI_DEVICE_ID_ATI_68800 0x4158 --- linux/drivers/pci/pci.c.ORIG Wed Feb 5 19:28:37 1997 +++ linux/drivers/pci/pci.c Mon Jan 20 00:45:21 1997 @@ -47,6 +47,7 @@ DEVICE( NCR, NCR_53C820, "53c820"), DEVICE( NCR, NCR_53C825, "53c825"), DEVICE( NCR, NCR_53C815, "53c815"), + DEVICE( NCR, NCR_53C875, "53c875"), DEVICE( ATI, ATI_68800, "68800AX"), DEVICE( ATI, ATI_215CT222, "215CT222"), DEVICE( ATI, ATI_210888CX, "210888CX"), --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/dc390.h Thu Feb 6 11:04:16 1997 @@ -0,0 +1,147 @@ +/*********************************************************************** + * FILE NAME : DC390.H * + * BY : C.L. Huang * + * Description: Device Driver for Tekram DC-390(T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + +/* Kernel version autodetection */ + +#include +/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ +#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) + +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,50) +#define VERSION_ELF_1_2_13 +#elseif LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,95) +#define VERSION_1_3_85 +#else +#define VERSION_2_0_0 +#endif + +/* + * AMD 53C974 driver, header file + */ + +#ifndef DC390_H +#define DC390_H + +#if defined(HOSTS_C) || defined(MODULE) + +#ifdef VERSION_2_0_0 +#include +#else +#include +#endif + +extern int DC390_detect(Scsi_Host_Template *psht); +extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); +extern int DC390_abort(Scsi_Cmnd *cmd); + +#ifdef VERSION_2_0_0 +extern int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags); +#else +extern int DC390_reset(Scsi_Cmnd *cmd); +#endif + +#ifdef VERSION_ELF_1_2_13 +extern int DC390_bios_param(Disk *disk, int devno, int geom[]); +#else +extern int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]); +#endif + +#ifdef MODULE +static int DC390_release(struct Scsi_Host *); +#else +#define DC390_release NULL +#endif + +#ifndef VERSION_ELF_1_2_13 +extern struct proc_dir_entry proc_scsi_tmscsim; +extern int tmscsim_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); +#endif + +#ifdef VERSION_2_0_0 + +#define DC390_T { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsim, /* *proc_dir */ \ + tmscsim_proc_info, /* (*proc_info)() */ \ + "Tekram DC390(T) V1.11 Feb-05-1997", /* *name */ \ + DC390_detect, \ + DC390_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + SG_ALL, \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + + +#ifdef VERSION_1_3_85 + +#define DC390_T { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsim, /* *proc_dir */ \ + tmscsim_proc_info, /* (*proc_info)() */ \ + "Tekram DC390(T) V1.11 Feb-05-1997", /* *name */ \ + DC390_detect, \ + DC390_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + SG_ALL, \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + + +#ifdef VERSION_ELF_1_2_13 + +#define DC390_T { \ + NULL, \ + NULL, \ + "Tekram DC390(T) V1.11 Feb-05-1997",\ + DC390_detect, \ + DC390_release, \ + NULL, /* info */ \ + NULL, /* command, deprecated */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + 16,/* old (SG_ALL) */ \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + +#endif /* defined(HOSTS_C) || defined(MODULE) */ + +#endif /* DC390_H */ --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/tmscsim.h Fri Dec 6 20:54:48 1996 @@ -0,0 +1,680 @@ +/*********************************************************************** +;* File Name : TMSCSIM.H * +;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter * +;* Device Driver * +;***********************************************************************/ + +#ifndef TMSCSIM_H +#define TMSCSIM_H + +#define IRQ_NONE 255 + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef unsigned int UINT; + +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef ULONG *PULONG; +typedef Scsi_Host_Template *PSHT; +typedef struct Scsi_Host *PSH; +typedef Scsi_Device *PSCSIDEV; +typedef Scsi_Cmnd *PSCSICMD; +typedef void *PVOID; +typedef struct scatterlist *PSGL, SGL; + + +/*;-----------------------------------------------------------------------*/ +typedef struct _SyncMsg +{ +UCHAR ExtendMsg; +UCHAR ExtMsgLen; +UCHAR SyncXferReq; +UCHAR Period; +UCHAR ReqOffset; +} SyncMsg; +/*;-----------------------------------------------------------------------*/ +typedef struct _Capacity +{ +ULONG BlockCount; +ULONG BlockLength; +} Capacity; +/*;-----------------------------------------------------------------------*/ +typedef struct _SGentry +{ +ULONG SGXferDataPtr; +ULONG SGXferDataLen; +} SGentry; + +typedef struct _SGentry1 +{ +ULONG SGXLen; +ULONG SGXPtr; +} SGentry1, *PSGE; + + +#define MAX_ADAPTER_NUM 4 +#define MAX_DEVICES 10 +#define MAX_SG_LIST_BUF 16 +#define MAX_CMD_QUEUE 20 +#define MAX_CMD_PER_LUN 8 +#define MAX_SCSI_ID 8 +#define MAX_SRB_CNT MAX_CMD_QUEUE+4 +#define END_SCAN 2 + +#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ + +/* +;----------------------------------------------------------------------- +; SCSI Request Block +;----------------------------------------------------------------------- +*/ +struct _SRB +{ +UCHAR CmdBlock[12]; + +struct _SRB *pNextSRB; +struct _DCB *pSRBDCB; +PSCSICMD pcmd; +PSGL pSegmentList; + +ULONG PhysSRB; +ULONG TotalXferredLen; +ULONG SGPhysAddr; /*;a segment starting address */ +ULONG SGToBeXferLen; /*; to be xfer length */ + +SGL Segmentx; /* make a one entry of S/G list table */ + +PUCHAR pMsgPtr; +USHORT SRBState; +USHORT Revxx2; /* ??? */ + +UCHAR MsgInBuf[6]; +UCHAR MsgOutBuf[6]; + +UCHAR AdaptStatus; +UCHAR TargetStatus; +UCHAR MsgCnt; +UCHAR EndMessage; +UCHAR TagNumber; +UCHAR SGcount; +UCHAR SGIndex; +UCHAR IORBFlag; /*;81h-Reset, 2-retry */ + +UCHAR SRBStatus; +UCHAR RetryCnt; +UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ + /*; b4-settimeout,b5-Residual valid */ +UCHAR ScsiCmdLen; +UCHAR ScsiPhase; +UCHAR Reserved3[3]; /*;for dword alignment */ +ULONG Segment0[2]; +ULONG Segment1[2]; +}; + +typedef struct _SRB DC390_SRB, *PSRB; + +/* +;----------------------------------------------------------------------- +; Device Control Block +;----------------------------------------------------------------------- +*/ +struct _DCB +{ +struct _DCB *pNextDCB; +struct _ACB *pDCBACB; + +PSCSICMD pQIORBhead; +PSCSICMD pQIORBtail; +PSCSICMD AboIORBhead; +PSCSICMD AboIORBtail; +USHORT QIORBCnt; +USHORT AboIORBcnt; + +PSRB pWaitingSRB; +PSRB pWaitLast; +PSRB pGoingSRB; +PSRB pGoingLast; +PSRB pActiveSRB; +USHORT GoingSRBCnt; +USHORT WaitSRBCnt; /* ??? */ + +ULONG TagMask; + +USHORT MaxCommand; +USHORT AdaptIndex; /*; UnitInfo struc start */ +USHORT UnitIndex; /*; nth Unit on this card */ +UCHAR UnitSCSIID; /*; SCSI Target ID (SCSI Only) */ +UCHAR UnitSCSILUN; /*; SCSI Log. Unit (SCSI Only) */ + +UCHAR IdentifyMsg; +UCHAR CtrlR1; +UCHAR CtrlR3; +UCHAR CtrlR4; + +UCHAR InqDataBuf[8]; +UCHAR CapacityBuf[8]; +UCHAR DevMode; +UCHAR AdpMode; +UCHAR SyncMode; /*; 0:async mode */ +UCHAR NegoPeriod; /*;for nego. */ +UCHAR SyncPeriod; /*;for reg. */ +UCHAR SyncOffset; /*;for reg. and nego.(low nibble) */ +UCHAR UnitCtrlFlag; +UCHAR DCBFlag; +UCHAR DevType; +UCHAR Reserved2[3]; /*;for dword alignment */ +}; + +typedef struct _DCB DC390_DCB, *PDCB; +/* +;----------------------------------------------------------------------- +; Adapter Control Block +;----------------------------------------------------------------------- +*/ +struct _ACB +{ +ULONG PhysACB; +PSH pScsiHost; +struct _ACB *pNextACB; +USHORT IOPortBase; +USHORT Revxx1; /* ??? */ + +PDCB pLinkDCB; +PDCB pDCBRunRobin; +PDCB pActiveDCB; +PDCB pDCB_free; +PSRB pFreeSRB; +PSRB pTmpSRB; +USHORT SRBCount; +USHORT AdapterIndex; /*; nth Adapter this driver */ +USHORT max_id; +USHORT max_lun; + +UCHAR msgin123[4]; +UCHAR status; +UCHAR AdaptSCSIID; /*; Adapter SCSI Target ID */ +UCHAR AdaptSCSILUN; /*; Adapter SCSI LUN */ +UCHAR DeviceCnt; +UCHAR IRQLevel; +UCHAR TagMaxNum; +UCHAR ACBFlag; +UCHAR Gmode2; +UCHAR LUNchk; +UCHAR scan_devices; +UCHAR HostID_Bit; +UCHAR Reserved1[1]; /*;for dword alignment */ +UCHAR DCBmap[MAX_SCSI_ID]; +DC390_DCB DCB_array[MAX_DEVICES]; /* +74h, Len=3E8 */ +DC390_SRB SRB_array[MAX_SRB_CNT]; /* +45Ch, Len= */ +DC390_SRB TmpSRB; +}; + +typedef struct _ACB DC390_ACB, *PACB; + +/*;-----------------------------------------------------------------------*/ + + +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 + +/*;---UnitCtrlFlag */ +#define UNIT_ALLOCATED BIT0 +#define UNIT_INFO_CHANGED BIT1 +#define FORMATING_MEDIA BIT2 +#define UNIT_RETRY BIT3 + +/*;---UnitFlags */ +#define DASD_SUPPORT BIT0 +#define SCSI_SUPPORT BIT1 +#define ASPI_SUPPORT BIT2 + +/*;----SRBState machine definition */ +#define SRB_FREE 0 +#define SRB_WAIT BIT0 +#define SRB_READY BIT1 +#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/ +#define SRB_MSGIN BIT3 +#define SRB_MSGIN_MULTI BIT4 +#define SRB_COMMAND BIT5 +#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/ +#define SRB_DISCONNECT BIT7 +#define SRB_DATA_XFER BIT8 +#define SRB_XFERPAD BIT9 +#define SRB_STATUS BIT10 +#define SRB_COMPLETED BIT11 +#define SRB_ABORT_SENT BIT12 +#define DO_SYNC_NEGO BIT13 +#define SRB_UNEXPECT_RESEL BIT14 + +/*;---ACBFlag */ +#define RESET_DEV BIT0 +#define RESET_DETECT BIT1 +#define RESET_DONE BIT2 + +/*;---DCBFlag */ +#define ABORT_DEV_ BIT0 + +/*;---SRBstatus */ +#define SRB_OK BIT0 +#define ABORTION BIT1 +#define OVER_RUN BIT2 +#define UNDER_RUN BIT3 +#define PARITY_ERROR BIT4 +#define SRB_ERROR BIT5 + +/*;---SRBFlag */ +#define DATAOUT BIT7 +#define DATAIN BIT6 +#define RESIDUAL_VALID BIT5 +#define ENABLE_TIMER BIT4 +#define RESET_DEV0 BIT2 +#define ABORT_DEV BIT1 +#define AUTO_REQSENSE BIT0 + +/*;---Adapter status */ +#define H_STATUS_GOOD 0 +#define H_SEL_TIMEOUT 0x11 +#define H_OVER_UNDER_RUN 0x12 +#define H_UNEXP_BUS_FREE 0x13 +#define H_TARGET_PHASE_F 0x14 +#define H_INVALID_CCB_OP 0x16 +#define H_LINK_CCB_BAD 0x17 +#define H_BAD_TARGET_DIR 0x18 +#define H_DUPLICATE_CCB 0x19 +#define H_BAD_CCB_OR_SG 0x1A +#define H_ABORT 0x0FF + +/*; SCSI Status byte codes*/ +#define SCSI_STAT_GOOD 0x0 /*; Good status */ +#define SCSI_STAT_CHECKCOND 0x02 /*; SCSI Check Condition */ +#define SCSI_STAT_CONDMET 0x04 /*; Condition Met */ +#define SCSI_STAT_BUSY 0x08 /*; Target busy status */ +#define SCSI_STAT_INTER 0x10 /*; Intermediate status */ +#define SCSI_STAT_INTERCONDMET 0x14 /*; Intermediate condition met */ +#define SCSI_STAT_RESCONFLICT 0x18 /*; Reservation conflict */ +#define SCSI_STAT_CMDTERM 0x22 /*; Command Terminated */ +#define SCSI_STAT_QUEUEFULL 0x28 /*; Queue Full */ + +#define SCSI_STAT_UNEXP_BUS_F 0xFD /*; Unexpect Bus Free */ +#define SCSI_STAT_BUS_RST_DETECT 0xFE /*; Scsi Bus Reset detected */ +#define SCSI_STAT_SEL_TIMEOUT 0xFF /*; Selection Time out */ + +/*;---Sync_Mode */ +#define SYNC_DISABLE 0 +#define SYNC_ENABLE BIT0 +#define SYNC_NEGO_DONE BIT1 +#define WIDE_ENABLE BIT2 +#define WIDE_NEGO_DONE BIT3 +#define EN_TAG_QUEUING BIT4 +#define EN_ATN_STOP BIT5 + +#define SYNC_NEGO_OFFSET 15 + +/*;---SCSI bus phase*/ +#define SCSI_DATA_OUT 0 +#define SCSI_DATA_IN 1 +#define SCSI_COMMAND 2 +#define SCSI_STATUS_ 3 +#define SCSI_NOP0 4 +#define SCSI_NOP1 5 +#define SCSI_MSG_OUT 6 +#define SCSI_MSG_IN 7 + +/*;----SCSI MSG BYTE*/ +#define MSG_COMPLETE 0x00 +#define MSG_EXTENDED 0x01 +#define MSG_SAVE_PTR 0x02 +#define MSG_RESTORE_PTR 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_INITIATOR_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT_ 0x07 +#define MSG_NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define MSG_LINK_CMD_COMPL 0x0A +#define MSG_LINK_CMD_COMPL_FLG 0x0B +#define MSG_BUS_RESET 0x0C +#define MSG_ABORT_TAG 0x0D +#define MSG_SIMPLE_QTAG 0x20 +#define MSG_HEAD_QTAG 0x21 +#define MSG_ORDER_QTAG 0x22 +#define MSG_IDENTIFY 0x80 +#define MSG_HOST_ID 0x0C0 + +/*;----SCSI STATUS BYTE*/ +#define STATUS_GOOD 0x00 +#define CHECK_CONDITION_ 0x02 +#define STATUS_BUSY 0x08 +#define STATUS_INTERMEDIATE 0x10 +#define RESERVE_CONFLICT 0x18 + +/* cmd->result */ +#define STATUS_MASK_ 0xFF +#define MSG_MASK 0xFF00 +#define RETURN_MASK 0xFF0000 + +/* +** Inquiry Data format +*/ + +typedef struct _SCSIInqData { /* INQ */ + + UCHAR DevType; /* Periph Qualifier & Periph Dev Type*/ + UCHAR RMB_TypeMod; /* rem media bit & Dev Type Modifier */ + UCHAR Vers; /* ISO, ECMA, & ANSI versions */ + UCHAR RDF; /* AEN, TRMIOP, & response data format*/ + UCHAR AddLen; /* length of additional data */ + UCHAR Res1; /* reserved */ + UCHAR Res2; /* reserved */ + UCHAR Flags; /* RelADr,Wbus32,Wbus16,Sync,etc. */ + UCHAR VendorID[8]; /* Vendor Identification */ + UCHAR ProductID[16]; /* Product Identification */ + UCHAR ProductRev[4]; /* Product Revision */ + + +} SCSI_INQDATA, *PSCSI_INQDATA; + + +/* Inquiry byte 0 masks */ + + +#define SCSI_DEVTYPE 0x1F /* Peripheral Device Type */ +#define SCSI_PERIPHQUAL 0xE0 /* Peripheral Qualifier */ + + +/* Inquiry byte 1 mask */ + +#define SCSI_REMOVABLE_MEDIA 0x80 /* Removable Media bit (1=removable) */ + + +/* Peripheral Device Type definitions */ + +#define SCSI_DASD 0x00 /* Direct-access Device */ +#define SCSI_SEQACESS 0x01 /* Sequential-access device */ +#define SCSI_PRINTER 0x02 /* Printer device */ +#define SCSI_PROCESSOR 0x03 /* Processor device */ +#define SCSI_WRITEONCE 0x04 /* Write-once device */ +#define SCSI_CDROM 0x05 /* CD-ROM device */ +#define SCSI_SCANNER 0x06 /* Scanner device */ +#define SCSI_OPTICAL 0x07 /* Optical memory device */ +#define SCSI_MEDCHGR 0x08 /* Medium changer device */ +#define SCSI_COMM 0x09 /* Communications device */ +#define SCSI_NODEV 0x1F /* Unknown or no device type */ + +/* +** Inquiry flag definitions (Inq data byte 7) +*/ + +#define SCSI_INQ_RELADR 0x80 /* device supports relative addressing*/ +#define SCSI_INQ_WBUS32 0x40 /* device supports 32 bit data xfers */ +#define SCSI_INQ_WBUS16 0x20 /* device supports 16 bit data xfers */ +#define SCSI_INQ_SYNC 0x10 /* device supports synchronous xfer */ +#define SCSI_INQ_LINKED 0x08 /* device supports linked commands */ +#define SCSI_INQ_CMDQUEUE 0x02 /* device supports command queueing */ +#define SCSI_INQ_SFTRE 0x01 /* device supports soft resets */ + + +/* +;========================================================== +; EEPROM byte offset +;========================================================== +*/ +typedef struct _EEprom +{ +UCHAR EE_MODE1; +UCHAR EE_SPEED; +UCHAR xx1; +UCHAR xx2; +} EEprom, *PEEprom; + +#define EE_ADAPT_SCSI_ID 64 +#define EE_MODE2 65 +#define EE_DELAY 66 +#define EE_TAG_CMD_NUM 67 + +/*; EE_MODE1 bits definition*/ +#define PARITY_CHK_ BIT0 +#define SYNC_NEGO_ BIT1 +#define EN_DISCONNECT_ BIT2 +#define SEND_START_ BIT3 +#define TAG_QUEUING_ BIT4 + +/*; EE_MODE2 bits definition*/ +#define MORE2_DRV BIT0 +#define GREATER_1G BIT1 +#define RST_SCSI_BUS BIT2 +#define ACTIVE_NEGATION BIT3 +#define NO_SEEK BIT4 +#define LUN_CHECK BIT5 + +#define ENABLE_CE 1 +#define DISABLE_CE 0 +#define EEPROM_READ 0x80 + +/* +;========================================================== +; AMD 53C974 Registers bit Definition +;========================================================== +*/ +/* +;==================== +; SCSI Register +;==================== +*/ + +/*; Command Reg.(+0CH) */ +#define DMA_COMMAND BIT7 +#define NOP_CMD 0 +#define CLEAR_FIFO_CMD 1 +#define RST_DEVICE_CMD 2 +#define RST_SCSI_BUS_CMD 3 +#define INFO_XFER_CMD 0x10 +#define INITIATOR_CMD_CMPLTE 0x11 +#define MSG_ACCEPTED_CMD 0x12 +#define XFER_PAD_BYTE 0x18 +#define SET_ATN_CMD 0x1A +#define RESET_ATN_CMD 0x1B +#define SELECT_W_ATN 0x42 +#define SEL_W_ATN_STOP 0x43 +#define EN_SEL_RESEL 0x44 +#define SEL_W_ATN2 0x46 +#define DATA_XFER_CMD INFO_XFER_CMD + + +/*; SCSI Status Reg.(+10H) */ +#define INTERRUPT BIT7 +#define ILLEGAL_OP_ERR BIT6 +#define PARITY_ERR BIT5 +#define COUNT_2_ZERO BIT4 +#define GROUP_CODE_VALID BIT3 +#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0) + +/*; Interrupt Status Reg.(+14H) */ +#define SCSI_RESET BIT7 +#define INVALID_CMD BIT6 +#define DISCONNECTED BIT5 +#define SERVICE_REQUEST BIT4 +#define SUCCESSFUL_OP BIT3 +#define RESELECTED BIT2 +#define SEL_ATTENTION BIT1 +#define SELECTED BIT0 + +/*; Internal State Reg.(+18H) */ +#define SYNC_OFFSET_FLAG BIT3 +#define INTRN_STATE_MASK (BIT2+BIT1+BIT0) + +/*; Clock Factor Reg.(+24H) */ +#define CLK_FREQ_40MHZ 0 +#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0) +#define CLK_FREQ_30MHZ (BIT2+BIT1) +#define CLK_FREQ_25MHZ (BIT2+BIT0) +#define CLK_FREQ_20MHZ BIT2 +#define CLK_FREQ_15MHZ (BIT1+BIT0) +#define CLK_FREQ_10MHZ BIT1 + +/*; Control Reg. 1(+20H) */ +#define EXTENDED_TIMING BIT7 +#define DIS_INT_ON_SCSI_RST BIT6 +#define PARITY_ERR_REPO BIT4 +#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0) + +/*; Control Reg. 2(+2CH) */ +#define EN_FEATURE BIT6 +#define EN_SCSI2_CMD BIT3 + +/*; Control Reg. 3(+30H) */ +#define ID_MSG_CHECK BIT7 +#define EN_QTAG_MSG BIT6 +#define EN_GRP2_CMD BIT5 +#define FAST_SCSI BIT4 /* ;10MB/SEC */ +#define FAST_CLK BIT3 /* ;25 - 40 MHZ */ + +/*; Control Reg. 4(+34H) */ +#define EATER_12NS 0 +#define EATER_25NS BIT7 +#define EATER_35NS BIT6 +#define EATER_0NS (BIT7+BIT6) +#define NEGATE_REQACKDATA BIT2 +#define NEGATE_REQACK BIT3 +/* +;==================== +; DMA Register +;==================== +*/ +/*; DMA Command Reg.(+40H) */ +#define READ_DIRECTION BIT7 +#define WRITE_DIRECTION 0 +#define EN_DMA_INT BIT6 +#define MAP_TO_MDL BIT5 +#define DIAGNOSTIC BIT4 +#define DMA_IDLE_CMD 0 +#define DMA_BLAST_CMD BIT0 +#define DMA_ABORT_CMD BIT1 +#define DMA_START_CMD (BIT1+BIT0) + +/*; DMA Status Reg.(+54H) */ +#define PCI_MS_ABORT BIT6 +#define BLAST_COMPLETE BIT5 +#define SCSI_INTERRUPT BIT4 +#define DMA_XFER_DONE BIT3 +#define DMA_XFER_ABORT BIT2 +#define DMA_XFER_ERROR BIT1 +#define POWER_DOWN BIT0 + +/* +; DMA SCSI Bus and Ctrl.(+70H) +;EN_INT_ON_PCI_ABORT +*/ + +/* +;========================================================== +; SCSI Chip register address offset +;========================================================== +*/ +#define CtcReg_Low 0x00 +#define CtcReg_Mid 0x04 +#define ScsiFifo 0x08 +#define ScsiCmd 0x0C +#define Scsi_Status 0x10 +#define INT_Status 0x14 +#define Sync_Period 0x18 +#define Sync_Offset 0x1C +#define CtrlReg1 0x20 +#define Clk_Factor 0x24 +#define CtrlReg2 0x2C +#define CtrlReg3 0x30 +#define CtrlReg4 0x34 +#define CtcReg_High 0x38 +#define DMA_Cmd 0x40 +#define DMA_XferCnt 0x44 +#define DMA_XferAddr 0x48 +#define DMA_Wk_ByteCntr 0x4C +#define DMA_Wk_AddrCntr 0x50 +#define DMA_Status 0x54 +#define DMA_MDL_Addr 0x58 +#define DMA_Wk_MDL_Cntr 0x5C +#define DMA_ScsiBusCtrl 0x70 + +#define StcReg_Low CtcReg_Low +#define StcReg_Mid CtcReg_Mid +#define Scsi_Dest_ID Scsi_Status +#define Scsi_TimeOut INT_Status +#define Intern_State Sync_Period +#define Current_Fifo Sync_Offset +#define StcReg_High CtcReg_High + +#define am_target Scsi_Status +#define am_timeout INT_Status +#define am_seq_step Sync_Period +#define am_fifo_count Sync_Offset + + +#define DC390_read8(address) \ + inb(DC390_ioport + (address))) + +#define DC390_read16(address) \ + inw(DC390_ioport + (address))) + +#define DC390_read32(address) \ + inl(DC390_ioport + (address))) + +#define DC390_write8(address,value) \ + outb((value), DC390_ioport + (address))) + +#define DC390_write16(address,value) \ + outw((value), DC390_ioport + (address))) + +#define DC390_write32(address,value) \ + outl((value), DC390_ioport + (address))) + + +/* Configuration method #1 */ +#define PCI_CFG1_ADDRESS_REG 0xcf8 +#define PCI_CFG1_DATA_REG 0xcfc +#define PCI_CFG1_ENABLE 0x80000000 +#define PCI_CFG1_TUPPLE(bus, device, function, register) \ + (PCI_CFG1_ENABLE | (((bus) << 16) & 0xff0000) | \ + (((device) << 11) & 0xf800) | (((function) << 8) & 0x700)| \ + (((register) << 2) & 0xfc)) + +/* Configuration method #2 */ +#define PCI_CFG2_ENABLE_REG 0xcf8 +#define PCI_CFG2_FORWARD_REG 0xcfa +#define PCI_CFG2_ENABLE 0x0f0 +#define PCI_CFG2_TUPPLE(function) \ + (PCI_CFG2_ENABLE | (((function) << 1) & 0xe)) + + +#endif /* TMSCSIM_H */ --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/tmscsim.c Thu Feb 6 11:03:19 1997 @@ -0,0 +1,1930 @@ +/*********************************************************************** + * FILE NAME : TMSCSIM.C * + * BY : C.L. Huang, ching@tekram.com.tw * + * Description: Device Driver for Tekram DC-390(T) PCI SCSI * + * Bus Master Host Adapter * + * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * + ***********************************************************************/ +/* Minor enhancements and bugfixes by * + * Kurt Garloff * + ***********************************************************************/ +/* HISTORY: * + * * + * REV# DATE NAME DESCRIPTION * + * 1.00 04/24/96 CLH First release * + * 1.01 06/12/96 CLH Fixed bug of Media Change for Removable * + * Device, scan all LUN. Support Pre2.0.10 * + * 1.02 06/18/96 CLH Fixed bug of Command timeout ... * + * 1.03 09/25/96 KG Added tmscsim_proc_info() * + * 1.04 10/11/96 CLH Updating for support KV 2.0.x * + * 1.05 10/18/96 KG Fixed bug in DC390_abort(null ptr deref)* + * 1.06 10/25/96 KG Fixed module support * + * 1.07 11/09/96 KG Fixed tmscsim_proc_info() * + * 1.08 11/18/96 KG Fixed null ptr in DC390_Disconnect() * + * 1.09 11/30/96 KG Added register the allocated IO space * + * 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset * + * pending interrupt in DC390_detect() * + * 1.11 02/05/97 KG/CLH Fixeds problem with partitions greater * + * than 1GB * + ***********************************************************************/ + + +#define DC390_DEBUG + +#define SCSI_MALLOC + +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#if LINUX_VERSION_CODE < 66354 /* 1.3.50 */ +#include "../block/blk.h" +#else +#include +#endif + +#include "scsi.h" +#include "hosts.h" +#include "tmscsim.h" +#include "constants.h" +#include "sd.h" +#include + +#include "dc390.h" + +#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI + + +#ifndef VERSION_ELF_1_2_13 +struct proc_dir_entry proc_scsi_tmscsim ={ + PROC_SCSI_DC390T, 7 ,"tmscsim", + S_IFDIR | S_IRUGO | S_IXUGO, 2 + }; +#endif + +static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); + +static void SetXferRate( PACB pACB, PDCB pDCB ); +static void DC390_Disconnect( PACB pACB ); +static void DC390_Reselect( PACB pACB ); +static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DoingSRB_Done( PACB pACB ); +static void DC390_ScsiRstDetect( PACB pACB ); +static void DC390_ResetSCSIBus( PACB pACB ); +static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void EnableMsgOut2( PACB pACB, PSRB pSRB ); +static void EnableMsgOut( PACB pACB, PSRB pSRB ); +static void DC390_InvalidCmd( PACB pACB ); + +int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ); +void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); + +#ifdef MODULE +static int DC390_release(struct Scsi_Host *host); +static int DC390_shutdown (struct Scsi_Host *host); +#endif + + +static PSHT pSHT_start = NULL; +static PSH pSH_start = NULL; +static PSH pSH_current = NULL; +static PACB pACB_start= NULL; +static PACB pACB_current = NULL; +static PDCB pPrevDCB = NULL; +static USHORT adapterCnt = 0; +static USHORT InitialTime = 0; +static USHORT CurrSyncOffset = 0; +static ULONG mech1addr; +static UCHAR mech2bus, mech2Agent, mech2CfgSPenR; + +static PVOID DC390_phase0[]={ + DC390_DataOut_0, + DC390_DataIn_0, + DC390_Command_0, + DC390_Status_0, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOut_0, + DC390_MsgIn_0, + DC390_Nop_1 + }; + +static PVOID DC390_phase1[]={ + DC390_DataOutPhase, + DC390_DataInPhase, + DC390_CommandPhase, + DC390_StatusPhase, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOutPhase, + DC390_MsgInPhase, + DC390_Nop_1, + }; + +UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; + + +UCHAR clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; + +UCHAR baddevname1[2][28] ={ + "SEAGATE ST3390N 9546", + "HP C3323-300 4269"}; + +#define BADDEVCNT 2 + + +/*********************************************************************** + * + * + * + **********************************************************************/ +static void +QLinkcmd( PSCSICMD cmd, PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + if( !pDCB->QIORBCnt ) + { + pDCB->pQIORBhead = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + else + { + pcmd = pDCB->pQIORBtail; + pcmd->next = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + + restore_flags(flags); +} + + +static PSCSICMD +Getcmd( PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + pcmd = pDCB->pQIORBhead; + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + + restore_flags(flags); + return( pcmd ); +} + + +static PSRB +GetSRB( PACB pACB ) +{ + ULONG flags; + PSRB pSRB; + + save_flags(flags); + cli(); + + pSRB = pACB->pFreeSRB; + if( pSRB ) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + restore_flags(flags); + return( pSRB ); +} + + +static void +RewaitSRB0( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + ULONG flags; + + save_flags(flags); + cli(); + + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + restore_flags(flags); +} + + +static void +RewaitSRB( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + ULONG flags; + UCHAR bval; + + save_flags(flags); + cli(); + pDCB->GoingSRBCnt--; + psrb1 = pDCB->pGoingSRB; + if( pSRB == psrb1 ) + { + pDCB->pGoingSRB = psrb1->pNextSRB; + } + else + { + while( pSRB != psrb1->pNextSRB ) + psrb1 = psrb1->pNextSRB; + psrb1->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb1; + } + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ + restore_flags(flags); +} + + +static void +DoWaitingSRB( PACB pACB ) +{ + ULONG flags; + PDCB ptr, ptr1; + PSRB pSRB; + + save_flags(flags); + cli(); + + if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + { + ptr = pACB->pDCBRunRobin; + if( !ptr ) + { + ptr = pACB->pLinkDCB; + pACB->pDCBRunRobin = ptr; + } + ptr1 = ptr; + for( ;ptr1; ) + { + pACB->pDCBRunRobin = ptr1->pNextDCB; + if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || + !( pSRB = ptr1->pWaitingSRB ) ) + { + if(pACB->pDCBRunRobin == ptr) + break; + ptr1 = ptr1->pNextDCB; + } + else + { + if( !DC390_StartSCSI(pACB, ptr1, pSRB) ) + { + ptr1->GoingSRBCnt++; + if( ptr1->pWaitLast == pSRB ) + { + ptr1->pWaitingSRB = NULL; + ptr1->pWaitLast = NULL; + } + else + { + ptr1->pWaitingSRB = pSRB->pNextSRB; + } + pSRB->pNextSRB = NULL; + + if( ptr1->pGoingSRB ) + ptr1->pGoingLast->pNextSRB = pSRB; + else + ptr1->pGoingSRB = pSRB; + ptr1->pGoingLast = pSRB; + } + break; + } + } + } + restore_flags(flags); + return; +} + + +static void +SRBwaiting( PDCB pDCB, PSRB pSRB) +{ + if( pDCB->pWaitingSRB ) + { + pDCB->pWaitLast->pNextSRB = pSRB; + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + } + else + { + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } +} + + +static void +SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) +{ + ULONG flags; + PDCB pDCB; + + save_flags(flags); + cli(); + + pDCB = pSRB->pSRBDCB; + if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) + { + SRBwaiting(pDCB, pSRB); + goto SND_EXIT; + } + + if( pDCB->pWaitingSRB ) + { + SRBwaiting(pDCB, pSRB); +/* pSRB = GetWaitingSRB(pDCB); */ + pSRB = pDCB->pWaitingSRB; + pDCB->pWaitingSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + + if( !DC390_StartSCSI(pACB, pDCB, pSRB) ) + { + pDCB->GoingSRBCnt++; + if( pDCB->pGoingSRB ) + { + pDCB->pGoingLast->pNextSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + else + { + pDCB->pGoingSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + } + else + RewaitSRB0( pDCB, pSRB ); + +SND_EXIT: + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, + * void (*done)(Scsi_Cmnd *)) + * + * Purpose : enqueues a SCSI command + * + * Inputs : cmd - SCSI command, done - function called on completion, with + * a pointer to the command descriptor. + * + * Returns : 0 + * + ***********************************************************************/ + +int +DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +{ + USHORT ioport, i; + Scsi_Cmnd *pcmd; + struct Scsi_Host *psh; + PACB pACB; + PDCB pDCB; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + + psh = cmd->host; + pACB = (PACB ) psh->hostdata; + ioport = pACB->IOPortBase; + +#ifdef DC390_DEBUG0 +/* if(pACB->scan_devices) */ + printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun); +#endif + + if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + + if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) ) + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return( 0 ); + } + + if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { + if( pACB->DeviceCnt < MAX_DEVICES ) + { + pACB->DCBmap[cmd->target] |= (1 << cmd->lun); + pDCB = pACB->pDCB_free; +#ifdef DC390_DEBUG0 + printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); +#endif + DC390_initDCB( pACB, pDCB, cmd ); + } + else /* ???? */ + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + } + else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + else + { + pDCB = pACB->pLinkDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + } +#ifdef DC390_DEBUG0 + printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); +#endif + } + + cmd->scsi_done = done; + cmd->result = 0; + + save_flags(flags); + cli(); + + if( pDCB->QIORBCnt ) + { + QLinkcmd( cmd, pDCB ); + pcmd = Getcmd( pDCB ); + } + else + pcmd = cmd; + + pSRB = GetSRB( pACB ); + + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return(0); + } + +/* BuildSRB(pSRB); */ + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + pSRB->ScsiCmdLen = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGPhysAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return(0); +} + + +static void +DoNextCmd( PACB pACB, PDCB pDCB ) +{ + Scsi_Cmnd *pcmd; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + USHORT i; + + + if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) + return; + save_flags(flags); + cli(); + + pcmd = Getcmd( pDCB ); + pSRB = GetSRB( pACB ); + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return; + } + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + pSRB->ScsiCmdLen = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGPhysAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function: + * DC390_bios_param + * + * Description: + * Return the disk geometry for the given SCSI device. + ***********************************************************************/ +#ifdef VERSION_ELF_1_2_13 +int DC390_bios_param(Disk *disk, int devno, int geom[]) +#else +int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]) +#endif +{ + int heads, sectors, cylinders; + PACB pACB; + + pACB = (PACB) disk->device->host->hostdata; + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) + { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + + +/*********************************************************************** + * Function : int DC390_abort (Scsi_Cmnd *cmd) + * + * Purpose : Abort an errant SCSI command + * + * Inputs : cmd - command to abort + * + * Returns : 0 on success, -1 on failure. + ***********************************************************************/ + +int +DC390_abort (Scsi_Cmnd *cmd) +{ + ULONG flags; + PACB pACB; + PDCB pDCB, pdcb; + PSRB pSRB, psrb; + USHORT count, i; + PSCSICMD pcmd, pcmd1; + int status; + + +#ifdef DC390_DEBUG0 + printk("DC390 : Abort Cmd."); +#endif + + save_flags(flags); + cli(); + + pACB = (PACB) cmd->host->hostdata; + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + goto NOT_RUN; + } + + if( pDCB->QIORBCnt ) + { + pcmd = pDCB->pQIORBhead; + if( pcmd == cmd ) + { + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + for( count = pDCB->QIORBCnt, i=0; inext == cmd ) + { + pcmd1 = pcmd->next; + pcmd->next = pcmd1->next; + pcmd1->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + else + { + pcmd = pcmd->next; + } + } + } + + pSRB = pDCB->pWaitingSRB; + if( !pSRB ) + goto ON_GOING; + if( pSRB->pcmd == cmd ) + { + pDCB->pWaitingSRB = pSRB->pNextSRB; + goto IN_WAIT; + } + else + { + psrb = pSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + while( psrb->pNextSRB->pcmd != cmd ) + { + psrb = psrb->pNextSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + } + pSRB = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pWaitLast ) + pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */ +IN_WAIT: + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + cmd->next = NULL; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + +ON_GOING: + pSRB = pDCB->pGoingSRB; + for( count = pDCB->GoingSRBCnt, i=0; ipcmd != cmd ) + pSRB = pSRB->pNextSRB; + else + { + if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) + { + status = SCSI_ABORT_BUSY; + goto ABO_X; + } + else + { + status = SCSI_ABORT_SNOOZE; + goto ABO_X; + } + } + } + +NOT_RUN: + status = SCSI_ABORT_NOT_RUNNING; + +ABO_X: + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); + restore_flags(flags); + return( status ); +} + + +static void +ResetDevParam( PACB pACB ) +{ + PDCB pDCB, pdcb; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + pDCB->SyncMode &= ~SYNC_NEGO_DONE; + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->CtrlR3 = FAST_CLK; + pDCB->CtrlR4 &= NEGATE_REQACKDATA; + pDCB->CtrlR4 |= EATER_25NS; + pDCB = pDCB->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +RecoverSRB( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for (i=0; ipNextSRB; +/* RewaitSRB( pDCB, psrb ); */ + if( pdcb->pWaitingSRB ) + { + psrb2->pNextSRB = pdcb->pWaitingSRB; + pdcb->pWaitingSRB = psrb2; + } + else + { + pdcb->pWaitingSRB = psrb2; + pdcb->pWaitLast = psrb2; + psrb2->pNextSRB = NULL; + } + } + pdcb->GoingSRBCnt = 0; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +/*********************************************************************** + * Function : int DC390_reset (Scsi_Cmnd *cmd, ...) + * + * Purpose : perform a hard reset on the SCSI bus + * + * Inputs : cmd - command which caused the SCSI RESET + * + * Returns : 0 on success. + ***********************************************************************/ + +#ifdef VERSION_2_0_0 +int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) +#else +int DC390_reset (Scsi_Cmnd *cmd) +#endif +{ + USHORT ioport; + unsigned long flags; + PACB pACB; + UCHAR bval; + USHORT i; + + +#ifdef DC390_DEBUG1 + printk("DC390: RESET,"); +#endif + + pACB = (PACB ) cmd->host->hostdata; + ioport = pACB->IOPortBase; + save_flags(flags); + cli(); + bval = inb(ioport+CtrlReg1); + bval |= DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* disable interrupt */ + DC390_ResetSCSIBus( pACB ); + for( i=0; i<500; i++ ) + udelay(1000); + bval = inb(ioport+CtrlReg1); + bval &= ~DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* re-enable interrupt */ + + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + bval = CLEAR_FIFO_CMD; + outb(bval,ioport+ScsiCmd); + + ResetDevParam( pACB ); + DoingSRB_Done( pACB ); + pACB->pActiveDCB = NULL; + + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + + restore_flags(flags); +#ifdef DC390_DEBUG1 + printk("DC390: RESET1,"); +#endif + return( SCSI_RESET_SUCCESS ); +} + + +#include "scsiiom.c" + + +/*********************************************************************** + * Function : static void DC390_initDCB + * + * Purpose : initialize the internal structures for a given DCB + * + * Inputs : cmd - pointer to this scsi cmd request block structure + * + ***********************************************************************/ +void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) +{ + PEEprom prom; + UCHAR bval; + USHORT index; + + if( pACB->DeviceCnt == 0 ) + { + pACB->pLinkDCB = pDCB; + pACB->pDCBRunRobin = pDCB; + pDCB->pNextDCB = pDCB; + pPrevDCB = pDCB; + } + else + pPrevDCB->pNextDCB = pDCB; + + pDCB->pDCBACB = pACB; + pDCB->QIORBCnt = 0; + pDCB->UnitSCSIID = cmd->target; + pDCB->UnitSCSILUN = cmd->lun; + pDCB->pWaitingSRB = NULL; + pDCB->pGoingSRB = NULL; + pDCB->GoingSRBCnt = 0; + pDCB->pActiveSRB = NULL; + pDCB->TagMask = 0; + pDCB->MaxCommand = 1; + pDCB->AdaptIndex = pACB->AdapterIndex; + index = pACB->AdapterIndex; + pDCB->DCBFlag = 0; + + prom = (PEEprom) &eepromBuf[index][cmd->target << 2]; + pDCB->DevMode = prom->EE_MODE1; + pDCB->AdpMode = eepromBuf[index][EE_MODE2]; + + if( pDCB->DevMode & EN_DISCONNECT_ ) + bval = 0xC0; + else + bval = 0x80; + bval |= cmd->lun; + pDCB->IdentifyMsg = bval; + + pDCB->SyncMode = 0; + if( pDCB->DevMode & SYNC_NEGO_ ) + { + if( !(cmd->lun) || CurrSyncOffset ) + pDCB->SyncMode = SYNC_ENABLE; + } + + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2; + + pDCB->CtrlR1 = pACB->AdaptSCSIID; + if( pDCB->DevMode & PARITY_CHK_ ) + pDCB->CtrlR1 |= PARITY_ERR_REPO; + + pDCB->CtrlR3 = FAST_CLK; + + pDCB->CtrlR4 = EATER_25NS; + if( pDCB->AdpMode & ACTIVE_NEGATION) + pDCB->CtrlR4 |= NEGATE_REQACKDATA; +} + + +/*********************************************************************** + * Function : static void DC390_initSRB + * + * Purpose : initialize the internal structures for a given SRB + * + * Inputs : psrb - pointer to this scsi request block structure + * + ***********************************************************************/ +void DC390_initSRB( PSRB psrb ) +{ +#ifndef VERSION_ELF_1_2_13 +#ifdef DC390_DEBUG0 + printk("DC390 init: %08lx %08lx,",(ULONG)psrb,(ULONG)virt_to_bus(psrb)); +#endif + psrb->PhysSRB = virt_to_bus( psrb ); +#else + psrb->PhysSRB = (ULONG) psrb; +#endif +} + + +void DC390_linkSRB( PACB pACB ) +{ + USHORT count, i; + PSRB psrb; + + count = pACB->SRBCount; + + for( i=0; i< count; i++) + { + if( i != count - 1) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + else + pACB->SRB_array[i].pNextSRB = NULL; + psrb = (PSRB) &pACB->SRB_array[i]; + DC390_initSRB( psrb ); + } +} + + +/*********************************************************************** + * Function : static void DC390_initACB + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +void DC390_initACB( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) +{ + PACB pACB; + USHORT i; + + psh->can_queue = MAX_CMD_QUEUE; + psh->cmd_per_lun = MAX_CMD_PER_LUN; + psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID]; + psh->io_port = io_port; + psh->n_io_port = 0x80; + psh->irq = Irq; + + pACB = (PACB) psh->hostdata; + +#ifndef VERSION_ELF_1_2_13 + psh->max_id = 8; +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + psh->max_lun = 8; + else +#endif + psh->max_lun = 1; +#endif + + pACB->max_id = 7; + if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) + pACB->max_id--; +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->max_lun = 7; + else +#endif + pACB->max_lun = 0; + + pACB->pScsiHost = psh; + pACB->IOPortBase = (USHORT) io_port; + pACB->pLinkDCB = NULL; + pACB->pDCBRunRobin = NULL; + pACB->pActiveDCB = NULL; + pACB->pFreeSRB = pACB->SRB_array; + pACB->SRBCount = MAX_SRB_CNT; + pACB->AdapterIndex = index; + pACB->status = 0; + pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; + pACB->HostID_Bit = (1 << pACB->AdaptSCSIID); + pACB->AdaptSCSILUN = 0; + pACB->DeviceCnt = 0; + pACB->IRQLevel = Irq; + pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2; + pACB->ACBFlag = 0; + pACB->scan_devices = 1; + pACB->Gmode2 = eepromBuf[index][EE_MODE2]; + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->LUNchk = 1; + pACB->pDCB_free = &pACB->DCB_array[0]; + DC390_linkSRB( pACB ); + pACB->pTmpSRB = &pACB->TmpSRB; + DC390_initSRB( pACB->pTmpSRB ); + for(i=0; iDCBmap[i] = 0; +} + + +/*********************************************************************** + * Function : static int DC390_initAdapter + * + * Purpose : initialize the SCSI chip ctrl registers + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) +{ + USHORT ioport; + UCHAR bval; + PACB pACB, pacb; + USHORT used_irq = 0; + + pacb = pACB_start; + if( pacb != NULL ) + { + for ( ; (pacb != (PACB) -1) ; ) + { + if( pacb->IRQLevel == Irq ) + { + used_irq = 1; + break; + } + else + pacb = pacb->pNextACB; + } + } + + if( !used_irq ) + { +#ifdef VERSION_ELF_1_2_13 + if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim")) +#else + if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsim", NULL)) +#endif + { + printk("DC390: register IRQ error!\n"); + return( -1 ); + } + } + + request_region(io_port,psh->n_io_port,"tmscsim"); + + ioport = (USHORT) io_port; + + pACB = (PACB) psh->hostdata; + bval = SEL_TIMEOUT; /* 250ms selection timeout */ + outb(bval,ioport+Scsi_TimeOut); + + bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */ + outb(bval,ioport+Clk_Factor); + + bval = NOP_CMD; /* NOP cmd - clear command register */ + outb(bval,ioport+ScsiCmd); + + bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */ + outb(bval,ioport+CtrlReg2); + + bval = FAST_CLK; /* fast clock */ + outb(bval,ioport+CtrlReg3); + + bval = EATER_25NS; + if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) + bval |= NEGATE_REQACKDATA; + outb(bval,ioport+CtrlReg4); + + bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */ + outb(bval,ioport+CtrlReg1); + + return(0); +} + + +void +DC390_EnableCfg( USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + + if(mechnum == 2) + { + outb(mech2bus, PCI_CFG2_FORWARD_REG); + outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG); + } + else + { + regval &= 0xFC; + wlval = mech1addr; + wlval |= (((ULONG)regval) & 0xff); + outl(wlval, PCI_CFG1_ADDRESS_REG); + } +} + + +void +DC390_DisableCfg( USHORT mechnum ) +{ + + if(mechnum == 2) + outb(0, PCI_CFG2_ENABLE_REG); + else + outl(0, PCI_CFG1_ADDRESS_REG); +} + + +UCHAR +DC390_inByte( USHORT mechnum, UCHAR regval ) +{ + UCHAR bval; + ULONG wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg( mechnum, regval ); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= ((USHORT) regval) & 0xff; + bval = inb(wval); + } + else + { + regval &= 3; + bval = inb(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(bval); +} + + +USHORT +DC390_inWord( USHORT mechnum, UCHAR regval ) +{ + USHORT wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wval = inw(wval); + } + else + { + regval &= 3; + wval = inw(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(wval); +} + + +ULONG +DC390_inDword(USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + ULONG flags; + USHORT wval; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wlval = inl(wval); + } + else + { + wlval = inl(PCI_CFG1_DATA_REG); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(wlval); +} + + +void +DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ) +{ + + USHORT wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + outb(bval, wval); + } + else + { + regval &= 3; + outb(bval, PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); +} + + +void +DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ) +{ + + UCHAR bval; + + bval = 0; + if(mode == ENABLE_CE) + *regval = 0xc0; + else + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + if(mode == DISABLE_CE) + DC390_OutB(mechnum,*regval,bval); + udelay(160); +} + + +void +DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ) +{ + UCHAR bval; + + bval = 0; + if(Carry) + { + bval = 0x40; + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + } + udelay(160); + bval |= 0x80; + DC390_OutB(mechnum,*regval,bval); + udelay(160); + bval = 0; + DC390_OutB(mechnum,*regval,bval); + udelay(160); +} + + +UCHAR +DC390_EEpromInDO( USHORT mechnum ) +{ + UCHAR bval,regval; + + regval = 0x80; + bval = 0x80; + DC390_OutB(mechnum,regval,bval); + udelay(160); + bval = 0x40; + DC390_OutB(mechnum,regval,bval); + udelay(160); + regval = 0x0; + bval = DC390_inByte(mechnum,regval); + if(bval == 0x22) + return(1); + else + return(0); +} + + +USHORT +EEpromGetData1( USHORT mechnum ) +{ + UCHAR i; + UCHAR carryFlag; + USHORT wval; + + wval = 0; + for(i=0; i<16; i++) + { + wval <<= 1; + carryFlag = DC390_EEpromInDO(mechnum); + wval |= carryFlag; + } + return(wval); +} + + +void +DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ) +{ + UCHAR i,j; + USHORT carryFlag; + + carryFlag = 1; + j = 0x80; + for(i=0; i<9; i++) + { + DC390_EEpromOutDI(mechnum,regval,carryFlag); + carryFlag = (EEpromCmd & j) ? 1 : 0; + j >>= 1; + } +} + + +void +DC390_ReadEEprom( USHORT mechnum, USHORT index ) +{ + UCHAR regval,cmd; + PUSHORT ptr; + USHORT i; + + ptr = (PUSHORT) &eepromBuf[index][0]; + cmd = EEPROM_READ; + for(i=0; i<0x40; i++) + { + DC390_EnDisableCE(ENABLE_CE, mechnum, ®val); + DC390_Prepare(mechnum, ®val, cmd); + *ptr = EEpromGetData1(mechnum); + ptr++; + cmd++; + DC390_EnDisableCE(DISABLE_CE,mechnum,®val); + } +} + + +USHORT +DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ) +{ + USHORT wval, rc, *ptr; + UCHAR i; + + DC390_ReadEEprom( MechNum, index ); + wval = 0; + ptr = (PUSHORT) &eepromBuf[index][0]; + for(i=0; i<128 ;i+=2, ptr++) + wval += *ptr; + if( wval == 0x1234 ) + rc = 0; + else + rc = -1; + return( rc ); +} + + +USHORT +DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum ) +{ + USHORT devnum; + + devnum = BusDevFunNum; + + if(Mechnum == 2) + { + if(devnum & 0x80) + return(-1); + mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */ + mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */ + mech2Agent |= 0xc0; + mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */ + mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20; + } + else /* use mech #1 method */ + { + mech1addr = 0x80000000 | ((ULONG)devnum << 8); + } + return(0); +} + +/*********************************************************************** + * Function : static int DC390_init (struct Scsi_Host *host) + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : host - pointer to this host adapter's structure/ + * + * Preconditions : when this function is called, the chip_type + * field of the pACB structure MUST have been set. + ***********************************************************************/ + +static int +DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum) +{ + PSH psh; + PACB pACB; + + if( !DC390_CheckEEpromCheckSum( MechNum, index) ) + { + psh = scsi_register( psht, sizeof(DC390_ACB) ); + if( !psh ) + return( -1 ); + if( !pSH_start ) + { + pSH_start = psh; + pSH_current = psh; + } + else + { + pSH_current->next = psh; + pSH_current = psh; + } + +#ifdef DC390_DEBUG0 + printk("DC390: pSH = %8x,", (UINT) psh); + printk("DC390: Index %02i,", index); +#endif + + DC390_initACB( psh, io_port, Irq, index ); + if( !DC390_initAdapter( psh, io_port, Irq, index ) ) + { + pACB = (PACB) psh->hostdata; + if( !pACB_start ) + { + pACB_start = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + else + { + pACB_current->pNextACB = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + +#ifdef DC390_DEBUG0 + printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", + (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); + printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n", + sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) ); +#endif + + } + else + { + pSH_start = NULL; + scsi_unregister( psh ); + return( -1 ); + } + return( 0 ); + } + else + { + printk("DC390_init: EEPROM reading error!\n"); + return( -1 ); + } +} + + +/*********************************************************************** + * Function : int DC390_detect(Scsi_Host_Template *psht) + * + * Purpose : detects and initializes AMD53C974 SCSI chips + * that were autoprobed, overridden on the LILO command line, + * or specified at compile time. + * + * Inputs : psht - template for this SCSI adapter + * + * Returns : number of host adapters detected + * + ***********************************************************************/ + +int +DC390_detect(Scsi_Host_Template *psht) +{ +#ifdef FOR_PCI_OK + UCHAR pci_bus, pci_device_fn; + int error = 0; + USHORT chipType = 0; + USHORT i; +#endif + + UCHAR irq; + UCHAR istatus; +#ifndef VERSION_ELF_1_2_13 + UINT io_port; +#else + ULONG io_port; +#endif + USHORT adaptCnt = 0; /* Number of boards detected */ + USHORT pci_index = 0; /* Device index to PCI BIOS calls */ + USHORT MechNum, BusDevFunNum; + ULONG wlval; + +#ifndef VERSION_ELF_1_2_13 + psht->proc_dir = &proc_scsi_tmscsim; +#endif + + InitialTime = 1; + pSHT_start = psht; + pACB_start = NULL; + + MechNum = 1; + for( ; (MechNum < 3) && (!adaptCnt); MechNum++) + { + BusDevFunNum = 0; + for (; adaptCnt < MAX_ADAPTER_NUM ;) + { + if( !DC390_ToMech( MechNum, BusDevFunNum) ) + { + wlval = DC390_inDword( MechNum, PCI_VENDOR_ID); + if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+ + PCI_VENDOR_ID_AMD) ) + { + io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE; + irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE); +#ifdef DC390_DEBUG0 + printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); +#endif + if( !DC390_init(psht, io_port, irq, pci_index, MechNum) ) + { + adaptCnt++; + pci_index++; + istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */ +#ifdef DC390_DEBUG0 + printk("DC390: Mech=%2x,\n",(UCHAR) MechNum); +#endif + } + } + } + if( BusDevFunNum != 0xfff8 ) + BusDevFunNum += 8; /* next device # */ + else + break; + } + } + +#ifdef FOR_PCI_OK + if ( pcibios_present() ) + { + for (i = 0; i < MAX_ADAPTER_NUM; ++i) + { + if( !pcibios_find_device( PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD53C974, + pci_index, &pci_bus, &pci_device_fn) ) + { + chipType = PCI_DEVICE_ID_AMD53C974; + pci_index++; + } + + if( chipType ) + { + + error = pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &io_port); + error |= pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + if( error ) + { + printk("DC390_detect: reading configuration registers error!\n"); + InitialTime = 0; + return( 0 ); + } + + (USHORT) io_port = (USHORT) io_port & 0xFFFE; +#ifdef DC390_DEBUG0 + printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); +#endif + if( !DC390_init(psht, io_port, irq, i) ) + adaptCnt++; + chipType = 0; + } + else + break; + } + } +#endif + + InitialTime = 0; + adapterCnt = adaptCnt; + return( adaptCnt ); +} + + +#ifndef VERSION_ELF_1_2_13 + +/******************************************************************** + * Function: tmscsim_set_info() + * + * Purpose: Set adapter info (!) + * + * Not yet implemented + * + *******************************************************************/ + +int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt) +{ + return(-ENOSYS); /* Currently this is a no-op */ +} + +/******************************************************************** + * Function: tmscsim_proc_info(char* buffer, char **start, + * off_t offset, int length, int hostno, int inout) + * + * Purpose: return SCSI Adapter/Device Info + * + * Input: buffer: Pointer to a buffer where to write info + * start : + * offset: + * hostno: Host adapter index + * inout : Read (=0) or set(!=0) info + * + * Output: buffer: contains info + * length; length of info in buffer + * + * return value: length + * + ********************************************************************/ + +/* KG: proc_info taken from driver aha152x.c */ + +#undef SPRINTF +#define SPRINTF(args...) pos += sprintf(pos, ## args) + +#define YESNO(YN)\ +if (YN) SPRINTF(" Yes ");\ +else SPRINTF(" No ") + +int tmscsim_proc_info(char *buffer, char **start, + off_t offset, int length, int hostno, int inout) +{ + int dev, spd, spd1; + char *pos = buffer; + PSH shpnt; + PACB acbpnt; + PDCB dcbpnt; + unsigned long flags; +/* Scsi_Cmnd *ptr; */ + + acbpnt = pACB_start; + + while(acbpnt != (PACB)-1) + { + shpnt = acbpnt->pScsiHost; + if (shpnt->host_no == hostno) break; + acbpnt = acbpnt->pNextACB; + } + + if (acbpnt == (PACB)-1) return(-ESRCH); + if(!shpnt) return(-ESRCH); + + if(inout) /* Has data been written to the file ? */ + return(tmscsim_set_info(buffer, length, shpnt)); + + SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, "); + SPRINTF("Driver Version 1.11, 1996/02/05\n"); + + save_flags(flags); + cli(); + + SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); + SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex); + SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase); + SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel); + + SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun); + SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); + + SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); + + SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); + + SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n"); + + dcbpnt = acbpnt->pLinkDCB; + for (dev = 0; dev < acbpnt->DeviceCnt; dev++) + { + SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); + YESNO(dcbpnt->DevMode & PARITY_CHK_); + YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE); + YESNO(dcbpnt->DevMode & EN_DISCONNECT_); + YESNO(dcbpnt->DevMode & SEND_START_); + YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING); + SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); + if (dcbpnt->SyncOffset & 0x0f) + { + spd = 1000/(dcbpnt->NegoPeriod <<2); + spd1 = 1000%(dcbpnt->NegoPeriod <<2); + spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2); + SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f)); + } + else SPRINTF("\n"); + /* Add more info ...*/ + dcbpnt = dcbpnt->pNextDCB; + } + + restore_flags(flags); + *start = buffer + offset; + + if (pos - buffer < offset) + return 0; + else if (pos - buffer - offset < length) + return pos - buffer - offset; + else + return length; +} +#endif /* VERSION_ELF_1_2_13 */ + + +#ifdef MODULE + +/*********************************************************************** + * Function : static int DC390_shutdown (struct Scsi_Host *host) + * + * Purpose : does a clean (we hope) shutdown of the SCSI chip. + * Use prior to dumping core, unloading the driver, etc. + * + * Returns : 0 on success + ***********************************************************************/ +static int +DC390_shutdown (struct Scsi_Host *host) +{ + UCHAR bval; + USHORT ioport; + unsigned long flags; + PACB pACB = (PACB)(host->hostdata); + + ioport = (unsigned int) pACB->IOPortBase; + + save_flags (flags); + cli(); + +/* pACB->soft_reset(host); */ + +#ifdef DC390_DEBUG0 + printk("DC390: shutdown,"); +#endif + + bval = inb(ioport+CtrlReg1); + bval |= DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* disable interrupt */ + DC390_ResetSCSIBus( pACB ); + + restore_flags (flags); + return( 0 ); +} + + +int DC390_release(struct Scsi_Host *host) +{ + int irq_count; + struct Scsi_Host *tmp; + + DC390_shutdown (host); + + if (host->irq != IRQ_NONE) + { + for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) + { + if ( tmp->irq == host->irq ) + ++irq_count; + } + if (irq_count == 1) + { +#ifdef DC390_DEBUG0 + printk("DC390: Free IRQ %i.",host->irq); +#endif +#ifndef VERSION_ELF_1_2_13 + free_irq(host->irq,NULL); +#else + free_irq(host->irq); +#endif + } + } + + release_region(host->io_port,host->n_io_port); + + return( 1 ); +} + +Scsi_Host_Template driver_template = DC390_T; +#include "scsi_module.c" +#endif /* def MODULE */ + --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/scsiiom.c Fri Dec 6 20:54:48 1996 @@ -0,0 +1,1540 @@ +/*********************************************************************** + * FILE NAME : SCSIIOM.C * + * BY : C.L. Huang, ching@tekram.com.tw * + * Description: Device Driver for Tekram DC-390 (T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + + +static USHORT +DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + USHORT ioport, rc; + UCHAR bval, bval1, i, cnt; + PUCHAR ptr; + ULONG wlval; + + pSRB->TagNumber = 31; + ioport = pACB->IOPortBase; + bval = pDCB->UnitSCSIID; + outb(bval,ioport+Scsi_Dest_ID); + bval = pDCB->SyncPeriod; + outb(bval,ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb(bval,ioport+Sync_Offset); + bval = pDCB->CtrlR1; + outb(bval,ioport+CtrlReg1); + bval = pDCB->CtrlR3; + outb(bval,ioport+CtrlReg3); + bval = pDCB->CtrlR4; + outb(bval,ioport+CtrlReg4); + bval = CLEAR_FIFO_CMD; /* Flush FIFO */ + outb(bval,ioport+ScsiCmd); + + pSRB->ScsiPhase = SCSI_NOP0; + bval = pDCB->IdentifyMsg; + if( !(pDCB->SyncMode & EN_ATN_STOP) ) + { + if( (pSRB->CmdBlock[0] == INQUIRY) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + bval &= 0xBF; /* NO disconnection */ + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + if( pDCB->SyncMode & SYNC_ENABLE ) + { + if( !(pDCB->IdentifyMsg & 7) || + (pSRB->CmdBlock[0] != INQUIRY) ) + { + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_MSGOUT; + } + } + } + else + { + if(pDCB->SyncMode & EN_TAG_QUEUING) + { + outb(bval,ioport+ScsiFifo); + bval = MSG_SIMPLE_QTAG; + outb(bval,ioport+ScsiFifo); + wlval = 1; + bval = 0; + while( wlval & pDCB->TagMask ) + { + wlval = wlval << 1; + bval++; + } + outb(bval,ioport+ScsiFifo); + pDCB->TagMask |= wlval; + pSRB->TagNumber = bval; + bval1 = SEL_W_ATN2; + pSRB->SRBState = SRB_START_; + } + else + { + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + } + } + + if( pSRB->SRBFlag & AUTO_REQSENSE ) + { + bval = REQUEST_SENSE; + outb(bval,ioport+ScsiFifo); + bval = pDCB->IdentifyMsg << 5; + outb(bval,ioport+ScsiFifo); + bval = 0; + outb(bval,ioport+ScsiFifo); + outb(bval,ioport+ScsiFifo); + bval = sizeof(pSRB->pcmd->sense_buffer); + outb(bval,ioport+ScsiFifo); + bval = 0; + outb(bval,ioport+ScsiFifo); + } + else + { + cnt = pSRB->ScsiCmdLen; + ptr = (PUCHAR) pSRB->CmdBlock; + for(i=0; iCmdBlock[0] == INQUIRY) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + bval &= 0xBF; + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + if( pDCB->SyncMode & SYNC_ENABLE ) + { + if( !(pDCB->IdentifyMsg & 7) || + (pSRB->CmdBlock[0] != INQUIRY) ) + { + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_MSGOUT; + } + } + } + else + { + if(pDCB->SyncMode & EN_TAG_QUEUING) + { + outb(bval,ioport+ScsiFifo); + pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG; + wlval = 1; + bval = 0; + while( wlval & pDCB->TagMask ) + { + wlval = wlval << 1; + bval++; + } + pDCB->TagMask |= wlval; + pSRB->TagNumber = bval; + pSRB->MsgOutBuf[1] = bval; + pSRB->MsgCnt = 2; + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_START_; + } + else + { + outb(bval,ioport+ScsiFifo); + pSRB->MsgOutBuf[0] = MSG_NOP; + pSRB->MsgCnt = 1; + pSRB->SRBState = SRB_START_; + bval1 = SEL_W_ATN_STOP; + } + } + } + bval = inb( ioport+Scsi_Status ); + if( bval & INTERRUPT ) + { + pSRB->SRBState = SRB_READY; + pDCB->TagMask &= ~( 1 << pSRB->TagNumber ); + rc = 1; + } + else + { + pSRB->ScsiPhase = SCSI_NOP1; + pACB->pActiveDCB = pDCB; + pDCB->pActiveSRB = pSRB; + rc = 0; + outb(bval1,ioport+ScsiCmd); + } + return( rc ); +} + + +#ifndef VERSION_ELF_1_2_13 +static void +DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) +#else +static void +DC390_Interrupt( int irq, struct pt_regs *regs) +#endif +{ + PACB pACB; + PDCB pDCB; + PSRB pSRB; + USHORT ioport = 0; + USHORT phase, i; + void (*stateV)( PACB, PSRB, PUCHAR ); + UCHAR istate = 0; + UCHAR sstatus=0, istatus; + + pACB = pACB_start; + if( pACB == NULL ) + return; + for( i=0; i < adapterCnt; i++ ) + { + if( pACB->IRQLevel == (UCHAR) irq ) + { + ioport = pACB->IOPortBase; + sstatus = inb( ioport+Scsi_Status ); + if( sstatus & INTERRUPT ) + break; + else + pACB = pACB->pNextACB; + } + else + { + pACB = pACB->pNextACB; + } + } + +#ifdef DC390_DEBUG1 + printk("sstatus=%2x,",sstatus); +#endif + + if( pACB == (PACB )-1 ) + { + printk("DC390: Spurious interrupt detected!\n"); + return; + } + + istate = inb( ioport+Intern_State ); + istatus = inb( ioport+INT_Status ); + +#ifdef DC390_DEBUG1 + printk("Istatus=%2x,",istatus); +#endif + + if(istatus & DISCONNECTED) + { + DC390_Disconnect( pACB ); + return; + } + + if(istatus & RESELECTED) + { + DC390_Reselect( pACB ); + return; + } + + if(istatus & INVALID_CMD) + { + DC390_InvalidCmd( pACB ); + return; + } + + if(istatus & SCSI_RESET) + { + DC390_ScsiRstDetect( pACB ); + return; + } + + if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) ) + { + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + if( pDCB ) + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + EnableMsgOut( pACB, pSRB ); + } + + phase = (USHORT) pSRB->ScsiPhase; + stateV = (void *) DC390_phase0[phase]; + stateV( pACB, pSRB, &sstatus ); + + pSRB->ScsiPhase = sstatus & 7; + phase = (USHORT) sstatus & 7; + stateV = (void *) DC390_phase1[phase]; + stateV( pACB, pSRB, &sstatus ); + } +} + + +static void +DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR sstatus, bval; + USHORT ioport; + PSGL psgl; + ULONG ResidCnt, xferCnt; + + ioport = pACB->IOPortBase; + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & PARITY_ERR ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + bval = inb(ioport+DMA_Status); + while( !(bval & DMA_XFER_DONE) ) + bval = inb(ioport+DMA_Status); + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else + { + bval = inb( ioport+Current_Fifo ); + bval &= 0x1f; + ResidCnt = (ULONG) inb(ioport+CtcReg_High); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Low); + ResidCnt += (ULONG) bval; + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGPhysAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + } + } + bval = WRITE_DIRECTION+DMA_IDLE_CMD; + outb( bval, ioport+DMA_Cmd); +} + +static void +DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR sstatus, bval; + USHORT i, ioport, residual; + PSGL psgl; + ULONG ResidCnt, xferCnt; + PUCHAR ptr; + + + ioport = pACB->IOPortBase; + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & PARITY_ERR ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + bval = inb(ioport+DMA_Status); + while( !(bval & DMA_XFER_DONE) ) + bval = inb(ioport+DMA_Status); + + bval = READ_DIRECTION+DMA_IDLE_CMD; + outb( bval, ioport+DMA_Cmd); + + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else /* phase changed */ + { + residual = 0; + bval = inb(ioport+Current_Fifo); + while( bval & 0x1f ) + { + if( (bval & 0x1f) == 1 ) + { + for(i=0; i< 0x100; i++) + { + bval = inb(ioport+Current_Fifo); + if( !(bval & 0x1f) ) + goto din_1; + else if( i == 0x0ff ) + { + residual = 1; /* ;1 residual byte */ + goto din_1; + } + } + } + else + bval = inb(ioport+Current_Fifo); + } +din_1: + bval = READ_DIRECTION+DMA_BLAST_CMD; + outb(bval, ioport+DMA_Cmd); + for(i=0; i<0x8000; i++) + { + bval = inb(ioport+DMA_Status); + if(bval & BLAST_COMPLETE) + break; + } + bval = READ_DIRECTION+DMA_IDLE_CMD; + outb(bval, ioport+DMA_Cmd); + + ResidCnt = (ULONG) inb(ioport+CtcReg_High); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGPhysAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + + if( residual ) + { + bval = inb(ioport+ScsiFifo); /* get residual byte */ +#ifndef VERSION_ELF_1_2_13 + ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr ); +#else + ptr = (PUCHAR) pSRB->SGPhysAddr; +#endif + *ptr = bval; + pSRB->SGPhysAddr++; + pSRB->TotalXferredLen++; + pSRB->SGToBeXferLen--; + } + } + } +} + +static void +DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + +static void +DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = inb(ioport+ScsiFifo); + pSRB->TargetStatus = bval; + bval++; + bval = inb(ioport+ScsiFifo); /* get message */ + pSRB->EndMessage = bval; + + *psstatus = SCSI_NOP0; + pSRB->SRBState = SRB_COMPLETED; + bval = MSG_ACCEPTED_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) ) + *psstatus = SCSI_NOP0; +} + +static void +DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport, wval, wval1; + PDCB pDCB; + PSRB psrb; + + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + + bval = inb( ioport+ScsiFifo ); + if( !(pSRB->SRBState & SRB_MSGIN_MULTI) ) + { + if(bval == MSG_DISCONNECT) + { + pSRB->SRBState = SRB_DISCONNECT; + } + else if( bval == MSG_SAVE_PTR ) + goto min6; + else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) && + (bval <= MSG_ORDER_QTAG)) ) + { + pSRB->SRBState |= SRB_MSGIN_MULTI; + pSRB->MsgInBuf[0] = bval; + pSRB->MsgCnt = 1; + pSRB->pMsgPtr = &pSRB->MsgInBuf[1]; + } + else if(bval == MSG_REJECT_) + { + bval = RESET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + if( pSRB->SRBState & DO_SYNC_NEGO) + goto set_async; + } + else if( bval == MSG_RESTORE_PTR) + goto min6; + else + goto min6; + } + else + { /* minx: */ + + *pSRB->pMsgPtr = bval; + pSRB->MsgCnt++; + pSRB->pMsgPtr++; + if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) && + (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) ) + { + if( pSRB->MsgCnt == 2) + { + pSRB->SRBState = 0; + bval = pSRB->MsgInBuf[1]; + pSRB = pDCB->pGoingSRB; + psrb = pDCB->pGoingLast; + if( pSRB ) + { + for( ;; ) + { + if(pSRB->TagNumber != bval) + { + if( pSRB == psrb ) + goto mingx0; + pSRB = pSRB->pNextSRB; + } + else + break; + } + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + EnableMsgOut( pACB, pSRB ); + } + if( !(pSRB->SRBState & SRB_DISCONNECT) ) + goto mingx0; + pDCB->pActiveSRB = pSRB; + pSRB->SRBState = SRB_DATA_XFER; + } + else + { +mingx0: + pSRB = pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; + EnableMsgOut2( pACB, pSRB ); + } + } + } + else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) ) + { + pSRB->SRBState &= ~(SRB_MSGIN_MULTI+DO_SYNC_NEGO); + if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != 1) ) + { /* reject_msg: */ + pSRB->MsgCnt = 1; + pSRB->MsgInBuf[0] = MSG_REJECT_; + bval = SET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + } + else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) ) + { +set_async: + pDCB = pSRB->pSRBDCB; + pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->CtrlR3 = FAST_CLK; /* ;non_fast */ + pDCB->CtrlR4 &= 0x3f; + pDCB->CtrlR4 |= EATER_25NS; /* ; 25ns glitch eater */ + goto re_prog; + } + else + { /* set_sync: */ + + pDCB = pSRB->pSRBDCB; + pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; + pDCB->SyncOffset &= 0x0f0; + pDCB->SyncOffset |= pSRB->MsgInBuf[4]; + pDCB->NegoPeriod = pSRB->MsgInBuf[3]; + wval = (USHORT) pSRB->MsgInBuf[3]; + wval = wval << 2; + wval--; + wval1 = wval / 25; + if( (wval1 * 25) != wval) + wval1++; + bval = FAST_CLK+FAST_SCSI; + pDCB->CtrlR4 &= 0x3f; + if(wval1 >= 8) + { + wval1--; + bval = FAST_CLK; /* ;fast clock/normal scsi */ + pDCB->CtrlR4 |= EATER_25NS; /* ;25 ns glitch eater */ + } + pDCB->CtrlR3 = bval; + pDCB->SyncPeriod = (UCHAR)wval1; +re_prog: + bval = pDCB->SyncPeriod; + outb(bval, ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb(bval, ioport+Sync_Offset); + bval = pDCB->CtrlR3; + outb(bval, ioport+CtrlReg3); + bval = pDCB->CtrlR4; + outb(bval, ioport+CtrlReg4); + SetXferRate( pACB, pDCB); + } + } + } +min6: + *psstatus = SCSI_NOP0; + bval = MSG_ACCEPTED_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir) +{ + PSGL psgl; + UCHAR bval; + USHORT ioport; + ULONG lval; + + + ioport = pACB->IOPortBase; + if( pSRB->SGIndex < pSRB->SGcount ) + { + bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */ + outb( bval, ioport+DMA_Cmd); + if( !pSRB->SGToBeXferLen ) + { + psgl = pSRB->pSegmentList; +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + lval = pSRB->SGToBeXferLen; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_Low); + lval = lval >> 8; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_Mid); + lval = lval >> 8; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_High); + + lval = pSRB->SGToBeXferLen; + outl(lval, ioport+DMA_XferCnt); + + lval = pSRB->SGPhysAddr; + outl( lval, ioport+DMA_XferAddr); + + bval = DMA_COMMAND+INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); + + pSRB->SRBState = SRB_DATA_XFER; + + bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */ + outb(bval, ioport+DMA_Cmd); + + bval = DMA_START_CMD | ioDir; /* ;+EN_DMA_INT */ + outb(bval, ioport+DMA_Cmd); + } + else /* xfer pad */ + { + if( pSRB->SGcount ) + { + pSRB->AdaptStatus = H_OVER_UNDER_RUN; + pSRB->SRBStatus |= OVER_RUN; + } + bval = 0; + outb(bval,ioport+CtcReg_Low); + outb(bval,ioport+CtcReg_Mid); + outb(bval,ioport+CtcReg_High); + + pSRB->SRBState |= SRB_XFERPAD; + bval = DMA_COMMAND+XFER_PAD_BYTE; + outb(bval, ioport+ScsiCmd); +/* + bval = DMA_IDLE_CMD | ioDir; ;+EN_DMA_INT + outb(bval, ioport+DMA_Cmd); + bval = DMA_START_CMD | ioDir; ;+EN_DMA_INT + outb(bval, ioport+DMA_Cmd); +*/ + } +} + + +static void +DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR ioDir; + + ioDir = WRITE_DIRECTION; + DataIO_Comm( pACB, pSRB, ioDir); +} + +static void +DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR ioDir; + + ioDir = READ_DIRECTION; + DataIO_Comm( pACB, pSRB, ioDir); +} + +static void +DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + PDCB pDCB; + UCHAR bval; + PUCHAR ptr; + USHORT ioport, i, cnt; + + + ioport = pACB->IOPortBase; + bval = RESET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) + { + cnt = (USHORT) pSRB->ScsiCmdLen; + ptr = (PUCHAR) pSRB->CmdBlock; + for(i=0; i < cnt; i++) + { + outb(*ptr, ioport+ScsiFifo); + ptr++; + } + } + else + { + bval = REQUEST_SENSE; + outb(bval, ioport+ScsiFifo); + pDCB = pACB->pActiveDCB; + bval = pDCB->IdentifyMsg << 5; + outb(bval, ioport+ScsiFifo); + bval = 0; + outb(bval, ioport+ScsiFifo); + outb(bval, ioport+ScsiFifo); + bval = sizeof(pSRB->pcmd->sense_buffer); + outb(bval, ioport+ScsiFifo); + bval = 0; + outb(bval, ioport+ScsiFifo); + } + pSRB->SRBState = SRB_COMMAND; + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + pSRB->SRBState = SRB_STATUS; + bval = INITIATOR_CMD_CMPLTE; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport, i, cnt; + PUCHAR ptr; + PDCB pDCB; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + pDCB = pACB->pActiveDCB; + if( !(pSRB->SRBState & SRB_MSGOUT) ) + { + cnt = pSRB->MsgCnt; + if( cnt ) + { + ptr = (PUCHAR) pSRB->MsgOutBuf; + for(i=0; i < cnt; i++) + { + outb(*ptr, ioport+ScsiFifo); + ptr++; + } + pSRB->MsgCnt = 0; + if( (pDCB->DCBFlag & ABORT_DEV_) && + (pSRB->MsgOutBuf[0] == MSG_ABORT) ) + pSRB->SRBState = SRB_ABORT_SENT; + } + else + { + bval = MSG_ABORT; /* ??? MSG_NOP */ + if( (pSRB->CmdBlock[0] == INQUIRY ) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + if( pDCB->SyncMode & SYNC_ENABLE ) + goto mop1; + } + outb(bval, ioport+ScsiFifo); + } + bval = INFO_XFER_CMD; + outb( bval, ioport+ScsiCmd); + } + else + { +mop1: + bval = MSG_EXTENDED; + outb(bval, ioport+ScsiFifo); + bval = 3; /* ;length of extended msg */ + outb(bval, ioport+ScsiFifo); + bval = 1; /* ; sync nego */ + outb(bval, ioport+ScsiFifo); + bval = pDCB->NegoPeriod; + outb(bval, ioport+ScsiFifo); + bval = SYNC_NEGO_OFFSET; + outb(bval, ioport+ScsiFifo); + pSRB->SRBState |= DO_SYNC_NEGO; + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); + } +} + +static void +DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + if( !(pSRB->SRBState & SRB_MSGIN) ) + { + pSRB->SRBState &= SRB_DISCONNECT; + pSRB->SRBState |= SRB_MSGIN; + } + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + +static void +DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + + +static void +SetXferRate( PACB pACB, PDCB pDCB ) +{ + UCHAR bval; + USHORT cnt, i; + PDCB ptr; + + if( !(pDCB->IdentifyMsg & 0x07) ) + { + if( pACB->scan_devices ) + { + CurrSyncOffset = pDCB->SyncOffset; + } + else + { + ptr = pACB->pLinkDCB; + cnt = pACB->DeviceCnt; + bval = pDCB->UnitSCSIID; + for(i=0; iUnitSCSIID == bval ) + { + ptr->SyncPeriod = pDCB->SyncPeriod; + ptr->SyncOffset = pDCB->SyncOffset; + ptr->CtrlR3 = pDCB->CtrlR3; + ptr->CtrlR4 = pDCB->CtrlR4; + ptr->SyncMode = pDCB->SyncMode; + } + ptr = ptr->pNextDCB; + } + } + } + return; +} + + +static void +DC390_Disconnect( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB, psrb; + ULONG flags; + USHORT ioport, i, cnt; + UCHAR bval; + +#ifdef DC390_DEBUG0 + printk("DISC,"); +#endif + + save_flags(flags); + cli(); + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + if (!pDCB) + { +#ifdef DC390_DEBUG0 + printk("ACB:%08lx->ActiveDCB:%08lx !,",(ULONG)pACB,(ULONG)pDCB); +#endif + restore_flags(flags); return; + } + pSRB = pDCB->pActiveSRB; + pACB->pActiveDCB = 0; + pSRB->ScsiPhase = SCSI_NOP0; + bval = EN_SEL_RESEL; + outb(bval, ioport+ScsiCmd); + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + { + pSRB->SRBState = 0; + DoWaitingSRB( pACB ); + } + else if( pSRB->SRBState & SRB_ABORT_SENT ) + { + pDCB->TagMask = 0; + pDCB->DCBFlag = 0; + cnt = pDCB->GoingSRBCnt; + pDCB->GoingSRBCnt = 0; + pSRB = pDCB->pGoingSRB; + for( i=0; i < cnt; i++) + { + psrb = pSRB->pNextSRB; + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pSRB = psrb; + } + pDCB->pGoingSRB = 0; + DoWaitingSRB( pACB ); + } + else + { + if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || + !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) + { /* Selection time out */ + if( !(pACB->scan_devices) ) + { + pSRB->SRBState = SRB_READY; + RewaitSRB( pDCB, pSRB); + } + else + { + pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; + goto disc1; + } + } + else if( pSRB->SRBState & SRB_DISCONNECT ) + { + DoWaitingSRB( pACB ); + } + else if( pSRB->SRBState & SRB_COMPLETED ) + { +disc1: + if(pDCB->MaxCommand > 1) + { + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* free tag mask */ + } + pDCB->pActiveSRB = 0; + pSRB->SRBState = SRB_FREE; + SRBdone( pACB, pDCB, pSRB); + } + } + restore_flags(flags); + return; +} + + +static void +DC390_Reselect( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB pSRB; + USHORT ioport, wval; + UCHAR bval, bval1; + + +#ifdef DC390_DEBUG0 + printk("RSEL,"); +#endif + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + if( pDCB ) + { /* Arbitration lost but Reselection win */ + pSRB = pDCB->pActiveSRB; + if( !( pACB->scan_devices ) ) + { + pSRB->SRBState = SRB_READY; + RewaitSRB( pDCB, pSRB); + } + } + bval = inb(ioport+ScsiFifo); /* get ID */ + bval = bval ^ pACB->HostID_Bit; + wval = 0; + bval1 = 1; + for(;;) + { + if( !(bval & bval1) ) + { + bval1 = bval1 << 1; + wval++; + } + else + break; + } + wval |= ( (USHORT) inb(ioport+ScsiFifo) & 7) << 8; /* get LUN */ + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( wval != *((PUSHORT) &pDCB->UnitSCSIID) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + return; + } + pACB->pActiveDCB = pDCB; + if( pDCB->SyncMode & EN_TAG_QUEUING ) + { + pSRB = pACB->pTmpSRB; + pDCB->pActiveSRB = pSRB; + } + else + { + pSRB = pDCB->pActiveSRB; + if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) + { + pSRB= pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + EnableMsgOut( pACB, pSRB ); + } + else + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + EnableMsgOut( pACB, pSRB ); + } + else + pSRB->SRBState = SRB_DATA_XFER; + } + } + pSRB->ScsiPhase = SCSI_NOP0; + bval = pDCB->UnitSCSIID; + outb( bval, ioport+Scsi_Dest_ID); + bval = pDCB->SyncPeriod; + outb(bval, ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb( bval, ioport+Sync_Offset); + bval = pDCB->CtrlR1; + outb(bval, ioport+CtrlReg1); + bval = pDCB->CtrlR3; + outb(bval, ioport+CtrlReg3); + bval = pDCB->CtrlR4; /* ; Glitch eater */ + outb(bval, ioport+CtrlReg4); + bval = MSG_ACCEPTED_CMD; /* ;to rls the /ACK signal */ + outb(bval, ioport+ScsiCmd); +} + + +static void +SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb; + UCHAR bval, bval1, i, j, status; + PSCSICMD pcmd; + PSCSI_INQDATA ptr; + USHORT disable_tag; + ULONG flags; + PSGL ptr2; + ULONG swlval; + + pcmd = pSRB->pcmd; + status = pSRB->TargetStatus; + if(pSRB->SRBFlag & AUTO_REQSENSE) + { + pSRB->SRBFlag &= ~AUTO_REQSENSE; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = SCSI_STAT_CHECKCOND; + if(status == SCSI_STAT_CHECKCOND) + { + pcmd->result = DID_BAD_TARGET << 16; + goto ckc_e; + } + if(pSRB->RetryCnt == 0) + { + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + pSRB->TotalXferredLen = pSRB->Segment1[1]; + if( (pSRB->TotalXferredLen) && + (pSRB->TotalXferredLen >= pcmd->underflow) ) + pcmd->result |= (DID_OK << 16); + else + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; +#ifdef DC390_DEBUG0 + printk("Cmd=%2x,Result=%8x,XferL=%8x,",pSRB->CmdBlock[0], + (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen); +#endif + goto ckc_e; + } + else + { + pSRB->RetryCnt--; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; + goto ckc_e; + } + pcmd->result |= (DRIVER_SENSE << 24); + pSRB->SGcount = (UCHAR) pSRB->Segment1[0]; + pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); + return; + } + } + if( status ) + { + if( status == SCSI_STAT_CHECKCOND) + { + if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) ) + { + bval = pSRB->SGcount; + swlval = 0; + ptr2 = pSRB->pSegmentList; + for( i=pSRB->SGIndex; i < bval; i++) + { + swlval += ptr2->length; + ptr2++; + } +#ifdef DC390_DEBUG0 + printk("XferredLen=%8x,NotXferLen=%8x,", + (UINT) pSRB->TotalXferredLen, (UINT) swlval); +#endif + } + RequestSense( pACB, pDCB, pSRB ); + return; + } + else if( status == SCSI_STAT_QUEUEFULL ) + { + bval = (UCHAR) pDCB->GoingSRBCnt; + bval--; + pDCB->MaxCommand = bval; + RewaitSRB( pDCB, pSRB ); + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + return; + } + else if(status == SCSI_STAT_SEL_TIMEOUT) + { + pSRB->AdaptStatus = H_SEL_TIMEOUT; + pSRB->TargetStatus = 0; + pcmd->result = DID_BAD_TARGET << 16; + } + else + { + pSRB->AdaptStatus = 0; + if( pSRB->RetryCnt ) + { + pSRB->RetryCnt--; + pSRB->TargetStatus = 0; + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); + return; + } + else + { + pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) | + (ULONG) status; + } + } + } + else + { + status = pSRB->AdaptStatus; + if(status & H_OVER_UNDER_RUN) + { + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8); + } + else if( pSRB->SRBStatus & PARITY_ERROR) + { + pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8); + } + else /* No error */ + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16); + } + } + +ckc_e: + if( pACB->scan_devices ) + { + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + if(pcmd->result != (DID_OK << 16)) + { + if( pcmd->result & SCSI_STAT_CHECKCOND ) + { + goto RTN_OK; + } + else + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && + ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) ) + { + pACB->scan_devices = 0; + } + } + } + else + { +RTN_OK: + pPrevDCB->pNextDCB = pDCB; + pDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) ) + pACB->scan_devices = END_SCAN; + } + } + else if( pSRB->CmdBlock[0] == INQUIRY ) + { + if( (pcmd->target == pACB->max_id) && + (pcmd->lun == pACB->max_lun) ) + { + pACB->scan_devices = 0; + } + ptr = (PSCSI_INQDATA) (pcmd->request_buffer); + if( pcmd->use_sg ) + ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); + bval1 = ptr->DevType & SCSI_DEVTYPE; + if(bval1 == SCSI_NODEV) + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else + { + pACB->DeviceCnt++; + pPrevDCB = pDCB; + pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390_DCB )); + pDCB->DevType = bval1; + if(bval1 == TYPE_DISK || bval1 == TYPE_MOD) + { + if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) && + (ptr->Flags & SCSI_INQ_CMDQUEUE) && + (pDCB->DevMode & TAG_QUEUING_) && + (pDCB->DevMode & EN_DISCONNECT_) ) + { + disable_tag = 0; + for(i=0; iMaxCommand = pACB->TagMaxNum; + pDCB->SyncMode |= EN_TAG_QUEUING; + pDCB->TagMask = 0; + } + else + { + pDCB->SyncMode |= EN_ATN_STOP; + } + } + } + } + } + } + + save_flags( flags ); + cli(); +/* ReleaseSRB( pDCB, pSRB ); */ + + if(pSRB == pDCB->pGoingSRB ) + { + pDCB->pGoingSRB = pSRB->pNextSRB; + } + else + { + psrb = pDCB->pGoingSRB; + while( psrb->pNextSRB != pSRB ) + psrb = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb; + } + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pDCB->GoingSRBCnt--; + + DoWaitingSRB( pACB ); + restore_flags(flags); + +/* Notify cmd done */ + pcmd->scsi_done( pcmd ); + + if( pDCB->QIORBCnt ) + DoNextCmd( pACB, pDCB ); + return; +} + + +static void +DoingSRB_Done( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + PSCSICMD pcmd; + + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for( i=0; ipNextSRB; + pcmd = psrb->pcmd; + pcmd->result = DID_RESET << 16; + +/* ReleaseSRB( pDCB, pSRB ); */ + + psrb->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = psrb; + + pcmd->scsi_done( pcmd ); + psrb = psrb2; + } + pdcb->GoingSRBCnt = 0;; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +DC390_ResetSCSIBus( PACB pACB ) +{ + USHORT ioport; + UCHAR bval; + ULONG flags; + + save_flags(flags); + cli(); + pACB->ACBFlag |= RESET_DEV; + ioport = pACB->IOPortBase; + + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + + bval = RST_SCSI_BUS_CMD; + outb(bval,ioport+ScsiCmd); + + restore_flags(flags); + return; +} + + +static void +DC390_ScsiRstDetect( PACB pACB ) +{ + ULONG wlval, flags; + USHORT ioport; + UCHAR bval; + +#ifdef DC390_DEBUG0 + printk("RST_DETEC"); +#endif + save_flags(flags); + sti(); + wlval = jiffies + HZ; + while( jiffies < wlval ); /* delay 1 sec */ + + cli(); + ioport = pACB->IOPortBase; + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + bval = CLEAR_FIFO_CMD; + outb(bval,ioport+ScsiCmd); + + if( pACB->ACBFlag & RESET_DEV ) + pACB->ACBFlag |= RESET_DONE; + else + { + pACB->ACBFlag |= RESET_DETECT; + + ResetDevParam( pACB ); +/* DoingSRB_Done( pACB ); ???? */ + RecoverSRB( pACB ); + pACB->pActiveDCB = NULL; + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + } + restore_flags(flags); + return; +} + + +static void +RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSCSICMD pcmd; + + pSRB->SRBFlag |= AUTO_REQSENSE; + pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0])); + pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4])); + pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount); + pSRB->Segment1[1] = pSRB->TotalXferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + + pcmd = pSRB->pcmd; + + pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); + pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + pSRB->pSegmentList = &pSRB->Segmentx; + pSRB->SGcount = 1; + pSRB->SGIndex = 0; + + *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003; + pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; + *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer); + pSRB->ScsiCmdLen = 6; + + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); +} + + +static void +EnableMsgOut2( PACB pACB, PSRB pSRB ) +{ + USHORT ioport; + UCHAR bval; + + ioport = pACB->IOPortBase; + pSRB->MsgCnt = 1; + bval = SET_ATN_CMD; + outb(bval, ioport+ScsiCmd); +} + + +static void +EnableMsgOut( PACB pACB, PSRB pSRB ) +{ + pSRB->MsgOutBuf[0] = MSG_ABORT; + EnableMsgOut2( pACB, pSRB ); +} + + +static void +DC390_InvalidCmd( PACB pACB ) +{ + UCHAR bval; + USHORT ioport; + PSRB pSRB; + + pSRB = pACB->pActiveDCB->pActiveSRB; + if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) + { + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval,(ioport+ScsiCmd)); + } +} + --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/dc390w.h Wed Feb 5 01:54:24 1997 @@ -0,0 +1,145 @@ +/*********************************************************************** + * FILE NAME : DC390W.H * + * BY : C.L. Huang * + * Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + +/* Kernel version autodetection */ + +#include +/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ +#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) + +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,50) +#define VERSION_ELF_1_2_13 +#elseif LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,95) +#define VERSION_1_3_85 +#else +#define VERSION_2_0_0 +#endif + +/* + * NCR 53c825A,875 driver, header file + */ + +#ifndef DC390W_H +#define DC390W_H + +#if defined(HOSTS_C) || defined(MODULE) + +#ifdef VERSION_2_0_0 +#include +#else +#include +#endif + +extern int DC390W_detect(Scsi_Host_Template *psht); +extern int DC390W_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); +extern int DC390W_abort(Scsi_Cmnd *cmd); + +#ifdef VERSION_2_0_0 +extern int DC390W_reset(Scsi_Cmnd *cmd, unsigned int resetFlags); +#else +extern int DC390W_reset(Scsi_Cmnd *cmd); +#endif + +#ifdef VERSION_ELF_1_2_13 +extern int DC390W_bios_param(Disk *disk, int devno, int geom[]); +#else +extern int DC390W_bios_param(Disk *disk, kdev_t devno, int geom[]); +#endif + +#ifdef MODULE +static int DC390W_release(struct Scsi_Host *); +#else +#define DC390W_release NULL +#endif + +#ifndef VERSION_ELF_1_2_13 +extern struct proc_dir_entry proc_scsi_tmscsiw; +extern int tmscsiw_proc_info(char*, char**, off_t, int, int, int); +#endif + +#ifdef VERSION_2_0_0 + +#define DC390WUF { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsiw, /* *proc_dir */ \ + tmscsiw_proc_info, /* (*proc_info)() */ \ + "Tekram DC390WUF(T) V1.11 Feb-04-1997", /* *name */ \ + DC390W_detect, \ + DC390W_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390W_queue_command, \ + DC390W_abort, \ + DC390W_reset, \ + NULL, /* slave attach */\ + DC390W_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + 32,/* old (SG_ALL) */ \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + ENABLE_CLUSTERING \ + } +#endif + +#ifdef VERSION_1_3_85 + +#define DC390WUF { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsiw, /* *proc_dir */ \ + tmscsiw_proc_info, /* (*proc_info)() */ \ + "Tekram DC390WUF(T) V1.11 Feb-04-1997", /* *name */ \ + DC390W_detect, \ + DC390W_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390W_queue_command, \ + DC390W_abort, \ + DC390W_reset, \ + NULL, /* slave attach */\ + DC390W_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + 16,/* old (SG_ALL) */ \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + ENABLE_CLUSTERING \ + } +#endif + +#ifdef VERSION_ELF_1_2_13 + +#define DC390WUF { \ + NULL, \ + NULL, \ + "Tekram DC390WUF(T) V1.11 Feb-04-1997",\ + DC390W_detect, \ + DC390W_release, \ + NULL, /* info */ \ + NULL, /* command, deprecated */ \ + DC390W_queue_command, \ + DC390W_abort, \ + DC390W_reset, \ + NULL, /* slave attach */\ + DC390W_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + 16,/* old (SG_ALL) */ \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + ENABLE_CLUSTERING \ + } +#endif + +#endif /* defined(HOSTS_C) || defined(MODULE) */ + +#endif /* DC390W_H */ --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/tmscsiw.h Wed Feb 5 01:54:24 1997 @@ -0,0 +1,1082 @@ +/*********************************************************************** +;* File Name : TMSCSIW.H * +;* TEKRAM DC-390 PCI Wide SCSI Bus Master Host Adapter* +;* Device Driver * +;***********************************************************************/ + +#ifndef TMSCSIW_H +#define TMSCSIW_H + +#define IRQ_NONE 255 + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef unsigned int UINT; + +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef ULONG *PULONG; +typedef Scsi_Host_Template *PSHT; +typedef struct Scsi_Host *PSH; +typedef Scsi_Device *PSCSIDEV; +typedef Scsi_Cmnd *PSCSICMD; +typedef void *PVOID; +typedef struct scatterlist *PSGL, SGL; + + +typedef struct _AddWkSpace +{ +USHORT WKIOCtrlFlag; /* ;b7-Done, b6-wrtVerify, b0-in process */ +USHORT XferredBlkCnt; +USHORT WKToXferBlkCnt; +USHORT WKcSGListDone; +USHORT WKMaxSGIndex; +ULONG WKToXferLen; +USHORT NxtSGoffset; +} AddWkSpace; + +/*;-----------------------------------------------------------------------*/ +typedef struct _SyncMsg +{ +UCHAR ExtendMsg; +UCHAR ExtMsgLen; +UCHAR SyncXferReq; +UCHAR Period; +UCHAR ReqOffset; +} SyncMsg; +/*;-----------------------------------------------------------------------*/ +typedef struct _Capacity +{ +ULONG BlockCount; +ULONG BlockLength; +} Capacity; +/*;-----------------------------------------------------------------------*/ +typedef struct _SGentry +{ +ULONG SGXferDataPtr; +ULONG SGXferDataLen; +} SGentry; + +typedef struct _SGentry1 +{ +ULONG SGXLen; +ULONG SGXPtr; +} SGentry1, *PSGE; + + +#define MAX_ADAPTER_NUM 4 +#define MAX_DEVICES 10 +#define MAX_SG_LIST_BUF 32 +#define MAX_CMD_QUEUE 20 +#define MAX_CMD_PER_LUN 8 +#define MAX_SCSI_ID 16 +#define MAX_SRB_CNT MAX_CMD_QUEUE+4 +#define END_SCAN 2 + +/* +;----------------------------------------------------------------------- +; SCSI Request Block +;----------------------------------------------------------------------- +*/ +struct _SRB +{ +UCHAR CmdBlock[12]; +ULONG Segment0[MAX_SG_LIST_BUF+1][2]; +ULONG SegmentPad[2]; + +ULONG __select; +ULONG __command[2]; /* ;len,ptr */ +ULONG __msgout0[2]; /* ;len,ptr */ + +ULONG PhysSRB; +ULONG ReturnAddr; +ULONG RemainSegPtr; +PSCSICMD pcmd; +struct _SRB *pNextSRB; +struct _DCB *pSRBDCB; +PSGL pSegmentList; +ULONG XferredLen; + +ULONG SGPhysAddr; /*;a segment starting address */ +ULONG XferredLen1; + +SGL Segmentx; /* make a one entry of S/G list table */ + +PUCHAR pMsgPtr; +USHORT SRBState; +USHORT Revxx2; /* ??? */ + +UCHAR MsgInBuf[6]; +UCHAR MsgOutBuf[6]; +UCHAR SenseDataBuf[0x12]; +UCHAR AdaptStatus; +UCHAR TargetStatus; + +UCHAR MsgCnt; +UCHAR EndMessage; +UCHAR TagNumber; +UCHAR InternalReq; /*; 1-ADD internal request, 0-DMD request */ + +UCHAR SGcount; +UCHAR SGIndex; +UCHAR IORBFlag; /*;81h-Reset, 2-retry */ +UCHAR SRBStatus; + +UCHAR RetryCnt; +UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ + /*; b4-settimeout,b5-Residual valid */ +UCHAR ScratchABuf; +UCHAR Reserved3[1]; /*;for dword alignment */ +}; + +typedef struct _SRB DC390W_SRB, *PSRB; + +/* +;----------------------------------------------------------------------- +; Device Control Block +;----------------------------------------------------------------------- +*/ +struct _DCB +{ +UCHAR DCBselect; +UCHAR DCBsxfer; +UCHAR DCBsdid; +UCHAR DCBscntl3; + +UCHAR DCBscntl0; +UCHAR IdentifyMsg; +UCHAR DevMode; +UCHAR AdpMode; + +struct _DCB *pNextDCB; +struct _ACB *pDCBACB; + +PSCSICMD pQIORBhead; +PSCSICMD pQIORBtail; +PSCSICMD AboIORBhead; +PSCSICMD AboIORBtail; +USHORT QIORBCnt; +USHORT AboIORBcnt; + +PSRB pWaitingSRB; +PSRB pWaitLast; +PSRB pGoingSRB; +PSRB pGoingLast; +PSRB pActiveSRB; +USHORT GoingSRBCnt; +USHORT WaitSRBCnt; /* ??? */ + +ULONG TagMask; + +USHORT MaxCommand; +USHORT AdaptIndex; /*; UnitInfo struc start */ +USHORT UnitIndex; /*; nth Unit on this card */ +UCHAR UnitSCSIID; /*; SCSI Target ID (SCSI Only) */ +UCHAR UnitSCSILUN; /*; SCSI Log. Unit (SCSI Only) */ + +UCHAR InqDataBuf[8]; +UCHAR CapacityBuf[8]; +UCHAR SyncMode; /*; 0:async mode */ +UCHAR NegoPeriod; /*;for nego. */ +UCHAR SyncPeriod; /*;for reg. */ +UCHAR SyncOffset; /*;for reg. and nego.(low nibble) */ +UCHAR UnitCtrlFlag; +UCHAR DCBFlag; +UCHAR DevType; +UCHAR Reserved2[1]; /*;for dword alignment */ +}; + +typedef struct _DCB DC390W_DCB, *PDCB; +/* +;----------------------------------------------------------------------- +; Adapter Control Block +;----------------------------------------------------------------------- +*/ +struct _ACB +{ +ULONG PhysACB; +ULONG DevVendorID; +PSH pScsiHost; +struct _ACB *pNextACB; +USHORT IOPortBase; +USHORT Revxx1; /* ??? */ + +PDCB pLinkDCB; +PDCB pDCBRunRobin; +PDCB pActiveDCB; +PDCB pDCB_free; +PSRB pFreeSRB; +USHORT SRBCount; +USHORT AdapterIndex; /*; nth Adapter this driver */ +USHORT max_id; +USHORT max_lun; + +ULONG jmp_reselect; +ULONG jmp_select; +ULONG jmp_table8; +ULONG jmp_set_atn; +ULONG jmp_clear_ack; +ULONG jmp_next; +ULONG jmp_din8; +ULONG jmp_dout8; +ULONG jmp_clear_atn; +ULONG jmp_reselecttag; + +UCHAR msgin123[4]; +UCHAR status; +UCHAR AdaptSCSIID; /*; Adapter SCSI Target ID */ +UCHAR AdaptSCSILUN; /*; Adapter SCSI LUN */ +UCHAR DeviceCnt; +UCHAR IRQLevel; +UCHAR AdaptType; /*;1:390W, 2:390U, 3:390F */ +UCHAR TagMaxNum; +UCHAR ACBFlag; +UCHAR Gmode2; +UCHAR LUNchk; +UCHAR scan_devices; +UCHAR Reserved1[1]; /*;for dword alignment */ +UCHAR DCBmap[MAX_SCSI_ID]; +DC390W_DCB DCB_array[MAX_DEVICES]; /* +74h, Len=3E8 */ +DC390W_SRB SRB_array[MAX_SRB_CNT]; /* +45Ch, Len= */ +}; + +typedef struct _ACB DC390W_ACB, *PACB; + +/*;-----------------------------------------------------------------------*/ + +#define PCI_DEVICE_ID_NCR53C825A 0x0003 +#define PCI_DEVICE_ID_NCR53C875 0x000f + +#define CHIP810_ID 0x00011000 +#define CHIP820_ID 0x00021000 +#define CHIP825_ID 0x00031000 +#define CHIP815_ID 0x00041000 +#define CHIP875_ID 0x000f1000 + +#define DC390W 1 /*;825A - 16 BIT*/ +#define DC390U 2 /*;875 - 8 BIT*/ +#define DC390F 3 /*;875 - 16 BIT*/ + +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 + +/*;---WKIOCtrlFlag */ +#define IN_PROCESSING BIT0 +#define BAD_WRITE_V_CMD BIT1 +#define VERIFY_CMD BIT2 +#define RESIDUAL_SG BIT3 + +/*;---UnitCtrlFlag */ +#define UNIT_ALLOCATED BIT0 +#define UNIT_INFO_CHANGED BIT1 +#define FORMATING_MEDIA BIT2 +#define UNIT_RETRY BIT3 + +/*;---UnitFlags */ +#define DASD_SUPPORT BIT0 +#define SCSI_SUPPORT BIT1 +#define ASPI_SUPPORT BIT2 + +/*;----SRBState machine definition */ +#define SRB_FREE 0 +#define SRB_WAIT BIT0 +#define SRB_READY BIT1 +#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/ +#define SRB_MSGIN BIT3 +#define SRB_MSGIN_MULTI BIT4 +#define SRB_COMMAND BIT5 +#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/ +#define SRB_DISCONNECT BIT7 +#define SRB_DATA_XFER BIT8 +#define SRB_XFERPAD BIT9 +#define SRB_STATUS BIT10 +#define SRB_COMPLETED BIT11 + +#define DO_WIDE_NEGO BIT12 +#define DO_SYNC_NEGO BIT13 +#define SRB_UNEXPECT_RESEL BIT14 + +/*;---ACBFlag */ +#define RESET_DEV BIT0 +#define RESET_DETECT BIT1 +#define RESET_DONE BIT2 + +/*;---DCBFlag */ +#define ABORT_DEV_ BIT0 + +/*;---SRBstatus */ +#define SRB_OK BIT0 +#define ABORTION BIT1 +#define OVER_RUN BIT2 +#define UNDER_RUN BIT3 +#define SRB_ERROR BIT4 + +/*;---SRBFlag */ +#define DATAOUT BIT7 +#define DATAIN BIT6 +#define RESIDUAL_VALID BIT5 +#define ENABLE_TIMER BIT4 +#define RESET_DEV0 BIT2 +#define ABORT_DEV BIT1 +#define AUTO_REQSENSE BIT0 + +/*;---Adapter status */ +#define H_STATUS_GOOD 0 +#define H_SEL_TIMEOUT 0x11 +#define H_OVER_UNDER_RUN 0x12 +#define H_UNEXP_BUS_FREE 0x13 +#define H_TARGET_PHASE_F 0x14 +#define H_INVALID_CCB_OP 0x16 +#define H_LINK_CCB_BAD 0x17 +#define H_BAD_TARGET_DIR 0x18 +#define H_DUPLICATE_CCB 0x19 +#define H_BAD_CCB_OR_SG 0x1A +#define H_ABORT 0x0FF + +/*; SCSI Status byte codes*/ +#define SCSI_STAT_GOOD 0x0 /*; Good status */ +#define SCSI_STAT_CHECKCOND 0x02 /*; SCSI Check Condition */ +#define SCSI_STAT_CONDMET 0x04 /*; Condition Met */ +#define SCSI_STAT_BUSY 0x08 /*; Target busy status */ +#define SCSI_STAT_INTER 0x10 /*; Intermediate status */ +#define SCSI_STAT_INTERCONDMET 0x14 /*; Intermediate condition met */ +#define SCSI_STAT_RESCONFLICT 0x18 /*; Reservation conflict */ +#define SCSI_STAT_CMDTERM 0x22 /*; Command Terminated */ +#define SCSI_STAT_QUEUEFULL 0x28 /*; Queue Full */ + +#define SCSI_STAT_UNEXP_BUS_F 0xFD /*; Unexpect Bus Free */ +#define SCSI_STAT_BUS_RST_DETECT 0xFE /*; Scsi Bus Reset detected */ +#define SCSI_STAT_SEL_TIMEOUT 0xFF /*; Selection Time out */ + +/*;---Sync_Mode */ +#define SYNC_DISABLE 0 +#define SYNC_ENABLE BIT0 +#define SYNC_NEGO_DONE BIT1 +#define WIDE_ENABLE BIT2 +#define WIDE_NEGO_DONE BIT3 +#define EN_TAG_QUEUING BIT4 + +#define SYNC_NEGO_OFFSET 16 + +/*;---SCSI bus phase*/ +#define SCSI_DATA_OUT 0 +#define SCSI_DATA_IN 1 +#define SCSI_COMMAND 2 +#define SCSI_STATUS_ 3 +#define SCSI_NOP0 4 +#define SCSI_NOP1 5 +#define SCSI_MSG_OUT 6 +#define SCSI_MSG_IN 7 + +/*;----SCSI MSG BYTE*/ +#define MSG_COMPLETE 0x00 +#define MSG_EXTENDED 0x01 +#define MSG_SAVE_PTR 0x02 +#define MSG_RESTORE_PTR 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_INITIATOR_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT_ 0x07 +#define MSG_NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define MSG_LINK_CMD_COMPL 0x0A +#define MSG_LINK_CMD_COMPL_FLG 0x0B +#define MSG_BUS_RESET 0x0C +#define MSG_ABORT_TAG 0x0D +#define MSG_SIMPLE_QTAG 0x20 +#define MSG_HEAD_QTAG 0x21 +#define MSG_ORDER_QTAG 0x22 +#define MSG_IDENTIFY 0x80 +#define MSG_HOST_ID 0x0C0 + +/*;----SCSI STATUS BYTE*/ +#define STATUS_GOOD 0x00 +#define CHECK_CONDITION_ 0x02 +#define STATUS_BUSY 0x08 +#define STATUS_INTERMEDIATE 0x10 +#define RESERVE_CONFLICT 0x18 + +/* cmd->result */ +#define STATUS_MASK_ 0xFF +#define MSG_MASK 0xFF00 +#define RETURN_MASK 0xFF0000 + +/* +** Inquiry Data format +*/ + +typedef struct _SCSIInqData { /* INQ */ + + UCHAR DevType; /* Periph Qualifier & Periph Dev Type*/ + UCHAR RMB_TypeMod; /* rem media bit & Dev Type Modifier */ + UCHAR Vers; /* ISO, ECMA, & ANSI versions */ + UCHAR RDF; /* AEN, TRMIOP, & response data format*/ + UCHAR AddLen; /* length of additional data */ + UCHAR Res1; /* reserved */ + UCHAR Res2; /* reserved */ + UCHAR Flags; /* RelADr,Wbus32,Wbus16,Sync,etc. */ + UCHAR VendorID[8]; /* Vendor Identification */ + UCHAR ProductID[16]; /* Product Identification */ + UCHAR ProductRev[4]; /* Product Revision */ + + +} SCSI_INQDATA, *PSCSI_INQDATA; + + +/* Inquiry byte 0 masks */ + + +#define SCSI_DEVTYPE 0x1F /* Peripheral Device Type */ +#define SCSI_PERIPHQUAL 0xE0 /* Peripheral Qualifier */ + + +/* Inquiry byte 1 mask */ + +#define SCSI_REMOVABLE_MEDIA 0x80 /* Removable Media bit (1=removable) */ + + +/* Peripheral Device Type definitions */ + +#define SCSI_DASD 0x00 /* Direct-access Device */ +#define SCSI_SEQACESS 0x01 /* Sequential-access device */ +#define SCSI_PRINTER 0x02 /* Printer device */ +#define SCSI_PROCESSOR 0x03 /* Processor device */ +#define SCSI_WRITEONCE 0x04 /* Write-once device */ +#define SCSI_CDROM 0x05 /* CD-ROM device */ +#define SCSI_SCANNER 0x06 /* Scanner device */ +#define SCSI_OPTICAL 0x07 /* Optical memory device */ +#define SCSI_MEDCHGR 0x08 /* Medium changer device */ +#define SCSI_COMM 0x09 /* Communications device */ +#define SCSI_NODEV 0x1F /* Unknown or no device type */ + +/* +** Inquiry flag definitions (Inq data byte 7) +*/ + +#define SCSI_INQ_RELADR 0x80 /* device supports relative addressing*/ +#define SCSI_INQ_WBUS32 0x40 /* device supports 32 bit data xfers */ +#define SCSI_INQ_WBUS16 0x20 /* device supports 16 bit data xfers */ +#define SCSI_INQ_SYNC 0x10 /* device supports synchronous xfer */ +#define SCSI_INQ_LINKED 0x08 /* device supports linked commands */ +#define SCSI_INQ_CMDQUEUE 0x02 /* device supports command queueing */ +#define SCSI_INQ_SFTRE 0x01 /* device supports soft resets */ + + +/* +;========================================================== +; EEPROM byte offset +;========================================================== +*/ +typedef struct _EEprom +{ +UCHAR EE_MODE1; +UCHAR EE_SPEED; +UCHAR xx1; +UCHAR xx2; +} EEprom, *PEEprom; + +#define EE_ADAPT_SCSI_ID 64 +#define EE_MODE2 65 +#define EE_DELAY 66 +#define EE_TAG_CMD_NUM 67 + +/*; EE_MODE1 bits definition*/ +#define PARITY_CHK_ BIT0 +#define SYNC_NEGO_ BIT1 +#define EN_DISCONNECT_ BIT2 +#define SEND_START_ BIT3 +#define TAG_QUEUING_ BIT4 +#define WIDE_NEGO_ BIT5 + +/*; EE_MODE2 bits definition*/ +#define MORE2_DRV BIT0 +#define GREATER_1G BIT1 +#define RST_SCSI_BUS BIT2 +#define ACTIVE_NEGATION BIT3 +#define NO_SEEK BIT4 +#define LUN_CHECK BIT5 + +#define ENABLE_CE 1 +#define DISABLE_CE 0 +#define EEPROM_READ 0x80 + +/* +;========================================================== +; NCR 53C825 Registers Structure +;========================================================== +*/ +typedef struct _OperatingReg +{ +UCHAR SCSICtrl0; /*; (+00)*/ +UCHAR SCSICtrl1; /*; (+01)*/ +UCHAR SCSICtrl2; /*; (+02)*/ +UCHAR SCSICtrl3; /*; (+03)*/ +UCHAR SCSIChipID; /*; (+04)*/ +UCHAR SCSIXfer; /*; (+05)*/ +UCHAR SCSIDestID; /*; (+06)*/ +UCHAR GeneralPReg; /*; (+07)*/ +UCHAR SCSI1stByteR; /*; (+08)*/ +UCHAR SCSIOPCtrlL; /*; (+09)*/ +UCHAR SCSISelID; /*; (+0A)*/ +UCHAR SCSIBusCtrlLin; /*; (+0B)*/ +UCHAR DMAStatus; /*; (+0C)*/ +UCHAR SCSIStatus0; /*; (+0D)*/ +UCHAR SCSIStatus1; /*; (+0E)*/ +UCHAR SCSIStatus2; /*; (+0F)*/ +ULONG DataStrucAddr; /*; (+10)*/ +UCHAR InterruptStatus;/*; (+14)*/ +UCHAR Reser1; /*; (+15)*/ +UCHAR Reser2; /*; (+16)*/ +UCHAR Reser3; /*; (+17)*/ +UCHAR ChipTest0; /*; (+18)*/ +UCHAR ChipTest1; /*; (+19)*/ +UCHAR ChipTest2; /*; (+1A)*/ +UCHAR ChipTest3; /*; (+1B)*/ +ULONG TempStack; /*; (+1C)*/ +UCHAR DMAFIFO; /*; (+20)*/ +UCHAR ChipTest4; /*; (+21)*/ +UCHAR ChipTest5; /*; (+22)*/ +UCHAR ChipTest6; /*; (+23)*/ +UCHAR DMAByteCnt[3]; /*; (+24)*/ +UCHAR DMACommand; /*; (+27)*/ +ULONG DMANextAddr; /*; (+28)*/ +ULONG DMAScriptsPtr; /*; (+2C)*/ +ULONG DMAScriptPtrSav;/*; (+30)*/ +ULONG ScratchA; /*; (+34)*/ +UCHAR DMAMode; /*; (+38)*/ +UCHAR DMAIntEnable; /*; (+39)*/ +UCHAR DMAWatchDog; /*; (+3A)*/ +UCHAR DMACtrl; /*; (+3B)*/ +ULONG ADDer; /*; (+3C)*/ +UCHAR SCSIIntEnable0; /*; (+40)*/ +UCHAR SCSIIntEnable1; /*; (+41)*/ +UCHAR SCSIIntStatus0; /*; (+42)*/ +UCHAR SCSIIntStatus1; /*; (+43)*/ +UCHAR SCSILongParity; /*; (+44)*/ +UCHAR WideResiData; /*; (+45)*/ +UCHAR MemAccessCtrl; /*; (+46)*/ +UCHAR GeneralPCtrl; /*; (+47)*/ +UCHAR SCSITimer0; /*; (+48)*/ +UCHAR SCSITimer1; /*; (+49)*/ +UCHAR ResponseID0; /*; (+4A)*/ +UCHAR ResponseID1; /*; (+4B)*/ +UCHAR SCSITest0; /*; (+4C)*/ +UCHAR SCSITest1; /*; (+4D)*/ +UCHAR SCSITest2; /*; (+4E)*/ +UCHAR SCSITest3; /*; (+4F)*/ +USHORT SCSIIPDataL; /*; (+50)*/ +USHORT Reser4; /*; (+52)*/ +USHORT SCSIOPDataL; /*; (+54)*/ +USHORT Reser5; /*; (+56)*/ +USHORT SCSIBusDataLin; /*; (+58)*/ +USHORT Reser6; /*; (+5A)*/ +ULONG ScratchB; /*; (+5C)*/ +ULONG ScratchC; /*; (+60)*/ +ULONG ScratchD; /*; (+64)*/ +ULONG ScratchE; /*; (+68)*/ +ULONG ScratchF; /*; (+6C)*/ +ULONG ScratchG; /*; (+70)*/ +ULONG ScratchH; /*; (+74)*/ +ULONG ScratchI; /*; (+78)*/ +ULONG ScratchJ; /*; (+7C)*/ +} OperatingReg; +/* +;========================================================== +; NCR 53C825 Registers bit Definition +;========================================================== +*/ +/*; SCSICtrl0 (+00)*/ +#define FULL_ARBITRATION (BIT7+BIT6) +#define START_ARBIT BIT5 +#define SEL_W_SATN BIT4 +#define EN_PARITY_CHK BIT3 +#define SATN_IF_PARITY_ERR BIT1 +#define TARGET_MODE BIT0 + +/*; SCSICtrl1 (+01)*/ +#define ASSERT_RST BIT3 +#define ASSERT_EVEN_P BIT2 +#define START_SCSI_XFER BIT0 + +/*; SCSICtrl2 (+02)*/ +#define DISC_UNEXPECTED BIT7 +#define CHAIN_MODE BIT6 +#define WIDE_SCSI_SEND BIT3 +#define WIDE_SCSI_RECV BIT0 + +/*; SCSICtrl3 (+03)*/ +#define EN_FAST_20 BIT7 +#define SYNC_CLK_F4 (BIT6+BIT4) +#define SYNC_CLK_F3 BIT6 +#define SYNC_CLK_F2 (BIT5+BIT4) +#define SYNC_CLK_F1_5 BIT5 +#define SYNC_CLK_F1 BIT4 +#define EN_WIDE_SCSI BIT3 +#define ASYNC_CLK_F4 (BIT2+BIT0) +#define ASYNC_CLK_F3 BIT2 +#define ASYNC_CLK_F2 (BIT1+BIT0) +#define ASYNC_CLK_F1_5 BIT1 +#define ASYNC_CLK_F1 BIT0 + +/*; SCSIChipID (+04)*/ +#define ENABLE_RESEL BIT6 +#define ENABLE_SEL BIT5 +#define CHIP_ID_MASK 0FH + +/*; SCSIXfer (+05)*/ +#define PERIOD_MASK (BIT7+BIT6+BIT5) +#define SYNC_PERIOD_F11 (BIT7+BIT6+BIT5) +#define SYNC_PERIOD_F10 (BIT7+BIT6) +#define SYNC_PERIOD_F9 (BIT7+BIT5) +#define SYNC_PERIOD_F8 BIT7 +#define SYNC_PERIOD_F7 (BIT6+BIT5) +#define SYNC_PERIOD_F6 BIT6 +#define SYNC_PERIOD_F5 BIT5 +#define SYNC_PERIOD_F4 0 +#define OFFSET_MASK (BIT4+BIT3+BIT2+BIT1+BIT0) +#define SYNC_OFFSET_16 BIT4 +#define SYNC_OFFSET_8 BIT3 +#define SYNC_OFFSET_7 (BIT2+BIT1+BIT0) +#define SYNC_OFFSET_6 (BIT2+BIT1) +#define SYNC_OFFSET_5 (BIT2+BIT0) +#define SYNC_OFFSET_4 BIT2 +#define SYNC_OFFSET_3 (BIT1+BIT0) +#define SYNC_OFFSET_2 BIT1 +#define SYNC_OFFSET_1 BIT0 +#define SYNC_OFFSET_0 0 +#define ASYNCHRONOUS SYNC_OFFSET_0 +/* +; SCSIDestID (+06) + +; GeneralPReg (+07) + +; SCSI1stByteR (+08) +*/ +/*; SCSIOPCtrlL (+09)*/ +#define ASSERT_REQ BIT7 +#define ASSERT_ACK BIT6 +#define ASSERT_BSY BIT5 +#define ASSERT_SEL BIT4 +#define ASSERT_ATN BIT3 +#define ASSERT_MSG BIT2 +#define ASSERT_C_D BIT1 +#define ASSERT_I_O BIT0 + +/*; SCSISelID (+0A) Read*/ +#define SCSI_ID_VALID BIT7 + +/*; SCSIBusCtrlLin (+0B) Read*/ +#define REQ_SIGNAL BIT7 +#define ACK_SIGNAL BIT6 +#define BSY_SIGNAL BIT5 +#define SEL_SIGNAL BIT4 +#define ATN_SIGNAL BIT3 +#define MSG_SIGNAL BIT2 +#define C_D_SIGNAL BIT1 +#define I_O_SIGNAL BIT0 + +/*; DMAStatus (+0C) Read*/ +#define DMA_FIFO_EMPTY BIT7 +#define MASTER_PARITY_ERR BIT6 +#define BUS_FAULT BIT5 +#define ABORT_ BIT4 +#define SINGLE_STEP_INT BIT3 +#define SCRIPTS_INT BIT2 +#define ILLEGAL_INSTRUC BIT0 + +/*; SCSIStatus0 (+0D) Read*/ +#define SIDL_LSB_FULL BIT7 +#define SODR_LSB_FULL BIT6 +#define SODL_LSB_FULL BIT5 +#define IN_ARBITRATION BIT4 +#define LOST_ARBITRATION BIT3 +#define WIN_ARBITRATION BIT2 +#define RST_SIGNAL BIT1 +#define PARITY_SIGNAL BIT0 + +/*; SCSIStatus1 (+0E) Read*/ +#define SCSI_FIFO_MASK (BIT7+BIT6+BIT5+BIT4) + +/*; SCSIStatus2 (+0F) Read*/ +#define SIDL_MSB_FULL BIT7 +#define SODR_MSB_FULL BIT6 +#define SODL_MSB_FULL BIT5 +#define SCSI_FIFO_MSB BIT4 + +/*; DataStrucAddr (+10)*/ + +/*; InterruptStatus (+14)*/ +#define ABORT_OP BIT7 +#define SOFTWARE_RST BIT6 +#define SIGNAL_PROC BIT5 +#define SEMAPHORE BIT4 +#define CONNECTED BIT3 +#define INT_ON_FLY BIT2 +#define SCSI_INT_PENDING BIT1 +#define DMA_INT_PENDING BIT0 + +/*; ChipTest0 (+18)*/ +/*; ChipTest1 (+19)*/ +#define FIFO_BYTE_EMPTY (BIT7+BIT6+BIT5+BIT4) +#define FIFO_BYTE_FULL (BIT3+BIT2+BIT1+BIT0) + +/*; ChipTest2 (+1A)*/ +#define READ_DIR BIT7 +#define WRITE_DIR 0 +#define SIGNAL_PROC_ BIT6 +#define CFG_AS_IO_MAP BIT5 +#define CFG_AS_MEM_MAP BIT4 +#define SCRATCHAB_AS_BASE BIT3 +#define TRUE_EOP BIT2 +#define INTERNAL_DREQ BIT1 +#define INTERNAL_DACK BIT0 + +/*; ChipTest3 (+1B)*/ +#define CHIP_REV_MASK (BIT7+BIT6+BIT5+BIT4) +#define FLUSH_DMA_FIFO BIT3 +#define CLR_DMA_FIFO BIT2 +#define FETCH_PIN_MODE BIT1 +#define WRT_EN_INVALIDATE BIT0 + +/*; TempStack (+1C)*/ + +/*; DMAFIFO (+20)*/ +/*; 2 upper bits in ChipTest5*/ + +/*; ChipTest4 (+21)*/ +#define BURST_DISABLE BIT7 + +/*; ChipTest5 (+22) */ +#define EN_DMA_FIFO_536 BIT5 +#define BURST_LEN_MSB BIT2 +#define DMAFIFO_MS2B (BIT1+BIT0) +/* +; ChipTest6 (+23) +; DMAByteCnt (+24) +; DMACommand (+27) +; DMANextAddr (+28) +; DMAScriptsPtr (+2C) +; DMAScriptPtrSav (+30) +*/ +/*; ScratchA (+34)*/ +#define COMPLETED_OK_ BIT0 +#define RE_SELECTED_ BIT1 +#define OVER_RUN_ BIT2 + +/*; DMAMode (+38)*/ +#define BURST_LEN16 (BIT7+BIT6) +#define BURST_LEN8 BIT7 +#define BURST_LEN4 BIT6 +#define BURST_LEN2 0 +#define SRC_IO_MAP BIT5 +#define SRC_MEM_MAP 0 +#define DEST_IO_MAP BIT4 +#define DEST_MEM_MAP 0 +#define EN_READ_LINE BIT3 +#define EN_READ_MULTIPLE BIT2 +#define BURST_OPCODE_FETCH BIT1 +#define MANUAL_START BIT0 +#define AUTO_START 0 + +/*; DMAIntEnable (+39)*/ +#define EN_MDPE BIT6 +#define EN_BUS_FAULT BIT5 +#define EN_ABORTED BIT4 +#define EN_SINGLE_STEP BIT3 +#define EN_SCRIPT_INT BIT2 +#define EN_ILLEGAL_INST BIT0 + + +/*; DMAWatchDog (+3A)*/ + +/*; DMACtrl (+3B)*/ +#define EN_CACHE_LINE_SIZE BIT7 +#define PRE_FETCH_FLUSH BIT6 +#define EN_PRE_FETCH BIT5 +#define SINGLE_STEP_MIDE BIT4 +#define TOTEM_POLE_IRQ BIT3 +#define OPEN_DRAIN_IRQ 0 +#define START_DMA BIT2 +#define IRQ_DISABLE BIT1 +#define COMPATIBLE_700 BIT0 + +/*; ADDer (+3C)*/ + +/*; SCSIIntEnable0 (+40)*/ +#define EN_PHASE_MISMATCH BIT7 +#define EN_ARB_SEL_DONE BIT6 +#define EN_BE_SELECTED BIT5 +#define EN_BE_RESELECTED BIT4 +#define EN_SCSI_GERROR BIT3 +#define EN_UNEXPECT_DISC BIT2 +#define EN_SCSI_RESET BIT1 +#define EN_PARITY_ERROR BIT0 + +/*; SCSIIntEnable1 (+41)*/ +#define EN_SEL_TIMEOUT BIT2 +#define EN_GENERAL_TIMEOUT BIT1 +#define EN_HANDSHAKE_TIMEOUT BIT0 + +/*; SCSIIntStatus0 (+42)*/ +#define PHASE_MISMATCH BIT7 +#define ARB_SEL_DONE BIT6 +#define BE_SELECTED BIT5 +#define BE_RESELECTED BIT4 +#define SCSI_GERROR BIT3 +#define UNEXPECT_DISC BIT2 +#define SCSI_RESET BIT1 +#define PARITY_ERROR BIT0 + +/*; SCSIIntStatus1 (+43)*/ +#define SEL_TIMEOUT BIT2 +#define GENERAL_TIMEOUT BIT1 +#define HANDSHAKE_TIMEOUT BIT0 +/* +; SCSILongParity (+44) +; WideResiData (+45) +; MemAccessCtrl (+46) +; GeneralPCtrl (+47) +*/ +/*; SCSITimer0 (+48)*/ +#define HTH_TO_DISABLE 0 +#define SEL_TO_204ms (BIT3+BIT2) +/* +; SCSITimer1 (+49) +; ResponseID0 (+4A) +; ResponseID1 (+4B) +; SCSITest0 (+4C) +; SCSITest1 (+4D) +; SCSITest2 (+4E) +*/ +/*; SCSITest3 (+4F)*/ +#define ACTIVE_NEGATION_ BIT7 +#define FIFO_TEST_READ BIT6 +#define HALT_SCSI_CLK BIT5 +#define DIS_SINGLE_INIT BIT4 +#define TIMER_TEST_MODE BIT2 +#define CLR_SCSI_FIFO BIT1 +#define FIFO_TEST_WRITE BIT0 +/* +; SCSIIPDataL (+50) +; SCSIOPDataL (+54) +; SCSIBusDataLin (+58) +; ScratchB (+5C) +; ScratchC (+60) +; ScratchD (+64) +; ScratchE (+68) +; ScratchF (+6C) +; ScratchG (+70) +; ScratchH (+74) +; ScratchI (+78) +; ScratchJ (+7C) +*/ + +/*********************************************************************** + * NCR53C825 I/O Address Map + * base address is stored at offset 0x10 in the PCI configuration space + *----------------------------------------------------------------------- + * SCSI Core Registers Offset + ***********************************************************************/ +#define SCNTL0 0x00 /* Scsi Control 0 R/W */ +#define SCNTL1 0x01 /* Scsi Control 1 R/W */ +#define SCNTL2 0x02 /* Scsi Control 2 R/W */ +#define SCNTL3 0x03 /* Scsi Control 3 R/W */ +#define SCID 0x04 /* Scsi Chip ID R/W */ +#define SXFER 0x05 /* Scsi Transfer R/W */ +#define SDID 0x06 /* Scsi Destination ID R/W */ +#define GPREG 0x07 /* General Purpose Bits R/W */ +#define SFBR 0x08 /* Scsi First Byte Received R/W */ +#define SOCL 0x09 /* Scsi Output Control Latch R/W */ +#define SSID 0x0A /* Scsi Selector ID R */ +#define SBCL 0x0B /* Scsi Bus Control Lines R/W */ +#define DSTAT 0x0C /* DMA Status R */ +#define SSTAT0 0x0D /* Scsi Status 0 R */ +#define SSTAT1 0x0E /* Scsi Status 1 R */ +#define SSTAT2 0x0F /* Scsi Status 2 R */ +#define DSA 0x10 /* Data Structure Address R/W */ +#define ISTAT 0x14 /* Interrupt Status R/W */ +#define RES15 0x15 /* Reserved */ +#define CTEST0 0x18 /* Reserved */ +#define CTEST1 0x19 /* Chip Test 1 R/W */ +#define CTEST2 0x1A /* Chip Test 2 R */ +#define CTEST3 0x1B /* Chip Test 3 R */ +#define TEMP 0x1C /* Temperary Stack R/W */ +#define DFIFO 0x20 /* DMA FIFO R/W */ +#define CTEST4 0x21 /* Chip Test 4 R/W */ +#define CTEST5 0x22 /* Chip Test 5 R/W */ +#define CTEST6 0x23 /* Chip Test 6 R/W */ +#define DBC 0x24 /* DMA Byte Counter R/W */ +#define DCMD 0x27 /* DMA Command R/W */ +#define DNAD 0x28 /* DMA Next Address For Data R/W */ +#define DSP 0x2C /* DMA SCIPTS Pointer R/W */ +#define DSPS 0x30 /* DMA SCIPTS Pointer Saves R/W */ +#define SCRATCHA 0x34 /* General Purpose Scratch Pad A R/W */ +#define DMODE 0x38 /* DMA Mode R/W */ +#define DIEN 0x39 /* DMA Interrupt Enable R/W */ +#define DWT 0x3A /* DMA Watchdog Timer R/W */ +#define DCNTL 0x3B /* DMA Control R/W */ +#define ADDER 0x3C /* Sum output of Internal adder R */ +#define SIEN0 0x40 /* Scsi Interrupt Enable 0 R/W */ +#define SIEN1 0x41 /* Scsi Interrupt Enable 1 R/W */ +#define SIST0 0x42 /* Scsi Interrupt Status 0 R */ +#define SIST1 0x43 /* Scsi Interrupt Status 1 R */ +#define SLPAR 0x44 /* Scsi Longitudinal Parity R/W */ +#define SWIDE 0x45 /* Reserved */ +#define MACNTL 0x46 /* Memory Access Control R/W */ +#define GPCNTL 0x47 /* General Purpose Control R/W */ +#define STIME0 0x48 /* Scsi Timer 0 R/W */ +#define STIME1 0x49 /* Scsi Timer 1 R/W */ +#define RESPID0 0x4A /* Response ID 0 R/W */ +#define RESPID1 0x4B /* Response ID 1 R/W */ +#define STEST0 0x4C /* Scsi Test 0 R */ +#define STEST1 0x4D /* Scsi Test 1 R */ +#define STEST2 0x4E /* Scsi Test 2 R/W */ +#define STEST3 0x4F /* Scsi Test 3 R/W */ +#define SIDL 0x50 /* Scsi Input Data Latch R */ +#define RES51 0x51 /* Reserved */ +#define SODL 0x54 /* Scsi Output Data Latch R/W */ +#define RES55 0x55 /* Reserved */ +#define SBDL 0x58 /* Scsi Bus Data Lines R */ +#define RES59 0x59 /* Reserved */ +#define SCRATCHB 0x5C /* General Purpose Scratch Pad B R/W */ + + +/* +;========================================================== +; structure for 53C825A register ( I/O ) +;========================================================== +*/ +#define __scntl0 0 +#define __scntl1 1 +#define __scntl2 2 +#define __scntl3 3 +#define __scid 4 +#define __sxfer 5 +#define __sdid 6 +#define __gpreg 7 +#define __sfbr 8 +#define __socl 9 +#define __ssid 0x0A +#define __sbcl 0x0B +#define __dstat 0x0C +#define __sstat0 0x0D +#define __sstat1 0x0E +#define __sstat2 0x0F +#define __dsa 0x10 +#define __istat 0x14 +/*#define 0x15*/ +#define __ctest0 0x18 +#define __ctest1 0x19 +#define __ctest2 0x1A +#define __ctest3 0x1B +#define __temp 0x1C +#define __dfifo 0x20 +#define __ctest4 0x21 +#define __ctest5 0x22 +#define __ctest6 0x23 +#define __dbc 0x24 +#define __dcmd 0x27 +#define __dnad 0x28 +#define __dsp 0x2C +#define __dsps 0x30 +#define __scratcha 0x34 +#define __dmode 0x38 +#define __dien 0x39 +#define __dwt 0x3A +#define __dcntl 0x3B +#define __adder 0x3C +#define __sien0 0x40 +#define __sien1 0x41 +#define __sist0 0x42 +#define __sist1 0x43 +#define __slpar 0x44 +#define __swide 0x45 +#define __mactrl 0x46 +#define __gpctrl 0x47 +#define __stime0 0x48 +#define __stime1 0x49 +#define __respid0 0x4A +#define __respid1 0x4B +#define __stest0 0x4C +#define __stest1 0x4D +#define __stest2 0x4E +#define __stest3 0x4F +#define __sidl 0x50 /*; For wide SCSI, this register*/ +/*#define 0x51 ; contains 2 bytes*/ +#define __sodl 0x54 +/*#define 0x55*/ +#define __sbdl 0x58 +/*#define 0x59*/ +#define __scratchb 0x5C +/* +;========================================================== +; Script interrupt code(Vector) +;========================================================== +*/ +#define __COMPLETE 0 /*; command complete*/ +#define __RESELECTED 1 /*; reselected, without MESSAGE*/ +#define __RESELECTED1 2 /*; reselected with idenntify bytes*/ +#define __RESELECTEDT 3 /*; reselected with TAGS*/ +#define __DISCONNECTED 4 /*; disconnected*/ +#define __MSGEXTEND 5 /*; Extended msgin*/ +#define __SIGNAL 6 /*; signaled, need to clear SIG*/ +#define __MSGUNKNOWN 7 /*; Unknown message*/ +#define __MSGOUT 8 /*; Message out phase detected*/ +#define __FATALERROR 9 /*; Fatal error*/ +#define __MSGSYNC 10 /*; Sync nego input*/ +#define __MSGWIDE 11 /*; Wide nego input*/ +#define __RESTOREPTR 12 /*; restore pointer received*/ +#define __MSGREJECT 13 /*; Reject message received*/ +#define __DEBUG 14 /*; For debug*/ + + +#define DC390W_read8(address) \ + inb(DC390W_ioport + (address))) + +#define DC390W_read16(address) \ + inw(DC390W_ioport + (address))) + +#define DC390W_read32(address) \ + inl(DC390W_ioport + (address))) + +#define DC390W_write8(address,value) \ + outb((value), DC390W_ioport + (address))) + +#define DC390W_write16(address,value) \ + outw((value), DC390W_ioport + (address))) + +#define DC390W_write32(address,value) \ + outl((value), DC390W_ioport + (address))) + +#endif /* TMSCSIW_H */ --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/tmscsiw.c Wed Feb 5 01:54:24 1997 @@ -0,0 +1,2095 @@ +/*********************************************************************** + * FILE NAME : TMSCSIW.C * + * BY : C.L. Huang (ching@tekram.com.tw) * + * Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI * + * Bus Master Host Adapter * + * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * + ***********************************************************************/ +/* Minor enhancements and bugfixes by * + * Kurt Garloff * + ***********************************************************************/ +/* HISTORY: * + * * + * REV# DATE NAME DESCRIPTION * + * 1.00 04/03/96 CLH First release * + * 1.01 04/11/96 CLH Maximum support up to 4 Adapters, * + * support KV 1_3_85 * + * 1.02 04/26/96 CLH fixed bug about EEpromBuf when >1 HA * + * 1.03 06/12/96 CLH fixed bug of Media Change for Removable * + * Device, scan all LUN. Support Pre2.0.10 * + * 1.04 06/18/96 CLH fixed bug of Command timeout .... * + * 1.05 10/04/96 CLH Updating for support KV 2.0.0, 2.0.20 * + * 1.06 10/30/96 KG Fixed bug in DC390W_abort(), module * + * support, added tmscsiw_proc_info() * + * 1.07 11/09/96 KG Fixed bug in tmscsiw_proc_info() * + * 1.08 11/18/96 CLH/KG ditto, null ptr in DC390W_Disconnect() * + * 1.09 11/30/96 KG Fixed bug in CheckEEpromCheckSum(), * + * add register the allocated IO space * + * 1.10 12/05/96 CLH Modify in tmscsiw_proc_info() and add * + * in DC390W_initAdapter() for 53C875 * + * Rev. F with double clock. * + * 1.11 02/04/97 CLH Fixed bug of Formatting a partition that* + * across 1GB boundary, with bad sector * + * checking. * + ***********************************************************************/ + + +#define DC390W_DEBUG +/* #define CHK_UNDER_RUN */ + +#define SCSI_MALLOC + +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#if LINUX_VERSION_CODE < 66354 /* 1.3.50 */ +#include "../block/blk.h" +#else +#include +#endif + +#include "scsi.h" +#include "hosts.h" +#include "tmscsiw.h" +#include "constants.h" +#include "sd.h" +#include "scripts.h" +#include + +#include "dc390w.h" + +#ifndef VERSION_ELF_1_2_13 +struct proc_dir_entry proc_scsi_tmscsiw ={ + PROC_SCSI_DC390WUF, 7 ,"tmscsiw", + S_IFDIR | S_IRUGO | S_IXUGO, 2 + }; +#endif + +static void DC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void PrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DoingSRB_Done( PACB pACB ); +static void ExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB); +static void ParityError( PACB pACB, PDCB pDCB ); +static void PhaseMismatch( PACB pACB ); +static void DC390W_ScsiRstDetect( PACB pACB ); +static void DC390W_ResetSCSIBus( PACB pACB ); +static void DC390W_ResetSCSIBus2( PACB pACB ); +static void AdjustTemp( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void SetXferRate( PACB pACB, PDCB pDCB ); +static void DataIOcommon( PACB pACB, ULONG Swlval, ULONG Cwlval ); +static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); + +static void DC390W_CmdCompleted( PACB pACB ); +static void DC390W_Reselected( PACB pACB ); +static void DC390W_Reselected1( PACB pACB ); +static void DC390W_ReselectedT( PACB pACB ); +static void DC390W_Disconnected( PACB pACB ); +static void DC390W_MessageExtnd( PACB pACB ); +static void DC390W_Signal( PACB pACB ); +static void DC390W_UnknownMsg( PACB pACB ); +static void DC390W_MessageOut( PACB pACB ); +static void DC390W_FatalError( PACB pACB ); +static void DC390W_MessageSync( PACB pACB ); +static void DC390W_MessageWide( PACB pACB ); +static void DC390W_RestorePtr( PACB pACB ); +static void DC390W_MsgReject( PACB pACB ); +static void DC390W_Debug( PACB pACB ); +static void DC390W_download_script (struct Scsi_Host *host); + +int DC390W_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index); +void DC390W_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); +void MyDelay( void ); +void EnDisableCE( UCHAR Flag, USHORT scsiIOPort ); +void EEpromOutDI( USHORT Carry, USHORT scsiIOPort ); +void EEpromPrepare( UCHAR EEpromCmd, USHORT scsiIOPort ); +void ReadEEprom( PUCHAR EEpromBuf, USHORT scsiIOPort ); +UCHAR EEpromInDo(USHORT scsiIOPort); +USHORT EEpromGetData(USHORT scsiIOPort); +USHORT CheckEEpromCheckSum( PUCHAR EEpromBuf, USHORT scsiIOPort); + +#ifdef MODULE +static int DC390W_release(struct Scsi_Host *host); +static int DC390W_shutdown (struct Scsi_Host *host); +#endif + + +static ULONG jmp_table16; +static ULONG jmp_din16; +static ULONG jmp_dout16; +static PSHT pSHT_start = NULL; +static PSH pSH_start = NULL; +static PSH pSH_current = NULL; +static PACB pACB_start= NULL; +static PACB pACB_current = NULL; +static PDCB pPrevDCB = NULL; +static USHORT adapterCnt = 0; +static USHORT InitialTime = 0; +static USHORT CurrDCBscntl3 = 0; +static UCHAR pad_buffer[128]; + +static PVOID IntVector[]={ + DC390W_CmdCompleted, + DC390W_Reselected, + DC390W_Reselected1, + DC390W_ReselectedT, + DC390W_Disconnected, + DC390W_MessageExtnd, + DC390W_Signal, + DC390W_UnknownMsg, + DC390W_MessageOut, + DC390W_FatalError, + DC390W_MessageSync, + DC390W_MessageWide, + DC390W_RestorePtr, + DC390W_MsgReject, + DC390W_Debug, + DC390W_FatalError + }; + +UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; + +UCHAR clock_period[12] = {25, 31, 37, 43, 50, 62, 75, 125, 12, 15, 18, 21}; +UCHAR baddevname[2][28] ={ + "SEAGATE ST3390N 9546", + "SEAGATE ST3390N ??? 0399"}; + +#define BADDEVCNT 2 + +/*********************************************************************** + * + * + * + **********************************************************************/ +static void +QLinkcmd( PSCSICMD cmd, PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + if( !pDCB->QIORBCnt ) + { + pDCB->pQIORBhead = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + else + { + pcmd = pDCB->pQIORBtail; + pcmd->next = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + + restore_flags(flags); +} + + +static PSCSICMD +Getcmd( PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + pcmd = pDCB->pQIORBhead; + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + + restore_flags(flags); + return( pcmd ); +} + + +static PSRB +GetSRB( PACB pACB ) +{ + ULONG flags; + PSRB pSRB; + + save_flags(flags); + cli(); + + pSRB = pACB->pFreeSRB; + if( pSRB ) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + restore_flags(flags); + return( pSRB ); +} + + +static void +RewaitSRB( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + ULONG flags; + UCHAR bval; + + save_flags(flags); + cli(); + pDCB->GoingSRBCnt--; + psrb1 = pDCB->pGoingSRB; + if( pSRB == psrb1 ) + { + pDCB->pGoingSRB = psrb1->pNextSRB; + } + else + { + while( pSRB != psrb1->pNextSRB ) + psrb1 = psrb1->pNextSRB; + psrb1->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb1; + } + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ + restore_flags(flags); +} + + +static void +DoWaitingSRB( PACB pACB ) +{ + ULONG flags; + PDCB ptr, ptr1; + PSRB pSRB; + + save_flags(flags); + cli(); + + if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + { + ptr = pACB->pDCBRunRobin; + if( !ptr ) + { + ptr = pACB->pLinkDCB; + pACB->pDCBRunRobin = ptr; + } + ptr1 = ptr; + for( ;ptr1; ) + { + pACB->pDCBRunRobin = ptr1->pNextDCB; + if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || + !( pSRB = ptr1->pWaitingSRB ) ) + { + if(pACB->pDCBRunRobin == ptr) + break; + ptr1 = ptr1->pNextDCB; + } + else + { + DC390W_StartSCSI(pACB, ptr1, pSRB); + ptr1->GoingSRBCnt++; + if( ptr1->pWaitLast == pSRB ) + { + ptr1->pWaitingSRB = NULL; + ptr1->pWaitLast = NULL; + } + else + { + ptr1->pWaitingSRB = pSRB->pNextSRB; + } + pSRB->pNextSRB = NULL; + + if( ptr1->pGoingSRB ) + ptr1->pGoingLast->pNextSRB = pSRB; + else + ptr1->pGoingSRB = pSRB; + ptr1->pGoingLast = pSRB; + + break; + } + } + } + restore_flags(flags); + return; +} + + +static void +SRBwaiting( PDCB pDCB, PSRB pSRB) +{ + if( pDCB->pWaitingSRB ) + { + pDCB->pWaitLast->pNextSRB = pSRB; + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + } + else + { + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } +} + + +static void +SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) +{ + ULONG flags; + PDCB pDCB; + + save_flags(flags); + cli(); + + pDCB = pSRB->pSRBDCB; + PrepareSG( pACB, pDCB, pSRB ); + if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) + { + SRBwaiting(pDCB, pSRB); + goto SND_EXIT; + } + + if( pDCB->pWaitingSRB ) + { + SRBwaiting(pDCB, pSRB); +/* pSRB = GetWaitingSRB(pDCB); */ + pSRB = pDCB->pWaitingSRB; + pDCB->pWaitingSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + + DC390W_StartSCSI(pACB, pDCB, pSRB); + pDCB->GoingSRBCnt++; + if( pDCB->pGoingSRB ) + { + pDCB->pGoingLast->pNextSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + else + { + pDCB->pGoingSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + +SND_EXIT: + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function : static int DC390W_queue_command (Scsi_Cmnd *cmd, + * void (*done)(Scsi_Cmnd *)) + * + * Purpose : enqueues a SCSI command + * + * Inputs : cmd - SCSI command, done - function called on completion, with + * a pointer to the command descriptor. + * + * Returns : 0 + * + ***********************************************************************/ + +int +DC390W_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +{ + USHORT ioport, i; + Scsi_Cmnd *pcmd; + struct Scsi_Host *psh; + PACB pACB; + PDCB pDCB; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + + psh = cmd->host; + pACB = (PACB ) psh->hostdata; + ioport = pACB->IOPortBase; + +#ifdef DC390W_DEBUG0 + printk("Cmd=%x,",cmd->cmnd[0]); +#endif + + if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + + if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) ) + { +/* printk("DC390W: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return( 0 ); + } + + if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { + if( pACB->DeviceCnt < MAX_DEVICES ) + { + pACB->DCBmap[cmd->target] |= (1 << cmd->lun); + pDCB = pACB->pDCB_free; +#ifdef DC390W_DEBUG0 + printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); +#endif + DC390W_initDCB( pACB, pDCB, cmd ); + } + else /* ???? */ + { +/* printk("DC390W: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + } + else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { +/* printk("DC390W: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + else + { + pDCB = pACB->pLinkDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + } +#ifdef DC390W_DEBUG0 + printk("pDCB=%8x,ID=%2x,Scan=%1x", (UINT) pDCB, cmd->target, + pACB->scan_devices); +#endif + } + + cmd->scsi_done = done; + cmd->result = 0; + + save_flags(flags); + cli(); + + if( pDCB->QIORBCnt ) + { + QLinkcmd( cmd, pDCB ); + pcmd = Getcmd( pDCB ); + } + else + pcmd = cmd; + + pSRB = GetSRB( pACB ); + + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return(0); + } + +/* BuildSRB(pSRB); */ + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + (UCHAR) pSRB->__command[0] = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->ScratchABuf = 0; + pSRB->SRBState = 0; + pSRB->RemainSegPtr = 0; + pSRB->XferredLen = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return(0); +} + + +static void +DoNextCmd( PACB pACB, PDCB pDCB ) +{ + Scsi_Cmnd *pcmd; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + USHORT i; + + + if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) + return; + save_flags(flags); + cli(); + + pcmd = Getcmd( pDCB ); + pSRB = GetSRB( pACB ); + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return; + } + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + (UCHAR) pSRB->__command[0] = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->ScratchABuf = 0; + pSRB->SRBState = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function: + * DC390W_bios_param + * + * Description: + * Return the disk geometry for the given SCSI device. + ***********************************************************************/ +#ifdef VERSION_ELF_1_2_13 +int DC390W_bios_param(Disk *disk, int devno, int geom[]) +#else +int DC390W_bios_param(Disk *disk, kdev_t devno, int geom[]) +#endif +{ + int heads, sectors, cylinders; + PACB pACB; + + pACB = (PACB) disk->device->host->hostdata; + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) + { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + + +/*********************************************************************** + * Function : int DC390W_abort (Scsi_Cmnd *cmd) + * + * Purpose : Abort an errant SCSI command + * + * Inputs : cmd - command to abort + * + * Returns : 0 on success, -1 on failure. + ***********************************************************************/ + +int +DC390W_abort (Scsi_Cmnd *cmd) +{ + ULONG flags; + PACB pACB; + PDCB pDCB, pdcb; + PSRB pSRB, psrb; + USHORT count, i; + PSCSICMD pcmd, pcmd1; + int status; + + +#ifdef DC390W_DEBUG0 + printk("DC390W : Abort Cmd."); +#endif + + save_flags(flags); + cli(); + + pACB = (PACB) cmd->host->hostdata; + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + goto NOT_RUN; + } + + if( pDCB->QIORBCnt ) + { + pcmd = pDCB->pQIORBhead; + if( pcmd == cmd ) + { + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + for( count = pDCB->QIORBCnt, i=0; inext == cmd ) + { + pcmd1 = pcmd->next; + pcmd->next = pcmd1->next; + pcmd1->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + else + { + pcmd = pcmd->next; + } + } + } + + pSRB = pDCB->pWaitingSRB; + if( !pSRB ) + goto ON_GOING; + if( pSRB->pcmd == cmd ) + { + pDCB->pWaitingSRB = pSRB->pNextSRB; + goto IN_WAIT; + } + else + { + psrb = pSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + while( psrb->pNextSRB->pcmd != cmd ) + { + psrb = psrb->pNextSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + } + pSRB = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pWaitLast ) + pDCB->pWaitLast = psrb; +IN_WAIT: + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + cmd->next = NULL; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + +ON_GOING: + pSRB = pDCB->pGoingSRB; + for( count = pDCB->GoingSRBCnt, i=0; ipcmd != cmd ) + pSRB = pSRB->pNextSRB; + else + { + if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) + { + status = SCSI_ABORT_BUSY; + goto ABO_X; + } + else + { + status = SCSI_ABORT_SNOOZE; + goto ABO_X; + } + } + } + +NOT_RUN: + status = SCSI_ABORT_NOT_RUNNING; + +ABO_X: + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); + restore_flags(flags); + return( status ); +} + + +static void +ResetDevParam( PACB pACB ) +{ + PDCB pDCB, pdcb; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + if( pACB->AdaptType == DC390W ) + pdcb->DCBscntl3 = SYNC_CLK_F2+ASYNC_CLK_F2; + else + pdcb->DCBscntl3 = SYNC_CLK_F4+ASYNC_CLK_F4; + pdcb->DCBsxfer = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +RecoverSRB( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for (i=0; ipNextSRB; +/* RewaitSRB( pDCB, psrb ); */ + if( pdcb->pWaitingSRB ) + { + psrb2->pNextSRB = pdcb->pWaitingSRB; + pdcb->pWaitingSRB = psrb2; + } + else + { + pdcb->pWaitingSRB = psrb2; + pdcb->pWaitLast = psrb2; + psrb2->pNextSRB = NULL; + } + } + pdcb->GoingSRBCnt = 0; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +/*********************************************************************** + * Function : int DC390W_reset (Scsi_Cmnd *cmd, ...) + * + * Purpose : perform a hard reset on the SCSI bus( and NCR chip). + * + * Inputs : cmd - command which caused the SCSI RESET + * + * Returns : 0 on success. + ***********************************************************************/ + +#ifdef VERSION_2_0_0 +int DC390W_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) +#else +int DC390W_reset (Scsi_Cmnd *cmd) +#endif +{ + USHORT ioport; + unsigned long flags; + PACB pACB; + ULONG wlval; + UCHAR bval; + USHORT wval; + USHORT i; + + +#ifdef DC390W_DEBUG0 + printk("DC390W : Reset Cmd0,"); +#endif + + pACB = (PACB ) cmd->host->hostdata; + ioport = pACB->IOPortBase; + save_flags(flags); + cli(); + bval = inb(ioport+DCNTL); + bval |= IRQ_DISABLE; + outb(bval,ioport+DCNTL); /* disable interrupt */ + DC390W_ResetSCSIBus( pACB ); + for( i=0; i<500; i++ ) + udelay(1000); + for(;;) + { + bval = inb(ioport+ISTAT); + if( bval & SCSI_INT_PENDING ) + { + wval = inw( ioport+SIST0 ); + if( wval & (SCSI_RESET+SCSI_GERROR) ) + break; + } + if(bval & DMA_INT_PENDING) + { + bval = inb(ioport+DSTAT); + if(bval & ABORT_) + { + wval = inw( ioport+SIST0 ); + break; + } + } + } + bval = inb(ioport+DCNTL); + bval &= ~IRQ_DISABLE; + outb(bval,ioport+DCNTL); /* re-enable interrupt */ + + ioport = pACB->IOPortBase; + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + ResetDevParam( pACB ); + DoingSRB_Done( pACB ); + pACB->pActiveDCB = NULL; + wlval = pACB->jmp_reselect; + outl(wlval,(ioport+DSP)); + + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + restore_flags(flags); + return( SCSI_RESET_SUCCESS ); +} + + +#include "scsiio.c" + + +/*********************************************************************** + * Function : static void DC390W_initDCB + * + * Purpose : initialize the internal structures for a given DCB + * + * Inputs : cmd - pointer to this scsi cmd request block structure + * + ***********************************************************************/ +void DC390W_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) +{ + PEEprom prom; + UCHAR bval; + USHORT index; + + if( pACB->DeviceCnt == 0 ) + { + pACB->pLinkDCB = pDCB; + pACB->pDCBRunRobin = pDCB; + pDCB->pNextDCB = pDCB; + pPrevDCB = pDCB; + } + else + pPrevDCB->pNextDCB = pDCB; + + pDCB->pDCBACB = pACB; + pDCB->QIORBCnt = 0; + pDCB->DCBselect = 0; + pDCB->DCBsxfer = 0; + pDCB->DCBsdid = cmd->target; + pDCB->UnitSCSIID = cmd->target; + pDCB->UnitSCSILUN = cmd->lun; + pDCB->pWaitingSRB = NULL; + pDCB->GoingSRBCnt = 0; + pDCB->TagMask = 0; + + pDCB->MaxCommand = 1; + pDCB->AdaptIndex = pACB->AdapterIndex; + index = pACB->AdapterIndex; + + prom = (PEEprom) &eepromBuf[index][cmd->target << 2]; + pDCB->DevMode = prom->EE_MODE1; + pDCB->NegoPeriod = clock_period[prom->EE_SPEED]; + + if( pACB->AdaptType == DC390W ) + pDCB->DCBscntl3 = SYNC_CLK_F2+ASYNC_CLK_F2; + else + pDCB->DCBscntl3 = SYNC_CLK_F4+ASYNC_CLK_F4; + + if( pDCB->DevMode & PARITY_CHK_ ) + pDCB->DCBscntl0 = EN_PARITY_CHK+SATN_IF_PARITY_ERR+FULL_ARBITRATION; + else + pDCB->DCBscntl0 = FULL_ARBITRATION; + + pDCB->AdpMode = eepromBuf[index][EE_MODE2]; + + if( pDCB->DevMode & EN_DISCONNECT_ ) + bval = 0xC0; + else + bval = 0x80; + bval |= cmd->lun; + pDCB->IdentifyMsg = bval; + + if( pDCB->DevMode & SYNC_NEGO_ ) + { + pDCB->SyncMode = SYNC_ENABLE; + pDCB->SyncOffset = SYNC_NEGO_OFFSET; + } + + if( pDCB->DevMode & WIDE_NEGO_ ) + { + if( cmd->lun ) + { + if( !(CurrDCBscntl3 & EN_WIDE_SCSI) ) + pDCB->DevMode &= ~WIDE_NEGO_; + } + else + CurrDCBscntl3 = 0; + } + pDCB->DCBFlag = 0; +} + + +/*********************************************************************** + * Function : static void DC390W_initSRB + * + * Purpose : initialize the internal structures for a given SRB + * + * Inputs : psrb - pointer to this scsi request block structure + * + ***********************************************************************/ +void DC390W_initSRB( PSRB psrb ) +{ +#ifndef VERSION_ELF_1_2_13 + psrb->PhysSRB = virt_to_phys( psrb ); + psrb->__command[1] = virt_to_phys( psrb->CmdBlock ); + psrb->__msgout0[0] = 1; + psrb->__msgout0[1] = virt_to_phys( psrb->MsgOutBuf ); + psrb->SegmentPad[0] = 16; + psrb->SegmentPad[1] = virt_to_phys( pad_buffer ); +#else + psrb->PhysSRB = (ULONG) psrb; + psrb->__command[1] = (ULONG) psrb->CmdBlock; + psrb->__msgout0[0] = 1; + psrb->__msgout0[1] = (ULONG) psrb->MsgOutBuf; + psrb->SegmentPad[0] = 16; + psrb->SegmentPad[1] = (ULONG) pad_buffer; +#endif +} + + +void DC390W_linkSRB( PACB pACB ) +{ + USHORT count, i; + PSRB psrb; + + count = pACB->SRBCount; + + for( i=0; i< count; i++) + { + if( i != count - 1) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + else + pACB->SRB_array[i].pNextSRB = NULL; + psrb = (PSRB) &pACB->SRB_array[i]; + DC390W_initSRB( psrb ); + } +} + + +/*********************************************************************** + * Function : static void DC390W_initACB + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +void DC390W_initACB( PSH psh, USHORT chipType, ULONG io_port, UCHAR Irq, USHORT index ) +{ + PACB pACB; + USHORT i; + UCHAR adaptType, bval; + + + psh->can_queue = MAX_CMD_QUEUE; + psh->cmd_per_lun = MAX_CMD_PER_LUN; + psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID]; + psh->io_port = io_port; + psh->n_io_port = 0x80; + psh->irq = Irq; + + if( chipType == PCI_DEVICE_ID_NCR53C825A ) + adaptType = DC390W; + else + { + outb( 2, io_port+GPREG ); + bval = inb( io_port+GPREG ); + if( bval & 8 ) + adaptType = DC390U; + else + adaptType = DC390F; + } + + pACB = (PACB) psh->hostdata; + +#ifndef VERSION_ELF_1_2_13 + if( adaptType == DC390U ) + { + psh->max_id = 8; + pACB->max_id = 7; + } + else + { + psh->max_id = 16; + pACB->max_id = 15; + } + +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + psh->max_lun = 8; + else +#endif + psh->max_lun = 1; + +#else + pACB->max_id = 7; +#endif + if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) + pACB->max_id--; + +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->max_lun = 7; + else +#endif + pACB->max_lun = 0; + + pACB->pScsiHost = psh; + pACB->IOPortBase = (USHORT) io_port; + pACB->pLinkDCB = NULL; + pACB->pDCBRunRobin = NULL; + pACB->pActiveDCB = NULL; + pACB->pFreeSRB = pACB->SRB_array; + pACB->SRBCount = MAX_SRB_CNT; + pACB->AdapterIndex = index; + pACB->status = 0; + pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; + pACB->AdaptSCSILUN = 0; + pACB->DeviceCnt = 0; + pACB->IRQLevel = Irq; + pACB->AdaptType = adaptType; + pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2; + pACB->ACBFlag = 0; + pACB->scan_devices = 1; + pACB->Gmode2 = eepromBuf[index][EE_MODE2]; + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->LUNchk = 1; + pACB->pDCB_free = &pACB->DCB_array[0]; + DC390W_linkSRB( pACB ); + for(i=0; iDCBmap[i] = 0; +} + + +/*********************************************************************** + * Function : static int DC390W_initAdapter + * + * Purpose : initialize the SCSI chip ctrl registers + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +int DC390W_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) +{ + USHORT ioport, wval; + UCHAR bval; + PACB pACB, pacb; + USHORT used_irq = 0; + + pacb = pACB_start; + if( pacb != NULL ) + { + for ( ; (pacb != (PACB) -1) ; ) + { + if( pacb->IRQLevel == Irq ) + { + used_irq = 1; + break; + } + else + pacb = pacb->pNextACB; + } + } + + if( !used_irq ) + { +#ifdef VERSION_ELF_1_2_13 + if( request_irq(Irq, DC390W_Interrupt, SA_INTERRUPT, "tmscsiw")) +#else + if( request_irq(Irq, DC390W_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsiw", NULL)) +#endif + { + printk("DC390W : register IRQ error!\n"); + return( -1 ); + } + } + request_region(io_port,psh->n_io_port,"tmscsiw"); + + ioport = (USHORT) io_port; + outb(IRQ_DISABLE, ioport+DCNTL); + outb(ABORT_OP, ioport+ISTAT); + udelay(100000); + outb(0, ioport+ISTAT); + bval = inb(ioport+DSTAT); + bval = inb(ioport+ISTAT); + wval = inw(ioport+SIST0); + + pACB = (PACB) psh->hostdata; + bval = pACB->AdaptSCSIID; + bval |= ENABLE_RESEL; + outb(bval,ioport+SCID); + + if(pACB->AdaptType == DC390W) + bval = SYNC_CLK_F2+ASYNC_CLK_F2; + else + { /* @1.09 */ + bval = inb(ioport+CTEST3); + if( (bval & CHIP_REV_MASK) < 0x30 ) /* 53C875 Rev. F or later ? */ + goto REVF; + bval = inb(ioport+STEST1); + if( (bval & 0x0C) == 0x0C ) /* double clock already enable ? */ + goto REVF; + outb(8,ioport+STEST1); /* enable clock doubler */ + udelay(20); + outb(HALT_SCSI_CLK,ioport+STEST3); /* halt clock */ + outb(0x0C,ioport+STEST1); /* select double SCSI clock */ + outb(0,ioport+STEST3); /* re-enable clock */ +REVF: + bval = SYNC_CLK_F4+ASYNC_CLK_F4; + } + outb(bval,ioport+SCNTL3); + + bval = SYNC_PERIOD_F4+ASYNCHRONOUS; /* set to async */ + outb(bval,ioport+SXFER); + + bval = WRT_EN_INVALIDATE; /* Enable write and invalidate */ + outb(bval,ioport+CTEST3); + + bval = EN_DMA_FIFO_536+BURST_LEN_MSB; /* select 536 bytes DMA FIFO, burst len bit2=1 */ + outb(bval,ioport+CTEST5); + + bval = BURST_LEN8+EN_READ_LINE+EN_READ_MULTIPLE+BURST_OPCODE_FETCH+AUTO_START; /* set DMA parameter */ + outb(bval,ioport+DMODE); + + bval = EN_ABORTED+EN_SCRIPT_INT+EN_ILLEGAL_INST; /* enable DMA interrupt */ + outb(bval,ioport+DIEN); + + bval = EN_CACHE_LINE_SIZE+EN_PRE_FETCH+TOTEM_POLE_IRQ+COMPATIBLE_700; + outb(bval,ioport+DCNTL); + + bval = EN_PHASE_MISMATCH+EN_SCSI_GERROR+EN_UNEXPECT_DISC+EN_SCSI_RESET+EN_PARITY_ERROR; + outb(bval,ioport+SIEN0); + + bval = EN_SEL_TIMEOUT+EN_GENERAL_TIMEOUT; + outb(bval,ioport+SIEN1); + + bval = SEL_TO_204ms; /* 250ms selection timeout */ + outb(bval,ioport+STIME0); + + wval = 1 << (eepromBuf[index][EE_ADAPT_SCSI_ID]); /* @1.11 */ + outw(wval,ioport+RESPID0); + + bval = DIS_SINGLE_INIT; + if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) + bval |= ACTIVE_NEGATION_; + outb(bval,ioport+STEST3); + + return(0); +} + + +/*********************************************************************** + * Function : static int DC390W_init (struct Scsi_Host *host) + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : host - pointer to this host adapter's structure/ + * + * Preconditions : when this function is called, the chip_type + * field of the pACB structure MUST have been set. + ***********************************************************************/ + +static int +DC390W_init (PSHT psht, USHORT chipType, ULONG io_port, UCHAR Irq, USHORT index) +{ + PSH psh; + PACB pACB; + + if( ! CheckEEpromCheckSum( &eepromBuf[index][0], (USHORT) io_port) ) + { + psh = scsi_register( psht, sizeof(DC390W_ACB) ); + if( !psh ) + return( -1 ); + if( !pSH_start ) + { + pSH_start = psh; + pSH_current = psh; + } + else + { + pSH_current->next = psh; + pSH_current = psh; + } + +#ifdef DC390W_DEBUG0 + printk("DC390W : pSH = %8x,", (UINT) psh); +#endif + + DC390W_initACB( psh, chipType, io_port, Irq, index ); + if( !DC390W_initAdapter( psh, io_port, Irq, index ) ) + { + pACB = (PACB) psh->hostdata; + if( !pACB_start ) + { + pACB_start = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + else + { + pACB_current->pNextACB = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + +#ifdef DC390W_DEBUG0 + printk("DC390W : pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", + (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); + printk("DC390W : ACB size= %4x, DCB size= %4x, SRB size= %4x\n", + sizeof(DC390W_ACB), sizeof(DC390W_DCB), sizeof(DC390W_SRB) ); +#endif + + } + else + { + pSH_start = NULL; + scsi_unregister( psh ); + return( -1 ); + } + DC390W_download_script( psh ); + return( 0 ); + } + else + { + printk("DC390W_init: EEPROM reading error!\n"); + return( -1 ); + } +} + + +void MyDelay( void ) +{ + UCHAR i,j; + + j = inb(0x61) & 0x10; + + for(;;) + { + i = inb(0x61) & 0x10; + if( j ^ i) + break; + } +} + + +void EnDisableCE( UCHAR Flag, USHORT scsiIOPort ) +{ + + UCHAR bval; + USHORT port; + + port = (scsiIOPort & 0xff00) + GPREG; + if(Flag == ENABLE_CE) + bval = 0x10; + else + bval = 0x00; + outb(bval,port); + udelay(8); /* Delay();*/ +} + + +void EEpromOutDI( USHORT Carry, USHORT scsiIOPort ) +{ + UCHAR bval; + USHORT port; + + port = (scsiIOPort & 0xff00) + GPREG; + bval = 0x10; + if(Carry) + bval |= 0x02; /* SK=0, DI */ + outb(bval,port); + udelay(8); /* Delay();*/ + bval |= 0x04; /* SK=1, DI */ + outb(bval,port); + udelay(8); /* Delay();*/ + bval &= 0xfb; /* SK=0, DI */ + outb(bval,port); + udelay(8); /* Delay();*/ +} + + +void EEpromPrepare( UCHAR EEpromCmd, USHORT scsiIOPort ) +{ + UCHAR i,j; + USHORT carryFlag; + + carryFlag = 1; + j = 0x80; + for(i=0;i<9;i++) + { + EEpromOutDI(carryFlag,scsiIOPort); + carryFlag = (EEpromCmd & j) ? 1 : 0; + j >>= 1; + } +} + + +UCHAR EEpromInDo(USHORT scsiIOPort) +{ + UCHAR bval; + USHORT port; + + port = (scsiIOPort & 0xff00) + GPREG; + bval = 0x14; /* SK=1 */ + outb(bval,port); + udelay(8); /* Delay();*/ + bval = 0x10; /* SK=0 */ + outb(bval,port); + udelay(8); /* Delay();*/ + bval = inb(port); + if(bval & 0x01) + return( 1 ); + else + return( 0 ); +} + + +USHORT EEpromGetData(USHORT scsiIOPort) +{ + UCHAR i; + UCHAR carryFlag; + USHORT wval; + + wval = 0; + for(i=0;i<16;i++) + { + wval <<= 1; + carryFlag = EEpromInDo(scsiIOPort); + wval |= carryFlag; + } + return( wval ); +} + + +void ReadEEprom( PUCHAR EEpromBuf, USHORT scsiIOPort ) +{ + UCHAR cmd; + + cmd = EEPROM_READ; +loop_rd: + EnDisableCE(ENABLE_CE, scsiIOPort); + EEpromPrepare(cmd, scsiIOPort); + *((PUSHORT)EEpromBuf) = EEpromGetData(scsiIOPort); + EEpromBuf++; + EEpromBuf++; + cmd++; + EnDisableCE(DISABLE_CE, scsiIOPort); + if(cmd & 0x3f) + goto loop_rd; +} + + +USHORT CheckEEpromCheckSum( PUCHAR EEpromBuf, USHORT scsiIOPort) +{ + USHORT wval,port, *ptr; + UCHAR i,bval; + + port = (scsiIOPort & 0xff00) + GPREG; + bval = 0x09; /* configure IO Pin */ + outb(bval,port); + ReadEEprom(EEpromBuf,scsiIOPort); /* read eeprom data */ + wval = 0; + ptr = (PUSHORT) EEpromBuf; + for(i=0; i<128 ;i+=2, ptr++) + wval += *ptr; + return( (wval == 0x1234) ? 0 : -1); +} + + + +static void +DC390W_download_script (struct Scsi_Host *host) +{ + ULONG wlval, wlval1, length, alignm; + USHORT j, k, m; + USHORT ioport; + UCHAR bval; + PACB pACB; + PSRB pSRB; + void *pSrc, *pSrc1; + ULONG *pStart; + ULONG Ent_reselected; + ULONG Ent_reselecttag; + ULONG Ent_select0; + ULONG Ent_select1; + ULONG Ent_check_phase; + ULONG Ent_status1_phase; + ULONG Ent_command_phase; + ULONG Ent_jump_table0; + ULONG Ent_din_phaseB; + ULONG Ent_dout_phaseB; + ULONG Ent_din_pad_0; + ULONG Ent_dout_pad_0; + ULONG Ent_jump_tablew; + ULONG Ent_din_pad_1; + ULONG Ent_dout_pad_1; + ULONG Ent_mout_phase; + ULONG Ent_status_phase; + ULONG Ent_min_phase; + ULONG Ent_jump_msgok; + ULONG Ent_msg__1; + ULONG Ent_msg___3; + ULONG Ent_msg___2; + ULONG Ent_set_atn; + ULONG Ent_msg__a; + ULONG Ent_msg__23; + ULONG Ent_msg__3; + ULONG Ent_msg__4; + ULONG Ent_clr_atn; + ULONG Ent_din_phaseW; + ULONG Ent_dout_phaseW; + ULONG Ent_din_pad_addrB; + ULONG Ent_dout_pad_addrB; + ULONG Ent_din_pad_addrW; + ULONG Ent_dout_pad_addrW; + + + pACB = (PACB) host->hostdata; + ioport = pACB->IOPortBase; + bval = SCRATCHAB_AS_BASE; /* set scratchB contains 4K RAM base address */ + outb(bval,ioport+CTEST2); + + wlval = inl((ioport+SCRATCHB)); /* get starting address of 4K RAM */ +/* wlval += 0x800; */ /* point to Upper 2K RAM */ + DesPhysAddr[0] = wlval; /* destination address */ + +#ifdef DC390W_DEBUG0 + printk("DesAddr=%8x,",(UINT) wlval); +#endif + bval = 0; /* set Scratch_A and Scratch_B to normal mode */ + outb(bval,ioport+CTEST2); + + /*------------------------------------------------------------------- + * patch the label in jump instruction: using offset relative + * to start_script + *------------------------------------------------------------------*/ + + Ent_reselected = (ULONG) reselected - (ULONG) start_script; + Ent_reselecttag = (ULONG) reselecttag - (ULONG) start_script; + Ent_select0 = (ULONG) select0 - (ULONG) start_script; + Ent_select1 = (ULONG) select1 - (ULONG) start_script; + Ent_check_phase = (ULONG) check_phase - (ULONG) start_script; + Ent_status1_phase = (ULONG) status1_phase - (ULONG) start_script; + Ent_command_phase = (ULONG) command_phase - (ULONG) start_script; + Ent_din_phaseB = (ULONG) din_phaseB - (ULONG) start_script; + Ent_dout_phaseB = (ULONG) dout_phaseB - (ULONG) start_script; + Ent_din_phaseW = (ULONG) din_phaseW - (ULONG) start_script; + Ent_dout_phaseW = (ULONG) dout_phaseW - (ULONG) start_script; + Ent_jump_table0 = (ULONG) jump_table0 - (ULONG) start_script; + Ent_din_pad_0 = (ULONG) din_pad_0 - (ULONG) start_script; + Ent_din_pad_addrB = (ULONG) din_pad_addrB - (ULONG) start_script; + Ent_dout_pad_0 = (ULONG) dout_pad_0 - (ULONG) start_script; + Ent_dout_pad_addrB = (ULONG) dout_pad_addrB - (ULONG) start_script; + Ent_jump_tablew = (ULONG) jump_tablew - (ULONG) start_script; + Ent_din_pad_1 = (ULONG) din_pad_1 - (ULONG) start_script; + Ent_din_pad_addrW = (ULONG) din_pad_addrW - (ULONG) start_script; + Ent_dout_pad_1 = (ULONG) dout_pad_1 - (ULONG) start_script; + Ent_dout_pad_addrW = (ULONG) dout_pad_addrW - (ULONG) start_script; + Ent_mout_phase = (ULONG) mout_phase - (ULONG) start_script; + Ent_status_phase = (ULONG) status_phase - (ULONG) start_script; + Ent_min_phase = (ULONG) min_phase - (ULONG) start_script; + Ent_jump_msgok = (ULONG) jump_msgok - (ULONG) start_script; + Ent_msg__1 = (ULONG) msg__1 - (ULONG) start_script; + Ent_msg___3 = (ULONG) msg___3 - (ULONG) start_script; + Ent_msg___2 = (ULONG) msg___2 - (ULONG) start_script; + Ent_set_atn = (ULONG) set_atn - (ULONG) start_script; + Ent_msg__a = (ULONG) msg__a - (ULONG) start_script; + Ent_msg__23 = (ULONG) msg__23 - (ULONG) start_script; + Ent_msg__3 = (ULONG) msg__3 - (ULONG) start_script; + Ent_msg__4 = (ULONG) msg__4 - (ULONG) start_script; + Ent_clr_atn = (ULONG) clr_atn - (ULONG) start_script; + + jmp_select0[0] = Ent_select0 + wlval; + jmp_reselected[0] = Ent_reselected + wlval; + jmp_check_phase[0] = Ent_check_phase + wlval; + jmp_check_phase1[0] = Ent_check_phase + wlval; + jmp_check_phase2[0] = Ent_check_phase + wlval; + jmp_check_phase3[0] = Ent_check_phase + wlval; + jmp_check_phase4[0] = Ent_check_phase + wlval; + jmp_check_phase5[0] = Ent_check_phase + wlval; + jmp_check_phase6[0] = Ent_check_phase + wlval; + jmp_status1_phase[0] = Ent_status1_phase + wlval; + jmp_status1_phase1[0] = Ent_status1_phase + wlval; + jmp_status1_phase2[0] = Ent_status1_phase + wlval; + jmp_status1_phase3[0] = Ent_status1_phase + wlval; + jmp_command_phase[0] = Ent_command_phase + wlval; + for(j=0,k=1,m=0; j< (MAX_SG_LIST_BUF+1); j++) + { + jmp_dio_phaseB[k] = Ent_din_phaseB + m + wlval; + jmp_dio_phaseW[k] = Ent_din_phaseW + m + wlval; + k += 2; + jmp_dio_phaseB[k] = Ent_dout_phaseB + m + wlval; + jmp_dio_phaseW[k] = Ent_dout_phaseW + m + wlval; + k += 2; + m += 8; + } + jmp_din_pad_0[0] = Ent_din_pad_0 + wlval; + jmp_dout_pad_0[0] = Ent_dout_pad_0 + wlval; + jmp_din_pad_addrB[0] = Ent_din_pad_addrB + wlval; + jmp_dout_pad_addrB[0] = Ent_dout_pad_addrB + wlval; + jmp_din_pad_addrW[0] = Ent_din_pad_addrW + wlval; + jmp_dout_pad_addrW[0] = Ent_dout_pad_addrW + wlval; + jmp_din_pad_1[0] = Ent_din_pad_1 + wlval; + jmp_dout_pad_1[0] = Ent_dout_pad_1 + wlval; + jmp_status_phase[0] = Ent_status_phase + wlval; + jmp_min_phase[0] = Ent_min_phase + wlval; + jmp_mout_phase[0] = Ent_mout_phase + wlval; + jmp_jump_msgok[0] = Ent_jump_msgok + wlval; + jmp_msg__1[0] = Ent_msg__1 + wlval; + jmp_msg___3[0] = Ent_msg___3 + wlval; + jmp_msg___2[0] = Ent_msg___2 + wlval; + jmp_msg__a[0] = Ent_msg__a + wlval; + jmp_msg__a1[0] = Ent_msg__a + wlval; + jmp_msg__a2[0] = Ent_msg__a + wlval; + jmp_msg__23[0] = Ent_msg__23 + wlval; + jmp_msg__3[0] = Ent_msg__3 + wlval; + jmp_msg__4[0] = Ent_msg__4 + wlval; + + /*-------------------------------------------------------------------- + // patch the element in ACB struct: using Physical address + //-------------------------------------------------------------------*/ + +#ifndef VERSION_ELF_1_2_13 + wlval1 = virt_to_phys( pACB->msgin123 ); +#else + wlval1 = (ULONG) pACB->msgin123; +#endif + ACB_msgin123_1[0] = wlval1; + ACB_msgin123_2[0] = wlval1; + ACB_msgin123_3[0] = wlval1; + ACB_msgin123_4[0] = wlval1; + ACB_msgin123_5[0] = wlval1; + ACB_msgin123_6[0] = wlval1; + ACB_msgin123_7[0] = wlval1; + +#ifndef VERSION_ELF_1_2_13 + ACB_status[0] = virt_to_phys( &pACB->status ); +#else + ACB_status[0] = (ULONG) &pACB->status; +#endif + /*-------------------------------------------------------------------- + // patch the element in SRB struct: using offset in struct + //-------------------------------------------------------------------*/ + + pSRB = (PSRB) pACB->SRB_array; + select1[0] = (select1[0] & 0xffff0000) + ((ULONG) &pSRB->__select - (ULONG) &pSRB->CmdBlock); + SRB_msgout0[0] = (ULONG) &pSRB->__msgout0 - (ULONG) &pSRB->CmdBlock; + SRB_msgout01[0] = (ULONG) &pSRB->__msgout0 - (ULONG) &pSRB->CmdBlock; + SRB_command[0] = (ULONG) &pSRB->__command - (ULONG) &pSRB->CmdBlock; + SRB_SegmentPad[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; + SRB_SegmentPad1[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; + SRB_SegmentPad2[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; + SRB_SegmentPad3[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; + wlval = (ULONG) &pSRB->Segment0 - (ULONG) &pSRB->CmdBlock; + for(j=0,k=1; j<(MAX_SG_LIST_BUF+1); j++) + { + din_phaseB[k] = wlval; + dout_phaseB[k] = wlval; + din_phaseW[k] = wlval; + dout_phaseW[k] = wlval; + k += 2; + wlval += 8; + } + + + bval = inb(ioport+DCNTL); + bval |= IRQ_DISABLE; + outb(bval,ioport+DCNTL); /* disable interrupt */ + +/* pSrc = scsi_init_malloc( 2048, GFP_ATOMIC); */ + pSrc = scsi_init_malloc( 4096, GFP_ATOMIC); /* 1.11 */ +#ifdef DC390W_DEBUG0 + printk("SrcAlloc=%8x,",(UINT) pSrc); +#endif + alignm = 4 - (((ULONG) pSrc) & 3); + pSrc1 = (void *)(((ULONG) pSrc) + alignm); + length = (ULONG) end_script - (ULONG) start_script; + memcpy( pSrc1, (void *) start_script, length); + pStart = (ULONG *) ((ULONG) start_mov - (ULONG) start_script); + pStart =(ULONG *) (((ULONG) pStart) + ((ULONG) pSrc1)); + +#ifdef DC390W_DEBUG0 + printk("SrcAddr=%8x,\n",(UINT) pSrc1); +#endif +#ifndef VERSION_ELF_1_2_13 + (ULONG *)pStart[1] = virt_to_phys( pSrc1 ); +#else + (ULONG *)pStart[1] = (ULONG) pSrc1; +#endif + +/* wlval = virt_to_phys( start_script ); */ /* physical address of start_script */ +/* SrcPhysAddr[0] = wlval; */ /* sources address */ + +/* start to download SCRIPT instruction to the RAM of NCR53c825A,875 */ + +/* wlval = virt_to_phys( start_mov ); */ + +#ifndef VERSION_ELF_1_2_13 + wlval = virt_to_phys( pStart ); +#else + wlval = (ULONG) pStart; +#endif + + outl(wlval,ioport+DSP); + + bval = inb(ioport+ISTAT); + while(!(bval & DMA_INT_PENDING)) /* check load start_script is finished? */ + bval = inb(ioport+ISTAT); + + bval = inb(ioport+DSTAT); /* clear interrupt */ + + bval = inb(ioport+DCNTL); + bval &= ~IRQ_DISABLE; + outb(bval,ioport+DCNTL); /* re-enable interrupt */ + + scsi_init_free((char *) pSrc, 4096); + + wlval = DesPhysAddr[0]; /* starting addr of RAM */ + wlval -= (ULONG) start_script; + + pACB->jmp_reselect = wlval + (ULONG) start_script; + pACB->jmp_select = wlval + (ULONG) select1; + pACB->jmp_table8 = wlval + (ULONG) jump_table0; + pACB->jmp_set_atn = wlval + (ULONG) set_atn; + pACB->jmp_clear_ack = wlval + (ULONG) msg__a; + pACB->jmp_next = wlval + (ULONG) check_phase; + pACB->jmp_din8 = wlval + (ULONG) din_phaseB+8; + pACB->jmp_dout8 = wlval + (ULONG) dout_phaseB+8; + pACB->jmp_clear_atn = wlval + (ULONG) clr_atn; + pACB->jmp_reselecttag = wlval + (ULONG) reselecttag; + + wlval = pACB->jmp_reselect; + outl(wlval,(ioport+DSP)); + return; +} + + +/*********************************************************************** + * Function : int DC390W_detect(Scsi_Host_Template *psht) + * + * Purpose : detects and initializes NCR53c825A,875 SCSI chips + * that were autoprobed, overridden on the LILO command line, + * or specified at compile time. + * + * Inputs : psht - template for this SCSI adapter + * + * Returns : number of host adapters detected + * + ***********************************************************************/ + +int +DC390W_detect(Scsi_Host_Template *psht) +{ + UCHAR pci_bus, pci_device_fn, irq; +#ifndef VERSION_ELF_1_2_13 + UINT io_port, ram_base; +#else + ULONG io_port, ram_base; +#endif + USHORT i; + int error = 0; + USHORT adaptCnt = 0; /* Number of boards detected */ + USHORT pci_index = 0; /* Device index to PCI BIOS calls */ + USHORT pci_index2 = 0; /* Device index to PCI BIOS calls */ + USHORT chipType = 0; + + +#ifndef VERSION_ELF_1_2_13 + psht->proc_dir = &proc_scsi_tmscsiw; +#endif + + InitialTime = 1; + pSHT_start = psht; + jmp_table16 = (ULONG) jump_tablew - (ULONG) jump_table0; + jmp_din16 = (ULONG) din_phaseW - (ULONG) din_phaseB; + jmp_dout16 = (ULONG) dout_phaseW - (ULONG) dout_phaseB; + pACB_start = NULL; + + if ( pcibios_present() ) + { + for (i = 0; i < MAX_ADAPTER_NUM; ++i) + { + if( !pcibios_find_device( PCI_VENDOR_ID_NCR, + PCI_DEVICE_ID_NCR53C825A, + pci_index, &pci_bus, &pci_device_fn) ) + { + chipType = PCI_DEVICE_ID_NCR53C825A; + pci_index++; + } + else if( !pcibios_find_device( PCI_VENDOR_ID_NCR, + PCI_DEVICE_ID_NCR53C875, + pci_index2, &pci_bus, &pci_device_fn) ) + { + chipType = PCI_DEVICE_ID_NCR53C875; + pci_index2++; + } + + if( chipType ) + { + error = pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &io_port); + error |= pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_2, &ram_base); + error |= pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + if( error ) + { + printk("DC390W_detect: reading configuration registers error!\n"); + InitialTime = 0; + return( 0 ); + } + + (USHORT) io_port = (USHORT) io_port & 0xFFFE; +#ifdef DC390W_DEBUG0 + printk("DC390W : IO_PORT=%4x,RAM_BASE=%8x,IRQ=%x,CHIPID=%x,\n", + (UINT) io_port, (UINT) ram_base, irq, (UCHAR)chipType); +#endif + + if( !DC390W_init(psht, chipType, io_port, irq, i) ) + adaptCnt++; + chipType = 0; + } + else + break; + } + } + InitialTime = 0; + adapterCnt = adaptCnt; + return( adaptCnt ); +} + +#ifndef VERSION_ELF_1_2_13 + +/******************************************************************** + * Function: tmscsiw_set_info() + * + * Purpose: Set adapter info (!) + * + * Not yet implemented + * + *******************************************************************/ + +int tmscsiw_set_info(char *buffer, int length, struct Scsi_Host *shpnt) +{ + return(-ENOSYS); /* Currently this is a no-op */ +} + +/******************************************************************** + * Function: tmscsiw_proc_info(char* buffer, char **start, + * off_t offset, int length, int hostno, int inout) + * + * Purpose: return SCSI Adapter/Device Info + * + * Input: buffer: Pointer to a buffer where to write info + * start : + * offset: + * hostno: Host adapter index + * inout : Read (=0) or set(!=0) info + * + * Output: buffer: contains info + * length; length of info in buffer + * + * return value: length + * + ********************************************************************/ + +/* KG: proc_info taken from driver aha152x.c */ + +#undef SPRINTF +#define SPRINTF(args...) pos += sprintf(pos, ## args) + +#define YESNO(YN)\ +if (YN) SPRINTF(" Yes ");\ +else SPRINTF(" No ") + +int tmscsiw_proc_info(char *buffer, char **start, + off_t offset, int length, int hostno, int inout) +{ + int dev, spd, spd1; + char *pos = buffer; + PSH shpnt; + PACB acbpnt; + PDCB dcbpnt; + unsigned long flags; +/* Scsi_Cmnd *ptr; */ + + acbpnt = pACB_start; + + while(acbpnt != (PACB)-1) + { + shpnt = acbpnt->pScsiHost; + if (shpnt->host_no == hostno) break; + acbpnt = acbpnt->pNextACB; + } + + if (acbpnt == (PACB)-1) return(-ESRCH); + if (!shpnt) return(-ESRCH); + + if(inout) /* Has data been written to the file ? */ + return(tmscsiw_set_info(buffer, length, shpnt)); + + SPRINTF("Tekram DC390W/U/F (T) PCI SCSI Host Adadpter, "); + SPRINTF("Driver Version 1.11, 1997/02/04\n"); + + save_flags(flags); + cli(); + + SPRINTF("SCSI Host Nr %i, ", hostno); + SPRINTF("DC390WUF Adapter Nr %i\n", acbpnt->AdapterIndex); + SPRINTF("IOPortBase 0x%04x, ", acbpnt -> IOPortBase); + SPRINTF("IRQLevel 0x%02x\n",acbpnt -> IRQLevel); + + SPRINTF("Adapter Type: "); + switch(acbpnt->AdaptType) + { + case DC390W: SPRINTF("DC390W, Fast Wide SCSI \n"); break; + case DC390U: SPRINTF("DC390U, Ultra SCSI\n"); break; + case DC390F: SPRINTF("DC390F, Ultra Wide SCSI\n"); break; + default: SPRINTF("Unknown !\n"); + } + + SPRINTF("MaxID %i, MaxLUN %i, ", acbpnt->max_id, acbpnt->max_lun); + SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); + + SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); + + SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); + + SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ Wide NegoPeriod SyncSpeed SyncOffs\n"); + dcbpnt = acbpnt->pLinkDCB; + + for (dev = 0; dev < acbpnt->DeviceCnt; dev++) + { + SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); + YESNO(dcbpnt->DevMode & PARITY_CHK_); + YESNO(dcbpnt->DCBsxfer & OFFSET_MASK); + YESNO(dcbpnt->DevMode & EN_DISCONNECT_); + YESNO(dcbpnt->DevMode & SEND_START_); + YESNO(dcbpnt->MaxCommand > 1); + YESNO(dcbpnt->DCBscntl3 & EN_WIDE_SCSI); + SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); + if (dcbpnt->DCBsxfer & OFFSET_MASK) + { + spd = 1000/(dcbpnt->SyncPeriod <<2); + spd1 = 1000%(dcbpnt->SyncPeriod <<2); + spd1 = (spd1 * 10)/(dcbpnt->SyncPeriod <<2); + SPRINTF(" %2i.%1i M %02i\n", spd, spd1, dcbpnt->DCBsxfer & OFFSET_MASK); + } + else SPRINTF("\n"); + /* Add more info ...*/ + dcbpnt = dcbpnt->pNextDCB; + } + + restore_flags(flags); + *start = buffer + offset; + + if (pos - buffer < offset) + return 0; + else if (pos - buffer - offset < length) + return pos - buffer - offset; + else + return length; +} +#endif /* VERSION_ELF_1_2_13 */ + +#ifdef MODULE + +/*********************************************************************** + * Function : static int DC390W_shutdown (struct Scsi_Host *host) + * + * Purpose : does a clean (we hope) shutdown of the NCR SCSI chip. + * Use prior to dumping core, unloading the NCR driver, etc. + * + * Returns : 0 on success + ***********************************************************************/ +static int +DC390W_shutdown (struct Scsi_Host *host) +{ + USHORT ioport; + unsigned long flags; + PACB pACB = (PACB) host->hostdata; + + ioport = (unsigned int) pACB->IOPortBase; + + save_flags (flags); + cli(); + +/* pACB->soft_reset(host); */ +/* + * For now, we take the simplest solution : reset the SCSI bus. Eventually, + * - If a command is connected, kill it with an ABORT message + * - If commands are disconnected, connect to each target/LUN and + * do a ABORT, followed by a SOFT reset, followed by a hard + * reset. + */ + +#ifdef DC390W_DEBUG0 + printk("DC390W: shutdown,"); +#endif + outb(ASSERT_RST, ioport+SCNTL1); + udelay(25); /* Minimum amount of time to assert RST */ + outb(0, ioport+SCNTL1); + restore_flags (flags); + return( 0 ); +} + + +int DC390W_release(struct Scsi_Host *host) +{ + int irq_count; + struct Scsi_Host *tmp; + + DC390W_shutdown (host); + + if (host->irq != IRQ_NONE) + { + for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) + { + if ( tmp->irq == host->irq ) + ++irq_count; + } + if (irq_count == 1) + { +#ifdef DC390W_DEBUG0 + printk("DC390W: Free IRQ %i.",host->irq); +#endif +#ifndef VERSION_ELF_1_2_13 + free_irq(host->irq,NULL); +#else + free_irq(host->irq); +#endif + } + } + + release_region(host->io_port,host->n_io_port); + + return( 1 ); +} + +Scsi_Host_Template driver_template = DC390WUF; +#include "scsi_module.c" +#endif /* def MODULE */ + --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/scsiio.c Wed Feb 5 01:54:24 1997 @@ -0,0 +1,1537 @@ +/*********************************************************************** + * FILE NAME : SCSIIO.C * + * BY : C.L. Huang * + * Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + + +static void +PrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + ULONG retAddr,wlval; + USHORT wval,i; + PSGL psgl; + PSGE psge; + + + retAddr = pACB->jmp_table8; + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + retAddr += jmp_table16; + wval = (USHORT)(pSRB->SGcount); + wval <<= 4; /* 16 bytes per entry, datain=8, dataout=8 */ + /* (4 bytes for count, 4 bytes for addr) */ + retAddr -= (ULONG)wval; + pSRB->ReturnAddr = retAddr; /* return address for SCRIPT */ + if(wval) + { + wval >>= 1; + wlval = (ULONG) pSRB->SegmentPad; + wlval -= (ULONG)wval; + wval >>= 3; + psge = (PSGE) wlval; + psgl = pSRB->pSegmentList; + for(i=0; iSGXPtr = virt_to_phys( psgl->address ); +#else + psge->SGXPtr = (ULONG) psgl->address; +#endif + psge->SGXLen = psgl->length; + psge++; + psgl++; + } + } +} + + +static void +DC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + USHORT ioport; + UCHAR bval; + + pSRB->TagNumber = 31; + ioport = pACB->IOPortBase; + bval = SIGNAL_PROC; + outb(bval,ioport+ISTAT); + pACB->pActiveDCB = pDCB; + pDCB->pActiveSRB = pSRB; + return; +} + + +#ifndef VERSION_ELF_1_2_13 +static void +DC390W_Interrupt( int irq, void *dev_id, struct pt_regs *regs) +#else +static void +DC390W_Interrupt( int irq, struct pt_regs *regs) +#endif +{ + PACB pACB; + PDCB pDCB; + ULONG wlval; + USHORT ioport = 0; + USHORT wval, i; + void (*stateV)( PACB ); + UCHAR istat = 0; + UCHAR bval; + + pACB = pACB_start; + if( pACB == NULL ) + return; + for( i=0; i < adapterCnt; i++ ) + { + if( pACB->IRQLevel == (UCHAR) irq ) + { + ioport = pACB->IOPortBase; + istat = inb( ioport+ISTAT ); + if( istat & (ABORT_OP+SCSI_INT_PENDING+DMA_INT_PENDING) ) + break; + else + pACB = pACB->pNextACB; + } + else + { + pACB = pACB->pNextACB; + } + } + + if( pACB == (PACB )-1 ) + { + printk("DC390W_intr: Spurious interrupt detected!\n"); + return; + } + + +#ifdef DC390W_DEBUG1 + printk("Istate=%2x,",istat); +#endif + /* if Abort operation occurred, reset abort bit before reading DMA status + to prevent further aborted interrupt. */ + + if(istat & ABORT_OP) + { + istat &= ~ABORT_OP; + outb(istat,ioport+ISTAT); + } + + pDCB = pACB->pActiveDCB; + bval = inb(ioport+CTEST2); /* Clear Signal Bit */ + + /* If Scsi Interrupt, then clear Interrupt Status by reading + Scsi interrupt status register 0. */ + + wlval = 0; + if(istat & SCSI_INT_PENDING) + { + wlval = (ULONG)inw( ioport+SIST0 ); + wlval <<= 8; + } + + /* If DMA Interrupt, then read the DMA status register to see what happen */ + + if(istat & DMA_INT_PENDING) + { + bval = inb(ioport+DSTAT); + wlval |= (ULONG) bval; + } + +#ifdef DC390W_DEBUG1 + printk("IDstate=%8x,",(UINT) wlval); +#endif + if(wlval & ( (SEL_TIMEOUT << 16)+ + ((SCSI_GERROR+UNEXPECT_DISC+SCSI_RESET) << 8)+ + ILLEGAL_INSTRUC+ABORT_) ) + { + ExceptionHandler( wlval, pACB, pDCB ); + } + else if( wlval & SCRIPTS_INT ) + { + wval = inw( ioport+DSPS ); + stateV = (void *) IntVector[wval]; + stateV( pACB ); + } + else if( wlval & ( PARITY_ERROR << 8) ) + ParityError( pACB, pDCB ); + else if( wlval & ( PHASE_MISMATCH << 8) ) + PhaseMismatch( pACB ); + return; +} + + +static void +ExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB) +{ + PSRB pSRB; + UCHAR bval; + USHORT ioport; + +/* disconnect/scsi reset/illegal instruction */ + + ioport = pACB->IOPortBase; + if(wlval & ( (SCSI_RESET+SCSI_GERROR) << 8) ) + DC390W_ScsiRstDetect( pACB ); + else if(wlval & ABORT_) + { +#ifdef DC390W_DEBUG0 + printk("AboRst,"); +#endif + if( !InitialTime ) + DC390W_ResetSCSIBus2( pACB ); + } + else if(wlval & (SEL_TIMEOUT << 16) ) + { + pACB->status = SCSI_STAT_SEL_TIMEOUT; +#ifdef DC390W_DEBUG1 + printk("Selto,"); +#endif + DC390W_CmdCompleted( pACB ); + } + else if(wlval & (UNEXPECT_DISC << 8) ) + { + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + pSRB = pDCB->pActiveSRB; + if( pSRB->SRBState & DO_SYNC_NEGO ) + { + pDCB->DevMode &= ~SYNC_NEGO_; + pACB->status = SCSI_STAT_CHECKCOND; + DC390W_CmdCompleted( pACB ); + } + else if( pSRB->SRBState & DO_WIDE_NEGO ) + { + pDCB->DevMode &= ~WIDE_NEGO_; + pACB->status = SCSI_STAT_CHECKCOND; + DC390W_CmdCompleted( pACB ); + } + else + { + pACB->status = SCSI_STAT_UNEXP_BUS_F; + DC390W_CmdCompleted( pACB ); + } +#ifdef DC390W_DEBUG0 + printk("Uxpbf,"); +#endif + } + else + { +#ifdef DC390W_DEBUG0 + printk("Except,"); +#endif + DC390W_ResetSCSIBus( pACB ); + } +} + + +static void +ParityError( PACB pACB, PDCB pDCB ) +{ + ULONG ioport; + UCHAR bval,msg; + ULONG wlval; + PSRB pSRB; + + ioport = pACB->IOPortBase; + bval = inb(ioport+SCRATCHA); + if(bval & RE_SELECTED_) + { +#ifdef DC390W_DEBUG0 + printk("ParityErr,"); +#endif + DC390W_ResetSCSIBus( pACB ); + return; + } + else + { + pSRB = pDCB->pActiveSRB; + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + + bval = inb(ioport+DCMD); + bval &= 0x07; /* get phase bits */ + if(bval == 0x07) /* message in phase */ + { + msg = MSG_PARITY_ERROR; + wlval = pACB->jmp_clear_ack; + } + else + { + msg = MSG_INITIATOR_ERROR; + wlval = pACB->jmp_next; + } + pSRB->__msgout0[0] = 1; + pSRB->MsgOutBuf[0] = msg; + outl(wlval,(ioport+DSP)); + return; + } +} + + +static void +DC390W_Signal( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + USHORT ioport; + ULONG wlval, flags; + UCHAR bval,msgcnt,tagnum; + + save_flags(flags); + cli(); + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; +#ifdef DC390W_DEBUG0 + printk("Signal,Cmd=%2x", pSRB->CmdBlock[0]); +#endif + wlval = pSRB->PhysSRB; + outl(wlval,(ioport+DSA)); + wlval = pSRB->ReturnAddr; + outl(wlval,(ioport+TEMP)); + msgcnt = 1; + bval = pDCB->IdentifyMsg; + pSRB->MsgOutBuf[0] = bval; + if( (pSRB->CmdBlock[0] != INQUIRY) && + (pSRB->CmdBlock[0] != REQUEST_SENSE) ) + { + if(pDCB->MaxCommand > 1) + { + wlval = 1; + tagnum = 0; + while( wlval & pDCB->TagMask ) + { + wlval = wlval << 1; + tagnum++; + } + pDCB->TagMask |= wlval; + pSRB->TagNumber = tagnum; + pSRB->MsgOutBuf[1] = MSG_SIMPLE_QTAG; + pSRB->MsgOutBuf[2] = tagnum; + msgcnt = 3; + } + } + else + { + pSRB->MsgOutBuf[0] &= 0xBF; /* Diable Disconnected */ + if(pSRB->CmdBlock[0] == INQUIRY) + { + if(bval & 0x07) + goto type_6_3; + } + if(pDCB->DevMode & WIDE_NEGO_) + { + msgcnt = 5; + *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x01030201; + pSRB->SRBState |= DO_WIDE_NEGO; + } + else if(pDCB->DevMode & SYNC_NEGO_) + { + msgcnt = 6; + *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x00010301; + pSRB->MsgOutBuf[4] = pDCB->NegoPeriod; + pSRB->MsgOutBuf[5] = SYNC_NEGO_OFFSET; + pSRB->SRBState |= DO_SYNC_NEGO; + } + } +type_6_3: + pSRB->__msgout0[0] = (ULONG) msgcnt; + wlval = 0; + outl(wlval,(ioport+SCRATCHA)); + bval = pDCB->DCBscntl0; + outb(bval,ioport+SCNTL0); + pSRB->__select = *((PULONG) &(pDCB->DCBselect)); +#ifdef DC390W_DEBUG0 + printk("__sel=%8x,", (UINT)(pSRB->__select)); +#endif + wlval = pACB->jmp_select; + outl(wlval,(ioport+DSP)); + restore_flags(flags); + return; +} + + +static void +DC390W_MessageWide( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + PUCHAR msgoutPtr; + USHORT ioport; + ULONG wlval; + UCHAR bval,msgcnt; + + +#ifdef DC390W_DEBUG0 + printk("MsgWide,"); +#endif + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + msgcnt = 0; + pDCB->DCBscntl3 &= ~EN_WIDE_SCSI; + msgoutPtr = pSRB->MsgOutBuf; + if( pSRB->SRBState & DO_WIDE_NEGO ) + { + pSRB->SRBState &= ~DO_WIDE_NEGO; + if( pACB->msgin123[0] == 3 ) + { + bval = pACB->msgin123[1]; + if(bval == 1) + { + pDCB->DCBscntl3 |= EN_WIDE_SCSI; + goto x5; + } + if(bval < 1) + goto x5; + } + } + +/*type_11_1:*/ + msgcnt = 1; + *msgoutPtr = MSG_REJECT_; + msgoutPtr++; +x5: + bval = pDCB->DCBscntl3; + outb(bval,ioport+SCNTL3); + AdjustTemp(pACB,pDCB,pSRB); + SetXferRate(pACB,pDCB); + if( pDCB->DevMode & SYNC_NEGO_ ) + { + *((PULONG)msgoutPtr) = 0x00010301; + *(msgoutPtr + 3) = pDCB->NegoPeriod; + *(msgoutPtr + 4) = SYNC_NEGO_OFFSET; + msgcnt += 5; + pSRB->SRBState |= DO_SYNC_NEGO; + } + + pSRB->__msgout0[0] = (ULONG) msgcnt; + wlval = pACB->jmp_clear_ack; + if(msgcnt) + wlval = pACB->jmp_set_atn; + outl(wlval,(ioport+DSP)); + return; +} + + +static void +DC390W_MessageSync( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + USHORT ioport; + ULONG wlval; + USHORT wval,wval1; + UCHAR bval,bval1; + +#ifdef DC390W_DEBUG0 + printk("MsgSync,"); +#endif + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + if( !(pSRB->SRBState & DO_SYNC_NEGO) ) + goto MessageExtnd; + pSRB->SRBState &= ~DO_SYNC_NEGO; + if(pACB->msgin123[0] != 1) + { +MessageExtnd: + pSRB->__msgout0[0] = 1; + pSRB->MsgOutBuf[0] = MSG_REJECT_; + wlval = pACB->jmp_set_atn; + outl(wlval,(ioport+DSP)); + return; + } + bval = pACB->msgin123[2]; /* offset */ +asyncx: + pDCB->DCBsxfer = bval; + if(bval == 0) /* if offset or period == 0, async */ + { + if( pACB->AdaptType == DC390W ) + bval = SYNC_CLK_F2+ASYNC_CLK_F2; + else + bval = SYNC_CLK_F4+ASYNC_CLK_F4; + pDCB->DCBscntl3 = bval; + } + else + { + bval = pACB->msgin123[1]; + if(bval == 0) + goto asyncx; + pDCB->SyncPeriod = bval; + wval = (USHORT)bval; + wval <<= 3; + bval = pDCB->DCBscntl3; + bval &= 0x0f; + if(wval < 200) /* < 100 ns ==> Fast-20 */ + { + bval |= 0x90; /* Fast-20 and div 1 */ + bval1 = 25; /* 12.5 ns */ + } + else if(wval < 400) + { + bval |= 0x30; /* 1 cycle = 25ns */ + bval1 = 50; + } + else /* Non Fast */ + { + bval |= 0x50; /* 1 cycle = 50ns */ + bval1 = 100; + } + if( pACB->AdaptType == DC390W ) + bval -= 0x20; /* turn down to 40Mhz scsi clock */ + /* assume 390W will not receive fast-20 */ + wval1 = wval; + wval /= bval1; + if(wval * bval1 < wval1) + wval++; + /* XFERP TP2 TP1 TP0 */ + wval -= 4; /* 4 0 0 0 */ + /* 5 0 0 1 */ + wval <<= 5; + pDCB->DCBsxfer |= (UCHAR)wval; + pDCB->DCBscntl3 = bval; + } +/*sync_2:*/ + SetXferRate( pACB,pDCB ); + wlval = pACB->jmp_clear_ack; +/*sync_3:*/ + bval = pDCB->DCBscntl3; + outb(bval,ioport+SCNTL3); + bval = pDCB->DCBsxfer; + outb(bval,ioport+SXFER); + outl(wlval,(ioport+DSP)); + return; +} + + +static void +DC390W_MsgReject( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + ULONG wlval; + USHORT ioport; + UCHAR bval; + +#ifdef DC390W_DEBUG0 + printk("Msgrjt,"); +#endif + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + wlval = pACB->jmp_clear_ack; + if(pSRB->SRBState & DO_WIDE_NEGO) + { + pSRB->SRBState &= ~DO_WIDE_NEGO; + pDCB->DCBscntl3 &= ~EN_WIDE_SCSI; + AdjustTemp( pACB, pDCB, pSRB ); + SetXferRate( pACB, pDCB ); + if( pDCB->DevMode & SYNC_NEGO_ ) + { + *((PULONG) &(pSRB->MsgOutBuf[0])) = 0x00010301; + pSRB->MsgOutBuf[3] = pDCB->NegoPeriod; + pSRB->MsgOutBuf[4] = SYNC_NEGO_OFFSET; + pSRB->__msgout0[0] = 5; + pSRB->SRBState |= DO_SYNC_NEGO; + wlval = pACB->jmp_set_atn; + } + } + else + { + if(pSRB->SRBState & DO_SYNC_NEGO) + { + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->DCBsxfer = 0; /* reject sync msg, set aync */ + if( pACB->AdaptType == DC390W ) + bval = SYNC_CLK_F2+ASYNC_CLK_F2; + else + bval = SYNC_CLK_F4+ASYNC_CLK_F4; + pDCB->DCBscntl3 = bval; + SetXferRate(pACB,pDCB); + wlval = pACB->jmp_clear_ack; + } + } + ioport = pACB->IOPortBase; + bval = pDCB->DCBscntl3; + outb(bval,ioport+SCNTL3); + bval = pDCB->DCBsxfer; + outb(bval,ioport+SXFER); + outl(wlval,(ioport+DSP)); + return; +} + + +static void +AdjustTemp( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + USHORT ioport; + ULONG wlval; + + wlval = pSRB->ReturnAddr; + if(wlval <= pACB->jmp_table8) + { + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + wlval += jmp_table16; + } + else + { + if((pDCB->DCBscntl3 & EN_WIDE_SCSI) == 0) + wlval -= jmp_table16; + } + pSRB->ReturnAddr = wlval; + ioport = pACB->IOPortBase; + outl(wlval,(ioport+TEMP)); + return; +} + + +static void +SetXferRate( PACB pACB, PDCB pDCB ) +{ + UCHAR bval; + USHORT cnt, i; + PDCB ptr; + + if( !(pDCB->IdentifyMsg & 0x07) ) + { + if( pACB->scan_devices ) + { + CurrDCBscntl3 = pDCB->DCBscntl3; + } + else + { + ptr = pACB->pLinkDCB; + cnt = pACB->DeviceCnt; + bval = pDCB->UnitSCSIID; + for(i=0; iUnitSCSIID == bval ) + { + ptr->DCBsxfer = pDCB->DCBsxfer; + ptr->DCBscntl3 = pDCB->DCBscntl3; + } + ptr = ptr->pNextDCB; + } + } + } + return; +} + + +static void +DC390W_UnknownMsg( PACB pACB ) +{ + PSRB pSRB; + ULONG wlval; + USHORT ioport; + + pSRB = pACB->pActiveDCB->pActiveSRB; + pSRB->__msgout0[0] = 1; + pSRB->MsgOutBuf[0] = MSG_REJECT_; + wlval = pACB->jmp_set_atn; + ioport = pACB->IOPortBase; + outl(wlval,(ioport+DSP)); + return; +} + + +static void +DC390W_MessageExtnd( PACB pACB ) +{ + DC390W_UnknownMsg( pACB ); +} + + +static void +DC390W_Disconnected( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + ULONG wlval, flags; + USHORT ioport; + UCHAR bval; + +#ifdef DC390W_DEBUG0 + printk("Discnet,"); +#endif + save_flags(flags); + cli(); + pDCB = pACB->pActiveDCB; + if (! pDCB) + { +#ifdef DC390W_DEBUG0 + printk("ACB:%08lx->ActiveDCB:%08lx !,", (ULONG)pACB, (ULONG)pDCB); +#endif + restore_flags(flags); return; + } + + pSRB = pDCB->pActiveSRB; + + ioport = pACB->IOPortBase; + bval = inb(ioport+SCRATCHA); + pSRB->ScratchABuf = bval; + pSRB->SRBState |= SRB_DISCONNECT; /* 1.02 */ + wlval = pACB->jmp_reselect; + outl(wlval,(ioport+DSP)); + pACB->pActiveDCB = 0; + DoWaitingSRB( pACB ); + restore_flags(flags); + return; +} + + +static void +DC390W_Reselected( PACB pACB ) +{ +#ifdef DC390W_DEBUG0 + printk("Rsel,"); +#endif + pACB->msgin123[0] = 0x80; /* set identify byte 80h */ + DC390W_Reselected1(pACB); + return; +} + + +static void +DC390W_Reselected1( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + USHORT ioport, wval; + ULONG wlval, flags; + UCHAR bval; + + +#ifdef DC390W_DEBUG0 + printk("Rsel1,"); +#endif + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + if(pDCB) + { + pSRB = pDCB->pActiveSRB; + RewaitSRB( pDCB, pSRB ); + } + + wval = (USHORT) (pACB->msgin123[0]); + wval = (wval & 7) << 8; /* get LUN */ + wval |= (USHORT) (inb(ioport+SSID) & 0x0f); /* get ID */ + pDCB = pACB->pLinkDCB; + while( *((PUSHORT) &pDCB->UnitSCSIID) != wval ) + pDCB = pDCB->pNextDCB; + pACB->pActiveDCB = pDCB; + bval = pDCB->DCBscntl3; + outb(bval,ioport+SCNTL3); + bval = pDCB->DCBsxfer; + outb(bval,ioport+SXFER); + bval = pDCB->DCBscntl0; + outb(bval,ioport+SCNTL0); + if(pDCB->MaxCommand > 1) + { + wlval = pACB->jmp_reselecttag; + outl(wlval,(ioport+DSP)); + } + else + { + pSRB = pDCB->pActiveSRB; + if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) + { + save_flags(flags); + cli(); + pSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB->pNextSRB; + restore_flags(flags); + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = MSG_ABORT; + pSRB->__msgout0[0] = 1; + } + pSRB->SRBState &= ~SRB_DISCONNECT; + wlval = pSRB->PhysSRB; + outl(wlval,(ioport+DSA)); + wlval = pSRB->ReturnAddr; + outl(wlval,(ioport+TEMP)); + bval = pSRB->ScratchABuf; + outb(bval,ioport+SCRATCHA); + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + wlval = pACB->jmp_set_atn; + else + wlval = pACB->jmp_clear_ack; + outl(wlval,(ioport+DSP)); + } + return; +} + + +static void +DC390W_ReselectedT( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB, psrb1; + USHORT ioport; + ULONG wlval, flags; + UCHAR bval; + +#ifdef DC390W_DEBUG0 + printk("RselT,"); +#endif + ioport = pACB->IOPortBase; + bval = pACB->msgin123[1]; + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pGoingSRB; + psrb1 = pDCB->pGoingLast; + if( !pSRB ) + goto UXP_RSL; + for(;;) + { + if(pSRB->TagNumber != bval) + { + if( pSRB != psrb1 ) + pSRB = pSRB->pNextSRB; + else + goto UXP_RSL; + } + else + break; + } + if( !(pSRB->SRBState & SRB_DISCONNECT) ) + { +UXP_RSL: + save_flags(flags); + cli(); + pSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB->pNextSRB; + restore_flags(flags); + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; + pSRB->__msgout0[0] = 1; + } + else + { + pSRB->SRBState &= ~SRB_DISCONNECT; + pDCB->pActiveSRB = pSRB; + } + wlval = pSRB->PhysSRB; + outl(wlval,(ioport+DSA)); + wlval = pSRB->ReturnAddr; + outl(wlval,(ioport+TEMP)); + bval = pSRB->ScratchABuf; + outb(bval,ioport+SCRATCHA); + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + wlval = pACB->jmp_set_atn; + else + wlval = pACB->jmp_clear_ack; + outl(wlval,(ioport+DSP)); + return; +} + + +static void +DC390W_RestorePtr( PACB pACB ) +{ + PSRB pSRB; + USHORT ioport; + ULONG wlval; + + pSRB = pACB->pActiveDCB->pActiveSRB; + wlval = pSRB->ReturnAddr; + ioport = pACB->IOPortBase; + outl(wlval,(ioport+TEMP)); + wlval = inl(ioport+DSP); + outl(wlval,(ioport+DSP)); + return; +} + + +static void +PhaseMismatch( PACB pACB ) +{ + USHORT ioport; + ULONG wlval,swlval; + USHORT wval; + UCHAR bval,phase; + PDCB pDCB; + +#ifdef DC390W_DEBUG0 + printk("Mismatch,"); +#endif + ioport = pACB->IOPortBase; + bval = inb(ioport+SCRATCHA); + if(bval & OVER_RUN_) /* xfer PAD */ + { + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + wlval = pACB->jmp_next; /* check phase */ + outl(wlval,(ioport+DSP)); + return; + } + pDCB = pACB->pActiveDCB; + wlval = inl(ioport+DBC); + phase = (UCHAR)((wlval & 0x07000000) >> 24); + wlval &= 0xffffff; /* bytes not xferred */ + if( phase == SCSI_DATA_IN ) + { + swlval = pACB->jmp_din8; + if( pDCB->DCBscntl3 & EN_WIDE_SCSI ) + swlval += jmp_din16; + DataIOcommon(pACB,swlval,wlval); + } + else if( phase == SCSI_DATA_OUT ) + { + wval = (USHORT)inb(ioport+CTEST5); + wval <<= 8; + bval = inb(ioport+DFIFO); + wval |= (USHORT) bval; + wval -= ((USHORT)(wlval & 0xffff)); + wval &= 0x3ff; + wlval += (ULONG)wval; /* # of bytes remains in FIFO */ + bval = inb(ioport+SSTAT0); + if(bval & SODR_LSB_FULL) + wlval++; /* data left in Scsi Output Data Buffer */ + if(bval & SODL_LSB_FULL) + wlval++; /* data left in Scsi Output Data Latch */ + swlval = pACB->jmp_dout8; + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + { + swlval += jmp_dout16; + bval = inb(ioport+SSTAT2); + if(bval & SODR_MSB_FULL) + wlval++; + if(bval & SODL_MSB_FULL) + wlval++; + } + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + DataIOcommon(pACB,swlval,wlval); + } + else + { + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + if(phase == SCSI_MSG_OUT) + wlval = pACB->jmp_clear_atn; + else + wlval = pACB->jmp_next; /* check phase */ + outl(wlval,(ioport+DSP)); + } + return; +} + + +static void +DataIOcommon( PACB pACB, ULONG Swlval, ULONG Cwlval ) +{ + /* Swlval - script address */ + /* Cwlval - bytes not xferred */ + PDCB pDCB; + PSRB pSRB; + PSGE Segptr; + USHORT ioport; + ULONG wlval,swlval,dataXferCnt; + UCHAR bval,bvald; + + ioport = pACB->IOPortBase; + wlval = inl((ioport+DSP)); + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + wlval -= Swlval; + bval = inb(ioport+SBCL); + bval &= 0x07; + if(bval == SCSI_MSG_IN) + { + bval = pDCB->DCBscntl3; + bval &= ~EN_WIDE_SCSI; + outb(bval,ioport+SCNTL3); + bval = inb(ioport+SBDL); + bvald = pDCB->DCBscntl3; /* enable WIDE SCSI */ + outb(bvald,ioport+SCNTL3); + if(bval == MSG_DISCONNECT || bval == MSG_SAVE_PTR) + { + Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval); + dataXferCnt = Segptr->SGXLen - Cwlval; + Segptr->SGXLen = Cwlval; /* modified count */ + Segptr->SGXPtr += dataXferCnt; /* modified address */ + swlval = pACB->jmp_table8; + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + swlval += jmp_table16; + wlval <<= 1; + swlval += wlval; + swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16); + pSRB->ReturnAddr = swlval; + } + } + else if( Cwlval ) /* Remaining not xferred -- UNDER_RUN */ + { + Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval); + dataXferCnt = Segptr->SGXLen - Cwlval; + Segptr->SGXLen = Cwlval; /* modified count */ + Segptr->SGXPtr += dataXferCnt; /* modified address */ + swlval = pACB->jmp_table8; + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + swlval += jmp_table16; + wlval <<= 1; + swlval += wlval; + swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16); + pSRB->RemainSegPtr = swlval; + } +/* pm__1: */ + wlval = pSRB->ReturnAddr; + outl(wlval,(ioport+TEMP)); + wlval = pACB->jmp_next; + outl(wlval,(ioport+DSP)); + return; +} + + +static void +DC390W_CmdCompleted( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB; + USHORT ioport; + ULONG wlval, flags; + UCHAR bval; + +#ifdef DC390W_DEBUG0 + printk("Cmplete,"); +#endif + save_flags(flags); + cli(); + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + pDCB->pActiveSRB = NULL; + ioport = pACB->IOPortBase; + + bval = inb(ioport+SCRATCHA); + pSRB->ScratchABuf = bval; /* save status */ + bval = pSRB->TagNumber; + if(pDCB->MaxCommand > 1) + pDCB->TagMask &= (~(1 << bval)); /* free tag mask */ + pACB->pActiveDCB = NULL; /* no active device */ + wlval = pACB->jmp_reselect; /* enable reselection */ + outl(wlval,(ioport+DSP)); + SRBdone( pACB, pDCB, pSRB); + restore_flags(flags); + return; +} + + +static void +SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb; + UCHAR bval, bval1, i, j, status; + PSCSICMD pcmd; + PSCSI_INQDATA ptr; + USHORT disable_tag; + ULONG flags; + PSGE ptr1; + PSGL ptr2; + ULONG wlval,swlval; + + pcmd = pSRB->pcmd; + status = pACB->status; + if(pSRB->SRBFlag & AUTO_REQSENSE) + { + pSRB->SRBFlag &= ~AUTO_REQSENSE; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = SCSI_STAT_CHECKCOND; + if(status == SCSI_STAT_CHECKCOND) + { + pcmd->result = DID_BAD_TARGET << 16; + goto ckc_e; + } + if(pSRB->RetryCnt == 0) + { + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0]; + pSRB->XferredLen = pSRB->Segment0[2][1]; + if( (pSRB->XferredLen) && + (pSRB->XferredLen >= pcmd->underflow) ) + { + pcmd->result |= (DID_OK << 16); + } + else + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; + goto ckc_e; + } + else + { + pSRB->RetryCnt--; + pSRB->TargetStatus = 0; + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0]; + *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[0][1]; + *((PULONG) &(pSRB->CmdBlock[8])) = pSRB->Segment0[1][0]; + pSRB->__command[0] = pSRB->Segment0[1][1] & 0xff; + pSRB->SGcount = (UCHAR) (pSRB->Segment0[1][1] >> 8); + *((PULONG) &(pSRB->pSegmentList))= pSRB->Segment0[2][0]; + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; + goto ckc_e; + } + pcmd->result |= (DRIVER_SENSE << 24); + PrepareSG(pACB,pDCB,pSRB); + pSRB->XferredLen = 0; + DC390W_StartSCSI( pACB, pDCB, pSRB ); + return; + } + } + if( status ) + { + if( status == SCSI_STAT_CHECKCOND) + { + if( !(pSRB->ScratchABuf & SRB_OK) && (pSRB->SGcount) && (pSRB->RemainSegPtr) ) + { + wlval = pSRB->RemainSegPtr; + swlval = pACB->jmp_table8; + if(pDCB->DCBscntl3 & EN_WIDE_SCSI) + swlval += jmp_table16; + swlval -= wlval; + swlval >>= 4; + bval = (UCHAR) swlval; + wlval = 0; + ptr1 = (PSGE) &pSRB->Segment0[MAX_SG_LIST_BUF+1][0]; + for( i=0; i< bval; i++) + { + wlval += ptr1->SGXLen; + ptr1--; + } + + bval = pSRB->SGcount; + swlval = 0; + ptr2 = pSRB->pSegmentList; + for( i=0; i< bval; i++) + { + swlval += ptr2->length; + ptr2++; + } + pSRB->XferredLen = swlval - wlval; + pSRB->RemainSegPtr = 0; +#ifdef DC390W_DEBUG0 + printk("XferredLen=%8x,NotXferLen=%8x,",(UINT) pSRB->XferredLen,(UINT) wlval); +#endif + } + RequestSense( pACB, pDCB, pSRB ); + return; + } + else if( status == SCSI_STAT_QUEUEFULL ) + { + bval = (UCHAR) pDCB->GoingSRBCnt; + bval--; + pDCB->MaxCommand = bval; + RewaitSRB( pDCB, pSRB ); + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + return; + } + else if(status == SCSI_STAT_SEL_TIMEOUT) + { + pSRB->AdaptStatus = H_SEL_TIMEOUT; + pSRB->TargetStatus = 0; + pcmd->result = DID_BAD_TARGET << 16; + } + else if(status == SCSI_STAT_UNEXP_BUS_F) + { + pSRB->AdaptStatus = H_UNEXP_BUS_FREE; + pSRB->TargetStatus = 0; + pcmd->result |= DID_NO_CONNECT << 16; + } + else if(status == SCSI_STAT_BUS_RST_DETECT ) + { + pSRB->AdaptStatus = H_ABORT; + pSRB->TargetStatus = 0; + pcmd->result = DID_RESET << 16; + } + else + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = status; + if( pSRB->RetryCnt ) + { + pSRB->RetryCnt--; + pSRB->TargetStatus = 0; + PrepareSG(pACB,pDCB,pSRB); + pSRB->XferredLen = 0; + DC390W_StartSCSI( pACB, pDCB, pSRB ); + return; + } + else + { + pcmd->result |= (DID_ERROR << 16) | (ULONG) (pACB->msgin123[0] << 8) | + (ULONG) status; + } + } + } + else + { + status = pSRB->ScratchABuf; + if(status & OVER_RUN_) + { + pSRB->AdaptStatus = H_OVER_UNDER_RUN; + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16) | (pACB->msgin123[0] << 8); + } + else /* No error */ + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16); + } + } +ckc_e: + + if( pACB->scan_devices ) + { + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + if(pcmd->result != (DID_OK << 16)) + { + if( pcmd->result & SCSI_STAT_CHECKCOND ) + { + goto RTN_OK; + } + else + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && + ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) ) + { + pACB->scan_devices = 0; + } + } + } + else + { +RTN_OK: + pPrevDCB->pNextDCB = pDCB; + pDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) ) + pACB->scan_devices = END_SCAN; + } + } + else if( pSRB->CmdBlock[0] == INQUIRY ) + { + if( (pcmd->target == pACB->max_id) && + (pcmd->lun == pACB->max_lun) ) + { + pACB->scan_devices = 0; + } + ptr = (PSCSI_INQDATA) (pcmd->request_buffer); + if( pcmd->use_sg ) + ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); + bval1 = ptr->DevType & SCSI_DEVTYPE; + if(bval1 == SCSI_NODEV) + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else + { + pACB->DeviceCnt++; + pPrevDCB = pDCB; + pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390W_DCB )); + pDCB->DevType = bval1; + if(bval1 == TYPE_DISK || bval1 == TYPE_MOD) + { + if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) && + (ptr->Flags & SCSI_INQ_CMDQUEUE) && + (pDCB->DevMode & TAG_QUEUING_) && + (pDCB->DevMode & EN_DISCONNECT_) ) + { + disable_tag = 0; + for(i=0; iMaxCommand = pACB->TagMaxNum; + pDCB->TagMask = 0; + } + } + } + } + } + } + + save_flags( flags ); + cli(); +/* ReleaseSRB( pDCB, pSRB ); */ + + if(pSRB == pDCB->pGoingSRB ) + { + pDCB->pGoingSRB = pSRB->pNextSRB; + } + else + { + psrb = pDCB->pGoingSRB; + while( psrb->pNextSRB != pSRB ) + psrb = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb; + } + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pDCB->GoingSRBCnt--; + + DoWaitingSRB( pACB ); + restore_flags(flags); + +/* Notify cmd done */ + pcmd->scsi_done( pcmd ); + + if( pDCB->QIORBCnt ) + DoNextCmd( pACB, pDCB ); + return; +} + + +static void +DoingSRB_Done( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + PSCSICMD pcmd; + + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for( i=0; ipNextSRB; + pcmd = psrb->pcmd; + pcmd->result = DID_RESET << 16; + +/* ReleaseSRB( pDCB, pSRB ); */ + + psrb->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = psrb; + + pcmd->scsi_done( pcmd ); + psrb = psrb2; + } + pdcb->GoingSRBCnt = 0;; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +DC390W_ResetSCSIBus( PACB pACB ) +{ + USHORT ioport; + UCHAR bval; + ULONG flags; + + save_flags(flags); + cli(); + pACB->ACBFlag |= RESET_DEV; + ioport = pACB->IOPortBase; + bval = ABORT_OP; + outb(bval,ioport+ISTAT); + udelay(25); + bval = 0; + outb(bval,ioport+ISTAT); + + bval = ASSERT_RST; + outb(bval,ioport+SCNTL1); + udelay(25); /* 25 us */ + bval = 0; + outb(bval,ioport+SCNTL1); + restore_flags(flags); + return; +} + + + +static void +DC390W_ResetSCSIBus2( PACB pACB ) +{ + USHORT ioport; + UCHAR bval; + ULONG flags; + + save_flags(flags); + cli(); + ioport = pACB->IOPortBase; + bval = ASSERT_RST; + outb(bval,ioport+SCNTL1); + udelay(25); /* 25 us */ + bval = 0; + outb(bval,ioport+SCNTL1); + restore_flags(flags); + return; +} + + + +static void +DC390W_ScsiRstDetect( PACB pACB ) +{ + ULONG wlval, flags; + USHORT ioport; + UCHAR bval; + + save_flags(flags); + sti(); +#ifdef DC390W_DEBUG0 + printk("Reset_Detect0,"); +#endif +/* delay 1 sec */ + wlval = jiffies + HZ; + while( jiffies < wlval ); +/* USHORT i; + for( i=0; i<1000; i++ ) + udelay(1000); */ + + cli(); + ioport = pACB->IOPortBase; + bval = inb(ioport+STEST3); + bval |= CLR_SCSI_FIFO; + outb(bval,ioport+STEST3); + bval = CLR_DMA_FIFO; + outb(bval,ioport+CTEST3); + + if( pACB->ACBFlag & RESET_DEV ) + pACB->ACBFlag |= RESET_DONE; + else + { + pACB->ACBFlag |= RESET_DETECT; + + ResetDevParam( pACB ); +/* DoingSRB_Done( pACB ); ???? */ + RecoverSRB( pACB ); + pACB->pActiveDCB = NULL; + wlval = pACB->jmp_reselect; + outl(wlval,(ioport+DSP)); + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + } + restore_flags(flags); + return; +} + + +static void +RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSCSICMD pcmd; + + pSRB->SRBFlag |= AUTO_REQSENSE; + pSRB->Segment0[0][0] = *((PULONG) &(pSRB->CmdBlock[0])); + pSRB->Segment0[0][1] = *((PULONG) &(pSRB->CmdBlock[4])); + pSRB->Segment0[1][0] = *((PULONG) &(pSRB->CmdBlock[8])); + pSRB->Segment0[1][1] = pSRB->__command[0] | (pSRB->SGcount << 8); + pSRB->Segment0[2][0] = *((PULONG) &(pSRB->pSegmentList)); + pSRB->Segment0[2][1] = pSRB->XferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + + pcmd = pSRB->pcmd; + + pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); + pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + pSRB->pSegmentList = &pSRB->Segmentx; + pSRB->SGcount = 1; + + *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003; + pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; + *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer); + pSRB->__command[0] = 6; + PrepareSG( pACB, pDCB, pSRB ); + pSRB->XferredLen = 0; + DC390W_StartSCSI( pACB, pDCB, pSRB ); + return; +} + + +static void +DC390W_MessageOut( PACB pACB ) +{ + DC390W_FatalError( pACB ); +} + + +static void +DC390W_FatalError( PACB pACB ) +{ + PSRB pSRB; + PDCB pDCB; + ULONG flags; + +#ifdef DC390W_DEBUG0 + printk("DC390W: Fatal Error!!\n"); +#endif + + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + { + save_flags(flags); + cli(); + pSRB->SRBState &= ~SRB_UNEXPECT_RESEL; + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pACB->pActiveDCB = NULL; + pDCB->pActiveSRB = NULL; + restore_flags(flags); + DoWaitingSRB( pACB ); + } + else + DC390W_ResetSCSIBus(pACB); + return; +} + + +static void +DC390W_Debug( PACB pACB ) +{ + ULONG wlval; + USHORT ioport; + + ioport = pACB->IOPortBase; + wlval = inl(ioport+DSP); + outl(wlval,(ioport+DSP)); + return; +} + + --- /dev/null Mon Aug 26 02:21:17 1996 +++ linux/drivers/scsi/scripts.h Wed Feb 5 01:54:24 1997 @@ -0,0 +1,1357 @@ +/*********************************************************************** +;* File Name : SCRIPTS.H * +;* Description:SCRIPT language for NCR53c825A,875 SCRIPT processor* +;* * +;*********************************************************************** + +;========================================================== +; NCR 53C810,53C815,53C820,53C825,53C825A,53C860,53C875 +; Script language definition for assembly programming +;========================================================== + +;========================================================== +; DMA Command +;========================================================== +*/ +#define DCMD_BLOCK_MOVE 0 +#define DCMD_IO 0x040000000 /*;BIT30 */ +#define DCMD_RD_WRT 0x040000000 /*;BIT30 */ +#define DCMD_XFER_CTRL 0x080000000 /*;BIT31 */ +#define DCMD_MEM_MOVE 0x0C0000000 /*;(BIT31+BIT30) */ +#define DCMD_LOAD_STORE 0x0E0000000 /*;(BIT31+BIT30+BIT29) */ +/*;==========================================================*/ +#define INDIRECT_ADDR 0x20000000 /*;BIT29 */ +#define TABLE_INDIRECT 0x10000000 /*;BIT28 */ +#define BLOCK_MOVE 0x08000000 /*;BIT27 */ +#define CHAIN_MOVE 0 +/*; SCSI phase definition */ +#define DATA_OUT_ 0x00000000 /*;data out phase */ +#define DATA_IN_ 0x01000000 /*;BIT24 ; data in phase */ +#define COMMAND_ 0x02000000 /*;BIT25 ; command phase */ +#define STATUS_ 0x03000000 /*;(BIT25+BIT24) ; status phase */ +#define RESERVED_OUT 0x04000000 /*;BIT26 */ +#define RESERVED_IN 0x05000000 /*;(BIT26+BIT24) */ +#define MSG_OUT_ 0x06000000 /*;(BIT26+BIT25) ; message in phase */ +#define MSG_IN_ 0x07000000 /*;(BIT26+BIT25+BIT24);message out phase */ +/*;----------------------------------------------------------*/ +#define DCMD_SELECT 0x40000000 /*;DCMD_IO+0 */ +#define DCMD_SELECT_ATN 0x41000000 /*;(DCMD_IO+BIT24) */ +#define DCMD_WAIT_DISC 0x48000000 /*;(DCMD_IO+BIT27) */ +#define DCMD_WAIT_RESEL 0x50000000 /*;(DCMD_IO+BIT28) */ +#define DCMD_SET_CARRY 0x58000400 /*;(DCMD_IO+BIT28+BIT27+BIT10) */ +#define DCMD_SET_ACK 0x58000040 /*;(DCMD_IO+BIT28+BIT27+BIT6) */ +#define DCMD_SET_ATN 0x58000008 /*;(DCMD_IO+BIT28+BIT27+BIT3) */ +#define DCMD_CLR_CARRY 0x60000400 /*;(DCMD_IO+BIT29+BIT10) */ +#define DCMD_CLR_ACK 0x60000040 /*;(DCMD_IO+BIT29+BIT6) */ +#define DCMD_CLR_ATN 0x60000008 /*;(DCMD_IO+BIT29+BIT3) */ +#define RELATIVE_ADDR 0x04000000 /*;BIT26 */ +#define IO_TABLE_INDIR 0x02000000 /*;BIT25 */ +/*;----------------------------------------------------------*/ +#define MOVE_FROM_SFBR 0x68000000 /*;(DCMD_RD_WRT+BIT29+BIT27) */ +#define MOVE_TO_SFBR 0x70000000 /*;(DCMD_RD_WRT+BIT29+BIT28) */ +#define RD_MODIFY_WRT 0x78000000 /*;(DCMD_RD_WRT+BIT29+BIT28+BIT27) */ +#define OP_MOVE_DATA 0 +#define OP_SHIFT_LEFT_C 0x01000000 /*;BIT24 */ +#define OP_OR 0x02000000 /*;BIT25 */ +#define OP_XOR 0x03000000 /*;(BIT25+BIT24) */ +#define OP_AND 0x04000000 /*;BIT26 */ +#define OP_SHIFT_RIGHT_C 0x05000000 /*;(BIT26+BIT24) */ +#define OP_ADD_DATA 0x06000000 /*;(BIT26+BIT25) */ +#define OP_ADD_DATA_C 0x07000000 /*;(BIT26+BIT25+BIT24) */ +#define USE_SFBR 0x00800000 /*;BIT23 */ +/*;----------------------------------------------------------*/ +#define DCMD_JUMP 0x80000000 /*;DCMD_XFER_CTRL+0 */ +#define DCMD_CALL 0x88000000 /*;(DCMD_XFER_CTRL+BIT27) */ +#define DCMD_RETURN 0x90000000 /*;(DCMD_XFER_CTRL+BIT28) */ +#define DCMD_INT 0x98000000 /*;(DCMD_XFER_CTRL+BIT28+BIT27) */ +#define RELATIVE_ 0x00800000 /*;BIT23 */ +#define IF_CARRY 0x00200000 /*;BIT21 */ +#define INT_ON_FLY_ 0x00100000 /*;BIT20 */ +#define IF_TRUE 0x00080000 /*;BIT19 */ +#define IF_NOT 0 +#define DATA_CMP 0x00040000 /*;BIT18 */ +#define PHASE_CMP 0x00020000 /*;BIT17 */ +#define WAIT_PHASE_VALID 0x00010000 /*;BIT16 */ +/*;----------------------------------------------------------*/ +#define DSA_RELATIVE 0x10000000 /*;BIT28 */ +#define FLUSH_PREFETCH 0x02000000 /*;BIT25 */ +#define DCMD_LOAD 0x0E1000000 /*;(DCMD_LOAD_STORE+BIT24) */ +#define DCMD_STORE 0x0E0000000 /*;DCMD_LOAD_STORE */ +/* +;========================================================== +; SCSI message EQUATES +;========================================================== +*/ +#define CMD_COMPLETE 0 +#define EXT_MSG 1 +#define SAVE_PTR 2 +#define RESTORE_PTR 3 +#define DISCONNECTMSG 4 +#define INITIATOR_ERR 5 +#define ABORTMSG 6 +#define MSG_REJECT 7 +#define NOPMSG 8 +#define MSG_PARITY 9 +#define LINK_CMD_CPL 0x0a +#define LINK_CMD_FLAG 0x0b +#define RESET_DEVICE 0x0c +#define IDENTIFYMSG 0x80 +#define SIMPLE_TAG 0x20 +#define IGNORE_WIDE_RES 0x23 +/* +;========================================================== +; Operation assumption +; 1. If phase mismatch during Xfer PAD ==> do nothing +; Else compute FIXUP needed +; 2. After phase mismatch ==> Set to Xfer PAD +; 3. At disconnection ==> Modify return address +; 4. 1st restore ptr after reselection is ignored +; 5. If Xfer PAD is done ==> Error +;========================================================== +*/ +/* static start_script + static reselected + static reselecttag + static select0 + static select1 + static check_phase + static status1_phase + static command_phase + static jump_table0 + static jump_tableB + static din_phase + static din_phaseB + static din_pad_0 + static din_pad_addrB + static dout_phase + static dout_phaseB + static dout_pad_0 + static dout_pad_addrB + static jump_tablew + static jump_tableW + static din_phase1 + static din_phaseW + static din_pad_1 + static din_pad_addrW + static dout_phase1 + static dout_phaseW + static dout_pad_1 + static dout_pad_addrW + static mout_phase + static status_phase + static min_phase + static set_atn + static clr_atn + static end_script + static start_mov + static SrcPhysAddr + static DesPhysAddr +*/ +ULONG start_script[]={ +/* +;========================================================== +; Wait for reselection +;========================================================== +*/ + DCMD_WAIT_RESEL + }; +ULONG jmp_select0[]={ + 0 /* offset select0 */ + }; +ULONG reselected[]={ + RD_MODIFY_WRT+OP_OR+0x200+0x340000, /* (2 shl 8) or (__scratcha shl 16) */ + 0, + + DCMD_INT+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+MSG_IN_, + __RESELECTED, + + BLOCK_MOVE+MSG_IN_+1 /* ;move in ID byte */ + }; +ULONG ACB_msgin123_1[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_INT+IF_TRUE, + __RESELECTED1 + }; +ULONG reselecttag[]={ + DCMD_CLR_ACK, + 0, + + BLOCK_MOVE+MSG_IN_+2 /* ;move 2 msg bytes */ + }; +ULONG ACB_msgin123_2[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_INT+IF_TRUE, + __RESELECTEDT + }; +/* +;========================================================== +; Select +; Case 1 : Only identify message is to be sent +; Case 2 : Synchronous negotiation is requested +;========================================================== +*/ +ULONG select0[]={ + DCMD_INT+IF_TRUE, + __SIGNAL + }; +ULONG select1[]={ /* ; Select with ATN */ + + DCMD_SELECT_ATN+IO_TABLE_INDIR /* +offset SRB.__select ;4200h or 0100H */ + }; +ULONG jmp_reselected[]={ + 0, /* offset reselected, */ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+MSG_OUT_ + }; +ULONG jmp_check_phase[]={ + 0, /* offset check_phase, */ + + TABLE_INDIRECT+BLOCK_MOVE+MSG_OUT_ + }; +ULONG SRB_msgout0[]={ + 0 /* offset SRB.__msgout0 */ + }; +ULONG check_phase[]={ + DCMD_RETURN+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, + + DCMD_RETURN+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0 + }; +ULONG status1_phase[]={ + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+STATUS_ + }; +ULONG jmp_status_phase[]={ + 0, /* offset status_phase,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+COMMAND_ + }; +ULONG jmp_command_phase[]={ + 0, /* offset command_phase, */ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+MSG_IN_ + }; +ULONG jmp_min_phase[]={ + 0, /* offset min_phase,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+MSG_OUT_ + }; +ULONG jmp_mout_phase[]={ + 0, /* offset mout_phase,*/ + + DCMD_INT+IF_TRUE, + __FATALERROR + }; +/* +;========================================================== +; Command phase +;========================================================== +*/ +ULONG command_phase[]={ + DCMD_CLR_ATN, + 0, + TABLE_INDIRECT+BLOCK_MOVE+COMMAND_ + }; +ULONG SRB_command[]={ + 0, /* offset SRB.__command,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase1[]={ + 0 /* offset check_phase */ + }; +/* +;========================================================== +; Data phase jump table for 8 bit operation +;========================================================== +*/ +ULONG jmp_dio_phaseB[]={ + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseB+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseB+ 128,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0 /* offset dout_phaseB+ 128 */ + }; +ULONG jump_table0[]={ + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_ + }; +ULONG jmp_din_pad_0[]={ + 0, /* offset din_pad_0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_ + }; +ULONG jmp_dout_pad_0[]={ + 0 /* offset dout_pad_0 */ + }; + +#define jump_tableB jump_table0 +/* +;========================================================== +; Data in phase +;========================================================== +*/ +ULONG din_phaseB[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_, + 0, /* offset SRB.Segment16,*/ + + RD_MODIFY_WRT+OP_OR+0x100+0x340000, /*;(1 shl 8) or (__scratcha shl 16)*/ + 0, + + DCMD_JUMP+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+DATA_IN_ + }; +ULONG jmp_status1_phase[]={ + 0 /* offset status1_phase */ + }; + +#define din_phase din_phaseB + +ULONG din_pad_0[]={ + RD_MODIFY_WRT+OP_OR+0x340000+0x400, /*;(4 shl 8) or (__scratcha shl 16)*/ + 0 + }; +ULONG din_pad_addrB[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_IN_ + }; +ULONG SRB_SegmentPad[]={ + 0, /* offset SRB.SegmentPad,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_din_pad_addrB[]={ + 0 /* offset din_pad_addrB */ + }; +/* +;========================================================== +; Data out phase +;========================================================== +*/ +ULONG dout_phaseB[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment16,*/ + + RD_MODIFY_WRT+OP_OR+0x100+0x340000, /*;(1 shl 8) or (__scratcha shl 16)*/ + 0, + + DCMD_JUMP+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+DATA_OUT_ + }; +ULONG jmp_status1_phase1[]={ + 0 /* offset status1_phase */ + }; + +#define dout_phase dout_phaseB + +ULONG dout_pad_0[]={ + RD_MODIFY_WRT+OP_OR+0x340000+0x400, /*;(4 shl 8) or (__scratcha shl 16)*/ + 0 + }; +ULONG dout_pad_addrB[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_ + }; +ULONG SRB_SegmentPad1[]={ + 0, /* offset SRB.SegmentPad,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_dout_pad_addrB[]={ + 0 /* offset dout_pad_addrB */ + }; +/* +;========================================================== +; Data phase jump table for WIDE SCSI operation +;========================================================== +*/ +ULONG jmp_dio_phaseW[]={ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 0,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 8,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 16,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 24,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 32,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 40,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 48,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 56,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 64,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 72,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 80,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 88,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 96,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 104,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 112,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0, /* offset dout_phaseW+ 120,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_, + 0, /* offset din_phaseW+ 128,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_, + 0 /* offset dout_phaseW+ 128 */ + }; +ULONG jump_tablew[]={ + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_IN_ + }; +ULONG jmp_din_pad_1[]={ + 0, /* offset din_pad_1,*/ + + DCMD_JUMP+WAIT_PHASE_VALID+IF_TRUE+PHASE_CMP+DATA_OUT_ + }; +ULONG jmp_dout_pad_1[]={ + 0 /* offset dout_pad_1 */ + }; + +#define jump_tableW jump_tablew +/* +;========================================================== +; Data in phase +;========================================================== +*/ +ULONG din_phaseW[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_, + 0, /* offset SRB.Segment16,*/ + + RD_MODIFY_WRT+OP_OR+0x340000+0x100, /*;(1 shl 8) or (__scratcha shl 16)*/ + 0, + + DCMD_JUMP+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+DATA_IN_ + }; +ULONG jmp_status1_phase2[]={ + 0 /* offset status1_phase */ + }; + +#define din_phase1 din_phaseW + +ULONG din_pad_1[]={ + RD_MODIFY_WRT+OP_OR+0x340000+0x400, /*;(4 shl 8) or (__scratcha shl 16)*/ + 0 + }; +ULONG din_pad_addrW[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_IN_ + }; +ULONG SRB_SegmentPad2[]={ + 0, /* offset SRB.SegmentPad,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_din_pad_addrW[]={ + 0 /* offset din_pad_addrW */ + }; +/* +;========================================================== +; Data out phase +;========================================================== +*/ +ULONG dout_phaseW[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment15,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment0,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment1,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment2,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment3,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment4,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment5,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment6,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment7,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment8,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment9,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment10,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment11,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment12,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment13,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment14,*/ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+CHAIN_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment15,*/ +/*; 18000000h or DATA_OUT_ */ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_, + 0, /* offset SRB.Segment16,*/ + + RD_MODIFY_WRT+OP_OR+0x340000+0x100, /*;(1 shl 8) or (__scratcha shl 16)*/ + 0, + + DCMD_JUMP+WAIT_PHASE_VALID+IF_NOT+PHASE_CMP+DATA_OUT_ + }; +ULONG jmp_status1_phase3[]={ + 0 /* offset status1_phase */ + }; + +#define dout_phase1 dout_phaseW + +ULONG dout_pad_1[]={ + RD_MODIFY_WRT+OP_OR+0x340000+0x400, /*;(4 shl 8) or (__scratcha shl 16)*/ + 0 + }; +ULONG dout_pad_addrW[]={ + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+DATA_OUT_ + }; +ULONG SRB_SegmentPad3[]={ + 0, /* offset SRB.SegmentPad,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_dout_pad_addrW[]={ + 0 /* offset dout_pad_addrW */ + }; +/* +;========================================================== +; message out phase +;========================================================== +*/ +ULONG mout_phase[]={ + DCMD_SET_ATN, + 0, + + DCMD_BLOCK_MOVE+TABLE_INDIRECT+BLOCK_MOVE+MSG_OUT_ + }; +ULONG SRB_msgout01[]={ + 0, /* offset SRB.__msgout0,*/ + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase2[]={ + 0 /* offset check_phase */ + }; +/* +;========================================================== +; Status phase process +;========================================================== +*/ +ULONG status_phase[]={ + DCMD_BLOCK_MOVE+BLOCK_MOVE+STATUS_+1 + }; +ULONG ACB_status[]={ + 0 /* offset ACB.status */ + }; +/* +;========================================================== +; message in phase +;========================================================== +*/ +ULONG min_phase[]={ + DCMD_BLOCK_MOVE+BLOCK_MOVE+MSG_IN_+1 + }; +ULONG ACB_msgin123_3[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_JUMP+IF_NOT+DATA_CMP+CMD_COMPLETE + }; +ULONG jmp_jump_msgok[]={ + 0 /* offset jump_msgok */ + }; +/* +;========================================================== +; command complete message +;========================================================== +*/ +ULONG msg__0[]={ + RD_MODIFY_WRT+OP_AND+0x20000+0x7F00, /*;(7FH shl 8) or (__scntl2 shl 16)*/ + 0, + + DCMD_CLR_ACK, + 0, + + DCMD_WAIT_DISC, + 0, + + DCMD_INT+IF_TRUE, + __COMPLETE + }; +/* +;========================================================== +; Other message +;========================================================== +*/ +ULONG jump_msgok[]={ + DCMD_JUMP+IF_TRUE+DATA_CMP+SAVE_PTR + }; +ULONG jmp_msg__a[]={ + 0, /* offset msg__a,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+RESTORE_PTR + }; +ULONG jmp_msg__3[]={ + 0, /* offset msg__3,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+DISCONNECTMSG + }; +ULONG jmp_msg__4[]={ + 0, /* offset msg__4,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+EXT_MSG + }; +ULONG jmp_msg__1[]={ + 0, /* offset msg__1,*/ + + DCMD_INT+IF_TRUE+DATA_CMP+MSG_REJECT, + __MSGREJECT, + + DCMD_JUMP+IF_TRUE+DATA_CMP+LINK_CMD_CPL + }; +ULONG jmp_msg__a1[]={ + 0, /* offset msg__a,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+LINK_CMD_FLAG + }; +ULONG jmp_msg__a2[]={ + 0, /* offset msg__a,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+IGNORE_WIDE_RES + }; +ULONG jmp_msg__23[]={ + 0, /* offset msg__23,*/ + + DCMD_INT+IF_TRUE, + __MSGUNKNOWN + }; +/* +;========================================================== +; Extended message +;========================================================== +*/ +ULONG msg__1[]={ + DCMD_CLR_ACK, + 0, + + DCMD_BLOCK_MOVE+BLOCK_MOVE+MSG_IN_+1 /* ;ext msg len */ + }; +ULONG ACB_msgin123_4[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+3 + }; +ULONG jmp_msg___3[]={ + 0, /* offset msg___3,*/ + + DCMD_JUMP+IF_TRUE+DATA_CMP+2 + }; +ULONG jmp_msg___2[]={ + 0, /* offset msg___2,*/ + + DCMD_INT+IF_TRUE, + __MSGEXTEND + }; + +ULONG msg___3[]={ + DCMD_CLR_ACK, + 0, + + DCMD_BLOCK_MOVE+BLOCK_MOVE+MSG_IN_+3 + }; +ULONG ACB_msgin123_5[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_INT+IF_TRUE, + __MSGSYNC + }; + +ULONG msg___2[]={ + DCMD_CLR_ACK, + 0, + + DCMD_BLOCK_MOVE+BLOCK_MOVE+MSG_IN_+2 + }; +ULONG ACB_msgin123_6[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_INT+IF_TRUE, + __MSGWIDE + }; +/* +;############################################################ +; for synchronous negotiation +; 1. Active ==> INT3, restart at data__1_2 +; 2. Passive ==> INT3, prepare message out, restart at data__1_1 +; 3. Disable ==> INT3, prepare message out, restart at data__1_1 +;############################################################ +*/ +ULONG set_atn[]={ + DCMD_SET_ATN, + 0 + }; +ULONG msg__a[]={ + DCMD_CLR_ACK, + 0, + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase3[]={ + 0 /* offset check_phase */ + }; + +ULONG msg__23[]={ /* ; ignore wide residue */ + DCMD_CLR_ACK, + 0, + + DCMD_BLOCK_MOVE+BLOCK_MOVE+MSG_IN_+1 + }; +ULONG ACB_msgin123_7[]={ + 0, /* offset ACB.msgin123,*/ + + DCMD_CLR_ACK, + 0, + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase4[]={ + 0 /* offset check_phase */ + }; + +ULONG msg__3[]={ + DCMD_CLR_ACK, + 0, + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase5[]={ + 0 /* offset check_phase */ + }; + +ULONG msg__4[]={ /* ; disconnect */ + RD_MODIFY_WRT+OP_AND+0x20000+0x7F00, /*;(7FH shl 8) or (__scntl2 shl 16)*/ + 0, + + DCMD_CLR_ACK, + 0, + + DCMD_WAIT_DISC, + 0, + + DCMD_INT+IF_TRUE, + __DISCONNECTED + }; + +ULONG clr_atn[]={ + DCMD_CLR_ATN, + 0, + + DCMD_JUMP+IF_TRUE + }; +ULONG jmp_check_phase6[]={ + 0 /* offset check_phase */ + }; +/* +;========================================================== +; Used for script operation +;========================================================== +*/ +ULONG start_mov[]={ +/*; DCMD_MEM_MOVE+(OFFSET DGROUP:end_script - OFFSET DGROUP:start_script) ;Memory move SCRIPTS instruction*/ + DCMD_MEM_MOVE+0x1000 /*;Memory move SCRIPTS instruction ( 4K )*/ + }; +ULONG SrcPhysAddr[]={ + 0 /*; source */ + }; +ULONG DesPhysAddr[]={ + 0, /*; destination */ + + DCMD_INT+IF_TRUE, /*; script interrupt, */ + 0, + + DCMD_INT+IF_NOT, /*; script interrupt */ + 0 + }; +ULONG end_script[]={0}; +/***********************************************************************/ +