]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ide/ide-gd-floppy.c
082800b9a558d3b1f86fe9af05efbb3bd4b40d66
[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 #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");