📄 eata_dma.c
字号:
} size = sizeof(hostdata) + ((sizeof(struct eata_ccb) + sizeof(long)) * ntohs(gc->queuesiz)); DBG(DBG_REGISTER, printk("scsi_register size: %ld\n", size)); sh = scsi_register(tpnt, size); if(sh != NULL) { hd = SD(sh); memset(hd->reads, 0, sizeof(u32) * 26); sh->select_queue_depths = eata_select_queue_depths; hd->bustype = bustype; /* * If we are using a ISA board, we can't use extended SG, * because we would need excessive amounts of memory for * bounce buffers. */ if (gc->SG_64K==TRUE && ntohs(gc->SGsiz)==64 && hd->bustype!=IS_ISA){ sh->sg_tablesize = SG_SIZE_BIG; } else { sh->sg_tablesize = ntohs(gc->SGsiz); if (sh->sg_tablesize > SG_SIZE || sh->sg_tablesize == 0) { if (sh->sg_tablesize == 0) printk(KERN_WARNING "Warning: SG size had to be fixed.\n" "This might be a PM2012 with a defective Firmware" "\nContact DPT support@dpt.com for an upgrade\n"); sh->sg_tablesize = SG_SIZE; } } hd->sgsize = sh->sg_tablesize; } if(sh != NULL) { sh->can_queue = hd->queuesize = ntohs(gc->queuesiz); sh->cmd_per_lun = 0; } if(sh == NULL) { DBG(DBG_REGISTER, printk(KERN_NOTICE "eata_dma: couldn't register HBA" " at%x \n", base)); scsi_unregister(sh); if (gc->DMA_valid) free_dma(dma_channel); reg_IRQ[gc->IRQ]--; if (reg_IRQ[gc->IRQ] == 0) free_irq(gc->IRQ, NULL); if (gc->IRQ_TR == FALSE) reg_IRQL[gc->IRQ] = FALSE; return (FALSE); } hd->broken_INQUIRY = (bugs & BROKEN_INQUIRY); if(hd->broken_INQUIRY == TRUE) { strcpy(hd->vendor, "DPT"); strcpy(hd->name, "??????????"); strcpy(hd->revision, "???.?"); hd->firmware_revision = 0; } else { strncpy(hd->vendor, &buff[8], 8); hd->vendor[8] = 0; strncpy(hd->name, &buff[16], 17); hd->name[17] = 0; hd->revision[0] = buff[32]; hd->revision[1] = buff[33]; hd->revision[2] = buff[34]; hd->revision[3] = '.'; hd->revision[4] = buff[35]; hd->revision[5] = 0; hd->firmware_revision = (buff[32] << 24) + (buff[33] << 16) + (buff[34] << 8) + buff[35]; } if (hd->firmware_revision >= (('0'<<24) + ('7'<<16) + ('G'<< 8) + '0')) hd->immediate_support = 1; else hd->immediate_support = 0; switch (ntohl(gc->len)) { case 0x1c: hd->EATA_revision = 'a'; break; case 0x1e: hd->EATA_revision = 'b'; break; case 0x22: hd->EATA_revision = 'c'; break; case 0x24: hd->EATA_revision = 'z'; default: hd->EATA_revision = '?'; } if(ntohl(gc->len) >= 0x22) { sh->max_id = gc->MAX_ID + 1; sh->max_lun = gc->MAX_LUN + 1; } else { sh->max_id = 8; sh->max_lun = 8; } hd->HBA_number = sh->host_no; hd->channel = gc->MAX_CHAN; sh->max_channel = gc->MAX_CHAN; sh->unique_id = base; sh->base = base; sh->io_port = base; sh->n_io_port = 9; sh->irq = gc->IRQ; sh->dma_channel = dma_channel; /* FIXME: * SCSI midlevel code should support different HBA ids on every channel */ sh->this_id = gc->scsi_id[3]; if (gc->SECOND) hd->primary = FALSE; else hd->primary = TRUE; if (hd->bustype != IS_ISA) { sh->unchecked_isa_dma = FALSE; } else { sh->unchecked_isa_dma = TRUE; /* We're doing ISA DMA */ } for(x = 0; x <= 11; x++){ /* Initialize min. latency */ hd->writes_lat[x][1] = 0xffffffff; hd->reads_lat[x][1] = 0xffffffff; } hd->all_lat[1] = 0xffffffff; hd->next = NULL; /* build a linked list of all HBAs */ hd->prev = last_HBA; if(hd->prev != NULL) SD(hd->prev)->next = sh; last_HBA = sh; if (first_HBA == NULL) first_HBA = sh; registered_HBAs++; return (TRUE);}void find_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt){ u32 base; int i; #if CHECKPAL u8 pal1, pal2, pal3;#endif for (i = 0; i < MAXEISA; i++) { if (EISAbases[i] == TRUE) { /* Still a possibility ? */ base = 0x1c88 + (i * 0x1000);#if CHECKPAL pal1 = inb((u16)base - 8); pal2 = inb((u16)base - 7); pal3 = inb((u16)base - 6); if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && (pal3 == NEC_ID3))|| ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && (pal3 == ATT_ID3))){ DBG(DBG_PROBE, printk("EISA EATA id tags found: %x %x %x \n", (int)pal1, (int)pal2, (int)pal3));#endif if (get_conf_PIO(base, buf) == TRUE) { if (buf->IRQ) { DBG(DBG_EISA, printk("Registering EISA HBA\n")); register_HBA(base, buf, tpnt, IS_EISA); } else printk("eata_dma: No valid IRQ. HBA removed from list\n"); }#if CHECK_BLINK else { if (check_blink_state(base)) printk("HBA is in BLINK state. Consult your HBAs " "Manual to correct this.\n"); } #endif /* Nothing found here so we take it from the list */ EISAbases[i] = 0; #if CHECKPAL } #endif } } return; }void find_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt){ int i; for (i = 0; i < MAXISA; i++) { if (ISAbases[i]) { if (get_conf_PIO(ISAbases[i],buf) == TRUE){ DBG(DBG_ISA, printk("Registering ISA HBA\n")); register_HBA(ISAbases[i], buf, tpnt, IS_ISA); } #if CHECK_BLINK else { if (check_blink_state(ISAbases[i])) printk("HBA is in BLINK state. Consult your HBAs " "Manual to correct this.\n"); }#endif ISAbases[i] = 0; } } return;}void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt){#ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");#else struct pci_dev *dev = NULL; u32 base, x; u8 pal1, pal2, pal3; while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { DBG(DBG_PROBE && DBG_PCI, printk("eata_dma: find_PCI, HBA at %s\n", dev->name)); if (pci_enable_device(dev)) continue; pci_set_master(dev); base = pci_resource_flags(dev, 0); if (base & IORESOURCE_MEM) { printk("eata_dma: invalid base address of device %s\n", dev->name); continue; } base = pci_resource_start(dev, 0); /* EISA tag there ? */ pal1 = inb(base); pal2 = inb(base + 1); pal3 = inb(base + 2); if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && (pal3 == NEC_ID3)) || ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && (pal3 == ATT_ID3))) base += 0x08; else base += 0x10; /* Now, THIS is the real address */ if (base != 0x1f8) { /* We didn't find it in the primary search */ if (get_conf_PIO(base, buf) == TRUE) { /* OK. We made it till here, so we can go now * and register it. We only have to check and * eventually remove it from the EISA and ISA list */ DBG(DBG_PCI, printk("Registering PCI HBA\n")); register_HBA(base, buf, tpnt, IS_PCI); if (base < 0x1000) { for (x = 0; x < MAXISA; ++x) { if (ISAbases[x] == base) { ISAbases[x] = 0; break; } } } else if ((base & 0x0fff) == 0x0c88) EISAbases[(base >> 12) & 0x0f] = 0; } #if CHECK_BLINK else if (check_blink_state(base) == TRUE) { printk("eata_dma: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n"); }#endif } }#endif /* #ifndef CONFIG_PCI */}int eata_detect(Scsi_Host_Template * tpnt){ struct Scsi_Host *HBA_ptr; struct get_conf gc; int i; DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG, printk("Using lots of delays to let you read the debugging output\n")); tpnt->proc_name = "eata_dma"; status = kmalloc(512, GFP_ATOMIC | GFP_DMA); dma_scratch = kmalloc(1024, GFP_ATOMIC | GFP_DMA); if(status == NULL || dma_scratch == NULL) { printk("eata_dma: can't allocate enough memory to probe for hosts !\n"); if(status) kfree(status); if(dma_scratch) kfree(dma_scratch); return(0); } dma_scratch += 4; find_PCI(&gc, tpnt); find_EISA(&gc, tpnt); find_ISA(&gc, tpnt); for (i = 0; i <= MAXIRQ; i++) { /* Now that we know what we have, we */ if (reg_IRQ[i] >= 1){ /* exchange the interrupt handler which */ free_irq(i, NULL); /* we used for probing with the real one */ request_irq(i, (void *)(do_eata_int_handler), SA_INTERRUPT|SA_SHIRQ, "eata_dma", NULL); } } HBA_ptr = first_HBA; if (registered_HBAs != 0) { printk("EATA (Extended Attachment) driver version: %d.%d%s" "\ndeveloped in co-operation with DPT\n" "(c) 1993-96 Michael Neuffer, mike@i-Connect.Net\n", VER_MAJOR, VER_MINOR, VER_SUB); printk("Registered HBAs:"); printk("\nHBA no. Boardtype Revis EATA Bus BaseIO IRQ" " DMA Ch ID Pr QS S/G IS\n"); for (i = 1; i <= registered_HBAs; i++) { printk("scsi%-2d: %.12s v%s 2.0%c %s %#.4x %2d", HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ", (u32) HBA_ptr->base, HBA_ptr->irq); if(HBA_ptr->dma_channel != BUSMASTER) printk(" %2x ", HBA_ptr->dma_channel); else printk(" %s", "BMST"); printk(" %d %d %c %3d %3d %c\n", SD(HBA_ptr)->channel+1, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', HBA_ptr->can_queue, HBA_ptr->sg_tablesize, (SD(HBA_ptr)->immediate_support == TRUE)?'Y':'N'); HBA_ptr = SD(HBA_ptr)->next; } } else { kfree((void *)status); } kfree((void *)dma_scratch - 4); DBG(DPT_DEBUG, DELAY(12)); return(registered_HBAs);}/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = EATA_DMA;#include "scsi_module.c"/* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -