diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:14 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:14 -0400 |
commit | 806f80a6fc203ad0bde84e5a9e94572617d2ae45 (patch) | |
tree | 20c684323e6e9f24af96df84008f06425a67ec6a | |
parent | 79cb380397c834a35952d8497651d93b543ef968 (diff) |
ide: add generic ATA/ATAPI disk driver
* Add struct ide_disk_ops containing protocol specific methods.
* Add 'struct ide_disk_ops *' to ide_drive_t.
* Convert ide-{disk,floppy} drivers to use struct ide_disk_ops.
* Merge ide-{disk,floppy} drivers into generic ide-gd driver.
While at it:
- ide_disk_init_capacity() -> ide_disk_get_capacity()
Acked-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/Kconfig | 64 | ||||
-rw-r--r-- | drivers/ide/Makefile | 19 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 39 | ||||
-rw-r--r-- | drivers/ide/ide-disk.h | 24 | ||||
-rw-r--r-- | drivers/ide/ide-disk_ioctl.c | 4 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 45 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.h | 58 | ||||
-rw-r--r-- | drivers/ide/ide-floppy_ioctl.c | 9 | ||||
-rw-r--r-- | drivers/ide/ide-gd-floppy.c | 309 | ||||
-rw-r--r-- | drivers/ide/ide-gd.c | 122 | ||||
-rw-r--r-- | drivers/ide/ide-gd.h | 44 | ||||
-rw-r--r-- | drivers/leds/Kconfig | 2 | ||||
-rw-r--r-- | include/linux/ide.h | 19 |
13 files changed, 303 insertions, 455 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 74a369a6116f..faa974e615da 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -84,21 +84,40 @@ config BLK_DEV_IDE_SATA | |||
84 | 84 | ||
85 | If unsure, say N. | 85 | If unsure, say N. |
86 | 86 | ||
87 | config BLK_DEV_IDEDISK | 87 | config IDE_GD |
88 | tristate "Include IDE/ATA-2 DISK support" | 88 | tristate "generic ATA/ATAPI disk support" |
89 | ---help--- | 89 | default y |
90 | This will include enhanced support for MFM/RLL/IDE hard disks. If | 90 | help |
91 | you have a MFM/RLL/IDE disk, and there is no special reason to use | 91 | Support for ATA/ATAPI disks (including ATAPI floppy drives). |
92 | the old hard disk driver instead, say Y. If you have an SCSI-only | ||
93 | system, you can say N here. | ||
94 | 92 | ||
95 | To compile this driver as a module, choose M here: the | 93 | To compile this driver as a module, choose M here. |
96 | module will be called ide-disk. | 94 | The module will be called ide-gd_mod. |
97 | Do not compile this driver as a module if your root file system | ||
98 | (the one containing the directory /) is located on the IDE disk. | ||
99 | 95 | ||
100 | If unsure, say Y. | 96 | If unsure, say Y. |
101 | 97 | ||
98 | config IDE_GD_ATA | ||
99 | bool "ATA disk support" | ||
100 | depends on IDE_GD | ||
101 | default y | ||
102 | help | ||
103 | This will include support for ATA hard disks. | ||
104 | |||
105 | If unsure, say Y. | ||
106 | |||
107 | config IDE_GD_ATAPI | ||
108 | bool "ATAPI floppy support" | ||
109 | depends on IDE_GD | ||
110 | select IDE_ATAPI | ||
111 | help | ||
112 | This will include support for ATAPI floppy drives | ||
113 | (i.e. Iomega ZIP or MKE LS-120). | ||
114 | |||
115 | For information about jumper settings and the question | ||
116 | of when a ZIP drive uses a partition table, see | ||
117 | <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>. | ||
118 | |||
119 | If unsure, say N. | ||
120 | |||
102 | config BLK_DEV_IDECS | 121 | config BLK_DEV_IDECS |
103 | tristate "PCMCIA IDE support" | 122 | tristate "PCMCIA IDE support" |
104 | depends on PCMCIA | 123 | depends on PCMCIA |
@@ -163,29 +182,6 @@ config BLK_DEV_IDETAPE | |||
163 | To compile this driver as a module, choose M here: the | 182 | To compile this driver as a module, choose M here: the |
164 | module will be called ide-tape. | 183 | module will be called ide-tape. |
165 | 184 | ||
166 | config BLK_DEV_IDEFLOPPY | ||
167 | tristate "Include IDE/ATAPI FLOPPY support" | ||
168 | select IDE_ATAPI | ||
169 | ---help--- | ||
170 | If you have an IDE floppy drive which uses the ATAPI protocol, | ||
171 | answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy | ||
172 | drives, similar to the SCSI protocol. | ||
173 | |||
174 | The LS-120 and the IDE/ATAPI Iomega ZIP drive are also supported by | ||
175 | this driver. For information about jumper settings and the question | ||
176 | of when a ZIP drive uses a partition table, see | ||
177 | <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>. | ||
178 | (ATAPI PD-CD/CDR drives are not supported by this driver; support | ||
179 | for PD-CD/CDR drives is available if you answer Y to | ||
180 | "SCSI emulation support", below). | ||
181 | |||
182 | If you say Y here, the FLOPPY drive will be identified along with | ||
183 | other IDE devices, as "hdb" or "hdc", or something similar (check | ||
184 | the boot messages with dmesg). | ||
185 | |||
186 | To compile this driver as a module, choose M here: the | ||
187 | module will be called ide-floppy. | ||
188 | |||
189 | config BLK_DEV_IDESCSI | 185 | config BLK_DEV_IDESCSI |
190 | tristate "SCSI emulation support (DEPRECATED)" | 186 | tristate "SCSI emulation support (DEPRECATED)" |
191 | depends on SCSI | 187 | depends on SCSI |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 7eeeab597959..093d3248ca89 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
@@ -37,18 +37,25 @@ obj-$(CONFIG_IDE_H8300) += h8300/ | |||
37 | obj-$(CONFIG_IDE_GENERIC) += ide-generic.o | 37 | obj-$(CONFIG_IDE_GENERIC) += ide-generic.o |
38 | obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o | 38 | obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o |
39 | 39 | ||
40 | ide-disk_mod-y += ide-gd.o ide-disk.o ide-disk_ioctl.o | 40 | ide-gd_mod-y += ide-gd.o |
41 | ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o | 41 | ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o |
42 | ide-floppy_mod-y += ide-gd-floppy.o ide-floppy.o ide-floppy_ioctl.o | ||
43 | 42 | ||
43 | ifeq ($(CONFIG_IDE_GD_ATA), y) | ||
44 | ide-gd_mod-y += ide-disk.o ide-disk_ioctl.o | ||
44 | ifeq ($(CONFIG_IDE_PROC_FS), y) | 45 | ifeq ($(CONFIG_IDE_PROC_FS), y) |
45 | ide-disk_mod-y += ide-disk_proc.o | 46 | ide-gd_mod-y += ide-disk_proc.o |
46 | ide-floppy_mod-y += ide-floppy_proc.o | 47 | endif |
48 | endif | ||
49 | |||
50 | ifeq ($(CONFIG_IDE_GD_ATAPI), y) | ||
51 | ide-gd_mod-y += ide-floppy.o ide-floppy_ioctl.o | ||
52 | ifeq ($(CONFIG_IDE_PROC_FS), y) | ||
53 | ide-gd_mod-y += ide-floppy_proc.o | ||
54 | endif | ||
47 | endif | 55 | endif |
48 | 56 | ||
49 | obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o | 57 | obj-$(CONFIG_IDE_GD) += ide-gd_mod.o |
50 | obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o | 58 | obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o |
51 | obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o | ||
52 | obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o | 59 | obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o |
53 | 60 | ||
54 | ifeq ($(CONFIG_BLK_DEV_IDECS), y) | 61 | ifeq ($(CONFIG_BLK_DEV_IDECS), y) |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 751be7af22c2..223750c1b5a6 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -184,8 +184,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
184 | * 1073741822 == 549756 MB or 48bit addressing fake drive | 184 | * 1073741822 == 549756 MB or 48bit addressing fake drive |
185 | */ | 185 | */ |
186 | 186 | ||
187 | ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | 187 | static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, |
188 | sector_t block) | 188 | sector_t block) |
189 | { | 189 | { |
190 | ide_hwif_t *hwif = HWIF(drive); | 190 | ide_hwif_t *hwif = HWIF(drive); |
191 | 191 | ||
@@ -333,7 +333,7 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
336 | void ide_disk_init_capacity(ide_drive_t *drive) | 336 | static int ide_disk_get_capacity(ide_drive_t *drive) |
337 | { | 337 | { |
338 | u16 *id = drive->id; | 338 | u16 *id = drive->id; |
339 | int lba; | 339 | int lba; |
@@ -382,6 +382,8 @@ void ide_disk_init_capacity(ide_drive_t *drive) | |||
382 | } else | 382 | } else |
383 | drive->dev_flags &= ~IDE_DFLAG_LBA48; | 383 | drive->dev_flags &= ~IDE_DFLAG_LBA48; |
384 | } | 384 | } |
385 | |||
386 | return 0; | ||
385 | } | 387 | } |
386 | 388 | ||
387 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 389 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) |
@@ -590,7 +592,12 @@ ide_ext_devset_rw(wcache, wcache); | |||
590 | 592 | ||
591 | ide_ext_devset_rw_sync(nowerr, nowerr); | 593 | ide_ext_devset_rw_sync(nowerr, nowerr); |
592 | 594 | ||
593 | void ide_disk_setup(ide_drive_t *drive) | 595 | static int ide_disk_check(ide_drive_t *drive, const char *s) |
596 | { | ||
597 | return 1; | ||
598 | } | ||
599 | |||
600 | static void ide_disk_setup(ide_drive_t *drive) | ||
594 | { | 601 | { |
595 | struct ide_disk_obj *idkp = drive->driver_data; | 602 | struct ide_disk_obj *idkp = drive->driver_data; |
596 | ide_hwif_t *hwif = drive->hwif; | 603 | ide_hwif_t *hwif = drive->hwif; |
@@ -626,7 +633,7 @@ void ide_disk_setup(ide_drive_t *drive) | |||
626 | drive->queue->max_sectors / 2); | 633 | drive->queue->max_sectors / 2); |
627 | 634 | ||
628 | /* calculate drive capacity, and select LBA if possible */ | 635 | /* calculate drive capacity, and select LBA if possible */ |
629 | ide_disk_init_capacity(drive); | 636 | ide_disk_get_capacity(drive); |
630 | 637 | ||
631 | /* | 638 | /* |
632 | * if possible, give fdisk access to more of the drive, | 639 | * if possible, give fdisk access to more of the drive, |
@@ -682,7 +689,7 @@ void ide_disk_setup(ide_drive_t *drive) | |||
682 | drive->dev_flags |= IDE_DFLAG_ATTACH; | 689 | drive->dev_flags |= IDE_DFLAG_ATTACH; |
683 | } | 690 | } |
684 | 691 | ||
685 | void ide_disk_flush(ide_drive_t *drive) | 692 | static void ide_disk_flush(ide_drive_t *drive) |
686 | { | 693 | { |
687 | if (ata_id_flush_enabled(drive->id) == 0 || | 694 | if (ata_id_flush_enabled(drive->id) == 0 || |
688 | (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) | 695 | (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) |
@@ -692,7 +699,13 @@ void ide_disk_flush(ide_drive_t *drive) | |||
692 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); | 699 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); |
693 | } | 700 | } |
694 | 701 | ||
695 | int ide_disk_set_doorlock(ide_drive_t *drive, int on) | 702 | static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk) |
703 | { | ||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | ||
708 | int on) | ||
696 | { | 709 | { |
697 | ide_task_t task; | 710 | ide_task_t task; |
698 | int ret; | 711 | int ret; |
@@ -711,3 +724,15 @@ int ide_disk_set_doorlock(ide_drive_t *drive, int on) | |||
711 | 724 | ||
712 | return ret; | 725 | return ret; |
713 | } | 726 | } |
727 | |||
728 | const struct ide_disk_ops ide_ata_disk_ops = { | ||
729 | .check = ide_disk_check, | ||
730 | .get_capacity = ide_disk_get_capacity, | ||
731 | .setup = ide_disk_setup, | ||
732 | .flush = ide_disk_flush, | ||
733 | .init_media = ide_disk_init_media, | ||
734 | .set_doorlock = ide_disk_set_doorlock, | ||
735 | .do_request = ide_do_rw_disk, | ||
736 | .end_request = ide_end_request, | ||
737 | .ioctl = ide_disk_ioctl, | ||
738 | }; | ||
diff --git a/drivers/ide/ide-disk.h b/drivers/ide/ide-disk.h index 104ad71288a5..b234b0feaf7b 100644 --- a/drivers/ide/ide-disk.h +++ b/drivers/ide/ide-disk.h | |||
@@ -1,22 +1,11 @@ | |||
1 | #ifndef __IDE_DISK_H | 1 | #ifndef __IDE_DISK_H |
2 | #define __IDE_DISK_H | 2 | #define __IDE_DISK_H |
3 | 3 | ||
4 | struct ide_disk_obj { | 4 | #include "ide-gd.h" |
5 | ide_drive_t *drive; | ||
6 | ide_driver_t *driver; | ||
7 | struct gendisk *disk; | ||
8 | struct kref kref; | ||
9 | unsigned int openers; /* protected by BKL for now */ | ||
10 | }; | ||
11 | |||
12 | sector_t ide_gd_capacity(ide_drive_t *); | ||
13 | 5 | ||
6 | #ifdef CONFIG_IDE_GD_ATA | ||
14 | /* ide-disk.c */ | 7 | /* ide-disk.c */ |
15 | void ide_disk_init_capacity(ide_drive_t *); | 8 | extern const struct ide_disk_ops ide_ata_disk_ops; |
16 | void ide_disk_setup(ide_drive_t *); | ||
17 | void ide_disk_flush(ide_drive_t *); | ||
18 | int ide_disk_set_doorlock(ide_drive_t *, int); | ||
19 | ide_startstop_t ide_do_rw_disk(ide_drive_t *, struct request *, sector_t); | ||
20 | ide_decl_devset(address); | 9 | ide_decl_devset(address); |
21 | ide_decl_devset(multcount); | 10 | ide_decl_devset(multcount); |
22 | ide_decl_devset(nowerr); | 11 | ide_decl_devset(nowerr); |
@@ -24,12 +13,17 @@ ide_decl_devset(wcache); | |||
24 | ide_decl_devset(acoustic); | 13 | ide_decl_devset(acoustic); |
25 | 14 | ||
26 | /* ide-disk_ioctl.c */ | 15 | /* ide-disk_ioctl.c */ |
27 | int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long); | 16 | int ide_disk_ioctl(ide_drive_t *, struct inode *, struct file *, unsigned int, |
17 | unsigned long); | ||
28 | 18 | ||
29 | #ifdef CONFIG_IDE_PROC_FS | 19 | #ifdef CONFIG_IDE_PROC_FS |
30 | /* ide-disk_proc.c */ | 20 | /* ide-disk_proc.c */ |
31 | extern ide_proc_entry_t ide_disk_proc[]; | 21 | extern ide_proc_entry_t ide_disk_proc[]; |
32 | extern const struct ide_proc_devset ide_disk_settings[]; | 22 | extern const struct ide_proc_devset ide_disk_settings[]; |
33 | #endif | 23 | #endif |
24 | #else | ||
25 | #define ide_disk_proc NULL | ||
26 | #define ide_disk_settings NULL | ||
27 | #endif | ||
34 | 28 | ||
35 | #endif /* __IDE_DISK_H */ | 29 | #endif /* __IDE_DISK_H */ |
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c index e6624eda9e69..a49698bcf966 100644 --- a/drivers/ide/ide-disk_ioctl.c +++ b/drivers/ide/ide-disk_ioctl.c | |||
@@ -13,12 +13,10 @@ static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { | |||
13 | { 0 } | 13 | { 0 } |
14 | }; | 14 | }; |
15 | 15 | ||
16 | int ide_disk_ioctl(struct inode *inode, struct file *file, | 16 | int ide_disk_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file, |
17 | unsigned int cmd, unsigned long arg) | 17 | unsigned int cmd, unsigned long arg) |
18 | { | 18 | { |
19 | struct block_device *bdev = inode->i_bdev; | 19 | struct block_device *bdev = inode->i_bdev; |
20 | struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj); | ||
21 | ide_drive_t *drive = idkp->drive; | ||
22 | int err; | 20 | int err; |
23 | 21 | ||
24 | err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); | 22 | err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 802e0968e32f..58746c748c12 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -68,7 +68,7 @@ | |||
68 | * Used to finish servicing a request. For read/write requests, we will call | 68 | * Used to finish servicing a request. For read/write requests, we will call |
69 | * ide_end_request to pass to the next buffer. | 69 | * ide_end_request to pass to the next buffer. |
70 | */ | 70 | */ |
71 | int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) | 71 | static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) |
72 | { | 72 | { |
73 | idefloppy_floppy_t *floppy = drive->driver_data; | 73 | idefloppy_floppy_t *floppy = drive->driver_data; |
74 | struct request *rq = HWGROUP(drive)->rq; | 74 | struct request *rq = HWGROUP(drive)->rq; |
@@ -280,13 +280,12 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, | |||
280 | pc->req_xfer = pc->buf_size = rq->data_len; | 280 | pc->req_xfer = pc->buf_size = rq->data_len; |
281 | } | 281 | } |
282 | 282 | ||
283 | ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq, | 283 | static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, |
284 | sector_t block_s) | 284 | struct request *rq, sector_t block) |
285 | { | 285 | { |
286 | idefloppy_floppy_t *floppy = drive->driver_data; | 286 | idefloppy_floppy_t *floppy = drive->driver_data; |
287 | ide_hwif_t *hwif = drive->hwif; | 287 | ide_hwif_t *hwif = drive->hwif; |
288 | struct ide_atapi_pc *pc; | 288 | struct ide_atapi_pc *pc; |
289 | unsigned long block = (unsigned long)block_s; | ||
290 | 289 | ||
291 | ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, " | 290 | ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, " |
292 | "errors: %d\n", | 291 | "errors: %d\n", |
@@ -316,7 +315,7 @@ ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq, | |||
316 | return ide_stopped; | 315 | return ide_stopped; |
317 | } | 316 | } |
318 | pc = &floppy->queued_pc; | 317 | pc = &floppy->queued_pc; |
319 | idefloppy_create_rw_cmd(drive, pc, rq, block); | 318 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); |
320 | } else if (blk_special_request(rq)) { | 319 | } else if (blk_special_request(rq)) { |
321 | pc = (struct ide_atapi_pc *) rq->buffer; | 320 | pc = (struct ide_atapi_pc *) rq->buffer; |
322 | } else if (blk_pc_request(rq)) { | 321 | } else if (blk_pc_request(rq)) { |
@@ -406,7 +405,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) | |||
406 | * Determine if a media is present in the floppy drive, and if so, its LBA | 405 | * Determine if a media is present in the floppy drive, and if so, its LBA |
407 | * capacity. | 406 | * capacity. |
408 | */ | 407 | */ |
409 | int ide_floppy_get_capacity(ide_drive_t *drive) | 408 | static int ide_floppy_get_capacity(ide_drive_t *drive) |
410 | { | 409 | { |
411 | idefloppy_floppy_t *floppy = drive->driver_data; | 410 | idefloppy_floppy_t *floppy = drive->driver_data; |
412 | struct gendisk *disk = floppy->disk; | 411 | struct gendisk *disk = floppy->disk; |
@@ -505,9 +504,9 @@ int ide_floppy_get_capacity(ide_drive_t *drive) | |||
505 | return rc; | 504 | return rc; |
506 | } | 505 | } |
507 | 506 | ||
508 | void ide_floppy_setup(ide_drive_t *drive) | 507 | static void ide_floppy_setup(ide_drive_t *drive) |
509 | { | 508 | { |
510 | struct ide_floppy_obj *floppy = drive->driver_data; | 509 | struct ide_disk_obj *floppy = drive->driver_data; |
511 | u16 *id = drive->id; | 510 | u16 *id = drive->id; |
512 | 511 | ||
513 | drive->pc_callback = ide_floppy_callback; | 512 | drive->pc_callback = ide_floppy_callback; |
@@ -547,3 +546,33 @@ void ide_floppy_setup(ide_drive_t *drive) | |||
547 | 546 | ||
548 | drive->dev_flags |= IDE_DFLAG_ATTACH; | 547 | drive->dev_flags |= IDE_DFLAG_ATTACH; |
549 | } | 548 | } |
549 | |||
550 | static void ide_floppy_flush(ide_drive_t *drive) | ||
551 | { | ||
552 | } | ||
553 | |||
554 | static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk) | ||
555 | { | ||
556 | int ret = 0; | ||
557 | |||
558 | if (ide_do_test_unit_ready(drive, disk)) | ||
559 | ide_do_start_stop(drive, disk, 1); | ||
560 | |||
561 | ret = ide_floppy_get_capacity(drive); | ||
562 | |||
563 | set_capacity(disk, ide_gd_capacity(drive)); | ||
564 | |||
565 | return ret; | ||
566 | } | ||
567 | |||
568 | const struct ide_disk_ops ide_atapi_disk_ops = { | ||
569 | .check = ide_check_atapi_device, | ||
570 | .get_capacity = ide_floppy_get_capacity, | ||
571 | .setup = ide_floppy_setup, | ||
572 | .flush = ide_floppy_flush, | ||
573 | .init_media = ide_floppy_init_media, | ||
574 | .set_doorlock = ide_set_media_lock, | ||
575 | .do_request = ide_floppy_do_request, | ||
576 | .end_request = ide_floppy_end_request, | ||
577 | .ioctl = ide_floppy_ioctl, | ||
578 | }; | ||
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h index b965da2f41ce..acebc8c5a827 100644 --- a/drivers/ide/ide-floppy.h +++ b/drivers/ide/ide-floppy.h | |||
@@ -1,48 +1,10 @@ | |||
1 | #ifndef __IDE_FLOPPY_H | 1 | #ifndef __IDE_FLOPPY_H |
2 | #define __IDE_FLOPPY_H | 2 | #define __IDE_FLOPPY_H |
3 | 3 | ||
4 | #define DRV_NAME "ide-floppy" | 4 | #include "ide-gd.h" |
5 | #define PFX DRV_NAME ": " | ||
6 | 5 | ||
7 | /* define to see debug info */ | 6 | #ifdef CONFIG_IDE_GD_ATAPI |
8 | #define IDEFLOPPY_DEBUG_LOG 0 | 7 | typedef struct ide_disk_obj idefloppy_floppy_t; |
9 | |||
10 | #if IDEFLOPPY_DEBUG_LOG | ||
11 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) | ||
12 | #else | ||
13 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
14 | #endif | ||
15 | |||
16 | /* | ||
17 | * Most of our global data which we need to save even as we leave the driver | ||
18 | * due to an interrupt or a timer event is stored in a variable of type | ||
19 | * idefloppy_floppy_t, defined below. | ||
20 | */ | ||
21 | typedef struct ide_floppy_obj { | ||
22 | ide_drive_t *drive; | ||
23 | ide_driver_t *driver; | ||
24 | struct gendisk *disk; | ||
25 | struct kref kref; | ||
26 | unsigned int openers; /* protected by BKL for now */ | ||
27 | |||
28 | /* Last failed packet command */ | ||
29 | struct ide_atapi_pc *failed_pc; | ||
30 | /* used for blk_{fs,pc}_request() requests */ | ||
31 | struct ide_atapi_pc queued_pc; | ||
32 | |||
33 | /* Last error information */ | ||
34 | u8 sense_key, asc, ascq; | ||
35 | |||
36 | int progress_indication; | ||
37 | |||
38 | /* Device information */ | ||
39 | /* Current format */ | ||
40 | int blocks, block_size, bs_factor; | ||
41 | /* Last format capacity descriptor */ | ||
42 | u8 cap_desc[8]; | ||
43 | /* Copy of the flexible disk page */ | ||
44 | u8 flexible_disk_page[32]; | ||
45 | } idefloppy_floppy_t; | ||
46 | 8 | ||
47 | /* | 9 | /* |
48 | * Pages of the SELECT SENSE / MODE SENSE packet commands. | 10 | * Pages of the SELECT SENSE / MODE SENSE packet commands. |
@@ -57,23 +19,23 @@ typedef struct ide_floppy_obj { | |||
57 | #define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 | 19 | #define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 |
58 | #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 | 20 | #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 |
59 | 21 | ||
60 | sector_t ide_gd_capacity(ide_drive_t *); | ||
61 | |||
62 | /* ide-floppy.c */ | 22 | /* ide-floppy.c */ |
23 | extern const struct ide_disk_ops ide_atapi_disk_ops; | ||
63 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); | 24 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); |
64 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); | 25 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); |
65 | int ide_floppy_get_capacity(ide_drive_t *); | ||
66 | void ide_floppy_setup(ide_drive_t *); | ||
67 | ide_startstop_t ide_floppy_do_request(ide_drive_t *, struct request *, sector_t); | ||
68 | int ide_floppy_end_request(ide_drive_t *, int, int); | ||
69 | 26 | ||
70 | /* ide-floppy_ioctl.c */ | 27 | /* ide-floppy_ioctl.c */ |
71 | int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long); | 28 | int ide_floppy_ioctl(ide_drive_t *, struct inode *, struct file *, unsigned int, |
29 | unsigned long); | ||
72 | 30 | ||
73 | #ifdef CONFIG_IDE_PROC_FS | 31 | #ifdef CONFIG_IDE_PROC_FS |
74 | /* ide-floppy_proc.c */ | 32 | /* ide-floppy_proc.c */ |
75 | extern ide_proc_entry_t ide_floppy_proc[]; | 33 | extern ide_proc_entry_t ide_floppy_proc[]; |
76 | extern const struct ide_proc_devset ide_floppy_settings[]; | 34 | extern const struct ide_proc_devset ide_floppy_settings[]; |
77 | #endif | 35 | #endif |
36 | #else | ||
37 | #define ide_floppy_proc NULL | ||
38 | #define ide_floppy_settings NULL | ||
39 | #endif | ||
78 | 40 | ||
79 | #endif /*__IDE_FLOPPY_H */ | 41 | #endif /*__IDE_FLOPPY_H */ |
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index b1f391df6cca..e8aa0a5bf5dc 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) | 34 | static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) |
35 | { | 35 | { |
36 | struct ide_floppy_obj *floppy = drive->driver_data; | 36 | struct ide_disk_obj *floppy = drive->driver_data; |
37 | struct ide_atapi_pc pc; | 37 | struct ide_atapi_pc pc; |
38 | u8 header_len, desc_cnt; | 38 | u8 header_len, desc_cnt; |
39 | int i, blocks, length, u_array_size, u_index; | 39 | int i, blocks, length, u_array_size, u_index; |
@@ -260,13 +260,10 @@ static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file, | |||
260 | } | 260 | } |
261 | } | 261 | } |
262 | 262 | ||
263 | int ide_floppy_ioctl(struct inode *inode, struct file *file, | 263 | int ide_floppy_ioctl(ide_drive_t *drive, struct inode *inode, |
264 | unsigned int cmd, unsigned long arg) | 264 | struct file *file, unsigned int cmd, unsigned long arg) |
265 | { | 265 | { |
266 | struct block_device *bdev = inode->i_bdev; | 266 | struct block_device *bdev = inode->i_bdev; |
267 | struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk, | ||
268 | ide_floppy_obj); | ||
269 | ide_drive_t *drive = floppy->drive; | ||
270 | struct ide_atapi_pc pc; | 267 | struct ide_atapi_pc pc; |
271 | void __user *argp = (void __user *)arg; | 268 | void __user *argp = (void __user *)arg; |
272 | int err; | 269 | int err; |
diff --git a/drivers/ide/ide-gd-floppy.c b/drivers/ide/ide-gd-floppy.c deleted file mode 100644 index 082800b9a558..000000000000 --- a/drivers/ide/ide-gd-floppy.c +++ /dev/null | |||
@@ -1,309 +0,0 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/string.h> | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/errno.h> | ||
6 | #include <linux/genhd.h> | ||
7 | #include <linux/mutex.h> | ||
8 | #include <linux/ide.h> | ||
9 | #include <linux/hdreg.h> | ||
10 | |||
11 | #include "ide-floppy.h" | ||
12 | |||
13 | #define IDEFLOPPY_VERSION "1.00" | ||
14 | |||
15 | /* module parameters */ | ||
16 | static unsigned long debug_mask; | ||
17 | module_param(debug_mask, ulong, 0644); | ||
18 | |||
19 | static DEFINE_MUTEX(ide_disk_ref_mutex); | ||
20 | |||
21 | static void ide_disk_release(struct kref *); | ||
22 | |||
23 | static struct ide_floppy_obj *ide_disk_get(struct gendisk *disk) | ||
24 | { | ||
25 | struct ide_floppy_obj *idkp = NULL; | ||
26 | |||
27 | mutex_lock(&ide_disk_ref_mutex); | ||
28 | idkp = ide_drv_g(disk, ide_floppy_obj); | ||
29 | if (idkp) { | ||
30 | if (ide_device_get(idkp->drive)) | ||
31 | idkp = NULL; | ||
32 | else | ||
33 | kref_get(&idkp->kref); | ||
34 | } | ||
35 | mutex_unlock(&ide_disk_ref_mutex); | ||
36 | return idkp; | ||
37 | } | ||
38 | |||
39 | static void ide_disk_put(struct ide_floppy_obj *idkp) | ||
40 | { | ||
41 | ide_drive_t *drive = idkp->drive; | ||
42 | |||
43 | mutex_lock(&ide_disk_ref_mutex); | ||
44 | kref_put(&idkp->kref, ide_disk_release); | ||
45 | ide_device_put(drive); | ||
46 | mutex_unlock(&ide_disk_ref_mutex); | ||
47 | } | ||
48 | |||
49 | sector_t ide_gd_capacity(ide_drive_t *drive) | ||
50 | { | ||
51 | return drive->capacity64; | ||
52 | } | ||
53 | |||
54 | static int ide_gd_probe(ide_drive_t *); | ||
55 | |||
56 | static void ide_gd_remove(ide_drive_t *drive) | ||
57 | { | ||
58 | struct ide_floppy_obj *idkp = drive->driver_data; | ||
59 | struct gendisk *g = idkp->disk; | ||
60 | |||
61 | ide_proc_unregister_driver(drive, idkp->driver); | ||
62 | |||
63 | del_gendisk(g); | ||
64 | |||
65 | ide_disk_put(idkp); | ||
66 | } | ||
67 | |||
68 | static void ide_disk_release(struct kref *kref) | ||
69 | { | ||
70 | struct ide_floppy_obj *idkp = to_ide_drv(kref, ide_floppy_obj); | ||
71 | ide_drive_t *drive = idkp->drive; | ||
72 | struct gendisk *g = idkp->disk; | ||
73 | |||
74 | drive->driver_data = NULL; | ||
75 | g->private_data = NULL; | ||
76 | put_disk(g); | ||
77 | kfree(idkp); | ||
78 | } | ||
79 | |||
80 | #ifdef CONFIG_IDE_PROC_FS | ||
81 | static ide_proc_entry_t *ide_floppy_proc_entries(ide_drive_t *drive) | ||
82 | { | ||
83 | return ide_floppy_proc; | ||
84 | } | ||
85 | |||
86 | static const struct ide_proc_devset *ide_floppy_proc_devsets(ide_drive_t *drive) | ||
87 | { | ||
88 | return ide_floppy_settings; | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | static ide_driver_t ide_gd_driver = { | ||
93 | .gen_driver = { | ||
94 | .owner = THIS_MODULE, | ||
95 | .name = "ide-floppy", | ||
96 | .bus = &ide_bus_type, | ||
97 | }, | ||
98 | .probe = ide_gd_probe, | ||
99 | .remove = ide_gd_remove, | ||
100 | .version = IDEFLOPPY_VERSION, | ||
101 | .do_request = ide_floppy_do_request, | ||
102 | .end_request = ide_floppy_end_request, | ||
103 | .error = __ide_error, | ||
104 | #ifdef CONFIG_IDE_PROC_FS | ||
105 | .proc_entries = ide_floppy_proc_entries, | ||
106 | .proc_devsets = ide_floppy_proc_devsets, | ||
107 | #endif | ||
108 | }; | ||
109 | |||
110 | static int ide_gd_open(struct inode *inode, struct file *filp) | ||
111 | { | ||
112 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
113 | struct ide_floppy_obj *idkp; | ||
114 | ide_drive_t *drive; | ||
115 | int ret = 0; | ||
116 | |||
117 | idkp = ide_disk_get(disk); | ||
118 | if (idkp == NULL) | ||
119 | return -ENXIO; | ||
120 | |||
121 | drive = idkp->drive; | ||
122 | |||
123 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
124 | |||
125 | idkp->openers++; | ||
126 | |||
127 | if (idkp->openers == 1) { | ||
128 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
129 | /* Just in case */ | ||
130 | |||
131 | if (ide_do_test_unit_ready(drive, disk)) | ||
132 | ide_do_start_stop(drive, disk, 1); | ||
133 | |||
134 | ret = ide_floppy_get_capacity(drive); | ||
135 | |||
136 | set_capacity(disk, ide_gd_capacity(drive)); | ||
137 | |||
138 | if (ret && (filp->f_flags & O_NDELAY) == 0) { | ||
139 | /* | ||
140 | * Allow O_NDELAY to open a drive without a disk, or with an | ||
141 | * unreadable disk, so that we can get the format capacity | ||
142 | * of the drive or begin the format - Sam | ||
143 | */ | ||
144 | ret = -EIO; | ||
145 | goto out_put_idkp; | ||
146 | } | ||
147 | |||
148 | if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) { | ||
149 | ret = -EROFS; | ||
150 | goto out_put_idkp; | ||
151 | } | ||
152 | |||
153 | ide_set_media_lock(drive, disk, 1); | ||
154 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | ||
155 | check_disk_change(inode->i_bdev); | ||
156 | } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { | ||
157 | ret = -EBUSY; | ||
158 | goto out_put_idkp; | ||
159 | } | ||
160 | return 0; | ||
161 | |||
162 | out_put_idkp: | ||
163 | idkp->openers--; | ||
164 | ide_disk_put(idkp); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static int ide_gd_release(struct inode *inode, struct file *filp) | ||
169 | { | ||
170 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
171 | struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj); | ||
172 | ide_drive_t *drive = idkp->drive; | ||
173 | |||
174 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
175 | |||
176 | if (idkp->openers == 1) { | ||
177 | ide_set_media_lock(drive, disk, 0); | ||
178 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
179 | } | ||
180 | |||
181 | idkp->openers--; | ||
182 | |||
183 | ide_disk_put(idkp); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
189 | { | ||
190 | struct ide_floppy_obj *idkp = ide_drv_g(bdev->bd_disk, ide_floppy_obj); | ||
191 | ide_drive_t *drive = idkp->drive; | ||
192 | |||
193 | geo->heads = drive->bios_head; | ||
194 | geo->sectors = drive->bios_sect; | ||
195 | geo->cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int ide_gd_media_changed(struct gendisk *disk) | ||
200 | { | ||
201 | struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj); | ||
202 | ide_drive_t *drive = idkp->drive; | ||
203 | int ret; | ||
204 | |||
205 | /* do not scan partitions twice if this is a removable device */ | ||
206 | if (drive->dev_flags & IDE_DFLAG_ATTACH) { | ||
207 | drive->dev_flags &= ~IDE_DFLAG_ATTACH; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED); | ||
212 | drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static int ide_gd_revalidate_disk(struct gendisk *disk) | ||
218 | { | ||
219 | struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj); | ||
220 | set_capacity(disk, ide_gd_capacity(idkp->drive)); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static struct block_device_operations ide_gd_ops = { | ||
225 | .owner = THIS_MODULE, | ||
226 | .open = ide_gd_open, | ||
227 | .release = ide_gd_release, | ||
228 | .ioctl = ide_floppy_ioctl, | ||
229 | .getgeo = ide_gd_getgeo, | ||
230 | .media_changed = ide_gd_media_changed, | ||
231 | .revalidate_disk = ide_gd_revalidate_disk | ||
232 | }; | ||
233 | |||
234 | static int ide_gd_probe(ide_drive_t *drive) | ||
235 | { | ||
236 | struct ide_floppy_obj *idkp; | ||
237 | struct gendisk *g; | ||
238 | |||
239 | if (!strstr("ide-floppy", drive->driver_req)) | ||
240 | goto failed; | ||
241 | |||
242 | if (drive->media != ide_floppy) | ||
243 | goto failed; | ||
244 | |||
245 | if (!ide_check_atapi_device(drive, DRV_NAME)) { | ||
246 | printk(KERN_ERR PFX "%s: not supported by this version of " | ||
247 | DRV_NAME "\n", drive->name); | ||
248 | goto failed; | ||
249 | } | ||
250 | idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); | ||
251 | if (!idkp) { | ||
252 | printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n", | ||
253 | drive->name); | ||
254 | goto failed; | ||
255 | } | ||
256 | |||
257 | g = alloc_disk_node(1 << PARTN_BITS, hwif_to_node(drive->hwif)); | ||
258 | if (!g) | ||
259 | goto out_free_idkp; | ||
260 | |||
261 | ide_init_disk(g, drive); | ||
262 | |||
263 | kref_init(&idkp->kref); | ||
264 | |||
265 | idkp->drive = drive; | ||
266 | idkp->driver = &ide_gd_driver; | ||
267 | idkp->disk = g; | ||
268 | |||
269 | g->private_data = &idkp->driver; | ||
270 | |||
271 | drive->driver_data = idkp; | ||
272 | |||
273 | drive->debug_mask = debug_mask; | ||
274 | |||
275 | ide_floppy_setup(drive); | ||
276 | |||
277 | set_capacity(g, ide_gd_capacity(drive)); | ||
278 | |||
279 | g->minors = 1 << PARTN_BITS; | ||
280 | g->driverfs_dev = &drive->gendev; | ||
281 | if (drive->dev_flags & IDE_DFLAG_REMOVABLE) | ||
282 | g->flags = GENHD_FL_REMOVABLE; | ||
283 | g->fops = &ide_gd_ops; | ||
284 | add_disk(g); | ||
285 | return 0; | ||
286 | |||
287 | out_free_idkp: | ||
288 | kfree(idkp); | ||
289 | failed: | ||
290 | return -ENODEV; | ||
291 | } | ||
292 | |||
293 | static int __init ide_gd_init(void) | ||
294 | { | ||
295 | printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n"); | ||
296 | return driver_register(&ide_gd_driver.gen_driver); | ||
297 | } | ||
298 | |||
299 | static void __exit ide_gd_exit(void) | ||
300 | { | ||
301 | driver_unregister(&ide_gd_driver.gen_driver); | ||
302 | } | ||
303 | |||
304 | MODULE_ALIAS("ide:*m-floppy*"); | ||
305 | MODULE_ALIAS("ide-floppy"); | ||
306 | module_init(ide_gd_init); | ||
307 | module_exit(ide_gd_exit); | ||
308 | MODULE_LICENSE("GPL"); | ||
309 | MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); | ||
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index a3d4ad7db2af..d44898f46c33 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c | |||
@@ -15,9 +15,14 @@ | |||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #include "ide-disk.h" | 17 | #include "ide-disk.h" |
18 | #include "ide-floppy.h" | ||
18 | 19 | ||
19 | #define IDE_GD_VERSION "1.18" | 20 | #define IDE_GD_VERSION "1.18" |
20 | 21 | ||
22 | /* module parameters */ | ||
23 | static unsigned long debug_mask; | ||
24 | module_param(debug_mask, ulong, 0644); | ||
25 | |||
21 | static DEFINE_MUTEX(ide_disk_ref_mutex); | 26 | static DEFINE_MUTEX(ide_disk_ref_mutex); |
22 | 27 | ||
23 | static void ide_disk_release(struct kref *); | 28 | static void ide_disk_release(struct kref *); |
@@ -64,7 +69,7 @@ static void ide_gd_remove(ide_drive_t *drive) | |||
64 | 69 | ||
65 | del_gendisk(g); | 70 | del_gendisk(g); |
66 | 71 | ||
67 | ide_disk_flush(drive); | 72 | drive->disk_ops->flush(drive); |
68 | 73 | ||
69 | ide_disk_put(idkp); | 74 | ide_disk_put(idkp); |
70 | } | 75 | } |
@@ -75,6 +80,7 @@ static void ide_disk_release(struct kref *kref) | |||
75 | ide_drive_t *drive = idkp->drive; | 80 | ide_drive_t *drive = idkp->drive; |
76 | struct gendisk *g = idkp->disk; | 81 | struct gendisk *g = idkp->disk; |
77 | 82 | ||
83 | drive->disk_ops = NULL; | ||
78 | drive->driver_data = NULL; | 84 | drive->driver_data = NULL; |
79 | g->private_data = NULL; | 85 | g->private_data = NULL; |
80 | put_disk(g); | 86 | put_disk(g); |
@@ -89,7 +95,7 @@ static void ide_disk_release(struct kref *kref) | |||
89 | static void ide_gd_resume(ide_drive_t *drive) | 95 | static void ide_gd_resume(ide_drive_t *drive) |
90 | { | 96 | { |
91 | if (ata_id_hpa_enabled(drive->id)) | 97 | if (ata_id_hpa_enabled(drive->id)) |
92 | ide_disk_init_capacity(drive); | 98 | (void)drive->disk_ops->get_capacity(drive); |
93 | } | 99 | } |
94 | 100 | ||
95 | static void ide_gd_shutdown(ide_drive_t *drive) | 101 | static void ide_gd_shutdown(ide_drive_t *drive) |
@@ -110,7 +116,7 @@ static void ide_gd_shutdown(ide_drive_t *drive) | |||
110 | #else | 116 | #else |
111 | if (system_state == SYSTEM_RESTART) { | 117 | if (system_state == SYSTEM_RESTART) { |
112 | #endif | 118 | #endif |
113 | ide_disk_flush(drive); | 119 | drive->disk_ops->flush(drive); |
114 | return; | 120 | return; |
115 | } | 121 | } |
116 | 122 | ||
@@ -122,19 +128,31 @@ static void ide_gd_shutdown(ide_drive_t *drive) | |||
122 | #ifdef CONFIG_IDE_PROC_FS | 128 | #ifdef CONFIG_IDE_PROC_FS |
123 | static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive) | 129 | static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive) |
124 | { | 130 | { |
125 | return ide_disk_proc; | 131 | return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc; |
126 | } | 132 | } |
127 | 133 | ||
128 | static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive) | 134 | static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive) |
129 | { | 135 | { |
130 | return ide_disk_settings; | 136 | return (drive->media == ide_disk) ? ide_disk_settings |
137 | : ide_floppy_settings; | ||
131 | } | 138 | } |
132 | #endif | 139 | #endif |
133 | 140 | ||
141 | static ide_startstop_t ide_gd_do_request(ide_drive_t *drive, | ||
142 | struct request *rq, sector_t sector) | ||
143 | { | ||
144 | return drive->disk_ops->do_request(drive, rq, sector); | ||
145 | } | ||
146 | |||
147 | static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs) | ||
148 | { | ||
149 | return drive->disk_ops->end_request(drive, uptodate, nrsecs); | ||
150 | } | ||
151 | |||
134 | static ide_driver_t ide_gd_driver = { | 152 | static ide_driver_t ide_gd_driver = { |
135 | .gen_driver = { | 153 | .gen_driver = { |
136 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
137 | .name = "ide-disk", | 155 | .name = "ide-gd", |
138 | .bus = &ide_bus_type, | 156 | .bus = &ide_bus_type, |
139 | }, | 157 | }, |
140 | .probe = ide_gd_probe, | 158 | .probe = ide_gd_probe, |
@@ -142,8 +160,8 @@ static ide_driver_t ide_gd_driver = { | |||
142 | .resume = ide_gd_resume, | 160 | .resume = ide_gd_resume, |
143 | .shutdown = ide_gd_shutdown, | 161 | .shutdown = ide_gd_shutdown, |
144 | .version = IDE_GD_VERSION, | 162 | .version = IDE_GD_VERSION, |
145 | .do_request = ide_do_rw_disk, | 163 | .do_request = ide_gd_do_request, |
146 | .end_request = ide_end_request, | 164 | .end_request = ide_gd_end_request, |
147 | .error = __ide_error, | 165 | .error = __ide_error, |
148 | #ifdef CONFIG_IDE_PROC_FS | 166 | #ifdef CONFIG_IDE_PROC_FS |
149 | .proc_entries = ide_disk_proc_entries, | 167 | .proc_entries = ide_disk_proc_entries, |
@@ -156,6 +174,7 @@ static int ide_gd_open(struct inode *inode, struct file *filp) | |||
156 | struct gendisk *disk = inode->i_bdev->bd_disk; | 174 | struct gendisk *disk = inode->i_bdev->bd_disk; |
157 | struct ide_disk_obj *idkp; | 175 | struct ide_disk_obj *idkp; |
158 | ide_drive_t *drive; | 176 | ide_drive_t *drive; |
177 | int ret = 0; | ||
159 | 178 | ||
160 | idkp = ide_disk_get(disk); | 179 | idkp = ide_disk_get(disk); |
161 | if (idkp == NULL) | 180 | if (idkp == NULL) |
@@ -163,19 +182,49 @@ static int ide_gd_open(struct inode *inode, struct file *filp) | |||
163 | 182 | ||
164 | drive = idkp->drive; | 183 | drive = idkp->drive; |
165 | 184 | ||
185 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
186 | |||
166 | idkp->openers++; | 187 | idkp->openers++; |
167 | 188 | ||
168 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { | 189 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { |
190 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
191 | /* Just in case */ | ||
192 | |||
193 | ret = drive->disk_ops->init_media(drive, disk); | ||
194 | |||
195 | /* | ||
196 | * Allow O_NDELAY to open a drive without a disk, or with an | ||
197 | * unreadable disk, so that we can get the format capacity | ||
198 | * of the drive or begin the format - Sam | ||
199 | */ | ||
200 | if (ret && (filp->f_flags & O_NDELAY) == 0) { | ||
201 | ret = -EIO; | ||
202 | goto out_put_idkp; | ||
203 | } | ||
204 | |||
205 | if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) { | ||
206 | ret = -EROFS; | ||
207 | goto out_put_idkp; | ||
208 | } | ||
209 | |||
169 | /* | 210 | /* |
170 | * Ignore the return code from door_lock, | 211 | * Ignore the return code from door_lock, |
171 | * since the open() has already succeeded, | 212 | * since the open() has already succeeded, |
172 | * and the door_lock is irrelevant at this point. | 213 | * and the door_lock is irrelevant at this point. |
173 | */ | 214 | */ |
174 | ide_disk_set_doorlock(drive, 1); | 215 | drive->disk_ops->set_doorlock(drive, disk, 1); |
175 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | 216 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; |
176 | check_disk_change(inode->i_bdev); | 217 | check_disk_change(inode->i_bdev); |
218 | } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { | ||
219 | ret = -EBUSY; | ||
220 | goto out_put_idkp; | ||
177 | } | 221 | } |
178 | return 0; | 222 | return 0; |
223 | |||
224 | out_put_idkp: | ||
225 | idkp->openers--; | ||
226 | ide_disk_put(idkp); | ||
227 | return ret; | ||
179 | } | 228 | } |
180 | 229 | ||
181 | static int ide_gd_release(struct inode *inode, struct file *filp) | 230 | static int ide_gd_release(struct inode *inode, struct file *filp) |
@@ -184,11 +233,15 @@ static int ide_gd_release(struct inode *inode, struct file *filp) | |||
184 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); | 233 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); |
185 | ide_drive_t *drive = idkp->drive; | 234 | ide_drive_t *drive = idkp->drive; |
186 | 235 | ||
236 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
237 | |||
187 | if (idkp->openers == 1) | 238 | if (idkp->openers == 1) |
188 | ide_disk_flush(drive); | 239 | drive->disk_ops->flush(drive); |
189 | 240 | ||
190 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) | 241 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { |
191 | ide_disk_set_doorlock(drive, 0); | 242 | drive->disk_ops->set_doorlock(drive, disk, 0); |
243 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
244 | } | ||
192 | 245 | ||
193 | idkp->openers--; | 246 | idkp->openers--; |
194 | 247 | ||
@@ -233,11 +286,21 @@ static int ide_gd_revalidate_disk(struct gendisk *disk) | |||
233 | return 0; | 286 | return 0; |
234 | } | 287 | } |
235 | 288 | ||
289 | static int ide_gd_ioctl(struct inode *inode, struct file *file, | ||
290 | unsigned int cmd, unsigned long arg) | ||
291 | { | ||
292 | struct block_device *bdev = inode->i_bdev; | ||
293 | struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj); | ||
294 | ide_drive_t *drive = idkp->drive; | ||
295 | |||
296 | return drive->disk_ops->ioctl(drive, inode, file, cmd, arg); | ||
297 | } | ||
298 | |||
236 | static struct block_device_operations ide_gd_ops = { | 299 | static struct block_device_operations ide_gd_ops = { |
237 | .owner = THIS_MODULE, | 300 | .owner = THIS_MODULE, |
238 | .open = ide_gd_open, | 301 | .open = ide_gd_open, |
239 | .release = ide_gd_release, | 302 | .release = ide_gd_release, |
240 | .ioctl = ide_disk_ioctl, | 303 | .ioctl = ide_gd_ioctl, |
241 | .getgeo = ide_gd_getgeo, | 304 | .getgeo = ide_gd_getgeo, |
242 | .media_changed = ide_gd_media_changed, | 305 | .media_changed = ide_gd_media_changed, |
243 | .revalidate_disk = ide_gd_revalidate_disk | 306 | .revalidate_disk = ide_gd_revalidate_disk |
@@ -245,19 +308,37 @@ static struct block_device_operations ide_gd_ops = { | |||
245 | 308 | ||
246 | static int ide_gd_probe(ide_drive_t *drive) | 309 | static int ide_gd_probe(ide_drive_t *drive) |
247 | { | 310 | { |
311 | const struct ide_disk_ops *disk_ops = NULL; | ||
248 | struct ide_disk_obj *idkp; | 312 | struct ide_disk_obj *idkp; |
249 | struct gendisk *g; | 313 | struct gendisk *g; |
250 | 314 | ||
251 | /* strstr("foo", "") is non-NULL */ | 315 | /* strstr("foo", "") is non-NULL */ |
252 | if (!strstr("ide-disk", drive->driver_req)) | 316 | if (!strstr("ide-gd", drive->driver_req)) |
317 | goto failed; | ||
318 | |||
319 | #ifdef CONFIG_IDE_GD_ATA | ||
320 | if (drive->media == ide_disk) | ||
321 | disk_ops = &ide_ata_disk_ops; | ||
322 | #endif | ||
323 | #ifdef CONFIG_IDE_GD_ATAPI | ||
324 | if (drive->media == ide_floppy) | ||
325 | disk_ops = &ide_atapi_disk_ops; | ||
326 | #endif | ||
327 | if (disk_ops == NULL) | ||
253 | goto failed; | 328 | goto failed; |
254 | 329 | ||
255 | if (drive->media != ide_disk) | 330 | if (disk_ops->check(drive, DRV_NAME) == 0) { |
331 | printk(KERN_ERR PFX "%s: not supported by this driver\n", | ||
332 | drive->name); | ||
256 | goto failed; | 333 | goto failed; |
334 | } | ||
257 | 335 | ||
258 | idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); | 336 | idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); |
259 | if (!idkp) | 337 | if (!idkp) { |
338 | printk(KERN_ERR PFX "%s: can't allocate a disk structure\n", | ||
339 | drive->name); | ||
260 | goto failed; | 340 | goto failed; |
341 | } | ||
261 | 342 | ||
262 | g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); | 343 | g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); |
263 | if (!g) | 344 | if (!g) |
@@ -274,8 +355,10 @@ static int ide_gd_probe(ide_drive_t *drive) | |||
274 | g->private_data = &idkp->driver; | 355 | g->private_data = &idkp->driver; |
275 | 356 | ||
276 | drive->driver_data = idkp; | 357 | drive->driver_data = idkp; |
358 | drive->debug_mask = debug_mask; | ||
359 | drive->disk_ops = disk_ops; | ||
277 | 360 | ||
278 | ide_disk_setup(drive); | 361 | disk_ops->setup(drive); |
279 | 362 | ||
280 | set_capacity(g, ide_gd_capacity(drive)); | 363 | set_capacity(g, ide_gd_capacity(drive)); |
281 | 364 | ||
@@ -296,6 +379,7 @@ failed: | |||
296 | 379 | ||
297 | static int __init ide_gd_init(void) | 380 | static int __init ide_gd_init(void) |
298 | { | 381 | { |
382 | printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n"); | ||
299 | return driver_register(&ide_gd_driver.gen_driver); | 383 | return driver_register(&ide_gd_driver.gen_driver); |
300 | } | 384 | } |
301 | 385 | ||
@@ -306,7 +390,9 @@ static void __exit ide_gd_exit(void) | |||
306 | 390 | ||
307 | MODULE_ALIAS("ide:*m-disk*"); | 391 | MODULE_ALIAS("ide:*m-disk*"); |
308 | MODULE_ALIAS("ide-disk"); | 392 | MODULE_ALIAS("ide-disk"); |
393 | MODULE_ALIAS("ide:*m-floppy*"); | ||
394 | MODULE_ALIAS("ide-floppy"); | ||
309 | module_init(ide_gd_init); | 395 | module_init(ide_gd_init); |
310 | module_exit(ide_gd_exit); | 396 | module_exit(ide_gd_exit); |
311 | MODULE_LICENSE("GPL"); | 397 | MODULE_LICENSE("GPL"); |
312 | MODULE_DESCRIPTION("ATA DISK Driver"); | 398 | MODULE_DESCRIPTION("generic ATA/ATAPI disk driver"); |
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h new file mode 100644 index 000000000000..7d3d101713e0 --- /dev/null +++ b/drivers/ide/ide-gd.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef __IDE_GD_H | ||
2 | #define __IDE_GD_H | ||
3 | |||
4 | #define DRV_NAME "ide-gd" | ||
5 | #define PFX DRV_NAME ": " | ||
6 | |||
7 | /* define to see debug info */ | ||
8 | #define IDE_GD_DEBUG_LOG 0 | ||
9 | |||
10 | #if IDE_GD_DEBUG_LOG | ||
11 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) | ||
12 | #else | ||
13 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
14 | #endif | ||
15 | |||
16 | struct ide_disk_obj { | ||
17 | ide_drive_t *drive; | ||
18 | ide_driver_t *driver; | ||
19 | struct gendisk *disk; | ||
20 | struct kref kref; | ||
21 | unsigned int openers; /* protected by BKL for now */ | ||
22 | |||
23 | /* Last failed packet command */ | ||
24 | struct ide_atapi_pc *failed_pc; | ||
25 | /* used for blk_{fs,pc}_request() requests */ | ||
26 | struct ide_atapi_pc queued_pc; | ||
27 | |||
28 | /* Last error information */ | ||
29 | u8 sense_key, asc, ascq; | ||
30 | |||
31 | int progress_indication; | ||
32 | |||
33 | /* Device information */ | ||
34 | /* Current format */ | ||
35 | int blocks, block_size, bs_factor; | ||
36 | /* Last format capacity descriptor */ | ||
37 | u8 cap_desc[8]; | ||
38 | /* Copy of the flexible disk page */ | ||
39 | u8 flexible_disk_page[32]; | ||
40 | }; | ||
41 | |||
42 | sector_t ide_gd_capacity(ide_drive_t *); | ||
43 | |||
44 | #endif /* __IDE_GD_H */ | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index e3e40427e00e..c7ff1e11ea85 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -179,7 +179,7 @@ config LEDS_TRIGGER_TIMER | |||
179 | 179 | ||
180 | config LEDS_TRIGGER_IDE_DISK | 180 | config LEDS_TRIGGER_IDE_DISK |
181 | bool "LED IDE Disk Trigger" | 181 | bool "LED IDE Disk Trigger" |
182 | depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK | 182 | depends on LEDS_TRIGGERS && IDE_GD_ATA |
183 | help | 183 | help |
184 | This allows LEDs to be controlled by IDE disk activity. | 184 | This allows LEDs to be controlled by IDE disk activity. |
185 | If unsure, say Y. | 185 | If unsure, say Y. |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 488808891acb..89e53cfbc787 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -461,6 +461,23 @@ struct ide_acpi_drive_link; | |||
461 | struct ide_acpi_hwif_link; | 461 | struct ide_acpi_hwif_link; |
462 | #endif | 462 | #endif |
463 | 463 | ||
464 | struct ide_drive_s; | ||
465 | |||
466 | struct ide_disk_ops { | ||
467 | int (*check)(struct ide_drive_s *, const char *); | ||
468 | int (*get_capacity)(struct ide_drive_s *); | ||
469 | void (*setup)(struct ide_drive_s *); | ||
470 | void (*flush)(struct ide_drive_s *); | ||
471 | int (*init_media)(struct ide_drive_s *, struct gendisk *); | ||
472 | int (*set_doorlock)(struct ide_drive_s *, struct gendisk *, | ||
473 | int); | ||
474 | ide_startstop_t (*do_request)(struct ide_drive_s *, struct request *, | ||
475 | sector_t); | ||
476 | int (*end_request)(struct ide_drive_s *, int, int); | ||
477 | int (*ioctl)(struct ide_drive_s *, struct inode *, | ||
478 | struct file *, unsigned int, unsigned long); | ||
479 | }; | ||
480 | |||
464 | /* ATAPI device flags */ | 481 | /* ATAPI device flags */ |
465 | enum { | 482 | enum { |
466 | IDE_AFLAG_DRQ_INTERRUPT = (1 << 0), | 483 | IDE_AFLAG_DRQ_INTERRUPT = (1 << 0), |
@@ -594,6 +611,8 @@ struct ide_drive_s { | |||
594 | #endif | 611 | #endif |
595 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ | 612 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ |
596 | 613 | ||
614 | const struct ide_disk_ops *disk_ops; | ||
615 | |||
597 | unsigned long dev_flags; | 616 | unsigned long dev_flags; |
598 | 617 | ||
599 | unsigned long sleep; /* sleep until this time */ | 618 | unsigned long sleep; /* sleep until this time */ |