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

📄 eata.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
      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_AUX_STATUS) & ABSY_ASSERTED) {      udelay(1L);      if (--loop == 0) return TRUE;      }   return FALSE;}static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) {   if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE;   if ((addr = V2DEV(addr))) {      outb((char) (addr >> 24), iobase + REG_LOW);      outb((char) (addr >> 16), iobase + REG_LM);      outb((char) (addr >> 8),  iobase + REG_MID);      outb((char)  addr,        iobase + REG_MSB);      }   outb(cmd, iobase + REG_CMD);   return FALSE;}static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) {   unsigned int loop = MAXLOOP;   ushort *p;   for (p = start; p <= end; p++) {      while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {         udelay(1L);         if (--loop == 0) return TRUE;         }      loop = MAXLOOP;      *p = inw(iobase);      }   return FALSE;}__initfunc (static inline int            get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) {#if defined(CONFIG_PCI)#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)   unsigned int addr;   struct pci_dev *dev = NULL;   if (!pci_present()) return FALSE;   while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) {      if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;#if defined(DEBUG_PCI_DETECT)      printk("%s: get_pci_irq, bus %d, devfn 0x%x, addr 0x%x, apic_irq %u.\n",             driver_name, dev->bus->number, dev->devfn, addr, dev->irq);#endif      if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)             continue;      if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {         *apic_irq = dev->irq;         return TRUE;         }      }#endif /* end new style PCI code */#endif /* end CONFIG_PCI */   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 protocol_rev, apic_irq;   struct eata_info info;   char *bus_type, dma_name[16], tag_type;   /* Allowed DMA channels for ISA (0 indicates reserved) */   unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };   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 (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE;   /* Read the info structure */   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0]))      return FALSE;   /* Check the controller "EATA" signature */   if (info.sign != EATA_SIGNATURE) return FALSE;   if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {      printk("%s: config structure size (%ld bytes) too short, detaching.\n",             name, DEV2H(info.data_len));      return FALSE;      }   else if (DEV2H(info.data_len) == EATA_2_0A_SIZE)      protocol_rev = 'A';   else if (DEV2H(info.data_len) == EATA_2_0B_SIZE)      protocol_rev = 'B';   else      protocol_rev = 'C';   if (!setup_done && j > 0 && j <= MAX_PCI) {      bus_type = "PCI";      subversion = ESA;      }   else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {      bus_type = "PCI";      subversion = ESA;      }   else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {      bus_type = "EISA";      subversion = ESA;      }   else if (protocol_rev == 'C' && !info.eisa && !info.pci) {      bus_type = "ISA";      subversion = ISA;      }   else if (port_base > MAX_ISA_ADDR) {      bus_type = "PCI";      subversion = ESA;      }   else {      bus_type = "ISA";      subversion = ISA;      }   if (!info.haaval || info.ata) {      printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n",             name, port_base, bus_type, info.haaval, info.ata);      return FALSE;      }   if (info.drqvld) {      if (subversion ==  ESA)         printk("%s: warning, weird %s board using DMA.\n", name, bus_type);      subversion = ISA;      dma_channel = dma_channel_table[3 - info.drqx];      }   else {      if (subversion ==  ISA)         printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);      subversion = ESA;      dma_channel = NO_DMA;      }   if (!info.dmasup)      printk("%s: warning, DMA protocol support not asserted.\n", name);   irq = info.irq;   if (subversion == ESA && !info.irq_tr)      printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",             name, irq);   if (get_pci_irq(port_base, &apic_irq) && (irq != apic_irq)) {      printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, apic_irq);      irq = apic_irq;      }   /* 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 defined(FORCE_CONFIG)   {   struct eata_config config;   /* Set board configuration */   memset((char *)&config, 0, sizeof(struct eata_config));   config.len = (ushort) htons((ushort)510);   config.ocena = TRUE;   if (do_dma(port_base, (unsigned int)&config, SET_CONFIG_DMA)) {      printk("%s: busy timeout sending configuration, detaching.\n", name);      return FALSE;      }   }#endif   sh[j] = scsi_register(tpnt, sizeof(struct hostdata));   if (sh[j] == NULL) {      printk("%s: unable to register host, detaching.\n", name);      free_irq(irq, &sha[j]);      if (subversion == ISA) free_dma(dma_channel);      return FALSE;      }   sh[j]->io_port = port_base;   sh[j]->unique_id = port_base;   sh[j]->n_io_port = REGION_SIZE;   sh[j]->dma_channel = dma_channel;   sh[j]->irq = irq;   sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size);   sh[j]->this_id = (ushort) info.host_addr[3];   sh[j]->can_queue = (ushort) ntohs(info.queue_size);   sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;   sh[j]->select_queue_depths = select_queue_depths;   /* Register the I/O space that we use */   request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name);   memset(HD(j), 0, sizeof(struct hostdata));   HD(j)->subversion = subversion;   HD(j)->protocol_rev = protocol_rev;   HD(j)->board_number = j;   if (HD(j)->subversion == ESA)      sh[j]->unchecked_isa_dma = FALSE;   else {      sh[j]->wish_block = TRUE;      sh[j]->unchecked_isa_dma = TRUE;      disable_dma(dma_channel);      clear_dma_ff(dma_channel);      set_dma_mode(dma_channel, DMA_MODE_CASCADE);      enable_dma(dma_channel);      }   strcpy(BN(j), name);   /* DPT PM2012 does not allow to detect sg_tablesize correctly */   if (sh[j]->sg_tablesize > MAX_SGLIST || sh[j]->sg_tablesize < 2) {      printk("%s: detect, wrong n. of SG lists %d, fixed.\n",             BN(j), sh[j]->sg_tablesize);      sh[j]->sg_tablesize = MAX_SGLIST;      }   /* DPT PM2012 does not allow to detect can_queue correctly */   if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue  < 2) {      printk("%s: detect, wrong n. of mbox %d, fixed.\n",             BN(j), sh[j]->can_queue);      sh[j]->can_queue = MAX_MAILBOXES;      }   if (protocol_rev != 'A') {      if (info.max_chan > 0 && info.max_chan < MAX_CHANNEL)         sh[j]->max_channel = info.max_chan;      if (info.max_id > 7 && info.max_id < MAX_TARGET)         sh[j]->max_id = info.max_id + 1;      if (info.large_sg && sh[j]->sg_tablesize == MAX_SGLIST)         sh[j]->sg_tablesize = MAX_LARGE_SGLIST;      }   if (protocol_rev == 'C') {      if (info.max_lun > 7 && info.max_lun < MAX_LUN)         sh[j]->max_lun = info.max_lun + 1;      }   if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST");   else                       sprintf(dma_name, "DMA %u", dma_channel);   for (i = 0; i < sh[j]->can_queue; i++)      if (! ((&HD(j)->cp[i])->sglist = kmalloc(            sh[j]->sg_tablesize * sizeof(struct sg_list),            (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {         printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);         eata2x_release(sh[j]);         return FALSE;         }   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)       max_queue_depth = MAX_TAGGED_CMD_PER_LUN;   if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;   if (tagged_comm) {      if      (tag_mode == TAG_SIMPLE)  tag_type = '1';      else if (tag_mode == TAG_HEAD)    tag_type = '2';      else if (tag_mode == TAG_ORDERED) tag_type = '3';      else                              tag_type = 'y';      }   else                                 tag_type = 'n';#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)   sh[j]->hostt->use_new_eh_code = use_new_eh_code;#else   use_new_eh_code = FALSE;#endif   if (j == 0) {      printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");      printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c, rs:%c, et:%c.\n",             driver_name, tag_type, YESNO(linked_comm), max_queue_depth,             YESNO(use_new_eh_code), YESNO(rev_scan), YESNO(ext_tran));      }   printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n",          BN(j), HD(j)->protocol_rev, bus_type, (unsigned long)sh[j]->io_port,          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue);   if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)      printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",             BN(j), sh[j]->max_id, sh[j]->max_lun);   for (i = 0; i <= sh[j]->max_channel; i++)      printk("%s: SCSI channel %u enabled, host target ID %d.\n",             BN(j), i, info.host_addr[3 - i]);#if defined(DEBUG_DETECT)   printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\          "sec. %u, infol %ld, cpl %ld spl %ld.\n", name, info.version,          info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync,          info.second, DEV2H(info.data_len), DEV2H(info.cp_len),          DEV2H(info.sp_len));   if (protocol_rev == 'B' || protocol_rev == 'C')      printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, "\             "large_sg %u, res1 %u.\n", name, info.isaena, info.forcaddr,             info.max_id, info.max_chan, info.large_sg, info.res1);   if (protocol_rev == 'C')      printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\             "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest,             info.pci, info.eisa, info.raidnum);#endif   return TRUE;}__initfunc (void eata2x_setup(char *str, int *ints)) {   int i, argc = ints[0];   char *cur = str, *pc;   if (argc > 0) {      if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];      io_port[i] = 0;      setup_done = TRUE;      }   while (cur && (pc = strchr(cur, ':'))) {      int val = 0, c = *++pc;      if (c == 'n' || c == 'N') val = FALSE;

⌨️ 快捷键说明

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