blob: 883f0c979c9ff12dca997979554dd493d716572b [file] [log] [blame]
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +02001#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>
Bruno Prémontb0aedb02009-04-22 20:33:41 +020010#include <linux/dmi.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020012
13#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
14#define IDE_DISK_MINORS (1 << PARTN_BITS)
15#else
16#define IDE_DISK_MINORS 0
17#endif
18
19#include "ide-disk.h"
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020020#include "ide-floppy.h"
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020021
22#define IDE_GD_VERSION "1.18"
23
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020024/* module parameters */
25static unsigned long debug_mask;
26module_param(debug_mask, ulong, 0644);
27
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020028static DEFINE_MUTEX(ide_disk_ref_mutex);
29
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010030static void ide_disk_release(struct device *);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020031
32static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
33{
34 struct ide_disk_obj *idkp = NULL;
35
36 mutex_lock(&ide_disk_ref_mutex);
37 idkp = ide_drv_g(disk, ide_disk_obj);
38 if (idkp) {
39 if (ide_device_get(idkp->drive))
40 idkp = NULL;
41 else
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010042 get_device(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020043 }
44 mutex_unlock(&ide_disk_ref_mutex);
45 return idkp;
46}
47
48static void ide_disk_put(struct ide_disk_obj *idkp)
49{
50 ide_drive_t *drive = idkp->drive;
51
52 mutex_lock(&ide_disk_ref_mutex);
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010053 put_device(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020054 ide_device_put(drive);
55 mutex_unlock(&ide_disk_ref_mutex);
56}
57
58sector_t ide_gd_capacity(ide_drive_t *drive)
59{
60 return drive->capacity64;
61}
62
63static int ide_gd_probe(ide_drive_t *);
64
65static void ide_gd_remove(ide_drive_t *drive)
66{
67 struct ide_disk_obj *idkp = drive->driver_data;
68 struct gendisk *g = idkp->disk;
69
70 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010071 device_del(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020072 del_gendisk(g);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020073 drive->disk_ops->flush(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020074
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010075 mutex_lock(&ide_disk_ref_mutex);
76 put_device(&idkp->dev);
77 mutex_unlock(&ide_disk_ref_mutex);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020078}
79
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010080static void ide_disk_release(struct device *dev)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020081{
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010082 struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020083 ide_drive_t *drive = idkp->drive;
84 struct gendisk *g = idkp->disk;
85
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020086 drive->disk_ops = NULL;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020087 drive->driver_data = NULL;
88 g->private_data = NULL;
89 put_disk(g);
90 kfree(idkp);
91}
92
93/*
94 * On HPA drives the capacity needs to be
95 * reinitilized on resume otherwise the disk
96 * can not be used and a hard reset is required
97 */
98static void ide_gd_resume(ide_drive_t *drive)
99{
100 if (ata_id_hpa_enabled(drive->id))
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200101 (void)drive->disk_ops->get_capacity(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200102}
103
Bruno Prémontb0aedb02009-04-22 20:33:41 +0200104static const struct dmi_system_id ide_coldreboot_table[] = {
105 {
106 /* Acer TravelMate 66x cuts power during reboot */
107 .ident = "Acer TravelMate 660",
108 .matches = {
109 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
110 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
111 },
112 },
113
114 { } /* terminate list */
115};
116
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200117static void ide_gd_shutdown(ide_drive_t *drive)
118{
119#ifdef CONFIG_ALPHA
120 /* On Alpha, halt(8) doesn't actually turn the machine off,
121 it puts you into the sort of firmware monitor. Typically,
122 it's used to boot another kernel image, so it's not much
123 different from reboot(8). Therefore, we don't need to
124 spin down the disk in this case, especially since Alpha
125 firmware doesn't handle disks in standby mode properly.
126 On the other hand, it's reasonably safe to turn the power
127 off when the shutdown process reaches the firmware prompt,
128 as the firmware initialization takes rather long time -
129 at least 10 seconds, which should be sufficient for
130 the disk to expire its write cache. */
131 if (system_state != SYSTEM_POWER_OFF) {
132#else
Bruno Prémontb0aedb02009-04-22 20:33:41 +0200133 if (system_state == SYSTEM_RESTART &&
134 !dmi_check_system(ide_coldreboot_table)) {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200135#endif
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200136 drive->disk_ops->flush(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200137 return;
138 }
139
140 printk(KERN_INFO "Shutdown: %s\n", drive->name);
141
142 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
143}
144
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200145#ifdef CONFIG_IDE_PROC_FS
146static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
147{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200148 return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200149}
150
151static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
152{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200153 return (drive->media == ide_disk) ? ide_disk_settings
154 : ide_floppy_settings;
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200155}
156#endif
157
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200158static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
159 struct request *rq, sector_t sector)
160{
161 return drive->disk_ops->do_request(drive, rq, sector);
162}
163
Bartlomiej Zolnierkiewicz7f3c8682009-01-06 17:20:53 +0100164static struct ide_driver ide_gd_driver = {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200165 .gen_driver = {
166 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200167 .name = "ide-gd",
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200168 .bus = &ide_bus_type,
169 },
170 .probe = ide_gd_probe,
171 .remove = ide_gd_remove,
172 .resume = ide_gd_resume,
173 .shutdown = ide_gd_shutdown,
174 .version = IDE_GD_VERSION,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200175 .do_request = ide_gd_do_request,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200176#ifdef CONFIG_IDE_PROC_FS
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200177 .proc_entries = ide_disk_proc_entries,
178 .proc_devsets = ide_disk_proc_devsets,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200179#endif
180};
181
Al Virob2f21e02008-10-16 10:34:00 -0400182static int ide_gd_open(struct block_device *bdev, fmode_t mode)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200183{
Al Virob2f21e02008-10-16 10:34:00 -0400184 struct gendisk *disk = bdev->bd_disk;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200185 struct ide_disk_obj *idkp;
186 ide_drive_t *drive;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200187 int ret = 0;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200188
189 idkp = ide_disk_get(disk);
190 if (idkp == NULL)
191 return -ENXIO;
192
193 drive = idkp->drive;
194
Borislav Petkov088b1b82009-01-02 13:34:47 +0100195 ide_debug_log(IDE_DBG_FUNC, "enter");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200196
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200197 idkp->openers++;
198
199 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200200 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
201 /* Just in case */
202
203 ret = drive->disk_ops->init_media(drive, disk);
204
205 /*
206 * Allow O_NDELAY to open a drive without a disk, or with an
207 * unreadable disk, so that we can get the format capacity
208 * of the drive or begin the format - Sam
209 */
Al Virob2f21e02008-10-16 10:34:00 -0400210 if (ret && (mode & FMODE_NDELAY) == 0) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200211 ret = -EIO;
212 goto out_put_idkp;
213 }
214
Al Virob2f21e02008-10-16 10:34:00 -0400215 if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200216 ret = -EROFS;
217 goto out_put_idkp;
218 }
219
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200220 /*
221 * Ignore the return code from door_lock,
222 * since the open() has already succeeded,
223 * and the door_lock is irrelevant at this point.
224 */
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200225 drive->disk_ops->set_doorlock(drive, disk, 1);
Bartlomiej Zolnierkiewiczcedd1202008-10-17 18:09:12 +0200226 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
Al Virob2f21e02008-10-16 10:34:00 -0400227 check_disk_change(bdev);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200228 } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
229 ret = -EBUSY;
230 goto out_put_idkp;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200231 }
232 return 0;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200233
234out_put_idkp:
235 idkp->openers--;
236 ide_disk_put(idkp);
237 return ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200238}
239
Al Virob2f21e02008-10-16 10:34:00 -0400240static int ide_gd_release(struct gendisk *disk, fmode_t mode)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200241{
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200242 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
243 ide_drive_t *drive = idkp->drive;
244
Borislav Petkov088b1b82009-01-02 13:34:47 +0100245 ide_debug_log(IDE_DBG_FUNC, "enter");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200246
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200247 if (idkp->openers == 1)
248 drive->disk_ops->flush(drive);
249
250 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
251 drive->disk_ops->set_doorlock(drive, disk, 0);
252 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
253 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200254
255 idkp->openers--;
256
257 ide_disk_put(idkp);
258
259 return 0;
260}
261
262static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
263{
264 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
265 ide_drive_t *drive = idkp->drive;
266
267 geo->heads = drive->bios_head;
268 geo->sectors = drive->bios_sect;
269 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
270 return 0;
271}
272
273static int ide_gd_media_changed(struct gendisk *disk)
274{
275 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
276 ide_drive_t *drive = idkp->drive;
Bartlomiej Zolnierkiewiczcedd1202008-10-17 18:09:12 +0200277 int ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200278
279 /* do not scan partitions twice if this is a removable device */
280 if (drive->dev_flags & IDE_DFLAG_ATTACH) {
281 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
282 return 0;
283 }
284
Bartlomiej Zolnierkiewiczcedd1202008-10-17 18:09:12 +0200285 ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
286 drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
287
288 return ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200289}
290
Tejun Heoc3e33e02010-05-15 20:09:29 +0200291static void ide_gd_unlock_native_capacity(struct gendisk *disk)
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200292{
293 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
294 ide_drive_t *drive = idkp->drive;
295 const struct ide_disk_ops *disk_ops = drive->disk_ops;
296
Tejun Heoc3e33e02010-05-15 20:09:29 +0200297 if (disk_ops->unlock_native_capacity)
298 disk_ops->unlock_native_capacity(drive);
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200299}
300
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200301static int ide_gd_revalidate_disk(struct gendisk *disk)
302{
303 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
Borislav Petkov52ebb432008-11-02 21:40:10 +0100304 ide_drive_t *drive = idkp->drive;
305
306 if (ide_gd_media_changed(disk))
307 drive->disk_ops->get_capacity(drive);
308
309 set_capacity(disk, ide_gd_capacity(drive));
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200310 return 0;
311}
312
Al Virob2f21e02008-10-16 10:34:00 -0400313static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200314 unsigned int cmd, unsigned long arg)
315{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200316 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
317 ide_drive_t *drive = idkp->drive;
318
Al Virob2f21e02008-10-16 10:34:00 -0400319 return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200320}
321
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700322static const struct block_device_operations ide_gd_ops = {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200323 .owner = THIS_MODULE,
Al Virob2f21e02008-10-16 10:34:00 -0400324 .open = ide_gd_open,
325 .release = ide_gd_release,
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200326 .ioctl = ide_gd_ioctl,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200327 .getgeo = ide_gd_getgeo,
328 .media_changed = ide_gd_media_changed,
Tejun Heoc3e33e02010-05-15 20:09:29 +0200329 .unlock_native_capacity = ide_gd_unlock_native_capacity,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200330 .revalidate_disk = ide_gd_revalidate_disk
331};
332
333static int ide_gd_probe(ide_drive_t *drive)
334{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200335 const struct ide_disk_ops *disk_ops = NULL;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200336 struct ide_disk_obj *idkp;
337 struct gendisk *g;
338
339 /* strstr("foo", "") is non-NULL */
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200340 if (!strstr("ide-gd", drive->driver_req))
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200341 goto failed;
342
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200343#ifdef CONFIG_IDE_GD_ATA
344 if (drive->media == ide_disk)
345 disk_ops = &ide_ata_disk_ops;
346#endif
347#ifdef CONFIG_IDE_GD_ATAPI
348 if (drive->media == ide_floppy)
349 disk_ops = &ide_atapi_disk_ops;
350#endif
351 if (disk_ops == NULL)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200352 goto failed;
353
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200354 if (disk_ops->check(drive, DRV_NAME) == 0) {
355 printk(KERN_ERR PFX "%s: not supported by this driver\n",
356 drive->name);
357 goto failed;
358 }
359
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200360 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200361 if (!idkp) {
362 printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
363 drive->name);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200364 goto failed;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200365 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200366
367 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
368 if (!g)
369 goto out_free_idkp;
370
371 ide_init_disk(g, drive);
372
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100373 idkp->dev.parent = &drive->gendev;
374 idkp->dev.release = ide_disk_release;
375 dev_set_name(&idkp->dev, dev_name(&drive->gendev));
376
377 if (device_register(&idkp->dev))
378 goto out_free_disk;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200379
380 idkp->drive = drive;
381 idkp->driver = &ide_gd_driver;
382 idkp->disk = g;
383
384 g->private_data = &idkp->driver;
385
386 drive->driver_data = idkp;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200387 drive->debug_mask = debug_mask;
388 drive->disk_ops = disk_ops;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200389
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200390 disk_ops->setup(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200391
392 set_capacity(g, ide_gd_capacity(drive));
393
394 g->minors = IDE_DISK_MINORS;
395 g->driverfs_dev = &drive->gendev;
396 g->flags |= GENHD_FL_EXT_DEVT;
397 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
398 g->flags = GENHD_FL_REMOVABLE;
399 g->fops = &ide_gd_ops;
400 add_disk(g);
401 return 0;
402
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100403out_free_disk:
404 put_disk(g);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200405out_free_idkp:
406 kfree(idkp);
407failed:
408 return -ENODEV;
409}
410
411static int __init ide_gd_init(void)
412{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200413 printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200414 return driver_register(&ide_gd_driver.gen_driver);
415}
416
417static void __exit ide_gd_exit(void)
418{
419 driver_unregister(&ide_gd_driver.gen_driver);
420}
421
422MODULE_ALIAS("ide:*m-disk*");
423MODULE_ALIAS("ide-disk");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200424MODULE_ALIAS("ide:*m-floppy*");
425MODULE_ALIAS("ide-floppy");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200426module_init(ide_gd_init);
427module_exit(ide_gd_exit);
428MODULE_LICENSE("GPL");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200429MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");