📄 am53c974.c
字号:
#include <linux/module.h>#include <linux/config.h>#include <linux/delay.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/bios32.h>#include <linux/pci.h>#include <linux/string.h>#include <linux/blk.h>#include <asm/io.h>#include <asm/system.h>#include "scsi.h"#include "hosts.h"#include "AM53C974.h"#include "constants.h"#include "sd.h"/* AM53/79C974 (PCscsi) driver release 0.5 * * The architecture and much of the code of this device * driver was originally developed by Drew Eckhardt for * the NCR5380. The following copyrights apply: * For the architecture and all pieces of code which can also be found * in the NCR5380 device driver: * Copyright 1993, Drew Eckhardt * Visionary Computing * (Unix and Linux consulting and custom programming) * drew@colorado.edu * +1 (303) 666-5836 * * The AM53C974_nobios_detect code was originally developed by * Robin Cutshaw (robin@xfree86.org) and is used here in a * slightly modified form. * * For the remaining code: * Copyright 1994, D. Frieauff * EMail: fri@rsx42sun0.dofn.de * Phone: x49-7545-8-2256 , x49-7541-42305 *//* * $Log: AM53C974.c,v $ * Revision 1.1 1999/04/26 05:53:47 tb * 1998-11-30 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> * * Clean up linux emulation code to make it architecture-independent * as much as possible. * * * linux: Renamed from linuxdev. * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o. * (MAKE): New variable. Used for the linux.o target. * * configure.in: Add AC_CHECK_TOOL(MAKE, make). * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with * OSF Mach 3.0. Suggested by Elgin Lee <ehl@funghi.com>. * * linux/src: Renamed from linux/linux. * * linux/dev: Renamed from linux/mach. * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h, * instead of mach/include/linux/autoconf.h. * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o. * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead * of <i386/ipl.h>. * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files, * <i386/ipl.h> and <i386/pic.h>. * * linux/dev/init/main.c: Many i386-dependent codes moved to ... * * linux/dev/arch/i386/irq.c: ... here. * * linux/dev/arch/i386/setup.c: New file. * * linux/dev/arch/i386/linux_emul.h: Likewise. * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c. * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead * of <i386/ipl.h>, and moved to ... * * linux/dev/kernel/sched.c: ... here. * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and * <linux_emul.h>, instead of i386-dependent header files, and * moved to ... * * linux/dev/glue/blocl.c: ... here. * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and * <linux_emul.h>, instead of i386-dependent header files, and * moved to ... * * linux/dev/glue/net.c: ... here. * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ... * * linux/dev/glue/misc.c: ... here. * * linux/dev/arch/i386/glue/kmem.c: Moved to ... * * linux/dev/glue/kmem.c: ... here. * */#ifdef AM53C974_DEBUG #define DEB(x) x #ifdef AM53C974_DEBUG_KEYWAIT #define KEYWAIT() AM53C974_keywait() #else #define KEYWAIT() #endif #ifdef AM53C974_DEBUG_INIT #define DEB_INIT(x) x #else #define DEB_INIT(x) #endif #ifdef AM53C974_DEBUG_MSG #define DEB_MSG(x) x #else #define DEB_MSG(x) #endif #ifdef AM53C974_DEB_RESEL #define DEB_RESEL(x) x #else #define DEB_RESEL(x) #endif #ifdef AM53C974_DEBUG_QUEUE #define DEB_QUEUE(x) x #define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } #define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } #else #define DEB_QUEUE(x) #define LIST(x,y) #define REMOVE(w,x,y,z) #endif #ifdef AM53C974_DEBUG_INFO #define DEB_INFO(x) x #else #define DEB_INFO(x) #endif #ifdef AM53C974_DEBUG_LINKED #define DEB_LINKED(x) x #else #define DEB_LINKED(x) #endif #ifdef AM53C974_DEBUG_INTR #define DEB_INTR(x) x #else #define DEB_INTR(x) #endif#else #define DEB_INIT(x) #define DEB(x) #define DEB_QUEUE(x) #define LIST(x,y) #define REMOVE(w,x,y,z) #define DEB_INFO(x) #define DEB_LINKED(x) #define DEB_INTR(x) #define DEB_MSG(x) #define DEB_RESEL(x) #define KEYWAIT()#endif #ifdef AM53C974_DEBUG_ABORT #define DEB_ABORT(x) x #else #define DEB_ABORT(x) #endif#ifdef VERBOSE_AM53C974_DEBUG#define VDEB(x) x#else#define VDEB(x)#endif#define INSIDE(x,l,h) ( ((x) >= (l)) && ((x) <= (h)) )#ifdef AM53C974_DEBUGstatic void AM53C974_print_pci(struct Scsi_Host *instance);static 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 int AM53C974_bios_detect(Scsi_Host_Template *tpnt);static int AM53C974_nobios_detect(Scsi_Host_Template *tpnt);static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config);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 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;/************************************************************************** * Function : void AM53C974_print_pci(struct Scsi_Host *instance) * * Purpose : dump the PCI registers for debugging purposes * * Input : instance - which AM53C974 **************************************************************************/static void AM53C974_print_pci(struct Scsi_Host *instance){int i;unsigned short vendor_id, device_id, command, status, scratch[8];unsigned long class_revision, base; unsigned char irq, cache_line_size, latency_timer, header_type;AM53C974_PCIREG_OPEN();for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i);vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID);device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID);command = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND);status = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS);class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION);cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE);latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER);header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE);base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0);irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE);AM53C974_PCIREG_CLOSE();printk("------------- start of PCI register dump -------------\n");printk("PCI_VENDOR_ID: 0x%x\n", vendor_id);printk("PCI_DEVICE_ID: 0x%x\n", device_id);printk("PCI_COMMAND: 0x%x\n", command);printk("PCI_STATUS: 0x%x\n", status);printk("PCI_CLASS_REVISION: 0x%lx\n", class_revision);printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size);printk("PCI_LATENCY_TIMER: 0x%x\n", latency_timer);printk("PCI_HEADER_TYPE: 0x%x\n", header_type);printk("PCI_BASE_ADDRESS_0: 0x%lx\n", base);printk("PCI_INTERRUPT_LINE: %d\n", irq);for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d: 0x%x\n", i, scratch[i]);printk("------------- end of PCI register dump -------------\n\n");}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){struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;Scsi_Cmnd *ptr;printk("AM53C974: coroutine is%s running.\n", main_running ? "" : "n't"); 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -