diff options
Diffstat (limited to 'drivers/ide')
30 files changed, 1258 insertions, 1712 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 42e5b8175cb..1c81174595b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -625,7 +625,7 @@ config BLK_DEV_NS87415 tristate "NS87415 chipset support" help This driver adds detection and support for the NS87415 chip - (used in SPARC64, among others). + (used mainly on SPARC64 and PA-RISC machines). Please read the comments at the top of <file:drivers/ide/pci/ns87415.c>. @@ -787,6 +787,10 @@ config BLK_DEV_IDE_PMAC_BLINK This option enables the use of the sleep LED as a hard drive activity LED. +config BLK_DEV_IDE_SWARM + tristate "IDE for Sibyte evaluation boards" + depends on SIBYTE_SB1xxx_SOC + config BLK_DEV_IDE_AU1XXX bool "IDE for AMD Alchemy Au1200" depends on SOC_AU1200 @@ -803,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" @@ -936,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/Makefile b/drivers/ide/Makefile index cca9c075966..569fae71750 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -48,6 +48,6 @@ obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o -obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ +obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ mips/ obj-$(CONFIG_BLK_DEV_HD) += legacy/ obj-$(CONFIG_ETRAX_IDE) += cris/ diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c2f47923d17..3325660f724 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); } @@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, * and attempt to recover if there are problems. Returns 0 if everything's * ok; nonzero if the request has been terminated. */ -static inline +static int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) { if (ireason == 2) @@ -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); } @@ -1333,8 +1332,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) if (cdrom_read_from_buffer(drive)) return ide_stopped; - blk_attempt_remerge(drive->queue, rq); - /* Clear the local sector buffer. */ info->nsectors_buffered = 0; @@ -1344,8 +1341,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 +1479,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; @@ -1545,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) /* * Write handling */ -static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) +static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) { /* Two notes about IDE interrupt reason here - 0 means that * the drive wants to receive data from us, 2 means that @@ -1739,7 +1733,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; @@ -1878,20 +1872,11 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) return ide_stopped; } - /* - * for dvd-ram and such media, it's a really big deal to get - * big writes all the time. so scour the queue and attempt to - * remerge requests, often the plugging will not have had time - * to do this properly - */ - blk_attempt_remerge(drive->queue, rq); - info->nsectors_buffered = 0; /* 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 +1901,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 +1909,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; /* @@ -2912,6 +2895,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) devinfo->mask |= CDC_CLOSE_TRAY; if (!CDROM_CONFIG_FLAGS(drive)->mo_drive) devinfo->mask |= CDC_MO_DRIVE; + if (!CDROM_CONFIG_FLAGS(drive)->ram) + devinfo->mask |= CDC_RAM; devinfo->disk = info->disk; return register_cdrom(devinfo); @@ -3271,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) } #endif -static int ide_cd_remove(struct device *dev) +static void ide_cd_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info = drive->driver_data; ide_unregister_subdriver(drive, info->driver); @@ -3281,8 +3265,6 @@ static int ide_cd_remove(struct device *dev) del_gendisk(info->disk); ide_cd_put(info); - - return 0; } static void ide_cd_release(struct kref *kref) @@ -3306,7 +3288,7 @@ static void ide_cd_release(struct kref *kref) kfree(info); } -static int ide_cd_probe(struct device *); +static int ide_cd_probe(ide_drive_t *); #ifdef CONFIG_PROC_FS static int proc_idecd_read_capacity @@ -3328,13 +3310,13 @@ static ide_proc_entry_t idecd_proc[] = { #endif static ide_driver_t ide_cdrom_driver = { - .owner = THIS_MODULE, .gen_driver = { + .owner = THIS_MODULE, .name = "ide-cdrom", .bus = &ide_bus_type, - .probe = ide_cd_probe, - .remove = ide_cd_remove, }, + .probe = ide_cd_probe, + .remove = ide_cd_remove, .version = IDECD_VERSION, .media = ide_cdrom, .supports_dsc_overlap = 1, @@ -3428,9 +3410,8 @@ static char *ignore = NULL; module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -static int ide_cd_probe(struct device *dev) +static int ide_cd_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info; struct gendisk *g; struct request_sense sense; @@ -3510,12 +3491,13 @@ static void __exit ide_cdrom_exit(void) { driver_unregister(&ide_cdrom_driver.gen_driver); } - -static int ide_cdrom_init(void) + +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 e827b39e4b3..ca25f9e3d0f 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) && id->lba_capacity_2; } -static inline void idedisk_check_hpa(ide_drive_t *drive) +static void idedisk_check_hpa(ide_drive_t *drive) { unsigned long long capacity, set_max; int lba48 = idedisk_supports_lba48(drive->id); @@ -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) @@ -1028,21 +997,18 @@ static void ide_cacheflush_p(ide_drive_t *drive) printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); } -static int ide_disk_remove(struct device *dev) +static void ide_disk_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_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_disk_put(idkp); + ide_cacheflush_p(drive); - return 0; + ide_disk_put(idkp); } static void ide_disk_release(struct kref *kref) @@ -1058,12 +1024,10 @@ static void ide_disk_release(struct kref *kref) kfree(idkp); } -static int ide_disk_probe(struct device *dev); +static int ide_disk_probe(ide_drive_t *drive); -static void ide_device_shutdown(struct device *dev) +static void ide_device_shutdown(ide_drive_t *drive) { - ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); - #ifdef CONFIG_ALPHA /* On Alpha, halt(8) doesn't actually turn the machine off, it puts you into the sort of firmware monitor. Typically, @@ -1085,18 +1049,18 @@ static void ide_device_shutdown(struct device *dev) } printk("Shutdown: %s\n", drive->name); - dev->bus->suspend(dev, PMSG_SUSPEND); + drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); } static ide_driver_t idedisk_driver = { - .owner = THIS_MODULE, .gen_driver = { + .owner = THIS_MODULE, .name = "ide-disk", .bus = &ide_bus_type, - .probe = ide_disk_probe, - .remove = ide_disk_remove, - .shutdown = ide_device_shutdown, }, + .probe = ide_disk_probe, + .remove = ide_disk_remove, + .shutdown = ide_device_shutdown, .version = IDEDISK_VERSION, .media = ide_disk, .supports_dsc_overlap = 0, @@ -1161,6 +1125,17 @@ static int idedisk_release(struct inode *inode, struct file *filp) return 0; } +static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); + ide_drive_t *drive = idkp->drive; + + geo->heads = drive->bios_head; + geo->sectors = drive->bios_sect; + geo->cylinders = (u16)drive->bios_cyl; /* truncate */ + return 0; +} + static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -1195,15 +1170,15 @@ static struct block_device_operations idedisk_ops = { .open = idedisk_open, .release = idedisk_release, .ioctl = idedisk_ioctl, + .getgeo = idedisk_getgeo, .media_changed = idedisk_media_changed, .revalidate_disk= idedisk_revalidate_disk }; MODULE_DESCRIPTION("ATA DISK Driver"); -static int ide_disk_probe(struct device *dev) +static int ide_disk_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct ide_disk_obj *idkp; struct gendisk *g; @@ -1266,11 +1241,12 @@ static void __exit idedisk_exit (void) driver_unregister(&idedisk_driver.gen_driver); } -static int idedisk_init (void) +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 f615ab75996..1f8db9ac05d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) idefloppy_add_settings(drive); } -static int ide_floppy_remove(struct device *dev) +static void ide_floppy_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; @@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev) del_gendisk(g); ide_floppy_put(floppy); - - return 0; } static void ide_floppy_release(struct kref *kref) @@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ -static int ide_floppy_probe(struct device *); +static int ide_floppy_probe(ide_drive_t *); static ide_driver_t idefloppy_driver = { - .owner = THIS_MODULE, .gen_driver = { + .owner = THIS_MODULE, .name = "ide-floppy", .bus = &ide_bus_type, - .probe = ide_floppy_probe, - .remove = ide_floppy_remove, }, + .probe = ide_floppy_probe, + .remove = ide_floppy_remove, .version = IDEFLOPPY_VERSION, .media = ide_floppy, .supports_dsc_overlap = 0, @@ -2031,6 +2028,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp) return 0; } +static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); + ide_drive_t *drive = floppy->drive; + + geo->heads = drive->bios_head; + geo->sectors = drive->bios_sect; + geo->cylinders = (u16)drive->bios_cyl; /* truncate */ + return 0; +} + static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2120,13 +2128,13 @@ static struct block_device_operations idefloppy_ops = { .open = idefloppy_open, .release = idefloppy_release, .ioctl = idefloppy_ioctl, + .getgeo = idefloppy_getgeo, .media_changed = idefloppy_media_changed, .revalidate_disk= idefloppy_revalidate_disk }; -static int ide_floppy_probe(struct device *dev) +static int ide_floppy_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy; struct gendisk *g; @@ -2191,15 +2199,13 @@ static void __exit idefloppy_exit (void) driver_unregister(&idefloppy_driver.gen_driver); } -/* - * idefloppy_init will register the driver for each floppy. - */ -static int idefloppy_init (void) +static int __init idefloppy_init(void) { printk("ide-floppy driver " IDEFLOPPY_VERSION "\n"); 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 5275cbb1afe..8d50df4526a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -83,15 +83,12 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, if (!end_that_request_first(rq, uptodate, nr_sectors)) { add_disk_randomness(rq->rq_disk); - - if (blk_rq_tagged(rq)) - blk_queue_end_tag(drive->queue, rq); - blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); + end_that_request_last(rq, uptodate); ret = 0; } + return ret; } EXPORT_SYMBOL(__ide_end_request); @@ -113,16 +110,17 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) unsigned long flags; int ret = 1; + /* + * room for locking improvements here, the calls below don't + * need the queue lock held at all + */ spin_lock_irqsave(&ide_lock, flags); rq = HWGROUP(drive)->rq; 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 +245,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 +377,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); } @@ -1629,12 +1627,6 @@ EXPORT_SYMBOL(ide_init_drive_cmd); * for the new rq to be completed. This is VERY DANGEROUS, and is * intended for careful use by the ATAPI tape/cdrom driver code. * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * * If action is ide_end, then the rq is queued at the end of the * request queue, and the function returns immediately without waiting * for the new rq to be completed. This is again intended for careful diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index b09a6537c7a..41d46dbe6c2 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ - if (on && drive->media == ide_disk) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else if (HWIF(drive)->pci_dev) + if (!PCI_DMA_BUS_IS_PHYS) { + addr = BLK_BOUNCE_ANY; + } else if (on && drive->media == ide_disk) { + if (HWIF(drive)->pci_dev) addr = HWIF(drive)->pci_dev->dma_mask; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 02167a5b751..e7425546b4b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -655,7 +655,7 @@ static void hwif_release_dev (struct device *dev) { ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev); - up(&hwif->gendev_rel_sem); + complete(&hwif->gendev_rel_comp); } static void hwif_register (ide_hwif_t *hwif) @@ -1325,7 +1325,7 @@ static void drive_release_dev (struct device *dev) drive->queue = NULL; spin_unlock_irq(&ide_lock); - up(&drive->gendev_rel_sem); + complete(&drive->gendev_rel_comp); } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 0ac7eb8f40d..0101d0def7c 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) idetape_add_settings(drive); } -static int ide_tape_remove(struct device *dev) +static void ide_tape_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape = drive->driver_data; ide_unregister_subdriver(drive, tape->driver); @@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev) ide_unregister_region(tape->disk); ide_tape_put(tape); - - return 0; } static void ide_tape_release(struct kref *kref) @@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = { #endif -static int ide_tape_probe(struct device *); +static int ide_tape_probe(ide_drive_t *); static ide_driver_t idetape_driver = { - .owner = THIS_MODULE, .gen_driver = { + .owner = THIS_MODULE, .name = "ide-tape", .bus = &ide_bus_type, - .probe = ide_tape_probe, - .remove = ide_tape_remove, }, + .probe = ide_tape_probe, + .remove = ide_tape_remove, .version = IDETAPE_VERSION, .media = ide_tape, .supports_dsc_overlap = 1, @@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = { .ioctl = idetape_ioctl, }; -static int ide_tape_probe(struct device *dev) +static int ide_tape_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape; struct gendisk *g; int minor; @@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev) idetape_setup(drive, tape, minor); class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); + MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); + MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), S_IFCHR | S_IRUGO | S_IWUGO, @@ -4916,10 +4912,7 @@ static void __exit idetape_exit (void) unregister_chrdev(IDETAPE_MAJOR, "ht"); } -/* - * idetape_init will register the driver for each tape. - */ -static int idetape_init (void) +static int __init idetape_init(void) { int error = 1; idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape"); @@ -4950,6 +4943,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-taskfile.c b/drivers/ide/ide-taskfile.c index 54f9639c2a8..9834dce4e20 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -51,8 +51,6 @@ #include <asm/uaccess.h> #include <asm/io.h> -#define DEBUG_TASKFILE 0 /* unset when fixed */ - static void ata_bswap_data (void *buffer, int wcount) { u16 *p = buffer; @@ -310,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) ide_pio_sector(drive, write); } -static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, +static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { if (rq->bio) /* fs request */ @@ -765,9 +763,6 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) ide_hwif_t *hwif = HWIF(drive); task_struct_t *taskfile = (task_struct_t *) task->tfRegister; hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; -#if DEBUG_TASKFILE - u8 status; -#endif if (task->data_phase == TASKFILE_MULTI_IN || task->data_phase == TASKFILE_MULTI_OUT) { @@ -778,19 +773,13 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) } /* - * (ks) Check taskfile in/out flags. + * (ks) Check taskfile in flags. * If set, then execute as it is defined. * If not set, then define default settings. * The default values are: - * write and read all taskfile registers (except data) - * write and read the hob registers (sector,nsector,lcyl,hcyl) + * read all taskfile registers (except data) + * read the hob registers (sector, nsector, lcyl, hcyl) */ - if (task->tf_out_flags.all == 0) { - task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; - if (drive->addressing == 1) - task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); - } - if (task->tf_in_flags.all == 0) { task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; if (drive->addressing == 1) @@ -803,16 +792,6 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); SELECT_MASK(drive, 0); -#if DEBUG_TASKFILE - status = hwif->INB(IDE_STATUS_REG); - if (status & 0x80) { - printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); - udelay(100); - status = hwif->INB(IDE_STATUS_REG); - printk("flagged_taskfile -> Status = %02x\n", status); - } -#endif - if (task->tf_out_flags.b.data) { u16 data = taskfile->data + (hobfile->data << 8); hwif->OUTW(data, IDE_DATA_REG); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8af179b531c..afeb02bbb72 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -222,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->mwdma_mask = 0x80; /* disable all mwdma */ hwif->swdma_mask = 0x80; /* disable all swdma */ - sema_init(&hwif->gendev_rel_sem, 0); + init_completion(&hwif->gendev_rel_comp); default_hwif_iops(hwif); default_hwif_transport(hwif); @@ -245,7 +245,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) drive->is_flash = 0; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); - sema_init(&drive->gendev_rel_sem, 0); + init_completion(&drive->gendev_rel_comp); } } @@ -602,7 +602,7 @@ void ide_unregister(unsigned int index) } spin_unlock_irq(&ide_lock); device_unregister(&drive->gendev); - down(&drive->gendev_rel_sem); + wait_for_completion(&drive->gendev_rel_comp); spin_lock_irq(&ide_lock); } hwif->present = 0; @@ -662,7 +662,7 @@ void ide_unregister(unsigned int index) /* More messed up locking ... */ spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); - down(&hwif->gendev_rel_sem); + wait_for_completion(&hwif->gendev_rel_comp); /* * Remove us from the kernel's knowledge @@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device up(&ide_setting_sem); switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry geom; - if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - geom.heads = drive->bios_head; - geom.sectors = drive->bios_sect; - geom.cylinders = (u16)drive->bios_cyl; /* truncate */ - geom.start = get_start_sect(bdev); - if (copy_to_user(p, &geom, sizeof(struct hd_geometry))) - return -EFAULT; - return 0; - } - case HDIO_OBSOLETE_IDENTITY: case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) @@ -1904,9 +1891,100 @@ 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; +} + +static int generic_ide_probe(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + return drv->probe ? drv->probe(drive) : -ENODEV; +} + +static int generic_ide_remove(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + if (drv->remove) + drv->remove(drive); + + return 0; +} + +static void generic_ide_shutdown(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + if (dev->driver && drv->shutdown) + drv->shutdown(drive); +} + struct bus_type ide_bus_type = { .name = "ide", .match = ide_bus_match, + .uevent = ide_uevent, + .probe = generic_ide_probe, + .remove = generic_ide_remove, + .shutdown = generic_ide_shutdown, + .dev_attrs = ide_dev_attrs, .suspend = generic_ide_suspend, .resume = generic_ide_resume, }; diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 242029c9c0c..6439dec6688 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q) enable_irq(HD_IRQ); } -static int hd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; - struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; - struct hd_geometry g; - - if (cmd != HDIO_GETGEO) - return -EINVAL; - if (!loc) - return -EINVAL; - g.heads = disk->head; - g.sectors = disk->sect; - g.cylinders = disk->cyl; - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; + struct hd_i_struct *disk = bdev->bd_disk->private_data; + + geo->heads = disk->head; + geo->sectors = disk->sect; + geo->cylinders = disk->cyl; + return 0; } /* @@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) } static struct block_device_operations hd_fops = { - .ioctl = hd_ioctl, + .getgeo = hd_getgeo, }; /* 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 new file mode 100644 index 00000000000..677c7b2bac9 --- /dev/null +++ b/drivers/ide/mips/Makefile @@ -0,0 +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/mips/swarm.c b/drivers/ide/mips/swarm.c new file mode 100644 index 00000000000..66f6064f464 --- /dev/null +++ b/drivers/ide/mips/swarm.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2001, 2002, 2003 Broadcom Corporation + * Copyright (C) 2004 MontaVista Software Inc. + * Author: Manish Lachwani, mlachwani@mvista.com + * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved. + * Author: Maciej W. Rozycki <macro@mips.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Derived loosely from ide-pmac.c, so: + * Copyright (C) 1998 Paul Mackerras. + * Copyright (C) 1995-1998 Mark Lord + */ + +/* + * Boards with SiByte processors so far have supported IDE devices via + * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all + * cases, byte-swapping must be avoided for these devices (whereas + * other PCI devices, for example, will require swapping). Any + * SiByte-targetted kernel including IDE support will include this + * file. Probing of a Generic Bus for an IDE device is controlled by + * the definition of "SIBYTE_HAVE_IDE", which is provided by + * <asm/sibyte/board.h> for Broadcom boards. + */ + +#include <linux/ide.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> + +#include <asm/io.h> + +#include <asm/sibyte/board.h> +#include <asm/sibyte/sb1250_genbus.h> +#include <asm/sibyte/sb1250_regs.h> + +#define DRV_NAME "ide-swarm" + +static char swarm_ide_string[] = DRV_NAME; + +static struct resource swarm_ide_resource = { + .name = "SWARM GenBus IDE", + .flags = IORESOURCE_MEM, +}; + +static struct platform_device *swarm_ide_dev; + +/* + * swarm_ide_probe - if the board header indicates the existence of + * Generic Bus IDE, allocate a HWIF for it. + */ +static int __devinit swarm_ide_probe(struct device *dev) +{ + ide_hwif_t *hwif; + u8 __iomem *base; + phys_t offset, size; + int i; + + if (!SIBYTE_HAVE_IDE) + return -ENODEV; + + /* Find an empty slot. */ + for (i = 0; i < MAX_HWIFS; i++) + if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) + break; + if (i >= MAX_HWIFS) { + printk(KERN_ERR DRV_NAME ": no free slot for interface\n"); + return -ENOMEM; + } + + hwif = ide_hwifs + i; + + base = ioremap(A_IO_EXT_BASE, 0x800); + offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)); + size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS)); + iounmap(base); + + offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE; + size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE; + if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) { + printk(KERN_INFO DRV_NAME + ": IDE interface at GenBus disabled\n"); + return -EBUSY; + } + + printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n", + IDE_CS); + + swarm_ide_resource.start = offset; + swarm_ide_resource.end = offset + size - 1; + if (request_resource(&iomem_resource, &swarm_ide_resource)) { + printk(KERN_ERR DRV_NAME + ": can't request I/O memory resource\n"); + return -EBUSY; + } + + base = ioremap(offset, size); + + /* Setup MMIO ops. */ + default_hwif_mmiops(hwif); + /* Prevent resource map manipulation. */ + hwif->mmio = 2; + hwif->noprobe = 0; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) + hwif->hw.io_ports[i] = + (unsigned long)(base + ((0x1f0 + i) << 5)); + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = + (unsigned long)(base + (0x3f6 << 5)); + hwif->hw.irq = K_INT_GB_IDE; + + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->irq = hwif->hw.irq; + + dev_set_drvdata(dev, hwif); + + return 0; +} + +static struct device_driver swarm_ide_driver = { + .name = swarm_ide_string, + .bus = &platform_bus_type, + .probe = swarm_ide_probe, +}; + +static void swarm_ide_platform_release(struct device *device) +{ + struct platform_device *pldev; + + /* free device */ + pldev = to_platform_device(device); + kfree(pldev); +} + +static int __devinit swarm_ide_init_module(void) +{ + struct platform_device *pldev; + int err; + + printk(KERN_INFO "SWARM IDE driver\n"); + + if (driver_register(&swarm_ide_driver)) { + printk(KERN_ERR "Driver registration failed\n"); + err = -ENODEV; + goto out; + } + + if (!(pldev = kmalloc(sizeof (*pldev), GFP_KERNEL))) { + err = -ENOMEM; + goto out_unregister_driver; + } + + memset (pldev, 0, sizeof (*pldev)); + pldev->name = swarm_ide_string; + pldev->id = 0; + pldev->dev.release = swarm_ide_platform_release; + + if (platform_device_register(pldev)) { + err = -ENODEV; + goto out_free_pldev; + } + + if (!pldev->dev.driver) { + /* + * The driver was not bound to this device, there was + * no hardware at this address. Unregister it, as the + * release fuction will take care of freeing the + * allocated structure + */ + platform_device_unregister (pldev); + } + + swarm_ide_dev = pldev; + + return 0; + +out_free_pldev: + kfree(pldev); + +out_unregister_driver: + driver_unregister(&swarm_ide_driver); +out: + return err; +} + +module_init(swarm_ide_init_module); diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 52cadc005d7..a21b1e11eef 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -65,23 +65,6 @@ static struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { #define BUSCLOCK(D) \ ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D))) -#if 0 - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { - (void) pci_read_config_byte(dev, 0x54, &art); - p += sprintf(p, "DMA Mode: %s(%s)", - (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO", - (art&0x02)?"2":(art&0x01)?"1":"0"); - p += sprintf(p, " %s(%s)", - (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO", - (art&0x08)?"2":(art&0x04)?"1":"0"); - p += sprintf(p, " %s(%s)", - (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO", - (art&0x20)?"2":(art&0x10)?"1":"0"); - p += sprintf(p, " %s(%s)\n", - (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", - (art&0x80)?"2":(art&0x40)?"1":"0"); - } else { -#endif /* * TO DO: active tuning and correction of cards without a bios. @@ -112,13 +95,9 @@ static u8 aec62xx_ratemask (ide_drive_t *drive) switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_ARTOP_ATP865: case PCI_DEVICE_ID_ARTOP_ATP865R: -#if 0 - mode = (hwif->INB(hwif->dma_master) & 0x10) ? 4 : 3; -#else mode = (hwif->INB(((hwif->channel) ? hwif->mate->dma_status : hwif->dma_status)) & 0x10) ? 4 : 3; -#endif break; case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: @@ -263,35 +242,9 @@ static int aec62xx_irq_timeout (ide_drive_t *drive) case PCI_DEVICE_ID_ARTOP_ATP865: case PCI_DEVICE_ID_ARTOP_ATP865R: printk(" AEC62XX time out "); -#if 0 - { - int i = 0; - u8 reg49h = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); - for (i=0;i<256;i++) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); - } - return 0; -#endif default: break; } -#if 0 - { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 tmp1 = 0, tmp2 = 0, mode6 = 0; - - pci_read_config_byte(dev, 0x44, &tmp1); - pci_read_config_byte(dev, 0x45, &tmp2); - printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2); - mode6 = HWIF(drive)->INB(((hwif->channel) ? - hwif->mate->dma_status : - hwif->dma_status)); - printk(" AEC6280 133=%x ", (mode6 & 0x10)); - } -#endif return 0; } diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 6cf49394a80..cf84350efc5 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -876,10 +876,15 @@ static ide_pci_device_t ali15x3_chipset __devinitdata = { static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { + static struct pci_device_id ati_rs100[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100) }, + { }, + }; + ide_pci_device_t *d = &ali15x3_chipset; - if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, NULL)) - printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not yet fully tested.\n"); + if (pci_dev_present(ati_rs100)) + printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n"); #if defined(CONFIG_SPARC64) d->init_hwif = init_hwif_common_ali15x3; diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 7dc24682d19..ea3c52cc8ac 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -222,10 +222,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic /* We must not grab the entire device, it has 'ISA' space in its BARS too and we will freak out other bits of the kernel */ - if(pci_enable_device_bars(dev, 1<<2)) - { + if (pci_enable_device_bars(dev, 1<<2)) { printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name); - return 1; + return -ENODEV; } pci_set_master(dev); if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 211641a5439..fe06ebb0e5b 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -39,7 +39,7 @@ #define PDC202_DEBUG_CABLE 0 -const static char *pdc_quirk_drives[] = { +static const char *pdc_quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", "QUANTUM FIREBALLP KA9.1", diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index ff2e217a8c8..0d3073f4eab 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -69,7 +69,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mode; + u8 mode = 0; if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); 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/siimage.c b/drivers/ide/pci/siimage.c index 022d244f2eb..f1ca154dd52 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -6,7 +6,13 @@ * * May be copied or modified under the terms of the GNU General Public License * - * Documentation available under NDA only + * Documentation for CMD680: + * http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2 + * + * Documentation for SiI 3112: + * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 + * + * Errata and other documentation only available under NDA. * * * FAQ Items: diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 16b3e2d8bfb..75a2253a3e6 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -87,6 +87,7 @@ static const struct { u8 chipset_family; u8 flags; } SiSHostChipInfo[] = { + { "SiS965", PCI_DEVICE_ID_SI_965, ATA_133 }, { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, { "SiS733", PCI_DEVICE_ID_SI_733, ATA_100 }, diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index ea0806c82be..8a5c7b286b2 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -399,34 +399,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c return dev->irq; } -static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) -{ - unsigned int rev; - u8 dma_state; - - DBG(("init_dma_sl82c105(hwif: ide%d, dma_base: 0x%08x)\n", hwif->index, dma_base)); - - hwif->autodma = 0; - - if (!dma_base) - return; - - dma_state = hwif->INB(dma_base + 2); - rev = sl82c105_bridge_revision(hwif->pci_dev); - if (rev <= 5) { - printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", - hwif->name, rev); - dma_state &= ~0x60; - } else { - dma_state |= 0x60; - if (!noautodma) - hwif->autodma = 1; - } - hwif->OUTB(dma_state, dma_base + 2); - - ide_setup_dma(hwif, dma_base, 8); -} - /* * Initialise the chip */ @@ -434,6 +406,8 @@ static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; + unsigned int rev; + u8 dma_state; u32 val; DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); @@ -455,33 +429,54 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) pci_read_config_dword(dev, 0x40, &val); *((u32 *)&hwif->hwif_data) = val; + hwif->atapi_dma = 0; + hwif->mwdma_mask = 0; + hwif->swdma_mask = 0; + hwif->autodma = 0; + if (!hwif->dma_base) return; - hwif->atapi_dma = 1; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; - + dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60; + rev = sl82c105_bridge_revision(hwif->pci_dev); + if (rev <= 5) { + /* + * Never ever EVER under any circumstances enable + * DMA when the bridge is this old. + */ + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", + hwif->name, rev); + } else { #ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_check = &sl82c105_check_drive; - hwif->ide_dma_on = &sl82c105_ide_dma_on; - hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; - hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; - hwif->dma_start = &sl82c105_ide_dma_start; - hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; - - if (!noautodma) - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; + dma_state |= 0x60; + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + hwif->ide_dma_check = &sl82c105_check_drive; + hwif->ide_dma_on = &sl82c105_ide_dma_on; + hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; + hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; + hwif->dma_start = &sl82c105_ide_dma_start; + hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; #endif /* CONFIG_BLK_DEV_IDEDMA */ + } + hwif->OUTB(dma_state, hwif->dma_base + 2); } static ide_pci_device_t sl82c105_chipset __devinitdata = { .name = "W82C105", .init_chipset = init_chipset_sl82c105, .init_hwif = init_hwif_sl82c105, - .init_dma = init_dma_sl82c105, .channels = 2, .autodma = NOAUTODMA, .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index a4d099c937f..c85b87cb59d 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -79,6 +79,8 @@ static struct via_isa_bridge { u8 rev_max; 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 }, @@ -100,185 +102,14 @@ static struct via_isa_bridge { { NULL } }; -static struct via_isa_bridge *via_config; -static unsigned int via_80w; static unsigned int via_clock; static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; -/* - * VIA /proc entry. - */ - -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) - -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static u8 via_proc = 0; -static unsigned long via_base; -static struct pci_dev *bmide_dev, *isa_dev; - -static char *via_control3[] = { "No limit", "64", "128", "192" }; - -#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) -#define via_print_drive(name, format, arg...)\ - p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); - - -/** - * via_get_info - generate via /proc file - * @buffer: buffer for data - * @addr: set to start of data to use - * @offset: current file offset - * @count: size of read - * - * Fills in buffer with the debugging/configuration information for - * the VIA chipset tuning and attached drives - */ - -static int via_get_info(char *buffer, char **addr, off_t offset, int count) +struct via82cxxx_dev { - int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], - uen[4], udma[4], umul[4], active8b[4], recover8b[4]; - struct pci_dev *dev = bmide_dev; - unsigned int v, u, i; - int len; - u16 c, w; - u8 t, x; - char *p = buffer; - - via_print("----------VIA BusMastering IDE Configuration" - "----------------"); - - via_print("Driver Version: 3.38"); - via_print("South Bridge: VIA %s", - via_config->name); - - pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); - pci_read_config_byte(dev, PCI_REVISION_ID, &x); - via_print("Revision: ISA %#x IDE %#x", t, x); - via_print("Highest DMA rate: %s", - via_dma[via_config->flags & VIA_UDMA]); - - via_print("BM-DMA base: %#lx", via_base); - via_print("PCI clock: %d.%dMHz", - via_clock / 1000, via_clock / 100 % 10); - - pci_read_config_byte(dev, VIA_MISC_1, &t); - via_print("Master Read Cycle IRDY: %dws", - (t & 64) >> 6); - via_print("Master Write Cycle IRDY: %dws", - (t & 32) >> 5); - via_print("BM IDE Status Register Read Retry: %s", - (t & 8) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_MISC_3, &t); - via_print("Max DRDY Pulse Width: %s%s", - via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : ""); - - via_print("-----------------------Primary IDE" - "-------Secondary IDE------"); - via_print("Read DMA FIFO flush: %10s%20s", - (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no"); - via_print("End Sector FIFO flush: %10s%20s", - (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); - via_print("Prefetch Buffer: %10s%20s", - (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); - via_print("Post Write Buffer: %10s%20s", - (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &t); - via_print("Enabled: %10s%20s", - (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); - - c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8); - via_print("Simplex only: %10s%20s", - (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); - - via_print("Cable Type: %10s%20s", - (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); - - via_print("-------------------drive0----drive1" - "----drive2----drive3-----"); - - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v); - pci_read_config_word(dev, VIA_8BIT_TIMING, &w); - - if (via_config->flags & VIA_UDMA) - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - else u = 0; - - for (i = 0; i < 4; i++) { - - setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; - recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; - active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; - active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; - recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; - udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2; - umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; - uen[i] = ((u >> ((3 - i) << 3)) & 0x20); - den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); - - speed[i] = 2 * via_clock / (active[i] + recover[i]); - cycle[i] = 1000000 * (active[i] + recover[i]) / via_clock; - - if (!uen[i] || !den[i]) - continue; - - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_33: - speed[i] = 2 * via_clock / udma[i]; - cycle[i] = 1000000 * udma[i] / via_clock; - break; - - case VIA_UDMA_66: - speed[i] = 4 * via_clock / (udma[i] * umul[i]); - cycle[i] = 500000 * (udma[i] * umul[i]) / via_clock; - break; - - case VIA_UDMA_100: - speed[i] = 6 * via_clock / udma[i]; - cycle[i] = 333333 * udma[i] / via_clock; - break; - - case VIA_UDMA_133: - speed[i] = 8 * via_clock / udma[i]; - cycle[i] = 250000 * udma[i] / via_clock; - break; - } - } - - via_print_drive("Transfer Mode: ", "%10s", - den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - - via_print_drive("Address Setup: ", "%8dns", - 1000000 * setup[i] / via_clock); - via_print_drive("Cmd Active: ", "%8dns", - 1000000 * active8b[i] / via_clock); - via_print_drive("Cmd Recovery: ", "%8dns", - 1000000 * recover8b[i] / via_clock); - via_print_drive("Data Active: ", "%8dns", - 1000000 * active[i] / via_clock); - via_print_drive("Data Recovery: ", "%8dns", - 1000000 * recover[i] / via_clock); - via_print_drive("Cycle Time: ", "%8dns", - cycle[i]); - via_print_drive("Transfer Rate: ", "%4d.%dMB/s", - speed[i] / 1000, speed[i] / 100 % 10); - - /* hoping it is less than 4K... */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} - -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ + struct via_isa_bridge *via_config; + unsigned int via_80w; +}; /** * via_set_speed - write timing registers @@ -289,11 +120,13 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count) * via_set_speed writes timing values to the chipset registers */ -static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing) +static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) { + struct pci_dev *dev = hwif->pci_dev; + struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif); u8 t; - if (~via_config->flags & VIA_BAD_AST) { + if (~vdev->via_config->flags & VIA_BAD_AST) { pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); @@ -305,7 +138,7 @@ static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing) pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); - switch (via_config->flags & VIA_UDMA) { + switch (vdev->via_config->flags & VIA_UDMA) { case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break; case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; @@ -329,6 +162,7 @@ static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing) static int via_set_drive(ide_drive_t *drive, u8 speed) { ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); + struct via82cxxx_dev *vdev = ide_get_hwifdata(drive->hwif); struct ide_timing t, p; unsigned int T, UT; @@ -337,7 +171,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed) T = 1000000000 / via_clock; - switch (via_config->flags & VIA_UDMA) { + switch (vdev->via_config->flags & VIA_UDMA) { case VIA_UDMA_33: UT = T; break; case VIA_UDMA_66: UT = T/2; break; case VIA_UDMA_100: UT = T/3; break; @@ -352,7 +186,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed) ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); } - via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + via_set_speed(HWIF(drive), drive->dn, &t); if (!drive->init_speed) drive->init_speed = speed; @@ -390,20 +224,41 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio) static int via82cxxx_ide_dma_check (ide_drive_t *drive) { - u16 w80 = HWIF(drive)->udma_four; + ide_hwif_t *hwif = HWIF(drive); + struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif); + u16 w80 = hwif->udma_four; u16 speed = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | - (via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0)); + (vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | + (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | + (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) | + (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0)); via_set_drive(drive, speed); if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) - return HWIF(drive)->ide_dma_on(drive); - return HWIF(drive)->ide_dma_off_quietly(drive); + return hwif->ide_dma_on(drive); + return hwif->ide_dma_off_quietly(drive); +} + +static struct via_isa_bridge *via_config_find(struct pci_dev **isa) +{ + struct via_isa_bridge *via_config; + u8 t; + + for (via_config = via_isa_bridges; via_config->id; via_config++) + if ((*isa = pci_find_device(PCI_VENDOR_ID_VIA + + !!(via_config->flags & VIA_BAD_ID), + via_config->id, NULL))) { + + pci_read_config_byte(*isa, PCI_REVISION_ID, &t); + if (t >= via_config->rev_min && + t <= via_config->rev_max) + break; + } + + return via_config; } /** @@ -418,82 +273,28 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive) static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name) { struct pci_dev *isa = NULL; + struct via_isa_bridge *via_config; u8 t, v; unsigned int u; - int i; /* * Find the ISA bridge to see how good the IDE is. */ - - for (via_config = via_isa_bridges; via_config->id; via_config++) - if ((isa = pci_find_device(PCI_VENDOR_ID_VIA + - !!(via_config->flags & VIA_BAD_ID), - via_config->id, NULL))) { - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - if (t >= via_config->rev_min && - t <= via_config->rev_max) - break; - } - + via_config = via_config_find(&isa); if (!via_config->id) { printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n"); return -ENODEV; } /* - * Check 80-wire cable presence and setup Clk66. + * Setup or disable Clk66 if appropriate */ - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_66: - /* Enable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); - for (i = 24; i >= 0; i -= 8) - if (((u >> (i & 16)) & 8) && - ((u >> i) & 0x20) && - (((u >> i) & 7) < 2)) { - /* - * 2x PCI clock and - * UDMA w/ < 3T/cycle - */ - via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case VIA_UDMA_100: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 4))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case VIA_UDMA_133: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 6))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - via_80w |= (1 << (1 - (i >> 4))); - } - break; - - } - - /* Disable Clk66 */ - if (via_config->flags & VIA_BAD_CLK66) { + if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) { + /* Enable Clk66 */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); + } else if (via_config->flags & VIA_BAD_CLK66) { /* Would cause trouble on 596a and 686 */ pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); @@ -560,33 +361,85 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const via_dma[via_config->flags & VIA_UDMA], pci_name(dev)); - /* - * Setup /proc/ide/via entry. - */ + return 0; +} + +/* + * Check and handle 80-wire cable presence + */ +static void __devinit via_cable_detect(struct pci_dev *dev, struct via82cxxx_dev *vdev) +{ + unsigned int u; + int i; + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + switch (vdev->via_config->flags & VIA_UDMA) { + + case VIA_UDMA_66: + for (i = 24; i >= 0; i -= 8) + if (((u >> (i & 16)) & 8) && + ((u >> i) & 0x20) && + (((u >> i) & 7) < 2)) { + /* + * 2x PCI clock and + * UDMA w/ < 3T/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_100: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 4))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_133: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 6))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) - if (!via_proc) { - via_base = pci_resource_start(dev, 4); - bmide_dev = dev; - isa_dev = isa; - ide_pci_create_host_proc("via", via_get_info); - via_proc = 1; } -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ - return 0; } static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) { + struct via82cxxx_dev *vdev = kmalloc(sizeof(struct via82cxxx_dev), + GFP_KERNEL); + struct pci_dev *isa = NULL; int i; + if (vdev == NULL) { + printk(KERN_ERR "VP_IDE: out of memory :(\n"); + return; + } + + memset(vdev, 0, sizeof(struct via82cxxx_dev)); + ide_set_hwifdata(hwif, vdev); + + vdev->via_config = via_config_find(&isa); + via_cable_detect(hwif->pci_dev, vdev); + hwif->autodma = 0; hwif->tuneproc = &via82cxxx_tune_drive; hwif->speedproc = &via_set_drive; -#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32) +#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) { hwif->irq = hwif->channel ? 15 : 14; } @@ -594,7 +447,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) for (i = 0; i < 2; i++) { hwif->drives[i].io_32bit = 1; - hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1; + hwif->drives[i].unmask = (vdev->via_config->flags & VIA_NO_UNMASK) ? 0 : 1; hwif->drives[i].autotune = 1; hwif->drives[i].dn = hwif->channel * 2 + i; } @@ -608,7 +461,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) hwif->swdma_mask = 0x07; if (!hwif->udma_four) - hwif->udma_four = (via_80w >> hwif->channel) & 1; + hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1; hwif->ide_dma_check = &via82cxxx_ide_dma_check; if (!noautodma) hwif->autodma = 1; @@ -616,24 +469,35 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) hwif->drives[1].autodma = hwif->autodma; } -static ide_pci_device_t via82cxxx_chipset __devinitdata = { - .name = "VP_IDE", - .init_chipset = init_chipset_via82cxxx, - .init_hwif = init_hwif_via82cxxx, - .channels = 2, - .autodma = NOAUTODMA, - .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, - .bootable = ON_BOARD, +static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { + { /* 0 */ + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_hwif = init_hwif_via82cxxx, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD + },{ /* 1 */ + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_hwif = init_hwif_via82cxxx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + } }; static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &via82cxxx_chipset); + return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]); } static struct pci_device_id via_pci_tbl[] = { { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, via_pci_tbl); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index b3e65a65d20..5013b1285e2 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1271,7 +1271,7 @@ static int pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) { struct device_node *np = pmif->node; - int *bidp, i; + int *bidp; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; @@ -1401,20 +1401,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* We probe the hwif now */ probe_hwif_init(hwif); - /* The code IDE code will have set hwif->present if we have devices attached, - * if we don't, the discard the interface except if we are on a media bay slot - */ - if (!hwif->present && !pmif->mediabay) { - printk(KERN_INFO "ide%d: Bus empty, interface released.\n", - hwif->index); - default_hwif_iops(hwif); - for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; ++i) - hwif->io_ports[i] = 0; - hwif->chipset = ide_unknown; - hwif->noprobe = 1; - return -ENODEV; - } - return 0; } @@ -1444,7 +1430,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) pmif = &pmac_ide[i]; hwif = &ide_hwifs[i]; - if (mdev->ofdev.node->n_addrs == 0) { + if (macio_resource_count(mdev) == 0) { printk(KERN_WARNING "ide%d: no address for %s\n", i, mdev->ofdev.node->full_name); return -ENXIO; @@ -1667,11 +1653,16 @@ static struct macio_driver pmac_ide_macio_driver = }; static struct pci_device_id pmac_ide_pci_match[] = { - { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, }; static struct pci_driver pmac_ide_pci_driver = { @@ -1695,7 +1686,7 @@ pmac_ide_probe(void) #else macio_register_driver(&pmac_ide_macio_driver); pci_register_driver(&pmac_ide_pci_driver); -#endif +#endif } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index d4f2111d436..7ebf992e8c2 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -787,7 +787,7 @@ static int pre_init = 1; /* Before first ordered IDE scan */ static LIST_HEAD(ide_pci_drivers); /* - * __ide_register_pci_driver - attach IDE driver + * __ide_pci_register_driver - attach IDE driver * @driver: pci driver * @module: owner module of the driver * |