aha1542.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,833 行 · 第 1/4 页
C
1,833 行
}; aha1542_out(base_io, inquiry_cmd, 1); aha1542_in(base_io, inquiry_result, 4); WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); while (0) {fail: printk(KERN_ERR "aha1542_detect: query card type\n"); } aha1542_intr_reset(base_io); *transl = BIOS_TRANSLATION_6432; /* Default case */ /* For an AHA1740 series board, we ignore the board since there is a hardware bug which can lead to wrong blocks being returned if the board is operating in the 1542 emulation mode. Since there is an extended mode driver, we simply ignore the board and let the 1740 driver pick it up. */ if (inquiry_result[0] == 0x43) { printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n"); return 1; }; /* Always call this - boards that do not support extended bios translation will ignore the command, and we will set the proper default */ *transl = aha1542_mbenable(base_io); return 0;}#ifndef MODULEstatic char *setup_str[MAXBOARDS] __initdata;static int setup_idx = 0;void __init aha1542_setup(char *str, int *ints){ const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n"; int setup_portbase; if (setup_idx >= MAXBOARDS) { printk(KERN_ERR "aha1542: aha1542_setup called too many times! Bad LILO params ?\n"); printk(KERN_ERR " Entryline 1: %s\n", setup_str[0]); printk(KERN_ERR " Entryline 2: %s\n", setup_str[1]); printk(KERN_ERR " This line: %s\n", str); return; } if (ints[0] < 1 || ints[0] > 4) { printk(KERN_ERR "aha1542: %s\n", str); printk(ahausage); printk(KERN_ERR "aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n"); } setup_called[setup_idx] = ints[0]; setup_str[setup_idx] = str; setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */ setup_buson[setup_idx] = ints[0] >= 2 ? ints[2] : 7; setup_busoff[setup_idx] = ints[0] >= 3 ? ints[3] : 5; if (ints[0] >= 4) { int atbt = -1; switch (ints[4]) { case 5: atbt = 0x00; break; case 6: atbt = 0x04; break; case 7: atbt = 0x01; break; case 8: atbt = 0x02; break; case 10: atbt = 0x03; break; default: printk(KERN_ERR "aha1542: %s\n", str); printk(ahausage); printk(KERN_ERR "aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n"); break; } setup_dmaspeed[setup_idx] = atbt; } if (setup_portbase != 0) bases[setup_idx] = setup_portbase; ++setup_idx;}static int __init do_setup(char *str){ int ints[5]; int count=setup_idx; get_options(str, sizeof(ints)/sizeof(int), ints); aha1542_setup(str,ints); return count<setup_idx;}__setup("aha1542=",do_setup);#endif/* return non-zero on detection */static int __init aha1542_detect(Scsi_Host_Template * tpnt){ unsigned char dma_chan; unsigned char irq_level; unsigned char scsi_id; unsigned long flags; unsigned int base_io; int trans; struct Scsi_Host *shpnt = NULL; int count = 0; int indx; DEB(printk("aha1542_detect: \n")); tpnt->proc_name = "aha1542";#ifdef MODULE bases[0] = aha1542[0]; setup_buson[0] = aha1542[1]; setup_busoff[0] = aha1542[2]; { int atbt = -1; switch (aha1542[3]) { case 5: atbt = 0x00; break; case 6: atbt = 0x04; break; case 7: atbt = 0x01; break; case 8: atbt = 0x02; break; case 10: atbt = 0x03; break; }; setup_dmaspeed[0] = atbt; }#endif /* * Find MicroChannel cards (AHA1640) */#ifdef CONFIG_MCA_LEGACY if(MCA_bus) { int slot = 0; int pos = 0; for (indx = 0; (slot != MCA_NOTFOUND) && (indx < sizeof(bases)/sizeof(bases[0])); indx++) { if (bases[indx]) continue; /* Detect only AHA-1640 cards -- MCA ID 0F1F */ slot = mca_find_unused_adapter(0x0f1f, slot); if (slot == MCA_NOTFOUND) break; /* Found one */ pos = mca_read_stored_pos(slot, 3); /* Decode address */ if (pos & 0x80) { if (pos & 0x02) { if (pos & 0x01) bases[indx] = 0x334; else bases[indx] = 0x234; } else { if (pos & 0x01) bases[indx] = 0x134; } } else { if (pos & 0x02) { if (pos & 0x01) bases[indx] = 0x330; else bases[indx] = 0x230; } else { if (pos & 0x01) bases[indx] = 0x130; } } /* No need to decode IRQ and Arb level -- those are * read off the card later. */ printk(KERN_INFO "Found an AHA-1640 in MCA slot %d, I/O 0x%04x\n", slot, bases[indx]); mca_set_adapter_name(slot, "Adapter AHA-1640"); mca_set_adapter_procfn(slot, NULL, NULL); mca_mark_as_used(slot); /* Go on */ slot++; } }#endif /* * Hunt for ISA Plug'n'Pray Adaptecs (AHA1535) */ if(isapnp) { struct pnp_dev *pdev = NULL; for(indx = 0; indx <sizeof(bases)/sizeof(bases[0]);indx++) { if(bases[indx]) continue; pdev = pnp_find_dev(NULL, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1542), pdev); if(pdev==NULL) break; /* * Activate the PnP card */ if(pnp_device_attach(pdev)<0) continue; if(pnp_activate_dev(pdev)<0) { pnp_device_detach(pdev); continue; } if(!pnp_port_valid(pdev, 0)) { pnp_device_detach(pdev); continue; } bases[indx] = pnp_port_start(pdev, 0); /* The card can be queried for its DMA, we have the DMA set up that is enough */ printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]); } } for (indx = 0; indx < sizeof(bases) / sizeof(bases[0]); indx++) if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) { shpnt = scsi_register(tpnt, sizeof(struct aha1542_hostdata)); if(shpnt==NULL) { release_region(bases[indx], 4); continue; } /* For now we do this - until kmalloc is more intelligent we are resigned to stupid hacks like this */ if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) { printk(KERN_ERR "Invalid address for shpnt with 1542.\n"); goto unregister; } if (!aha1542_test_port(bases[indx], shpnt)) goto unregister; base_io = bases[indx]; /* Set the Bus on/off-times as not to ruin floppy performance */ { unchar oncmd[] = {CMD_BUSON_TIME, 7}; unchar offcmd[] = {CMD_BUSOFF_TIME, 5}; if (setup_called[indx]) { oncmd[1] = setup_buson[indx]; offcmd[1] = setup_busoff[indx]; } aha1542_intr_reset(base_io); aha1542_out(base_io, oncmd, 2); WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); aha1542_intr_reset(base_io); aha1542_out(base_io, offcmd, 2); WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); if (setup_dmaspeed[indx] >= 0) { unchar dmacmd[] = {CMD_DMASPEED, 0}; dmacmd[1] = setup_dmaspeed[indx]; aha1542_intr_reset(base_io); aha1542_out(base_io, dmacmd, 2); WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); } while (0) {fail: printk(KERN_ERR "aha1542_detect: setting bus on/off-time failed\n"); } aha1542_intr_reset(base_io); } if (aha1542_query(base_io, &trans)) goto unregister; if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1) goto unregister; printk(KERN_INFO "Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level); if (dma_chan != 0xFF) printk(", DMA priority %d", dma_chan); printk("\n"); DEB(aha1542_stat()); setup_mailboxes(base_io, shpnt); DEB(aha1542_stat()); DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level)); spin_lock_irqsave(&aha1542_lock, flags); if (request_irq(irq_level, do_aha1542_intr_handle, 0, "aha1542", NULL)) { printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n"); spin_unlock_irqrestore(&aha1542_lock, flags); goto unregister; } if (dma_chan != 0xFF) { if (request_dma(dma_chan, "aha1542")) { printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n"); free_irq(irq_level, NULL); spin_unlock_irqrestore(&aha1542_lock, flags); goto unregister; } if (dma_chan == 0 || dma_chan >= 5) { set_dma_mode(dma_chan, DMA_MODE_CASCADE); enable_dma(dma_chan); } } aha_host[irq_level - 9] = shpnt; shpnt->this_id = scsi_id; shpnt->unique_id = base_io; shpnt->io_port = base_io; shpnt->n_io_port = 4; /* Number of bytes of I/O space used */ shpnt->dma_channel = dma_chan; shpnt->irq = irq_level; HOSTDATA(shpnt)->bios_translation = trans; if (trans == BIOS_TRANSLATION_25563) printk(KERN_INFO "aha1542.c: Using extended bios translation\n"); HOSTDATA(shpnt)->aha1542_last_mbi_used = (2 * AHA1542_MAILBOXES - 1); HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1); memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint)); spin_unlock_irqrestore(&aha1542_lock, flags);#if 0 DEB(printk(" *** READ CAPACITY ***\n")); { unchar buf[8]; static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int i; for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87; for (i = 0; i < 2; ++i) if (!aha1542_command(i, cmd, buf, sizeof(buf))) { printk(KERN_DEBUG "aha_detect: LU %d sector_size %d device_size %d\n", i, xscsi2int(buf + 4), xscsi2int(buf)); } } DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n")); for (i = 0; i < 4; ++i) { unsigned char cmd[10]; static buffer[512]; cmd[0] = READ_10; cmd[1] = 0; xany2scsi(cmd + 2, i); cmd[6] = 0; cmd[7] = 0; cmd[8] = 1; cmd[9] = 0; aha1542_command(0, cmd, buffer, 512); }#endif count++; continue;unregister: release_region(bases[indx], 4); scsi_unregister(shpnt); continue; }; return count;}static int aha1542_release(struct Scsi_Host *shost){ if (shost->irq) free_irq(shost->irq, NULL); if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); return 0;}static int aha1542_restart(struct Scsi_Host *shost){ int i; int count = 0;#if 0 unchar ahacmd = CMD_START_SCSI;#endif for (i = 0; i < AHA1542_MAILBOXES; i++) if (HOSTDATA(shost)->SCint[i] && !(HOSTDATA(shost)->SCint[i]->device->soft_reset)) {#if 0 HOSTDATA(shost)->mb[i].status = 1; /* Indicate ready to restart... */#endif count++; } printk(KERN_DEBUG "Potential to restart %d stalled commands...\n", count);#if 0 /* start scsi command */ if (count) aha1542_out(shost->io_port, &ahacmd, 1);#endif return 0;}static int aha1542_abort(Scsi_Cmnd * SCpnt){ /* * The abort command does not leave the device in a clean state where * it is available to be used again. Until this gets worked out, we * will leave it commented out. */ printk(KERN_ERR "aha1542.c: Unable to abort command for target %d\n", SCpnt->device->id); return FAILED;}/* * This is a device reset. This is handled by sending a special command * to the device. */static int aha1542_dev_reset(Scsi_Cmnd * SCpnt){ unsigned long flags; struct mailbox *mb; unchar target = SCpnt->device->id; unchar lun = SCpnt->device->lun; int mbo; struct ccb *ccb; unchar ahacmd = CMD_START_SCSI;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?