📄 am53c974.c
字号:
#define TAG_NEXT -1 /* Use next free tag */#define TAG_NONE -2 /* Establish I_T_L nexus instead of I_T_L_Q * even on SCSI-II devices *//************ LILO overrides *************/typedef struct _override_t { int host_scsi_id; /* SCSI id of the bus controller */ int target_scsi_id; /* SCSI id of target */ int max_rate; /* max. transfer rate */ int max_offset; /* max. sync. offset, 0 = asynchronous */} override_t;#ifdef AM53C974_DEBUGstatic void AM53C974_print_phase(struct Scsi_Host *instance);static void AM53C974_print_queues(struct Scsi_Host *instance);#endif /* AM53C974_DEBUG */static void AM53C974_print(struct Scsi_Host *instance);static void AM53C974_keywait(void);static __inline__ int AM53C974_pci_detect(Scsi_Host_Template * tpnt);static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev);static void AM53C974_config_after_reset(struct Scsi_Host *instance);static __inline__ void initialize_SCp(Scsi_Cmnd * cmd);static __inline__ void run_main(void);static void AM53C974_main(void);static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs);static void do_AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs);static void AM53C974_intr_disconnect(struct Scsi_Host *instance);static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg);static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target);static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target);static void AM53C974_information_transfer(struct Scsi_Host *instance, unsigned char statreg, unsigned char isreg, unsigned char instreg, unsigned char cfifo, unsigned char dmastatus);static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd * cmd, unsigned char msg);static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);static void AM53C974_intr_reselect(struct Scsi_Host *instance, unsigned char statreg);static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, unsigned long length, char *data);static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, unsigned char statreg);static void AM53C974_intr_bus_reset(struct Scsi_Host *instance);static struct Scsi_Host *first_instance = NULL;static Scsi_Host_Template *the_template = NULL;static struct Scsi_Host *first_host = NULL; /* Head of list of AMD boards */static volatile int main_running = 0;static int commandline_current = 0;override_t overrides[7] ={ {-1, 0, 0, 0},}; /* LILO overrides */struct proc_dir_entry proc_scsi_am53c974 ={ PROC_SCSI_AM53C974, 8, "am53c974", S_IFDIR | S_IRUGO | S_IXUGO, 2};#ifdef AM53C974_DEBUGstatic int deb_stop = 1;static struct { unsigned char value; char *name;} phases[] = { { PHASE_DATAOUT, "DATAOUT" }, { PHASE_DATAIN, "DATAIN" }, { PHASE_CMDOUT, "CMDOUT" }, { PHASE_STATIN, "STATIN" }, { PHASE_MSGOUT, "MSGOUT" }, { PHASE_MSGIN, "MSGIN" }, { PHASE_RES_0, "RESERVED 0" }, { PHASE_RES_1, "RESERVED 1" }};/************************************************************************** * Function : void AM53C974_print_phase(struct Scsi_Host *instance) * * Purpose : print the current SCSI phase for debugging purposes * * Input : instance - which AM53C974 **************************************************************************/static void AM53C974_print_phase(struct Scsi_Host *instance){ AM53C974_local_declare(); unsigned char statreg, latched; int i; AM53C974_setio(instance); latched = (AM53C974_read_8(CNTLREG2)) & CNTLREG2_ENF; statreg = AM53C974_read_8(STATREG); for (i = 0; (phases[i].value != PHASE_RES_1) && (phases[i].value != (statreg & STATREG_PHASE)); ++i); if (latched) printk("scsi%d : phase %s, latched at end of last command\n", instance->host_no, phases[i].name); else printk("scsi%d : phase %s, real time\n", instance->host_no, phases[i].name);}/************************************************************************** * Function : void AM53C974_print_queues(struct Scsi_Host *instance) * * Purpose : print commands in the various queues * * Inputs : instance - which AM53C974 **************************************************************************/static void AM53C974_print_queues(struct Scsi_Host *instance){ unsigned long flags; struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata; Scsi_Cmnd *ptr; printk("AM53C974: coroutine is%s running.\n", main_running ? "" : "n't"); save_flags(flags); cli(); if (!hostdata->connected) { printk("scsi%d: no currently connected command\n", instance->host_no); } else { print_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected); } if (!hostdata->sel_cmd) { printk("scsi%d: no currently arbitrating command\n", instance->host_no); } else { print_Scsi_Cmnd((Scsi_Cmnd *) hostdata->sel_cmd); } printk("scsi%d: issue_queue ", instance->host_no); if (!hostdata->issue_queue) printk("empty\n"); else { printk(":\n"); for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) print_Scsi_Cmnd(ptr); } printk("scsi%d: disconnected_queue ", instance->host_no); if (!hostdata->disconnected_queue) printk("empty\n"); else { printk(":\n"); for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) print_Scsi_Cmnd(ptr); } restore_flags(flags);}#endif /* AM53C974_DEBUG *//************************************************************************** * Function : void AM53C974_print(struct Scsi_Host *instance) * * Purpose : dump the chip registers for debugging purposes * * Input : instance - which AM53C974 **************************************************************************/static void AM53C974_print(struct Scsi_Host *instance){ AM53C974_local_declare(); unsigned long flags; unsigned long ctcreg, dmastc, dmaspa, dmawbc, dmawac; unsigned char cmdreg, statreg, isreg, cfireg, cntlreg[4], dmacmd, dmastatus; AM53C974_setio(instance); save_flags(flags); cli(); ctcreg = AM53C974_read_8(CTCHREG) << 16; ctcreg |= AM53C974_read_8(CTCMREG) << 8; ctcreg |= AM53C974_read_8(CTCLREG); cmdreg = AM53C974_read_8(CMDREG); statreg = AM53C974_read_8(STATREG); isreg = AM53C974_read_8(ISREG); cfireg = AM53C974_read_8(CFIREG); cntlreg[0] = AM53C974_read_8(CNTLREG1); cntlreg[1] = AM53C974_read_8(CNTLREG2); cntlreg[2] = AM53C974_read_8(CNTLREG3); cntlreg[3] = AM53C974_read_8(CNTLREG4); dmacmd = AM53C974_read_8(DMACMD); dmastc = AM53C974_read_32(DMASTC); dmaspa = AM53C974_read_32(DMASPA); dmawbc = AM53C974_read_32(DMAWBC); dmawac = AM53C974_read_32(DMAWAC); dmastatus = AM53C974_read_8(DMASTATUS); restore_flags(flags); printk("AM53C974 register dump:\n"); printk("IO base: 0x%04lx; CTCREG: 0x%04lx; CMDREG: 0x%02x; STATREG: 0x%02x; ISREG: 0x%02x\n", io_port, ctcreg, cmdreg, statreg, isreg); printk("CFIREG: 0x%02x; CNTLREG1-4: 0x%02x; 0x%02x; 0x%02x; 0x%02x\n", cfireg, cntlreg[0], cntlreg[1], cntlreg[2], cntlreg[3]); printk("DMACMD: 0x%02x; DMASTC: 0x%04lx; DMASPA: 0x%04lx\n", dmacmd, dmastc, dmaspa); printk("DMAWBC: 0x%04lx; DMAWAC: 0x%04lx; DMASTATUS: 0x%02x\n", dmawbc, dmawac, dmastatus); printk("---------------------------------------------------------\n");}/*************************************************************************** Function : void AM53C974_keywait(void)** Purpose : wait until a key is pressed, if it was the 'r' key leave singlestep mode;* this function is used for debugging only** Input : none**************************************************************************/static void AM53C974_keywait(void){ unsigned long flags;#ifdef AM53C974_DEBUG int key; if (!deb_stop) return;#endif save_flags(flags); cli(); while ((inb_p(0x64) & 0x01) != 0x01);#ifdef AM53C974_DEBUG key = inb(0x60); if (key == 0x93) deb_stop = 0; /* don't stop if 'r' was pressed */#endif restore_flags(flags);}/*************************************************************************** Function : AM53C974_setup(char *str, int *ints)** Purpose : LILO command line initialization of the overrides array,* * Inputs : str - unused, ints - array of integer parameters with ints[0]* equal to the number of ints.** NOTE : this function needs to be declared as an external function* in init/main.c and included there in the bootsetups list***************************************************************************/void AM53C974_setup(char *str, int *ints){ if (ints[0] < 4) printk("AM53C974_setup: wrong number of parameters;\n correct syntax is: AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset\n"); else { if (commandline_current < (sizeof(overrides) / sizeof(override_t))) { if ((ints[1] < 0) || (ints[1] > 7) || (ints[2] < 0) || (ints[2] > 7) || (ints[1] == ints[2]) || (ints[3] < (DEF_CLK / MAX_PERIOD)) || (ints[3] > (DEF_CLK / MIN_PERIOD)) || (ints[4] < 0) || (ints[4] > MAX_OFFSET)) printk("AM53C974_setup: illegal parameter\n"); else { overrides[commandline_current].host_scsi_id = ints[1]; overrides[commandline_current].target_scsi_id = ints[2]; overrides[commandline_current].max_rate = ints[3]; overrides[commandline_current].max_offset = ints[4]; commandline_current++; } } else printk("AM53C974_setup: too many overrides\n"); }}#if defined (CONFIG_PCI)/*************************************************************************** Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt)** Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios** Inputs : tpnt - host template* * Returns : number of host adapters detected**************************************************************************/static __inline__ int AM53C974_pci_detect(Scsi_Host_Template * tpnt){ int count = 0; /* number of boards detected */ struct pci_dev *pdev = NULL; unsigned short command; while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pdev))) { pci_read_config_word(pdev, PCI_COMMAND, &command); /* check whether device is I/O mapped -- should be */ if (!(command & PCI_COMMAND_IO)) continue; /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility to set the PCI Master Enable Bit if needed. (from Mark Stockton <marks@schooner.sys.hou.compaq.com>) */ if (!(command & PCI_COMMAND_MASTER)) { command |= PCI_COMMAND_MASTER; printk("PCI Master Bit has not been set. Setting...\n"); pci_write_config_word(pdev, PCI_COMMAND, command); } /* everything seems OK now, so initialize */ if (AM53C974_init(tpnt, pdev)) count++; } return (count);}#endif/*************************************************************************** Function : int AM53C974_detect(Scsi_Host_Template *tpnt)** Purpose : detects and initializes AM53C974 SCSI chips** Inputs : tpnt - host template* * Returns : number of host adapters detected**************************************************************************/__initfunc(int AM53C974_detect(Scsi_Host_Template * tpnt)){ int count = 0; /* number of boards detected */ tpnt->proc_dir = &proc_scsi_am53c974;#if defined (CONFIG_PCI) if (pci_present()) count = AM53C974_pci_detect(tpnt);#endif return (count);}/*************************************************************************** Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -