]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/ide/ide-gd.c
ide: prepare for merging ide-gd-floppy.c with ide-gd.c
[mirror_ubuntu-bionic-kernel.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>
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
21static DEFINE_MUTEX(ide_disk_ref_mutex);
22
23static void ide_disk_release(struct kref *);
24
25static 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
41static 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
51sector_t ide_gd_capacity(ide_drive_t *drive)
52{
53 return drive->capacity64;
54}
55
56static int ide_gd_probe(ide_drive_t *);
57
58static 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
72static 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 */
89static 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
95static 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
122static 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
142static 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);
cedd120c 163 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
5fef0e5c
BZ
164 check_disk_change(inode->i_bdev);
165 }
166 return 0;
167}
168
169static int ide_gd_release(struct inode *inode, struct file *filp)
170{
171 struct gendisk *disk = inode->i_bdev->bd_disk;
172 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
173 ide_drive_t *drive = idkp->drive;
174
175 if (idkp->openers == 1)
176 ide_disk_flush(drive);
177
178 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1)
179 ide_disk_set_doorlock(drive, 0);
180
181 idkp->openers--;
182
183 ide_disk_put(idkp);
184
185 return 0;
186}
187
188static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
189{
190 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_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
199static int ide_gd_media_changed(struct gendisk *disk)
200{
201 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
202 ide_drive_t *drive = idkp->drive;
cedd120c 203 int ret;
5fef0e5c
BZ
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
cedd120c
BZ
211 ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
212 drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
213
214 return ret;
5fef0e5c
BZ
215}
216
217static int ide_gd_revalidate_disk(struct gendisk *disk)
218{
219 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
220 set_capacity(disk, ide_gd_capacity(idkp->drive));
221 return 0;
222}
223
224static struct block_device_operations ide_gd_ops = {
225 .owner = THIS_MODULE,
226 .open = ide_gd_open,
227 .release = ide_gd_release,
228 .ioctl = ide_disk_ioctl,
229 .getgeo = ide_gd_getgeo,
230 .media_changed = ide_gd_media_changed,
231 .revalidate_disk = ide_gd_revalidate_disk
232};
233
234static int ide_gd_probe(ide_drive_t *drive)
235{
236 struct ide_disk_obj *idkp;
237 struct gendisk *g;
238
239 /* strstr("foo", "") is non-NULL */
240 if (!strstr("ide-disk", drive->driver_req))
241 goto failed;
242
243 if (drive->media != ide_disk)
244 goto failed;
245
246 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
247 if (!idkp)
248 goto failed;
249
250 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
251 if (!g)
252 goto out_free_idkp;
253
254 ide_init_disk(g, drive);
255
256 kref_init(&idkp->kref);
257
258 idkp->drive = drive;
259 idkp->driver = &ide_gd_driver;
260 idkp->disk = g;
261
262 g->private_data = &idkp->driver;
263
264 drive->driver_data = idkp;
265
266 ide_disk_setup(drive);
267
268 set_capacity(g, ide_gd_capacity(drive));
269
270 g->minors = IDE_DISK_MINORS;
271 g->driverfs_dev = &drive->gendev;
272 g->flags |= GENHD_FL_EXT_DEVT;
273 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
274 g->flags = GENHD_FL_REMOVABLE;
275 g->fops = &ide_gd_ops;
276 add_disk(g);
277 return 0;
278
279out_free_idkp:
280 kfree(idkp);
281failed:
282 return -ENODEV;
283}
284
285static int __init ide_gd_init(void)
286{
287 return driver_register(&ide_gd_driver.gen_driver);
288}
289
290static void __exit ide_gd_exit(void)
291{
292 driver_unregister(&ide_gd_driver.gen_driver);
293}
294
295MODULE_ALIAS("ide:*m-disk*");
296MODULE_ALIAS("ide-disk");
297module_init(ide_gd_init);
298module_exit(ide_gd_exit);
299MODULE_LICENSE("GPL");
300MODULE_DESCRIPTION("ATA DISK Driver");