^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (C) 2002 Toshiba Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define DRV_NAME "tc86c001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void tc86c001_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u16 mode, scr = inw(scr_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) const u8 speed = drive->dma_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) switch (speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) case XFER_UDMA_4: mode = 0x00c0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) case XFER_UDMA_3: mode = 0x00b0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) case XFER_UDMA_2: mode = 0x00a0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) case XFER_UDMA_1: mode = 0x0090; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) case XFER_UDMA_0: mode = 0x0080; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) case XFER_MW_DMA_2: mode = 0x0070; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) case XFER_MW_DMA_1: mode = 0x0060; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) case XFER_MW_DMA_0: mode = 0x0050; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case XFER_PIO_4: mode = 0x0400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case XFER_PIO_3: mode = 0x0300; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) case XFER_PIO_2: mode = 0x0200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) case XFER_PIO_1: mode = 0x0100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case XFER_PIO_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) default: mode = 0x0000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) scr |= mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) outw(scr, scr_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void tc86c001_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) drive->dma_mode = drive->pio_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) tc86c001_set_mode(hwif, drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * HACKITY HACK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * if a DMA transfer terminates prematurely, the controller leaves the device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * set the interrupt bit in the DMA status register), thus no PCI interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * will occur until a DMA transfer has been successfully completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * We work around this by initiating dummy, zero-length DMA transfer on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * a DMA timeout expiration. I found no better way to do this with the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * IDE core than to temporarily replace a higher level driver's timer expiry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * handler with our own backing up to that handler in case our recovery fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int tc86c001_timer_expiry(ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ide_hwif_t *hwif = drive->hwif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ide_expiry_t *expiry = ide_get_hwifdata(hwif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Restore a higher level driver's expiry handler first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hwif->expiry = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long sc_base = hwif->config_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "attempting recovery...\n", drive->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Stop DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Setup the dummy DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) outw(0, sc_base + 0x0a); /* Sector Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) outw(0, twcr_port); /* Transfer Word Count 1 or 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Start the dummy DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* clear R_OR_WCTR for write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) outb(0x00, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* set START_STOPBM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) outb(0x01, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * If an interrupt was pending, it should come thru shortly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * If not, a higher level driver's expiry handler should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * eventually cause some kind of recovery from the DMA stall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return WAIT_MIN_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Chain to the restored expiry handler if DMA wasn't active. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (likely(expiry != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return expiry(drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* If there was no handler, "emulate" that for ide_timer_expiry()... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void tc86c001_dma_start(ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ide_hwif_t *hwif = drive->hwif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned long sc_base = hwif->config_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long nsectors = blk_rq_sectors(hwif->rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * We have to manually load the sector count and size into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * the appropriate system control registers for DMA to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * with LBA48 and ATAPI devices...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) outw(nsectors, sc_base + 0x0a); /* Sector Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Install our timeout expiry hook, saving the current handler... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ide_set_hwifdata(hwif, hwif->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) hwif->expiry = &tc86c001_timer_expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ide_dma_start(drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static u8 tc86c001_cable_detect(ide_hwif_t *hwif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct pci_dev *dev = to_pci_dev(hwif->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned long sc_base = pci_resource_start(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u16 scr1 = inw(sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * System Control 1 Register bit 13 (PDIAGN):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * 0=80-pin cable, 1=40-pin cable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void init_hwif_tc86c001(ide_hwif_t *hwif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct pci_dev *dev = to_pci_dev(hwif->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned long sc_base = pci_resource_start(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u16 scr1 = inw(sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* System Control 1 Register bit 15 (Soft Reset) set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) outw(scr1 | 0x8000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* System Control 1 Register bit 14 (FIFO Reset) set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) outw(scr1 | 0x4000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* System Control 1 Register: reset clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) outw(scr1 & ~0xc000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Store the system control register base for convenience... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) hwif->config_data = sc_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!hwif->dma_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Sector Count Control Register bits 0 and 1 set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * software sets Sector Count Register for master and slave device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) outw(0x0003, sc_base + 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* Sector Count Register limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) hwif->rqsize = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static const struct ide_port_ops tc86c001_port_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .set_pio_mode = tc86c001_set_pio_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .set_dma_mode = tc86c001_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .cable_detect = tc86c001_cable_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static const struct ide_dma_ops tc86c001_dma_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .dma_host_set = ide_dma_host_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .dma_setup = ide_dma_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .dma_start = tc86c001_dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .dma_end = ide_dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .dma_test_irq = ide_dma_test_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .dma_lost_irq = ide_dma_lost_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .dma_timer_expiry = ide_dma_sff_timer_expiry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .dma_sff_read_status = ide_dma_sff_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static const struct ide_port_info tc86c001_chipset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .init_hwif = init_hwif_tc86c001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .port_ops = &tc86c001_port_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .dma_ops = &tc86c001_dma_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .pio_mask = ATA_PIO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .mwdma_mask = ATA_MWDMA2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .udma_mask = ATA_UDMA4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int tc86c001_init_one(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) rc = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rc = pci_request_region(dev, 5, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) printk(KERN_ERR DRV_NAME ": system control regs already in use");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) out_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pci_release_region(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) out_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static void tc86c001_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ide_pci_remove(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pci_release_region(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static const struct pci_device_id tc86c001_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static struct pci_driver tc86c001_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .name = "TC86C001",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .id_table = tc86c001_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .probe = tc86c001_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .remove = tc86c001_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int __init tc86c001_ide_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return ide_pci_register_driver(&tc86c001_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void __exit tc86c001_ide_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pci_unregister_driver(&tc86c001_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) module_init(tc86c001_ide_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) module_exit(tc86c001_ide_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) MODULE_LICENSE("GPL");