ide-disk: factor out generic disk handling code to ide-gd.c
[safe/jmp/linux-2.6] / drivers / ide / ide-gd.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 #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
12 #define IDE_DISK_MINORS         (1 << PARTN_BITS)
13 #else
14 #define IDE_DISK_MINORS         0
15 #endif
16
17 #include "ide-disk.h"
18
19 #define IDE_GD_VERSION  "1.18"
20
21 static DEFINE_MUTEX(ide_disk_ref_mutex);
22
23 static void ide_disk_release(struct kref *);
24
25 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
26 {
27         struct ide_disk_obj *idkp = NULL;
28
29         mutex_lock(&ide_disk_ref_mutex);
30         idkp = ide_drv_g(disk, ide_disk_obj);
31         if (idkp) {
32                 if (ide_device_get(idkp->drive))
33                         idkp = NULL;
34                 else
35                         kref_get(&idkp->kref);
36         }
37         mutex_unlock(&ide_disk_ref_mutex);
38         return idkp;
39 }
40
41 static void ide_disk_put(struct ide_disk_obj *idkp)
42 {
43         ide_drive_t *drive = idkp->drive;
44
45         mutex_lock(&ide_disk_ref_mutex);
46         kref_put(&idkp->kref, ide_disk_release);
47         ide_device_put(drive);
48         mutex_unlock(&ide_disk_ref_mutex);
49 }
50
51 sector_t ide_gd_capacity(ide_drive_t *drive)
52 {
53         return drive->capacity64;
54 }
55
56 static int ide_gd_probe(ide_drive_t *);
57
58 static void ide_gd_remove(ide_drive_t *drive)
59 {
60         struct ide_disk_obj *idkp = drive->driver_data;
61         struct gendisk *g = idkp->disk;
62
63         ide_proc_unregister_driver(drive, idkp->driver);
64
65         del_gendisk(g);
66
67         ide_disk_flush(drive);
68
69         ide_disk_put(idkp);
70 }
71
72 static void ide_disk_release(struct kref *kref)
73 {
74         struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
75         ide_drive_t *drive = idkp->drive;
76         struct gendisk *g = idkp->disk;
77
78         drive->driver_data = NULL;
79         g->private_data = NULL;
80         put_disk(g);
81         kfree(idkp);
82 }
83
84 /*
85  * On HPA drives the capacity needs to be
86  * reinitilized on resume otherwise the disk
87  * can not be used and a hard reset is required
88  */
89 static void ide_gd_resume(ide_drive_t *drive)
90 {
91         if (ata_id_hpa_enabled(drive->id))
92                 ide_disk_init_capacity(drive);
93 }
94
95 static void ide_gd_shutdown(ide_drive_t *drive)
96 {
97 #ifdef  CONFIG_ALPHA
98         /* On Alpha, halt(8) doesn't actually turn the machine off,
99            it puts you into the sort of firmware monitor. Typically,
100            it's used to boot another kernel image, so it's not much
101            different from reboot(8). Therefore, we don't need to
102            spin down the disk in this case, especially since Alpha
103            firmware doesn't handle disks in standby mode properly.
104            On the other hand, it's reasonably safe to turn the power
105            off when the shutdown process reaches the firmware prompt,
106            as the firmware initialization takes rather long time -
107            at least 10 seconds, which should be sufficient for
108            the disk to expire its write cache. */
109         if (system_state != SYSTEM_POWER_OFF) {
110 #else
111         if (system_state == SYSTEM_RESTART) {
112 #endif
113                 ide_disk_flush(drive);
114                 return;
115         }
116
117         printk(KERN_INFO "Shutdown: %s\n", drive->name);
118
119         drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
120 }
121
122 static ide_driver_t ide_gd_driver = {
123         .gen_driver = {
124                 .owner          = THIS_MODULE,
125                 .name           = "ide-disk",
126                 .bus            = &ide_bus_type,
127         },
128         .probe                  = ide_gd_probe,
129         .remove                 = ide_gd_remove,
130         .resume                 = ide_gd_resume,
131         .shutdown               = ide_gd_shutdown,
132         .version                = IDE_GD_VERSION,
133         .do_request             = ide_do_rw_disk,
134         .end_request            = ide_end_request,
135         .error                  = __ide_error,
136 #ifdef CONFIG_IDE_PROC_FS
137         .proc                   = ide_disk_proc,
138         .settings               = ide_disk_settings,
139 #endif
140 };
141
142 static int ide_gd_open(struct inode *inode, struct file *filp)
143 {
144         struct gendisk *disk = inode->i_bdev->bd_disk;
145         struct ide_disk_obj *idkp;
146         ide_drive_t *drive;
147
148         idkp = ide_disk_get(disk);
149         if (idkp == NULL)
150                 return -ENXIO;
151
152         drive = idkp->drive;
153
154         idkp->openers++;
155
156         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
157                 /*
158                  * Ignore the return code from door_lock,
159                  * since the open() has already succeeded,
160                  * and the door_lock is irrelevant at this point.
161                  */
162                 ide_disk_set_doorlock(drive, 1);
163                 check_disk_change(inode->i_bdev);
164         }
165         return 0;
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_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
172         ide_drive_t *drive = idkp->drive;
173
174         if (idkp->openers == 1)
175                 ide_disk_flush(drive);
176
177         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1)
178                 ide_disk_set_doorlock(drive, 0);
179
180         idkp->openers--;
181
182         ide_disk_put(idkp);
183
184         return 0;
185 }
186
187 static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
188 {
189         struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
190         ide_drive_t *drive = idkp->drive;
191
192         geo->heads = drive->bios_head;
193         geo->sectors = drive->bios_sect;
194         geo->cylinders = (u16)drive->bios_cyl; /* truncate */
195         return 0;
196 }
197
198 static int ide_gd_media_changed(struct gendisk *disk)
199 {
200         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
201         ide_drive_t *drive = idkp->drive;
202
203         /* do not scan partitions twice if this is a removable device */
204         if (drive->dev_flags & IDE_DFLAG_ATTACH) {
205                 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
206                 return 0;
207         }
208
209         /* if removable, always assume it was changed */
210         return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
211 }
212
213 static int ide_gd_revalidate_disk(struct gendisk *disk)
214 {
215         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
216         set_capacity(disk, ide_gd_capacity(idkp->drive));
217         return 0;
218 }
219
220 static struct block_device_operations ide_gd_ops = {
221         .owner                  = THIS_MODULE,
222         .open                   = ide_gd_open,
223         .release                = ide_gd_release,
224         .ioctl                  = ide_disk_ioctl,
225         .getgeo                 = ide_gd_getgeo,
226         .media_changed          = ide_gd_media_changed,
227         .revalidate_disk        = ide_gd_revalidate_disk
228 };
229
230 static int ide_gd_probe(ide_drive_t *drive)
231 {
232         struct ide_disk_obj *idkp;
233         struct gendisk *g;
234
235         /* strstr("foo", "") is non-NULL */
236         if (!strstr("ide-disk", drive->driver_req))
237                 goto failed;
238
239         if (drive->media != ide_disk)
240                 goto failed;
241
242         idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
243         if (!idkp)
244                 goto failed;
245
246         g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
247         if (!g)
248                 goto out_free_idkp;
249
250         ide_init_disk(g, drive);
251
252         kref_init(&idkp->kref);
253
254         idkp->drive = drive;
255         idkp->driver = &ide_gd_driver;
256         idkp->disk = g;
257
258         g->private_data = &idkp->driver;
259
260         drive->driver_data = idkp;
261
262         ide_disk_setup(drive);
263
264         set_capacity(g, ide_gd_capacity(drive));
265
266         g->minors = IDE_DISK_MINORS;
267         g->driverfs_dev = &drive->gendev;
268         g->flags |= GENHD_FL_EXT_DEVT;
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         return driver_register(&ide_gd_driver.gen_driver);
284 }
285
286 static void __exit ide_gd_exit(void)
287 {
288         driver_unregister(&ide_gd_driver.gen_driver);
289 }
290
291 MODULE_ALIAS("ide:*m-disk*");
292 MODULE_ALIAS("ide-disk");
293 module_init(ide_gd_init);
294 module_exit(ide_gd_exit);
295 MODULE_LICENSE("GPL");
296 MODULE_DESCRIPTION("ATA DISK Driver");