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