📄 eata_dma.c
字号:
device->queue_depth = 2; }#else /* First we do a sample run go find out what we have */ for(device = devicelist; device != NULL; device = device->next) { if (device->host == host) { devcount++; switch(device->type) { case TYPE_DISK: case TYPE_MOD: factor += TYPE_DISK_QUEUE; break; case TYPE_TAPE: factor += TYPE_TAPE_QUEUE; break; case TYPE_WORM: case TYPE_ROM: factor += TYPE_ROM_QUEUE; break; case TYPE_PROCESSOR: case TYPE_SCANNER: default: factor += TYPE_OTHER_QUEUE; break; } } } DBG(DBG_REGISTER, printk(KERN_DEBUG "scsi%d: needed queueslots %d\n", host->host_no, factor)); if(factor == 0) /* We don't want to get a DIV BY ZERO error */ factor = 1; factor = (SD(host)->queuesize * 10) / factor; DBG(DBG_REGISTER, printk(KERN_DEBUG "scsi%d: using factor %dE-1\n", host->host_no, factor)); /* Now that have the factor we can set the individual queuesizes */ for(device = devicelist; device != NULL; device = device->next) { if(device->host == host) { if(SD(device->host)->bustype != IS_ISA){ switch(device->type) { case TYPE_DISK: case TYPE_MOD: device->queue_depth = (TYPE_DISK_QUEUE * factor) / 10; break; case TYPE_TAPE: device->queue_depth = (TYPE_TAPE_QUEUE * factor) / 10; break; case TYPE_WORM: case TYPE_ROM: device->queue_depth = (TYPE_ROM_QUEUE * factor) / 10; break; case TYPE_PROCESSOR: case TYPE_SCANNER: default: device->queue_depth = (TYPE_OTHER_QUEUE * factor) / 10; break; } } else /* ISA forces us to limit the queue depth because of the * bounce buffer memory overhead. I know this is cruel */ device->queue_depth = 2; /* * It showed that we need to set an upper limit of commands * we can allow to queue for a single device on the bus. * If we get above that limit, the broken midlevel SCSI code * will produce bogus timeouts and aborts en masse. :-( */ if(device->queue_depth > UPPER_DEVICE_QUEUE_LIMIT) device->queue_depth = UPPER_DEVICE_QUEUE_LIMIT; if(device->queue_depth == 0) device->queue_depth = 1; printk(KERN_INFO "scsi%d: queue depth for target %d on channel %d " "set to %d\n", host->host_no, device->id, device->channel, device->queue_depth); } }#endif}#if CHECK_BLINKint check_blink_state(long base){ ushort loops = 10; u32 blinkindicator; u32 state = 0x12345678; u32 oldstate = 0; blinkindicator = htonl(0x54504442); while ((loops--) && (state != oldstate)) { oldstate = state; state = inl((uint) base + 1); } DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n", (state == oldstate) && (state == blinkindicator))); if ((state == oldstate) && (state == blinkindicator)) return(TRUE); else return (FALSE);}#endifchar * get_board_data(u32 base, u32 irq, u32 id){ struct eata_ccb *cp; struct eata_sp *sp; static char *buff; ulong i; cp = (struct eata_ccb *) scsi_init_malloc(sizeof(struct eata_ccb), GFP_ATOMIC | GFP_DMA); sp = (struct eata_sp *) scsi_init_malloc(sizeof(struct eata_sp), GFP_ATOMIC | GFP_DMA); buff = dma_scratch; memset(cp, 0, sizeof(struct eata_ccb)); memset(sp, 0, sizeof(struct eata_sp)); memset(buff, 0, 256); cp->DataIn = TRUE; cp->Interpret = TRUE; /* Interpret command */ cp->cp_dispri = TRUE; cp->cp_identify = TRUE; cp->cp_datalen = htonl(56); cp->cp_dataDMA = htonl(virt_to_bus(buff)); cp->cp_statDMA = htonl(virt_to_bus(sp)); cp->cp_viraddr = cp; cp->cp_id = id; cp->cp_lun = 0; cp->cp_cdb[0] = INQUIRY; cp->cp_cdb[1] = 0; cp->cp_cdb[2] = 0; cp->cp_cdb[3] = 0; cp->cp_cdb[4] = 56; cp->cp_cdb[5] = 0; fake_int_base = (struct eata_register *) base; fake_int_result = FALSE; fake_int_happened = FALSE; eata_send_command((u32) cp, (u32) base, EATA_CMD_DMA_SEND_CP); i = jiffies + (3 * HZ); while (fake_int_happened == FALSE && jiffies <= i) barrier(); DBG(DBG_INTR3, printk(KERN_DEBUG "fake_int_result: %#x hbastat %#x " "scsistat %#x, buff %p sp %p\n", fake_int_result, (u32) (sp->hba_stat /*& 0x7f*/), (u32) sp->scsi_stat, buff, sp)); scsi_init_free((void *)cp, sizeof(struct eata_ccb)); scsi_init_free((void *)sp, sizeof(struct eata_sp)); if ((fake_int_result & HA_SERROR) || jiffies > i){ printk(KERN_WARNING "eata_dma: trying to reset HBA at %x to clear " "possible blink state\n", base); /* hard reset the HBA */ inb((u32) (base) + HA_RSTATUS); eata_send_command(0, base, EATA_CMD_RESET); DELAY(1); return (NULL); } else return (buff);}int get_conf_PIO(u32 base, struct get_conf *buf){ ulong loop = R_LIMIT; u16 *p; if(check_region(base, 9)) return (FALSE); memset(buf, 0, sizeof(struct get_conf)); while (inb(base + HA_RSTATUS) & HA_SBUSY) if (--loop == 0) return (FALSE); fake_int_base = (struct eata_register *) base; fake_int_result = FALSE; fake_int_happened = FALSE; DBG(DBG_PIO && DBG_PROBE, printk("Issuing PIO READ CONFIG to HBA at %#x\n", base)); eata_send_command(0, base, EATA_CMD_PIO_READ_CONFIG); loop = R_LIMIT; for (p = (u16 *) buf; (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) { while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) if (--loop == 0) return (FALSE); loop = R_LIMIT; *p = inw(base + HA_RDATA); } if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ if (htonl(EATA_SIGNATURE) == buf->signature) { DBG(DBG_PIO&&DBG_PROBE, printk("EATA Controller found at %x " "EATA Level: %x\n", (uint) base, (uint) (buf->version))); while (inb(base + HA_RSTATUS) & HA_SDRQ) inw(base + HA_RDATA); return (TRUE); } } else { DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %lx\n", (long)base)); } return (FALSE);}void print_config(struct get_conf *gc){ printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d DMAS:%d\n", (u32) ntohl(gc->len), gc->version, gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support, gc->DMA_support); printk("DMAV:%d HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", gc->DMA_valid, gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND); printk("IRQ:%d IRQT:%d DMAC:%d FORCADR:%d SG_64K:%d SG_UAE:%d MID:%d " "MCH:%d MLUN:%d\n", gc->IRQ, gc->IRQ_TR, (8 - gc->DMA_channel) & 7, gc->FORCADR, gc->SG_64K, gc->SG_UAE, gc->MAX_ID, gc->MAX_CHAN, gc->MAX_LUN); printk("RIDQ:%d PCI:%d EISA:%d\n", gc->ID_qest, gc->is_PCI, gc->is_EISA); DBG(DPT_DEBUG, DELAY(14));}short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt, u8 bustype){ ulong size = 0; unchar dma_channel = 0; char *buff = 0; unchar bugs = 0; struct Scsi_Host *sh; hostdata *hd; int x; DBG(DBG_REGISTER, print_config(gc)); if (gc->DMA_support == FALSE) { printk("The EATA HBA at %#.4x does not support DMA.\n" "Please use the EATA-PIO driver.\n", base); return (FALSE); } if(gc->HAA_valid == FALSE || ntohl(gc->len) < 0x22) gc->MAX_CHAN = 0; if (reg_IRQ[gc->IRQ] == FALSE) { /* Interrupt already registered ? */ if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT, "eata_dma", NULL)){ reg_IRQ[gc->IRQ]++; if (!gc->IRQ_TR) reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ } else { printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ); return (FALSE); } } else { /* More than one HBA on this IRQ */ if (reg_IRQL[gc->IRQ] == TRUE) { printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n"); return (FALSE); } else reg_IRQ[gc->IRQ]++; } /* If DMA is supported but DMA_valid isn't set to indicate that * the channel number is given we must have pre 2.0 firmware (1.7?) * which leaves us to guess since the "newer ones" also don't set the * DMA_valid bit. */ if (gc->DMA_support && !gc->DMA_valid && gc->DMA_channel) { printk(KERN_WARNING "eata_dma: If you are using a pre 2.0 firmware " "please update it !\n" " You can get new firmware releases from ftp.dpt.com\n"); gc->DMA_channel = (base == 0x1f0 ? 3 /* DMA=5 */ : 2 /* DMA=6 */); gc->DMA_valid = TRUE; } /* if gc->DMA_valid it must be an ISA HBA and we have to register it */ dma_channel = BUSMASTER; if (gc->DMA_valid) { if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "eata_dma")) { printk(KERN_WARNING "Unable to allocate DMA channel %d for ISA HBA" " at %#.4x.\n", dma_channel, base); 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); } } if (dma_channel != BUSMASTER) { disable_dma(dma_channel); clear_dma_ff(dma_channel); set_dma_mode(dma_channel, DMA_MODE_CASCADE); enable_dma(dma_channel); } if (bustype != IS_EISA && bustype != IS_ISA) buff = get_board_data(base, gc->IRQ, gc->scsi_id[3]); if (buff == NULL) { if (bustype == IS_EISA || bustype == IS_ISA) { bugs = bugs || BROKEN_INQUIRY; } else { if (gc->DMA_support == FALSE) printk(KERN_WARNING "HBA at %#.4x doesn't support DMA. " "Sorry\n", base); else printk(KERN_WARNING "HBA at %#.4x does not react on INQUIRY. " "Sorry.\n", base); 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); } } if (gc->DMA_support == FALSE && buff != NULL) printk(KERN_WARNING "HBA %.12sat %#.4x doesn't set the DMA_support " "flag correctly.\n", &buff[16], base); request_region(base, 9, "eata_dma"); /* We already checked the * availability, so this * should not fail. */ if(ntohs(gc->queuesiz) == 0) { gc->queuesiz = ntohs(64); printk(KERN_WARNING "Warning: Queue size has to be corrected. Assuming" " 64 queueslots\n" " This might be a PM2012B with a defective Firmware\n" " Contact DPT support@dpt.com for an upgrade\n"); } 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -