partitions: add ->set_capacity block device method
[deliverable/linux.git] / drivers / ide / ide-gd.c
CommitLineData
5fef0e5c
BZ
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>
b0aedb04 10#include <linux/dmi.h>
5fef0e5c
BZ
11
12#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
13#define IDE_DISK_MINORS (1 << PARTN_BITS)
14#else
15#define IDE_DISK_MINORS 0
16#endif
17
18#include "ide-disk.h"
806f80a6 19#include "ide-floppy.h"
5fef0e5c
BZ
20
21#define IDE_GD_VERSION "1.18"
22
806f80a6
BZ
23/* module parameters */
24static unsigned long debug_mask;
25module_param(debug_mask, ulong, 0644);
26
5fef0e5c
BZ
27static DEFINE_MUTEX(ide_disk_ref_mutex);
28
8fed4368 29static void ide_disk_release(struct device *);
5fef0e5c
BZ
30
31static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
32{
33 struct ide_disk_obj *idkp = NULL;
34
35 mutex_lock(&ide_disk_ref_mutex);
36 idkp = ide_drv_g(disk, ide_disk_obj);
37 if (idkp) {
38 if (ide_device_get(idkp->drive))
39 idkp = NULL;
40 else
8fed4368 41 get_device(&idkp->dev);
5fef0e5c
BZ
42 }
43 mutex_unlock(&ide_disk_ref_mutex);
44 return idkp;
45}
46
47static void ide_disk_put(struct ide_disk_obj *idkp)
48{
49 ide_drive_t *drive = idkp->drive;
50
51 mutex_lock(&ide_disk_ref_mutex);
8fed4368 52 put_device(&idkp->dev);
5fef0e5c
BZ
53 ide_device_put(drive);
54 mutex_unlock(&ide_disk_ref_mutex);
55}
56
57sector_t ide_gd_capacity(ide_drive_t *drive)
58{
59 return drive->capacity64;
60}
61
62static int ide_gd_probe(ide_drive_t *);
63
64static void ide_gd_remove(ide_drive_t *drive)
65{
66 struct ide_disk_obj *idkp = drive->driver_data;
67 struct gendisk *g = idkp->disk;
68
69 ide_proc_unregister_driver(drive, idkp->driver);
8fed4368 70 device_del(&idkp->dev);
5fef0e5c 71 del_gendisk(g);
806f80a6 72 drive->disk_ops->flush(drive);
5fef0e5c 73
8fed4368
BZ
74 mutex_lock(&ide_disk_ref_mutex);
75 put_device(&idkp->dev);
76 mutex_unlock(&ide_disk_ref_mutex);
5fef0e5c
BZ
77}
78
8fed4368 79static void ide_disk_release(struct device *dev)
5fef0e5c 80{
8fed4368 81 struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
5fef0e5c
BZ
82 ide_drive_t *drive = idkp->drive;
83 struct gendisk *g = idkp->disk;
84
806f80a6 85 drive->disk_ops = NULL;
5fef0e5c
BZ
86 drive->driver_data = NULL;
87 g->private_data = NULL;
88 put_disk(g);
89 kfree(idkp);
90}
91
92/*
93 * On HPA drives the capacity needs to be
94 * reinitilized on resume otherwise the disk
95 * can not be used and a hard reset is required
96 */
97static void ide_gd_resume(ide_drive_t *drive)
98{
99 if (ata_id_hpa_enabled(drive->id))
806f80a6 100 (void)drive->disk_ops->get_capacity(drive);
5fef0e5c
BZ
101}
102
b0aedb04
BP
103static const struct dmi_system_id ide_coldreboot_table[] = {
104 {
105 /* Acer TravelMate 66x cuts power during reboot */
106 .ident = "Acer TravelMate 660",
107 .matches = {
108 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
109 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
110 },
111 },
112
113 { } /* terminate list */
114};
115
5fef0e5c
BZ
116static void ide_gd_shutdown(ide_drive_t *drive)
117{
118#ifdef CONFIG_ALPHA
119 /* On Alpha, halt(8) doesn't actually turn the machine off,
120 it puts you into the sort of firmware monitor. Typically,
121 it's used to boot another kernel image, so it's not much
122 different from reboot(8). Therefore, we don't need to
123 spin down the disk in this case, especially since Alpha
124 firmware doesn't handle disks in standby mode properly.
125 On the other hand, it's reasonably safe to turn the power
126 off when the shutdown process reaches the firmware prompt,
127 as the firmware initialization takes rather long time -
128 at least 10 seconds, which should be sufficient for
129 the disk to expire its write cache. */
130 if (system_state != SYSTEM_POWER_OFF) {
131#else
b0aedb04
BP
132 if (system_state == SYSTEM_RESTART &&
133 !dmi_check_system(ide_coldreboot_table)) {
5fef0e5c 134#endif
806f80a6 135 drive->disk_ops->flush(drive);
5fef0e5c
BZ
136 return;
137 }
138
139 printk(KERN_INFO "Shutdown: %s\n", drive->name);
140
141 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
142}
143
79cb3803
BZ
144#ifdef CONFIG_IDE_PROC_FS
145static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
146{
806f80a6 147 return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
79cb3803
BZ
148}
149
150static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
151{
806f80a6
BZ
152 return (drive->media == ide_disk) ? ide_disk_settings
153 : ide_floppy_settings;
79cb3803
BZ
154}
155#endif
156
806f80a6
BZ
157static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
158 struct request *rq, sector_t sector)
159{
160 return drive->disk_ops->do_request(drive, rq, sector);
161}
162
7f3c868b 163static struct ide_driver ide_gd_driver = {
5fef0e5c
BZ
164 .gen_driver = {
165 .owner = THIS_MODULE,
806f80a6 166 .name = "ide-gd",
5fef0e5c
BZ
167 .bus = &ide_bus_type,
168 },
169 .probe = ide_gd_probe,
170 .remove = ide_gd_remove,
171 .resume = ide_gd_resume,
172 .shutdown = ide_gd_shutdown,
173 .version = IDE_GD_VERSION,
806f80a6 174 .do_request = ide_gd_do_request,
5fef0e5c 175#ifdef CONFIG_IDE_PROC_FS
79cb3803
BZ
176 .proc_entries = ide_disk_proc_entries,
177 .proc_devsets = ide_disk_proc_devsets,
5fef0e5c
BZ
178#endif
179};
180
b2f21e05 181static int ide_gd_open(struct block_device *bdev, fmode_t mode)
5fef0e5c 182{
b2f21e05 183 struct gendisk *disk = bdev->bd_disk;
5fef0e5c
BZ
184 struct ide_disk_obj *idkp;
185 ide_drive_t *drive;
806f80a6 186 int ret = 0;
5fef0e5c
BZ
187
188 idkp = ide_disk_get(disk);
189 if (idkp == NULL)
190 return -ENXIO;
191
192 drive = idkp->drive;
193
088b1b88 194 ide_debug_log(IDE_DBG_FUNC, "enter");
806f80a6 195
5fef0e5c
BZ
196 idkp->openers++;
197
198 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
806f80a6
BZ
199 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
200 /* Just in case */
201
202 ret = drive->disk_ops->init_media(drive, disk);
203
204 /*
205 * Allow O_NDELAY to open a drive without a disk, or with an
206 * unreadable disk, so that we can get the format capacity
207 * of the drive or begin the format - Sam
208 */
b2f21e05 209 if (ret && (mode & FMODE_NDELAY) == 0) {
806f80a6
BZ
210 ret = -EIO;
211 goto out_put_idkp;
212 }
213
b2f21e05 214 if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
806f80a6
BZ
215 ret = -EROFS;
216 goto out_put_idkp;
217 }
218
5fef0e5c
BZ
219 /*
220 * Ignore the return code from door_lock,
221 * since the open() has already succeeded,
222 * and the door_lock is irrelevant at this point.
223 */
806f80a6 224 drive->disk_ops->set_doorlock(drive, disk, 1);
cedd120c 225 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
b2f21e05 226 check_disk_change(bdev);
806f80a6
BZ
227 } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
228 ret = -EBUSY;
229 goto out_put_idkp;
5fef0e5c
BZ
230 }
231 return 0;
806f80a6
BZ
232
233out_put_idkp:
234 idkp->openers--;
235 ide_disk_put(idkp);
236 return ret;
5fef0e5c
BZ
237}
238
b2f21e05 239static int ide_gd_release(struct gendisk *disk, fmode_t mode)
5fef0e5c 240{
5fef0e5c
BZ
241 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
242 ide_drive_t *drive = idkp->drive;
243
088b1b88 244 ide_debug_log(IDE_DBG_FUNC, "enter");
806f80a6 245
5fef0e5c 246 if (idkp->openers == 1)
806f80a6 247 drive->disk_ops->flush(drive);
5fef0e5c 248
806f80a6
BZ
249 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
250 drive->disk_ops->set_doorlock(drive, disk, 0);
251 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
252 }
5fef0e5c
BZ
253
254 idkp->openers--;
255
256 ide_disk_put(idkp);
257
258 return 0;
259}
260
261static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
262{
263 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
264 ide_drive_t *drive = idkp->drive;
265
266 geo->heads = drive->bios_head;
267 geo->sectors = drive->bios_sect;
268 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
269 return 0;
270}
271
272static int ide_gd_media_changed(struct gendisk *disk)
273{
274 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
275 ide_drive_t *drive = idkp->drive;
cedd120c 276 int ret;
5fef0e5c
BZ
277
278 /* do not scan partitions twice if this is a removable device */
279 if (drive->dev_flags & IDE_DFLAG_ATTACH) {
280 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
281 return 0;
282 }
283
cedd120c
BZ
284 ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
285 drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
286
287 return ret;
5fef0e5c
BZ
288}
289
290static int ide_gd_revalidate_disk(struct gendisk *disk)
291{
292 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
52ebb438
BP
293 ide_drive_t *drive = idkp->drive;
294
295 if (ide_gd_media_changed(disk))
296 drive->disk_ops->get_capacity(drive);
297
298 set_capacity(disk, ide_gd_capacity(drive));
5fef0e5c
BZ
299 return 0;
300}
301
b2f21e05 302static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
806f80a6
BZ
303 unsigned int cmd, unsigned long arg)
304{
806f80a6
BZ
305 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
306 ide_drive_t *drive = idkp->drive;
307
b2f21e05 308 return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
806f80a6
BZ
309}
310
5fef0e5c
BZ
311static struct block_device_operations ide_gd_ops = {
312 .owner = THIS_MODULE,
b2f21e05
AV
313 .open = ide_gd_open,
314 .release = ide_gd_release,
315 .locked_ioctl = ide_gd_ioctl,
5fef0e5c
BZ
316 .getgeo = ide_gd_getgeo,
317 .media_changed = ide_gd_media_changed,
318 .revalidate_disk = ide_gd_revalidate_disk
319};
320
321static int ide_gd_probe(ide_drive_t *drive)
322{
806f80a6 323 const struct ide_disk_ops *disk_ops = NULL;
5fef0e5c
BZ
324 struct ide_disk_obj *idkp;
325 struct gendisk *g;
326
327 /* strstr("foo", "") is non-NULL */
806f80a6
BZ
328 if (!strstr("ide-gd", drive->driver_req))
329 goto failed;
330
331#ifdef CONFIG_IDE_GD_ATA
332 if (drive->media == ide_disk)
333 disk_ops = &ide_ata_disk_ops;
334#endif
335#ifdef CONFIG_IDE_GD_ATAPI
336 if (drive->media == ide_floppy)
337 disk_ops = &ide_atapi_disk_ops;
338#endif
339 if (disk_ops == NULL)
5fef0e5c
BZ
340 goto failed;
341
806f80a6
BZ
342 if (disk_ops->check(drive, DRV_NAME) == 0) {
343 printk(KERN_ERR PFX "%s: not supported by this driver\n",
344 drive->name);
5fef0e5c 345 goto failed;
806f80a6 346 }
5fef0e5c
BZ
347
348 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
806f80a6
BZ
349 if (!idkp) {
350 printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
351 drive->name);
5fef0e5c 352 goto failed;
806f80a6 353 }
5fef0e5c
BZ
354
355 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
356 if (!g)
357 goto out_free_idkp;
358
359 ide_init_disk(g, drive);
360
8fed4368
BZ
361 idkp->dev.parent = &drive->gendev;
362 idkp->dev.release = ide_disk_release;
363 dev_set_name(&idkp->dev, dev_name(&drive->gendev));
364
365 if (device_register(&idkp->dev))
366 goto out_free_disk;
5fef0e5c
BZ
367
368 idkp->drive = drive;
369 idkp->driver = &ide_gd_driver;
370 idkp->disk = g;
371
372 g->private_data = &idkp->driver;
373
374 drive->driver_data = idkp;
806f80a6
BZ
375 drive->debug_mask = debug_mask;
376 drive->disk_ops = disk_ops;
5fef0e5c 377
806f80a6 378 disk_ops->setup(drive);
5fef0e5c
BZ
379
380 set_capacity(g, ide_gd_capacity(drive));
381
382 g->minors = IDE_DISK_MINORS;
383 g->driverfs_dev = &drive->gendev;
384 g->flags |= GENHD_FL_EXT_DEVT;
385 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
386 g->flags = GENHD_FL_REMOVABLE;
387 g->fops = &ide_gd_ops;
388 add_disk(g);
389 return 0;
390
8fed4368
BZ
391out_free_disk:
392 put_disk(g);
5fef0e5c
BZ
393out_free_idkp:
394 kfree(idkp);
395failed:
396 return -ENODEV;
397}
398
399static int __init ide_gd_init(void)
400{
806f80a6 401 printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
5fef0e5c
BZ
402 return driver_register(&ide_gd_driver.gen_driver);
403}
404
405static void __exit ide_gd_exit(void)
406{
407 driver_unregister(&ide_gd_driver.gen_driver);
408}
409
410MODULE_ALIAS("ide:*m-disk*");
411MODULE_ALIAS("ide-disk");
806f80a6
BZ
412MODULE_ALIAS("ide:*m-floppy*");
413MODULE_ALIAS("ide-floppy");
5fef0e5c
BZ
414module_init(ide_gd_init);
415module_exit(ide_gd_exit);
416MODULE_LICENSE("GPL");
806f80a6 417MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");
This page took 0.086167 seconds and 5 git commands to generate.