]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ide/ide-gd-floppy.c
ide: prepare for merging ide-gd-floppy.c with ide-gd.c
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-gd-floppy.c
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 static ide_driver_t ide_gd_driver = {
81         .gen_driver = {
82                 .owner          = THIS_MODULE,
83                 .name           = "ide-floppy",
84                 .bus            = &ide_bus_type,
85         },
86         .probe                  = ide_gd_probe,
87         .remove                 = ide_gd_remove,
88         .version                = IDEFLOPPY_VERSION,
89         .do_request             = ide_floppy_do_request,
90         .end_request            = ide_floppy_end_request,
91         .error                  = __ide_error,
92 #ifdef CONFIG_IDE_PROC_FS
93         .proc                   = ide_floppy_proc,
94         .settings               = ide_floppy_settings,
95 #endif
96 };
97
98 static int ide_gd_open(struct inode *inode, struct file *filp)
99 {
100         struct gendisk *disk = inode->i_bdev->bd_disk;
101         struct ide_floppy_obj *idkp;
102         ide_drive_t *drive;
103         int ret = 0;
104
105         idkp = ide_disk_get(disk);
106         if (idkp == NULL)
107                 return -ENXIO;
108
109         drive = idkp->drive;
110
111         ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
112
113         idkp->openers++;
114
115         if (idkp->openers == 1) {
116                 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
117                 /* Just in case */
118
119                 if (ide_do_test_unit_ready(drive, disk))
120                         ide_do_start_stop(drive, disk, 1);
121
122                 ret = ide_floppy_get_capacity(drive);
123
124                 set_capacity(disk, ide_gd_capacity(drive));
125
126                 if (ret && (filp->f_flags & O_NDELAY) == 0) {
127                     /*
128                      * Allow O_NDELAY to open a drive without a disk, or with an
129                      * unreadable disk, so that we can get the format capacity
130                      * of the drive or begin the format - Sam
131                      */
132                         ret = -EIO;
133                         goto out_put_idkp;
134                 }
135
136                 if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) {
137                         ret = -EROFS;
138                         goto out_put_idkp;
139                 }
140
141                 ide_set_media_lock(drive, disk, 1);
142                 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
143                 check_disk_change(inode->i_bdev);
144         } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
145                 ret = -EBUSY;
146                 goto out_put_idkp;
147         }
148         return 0;
149
150 out_put_idkp:
151         idkp->openers--;
152         ide_disk_put(idkp);
153         return ret;
154 }
155
156 static int ide_gd_release(struct inode *inode, struct file *filp)
157 {
158         struct gendisk *disk = inode->i_bdev->bd_disk;
159         struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
160         ide_drive_t *drive = idkp->drive;
161
162         ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
163
164         if (idkp->openers == 1) {
165                 ide_set_media_lock(drive, disk, 0);
166                 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
167         }
168
169         idkp->openers--;
170
171         ide_disk_put(idkp);
172
173         return 0;
174 }
175
176 static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
177 {
178         struct ide_floppy_obj *idkp = ide_drv_g(bdev->bd_disk, ide_floppy_obj);
179         ide_drive_t *drive = idkp->drive;
180
181         geo->heads = drive->bios_head;
182         geo->sectors = drive->bios_sect;
183         geo->cylinders = (u16)drive->bios_cyl; /* truncate */
184         return 0;
185 }
186
187 static int ide_gd_media_changed(struct gendisk *disk)
188 {
189         struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
190         ide_drive_t *drive = idkp->drive;
191         int ret;
192
193         /* do not scan partitions twice if this is a removable device */
194         if (drive->dev_flags & IDE_DFLAG_ATTACH) {
195                 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
196                 return 0;
197         }
198
199         ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
200         drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
201
202         return ret;
203 }
204
205 static int ide_gd_revalidate_disk(struct gendisk *disk)
206 {
207         struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
208         set_capacity(disk, ide_gd_capacity(idkp->drive));
209         return 0;
210 }
211
212 static struct block_device_operations ide_gd_ops = {
213         .owner                  = THIS_MODULE,
214         .open                   = ide_gd_open,
215         .release                = ide_gd_release,
216         .ioctl                  = ide_floppy_ioctl,
217         .getgeo                 = ide_gd_getgeo,
218         .media_changed          = ide_gd_media_changed,
219         .revalidate_disk        = ide_gd_revalidate_disk
220 };
221
222 static int ide_gd_probe(ide_drive_t *drive)
223 {
224         struct ide_floppy_obj *idkp;
225         struct gendisk *g;
226
227         if (!strstr("ide-floppy", drive->driver_req))
228                 goto failed;
229
230         if (drive->media != ide_floppy)
231                 goto failed;
232
233         if (!ide_check_atapi_device(drive, DRV_NAME)) {
234                 printk(KERN_ERR PFX "%s: not supported by this version of "
235                        DRV_NAME "\n", drive->name);
236                 goto failed;
237         }
238         idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
239         if (!idkp) {
240                 printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
241                        drive->name);
242                 goto failed;
243         }
244
245         g = alloc_disk_node(1 << PARTN_BITS, hwif_to_node(drive->hwif));
246         if (!g)
247                 goto out_free_idkp;
248
249         ide_init_disk(g, drive);
250
251         kref_init(&idkp->kref);
252
253         idkp->drive = drive;
254         idkp->driver = &ide_gd_driver;
255         idkp->disk = g;
256
257         g->private_data = &idkp->driver;
258
259         drive->driver_data = idkp;
260
261         drive->debug_mask = debug_mask;
262
263         ide_floppy_setup(drive);
264
265         set_capacity(g, ide_gd_capacity(drive));
266
267         g->minors = 1 << PARTN_BITS;
268         g->driverfs_dev = &drive->gendev;
269         if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
270                 g->flags = GENHD_FL_REMOVABLE;
271         g->fops = &ide_gd_ops;
272         add_disk(g);
273         return 0;
274
275 out_free_idkp:
276         kfree(idkp);
277 failed:
278         return -ENODEV;
279 }
280
281 static int __init ide_gd_init(void)
282 {
283         printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
284         return driver_register(&ide_gd_driver.gen_driver);
285 }
286
287 static void __exit ide_gd_exit(void)
288 {
289         driver_unregister(&ide_gd_driver.gen_driver);
290 }
291
292 MODULE_ALIAS("ide:*m-floppy*");
293 MODULE_ALIAS("ide-floppy");
294 module_init(ide_gd_init);
295 module_exit(ide_gd_exit);
296 MODULE_LICENSE("GPL");
297 MODULE_DESCRIPTION("ATAPI FLOPPY Driver");