⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 u14-34f.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define PRODUCT_ID2  0x40        /* NOTE: Only upper nibble is used *//* Subversion values */#define ISA  0#define ESA 1#define OP_HOST_ADAPTER   0x1#define OP_SCSI           0x2#define OP_RESET          0x4#define DTD_SCSI          0x0#define DTD_IN            0x1#define DTD_OUT           0x2#define DTD_NONE          0x3#define HA_CMD_INQUIRY    0x1#define HA_CMD_SELF_DIAG  0x2#define HA_CMD_READ_BUFF  0x3#define HA_CMD_WRITE_BUFF 0x4#undef  DEBUG_LINKED_COMMANDS#undef  DEBUG_DETECT#undef  DEBUG_INTERRUPT#undef  DEBUG_RESET#undef  DEBUG_GENERATE_ERRORS#undef  DEBUG_GENERATE_ABORTS#undef  DEBUG_GEOMETRY#define MAX_ISA 3#define MAX_VESA 1#define MAX_EISA 0#define MAX_PCI 0#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)#define MAX_CHANNEL 1#define MAX_LUN 8#define MAX_TARGET 8#define MAX_MAILBOXES 16#define MAX_SGLIST 32#define MAX_SAFE_SGLIST 16#define MAX_INTERNAL_RETRIES 64#define MAX_CMD_PER_LUN 2#define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)#define SKIP ULONG_MAX#define FALSE 0#define TRUE 1#define FREE 0#define IN_USE   1#define LOCKED   2#define IN_RESET 3#define IGNORE   4#define READY    5#define ABORTING 6#define NO_DMA  0xff#define MAXLOOP  10000#define REG_LCL_MASK      0#define REG_LCL_INTR      1#define REG_SYS_MASK      2#define REG_SYS_INTR      3#define REG_PRODUCT_ID1   4#define REG_PRODUCT_ID2   5#define REG_CONFIG1       6#define REG_CONFIG2       7#define REG_OGM           8#define REG_ICM           12#define REGION_SIZE       13#define BSY_ASSERTED      0x01#define IRQ_ASSERTED      0x01#define CMD_RESET         0xc0#define CMD_OGM_INTR      0x01#define CMD_CLR_INTR      0x01#define CMD_ENA_INTR      0x81#define ASOK              0x00#define ASST              0x91#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])#define YESNO(a) ((a) ? 'y' : 'n')#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)#define PACKED          __attribute__((packed))struct sg_list {   unsigned int address;                /* Segment Address */   unsigned int num_bytes;              /* Segment Length */   };/* MailBox SCSI Command Packet */struct mscp {   unsigned char opcode: 3;             /* type of command */   unsigned char xdir: 2;               /* data transfer direction */   unsigned char dcn: 1;                /* disable disconnect */   unsigned char ca: 1;                 /* use cache (if available) */   unsigned char sg: 1;                 /* scatter/gather operation */   unsigned char target: 3;             /* SCSI target id */   unsigned char channel: 2;            /* SCSI channel number */   unsigned char lun: 3;                /* SCSI logical unit number */   unsigned int data_address PACKED;    /* transfer data pointer */   unsigned int data_len PACKED;        /* length in bytes */   unsigned int link_address PACKED;    /* for linking command chains */   unsigned char clink_id;              /* identifies command in chain */   unsigned char use_sg;                /* (if sg is set) 8 bytes per list */   unsigned char sense_len;   unsigned char scsi_cdbs_len;         /* 6, 10, or 12 */   unsigned char scsi_cdbs[12];         /* SCSI commands */   unsigned char adapter_status;        /* non-zero indicates HA error */   unsigned char target_status;         /* non-zero indicates target error */   unsigned int sense_addr PACKED;   Scsi_Cmnd *SCpnt;   unsigned int index;                  /* cp index */   struct sg_list *sglist;   };struct hostdata {   struct mscp cp[MAX_MAILBOXES];       /* Mailboxes for this board */   unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */   unsigned int last_cp_used;           /* Index of last mailbox used */   unsigned int iocount;                /* Total i/o done for this board */   int board_number;                    /* Number of this board */   char board_name[16];                 /* Name of this board */   char board_id[256];                  /* data from INQUIRY on this board */   int in_reset;                        /* True if board is doing a reset */   int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */   int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */   unsigned int retries;                /* Number of internal retries */   unsigned long last_retried_pid;      /* Pid of last retried command */   unsigned char subversion;            /* Bus type, either ISA or ESA */   unsigned char heads;   unsigned char sectors;   /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */   unsigned char slot;   };static struct Scsi_Host *sh[MAX_BOARDS + 1];static const char *driver_name = "Ux4F";static char sha[MAX_BOARDS];/* Initialize num_boards so that ihdlr can work while detect is in progress */static unsigned int num_boards = MAX_BOARDS;static unsigned long io_port[] __initdata = {   /* Space for MAX_INT_PARAM ports usable while loading as a module */   SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,    SKIP,   /* Possible ISA/VESA ports */   0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140,   /* End of list */   0x0   };#define HD(board) ((struct hostdata *) &sh[board]->hostdata)#define BN(board) (HD(board)->board_name)#define SWAP_BYTE(x) ((unsigned long)( \        (((unsigned long)(x) & 0x000000ffU) << 24) | \        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \        (((unsigned long)(x) & 0xff000000U) >> 24)))#if defined(__BIG_ENDIAN)#define H2DEV(x) SWAP_BYTE(x)#else#define H2DEV(x) (x)#endif#define DEV2H(x) H2DEV(x)#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)static void do_interrupt_handler(int, void *, struct pt_regs *);static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);static int do_trace = FALSE;static int setup_done = FALSE;static int link_statistics = 0;static int ext_tran = FALSE;#if defined(HAVE_OLD_UX4F_FIRMWARE)static int have_old_firmware = TRUE;#elsestatic int have_old_firmware = FALSE;#endif#if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS)static int linked_comm = TRUE;#elsestatic int linked_comm = FALSE;#endif#if defined(CONFIG_SCSI_U14_34F_MAX_TAGS)static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS;#elsestatic int max_queue_depth = MAX_CMD_PER_LUN;#endifstatic void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {   Scsi_Device *dev;   int j, ntag = 0, nuntag = 0, tqd, utqd;   IRQ_FLAGS   IRQ_LOCK_SAVE   j = ((struct hostdata *) host->hostdata)->board_number;   for(dev = devlist; dev; dev = dev->next) {      if (dev->host != host) continue;      if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm))         ntag++;      else         nuntag++;      }   utqd = MAX_CMD_PER_LUN;   tqd = (host->can_queue - utqd * nuntag) / (ntag ? ntag : 1);   if (tqd > max_queue_depth) tqd = max_queue_depth;   if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN;   for(dev = devlist; dev; dev = dev->next) {      char *tag_suffix = "", *link_suffix = "";      if (dev->host != host) continue;      if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm))         dev->queue_depth = tqd;      else         dev->queue_depth = utqd;      if (TLDEV(dev->type)) {         if (linked_comm && dev->queue_depth > 2)            link_suffix = ", sorted";         else            link_suffix = ", unsorted";         }      if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)         tag_suffix = ", tagged";      else if (dev->tagged_supported && TLDEV(dev->type))         tag_suffix = ", untagged";      printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n",             BN(j), host->host_no, dev->channel, dev->id, dev->lun,             dev->queue_depth, link_suffix, tag_suffix);      }   IRQ_UNLOCK_RESTORE   return;}static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {   while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {      udelay(1L);      if (--loop == 0) return TRUE;      }   return FALSE;}static int board_inquiry(unsigned int j) {   struct mscp *cpp;   unsigned int time, limit = 0;   cpp = &HD(j)->cp[0];   memset(cpp, 0, sizeof(struct mscp));   cpp->opcode = OP_HOST_ADAPTER;   cpp->xdir = DTD_IN;   cpp->data_address = V2DEV(HD(j)->board_id);   cpp->data_len = H2DEV(sizeof(HD(j)->board_id));   cpp->scsi_cdbs_len = 6;   cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {      printk("%s: board_inquiry, adapter busy.\n", BN(j));      return TRUE;      }   HD(j)->cp_stat[0] = IGNORE;   /* Clear the interrupt indication */   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);   /* Store pointer in OGM address bytes */   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);   /* Issue OGM interrupt */   outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);   SPIN_UNLOCK   IRQ_UNLOCK   time = jiffies;   while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);   IRQ_LOCK   SPIN_LOCK   if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {      HD(j)->cp_stat[0] = FREE;      printk("%s: board_inquiry, err 0x%x.\n", BN(j), cpp->adapter_status);      return TRUE;      }   return FALSE;}__initfunc (static inline int port_detect \      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {   unsigned char irq, dma_channel, subversion, i;   unsigned char in_byte;   char *bus_type, dma_name[16];   /* Allowed BIOS base addresses (NULL indicates reserved) */   void *bios_segment_table[8] = {      NULL,      (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000,      (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000      };   /* Allowed IRQs */   unsigned char interrupt_table[4] = { 15, 14, 11, 10 };   /* Allowed DMA channels for ISA (0 indicates reserved) */   unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };   /* Head/sector mappings */   struct {      unsigned char heads;      unsigned char sectors;      } mapping_table[4] = {           { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }           };   struct config_1 {      unsigned char bios_segment: 3;      unsigned char removable_disks_as_fixed: 1;      unsigned char interrupt: 2;      unsigned char dma_channel: 2;      } config_1;   struct config_2 {      unsigned char ha_scsi_id: 3;      unsigned char mapping_mode: 2;      unsigned char bios_drive_number: 1;      unsigned char tfr_port: 2;      } config_2;   char name[16];   sprintf(name, "%s%d", driver_name, j);   if(check_region(port_base, REGION_SIZE)) {      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);      return FALSE;      }   if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE;   in_byte = inb(port_base + REG_PRODUCT_ID2);   if ((in_byte & 0xf0) != PRODUCT_ID2) return FALSE;   *(char *)&config_1 = inb(port_base + REG_CONFIG1);   *(char *)&config_2 = inb(port_base + REG_CONFIG2);   irq = interrupt_table[config_1.interrupt];   dma_channel = dma_channel_table[config_1.dma_channel];   subversion = (in_byte & 0x0f);   /* Board detected, allocate its IRQ */   if (request_irq(irq, do_interrupt_handler,             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),             driver_name, (void *) &sha[j])) {      printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);      return FALSE;      }   if (subversion == ISA && request_dma(dma_channel, driver_name)) {      printk("%s: unable to allocate DMA channel %u, detaching.\n",             name, dma_channel);      free_irq(irq, &sha[j]);      return FALSE;      }   if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING;#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)   tpnt->use_new_eh_code = use_new_eh_code;#else   use_new_eh_code = FALSE;#endif   sh[j] = scsi_register(tpnt, sizeof(struct hostdata));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -