diff -urN -X ../patches/linux/dontdiff linuxppc-2.5.orig/drivers/ide/Kconfig linuxppc-2.5/drivers/ide/Kconfig --- linuxppc-2.5.orig/drivers/ide/Kconfig 2005-02-16 20:15:27.000000000 +0100 +++ linuxppc-2.5/drivers/ide/Kconfig 2005-02-17 01:44:58.437817472 +0100 @@ -930,7 +930,7 @@ endchoice config BLK_DEV_IDE_STB04xxx - bool "STB04xxx (Redwood-5) IDE support" + tristate "STB04xxx (Redwood-5) IDE support" depends on BLK_DEV_IDE && REDWOOD_5 help This option provides support for IDE on IBM STB04xxx Redwood-5 @@ -1016,11 +1016,11 @@ endif config BLK_DEV_IDEDMA - def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS + def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_STB04xxx config IDEDMA_IVB bool "IGNORE word93 Validation BITS" - depends on BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS + depends on BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_STB04xxx ---help--- There are unclear terms in ATA-4 and ATA-5 standards how certain hardware (an 80c ribbon) should be detected. Different interpretations @@ -1035,7 +1035,7 @@ It is normally safe to answer Y; however, the default is N. config IDEDMA_AUTO - def_bool IDEDMA_PCI_AUTO || IDEDMA_ICS_AUTO + def_bool IDEDMA_PCI_AUTO || IDEDMA_ICS_AUTO || BLK_DEV_IDE_STB04xxx endif diff -urN -X ../patches/linux/dontdiff linuxppc-2.5.orig/drivers/ide/Makefile linuxppc-2.5/drivers/ide/Makefile --- linuxppc-2.5.orig/drivers/ide/Makefile 2005-02-16 20:15:29.000000000 +0100 +++ linuxppc-2.5/drivers/ide/Makefile 2005-02-17 01:44:58.505807136 +0100 @@ -38,6 +38,11 @@ # built-in only drivers from ppc/ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o +ifeq ($(CONFIG_BLK_DEV_IDE_STB04xxx),y) +ide-core-$(CONFIG_BLK_DEV_IDE_STB04xxx) += ppc/ibm_ocp_ide.o +else +obj-$(CONFIG_BLK_DEV_IDE_STB04xxx) += ppc/ibm_ocp_ide.o +endif # built-in only drivers from h8300/ ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o diff -urN -X ../patches/linux/dontdiff linuxppc-2.5.orig/drivers/ide/ppc/ibm_ocp_ide.c linuxppc-2.5/drivers/ide/ppc/ibm_ocp_ide.c --- linuxppc-2.5.orig/drivers/ide/ppc/ibm_ocp_ide.c 2005-02-16 20:15:27.000000000 +0100 +++ linuxppc-2.5/drivers/ide/ppc/ibm_ocp_ide.c 2005-02-17 01:44:59.263691920 +0100 @@ -1,14 +1,26 @@ /* - * Copyright 2002 MontaVista Software Inc. - * Completed implementation. - * Author: Armin Kuster - * MontaVista Software, Inc. + * IDE driver for IBM On-chip IDE contollers + * Copyright 2001 - 2002 MontaVista Software Inc. + * Dan Malek. * - * Module name: ibm_ocp_ide.c + * Version 1.2 (01/30/12) Armin + * Converted to ocp + * merger up to new ide-timing.h * - * Description: + * Version 2.0 (05/02/15) - armin + * converted to new core_ocp and only supports one interface for now. * - * Based on ocp_stbxxxx.c + * Version 2.1 (05/25/02) - armin + * name change from *_driver to *_dev + * Version 2.2 06/13/02 - Armin + * changed irq_resource array to just irq + * + * Version 2.3 (Feb 2005) - andre + * - big rewrite to fix some serious bugs + * - bring up to date with ide in 2.6.11-rc3 + * - DMA works correctly now, even with non-hard-disks + * I snagged bits and pieces from a variety of drivers, primarily + * ide-pmac.c and ide-dma.c .....thanks to previous authors! */ #include @@ -17,54 +29,47 @@ #include #include #include -#include "../ide-timing.h" +#include #include #include #include -#include - -#include "ide_modes.h" +#include -#define IDE_VER "2.0" -ppc_dma_ch_t dma_ch; +#define OCPVR "2.3" -/* use DMA channel 2 for IDE DMA operations */ -#define IDE_DMACH 2 /* 2nd DMA channel */ -#define IDE_DMA_INT 6 /* IDE dma channel 2 interrupt */ -#define WMODE 0 /* default to DMA line mode */ -#define PIOMODE 0 #define MK_TIMING(AS, DIOP, DIOY, DH) \ - ((FIT((AS), 0, 15) << 27) | \ - (FIT((DIOP), 0, 63) << 20) | \ - (FIT((DIOY), 0, 63) << 13) | \ - (FIT((DH), 0, 7) << 9)) + ((FIT((AS), 0, 0x0f) << 27) | \ + (FIT((DIOP), 0, 0x3f) << 20) | \ + (FIT((DIOY), 0, 0x3f) << 13) | \ + (FIT((DH), 0, 0x07) << 9)) #define UTIMING_SETHLD (EZ(20 /*tACK*/, SYS_CLOCK_NS) - 1 /*fixed cycles*/) #define UTIMING_ENV (EZ(20 /*tENV*/, SYS_CLOCK_NS) - 1 /*fixed cycles*/) #define UTIMING_SS (EZ(50 /*tSS */, SYS_CLOCK_NS) - 3 /*fixed cycles*/) + #define MK_UTIMING(CYC, RP) \ - ((FIT(UTIMING_SETHLD, 0, 15) << 27) | \ - (FIT(UTIMING_ENV, 0, 15) << 22) | \ - (FIT((CYC), 0, 15) << 17) | \ - (FIT((RP), 0, 63) << 10) | \ - (FIT(UTIMING_SS, 0, 15) << 5) | \ + ((FIT(UTIMING_SETHLD, 0, 0x0f) << 27) | \ + (FIT(UTIMING_ENV, 0, 0x0f) << 22) | \ + (FIT((CYC), 0, 0x0f) << 17) | \ + (FIT((RP), 0, 0x3f) << 10) | \ + (FIT(UTIMING_SS, 0, 0x0f) << 5) | \ 1 /* Turn on Ultra DMA */) /* Define the period of the STB clock used to generate the * IDE bus timing. The clock is actually 63 MHz, but it - * get rounded in a favorable direction. + * gets rounded in a favorable direction. */ #define IDE_SYS_FREQ 63 /* MHz */ -#define SYS_CLOCK_NS (1000 / IDE_SYS_FREQ) +#define SYS_CLOCK_NS (1000 / IDE_SYS_FREQ) /* 1takt == SYS_CLOCK_NS nanosekunden */ struct whold_timing { short mode; short whold; }; -static struct whold_timing whold_timing[] = { +static const struct whold_timing whold_timing[] = { {XFER_UDMA_5, 0}, {XFER_UDMA_4, 0}, @@ -101,10 +106,10 @@ * but rather "fast" and "slow" timing. We have to determeine * which is the "fast" device based upon their capability. */ -static int pio_mode[2]; +static int pio_mode[2] = { -1, -1 }; + -/* Structure of the memory mapped IDE control. -*/ +/* structure of the memory mapped IDE control */ typedef struct ide_regs { unsigned int si_stat; /* IDE status */ unsigned int si_intenable; /* IDE interrupt enable */ @@ -114,8 +119,8 @@ unsigned int si_c0fpt; /* Chan 0 Fast PIO transfer timing */ unsigned int si_c0timo; /* Chan 0 timeout */ unsigned int pad1[2]; - unsigned int si_c0d0u; /* Chan 0 UDMA transfer timing */ -#define si_c0d0m si_c0d0u /* Chan 0 Multiword DMA timing */ + unsigned int si_c0d0u; /* Chan 0 dev 0 UDMA timing */ +#define si_c0d0m si_c0d0u /* Chan 0 dev 0 Multiword DMA timing */ unsigned int pad2; unsigned int si_c0d1u; /* Chan 0 dev 1 UDMA timing */ #define si_c0d1m si_c0d1u /* Chan 0 dev 1 Multiword DMA timing */ @@ -148,84 +153,74 @@ unsigned int prd_physptr; unsigned int prd_count; /* Count only in lower 16 bits */ } prd_entry_t; -#define PRD_EOT (uint)0x80000000 /* Set in prd_count */ +#define PRD_EOT 0x80000000lu /* Set in prd_count */ /* The number of PRDs required in a single transfer from the upper IDE - * functions. I believe the maximum number is 128, but most seem to - * code to 256. It's probably best to keep this under one page...... + * functions. The maximum number is 128 (ide.h), but most seem to code to + * 256 (because of having two IDE channels). must be less than one page. */ -#define NUM_PRD 256 +#define NUM_PRD 256 -static volatile ide_t *idp; -/* Virtual and physical address of the PRD page. -*/ -static prd_entry_t *prd_table; -static dma_addr_t prd_phys; - -/* Function Prototypes */ -static void ocp_ide_tune_drive(ide_drive_t *, byte); -static int ocp_ide_dma_off(ide_drive_t * drive); -/* The STB04 has a fixed number of cycles that get added in - * regardless. Adjust an ide_timing struct to accommodate that. - */ -static void -ocp_ide_adjust_timing(struct ide_timing *t) -{ - t->setup -= 2; - t->act8b -= 1; - t->rec8b -= 1; - t->active -= 1; - t->recover -= 1; -} -/* this iis barrowed from ide_timing_find_mode so we can find the proper - * whold parameter +/* this is borrowed from ide_timing_find_mode so we can find the proper + * whold parameter */ - static short whold_timing_find_mode(short speed) { - struct whold_timing *t; + const struct whold_timing *t; + + for (t = whold_timing; likely (t->mode >= 0); t++) + if (t->mode == speed) + return t->whold; - for (t = whold_timing; t->mode != speed; t++) - if (t->mode < 0) - return 0; - return t->whold; + return 0; +} + +/* The STB04 has a fixed number of cycles that get added in + * regardless. Adjust an ide_timing struct to accommodate that. + */ +static void +stb04xxx_ide_adjust_timing(struct ide_timing * const t) +{ + t->setup -= 2; + t->act8b -= 1; + t->rec8b -= 1; + t->active -= 1; + t->recover -= 1; } static int -ocp_ide_set_drive(ide_drive_t * drive, unsigned char speed) +stb04xxx_ide_tune_chipset (ide_drive_t * const drive, + u8 speed) { - ide_drive_t *peer; - struct ide_timing d, p, merge, *fast; - int fast_device; - unsigned int ctl; - volatile unsigned int *dtiming; + volatile ide_t __iomem * const ide_regs = HWIF (drive)->hwif_data; + ide_drive_t *peer = HWIF (drive)->drives + (~drive->dn & 1); + struct ide_timing t, p, merge, *fast; + int fast_device; + unsigned int ctl; if (speed != XFER_PIO_SLOW && speed != drive->current_speed) if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING - "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); - - ide_timing_compute(drive, speed, &d, SYS_CLOCK_NS, SYS_CLOCK_NS); - ocp_ide_adjust_timing(&d); + printk (KERN_WARNING + "ide%d: Drive %d didn't accept speed setting. " + "Oh, well.\n", + drive->dn >> 1, drive->dn & 1); - /* This should be set somewhere else, but it isn't..... - */ - drive->dn = ((drive->select.all & 0x10) != 0); - peer = HWIF(drive)->drives + (~drive->dn & 1); + ide_timing_compute(drive, speed, &t, SYS_CLOCK_NS, SYS_CLOCK_NS); + stb04xxx_ide_adjust_timing(&t); + /* peer is the other, i.e. not current, drive */ if (peer->present) { ide_timing_compute(peer, peer->current_speed, &p, SYS_CLOCK_NS, SYS_CLOCK_NS); - ocp_ide_adjust_timing(&p); - ide_timing_merge(&p, &d, &merge, + stb04xxx_ide_adjust_timing(&p); + ide_timing_merge(&p, &t, &merge, IDE_TIMING_8BIT | IDE_TIMING_SETUP); - } else { - merge = d; } + else + merge = t; if (!drive->init_speed) drive->init_speed = speed; @@ -235,58 +230,59 @@ * interface timing. It would sure be nice if they would * have just had the timing registers for each device...... */ - if (drive->dn & 1) - pio_mode[1] = (int) speed; - else - pio_mode[0] = (int) speed; - - if (pio_mode[0] > pio_mode[1]) - fast_device = 0; - else - fast_device = 1; + /* change pio_mode of current drive */ + pio_mode[(drive->dn & 1)] = (int) speed; /* Now determine which of the drives * the first call we only know one device, and on subsequent * calls the user may manually change drive parameters. * Make timing[0] the fast device and timing[1] the slow. */ + + /* compare pio_mode of both drives, one of them is + faster than the other */ + if (pio_mode[0] >= pio_mode[1]) + fast_device = 0; + else + fast_device = 1; + if (fast_device == (drive->dn & 1)) - fast = &d; + /* if fast drive == current drive */ + fast = &t; else + /* if fast drive == peer (other) drive */ fast = &p; /* Now we know which device is the fast one and which is * the slow one. The merged timing goes into the "regular" * timing registers and represents the slower of both times. */ - - idp->si_c0rt = MK_TIMING(merge.setup, merge.act8b, - merge.rec8b, - whold_timing_find_mode(merge.mode)); - - idp->si_c0fpt = MK_TIMING(fast->setup, fast->act8b, - fast->rec8b, - whold_timing_find_mode(fast->mode)); - - /* Tell the interface which drive is the fast one. - */ - ctl = idp->si_c0c; /* Chan 0 Control */ - ctl &= ~0x10000000; + ide_regs->si_c0rt = MK_TIMING(merge.setup, merge.act8b, + merge.rec8b, + whold_timing_find_mode(merge.mode)); + + ide_regs->si_c0fpt = MK_TIMING(fast->setup, fast->act8b, + fast->rec8b, + whold_timing_find_mode(fast->mode)); + + /* tell the interface which drive is the fast one. */ + ctl = ide_regs->si_c0c; /* Chan 0 Control */ + ctl &= ~0x10000000ul; ctl |= fast_device << 28; - idp->si_c0c = ctl; + ide_regs->si_c0c = ctl; - /* Set up DMA timing. - */ + /* Set up DMA timing. */ if ((speed & XFER_MODE) != XFER_PIO) { /* NOTE: si_c0d0m and si_c0d0u are two different names * for the same register. Whether it is used for * Multi-word DMA timings or Ultra DMA timings is * determined by the LSB written into it. This is also * true for si_c0d1m and si_c0d1u. */ + volatile unsigned int __iomem *dtiming; if (drive->dn & 1) - dtiming = &(idp->si_c0d1m); + dtiming = &(ide_regs->si_c0d1u); else - dtiming = &(idp->si_c0d0m); + dtiming = &(ide_regs->si_c0d0u); if ((speed & XFER_MODE) == XFER_UDMA) { static const int tRP[] = { @@ -295,18 +291,18 @@ EZ(100, SYS_CLOCK_NS) - 2 /*fixed cycles */ , EZ(100, SYS_CLOCK_NS) - 2 /*fixed cycles */ , EZ(100, SYS_CLOCK_NS) - 2 /*fixed cycles */ , - EZ(85, SYS_CLOCK_NS) - 2 /*fixed cycles */ + EZ( 85, SYS_CLOCK_NS) - 2 /*fixed cycles */ }; static const int NUMtRP = (sizeof (tRP) / sizeof (tRP[0])); *dtiming = - MK_UTIMING(d.udma, + MK_UTIMING(t.udma, tRP[FIT(speed & 0xf, 0, NUMtRP - 1)]); } else { - /* Multi-word DMA. Note that d.recover/2 is an + /* Multi-word DMA. Note that t.recover/2 is an * approximation of MAX(tH, MAX(tJ, tN)) */ - *dtiming = MK_TIMING(d.setup, d.active, - d.recover, d.recover / 2); + *dtiming = MK_TIMING(t.setup, t.active, + t.recover, t.recover / 2); } drive->using_dma = 1; } @@ -314,590 +310,547 @@ return 0; } +/** + * stb04xxx_ide_tune_drive - tune a drive attached to a stb04 + * @drive: drive to tune + * @pio: desired PIO mode (255 for "best possible") + * + * Set the interface PIO mode. + */ static void -ocp_ide_tune_drive(ide_drive_t * drive, byte pio) +stb04xxx_ide_tune_drive (ide_drive_t * const drive, + u8 pio) { - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode (drive, pio, 4, NULL); + stb04xxx_ide_tune_chipset(drive, XFER_PIO_0 + pio); } -/* - * Fill in the next PRD entry. - */ - -static int ocp_ide_build_prd_entry(prd_entry_t **table, unsigned int paddr, - unsigned int size, int *count) +static int +stb04xxx_ide_dma_host_off (ide_drive_t * const drive) { + return 0; +} +static int stb04xxx_ide_dma_host_on (ide_drive_t * const drive) __attribute__((alias("stb04xxx_ide_dma_host_off"))); - /* - * Note that one PRD entry can transfer - * at most 65535 bytes. - */ - - while (size) { - unsigned int tc = (size < 0xfe00) ? size : 0xfe00; +static int +stb04xxx_ide_dma_off_quietly (ide_drive_t * const drive) +{ + drive->using_dma = 0; + return stb04xxx_ide_dma_host_off (drive); +} - if (++(*count) >= NUM_PRD) { - printk(KERN_WARNING "DMA table too small\n"); - return 0; /* revert to PIO for this request */ - } - (*table)->prd_physptr = (paddr & 0xfffffffe); +#if 0 +static int +config_drive_for_dma (ide_drive_t * const drive) +{ + struct hd_driveid * const id = drive->id; + ide_hwif_t * const hwif = HWIF (drive); - if ((*table)->prd_physptr & 0xF) { - printk(KERN_WARNING "DMA buffer not 16 byte aligned.\n"); - return 0; /* revert to PIO for this request */ - } - - (*table)->prd_count = (tc & 0xfffe); - paddr += tc; - size -= tc; - ++(*table); + if ((id->capability & 1) && hwif->autodma) { + /* Consult the list of known "bad" drives */ + if (0) + return stb04xxx_ide_dma_off_quietly (drive); + + /* enable DMA on any drive that has + UltraDMA (mode 0/1/2/3/4/5) enabled */ + if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x3f)) + return stb04xxx_ide_dma_on (drive); + + /* enable DMA on any drive that has mode2 DMA + (multi) enabled */ + if (id->field_valid & 2) + if ((id->dma_mword & 0x404) == 0x404) + return stb04xxx_ide_dma_on (drive); + + /* Consult the list of known "good" drives */ + if (1) + return stb04xxx_ide_dma_on (drive); } - - return 1; + return stb04xxx_ide_dma_off_quietly (drive); } +#endif - +/** + * stb04xxx_ide_dma_check - set up for DMA if possible + * @drive: IDE drive to set up + * + * Set up the drive for the highest supported speed considering the + * driver, controller and cable + */ static int -ocp_ide_build_dmatable(ide_drive_t * drive, int wr) +stb04xxx_ide_dma_check (ide_drive_t * const drive) { - prd_entry_t *table; - int count = 0; - struct request *rq = HWGROUP(drive)->rq; - unsigned long size, vaddr, paddr; - unsigned long prd_size, prd_paddr = 0; - struct bio_vec *bvec, *bvprv; - struct bio *bio; - int i; +#if 0 + return config_drive_for_dma (drive); +#else + /* Allow UDMA_66 only if an 80 conductor cable is connected. */ + u16 w80 = HWIF (drive)->udma_four; - table = prd_table; + /* Section 1.6.2.6 "IDE Controller, ATA/ATAPI-5" in the STB04xxx + * Datasheet says the following modes are supported: + * PIO modes 0 to 4 + * Multiword DMA modes 0 to 2 + * UltraDMA modes 0 to 4 + */ + int modes = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA + | (w80 ? XFER_UDMA_66 : 0); + int mode; + + /* XFER_EPIO includes both PIO modes 4 and 5. Mode 5 is not + * valid for the STB04, so mask it out of consideration just + * in case some drive sets it... + */ + drive->id->eide_pio_modes &= ~4; - bvprv = NULL; - rq_for_each_bio(bio, rq) { - bio_for_each_segment(bvec, bio, i) { - paddr = bvec_to_phys(bvec); - vaddr = (unsigned long) __va(paddr); - size = bvec->bv_len; - if (wr) - consistent_sync((void *)vaddr, - size, PCI_DMA_TODEVICE); - else - consistent_sync((void *)vaddr, - size, PCI_DMA_FROMDEVICE); - - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) { - if (ocp_ide_build_prd_entry(&table, - prd_paddr, - prd_size, - &count) == 0) - return 0; /* use PIO */ - prd_paddr = 0; - } - - if (prd_paddr == 0) { - prd_paddr = paddr; - prd_size = size; - } else { - prd_size += size; - } - - bvprv = bvec; - } /* segments in bio */ - } /* bios in rq */ - - if (prd_paddr) { - if (ocp_ide_build_prd_entry(&table, - prd_paddr, - prd_size, - &count) == 0) - return 0; /* use PIO */ - } + mode = ide_find_best_mode (drive, modes); - /* Add the EOT to the last table entry. - */ - if (count) { - table--; - table->prd_count |= PRD_EOT; - } else { - printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - } + drive->using_dma = 0; + stb04xxx_ide_tune_chipset (drive, mode); + if (HWIF (drive)->autodma + && (((mode & XFER_MODE) == XFER_PIO) + || ((mode & XFER_MODE) == XFER_EPIO))) + drive->using_dma = 0; - return 1; + return 0; +#endif } -/* - * ocp_ide_dma_intr() is the handler for disk read/write DMA interrupts - * This is taken directly from ide-dma.c, which we can't use because - * it requires PCI support. - */ -ide_startstop_t -ocp_ide_dma_intr(ide_drive_t * drive) +static int +stb04xxx_ide_dma_on (ide_drive_t * const drive) { - int i; - byte stat, dma_stat; - - dma_stat = HWIF(drive)->ide_dma_end(drive); - stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ - if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(drive, 1, - rq->current_nr_sectors ); - } - return ide_stopped; - } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return ide_error(drive, "dma_intr", stat); + drive->using_dma = 1; + return stb04xxx_ide_dma_host_on (drive); } -/* ....and another one.... -*/ -int -report_drive_dmaing(ide_drive_t * drive) -{ - struct hd_driveid *id = drive->id; - if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { - if ((id->dma_ultra >> 13) & 1) { - printk(", UDMA(100)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 12) & 1) { - printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(44)"); /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && - (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - if ((id->dma_ultra >> 10) & 1) { - printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 9) & 1) { - printk(", UDMA(25)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(16)"); /* UDMA BIOS-enabled! */ - } - } else if (id->field_valid & 4) { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } else { - printk(", DMA"); - } - return 1; -} +/* fill in the next PRD entry + note that one PRD entry can transfer at most 65536 bytes */ static int -ocp_ide_check_dma(ide_drive_t * drive) +build_prd_entry (prd_entry_t **table, + u32 paddr, + u32 size, + int *count) { - struct hd_driveid *id = drive->id; - int enable = 1; - int speed; + while (size) { + u16 tc = size & 0xffff; - drive->using_dma = 0; + if (unlikely (*count >= NUM_PRD)) { +// printk (KERN_WARNING "%s: DMA table too small\n", +// __FUNCTION__); + return 0; /* revert to PIO for this request */ + } - if (drive->media == ide_floppy) - enable = 0; + /* data must be 16 byte aligned */ + if (unlikely (paddr & 0xf)) { +// printk (KERN_WARNING +// "%s: DMA buffer not 16 byte aligned.\n", +// __FUNCTION__); + return 0; /* revert to PIO for this request */ + } - /* Check timing here, we may be able to include XFER_UDMA_66 - * and XFER_UDMA_100. This basically tells the 'best_mode' - * function to also consider UDMA3 to UDMA5 device timing. - */ - if (enable) { - /* Section 1.6.2.6 "IDE Controller, ATA/ATAPI-5" in the STB04xxx - * Datasheet says the following modes are supported: - * PIO modes 0 to 4 - * Multiword DMA modes 0 to 2 - * UltraDMA modes 0 to 4 - */ - int map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA; - /* XFER_EPIO includes both PIO modes 4 and 5. Mode 5 is not - * valid for the STB04, so mask it out of consideration just - * in case some drive sets it... - */ - id->eide_pio_modes &= ~4; - - /* Allow UDMA_66 only if an 80 conductor cable is connected. */ - if (eighty_ninty_three(drive)) - map |= XFER_UDMA_66; - - speed = ide_find_best_mode(drive, map); - ocp_ide_set_drive(drive, speed); - - if (HWIF(drive)->autodma && - (((speed & XFER_MODE) == XFER_PIO) || - ((speed & XFER_MODE) == XFER_EPIO))) { - drive->using_dma = 0; + /* transfer count must be a multiple of 16 */ + if (unlikely (tc & 0x0f)) { +// printk (KERN_WARNING +// "%s: invalid DMA transfer count.\n", +// __FUNCTION__); + return 0; /* revert to PIO for this request */ } + + (*table)->prd_physptr = paddr; + (*table)->prd_count = tc; + + paddr += (tc ? : 65536); + size -= (tc ? : 65536); + + ++(*table); + ++(*count); } - return 0; + return 1; } -static int ocp_ide_dma_off_quietly(ide_drive_t * drive) +static int +stb04xxx_ide_build_sglist (ide_drive_t * const drive, + ide_hwif_t * const hwif, + struct request * const rq, + struct scatterlist *sg) { - drive->using_dma = 0; - return 0; -} + if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256) + BUG(); -static int ocp_ide_dma_off(ide_drive_t * drive) -{ - printk(KERN_INFO "%s: DMA disabled\n", drive->name); - return ocp_ide_dma_off_quietly(drive); -} + ide_map_sg(drive, rq); -static int ocp_ide_dma_on(ide_drive_t * drive) -{ - return ocp_ide_check_dma(drive); + hwif->sg_dma_direction = (rq_data_dir (rq) == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + return dma_map_sg(/* hwif->pci_dev */ NULL, sg, hwif->sg_nents, + hwif->sg_dma_direction); } -static int ocp_ide_dma_check(ide_drive_t * drive) +static int +stb04xxx_ide_build_dmatable (ide_drive_t * const drive, + ide_hwif_t * const hwif, + struct request * const rq) { - return ocp_ide_dma_on(drive); -} + prd_entry_t *table = (prd_entry_t *) hwif->dmatable_cpu; + unsigned int count = 0; + int i; + struct scatterlist *sg = hwif->sg_table; -static int __ocp_ide_dma_begin(ide_drive_t * drive, int writing) -{ - idp->si_c0tb = (unsigned int) prd_phys; - idp->si_c0s0 = 0xdc800000; /* Clear all status */ - idp->si_c0ie = 0x90000000; /* Enable all intr */ - idp->si_c0dcm = 0; - idp->si_c0dcm = - (writing ? 0x09000000 : 0x01000000); - return 0; + hwif->sg_nents = i = stb04xxx_ide_build_sglist (drive, hwif, rq, sg); + + if (unlikely (!i)) + goto use_pio_instead; + + ++i; + while (--i) { + if (unlikely (!build_prd_entry (&table, + sg_dma_address (sg), + sg_dma_len (sg), + &count))) + goto use_pio_instead; + + ++sg; + } + + if (likely (count)) { + --table; + table->prd_count |= PRD_EOT; + return count; + } + + printk (KERN_ERR "%s: empty DMA table?\n", drive->name); + +use_pio_instead: + dma_unmap_sg (NULL, + hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); + + return 0; /* revert to PIO for this request */ } + -static int ocp_ide_dma_begin(ide_drive_t * drive) +static void +stb04xxx_ide_destroy_dmatable (ide_drive_t * const drive) { - idp->si_c0tb = (unsigned int) prd_phys; - idp->si_c0s0 = 0xdc800000; /* Clear all status */ - idp->si_c0ie = 0x90000000; /* Enable all intr */ - idp->si_c0dcm = 0; - idp->si_c0dcm = 0x01000000; - return 0; + ide_hwif_t *hwif = drive->hwif; + int nents = hwif->sg_nents; + + if (nents) { + dma_unmap_sg (NULL, hwif->sg_table, nents, + hwif->sg_dma_direction); + hwif->sg_nents = 0; + } } -static int ocp_ide_dma_io(ide_drive_t * drive, int writing) + +static int +stb04xxx_dma_setup (ide_drive_t * const drive) { - if (!ocp_ide_build_dmatable(drive, writing)) + ide_hwif_t * const hwif = HWIF (drive); + volatile ide_t __iomem * const ide_regs = (ide_t *) hwif->hwif_data; + struct request * const rq = HWGROUP (drive)->rq; + + /* PRD table */ + if (unlikely (!stb04xxx_ide_build_dmatable (drive, hwif, rq))) { + /* try PIO instead of DMA */ + ide_map_sg (drive, rq); return 1; + } + + ide_regs->si_c0tb = hwif->dmatable_dma; /* address of sg list */ + ide_regs->si_c0s0 = 0xdc800000ul; /* clear all status */ + ide_regs->si_c0ie = 0x90000000ul; /* enable all intr */ + /* specify r/w */ + ide_regs->si_c0dcm = (rq_data_dir (rq) == READ) ? 0x00000000ul : 0x08000000ul; drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - ide_set_handler(drive, &ocp_ide_dma_intr, WAIT_CMD, NULL); - HWIF(drive)->OUTB(writing ? WIN_WRITEDMA : WIN_READDMA, - IDE_COMMAND_REG); - return __ocp_ide_dma_begin(drive, writing); + return 0; } -static int ocp_ide_dma_read(ide_drive_t * drive) +static void +stb04xxx_dma_exec_cmd (ide_drive_t * const drive, + u8 command) { - return ocp_ide_dma_io(drive, 0); + ide_execute_command (drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); } -static int ocp_ide_dma_write(ide_drive_t * drive) +static void +stb04xxx_dma_start (ide_drive_t * const drive) { - return ocp_ide_dma_io(drive, 1); + volatile ide_t __iomem * const ide_regs = (ide_t *) HWIF (drive)->hwif_data; + + /* start DMA */ + mb (); + ide_regs->si_c0dcm |= 0x01000000ul; /* kick it */ } -static int ocp_ide_dma_end(ide_drive_t * drive) +static int +stb04xxx_ide_dma_end (ide_drive_t * const drive) { - unsigned int dstat; + volatile ide_t __iomem * const ide_regs = (ide_t *) HWIF (drive)->hwif_data; + unsigned int dstat; drive->waiting_for_dma = 0; - dstat = idp->si_c0s1; - idp->si_c0s0 = 0xdc800000; /* Clear all status */ + /* stop DMA */ + ide_regs->si_c0dcm &= ~0x01000000ul; + /* get DMA status */ + dstat = ide_regs->si_c0s1; + /* clear all status bits */ + ide_regs->si_c0s0 = 0xdc800000ul; + wmb (); + stb04xxx_ide_destroy_dmatable (drive); /* verify good dma status */ - return (dstat & 0x80000000); -} - -static int ocp_ide_dma_test_irq(ide_drive_t * drive) -{ - return idp->si_c0s0 & 0x10000000 ? 1 : 0; + return (dstat & 0x10000000ul) ? 0 : 1; /* return true if DMA still active */ } -static int ocp_ide_dma_verbose(ide_drive_t * drive) -{ - return report_drive_dmaing(drive); -} - -static unsigned int -ocp_ide_spinup(int index) +static int +stb04xxx_ide_dma_test_irq (ide_drive_t * const drive) { - int i, ret; - ide_ioreg_t *io_ports; + /* return 1 if dma irq issued, 0 otherwise */ + volatile ide_t __iomem * const ide = (ide_t *) HWIF (drive)->hwif_data; - ret = 1; - printk("OCP ide: waiting for drive spinup"); - printk("ioports for drive %d @ %p\n",index,ide_hwifs[index].io_ports); - io_ports = ide_hwifs[index].io_ports; - printk("."); - - /* wait until drive is not busy (it may be spinning up) */ - for (i = 0; i < 30; i++) { - unsigned char stat; - stat = inb_p(io_ports[7]); - /* wait for !busy & ready */ - if ((stat & 0x80) == 0) { - break; - } - udelay(1000 * 1000); /* 1 second */ + if (ide->si_c0s0 & 0x10000000ul) + return 1; + if (!drive->waiting_for_dma) { + printk(KERN_WARNING "%s: (%s) called while not waiting\n", + drive->name, __FUNCTION__); } - printk("."); + return 0; +} - /* select slave */ - outb_p(0xa0 | 0x10, io_ports[6]); - for (i = 0; i < 30; i++) { - unsigned char stat; - stat = inb_p(io_ports[7]); - /* wait for !busy & ready */ - if ((stat & 0x80) == 0) { - break; - } - udelay(1000 * 1000); /* 1 second */ - } - if( i < 30){ - outb_p(0xa0, io_ports[6]); - printk("Drive spun up \n"); - } else { - printk("Drive spin up Failed !\n"); - ret = 0; - } - return (ret); +static int +stb04xxx_ide_dma_lostirq (ide_drive_t * const drive) +{ + printk ("%s: DMA interrupt recovery neccessary\n", drive->name); + return 1; } -int -ocp_ide_default_irq(ide_ioreg_t base) +static int +stb04xxx_ide_dma_timeout (ide_drive_t * const drive) { - return IDE0_IRQ; + printk (KERN_ERR "%s: timeout waiting for DMA\n", drive->name); + if (stb04xxx_ide_dma_test_irq (drive)) + return 0; + return stb04xxx_ide_dma_end (drive); } -/* - * setup_ocp_ide() - * Completes the setup of a on-chip ide controller card, once found. - */ -int __init setup_ocp_ide (struct ocp_device *pdev) +static void +stb04xxx_ide_setup_dma (ide_hwif_t * const hwif) { - ide_hwif_t *hwif; - unsigned int uicdcr; - - hwif = &ide_hwifs[pdev->num]; - hwif->index = pdev->num; -#ifdef WMODE - /*Word Mode psc(11-12)=00,pwc(13-18)=000110, phc(19-21)=010, 22=1, 30=1 ---- 0xCB02*/ - - dma_ch.mode =TM_S_MM; /* xfer from peripheral to mem */ - dma_ch.pwidth = PW_16; - dma_ch.pwc = 6; /* set the max wait cycles */ -#else -/*Line Mode psc(11-12)=00,pwc(13-18)=000001, phc(19-21)=010, 22=1, 30=1 ---- 0x2B02*/ + hwif->autodma = 1; + hwif->drives[0].autotune = hwif->drives[1].autotune = IDE_TUNE_AUTO; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + + hwif->atapi_dma = 1; + hwif->ultra_mask = hwif->udma_four ? 0x1f : 0x07; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x00; + + /* set everything to something != NULL */ + hwif->ide_dma_host_off = &stb04xxx_ide_dma_host_off; + hwif->ide_dma_host_on = &stb04xxx_ide_dma_host_on; + + hwif->ide_dma_check = &stb04xxx_ide_dma_check; + hwif->ide_dma_off_quietly = &stb04xxx_ide_dma_off_quietly; + hwif->ide_dma_on = &stb04xxx_ide_dma_on; + + hwif->dma_setup = &stb04xxx_dma_setup; + hwif->dma_exec_cmd = &stb04xxx_dma_exec_cmd; + hwif->dma_start = &stb04xxx_dma_start; + hwif->ide_dma_end = &stb04xxx_ide_dma_end; - dma_ch.mode =DMA_MODE_MM_DEVATSRC; /* xfer from peripheral to mem */ - dma_ch.pwidth = PW_64; /* Line mode on stbs */ - dma_ch.pwc = 1; /* set the max wait cycles */ -#endif + hwif->ide_dma_test_irq = &stb04xxx_ide_dma_test_irq; - dma_ch.td = DMA_TD; - dma_ch.buffer_enable = 0; - dma_ch.tce_enable = 0; - dma_ch.etd_output = 0; - dma_ch.pce = 0; - dma_ch.pl = EXTERNAL_PERIPHERAL; /* no op */ - dma_ch.dai = 1; - dma_ch.sai = 0; - dma_ch.psc = 0; /* set the max setup cycles */ - dma_ch.phc = 2; /* set the max hold cycles */ - dma_ch.cp = PRIORITY_LOW; - dma_ch.int_enable = 0; - dma_ch.ch_enable = 0; /* No chaining */ - dma_ch.tcd_disable = 1; /* No chaining */ - - if (hw_init_dma_channel(IDE_DMACH, &dma_ch) != DMA_STATUS_GOOD) - return -EBUSY; - - /* init CIC select2 reg to connect external DMA port 3 to internal - * DMA channel 2 - */ - map_dma_port(IDE_DMACH,EXT_DMA_3,DMA_CHAN_2); - - /* Enable the interface. - */ - idp->si_control = 0x80000000; - idp->si_c0s0 = 0xdc800000; /* Clear all status */ - idp->si_intenable = 0x80000000; - - /* Per the STB04 data sheet: - * 1) tTO = ((8*RDYT) + 1) * SYS_CLK - * and: - * 2) tTO >= 1250 + (2 * SYS_CLK) - t2 - * Solving the first equation for RDYT: - * (tTO/SYS_CLK) - 1 - * 3) RDYT = ----------------- - * 8 - * Substituting equation 2) for tTO in equation 3: - * ((1250 + (2 * SYS_CLK) - t2)/SYS_CLK) - 1 - * 3) RDYT = ----------------------------------------- - * 8 - * It's just the timeout so having it too long isn't too - * significant, so we'll just assume t2 is zero. All this math - * is handled by the compiler and RDYT ends up being 11 assuming - * that SYS_CLOCK_NS is 15. - */ - idp->si_c0timo = (EZ(EZ(1250 + 2 * SYS_CLOCK_NS, SYS_CLOCK_NS) - 1, 8)) << 23; /* Chan 0 timeout */ - - /* Stuff some slow default PIO timing. - */ - idp->si_c0rt = MK_TIMING(6, 19, 15, 2); - idp->si_c0fpt = MK_TIMING(6, 19, 15, 2); - - /* We should probably have UIC functions to set external - * interrupt level/edge. - */ - uicdcr = mfdcr(DCRN_UIC_PR(UIC0)); - uicdcr &= ~(0x80000000 >> IDE0_IRQ); - mtdcr(DCRN_UIC_PR(UIC0), uicdcr); - mtdcr(DCRN_UIC_TR(UIC0), 0x80000000 >> IDE0_IRQ); - - /* Grab a page for the PRD Table. - */ - prd_table = (prd_entry_t *) consistent_alloc(GFP_KERNEL, - NUM_PRD * - sizeof - (prd_entry_t), - &prd_phys); - - - if(!ocp_ide_spinup(hwif->index)) - return 0; - - return 1; + hwif->ide_dma_lostirq = &stb04xxx_ide_dma_lostirq; + hwif->ide_dma_timeout = &stb04xxx_ide_dma_timeout; } - -static int __devinit ocp_ide_probe(struct ocp_device *pdev) +static int __init +stb04xxx_ide_probe (struct ocp_device * const ocp) { - int i; - unsigned int index; - hw_regs_t * hw; - unsigned char *ip; - - printk("IBM STB04xxx IDE driver version %s\n", IDE_VER); - - hw = kmalloc(sizeof(*hw), GFP_KERNEL); - if (!hw) - return 0; - memset(hw, 0, sizeof(*hw)); - - if (!request_region(pdev->paddr, IDE0_SIZE, "IDE")) { - printk(KERN_WARNING "ocp_ide: failed request_region\n"); - return -1; - } - - if ((idp = (ide_t *) ioremap(pdev->paddr, - IDE0_SIZE)) == NULL) { - printk(KERN_WARNING "ocp_ide: failed ioremap\n"); - return -1; + int err; + unsigned int uicdcr; + volatile ide_t __iomem *ide_regs; + unsigned long flags; + ide_hwif_t * const hwif = &ide_hwifs[0]; + unsigned char * ip; + int i; + + printk ("IBM STB04xxx OCP IDE driver version %s\n", OCPVR); + + if (!request_region (ocp->def->paddr, sizeof (ide_t), "ide")) + return -ENOMEM; + + ocp_force_power_on (ocp); + + ide_regs = ioremap (ocp->def->paddr, sizeof (ide_t)); + if (unlikely (!ide_regs)) { + err = -ENOMEM; + goto error1; } - pdev->dev.driver_data = (void *) idp; - pdev->ocpdev = (void *) hw; - index = pdev->num; - ip = (unsigned char *) (&(idp->si_c0d)); /* Chan 0 data */ + /* Enable the interface. */ + ide_regs->si_control = 0x80000000ul; + ide_regs->si_c0s0 = 0xdc800000ul; /* Clear all status */ + ide_regs->si_intenable = 0x80000000ul; + /* Per the STB04 data sheet: + * 1) tTO = ((8*RDYT) + 1) * SYS_CLK + * and: + * 2) tTO >= 1250 + (2 * SYS_CLK) - t2 + * Solving the first equation for RDYT: + * (tTO/SYS_CLK) - 1 + * 3) RDYT = ----------------- + * 8 + * Substituting equation 2) for tTO in equation 3: + * ((1250 + (2 * SYS_CLK) - t2)/SYS_CLK) - 1 + * 3) RDYT = ----------------------------------------- + * 8 + * It's just the timeout so having it too long isn't too + * significant, so we'll just assume t2 is zero. All this math + * is handled by the compiler and RDYT ends up being 11 assuming + * that SYS_CLOCK_NS is 15. + */ + ide_regs->si_c0timo = (EZ(EZ(1250 + 2 * SYS_CLOCK_NS, SYS_CLOCK_NS) - 1, 8)) << 23; /* Chan 0 timeout */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = (unsigned long) (ip++); + /* stuff some slow default PIO timing */ + ide_regs->si_c0rt = MK_TIMING(6, 19, 15, 2); + ide_regs->si_c0fpt = MK_TIMING(6, 19, 15, 2); + + /* enable 32bit access on both devices */ + ide_regs->si_c0c |= 0x00008040ul; + + /* we should probably have UIC functions to set external + interrupt level/edge */ + local_irq_save (flags); + uicdcr = mfdcr (DCRN_UIC_PR (UIC0)); + uicdcr &= ~(0x80000000ul >> IDE0_IRQ); + mtdcr (DCRN_UIC_PR(UIC0), uicdcr); + mtdcr (DCRN_UIC_TR(UIC0), + mfdcr (DCRN_UIC_TR (UIC0)) | (0x80000000ul >> IDE0_IRQ)); + local_irq_restore (flags); + + + /* initialize */ + hwif->gendev.parent = &ocp->dev; + ocp_set_drvdata (ocp, hwif); + + /* setup MMIO ops */ + default_hwif_mmiops (hwif); + + /* tell common code _not_ to mess with resources */ + hwif->mmio = 2; + ide_set_hwifdata (hwif, (void *) ide_regs); + + ip = (unsigned char *) (&(ide_regs->si_c0d)); /* Chan 0 data */ + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) + hwif->hw.io_ports[i] = (int) (ip++); + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (int) (&(ide_regs->si_c0adc)); + memcpy (hwif->io_ports, hwif->hw.io_ports, sizeof (hwif->hw.io_ports)); + hwif->chipset = ide_generic; + hwif->irq = ocp->def->irq; + hwif->noprobe = 0; + hwif->hold = 1; + /* Figure out if an 80 conductor cable is connected */ + hwif->udma_four = (ide_regs->si_c0s1 & 0x20000000ul) != 0; + hwif->tuneproc = &stb04xxx_ide_tune_drive; + hwif->speedproc = &stb04xxx_ide_tune_chipset; + hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1; + hwif->drives[0].unmask = hwif->drives[1].unmask = 1; + pio_mode[0] = pio_mode[1] = -1; + stb04xxx_ide_setup_dma (hwif); + + /* grab a page for the PRD table. this is save with respect to not + crossing a 64k border because returned memory is page aligned + and NUM_PRD*sizeof(prd_entry_t) end up being 2048 bytes, i.e. + less than one page. */ + hwif->dmatable_cpu = dma_alloc_coherent (NULL, + NUM_PRD * sizeof (prd_entry_t), + &hwif->dmatable_dma, + GFP_KERNEL | GFP_DMA); + if (unlikely (!hwif->dmatable_cpu)) { + err = -ENOMEM; + goto error2; } + hwif->sg_max_nents = NUM_PRD; - hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long) (&(idp->si_c0adc)); - hw->irq = pdev->irq; - - /* use DMA channel 2 for IDE DMA operations */ - hw->dma = IDE_DMACH; + probe_hwif_init (hwif); - ide_hwifs[index].tuneproc = &ocp_ide_tune_drive; - ide_hwifs[index].drives[0].autotune = 1; - ide_hwifs[index].autodma = 1; - ide_hwifs[index].ide_dma_off = &ocp_ide_dma_off; - ide_hwifs[index].ide_dma_off_quietly = &ocp_ide_dma_off_quietly; - ide_hwifs[index].ide_dma_host_off = &ocp_ide_dma_off_quietly; - ide_hwifs[index].ide_dma_on = &ocp_ide_dma_on; - ide_hwifs[index].ide_dma_host_on = &ocp_ide_dma_on; - ide_hwifs[index].ide_dma_check = &ocp_ide_dma_check; - ide_hwifs[index].ide_dma_read = &ocp_ide_dma_read; - ide_hwifs[index].ide_dma_write = &ocp_ide_dma_write; - ide_hwifs[index].ide_dma_begin = &ocp_ide_dma_begin; - ide_hwifs[index].ide_dma_end = &ocp_ide_dma_end; - ide_hwifs[index].ide_dma_test_irq = &ocp_ide_dma_test_irq; - ide_hwifs[index].ide_dma_verbose = &ocp_ide_dma_verbose; - ide_hwifs[index].speedproc = &ocp_ide_set_drive; - ide_hwifs[index].noprobe = 0; + create_proc_ide_interfaces (); - memcpy(ide_hwifs[index].io_ports, hw->io_ports, sizeof (hw->io_ports)); - ide_hwifs[index].irq = pdev->irq; + return 0; - ocp_force_power_on(pdev); - return 1; +error2: + ide_set_hwifdata (hwif, NULL); + hwif->noprobe = 1; + hwif->chipset = ide_unknown; + ocp_set_drvdata (ocp, NULL); + iounmap (ide_regs); +error1: + ocp_force_power_off (ocp); + release_region (ocp->def->paddr, sizeof (ide_t)); + return err; } -static void __devexit ocp_ide_remove_one (struct ocp_device *pdev) +static void +stb04xxx_ide_remove (struct ocp_device * const ocp) { - ocp_force_power_off(pdev); + ide_hwif_t * const hwif = ocp_get_drvdata (ocp); + volatile ide_t __iomem * const ide_regs = ide_get_hwifdata (hwif); + + /* ide_unregister () can't ever handle these correctly for us */ + dma_free_coherent (NULL, NUM_PRD * sizeof (prd_entry_t), + hwif->dmatable_cpu, hwif->dmatable_dma); + hwif->dmatable_cpu = NULL; + hwif->dmatable_dma = 0; + + ide_unregister (hwif->index); + iounmap (ide_regs); + release_region (ocp->def->paddr, sizeof (ide_t)); + + ocp_force_power_off (ocp); } -static struct ocp_device_id ocp_ide_id_tbl[] __devinitdata = { - {OCP_VENDOR_IBM,OCP_FUNC_IDE}, - {0,} + +static struct ocp_device_id stb04xxx_ide_ids[] __devinitdata = +{ + { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IDE}, + { .vendor = OCP_VENDOR_INVALID } }; -MODULE_DEVICE_TABLE(ocp,ocp_ide_id_tbl ); +MODULE_DEVICE_TABLE (ocp, stb04xxx_ide_ids); -static struct ocp_driver ocp_ide_driver = { - .name = "ocp_ide", - .id_table = ocp_ide_id_tbl, - .probe = ocp_ide_probe, - .remove = __devexit_p(ocp_ide_remove_one), +static struct ocp_driver stb04xxx_ide_driver = { + .name = "ide", + .id_table = stb04xxx_ide_ids, + .probe = stb04xxx_ide_probe, + .remove = __devexit_p (stb04xxx_ide_remove), #if defined(CONFIG_PM) - .suspend = ocp_generic_suspend, - .resume = ocp_generic_resume, -#endif /* CONFIG_PM */ + .suspend = NULL, + .resume = NULL, +#endif }; -void __init std_ide_cntl_scan(void) -{ - struct ocp_device *dev; - int i, max; - printk("OCP ide ver:%s\n", IDE_VER); - - ocp_module_init(&ocp_ide_driver); - max = ocp_get_num(OCP_FUNC_IDE); - for(i = 0; i < max; i++){ - dev = ocp_get_dev(OCP_FUNC_IDE,i); - if(!dev) - setup_ocp_ide(dev); - } -} -#if 0 -#if defined (CONFIG_MODULE) + static int __init -ocp_ide_init(void) +stb04xxx_ide_init (void) { - printk("OCP ide ver:%s\n", IDE_VER); - return ocp_module_init(&ocp_ide_driver); + return ocp_register_driver (&stb04xxx_ide_driver); } -void __exit -ocp_ide_fini(void) +static void __exit +stb04xxx_ide_exit (void) { - ocp_unregister_driver(&ocp_ide_driver); + ocp_unregister_driver (&stb04xxx_ide_driver); } -module_init(ocp_ide_init); -module_exit(ocp_ide_fini); -#endif -#endif +/* needs to be called after ide has been initialized */ +late_initcall (stb04xxx_ide_init); +module_exit (stb04xxx_ide_exit); +MODULE_LICENSE ("GPL"); +MODULE_AUTHOR ("André Draszik "); +MODULE_DESCRIPTION ("driver for IBM OCP IDE on STB04xxx");