📄 icside.c
字号:
}/* * The following is a sick duplication from ide-dma.c ;( * * This should be defined in one place only. */struct drive_list_entry { char * id_model; char * id_firmware;};static struct drive_list_entry drive_whitelist [] = { { "Micropolis 2112A", "ALL" }, { "CONNER CTMA 4000", "ALL" }, { "CONNER CTT8000-A", "ALL" }, { "ST34342A", "ALL" }, { NULL, 0 }};static struct drive_list_entry drive_blacklist [] = { { "WDC AC11000H", "ALL" }, { "WDC AC22100H", "ALL" }, { "WDC AC32500H", "ALL" }, { "WDC AC33100H", "ALL" }, { "WDC AC31600H", "ALL" }, { "WDC AC32100H", "24.09P07" }, { "WDC AC23200L", "21.10N21" }, { "Compaq CRD-8241B", "ALL" }, { "CRD-8400B", "ALL" }, { "CRD-8480B", "ALL" }, { "CRD-8480C", "ALL" }, { "CRD-8482B", "ALL" }, { "CRD-84", "ALL" }, { "SanDisk SDP3B", "ALL" }, { "SanDisk SDP3B-64", "ALL" }, { "SANYO CD-ROM CRD", "ALL" }, { "HITACHI CDR-8", "ALL" }, { "HITACHI CDR-8335", "ALL" }, { "HITACHI CDR-8435", "ALL" }, { "Toshiba CD-ROM XM-6202B", "ALL" }, { "CD-532E-A", "ALL" }, { "E-IDE CD-ROM CR-840", "ALL" }, { "CD-ROM Drive/F5A", "ALL" }, { "RICOH CD-R/RW MP7083A", "ALL" }, { "WPI CDD-820", "ALL" }, { "SAMSUNG CD-ROM SC-148C", "ALL" }, { "SAMSUNG CD-ROM SC-148F", "ALL" }, { "SAMSUNG CD-ROM SC", "ALL" }, { "SanDisk SDP3B-64", "ALL" }, { "SAMSUNG CD-ROM SN-124", "ALL" }, { "PLEXTOR CD-R PX-W8432T", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, { NULL, 0 }};static intin_drive_list(struct hd_driveid *id, struct drive_list_entry *drive_table){ for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && ((!strstr(drive_table->id_firmware, id->fw_rev)) || (!strcmp(drive_table->id_firmware, "ALL")))) return 1; return 0;}static int icside_check_drive_lists(ide_drive_t *drive, ide_dma_action_t func){ struct hd_driveid *id = drive->id; int found; if (func == ide_dma_good_drive) { found = in_drive_list(id, drive_whitelist); } else { found = in_drive_list(id, drive_blacklist); if (found) printk("%s: Disabling DMA for %s (blacklisted)\n", drive->name, id->model); } return found;}static int icside_dma_check(ide_drive_t *drive){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); int autodma = hwif->autodma; int xfer_mode = XFER_PIO_2; int func = ide_dma_off_quietly; if (!id || !(id->capability & 1) || !autodma) goto out; /* * Consult the list of known "bad" drives */ if (icside_check_drive_lists(drive, ide_dma_bad_drive)) goto out; /* * Enable DMA on any drive that has multiword DMA */ if (id->field_valid & 2) { if (id->dma_mword & 4) { xfer_mode = XFER_MW_DMA_2; func = ide_dma_on; } else if (id->dma_mword & 2) { xfer_mode = XFER_MW_DMA_1; func = ide_dma_on; } else if (id->dma_mword & 1) { xfer_mode = XFER_MW_DMA_0; func = ide_dma_on; } goto out; } /* * Consult the list of known "good" drives */ if (icside_check_drive_lists(drive, ide_dma_good_drive)) { if (id->eide_dma_time > 150) goto out; xfer_mode = XFER_MW_DMA_1; func = ide_dma_on; }out: func = icside_speedproc(drive, xfer_mode); return icside_dmaproc(func, drive);}static int icside_dma_verbose(ide_drive_t *drive){ printk(", %s (peak %dMB/s)", ide_xfer_verbose(drive->current_speed), 2000 / drive->drive_data); return 1;}static int icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct icside_state *state = hwif->hw.priv; int count, dma_mode = DMA_MODE_READ; switch (func) { case ide_dma_off: printk("%s: DMA disabled\n", drive->name); /*FALLTHROUGH*/ case ide_dma_off_quietly: case ide_dma_on: drive->using_dma = (func == ide_dma_on); return 0; case ide_dma_check: return icside_dma_check(drive); case ide_dma_write: dma_mode = DMA_MODE_WRITE; case ide_dma_read: count = icside_build_dmatable(drive, dma_mode); if (!count) return 1; disable_dma(hwif->hw.dma); /* * Ensure that we have the right interrupt routed. */ icside_maskproc(drive, 0); /* * Route the DMA signals to to the correct interface. */ outb(hwif->select_data, hwif->config_data); /* * Select the correct timing for this drive. */ set_dma_speed(hwif->hw.dma, drive->drive_data); set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); set_dma_mode(hwif->hw.dma, dma_mode); drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); OUT_BYTE(dma_mode == DMA_MODE_READ ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); /*FALLTHROUGH*/ case ide_dma_begin: enable_dma(hwif->hw.dma); return 0; case ide_dma_end: drive->waiting_for_dma = 0; disable_dma(hwif->hw.dma); icside_destroy_dmatable(hwif); return get_dma_residue(hwif->hw.dma) != 0; case ide_dma_test_irq: return inb(state->irq_port + (hwif->channel ? ICS_ARCIN_V6_INTRSTAT_2 : ICS_ARCIN_V6_INTRSTAT_1)) & 1; case ide_dma_bad_drive: case ide_dma_good_drive: return icside_check_drive_lists(drive, func); case ide_dma_verbose: return icside_dma_verbose(drive); case ide_dma_lostirq: case ide_dma_timeout: default: printk("icside_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); } return 1;}static int icside_setup_dma(ide_hwif_t *hwif, int autodma){ hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, GFP_KERNEL); if (!hwif->sg_table) goto failed; hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; hwif->speedproc = icside_speedproc; hwif->dmaproc = icside_dmaproc; hwif->autodma = autodma; return 1;failed: printk(" -- ERROR, unable to allocate DMA table\n"); return 0;}int ide_release_dma(ide_hwif_t *hwif){ if (hwif->sg_table) { kfree(hwif->sg_table); hwif->sg_table = NULL; } return 1;}#endifstatic ide_hwif_t *icside_find_hwif(unsigned long dataport){ ide_hwif_t *hwif; int index; for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; if (hwif->io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) goto found; } for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; if (!hwif->io_ports[IDE_DATA_OFFSET]) goto found; } hwif = NULL;found: return hwif;}static ide_hwif_t *icside_setup(unsigned long base, struct cardinfo *info, int irq){ unsigned long port = base + info->dataoffset; ide_hwif_t *hwif; hwif = icside_find_hwif(base); if (hwif) { int i; memset(&hwif->hw, 0, sizeof(hw_regs_t)); for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { hwif->hw.io_ports[i] = (ide_ioreg_t)port; hwif->io_ports[i] = (ide_ioreg_t)port; port += 1 << info->stepping; } hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; hwif->hw.irq = irq; hwif->irq = irq; hwif->hw.dma = NO_DMA; hwif->noprobe = 0; hwif->chipset = ide_acorn; } return hwif;}static int __init icside_register_v5(struct expansion_card *ec, int autodma){ unsigned long slot_port; ide_hwif_t *hwif; slot_port = ecard_address(ec, ECARD_MEMC, 0); ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); ec->irqmask = 1; ec->irq_data = (void *)slot_port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; /* * Be on the safe side - disable interrupts */ inb(slot_port + ICS_ARCIN_V5_INTROFFSET); hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); return hwif ? 0 : -ENODEV;}static int __init icside_register_v6(struct expansion_card *ec, int autodma){ unsigned long slot_port, port; struct icside_state *state; ide_hwif_t *hwif, *mate; unsigned int sel = 0; slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); port = ecard_address(ec, ECARD_EASI, ECARD_FAST); if (port == 0) port = slot_port; else sel = 1 << 5; outb(sel, slot_port); /* * Be on the safe side - disable interrupts */ inb(port + ICS_ARCIN_V6_INTROFFSET_1); inb(port + ICS_ARCIN_V6_INTROFFSET_2); /* * Find and register the interfaces. */ hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); if (!hwif || !mate) return -ENODEV; state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); if (!state) return -ENOMEM; state->channel = 0; state->enabled = 0; state->irq_port = port; ec->irq_data = state; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; hwif->maskproc = icside_maskproc; hwif->channel = 0; hwif->hw.priv = state; hwif->mate = mate; hwif->serialized = 1; hwif->config_data = slot_port; hwif->select_data = sel; hwif->hw.dma = ec->dma; mate->maskproc = icside_maskproc; mate->channel = 1; mate->hw.priv = state; mate->mate = hwif; mate->serialized = 1; mate->config_data = slot_port; mate->select_data = sel | 1; mate->hw.dma = ec->dma;#ifdef CONFIG_BLK_DEV_IDEDMA_ICS if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { icside_setup_dma(hwif, autodma); icside_setup_dma(mate, autodma); }#endif return 0;}int __init icside_init(void){ int autodma = 0;#ifdef CONFIG_IDEDMA_ICS_AUTO autodma = 1;#endif ecard_startfind (); do { struct expansion_card *ec; int result; ec = ecard_find(0, icside_cids); if (ec == NULL) break; ecard_claim(ec); switch (icside_identifyif(ec)) { case ics_if_arcin_v5: result = icside_register_v5(ec, autodma); break; case ics_if_arcin_v6: result = icside_register_v6(ec, autodma); break; default: result = -1; break; } if (result) ecard_release(ec); } while (1); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -