static int siimage_busproc (ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); u32 stat_config = 0; unsigned long addr = siimage_selreg(hwif, 0); if (hwif->mmio) { stat_config = hwif->INL(addr); } else pci_read_config_dword(hwif->pci_dev, addr, &stat_config); switch (state) { case BUSSTATE_ON: hwif->drives[0].failures = 0; hwif->drives[1].failures = 0; break; case BUSSTATE_OFF: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; case BUSSTATE_TRISTATE: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; default: return -EINVAL; } hwif->bus_state = state; return 0; }
static void siimage_reset (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 reset = 0; unsigned long addr = siimage_selreg(hwif, 0); if (hwif->mmio) { reset = hwif->INB(addr); hwif->OUTB((reset|0x03), addr); /* FIXME:posting */ udelay(25); hwif->OUTB(reset, addr); (void) hwif->INB(addr); } else { pci_read_config_byte(hwif->pci_dev, addr, &reset); pci_write_config_byte(hwif->pci_dev, addr, reset|0x03); udelay(25); pci_write_config_byte(hwif->pci_dev, addr, reset); pci_read_config_byte(hwif->pci_dev, addr, &reset); } if (SATA_STATUS_REG) { u32 sata_stat = hwif->INL(SATA_STATUS_REG); printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", hwif->name, sata_stat, __FUNCTION__); if (!(sata_stat)) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", hwif->name, sata_stat); drive->failures++; } } }
static int sil_sata_busproc(ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); u32 stat_config = 0; unsigned long addr = siimage_selreg(hwif, 0); if (hwif->mmio) stat_config = readl((void __iomem *)addr); else pci_read_config_dword(dev, addr, &stat_config); switch (state) { case BUSSTATE_ON: hwif->drives[0].failures = 0; hwif->drives[1].failures = 0; break; case BUSSTATE_OFF: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; case BUSSTATE_TRISTATE: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; default: return -EINVAL; } hwif->bus_state = state; return 0; }
static u8 sil_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long addr = siimage_selreg(hwif, 0); u8 ata66 = sil_ioread8(dev, addr); return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; }
static int sil_test_irq(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long addr = siimage_selreg(hwif, 1); u8 val = sil_ioread8(dev, addr); return (val & 8) ? 1 : 0; }
static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) { ide_hwif_t *hwif = HWIF(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); unsigned long tfaddr = siimage_selreg(hwif, 0x02); /* cheat for now and use the docs */ switch(mode_wanted) { case 4: speedp = 0x10c1; speedt = 0x10c1; break; case 3: speedp = 0x10C3; speedt = 0x10C3; break; case 2: speedp = 0x1104; speedt = 0x1281; break; case 1: speedp = 0x2283; speedt = 0x1281; break; case 0: default: speedp = 0x328A; speedt = 0x328A; break; } if (hwif->mmio) { hwif->OUTW(speedt, addr); hwif->OUTW(speedp, tfaddr); /* Now set up IORDY */ if(mode_wanted == 3 || mode_wanted == 4) hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); else hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); } else { pci_write_config_word(hwif->pci_dev, addr, speedp); pci_write_config_word(hwif->pci_dev, tfaddr, speedt); pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); speedp &= ~0x200; /* Set IORDY for mode 3 or 4 */ if(mode_wanted == 3 || mode_wanted == 4) speedp |= 0x200; pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); } }
static unsigned int __init ata66_siimage (ide_hwif_t *hwif) { unsigned long addr = siimage_selreg(hwif, 0); if (pci_get_drvdata(hwif->pci_dev) == NULL) { u8 ata66 = 0; pci_read_config_byte(hwif->pci_dev, addr, &ata66); return (ata66 & 0x01) ? 1 : 0; } return (hwif->INB(addr) & 0x01) ? 1 : 0; }
static u8 __devinit ata66_siimage(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long addr = siimage_selreg(hwif, 0); u8 ata66 = 0; if (pci_get_drvdata(dev) == NULL) pci_read_config_byte(dev, addr, &ata66); else ata66 = hwif->INB(addr); return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; }
static void sil_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) { static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; struct pci_dev *dev = to_pci_dev(hwif->dev); ide_drive_t *pair = ide_get_pair_dev(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); unsigned long tfaddr = siimage_selreg(hwif, 0x02); unsigned long base = (unsigned long)hwif->hwif_data; const u8 pio = drive->pio_mode - XFER_PIO_0; u8 tf_pio = pio; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) : (mmio ? 0xB4 : 0x80); u8 mode = 0; u8 unit = drive->dn & 1; if (pair) { u8 pair_pio = pair->pio_mode - XFER_PIO_0; if (pair_pio < tf_pio) tf_pio = pair_pio; } speedp = data_speed[pio]; speedt = tf_speed[tf_pio]; sil_iowrite16(dev, speedp, addr); sil_iowrite16(dev, speedt, tfaddr); speedp = sil_ioread16(dev, tfaddr - 2); speedp &= ~0x200; mode = sil_ioread8(dev, base + addr_mask); mode &= ~(unit ? 0x30 : 0x03); if (ide_pio_need_iordy(drive, pio)) { speedp |= 0x200; mode |= unit ? 0x10 : 0x01; } sil_iowrite16(dev, speedp, tfaddr - 2); sil_iowrite8(dev, mode, base + addr_mask); }
/* returns 1 if dma irq issued, 0 otherwise */ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_altstat = 0; unsigned long addr = siimage_selreg(hwif, 1); /* return 1 if INTR asserted */ if ((hwif->INB(hwif->dma_status) & 4) == 4) return 1; /* return 1 if Device INTR asserted */ pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat); if (dma_altstat & 8) return 0; //return 1; return 0; }
static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) { static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); ide_drive_t *pair = ide_get_paired_drive(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); unsigned long tfaddr = siimage_selreg(hwif, 0x02); unsigned long base = (unsigned long)hwif->hwif_data; u8 tf_pio = pio; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84) : (mmio ? 0xB4 : 0x80); u8 mode = 0; u8 unit = drive->select.b.unit; /* trim *taskfile* PIO to the slowest of the master/slave */ if (pair->present) { u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); if (pair_pio < tf_pio) tf_pio = pair_pio; } /* cheat for now and use the docs */ speedp = data_speed[pio]; speedt = tf_speed[tf_pio]; sil_iowrite16(dev, speedp, addr); sil_iowrite16(dev, speedt, tfaddr); /* now set up IORDY */ speedp = sil_ioread16(dev, tfaddr - 2); speedp &= ~0x200; if (pio > 2) speedp |= 0x200; sil_iowrite16(dev, speedp, tfaddr - 2); mode = sil_ioread8(dev, base + addr_mask); mode &= ~(unit ? 0x30 : 0x03); mode |= unit ? 0x10 : 0x01; sil_iowrite8(dev, mode, base + addr_mask); }
static int siimage_mmio_ide_dma_count (ide_drive_t *drive) { #ifdef SIIMAGE_VIRTUAL_DMAPIO struct request *rq = HWGROUP(drive)->rq; ide_hwif_t *hwif = HWIF(drive); u32 count = (rq->nr_sectors * SECTOR_SIZE); u32 rcount = 0; unsigned long addr = siimage_selreg(hwif, 0x1C); hwif->OUTL(count, addr); rcount = hwif->INL(addr); printk("\n%s: count = %d, rcount = %d, nr_sectors = %lu\n", drive->name, count, rcount, rq->nr_sectors); #endif /* SIIMAGE_VIRTUAL_DMAPIO */ return __ide_dma_count(drive); }
static byte siimage_taskfile_timing (ide_hwif_t *hwif) { u16 timing = 0x328a; unsigned long addr = siimage_selreg(hwif, 2); if (hwif->mmio) timing = hwif->INW(addr); else pci_read_config_word(hwif->pci_dev, addr, &timing); switch (timing) { case 0x10c1: return 4; case 0x10c3: return 3; case 0x1104: case 0x1281: return 2; case 0x2283: return 1; case 0x328a: default: return 0; } }
static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long addr = siimage_selreg(hwif, 0x1); void __iomem *sata_error_addr = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; if (sata_error_addr) { unsigned long base = (unsigned long)hwif->hwif_data; u32 ext_stat = readl((void __iomem *)(base + 0x10)); u8 watchdog = 0; if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { u32 sata_error = readl(sata_error_addr); writel(sata_error, sata_error_addr); watchdog = (sata_error & 0x00680000) ? 1 : 0; printk(KERN_WARNING "%s: sata_error = 0x%08x, " "watchdog = %d, %s\n", drive->name, sata_error, watchdog, __FUNCTION__); } else { watchdog = (ext_stat & 0x8000) ? 1 : 0; } ext_stat >>= 16; if (!(ext_stat & 0x0404) && !watchdog) return 0; } /* return 1 if INTR asserted */ if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04) return 1; /* return 1 if Device INTR asserted */ if ((readb((void __iomem *)addr) & 8) == 8) return 0; //return 1; return 0; }
static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long base = (unsigned long)hwif->hwif_data; unsigned long addr = siimage_selreg(hwif, 0x1); if (SATA_ERROR_REG) { u32 ext_stat = hwif->INL(base + 0x10); u8 watchdog = 0; if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { u32 sata_error = hwif->INL(SATA_ERROR_REG); hwif->OUTL(sata_error, SATA_ERROR_REG); watchdog = (sata_error & 0x00680000) ? 1 : 0; #if 1 printk(KERN_WARNING "%s: sata_error = 0x%08x, " "watchdog = %d, %s\n", drive->name, sata_error, watchdog, __FUNCTION__); #endif } else { watchdog = (ext_stat & 0x8000) ? 1 : 0; } ext_stat >>= 16; if (!(ext_stat & 0x0404) && !watchdog) return 0; } /* return 1 if INTR asserted */ if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04) return 1; /* return 1 if Device INTR asserted */ if ((hwif->INB(addr) & 8) == 8) return 0; //return 1; return 0; }
static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) { const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; ide_hwif_t *hwif = HWIF(drive); ide_drive_t *pair = ide_get_paired_drive(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); unsigned long tfaddr = siimage_selreg(hwif, 0x02); unsigned long base = (unsigned long)hwif->hwif_data; u8 tf_pio = pio; u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84) : (hwif->mmio ? 0xB4 : 0x80); u8 mode = 0; u8 unit = drive->select.b.unit; /* trim *taskfile* PIO to the slowest of the master/slave */ if (pair->present) { u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); if (pair_pio < tf_pio) tf_pio = pair_pio; } /* cheat for now and use the docs */ speedp = data_speed[pio]; speedt = tf_speed[tf_pio]; if (hwif->mmio) { hwif->OUTW(speedp, addr); hwif->OUTW(speedt, tfaddr); /* Now set up IORDY */ if (pio > 2) hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); else hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); mode = hwif->INB(base + addr_mask); mode &= ~(unit ? 0x30 : 0x03); mode |= (unit ? 0x10 : 0x01); hwif->OUTB(mode, base + addr_mask); } else { struct pci_dev *dev = to_pci_dev(hwif->dev); pci_write_config_word(dev, addr, speedp); pci_write_config_word(dev, tfaddr, speedt); pci_read_config_word(dev, tfaddr - 2, &speedp); speedp &= ~0x200; /* Set IORDY for mode 3 or 4 */ if (pio > 2) speedp |= 0x200; pci_write_config_word(dev, tfaddr - 2, speedp); pci_read_config_byte(dev, addr_mask, &mode); mode &= ~(unit ? 0x30 : 0x03); mode |= (unit ? 0x10 : 0x01); pci_write_config_byte(dev, addr_mask, mode); } }