diff options
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/Kconfig | 10 | ||||
-rw-r--r-- | drivers/ide/ide-cd.c | 12 | ||||
-rw-r--r-- | drivers/ide/ide-cd.h | 1 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 142 | ||||
-rw-r--r-- | drivers/ide/ide-dma.c | 15 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 1 | ||||
-rw-r--r-- | drivers/ide/ide-io.c | 11 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 1 | ||||
-rw-r--r-- | drivers/ide/ide.c | 60 | ||||
-rw-r--r-- | drivers/ide/legacy/ide-cs.c | 132 | ||||
-rw-r--r-- | drivers/ide/mips/Makefile | 3 | ||||
-rw-r--r-- | drivers/ide/mips/au1xxx-ide.c | 1498 | ||||
-rw-r--r-- | drivers/ide/pci/sgiioc4.c | 8 | ||||
-rw-r--r-- | drivers/ide/pci/via82cxxx.c | 1 |
14 files changed, 723 insertions, 1172 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 31e649a9ff7..1c81174595b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -807,14 +807,6 @@ config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX endchoice -config BLK_DEV_IDE_AU1XXX_BURSTABLE_ON - bool "Enable burstable Mode on DbDMA" - default false - depends BLK_DEV_IDE_AU1XXX - help - This option enable the burstable Flag on DbDMA controller - (cf. "AMD Alchemy 'Au1200' Processor Data Book - PRELIMINARY"). - config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ int "Maximum transfer size (KB) per request (up to 128)" default "128" @@ -940,7 +932,7 @@ config BLK_DEV_Q40IDE config BLK_DEV_MPC8xx_IDE bool "MPC8xx IDE support" - depends on 8xx + depends on 8xx && IDE=y && BLK_DEV_IDE=y help This option provides support for IDE on Motorola MPC8xx Systems. Please see 'Type of MPC8xx IDE interface' for details. diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 9455e42abb2..d31117eb95a 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) */ spin_lock_irqsave(&ide_lock, flags); end_that_request_chunk(failed, 0, failed->data_len); - end_that_request_last(failed); + end_that_request_last(failed, 0); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1292,7 +1292,6 @@ static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) struct cdrom_info *info = drive->driver_data; info->dma = 0; - info->cmd = 0; info->start_seek = jiffies; return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation); } @@ -1344,8 +1343,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) (rq->nr_sectors & (sectors_per_frame - 1))) info->dma = 0; - info->cmd = READ; - /* Start sending the read request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); } @@ -1484,7 +1481,6 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) struct cdrom_info *info = drive->driver_data; info->dma = 0; - info->cmd = 0; rq->flags &= ~REQ_FAILED; len = rq->data_len; @@ -1739,7 +1735,7 @@ end_request: spin_lock_irqsave(&ide_lock, flags); blkdev_dequeue_request(rq); - end_that_request_last(rq); + end_that_request_last(rq, 1); HWGROUP(drive)->rq = NULL; spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; @@ -1891,7 +1887,6 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) /* use dma, if possible. we don't need to check more, since we * know that the transfer is always (at least!) frame aligned */ info->dma = drive->using_dma ? 1 : 0; - info->cmd = WRITE; info->devinfo.media_written = 1; @@ -1916,7 +1911,6 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) rq->flags |= REQ_QUIET; info->dma = 0; - info->cmd = 0; /* * sg request @@ -1925,7 +1919,6 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) int mask = drive->queue->dma_alignment; unsigned long addr = (unsigned long) page_address(bio_page(rq->bio)); - info->cmd = rq_data_dir(rq); info->dma = drive->using_dma; /* @@ -3516,6 +3509,7 @@ static int __init ide_cdrom_init(void) return driver_register(&ide_cdrom_driver.gen_driver); } +MODULE_ALIAS("ide:*m-cdrom*"); module_init(ide_cdrom_init); module_exit(ide_cdrom_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 7ca3e5afc66..ad1f2ed14a3 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -480,7 +480,6 @@ struct cdrom_info { struct request request_sense_request; int dma; - int cmd; unsigned long last_block; unsigned long start_seek; /* Buffer to hold mechanism status and changer slot table. */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f4e3d3527b0..4b441720b6b 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -681,50 +681,9 @@ static ide_proc_entry_t idedisk_proc[] = { #endif /* CONFIG_PROC_FS */ -static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq) +static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) { ide_drive_t *drive = q->queuedata; - struct request *rq = flush_rq->end_io_data; - int good_sectors = rq->hard_nr_sectors; - int bad_sectors; - sector_t sector; - - if (flush_rq->errors & ABRT_ERR) { - printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name); - blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE); - blk_queue_issue_flush_fn(drive->queue, NULL); - good_sectors = 0; - } else if (flush_rq->errors) { - good_sectors = 0; - if (blk_barrier_preflush(rq)) { - sector = ide_get_error_location(drive,flush_rq->buffer); - if ((sector >= rq->hard_sector) && - (sector < rq->hard_sector + rq->hard_nr_sectors)) - good_sectors = sector - rq->hard_sector; - } - } - - if (flush_rq->errors) - printk(KERN_ERR "%s: failed barrier write: " - "sector=%Lx(good=%d/bad=%d)\n", - drive->name, (unsigned long long)rq->sector, - good_sectors, - (int) (rq->hard_nr_sectors-good_sectors)); - - bad_sectors = rq->hard_nr_sectors - good_sectors; - - if (good_sectors) - __ide_end_request(drive, rq, 1, good_sectors); - if (bad_sectors) - __ide_end_request(drive, rq, 0, bad_sectors); -} - -static int idedisk_prepare_flush(request_queue_t *q, struct request *rq) -{ - ide_drive_t *drive = q->queuedata; - - if (!drive->wcache) - return 0; memset(rq->cmd, 0, sizeof(rq->cmd)); @@ -735,9 +694,8 @@ static int idedisk_prepare_flush(request_queue_t *q, struct request *rq) rq->cmd[0] = WIN_FLUSH_CACHE; - rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER; + rq->flags |= REQ_DRIVE_TASK; rq->buffer = rq->cmd; - return 1; } static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, @@ -794,27 +752,64 @@ static int set_nowerr(ide_drive_t *drive, int arg) return 0; } +static void update_ordered(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + unsigned ordered = QUEUE_ORDERED_NONE; + prepare_flush_fn *prep_fn = NULL; + issue_flush_fn *issue_fn = NULL; + + if (drive->wcache) { + unsigned long long capacity; + int barrier; + /* + * We must avoid issuing commands a drive does not + * understand or we may crash it. We check flush cache + * is supported. We also check we have the LBA48 flush + * cache if the drive capacity is too large. By this + * time we have trimmed the drive capacity if LBA48 is + * not available so we don't need to recheck that. + */ + capacity = idedisk_capacity(drive); + barrier = ide_id_has_flush_cache(id) && + (drive->addressing == 0 || capacity <= (1ULL << 28) || + ide_id_has_flush_cache_ext(id)); + + printk(KERN_INFO "%s: cache flushes %ssupported\n", + drive->name, barrier ? "" : "not"); + + if (barrier) { + ordered = QUEUE_ORDERED_DRAIN_FLUSH; + prep_fn = idedisk_prepare_flush; + issue_fn = idedisk_issue_flush; + } + } else + ordered = QUEUE_ORDERED_DRAIN; + + blk_queue_ordered(drive->queue, ordered, prep_fn); + blk_queue_issue_flush_fn(drive->queue, issue_fn); +} + static int write_cache(ide_drive_t *drive, int arg) { ide_task_t args; - int err; - - if (!ide_id_has_flush_cache(drive->id)) - return 1; + int err = 1; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? + if (ide_id_has_flush_cache(drive->id)) { + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = IDE_DRIVE_TASK_NO_DATA; + args.handler = &task_no_data_intr; + err = ide_raw_taskfile(drive, &args, NULL); + if (err == 0) + drive->wcache = arg; + } - err = ide_raw_taskfile(drive, &args, NULL); - if (err) - return err; + update_ordered(drive); - drive->wcache = arg; - return 0; + return err; } static int do_idedisk_flushcache (ide_drive_t *drive) @@ -888,7 +883,6 @@ static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; unsigned long long capacity; - int barrier; idedisk_add_settings(drive); @@ -992,31 +986,6 @@ static void idedisk_setup (ide_drive_t *drive) drive->wcache = 1; write_cache(drive, 1); - - /* - * We must avoid issuing commands a drive does not understand - * or we may crash it. We check flush cache is supported. We also - * check we have the LBA48 flush cache if the drive capacity is - * too large. By this time we have trimmed the drive capacity if - * LBA48 is not available so we don't need to recheck that. - */ - barrier = 0; - if (ide_id_has_flush_cache(id)) - barrier = 1; - if (drive->addressing == 1) { - /* Can't issue the correct flush ? */ - if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id)) - barrier = 0; - } - - printk(KERN_INFO "%s: cache flushes %ssupported\n", - drive->name, barrier ? "" : "not "); - if (barrier) { - blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH); - drive->queue->prepare_flush_fn = idedisk_prepare_flush; - drive->queue->end_flush_fn = idedisk_end_flush; - blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush); - } } static void ide_cacheflush_p(ide_drive_t *drive) @@ -1034,12 +1003,12 @@ static int ide_disk_remove(struct device *dev) struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; - ide_cacheflush_p(drive); - ide_unregister_subdriver(drive, idkp->driver); del_gendisk(g); + ide_cacheflush_p(drive); + ide_disk_put(idkp); return 0; @@ -1271,6 +1240,7 @@ static int __init idedisk_init(void) return driver_register(&idedisk_driver.gen_driver); } +MODULE_ALIAS("ide:*m-disk*"); module_init(idedisk_init); module_exit(idedisk_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 1e1531334c2..0523da77425 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -90,11 +90,6 @@ #include <asm/io.h> #include <asm/irq.h> -struct drive_list_entry { - const char *id_model; - const char *id_firmware; -}; - static const struct drive_list_entry drive_whitelist [] = { { "Micropolis 2112A" , "ALL" }, @@ -139,7 +134,7 @@ static const struct drive_list_entry drive_blacklist [] = { }; /** - * in_drive_list - look for drive in black/white list + * ide_in_drive_list - look for drive in black/white list * @id: drive identifier * @drive_table: list to inspect * @@ -147,7 +142,7 @@ static const struct drive_list_entry drive_blacklist [] = { * Returns 1 if the drive is found in the table. */ -static int in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) +int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) { for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && @@ -157,6 +152,8 @@ static int in_drive_list(struct hd_driveid *id, const struct drive_list_entry *d return 0; } +EXPORT_SYMBOL_GPL(ide_in_drive_list); + /** * ide_dma_intr - IDE DMA interrupt handler * @drive: the drive the interrupt is for @@ -663,7 +660,7 @@ int __ide_dma_bad_drive (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - int blacklist = in_drive_list(id, drive_blacklist); + int blacklist = ide_in_drive_list(id, drive_blacklist); if (blacklist) { printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n", drive->name, id->model); @@ -677,7 +674,7 @@ EXPORT_SYMBOL(__ide_dma_bad_drive); int __ide_dma_good_drive (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - return in_drive_list(id, drive_whitelist); + return ide_in_drive_list(id, drive_whitelist); } EXPORT_SYMBOL(__ide_dma_good_drive); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 9e293c8063d..fba3fffc2d6 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -2197,6 +2197,7 @@ static int __init idefloppy_init(void) return driver_register(&idefloppy_driver.gen_driver); } +MODULE_ALIAS("ide:*m-floppy*"); module_init(idefloppy_init); module_exit(idefloppy_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ecfafcdafea..b5dc6df8e67 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -89,7 +89,7 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); + end_that_request_last(rq, uptodate); ret = 0; } return ret; @@ -119,10 +119,7 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) if (!nr_sectors) nr_sectors = rq->hard_cur_sectors; - if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors)) - ret = rq->nr_sectors != 0; - else - ret = __ide_end_request(drive, rq, uptodate, nr_sectors); + ret = __ide_end_request(drive, rq, uptodate, nr_sectors); spin_unlock_irqrestore(&ide_lock, flags); return ret; @@ -247,7 +244,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) } blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); + end_that_request_last(rq, 1); spin_unlock_irqrestore(&ide_lock, flags); } @@ -379,7 +376,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; rq->errors = err; - end_that_request_last(rq); + end_that_request_last(rq, !rq->errors); spin_unlock_irqrestore(&ide_lock, flags); } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7d7944ed415..fab9b2b0250 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4947,6 +4947,7 @@ out: return error; } +MODULE_ALIAS("ide:*m-tape*"); module_init(idetape_init); module_exit(idetape_exit); MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8af179b531c..4b524f6b3ec 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1904,9 +1904,69 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv) return 1; } +static char *media_string(ide_drive_t *drive) +{ + switch (drive->media) { + case ide_disk: + return "disk"; + case ide_cdrom: + return "cdrom"; + case ide_tape: + return "tape"; + case ide_floppy: + return "floppy"; + default: + return "UNKNOWN"; + } +} + +static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", media_string(drive)); +} + +static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->name); +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "ide:m-%s\n", media_string(drive)); +} + +static struct device_attribute ide_dev_attrs[] = { + __ATTR_RO(media), + __ATTR_RO(drivename), + __ATTR_RO(modalias), + __ATTR_NULL +}; + +static int ide_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + ide_drive_t *drive = to_ide_device(dev); + int i = 0; + int length = 0; + + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MEDIA=%s", media_string(drive)); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "DRIVENAME=%s", drive->name); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MODALIAS=ide:m-%s", media_string(drive)); + envp[i] = NULL; + return 0; +} + struct bus_type ide_bus_type = { .name = "ide", .match = ide_bus_match, + .uevent = ide_uevent, + .dev_attrs = ide_dev_attrs, .suspend = generic_ide_suspend, .resume = generic_ide_resume, }; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index ef79805218e..4c2af902090 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -88,15 +88,12 @@ typedef struct ide_info_t { } ide_info_t; static void ide_release(dev_link_t *); -static int ide_event(event_t event, int priority, - event_callback_args_t *args); +static void ide_config(dev_link_t *); + +static void ide_detach(struct pcmcia_device *p_dev); -static dev_info_t dev_info = "ide-cs"; -static dev_link_t *ide_attach(void); -static void ide_detach(dev_link_t *); -static dev_link_t *dev_list = NULL; /*====================================================================== @@ -106,18 +103,17 @@ static dev_link_t *dev_list = NULL; ======================================================================*/ -static dev_link_t *ide_attach(void) +static int ide_attach(struct pcmcia_device *p_dev) { ide_info_t *info; dev_link_t *link; - client_reg_t client_reg; - int ret; - + DEBUG(0, "ide_attach()\n"); /* Create new ide device */ info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) return NULL; + if (!info) + return -ENOMEM; link = &info->link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -128,21 +124,14 @@ static dev_link_t *ide_attach(void) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = pcmcia_register_client(&link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - ide_detach(link); - return NULL; - } - - return link; + + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ide_config(link); + + return 0; } /* ide_attach */ /*====================================================================== @@ -154,32 +143,16 @@ static dev_link_t *ide_attach(void) ======================================================================*/ -static void ide_detach(dev_link_t *link) +static void ide_detach(struct pcmcia_device *p_dev) { - dev_link_t **linkp; - int ret; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "ide_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; if (link->state & DEV_CONFIG) ide_release(link); - - if (link->handle) { - ret = pcmcia_deregister_client(link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink, free device structure */ - *linkp = link->next; + kfree(link->priv); - } /* ide_detach */ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) @@ -406,6 +379,28 @@ void ide_release(dev_link_t *link) } /* ide_release */ +static int ide_suspend(struct pcmcia_device *dev) +{ + dev_link_t *link = dev_to_instance(dev); + + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + + return 0; +} + +static int ide_resume(struct pcmcia_device *dev) +{ + dev_link_t *link = dev_to_instance(dev); + + link->state &= ~DEV_SUSPEND; + if (DEV_OK(link)) + pcmcia_request_configuration(link->handle, &link->conf); + + return 0; +} + /*====================================================================== The card status event handler. Mostly, this schedules other @@ -415,48 +410,15 @@ void ide_release(dev_link_t *link) ======================================================================*/ -int ide_event(event_t event, int priority, - event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - - DEBUG(1, "ide_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - ide_release(link); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ide_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - break; - } - return 0; -} /* ide_event */ - static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_FUNC_ID(4), + PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ + PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */ PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), @@ -471,6 +433,8 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), + PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), + PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), @@ -494,10 +458,11 @@ static struct pcmcia_driver ide_cs_driver = { .drv = { .name = "ide-cs", }, - .attach = ide_attach, - .event = ide_event, - .detach = ide_detach, + .probe = ide_attach, + .remove = ide_detach, .id_table = ide_ids, + .suspend = ide_suspend, + .resume = ide_resume, }; static int __init init_ide_cs(void) @@ -508,7 +473,6 @@ static int __init init_ide_cs(void) static void __exit exit_ide_cs(void) { pcmcia_unregister_driver(&ide_cs_driver); - BUG_ON(dev_list != NULL); } late_initcall(init_ide_cs); diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile index 578e52a5958..677c7b2bac9 100644 --- a/drivers/ide/mips/Makefile +++ b/drivers/ide/mips/Makefile @@ -1 +1,4 @@ obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o +obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o + +EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 2b6327c576b..32431dcf5d8 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -31,865 +31,638 @@ */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ -#include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/hdreg.h> +#include <linux/platform_device.h> + #include <linux/init.h> #include <linux/ide.h> #include <linux/sysdev.h> #include <linux/dma-mapping.h> +#include "ide-timing.h" + #include <asm/io.h> #include <asm/mach-au1x00/au1xxx.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> -#if CONFIG_PM -#include <asm/mach-au1x00/au1xxx_pm.h> -#endif - #include <asm/mach-au1x00/au1xxx_ide.h> #define DRV_NAME "au1200-ide" #define DRV_VERSION "1.0" -#define DRV_AUTHOR "AMD PCS / Pete Popov <ppopov@embeddedalley.com>" -#define DRV_DESC "Au1200 IDE" - -static _auide_hwif auide_hwif; -static spinlock_t ide_tune_drive_spin_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t ide_tune_chipset_spin_lock = SPIN_LOCK_UNLOCKED; -static int dbdma_init_done = 0; - -/* - * local I/O functions - */ -u8 auide_inb(unsigned long port) -{ - return (au_readb(port)); -} +#define DRV_AUTHOR "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>" -u16 auide_inw(unsigned long port) -{ - return (au_readw(port)); -} +/* enable the burstmode in the dbdma */ +#define IDE_AU1XXX_BURSTMODE 1 -u32 auide_inl(unsigned long port) -{ - return (au_readl(port)); -} +static _auide_hwif auide_hwif; +static int dbdma_init_done; -void auide_insw(unsigned long port, void *addr, u32 count) -{ #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, - DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->rx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -#else - while (count--) - { - *(u16 *)addr = au_readw(port); - addr +=2 ; - } -#endif -} - -void auide_insl(unsigned long port, void *addr, u32 count) -{ - while (count--) - { - *(u32 *)addr = au_readl(port); - /* NOTE: For IDE interfaces over PCMCIA, - * 32-bit access does not work - */ - addr += 4; - } -} - -void auide_outb(u8 addr, unsigned long port) +void auide_insw(unsigned long port, void *addr, u32 count) { - return (au_writeb(addr, port)); -} + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; -void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port) -{ - return (au_writeb(addr, port)); + if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, + DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->rx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); } -void auide_outw(u16 addr, unsigned long port) +void auide_outsw(unsigned long port, void *addr, u32 count) { - return (au_writew(addr, port)); -} + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; -void auide_outl(u32 addr, unsigned long port) -{ - return (au_writel(addr, port)); + if(!put_source_flags(ahwif->tx_chan, (void*)addr, + count << 1, DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->tx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); } -void auide_outsw(unsigned long port, void *addr, u32 count) -{ -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_source_flags(ahwif->tx_chan, (void*)addr, - count << 1, DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->tx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -#else - while (count--) - { - au_writew(*(u16 *)addr, port); - addr += 2; - } #endif -} - -void auide_outsl(unsigned long port, void *addr, u32 count) -{ - while (count--) - { - au_writel(*(u32 *)addr, port); - /* NOTE: For IDE interfaces over PCMCIA, - * 32-bit access does not work - */ - addr += 4; - } -} static void auide_tune_drive(ide_drive_t *drive, byte pio) { - int mem_sttime; - int mem_stcfg; - unsigned long flags; - u8 speed; - - /* get the best pio mode for the drive */ - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - - printk("%s: setting Au1XXX IDE to PIO mode%d\n", - drive->name, pio); - - spin_lock_irqsave(&ide_tune_drive_spin_lock, flags); - - mem_sttime = 0; - mem_stcfg = au_readl(MEM_STCFG2); - - /* set pio mode! */ - switch(pio) { - case 0: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO0_TWCS - | SBC_IDE_PIO0_TCSH - | SBC_IDE_PIO0_TCSOFF - | SBC_IDE_PIO0_TWP - | SBC_IDE_PIO0_TCSW - | SBC_IDE_PIO0_TPM - | SBC_IDE_PIO0_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); - break; - - case 1: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO1_TWCS - | SBC_IDE_PIO1_TCSH - | SBC_IDE_PIO1_TCSOFF - | SBC_IDE_PIO1_TWP - | SBC_IDE_PIO1_TCSW - | SBC_IDE_PIO1_TPM - | SBC_IDE_PIO1_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; - break; - - case 2: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO2_TWCS - | SBC_IDE_PIO2_TCSH - | SBC_IDE_PIO2_TCSOFF - | SBC_IDE_PIO2_TWP - | SBC_IDE_PIO2_TCSW - | SBC_IDE_PIO2_TPM - | SBC_IDE_PIO2_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; - break; - - case 3: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO3_TWCS - | SBC_IDE_PIO3_TCSH - | SBC_IDE_PIO3_TCSOFF - | SBC_IDE_PIO3_TWP - | SBC_IDE_PIO3_TCSW - | SBC_IDE_PIO3_TPM - | SBC_IDE_PIO3_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; - - break; - - case 4: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO4_TWCS - | SBC_IDE_PIO4_TCSH - | SBC_IDE_PIO4_TCSOFF - | SBC_IDE_PIO4_TWP - | SBC_IDE_PIO4_TCSW - | SBC_IDE_PIO4_TPM - | SBC_IDE_PIO4_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; - break; - } - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); - - spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags); - - speed = pio + XFER_PIO_0; - ide_config_drive_speed(drive, speed); + int mem_sttime; + int mem_stcfg; + u8 speed; + + /* get the best pio mode for the drive */ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + + printk(KERN_INFO "%s: setting Au1XXX IDE to PIO mode%d\n", + drive->name, pio); + + mem_sttime = 0; + mem_stcfg = au_readl(MEM_STCFG2); + + /* set pio mode! */ + switch(pio) { + case 0: + mem_sttime = SBC_IDE_TIMING(PIO0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; + break; + + case 1: + mem_sttime = SBC_IDE_TIMING(PIO1); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; + break; + + case 2: + mem_sttime = SBC_IDE_TIMING(PIO2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; + break; + + case 3: + mem_sttime = SBC_IDE_TIMING(PIO3); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; + + break; + + case 4: + mem_sttime = SBC_IDE_TIMING(PIO4); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; + break; + } + + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); + + speed = pio + XFER_PIO_0; + ide_config_drive_speed(drive, speed); } static int auide_tune_chipset (ide_drive_t *drive, u8 speed) { - u8 mode = 0; - int mem_sttime; - int mem_stcfg; - unsigned long flags; + int mem_sttime; + int mem_stcfg; + unsigned long mode; + #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - struct hd_driveid *id = drive->id; - - /* - * Now see what the current drive is capable of, - * selecting UDMA only if the mate said it was ok. - */ - if (id && (id->capability & 1) && drive->autodma && - !__ide_dma_bad_drive(drive)) { - if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { - if (id->dma_mword & 4) - mode = XFER_MW_DMA_2; - else if (id->dma_mword & 2) - mode = XFER_MW_DMA_1; - else if (id->dma_mword & 1) - mode = XFER_MW_DMA_0; - } - } + if (ide_use_dma(drive)) + mode = ide_dma_speed(drive, 0); #endif - spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags); + mem_sttime = 0; + mem_stcfg = au_readl(MEM_STCFG2); - mem_sttime = 0; - mem_stcfg = au_readl(MEM_STCFG2); - - switch(speed) { - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - auide_tune_drive(drive, (speed - XFER_PIO_0)); - break; + if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) { + auide_tune_drive(drive, speed - XFER_PIO_0); + return 0; + } + + switch(speed) { #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - case XFER_MW_DMA_2: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA2_TWCS - | SBC_IDE_MDMA2_TCSH - | SBC_IDE_MDMA2_TCSOFF - | SBC_IDE_MDMA2_TWP - | SBC_IDE_MDMA2_TCSW - | SBC_IDE_MDMA2_TPM - | SBC_IDE_MDMA2_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; - - mode = XFER_MW_DMA_2; - break; - case XFER_MW_DMA_1: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA1_TWCS - | SBC_IDE_MDMA1_TCSH - | SBC_IDE_MDMA1_TCSOFF - | SBC_IDE_MDMA1_TWP - | SBC_IDE_MDMA1_TCSW - | SBC_IDE_MDMA1_TPM - | SBC_IDE_MDMA1_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; - - mode = XFER_MW_DMA_1; - break; - case XFER_MW_DMA_0: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA0_TWCS - | SBC_IDE_MDMA0_TCSH - | SBC_IDE_MDMA0_TCSOFF - | SBC_IDE_MDMA0_TWP - | SBC_IDE_MDMA0_TCSW - | SBC_IDE_MDMA0_TPM - | SBC_IDE_MDMA0_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; - - mode = XFER_MW_DMA_0; - break; + case XFER_MW_DMA_2: + mem_sttime = SBC_IDE_TIMING(MDMA2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; + + mode = XFER_MW_DMA_2; + break; + case XFER_MW_DMA_1: + mem_sttime = SBC_IDE_TIMING(MDMA1); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; + + mode = XFER_MW_DMA_1; + break; + case XFER_MW_DMA_0: + mem_sttime = SBC_IDE_TIMING(MDMA0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; + + mode = XFER_MW_DMA_0; + break; #endif - default: - return 1; - } - - /* - * Tell the drive to switch to the new mode; abort on failure. - */ - if (!mode || ide_config_drive_speed(drive, mode)) - { - return 1; /* failure */ - } - - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); + default: + return 1; + } + + if (ide_config_drive_speed(drive, mode)) + return 1; - spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags); + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); - return 0; + return 0; } /* * Multi-Word DMA + DbDMA functions */ -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -static int in_drive_list(struct hd_driveid *id, - const 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; -} +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA static int auide_build_sglist(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = drive->hwif; - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - struct scatterlist *sg = hwif->sg_table; + ide_hwif_t *hwif = drive->hwif; + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + struct scatterlist *sg = hwif->sg_table; - ide_map_sg(drive, rq); + ide_map_sg(drive, rq); - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; + if (rq_data_dir(rq) == READ) + hwif->sg_dma_direction = DMA_FROM_DEVICE; + else + hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, + hwif->sg_dma_direction); } static int auide_build_dmatable(ide_drive_t *drive) { - int i, iswrite, count = 0; - ide_hwif_t *hwif = HWIF(drive); - - struct request *rq = HWGROUP(drive)->rq; - - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - struct scatterlist *sg; - - iswrite = (rq_data_dir(rq) == WRITE); - /* Save for interrupt context */ - ahwif->drive = drive; - - /* Build sglist */ - hwif->sg_nents = i = auide_build_sglist(drive, rq); - - if (!i) - return 0; - - /* fill the descriptors */ - sg = hwif->sg_table; - while (i && sg_dma_len(sg)) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - u32 flags = DDMA_FLAGS_NOIE; - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (++count >= PRD_ENTRIES) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - goto use_pio_instead; - } - - /* Lets enable intr for the last descriptor only */ - if (1==i) - flags = DDMA_FLAGS_IE; - else - flags = DDMA_FLAGS_NOIE; - - if (iswrite) { - if(!put_source_flags(ahwif->tx_chan, - (void*)(page_address(sg->page) - + sg->offset), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + int i, iswrite, count = 0; + ide_hwif_t *hwif = HWIF(drive); + + struct request *rq = HWGROUP(drive)->rq; + + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + struct scatterlist *sg; + + iswrite = (rq_data_dir(rq) == WRITE); + /* Save for interrupt context */ + ahwif->drive = drive; + + /* Build sglist */ + hwif->sg_nents = i = auide_build_sglist(drive, rq); + + if (!i) + return 0; + + /* fill the descriptors */ + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + u32 flags = DDMA_FLAGS_NOIE; + unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; + + if (++count >= PRD_ENTRIES) { + printk(KERN_WARNING "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } + + /* Lets enable intr for the last descriptor only */ + if (1==i) + flags = DDMA_FLAGS_IE; + else + flags = DDMA_FLAGS_NOIE; + + if (iswrite) { + if(!put_source_flags(ahwif->tx_chan, + (void*)(page_address(sg->page) + + sg->offset), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __FUNCTION__, __LINE__); } - } else + } else { - if(!put_dest_flags(ahwif->rx_chan, - (void*)(page_address(sg->page) - + sg->offset), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + if(!put_dest_flags(ahwif->rx_chan, + (void*)(page_address(sg->page) + + sg->offset), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __FUNCTION__, __LINE__); } - } + } - cur_addr += tc; - cur_len -= tc; - } - sg++; - i--; - } + cur_addr += tc; + cur_len -= tc; + } + sg++; + i--; + } - if (count) - return 1; + if (count) + return 1; -use_pio_instead: - dma_unmap_sg(ahwif->dev, - hwif->sg_table, - hwif->sg_nents, - hwif->sg_dma_direction); + use_pio_instead: + dma_unmap_sg(ahwif->dev, + hwif->sg_table, + hwif->sg_nents, + hwif->sg_dma_direction); - return 0; /* revert to PIO for this request */ + return 0; /* revert to PIO for this request */ } static int auide_dma_end(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + ide_hwif_t *hwif = HWIF(drive); + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - if (hwif->sg_nents) { - dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, - hwif->sg_dma_direction); - hwif->sg_nents = 0; - } + if (hwif->sg_nents) { + dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, + hwif->sg_dma_direction); + hwif->sg_nents = 0; + } - return 0; + return 0; } static void auide_dma_start(ide_drive_t *drive ) { -// printk("%s\n", __FUNCTION__); } -ide_startstop_t auide_dma_intr(ide_drive_t *drive) -{ - //printk("%s\n", __FUNCTION__); - - u8 stat = 0, dma_stat = 0; - - 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; - - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; - } - printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return ide_error(drive, "dma_intr", stat); -} static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - //printk("%s\n", __FUNCTION__); - - /* issue cmd to drive */ - ide_execute_command(drive, command, &auide_dma_intr, - (2*WAIT_CMD), NULL); + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, + (2*WAIT_CMD), NULL); } static int auide_dma_setup(ide_drive_t *drive) -{ -// printk("%s\n", __FUNCTION__); - - if (drive->media != ide_disk) - return 1; - - if (!auide_build_dmatable(drive)) - /* try PIO instead of DMA */ - return 1; +{ + struct request *rq = HWGROUP(drive)->rq; - drive->waiting_for_dma = 1; + if (!auide_build_dmatable(drive)) { + ide_map_sg(drive, rq); + return 1; + } - return 0; + drive->waiting_for_dma = 1; + return 0; } static int auide_dma_check(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); + u8 speed; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - if( !dbdma_init_done ){ - auide_hwif.white_list = in_drive_list(drive->id, - dma_white_list); - auide_hwif.black_list = in_drive_list(drive->id, - dma_black_list); - auide_hwif.drive = drive; - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; - } + + if( dbdma_init_done == 0 ){ + auide_hwif.white_list = ide_in_drive_list(drive->id, + dma_white_list); + auide_hwif.black_list = ide_in_drive_list(drive->id, + dma_black_list); + auide_hwif.drive = drive; + auide_ddma_init(&auide_hwif); + dbdma_init_done = 1; + } #endif - /* Is the drive in our DMA black list? */ - if ( auide_hwif.black_list ) { - drive->using_dma = 0; - printk("%s found in dma_blacklist[]! Disabling DMA.\n", - drive->id->model); - } - else - drive->using_dma = 1; + /* Is the drive in our DMA black list? */ + + if ( auide_hwif.black_list ) { + drive->using_dma = 0; + + /* Borrowed the warning message from ide-dma.c */ - return HWIF(drive)->ide_dma_host_on(drive); + printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n", + drive->name, drive->id->model); + } + else + drive->using_dma = 1; + + speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA); + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + + return HWIF(drive)->ide_dma_off_quietly(drive); } static int auide_dma_test_irq(ide_drive_t *drive) -{ -// printk("%s\n", __FUNCTION__); - - if (!drive->waiting_for_dma) - printk(KERN_WARNING "%s: ide_dma_test_irq \ +{ + if (drive->waiting_for_dma == 0) + printk(KERN_WARNING "%s: ide_dma_test_irq \ called while not waiting\n", drive->name); - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "%s: timeout waiting for ddma to \ + drive->waiting_for_dma++; + if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { + printk(KERN_WARNING "%s: timeout waiting for ddma to \ complete\n", drive->name); - return 1; - } - udelay(10); - return 0; + return 1; + } + udelay(10); + return 0; } static int auide_dma_host_on(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - return 0; + return 0; } static int auide_dma_on(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - drive->using_dma = 1; - return auide_dma_host_on(drive); + drive->using_dma = 1; + return auide_dma_host_on(drive); } static int auide_dma_host_off(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - return 0; + return 0; } static int auide_dma_off_quietly(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - drive->using_dma = 0; - return auide_dma_host_off(drive); + drive->using_dma = 0; + return auide_dma_host_off(drive); } static int auide_dma_lostirq(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - - printk(KERN_ERR "%s: IRQ lost\n", drive->name); - return 0; + printk(KERN_ERR "%s: IRQ lost\n", drive->name); + return 0; } static void auide_ddma_tx_callback(int irq, void *param, struct pt_regs *regs) { -// printk("%s\n", __FUNCTION__); - - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; - return; + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; } static void auide_ddma_rx_callback(int irq, void *param, struct pt_regs *regs) { -// printk("%s\n", __FUNCTION__); + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; +} + +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; - return; +static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) +{ + dev->dev_id = dev_id; + dev->dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; + dev->dev_intlevel = 0; + dev->dev_intpolarity = 0; + dev->dev_tsize = tsize; + dev->dev_devwidth = devwidth; + dev->dev_flags = flags; } + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) static int auide_dma_timeout(ide_drive_t *drive) { // printk("%s\n", __FUNCTION__); - printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); + printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); - if (HWIF(drive)->ide_dma_test_irq(drive)) - return 0; + if (HWIF(drive)->ide_dma_test_irq(drive)) + return 0; - return HWIF(drive)->ide_dma_end(drive); + return HWIF(drive)->ide_dma_end(drive); } -#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ + +static int auide_ddma_init(_auide_hwif *auide) { + + dbdev_tab_t source_dev_tab, target_dev_tab; + u32 dev_id, tsize, devwidth, flags; + ide_hwif_t *hwif = auide->hwif; -static int auide_ddma_init( _auide_hwif *auide ) -{ -// printk("%s\n", __FUNCTION__); + dev_id = AU1XXX_ATA_DDMA_REQ; - dbdev_tab_t source_dev_tab; -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - dbdev_tab_t target_dev_tab; - ide_hwif_t *hwif = auide->hwif; - char warning_output [2][80]; - int i; -#endif + if (auide->white_list || auide->black_list) { + tsize = 8; + devwidth = 32; + } + else { + tsize = 1; + devwidth = 16; + + printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model); + printk(KERN_ERR " please read 'Documentation/mips/AU1xxx_IDE.README'"); + } - /* Add our custom device to DDMA device table */ - /* Create our new device entries in the table */ -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - source_dev_tab.dev_id = AU1XXX_ATA_DDMA_REQ; - - if( auide->white_list || auide->black_list ){ - source_dev_tab.dev_tsize = 8; - source_dev_tab.dev_devwidth = 32; - source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - source_dev_tab.dev_intlevel = 0; - source_dev_tab.dev_intpolarity = 0; - - /* init device table for target - static bus controller - */ - target_dev_tab.dev_id = DSCR_CMD0_ALWAYS; - target_dev_tab.dev_tsize = 8; - target_dev_tab.dev_devwidth = 32; - target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - target_dev_tab.dev_intlevel = 0; - target_dev_tab.dev_intpolarity = 0; - target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE; - } - else{ - source_dev_tab.dev_tsize = 1; - source_dev_tab.dev_devwidth = 16; - source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - source_dev_tab.dev_intlevel = 0; - source_dev_tab.dev_intpolarity = 0; - - /* init device table for target - static bus controller - */ - target_dev_tab.dev_id = DSCR_CMD0_ALWAYS; - target_dev_tab.dev_tsize = 1; - target_dev_tab.dev_devwidth = 16; - target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - target_dev_tab.dev_intlevel = 0; - target_dev_tab.dev_intpolarity = 0; - target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE; - - sprintf(&warning_output[0][0], - "%s is not on ide driver white list.", - auide_hwif.drive->id->model); - for ( i=strlen(&warning_output[0][0]) ; i<76; i++ ){ - sprintf(&warning_output[0][i]," "); - } - - sprintf(&warning_output[1][0], - "To add %s please read 'Documentation/mips/AU1xxx_IDE.README'.", - auide_hwif.drive->id->model); - for ( i=strlen(&warning_output[1][0]) ; i<76; i++ ){ - sprintf(&warning_output[1][i]," "); - } - - printk("\n****************************************"); - printk("****************************************\n"); - printk("* %s *\n",&warning_output[0][0]); - printk("* Switch to safe MWDMA Mode! "); - printk(" *\n"); - printk("* %s *\n",&warning_output[1][0]); - printk("****************************************"); - printk("****************************************\n\n"); - } +#ifdef IDE_AU1XXX_BURSTMODE + flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; #else - source_dev_tab.dev_id = DSCR_CMD0_ALWAYS; - source_dev_tab.dev_tsize = 8; - source_dev_tab.dev_devwidth = 32; - source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - source_dev_tab.dev_intlevel = 0; - source_dev_tab.dev_intpolarity = 0; + flags = DEV_FLAGS_SYNC; #endif -#if CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON - /* set flags for tx channel */ - source_dev_tab.dev_flags = DEV_FLAGS_OUT - | DEV_FLAGS_SYNC - | DEV_FLAGS_BURSTABLE; - auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - /* set flags for rx channel */ - source_dev_tab.dev_flags = DEV_FLAGS_IN - | DEV_FLAGS_SYNC - | DEV_FLAGS_BURSTABLE; - auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + /* setup dev_tab for tx channel */ + auide_init_dbdma_dev( &source_dev_tab, + dev_id, + tsize, devwidth, DEV_FLAGS_OUT | flags); + auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + auide_init_dbdma_dev( &source_dev_tab, + dev_id, + tsize, devwidth, DEV_FLAGS_IN | flags); + auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + /* We also need to add a target device for the DMA */ + auide_init_dbdma_dev( &target_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + tsize, devwidth, DEV_FLAGS_ANYUSE); + auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); + + /* Get a channel for TX */ + auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id, + auide->tx_dev_id, + auide_ddma_tx_callback, + (void*)auide); + + /* Get a channel for RX */ + auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, + auide->target_dev_id, + auide_ddma_rx_callback, + (void*)auide); + + auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, + NUM_DESCRIPTORS); + auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, + NUM_DESCRIPTORS); + + hwif->dmatable_cpu = dma_alloc_coherent(auide->dev, + PRD_ENTRIES * PRD_BYTES, /* 1 Page */ + &hwif->dmatable_dma, GFP_KERNEL); + + au1xxx_dbdma_start( auide->tx_chan ); + au1xxx_dbdma_start( auide->rx_chan ); + + return 0; +} #else - /* set flags for tx channel */ - source_dev_tab.dev_flags = DEV_FLAGS_OUT | DEV_FLAGS_SYNC; - auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); - /* set flags for rx channel */ - source_dev_tab.dev_flags = DEV_FLAGS_IN | DEV_FLAGS_SYNC; - auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); -#endif + +static int auide_ddma_init( _auide_hwif *auide ) +{ + dbdev_tab_t source_dev_tab; + int flags; -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - - auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); - - /* Get a channel for TX */ - auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id, - auide->tx_dev_id, - auide_ddma_tx_callback, - (void*)auide); - /* Get a channel for RX */ - auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, - auide->target_dev_id, - auide_ddma_rx_callback, - (void*)auide); -#else /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */ - /* - * Note: if call back is not enabled, update ctp->cur_ptr manually - */ - auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, - auide->tx_dev_id, - NULL, - (void*)auide); - auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, - DSCR_CMD0_ALWAYS, - NULL, - (void*)auide); +#ifdef IDE_AU1XXX_BURSTMODE + flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; +#else + flags = DEV_FLAGS_SYNC; #endif - auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, - NUM_DESCRIPTORS); - auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, - NUM_DESCRIPTORS); -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - hwif->dmatable_cpu = dma_alloc_coherent(auide->dev, - PRD_ENTRIES * PRD_BYTES, /* 1 Page */ - &hwif->dmatable_dma, GFP_KERNEL); - - auide->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL|GFP_DMA); - if (auide->sg_table == NULL) { - return -ENOMEM; - } -#endif - au1xxx_dbdma_start( auide->tx_chan ); - au1xxx_dbdma_start( auide->rx_chan ); - return 0; + /* setup dev_tab for tx channel */ + auide_init_dbdma_dev( &source_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + 8, 32, DEV_FLAGS_OUT | flags); + auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + auide_init_dbdma_dev( &source_dev_tab, + (u32)DSCR_CMD0_ALWAYS, + 8, 32, DEV_FLAGS_IN | flags); + auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); + + /* Get a channel for TX */ + auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, + auide->tx_dev_id, + NULL, + (void*)auide); + + /* Get a channel for RX */ + auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, + DSCR_CMD0_ALWAYS, + NULL, + (void*)auide); + + auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, + NUM_DESCRIPTORS); + auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, + NUM_DESCRIPTORS); + + au1xxx_dbdma_start( auide->tx_chan ); + au1xxx_dbdma_start( auide->rx_chan ); + + return 0; } +#endif static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) { - int i; -#define ide_ioreg_t unsigned long - ide_ioreg_t *ata_regs = hw->io_ports; - - /* fixme */ - for (i = 0; i < IDE_CONTROL_OFFSET; i++) { - *ata_regs++ = (ide_ioreg_t) ahwif->regbase - + (ide_ioreg_t)(i << AU1XXX_ATA_REG_OFFSET); - } - - /* set the Alternative Status register */ - *ata_regs = (ide_ioreg_t) ahwif->regbase - + (ide_ioreg_t)(14 << AU1XXX_ATA_REG_OFFSET); + int i; + unsigned long *ata_regs = hw->io_ports; + + /* FIXME? */ + for (i = 0; i < IDE_CONTROL_OFFSET; i++) { + *ata_regs++ = ahwif->regbase + (i << AU1XXX_ATA_REG_OFFSET); + } + + /* set the Alternative Status register */ + *ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET); } static int au_ide_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - _auide_hwif *ahwif = &auide_hwif; - ide_hwif_t *hwif; + _auide_hwif *ahwif = &auide_hwif; + ide_hwif_t *hwif; struct resource *res; int ret = 0; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - char *mode = "MWDMA2"; + char *mode = "MWDMA2"; #elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - char *mode = "PIO+DDMA(offload)"; + char *mode = "PIO+DDMA(offload)"; #endif - memset(&auide_hwif, 0, sizeof(_auide_hwif)); - auide_hwif.dev = 0; + memset(&auide_hwif, 0, sizeof(_auide_hwif)); + auide_hwif.dev = 0; ahwif->dev = dev; ahwif->irq = platform_get_irq(pdev, 0); @@ -902,11 +675,11 @@ static int au_ide_probe(struct device *dev) goto out; } - if (!request_mem_region (res->start, res->end-res->start, pdev->name)) { + if (!request_mem_region (res->start, res->end-res->start, pdev->name)) { pr_debug("%s: request_mem_region failed\n", DRV_NAME); - ret = -EBUSY; + ret = -EBUSY; goto out; - } + } ahwif->regbase = (u32)ioremap(res->start, res->end-res->start); if (ahwif->regbase == 0) { @@ -914,130 +687,92 @@ static int au_ide_probe(struct device *dev) goto out; } - hwif = &ide_hwifs[pdev->id]; + /* FIXME: This might possibly break PCMCIA IDE devices */ + + hwif = &ide_hwifs[pdev->id]; hw_regs_t *hw = &hwif->hw; - hwif->irq = hw->irq = ahwif->irq; - hwif->chipset = ide_au1xxx; + hwif->irq = hw->irq = ahwif->irq; + hwif->chipset = ide_au1xxx; - auide_setup_ports(hw, ahwif); + auide_setup_ports(hw, ahwif); memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - hwif->rqsize = CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ; - hwif->rqsize = ((hwif->rqsize > AU1XXX_ATA_RQSIZE) - || (hwif->rqsize < 32)) ? AU1XXX_ATA_RQSIZE : hwif->rqsize; -#else /* if kernel config is not set */ - hwif->rqsize = AU1XXX_ATA_RQSIZE; -#endif - - hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ + hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */ - hwif->swdma_mask = 0x07; + hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */ + hwif->swdma_mask = 0x00; #else - hwif->mwdma_mask = 0x0; - hwif->swdma_mask = 0x0; + hwif->mwdma_mask = 0x0; + hwif->swdma_mask = 0x0; +#endif + + hwif->noprobe = 0; + hwif->drives[0].unmask = 1; + hwif->drives[1].unmask = 1; + + /* hold should be on in all cases */ + hwif->hold = 1; + hwif->mmio = 2; + + /* If the user has selected DDMA assisted copies, + then set up a few local I/O function entry points + */ + +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA + hwif->INSW = auide_insw; + hwif->OUTSW = auide_outsw; #endif - //hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - hwif->noprobe = 0; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; - - /* hold should be on in all cases */ - hwif->hold = 1; - hwif->mmio = 2; - - /* set up local I/O function entry points */ - hwif->INB = auide_inb; - hwif->INW = auide_inw; - hwif->INL = auide_inl; - hwif->INSW = auide_insw; - hwif->INSL = auide_insl; - hwif->OUTB = auide_outb; - hwif->OUTBSYNC = auide_outbsync; - hwif->OUTW = auide_outw; - hwif->OUTL = auide_outl; - hwif->OUTSW = auide_outsw; - hwif->OUTSL = auide_outsl; - - hwif->tuneproc = &auide_tune_drive; - hwif->speedproc = &auide_tune_chipset; + + hwif->tuneproc = &auide_tune_drive; + hwif->speedproc = &auide_tune_chipset; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->ide_dma_off_quietly = &auide_dma_off_quietly; - hwif->ide_dma_timeout = &auide_dma_timeout; - - hwif->ide_dma_check = &auide_dma_check; - hwif->dma_exec_cmd = &auide_dma_exec_cmd; - hwif->dma_start = &auide_dma_start; - hwif->ide_dma_end = &auide_dma_end; - hwif->dma_setup = &auide_dma_setup; - hwif->ide_dma_test_irq = &auide_dma_test_irq; - hwif->ide_dma_host_off = &auide_dma_host_off; - hwif->ide_dma_host_on = &auide_dma_host_on; - hwif->ide_dma_lostirq = &auide_dma_lostirq; - hwif->ide_dma_on = &auide_dma_on; - - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; - hwif->atapi_dma = 1; - hwif->drives[0].using_dma = 1; - hwif->drives[1].using_dma = 1; + hwif->ide_dma_off_quietly = &auide_dma_off_quietly; + hwif->ide_dma_timeout = &auide_dma_timeout; + + hwif->ide_dma_check = &auide_dma_check; + hwif->dma_exec_cmd = &auide_dma_exec_cmd; + hwif->dma_start = &auide_dma_start; + hwif->ide_dma_end = &auide_dma_end; + hwif->dma_setup = &auide_dma_setup; + hwif->ide_dma_test_irq = &auide_dma_test_irq; + hwif->ide_dma_host_off = &auide_dma_host_off; + hwif->ide_dma_host_on = &auide_dma_host_on; + hwif->ide_dma_lostirq = &auide_dma_lostirq; + hwif->ide_dma_on = &auide_dma_on; + + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + hwif->atapi_dma = 1; + #else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ - hwif->autodma = 0; - hwif->channel = 0; - hwif->hold = 1; - hwif->select_data = 0; /* no chipset-specific code */ - hwif->config_data = 0; /* no chipset-specific code */ - - hwif->drives[0].autodma = 0; - hwif->drives[0].drive_data = 0; /* no drive data */ - hwif->drives[0].using_dma = 0; - hwif->drives[0].waiting_for_dma = 0; - hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ - /* secondary hdd not supported */ - hwif->drives[1].autodma = 0; - - hwif->drives[1].drive_data = 0; - hwif->drives[1].using_dma = 0; - hwif->drives[1].waiting_for_dma = 0; - hwif->drives[1].autotune = 2; /* 1=autotune, 2=noautotune, 0=default */ -#endif - hwif->drives[0].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ - hwif->drives[1].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ - - /*Register Driver with PM Framework*/ -#ifdef CONFIG_PM - auide_hwif.pm.lock = SPIN_LOCK_UNLOCKED; - auide_hwif.pm.stopped = 0; - - auide_hwif.pm.dev = new_au1xxx_power_device( "ide", - &au1200ide_pm_callback, - NULL); - if ( auide_hwif.pm.dev == NULL ) - printk(KERN_INFO "Unable to create a power management \ - device entry for the au1200-IDE.\n"); - else - printk(KERN_INFO "Power management device entry for the \ - au1200-IDE loaded.\n"); + hwif->autodma = 0; + hwif->channel = 0; + hwif->hold = 1; + hwif->select_data = 0; /* no chipset-specific code */ + hwif->config_data = 0; /* no chipset-specific code */ + + hwif->drives[0].autodma = 0; + hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ #endif + hwif->drives[0].no_io_32bit = 1; - auide_hwif.hwif = hwif; - hwif->hwif_data = &auide_hwif; + auide_hwif.hwif = hwif; + hwif->hwif_data = &auide_hwif; -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA + auide_ddma_init(&auide_hwif); + dbdma_init_done = 1; #endif probe_hwif_init(hwif); dev_set_drvdata(dev, hwif); - printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); + printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); -out: - return ret; + out: + return ret; } static int au_ide_remove(struct device *dev) @@ -1045,7 +780,7 @@ static int au_ide_remove(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct resource *res; ide_hwif_t *hwif = dev_get_drvdata(dev); - _auide_hwif *ahwif = &auide_hwif; + _auide_hwif *ahwif = &auide_hwif; ide_unregister(hwif - ide_hwifs); @@ -1069,180 +804,11 @@ static int __init au_ide_init(void) return driver_register(&au1200_ide_driver); } -static void __init au_ide_exit(void) +static void __exit au_ide_exit(void) { driver_unregister(&au1200_ide_driver); } -#ifdef CONFIG_PM -int au1200ide_pm_callback( au1xxx_power_dev_t *dev,\ - au1xxx_request_t request, void *data) { - - unsigned int d, err = 0; - unsigned long flags; - - spin_lock_irqsave(auide_hwif.pm.lock, flags); - - switch (request){ - case AU1XXX_PM_SLEEP: - err = au1xxxide_pm_sleep(dev); - break; - case AU1XXX_PM_WAKEUP: - d = *((unsigned int*)data); - if ( d > 0 && d <= 99) { - err = au1xxxide_pm_standby(dev); - } - else { - err = au1xxxide_pm_resume(dev); - } - break; - case AU1XXX_PM_GETSTATUS: - err = au1xxxide_pm_getstatus(dev); - break; - case AU1XXX_PM_ACCESS: - err = au1xxxide_pm_access(dev); - break; - case AU1XXX_PM_IDLE: - err = au1xxxide_pm_idle(dev); - break; - case AU1XXX_PM_CLEANUP: - err = au1xxxide_pm_cleanup(dev); - break; - default: - err = -1; - break; - } - - spin_unlock_irqrestore(auide_hwif.pm.lock, flags); - - return err; -} - -static int au1xxxide_pm_standby( au1xxx_power_dev_t *dev ) { - return 0; -} - -static int au1xxxide_pm_sleep( au1xxx_power_dev_t *dev ) { - - int retval; - ide_hwif_t *hwif = auide_hwif.hwif; - struct request rq; - struct request_pm_state rqpm; - ide_task_t args; - - if(auide_hwif.pm.stopped) - return -1; - - /* - * wait until hard disc is ready - */ - if ( wait_for_ready(&hwif->drives[0], 35000) ) { - printk("Wait for drive sleep timeout!\n"); - retval = -1; - } - - /* - * sequenz to tell the high level ide driver that pm is resuming - */ - memset(&rq, 0, sizeof(rq)); - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq.flags = REQ_PM_SUSPEND; - rq.special = &args; - rq.pm = &rqpm; - rqpm.pm_step = ide_pm_state_start_suspend; - rqpm.pm_state = PMSG_SUSPEND; - - retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_wait); - - if (wait_for_ready (&hwif->drives[0], 35000)) { - printk("Wait for drive sleep timeout!\n"); - retval = -1; - } - - /* - * stop dbdma channels - */ - au1xxx_dbdma_reset(auide_hwif.tx_chan); - au1xxx_dbdma_reset(auide_hwif.rx_chan); - - auide_hwif.pm.stopped = 1; - - return retval; -} - -static int au1xxxide_pm_resume( au1xxx_power_dev_t *dev ) { - - int retval; - ide_hwif_t *hwif = auide_hwif.hwif; - struct request rq; - struct request_pm_state rqpm; - ide_task_t args; - - if(!auide_hwif.pm.stopped) - return -1; - - /* - * start dbdma channels - */ - au1xxx_dbdma_start(auide_hwif.tx_chan); - au1xxx_dbdma_start(auide_hwif.rx_chan); - - /* - * wait until hard disc is ready - */ - if (wait_for_ready ( &hwif->drives[0], 35000)) { - printk("Wait for drive wake up timeout!\n"); - retval = -1; - } - - /* - * sequenz to tell the high level ide driver that pm is resuming - */ - memset(&rq, 0, sizeof(rq)); - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq.flags = REQ_PM_RESUME; - rq.special = &args; - rq.pm = &rqpm; - rqpm.pm_step = ide_pm_state_start_resume; - rqpm.pm_state = PMSG_ON; - - retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_head_wait); - - /* - * wait for hard disc - */ - if ( wait_for_ready(&hwif->drives[0], 35000) ) { - printk("Wait for drive wake up timeout!\n"); - retval = -1; - } - - auide_hwif.pm.stopped = 0; - - return retval; -} - -static int au1xxxide_pm_getstatus( au1xxx_power_dev_t *dev ) { - return dev->cur_state; -} - -static int au1xxxide_pm_access( au1xxx_power_dev_t *dev ) { - if (dev->cur_state != AWAKE_STATE) - return 0; - else - return -1; -} - -static int au1xxxide_pm_idle( au1xxx_power_dev_t *dev ) { - return 0; -} - -static int au1xxxide_pm_cleanup( au1xxx_power_dev_t *dev ) { - return 0; -} -#endif /* CONFIG_PM */ - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AU1200 IDE driver"); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index af526b671c4..4ee597d0879 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -622,12 +622,18 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) ide_hwif_t *hwif; int h; + /* + * Find an empty HWIF; if none available, return -ENOMEM. + */ for (h = 0; h < MAX_HWIFS; ++h) { hwif = &ide_hwifs[h]; - /* Find an empty HWIF */ if (hwif->chipset == ide_unknown) break; } + if (h == MAX_HWIFS) { + printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", d->name); + return -ENOMEM; + } /* Get the CmdBlk and CtrlBlk Base Registers */ base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 7161ce0ef5a..86fb1e0286d 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -80,6 +80,7 @@ static struct via_isa_bridge { u16 flags; } via_isa_bridges[] = { { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |