Blame view

drivers/ide/ide-gd.c 10.8 KB
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
1
2
3
4
5
6
7
8
9
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/genhd.h>
  #include <linux/mutex.h>
  #include <linux/ide.h>
  #include <linux/hdreg.h>
b0aedb04e   Bruno Prémont   ide: Stop disks o...
10
  #include <linux/dmi.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
12
13
14
15
16
17
18
19
  
  #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
  #define IDE_DISK_MINORS		(1 << PARTN_BITS)
  #else
  #define IDE_DISK_MINORS		0
  #endif
  
  #include "ide-disk.h"
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
20
  #include "ide-floppy.h"
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
21
22
  
  #define IDE_GD_VERSION	"1.18"
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
23
  /* module parameters */
2a48fc0ab   Arnd Bergmann   block: autoconver...
24
  static DEFINE_MUTEX(ide_gd_mutex);
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
25
26
  static unsigned long debug_mask;
  module_param(debug_mask, ulong, 0644);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
27
  static DEFINE_MUTEX(ide_disk_ref_mutex);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
28
  static void ide_disk_release(struct device *);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
29
30
31
32
33
34
35
36
37
38
39
  
  static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
  {
  	struct ide_disk_obj *idkp = NULL;
  
  	mutex_lock(&ide_disk_ref_mutex);
  	idkp = ide_drv_g(disk, ide_disk_obj);
  	if (idkp) {
  		if (ide_device_get(idkp->drive))
  			idkp = NULL;
  		else
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
40
  			get_device(&idkp->dev);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
41
42
43
44
45
46
47
48
49
50
  	}
  	mutex_unlock(&ide_disk_ref_mutex);
  	return idkp;
  }
  
  static void ide_disk_put(struct ide_disk_obj *idkp)
  {
  	ide_drive_t *drive = idkp->drive;
  
  	mutex_lock(&ide_disk_ref_mutex);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
51
  	put_device(&idkp->dev);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  	ide_device_put(drive);
  	mutex_unlock(&ide_disk_ref_mutex);
  }
  
  sector_t ide_gd_capacity(ide_drive_t *drive)
  {
  	return drive->capacity64;
  }
  
  static int ide_gd_probe(ide_drive_t *);
  
  static void ide_gd_remove(ide_drive_t *drive)
  {
  	struct ide_disk_obj *idkp = drive->driver_data;
  	struct gendisk *g = idkp->disk;
  
  	ide_proc_unregister_driver(drive, idkp->driver);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
69
  	device_del(&idkp->dev);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
70
  	del_gendisk(g);
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
71
  	drive->disk_ops->flush(drive);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
72

8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
73
74
75
  	mutex_lock(&ide_disk_ref_mutex);
  	put_device(&idkp->dev);
  	mutex_unlock(&ide_disk_ref_mutex);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
76
  }
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
77
  static void ide_disk_release(struct device *dev)
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
78
  {
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
79
  	struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
80
81
  	ide_drive_t *drive = idkp->drive;
  	struct gendisk *g = idkp->disk;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
82
  	drive->disk_ops = NULL;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
83
84
85
86
87
88
89
90
  	drive->driver_data = NULL;
  	g->private_data = NULL;
  	put_disk(g);
  	kfree(idkp);
  }
  
  /*
   * On HPA drives the capacity needs to be
421f91d21   Uwe Kleine-König   fix typos concern...
91
   * reinitialized on resume otherwise the disk
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
92
93
94
95
96
   * can not be used and a hard reset is required
   */
  static void ide_gd_resume(ide_drive_t *drive)
  {
  	if (ata_id_hpa_enabled(drive->id))
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
97
  		(void)drive->disk_ops->get_capacity(drive);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
98
  }
b0aedb04e   Bruno Prémont   ide: Stop disks o...
99
100
101
102
103
104
105
106
107
108
109
110
  static const struct dmi_system_id ide_coldreboot_table[] = {
  	{
  		/* Acer TravelMate 66x cuts power during reboot */
  		.ident   = "Acer TravelMate 660",
  		.matches = {
  			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
  		},
  	},
  
  	{ }	/* terminate list */
  };
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  static void ide_gd_shutdown(ide_drive_t *drive)
  {
  #ifdef	CONFIG_ALPHA
  	/* On Alpha, halt(8) doesn't actually turn the machine off,
  	   it puts you into the sort of firmware monitor. Typically,
  	   it's used to boot another kernel image, so it's not much
  	   different from reboot(8). Therefore, we don't need to
  	   spin down the disk in this case, especially since Alpha
  	   firmware doesn't handle disks in standby mode properly.
  	   On the other hand, it's reasonably safe to turn the power
  	   off when the shutdown process reaches the firmware prompt,
  	   as the firmware initialization takes rather long time -
  	   at least 10 seconds, which should be sufficient for
  	   the disk to expire its write cache. */
  	if (system_state != SYSTEM_POWER_OFF) {
  #else
b0aedb04e   Bruno Prémont   ide: Stop disks o...
127
128
  	if (system_state == SYSTEM_RESTART &&
  		!dmi_check_system(ide_coldreboot_table)) {
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
129
  #endif
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
130
  		drive->disk_ops->flush(drive);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
131
132
133
134
135
136
137
138
  		return;
  	}
  
  	printk(KERN_INFO "Shutdown: %s
  ", drive->name);
  
  	drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
  }
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
139
140
141
  #ifdef CONFIG_IDE_PROC_FS
  static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
142
  	return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
143
144
145
146
  }
  
  static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
147
148
  	return (drive->media == ide_disk) ? ide_disk_settings
  					  : ide_floppy_settings;
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
149
150
  }
  #endif
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
151
152
153
154
155
  static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
  					 struct request *rq, sector_t sector)
  {
  	return drive->disk_ops->do_request(drive, rq, sector);
  }
7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
156
  static struct ide_driver ide_gd_driver = {
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
157
158
  	.gen_driver = {
  		.owner		= THIS_MODULE,
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
159
  		.name		= "ide-gd",
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
160
161
162
163
164
165
166
  		.bus		= &ide_bus_type,
  	},
  	.probe			= ide_gd_probe,
  	.remove			= ide_gd_remove,
  	.resume			= ide_gd_resume,
  	.shutdown		= ide_gd_shutdown,
  	.version		= IDE_GD_VERSION,
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
167
  	.do_request		= ide_gd_do_request,
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
168
  #ifdef CONFIG_IDE_PROC_FS
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
169
170
  	.proc_entries		= ide_disk_proc_entries,
  	.proc_devsets		= ide_disk_proc_devsets,
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
171
172
  #endif
  };
b2f21e057   Al Viro   [PATCH] switch id...
173
  static int ide_gd_open(struct block_device *bdev, fmode_t mode)
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
174
  {
b2f21e057   Al Viro   [PATCH] switch id...
175
  	struct gendisk *disk = bdev->bd_disk;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
176
177
  	struct ide_disk_obj *idkp;
  	ide_drive_t *drive;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
178
  	int ret = 0;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
179
180
181
182
183
184
  
  	idkp = ide_disk_get(disk);
  	if (idkp == NULL)
  		return -ENXIO;
  
  	drive = idkp->drive;
088b1b886   Borislav Petkov   ide: improve debu...
185
  	ide_debug_log(IDE_DBG_FUNC, "enter");
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
186

5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
187
188
189
  	idkp->openers++;
  
  	if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
190
191
192
193
194
195
196
197
198
199
  		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
  		/* Just in case */
  
  		ret = drive->disk_ops->init_media(drive, disk);
  
  		/*
  		 * Allow O_NDELAY to open a drive without a disk, or with an
  		 * unreadable disk, so that we can get the format capacity
  		 * of the drive or begin the format - Sam
  		 */
b2f21e057   Al Viro   [PATCH] switch id...
200
  		if (ret && (mode & FMODE_NDELAY) == 0) {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
201
202
203
  			ret = -EIO;
  			goto out_put_idkp;
  		}
b2f21e057   Al Viro   [PATCH] switch id...
204
  		if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
205
206
207
  			ret = -EROFS;
  			goto out_put_idkp;
  		}
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
208
209
210
211
212
  		/*
  		 * Ignore the return code from door_lock,
  		 * since the open() has already succeeded,
  		 * and the door_lock is irrelevant at this point.
  		 */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
213
  		drive->disk_ops->set_doorlock(drive, disk, 1);
cedd120ca   Bartlomiej Zolnierkiewicz   ide-disk: use IDE...
214
  		drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
b2f21e057   Al Viro   [PATCH] switch id...
215
  		check_disk_change(bdev);
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
216
217
218
  	} else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
  		ret = -EBUSY;
  		goto out_put_idkp;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
219
220
  	}
  	return 0;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
221
222
223
224
225
  
  out_put_idkp:
  	idkp->openers--;
  	ide_disk_put(idkp);
  	return ret;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
226
  }
6e9624b8c   Arnd Bergmann   block: push down ...
227
228
229
  static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
  {
  	int ret;
2a48fc0ab   Arnd Bergmann   block: autoconver...
230
  	mutex_lock(&ide_gd_mutex);
6e9624b8c   Arnd Bergmann   block: push down ...
231
  	ret = ide_gd_open(bdev, mode);
2a48fc0ab   Arnd Bergmann   block: autoconver...
232
  	mutex_unlock(&ide_gd_mutex);
6e9624b8c   Arnd Bergmann   block: push down ...
233
234
235
  
  	return ret;
  }
b2f21e057   Al Viro   [PATCH] switch id...
236
  static int ide_gd_release(struct gendisk *disk, fmode_t mode)
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
237
  {
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
238
239
  	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
  	ide_drive_t *drive = idkp->drive;
088b1b886   Borislav Petkov   ide: improve debu...
240
  	ide_debug_log(IDE_DBG_FUNC, "enter");
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
241

2a48fc0ab   Arnd Bergmann   block: autoconver...
242
  	mutex_lock(&ide_gd_mutex);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
243
  	if (idkp->openers == 1)
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
244
  		drive->disk_ops->flush(drive);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
245

806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
246
247
248
249
  	if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
  		drive->disk_ops->set_doorlock(drive, disk, 0);
  		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
  	}
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
250
251
252
253
  
  	idkp->openers--;
  
  	ide_disk_put(idkp);
2a48fc0ab   Arnd Bergmann   block: autoconver...
254
  	mutex_unlock(&ide_gd_mutex);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  
  	return 0;
  }
  
  static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
  {
  	struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
  	ide_drive_t *drive = idkp->drive;
  
  	geo->heads = drive->bios_head;
  	geo->sectors = drive->bios_sect;
  	geo->cylinders = (u16)drive->bios_cyl; /* truncate */
  	return 0;
  }
5b03a1b14   Tejun Heo   ide: Convert to b...
269
270
  static unsigned int ide_gd_check_events(struct gendisk *disk,
  					unsigned int clearing)
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
271
272
273
  {
  	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
  	ide_drive_t *drive = idkp->drive;
5b03a1b14   Tejun Heo   ide: Convert to b...
274
  	bool ret;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
275
276
277
278
279
280
  
  	/* do not scan partitions twice if this is a removable device */
  	if (drive->dev_flags & IDE_DFLAG_ATTACH) {
  		drive->dev_flags &= ~IDE_DFLAG_ATTACH;
  		return 0;
  	}
7eec77a18   Tejun Heo   ide: unexport DIS...
281
282
283
284
285
286
  	/*
  	 * The following is used to force revalidation on the first open on
  	 * removeable devices, and never gets reported to userland as
  	 * genhd->events is 0.  This is intended as removeable ide disk
  	 * can't really detect MEDIA_CHANGE events.
  	 */
5b03a1b14   Tejun Heo   ide: Convert to b...
287
  	ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
cedd120ca   Bartlomiej Zolnierkiewicz   ide-disk: use IDE...
288
  	drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
5b03a1b14   Tejun Heo   ide: Convert to b...
289
  	return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
290
  }
c3e33e043   Tejun Heo   block,ide: simpli...
291
  static void ide_gd_unlock_native_capacity(struct gendisk *disk)
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
292
293
294
295
  {
  	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
  	ide_drive_t *drive = idkp->drive;
  	const struct ide_disk_ops *disk_ops = drive->disk_ops;
c3e33e043   Tejun Heo   block,ide: simpli...
296
297
  	if (disk_ops->unlock_native_capacity)
  		disk_ops->unlock_native_capacity(drive);
e957b60d1   Bartlomiej Zolnierkiewicz   ide-gd: implement...
298
  }
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
299
300
301
  static int ide_gd_revalidate_disk(struct gendisk *disk)
  {
  	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
52ebb438e   Borislav Petkov   ide-gd: re-get ca...
302
  	ide_drive_t *drive = idkp->drive;
5b03a1b14   Tejun Heo   ide: Convert to b...
303
  	if (ide_gd_check_events(disk, 0))
52ebb438e   Borislav Petkov   ide-gd: re-get ca...
304
305
306
  		drive->disk_ops->get_capacity(drive);
  
  	set_capacity(disk, ide_gd_capacity(drive));
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
307
308
  	return 0;
  }
b2f21e057   Al Viro   [PATCH] switch id...
309
  static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
310
311
  			     unsigned int cmd, unsigned long arg)
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
312
313
  	struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
  	ide_drive_t *drive = idkp->drive;
b2f21e057   Al Viro   [PATCH] switch id...
314
  	return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
315
  }
83d5cde47   Alexey Dobriyan   const: make block...
316
  static const struct block_device_operations ide_gd_ops = {
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
317
  	.owner			= THIS_MODULE,
6e9624b8c   Arnd Bergmann   block: push down ...
318
  	.open			= ide_gd_unlocked_open,
b2f21e057   Al Viro   [PATCH] switch id...
319
  	.release		= ide_gd_release,
8a6cfeb6d   Arnd Bergmann   block: push down ...
320
  	.ioctl			= ide_gd_ioctl,
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
321
  	.getgeo			= ide_gd_getgeo,
5b03a1b14   Tejun Heo   ide: Convert to b...
322
  	.check_events		= ide_gd_check_events,
c3e33e043   Tejun Heo   block,ide: simpli...
323
  	.unlock_native_capacity	= ide_gd_unlock_native_capacity,
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
324
325
326
327
328
  	.revalidate_disk	= ide_gd_revalidate_disk
  };
  
  static int ide_gd_probe(ide_drive_t *drive)
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
329
  	const struct ide_disk_ops *disk_ops = NULL;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
330
331
332
333
  	struct ide_disk_obj *idkp;
  	struct gendisk *g;
  
  	/* strstr("foo", "") is non-NULL */
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
334
335
336
337
338
339
340
341
342
343
344
345
  	if (!strstr("ide-gd", drive->driver_req))
  		goto failed;
  
  #ifdef CONFIG_IDE_GD_ATA
  	if (drive->media == ide_disk)
  		disk_ops = &ide_ata_disk_ops;
  #endif
  #ifdef CONFIG_IDE_GD_ATAPI
  	if (drive->media == ide_floppy)
  		disk_ops = &ide_atapi_disk_ops;
  #endif
  	if (disk_ops == NULL)
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
346
  		goto failed;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
347
348
349
350
  	if (disk_ops->check(drive, DRV_NAME) == 0) {
  		printk(KERN_ERR PFX "%s: not supported by this driver
  ",
  			drive->name);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
351
  		goto failed;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
352
  	}
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
353
354
  
  	idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
355
356
357
358
  	if (!idkp) {
  		printk(KERN_ERR PFX "%s: can't allocate a disk structure
  ",
  			drive->name);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
359
  		goto failed;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
360
  	}
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
361
362
363
364
365
366
  
  	g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
  	if (!g)
  		goto out_free_idkp;
  
  	ide_init_disk(g, drive);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
367
368
369
370
371
372
  	idkp->dev.parent = &drive->gendev;
  	idkp->dev.release = ide_disk_release;
  	dev_set_name(&idkp->dev, dev_name(&drive->gendev));
  
  	if (device_register(&idkp->dev))
  		goto out_free_disk;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
373
374
375
376
377
378
379
380
  
  	idkp->drive = drive;
  	idkp->driver = &ide_gd_driver;
  	idkp->disk = g;
  
  	g->private_data = &idkp->driver;
  
  	drive->driver_data = idkp;
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
381
382
  	drive->debug_mask = debug_mask;
  	drive->disk_ops = disk_ops;
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
383

806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
384
  	disk_ops->setup(drive);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
385
386
387
388
389
390
391
392
393
394
395
  
  	set_capacity(g, ide_gd_capacity(drive));
  
  	g->minors = IDE_DISK_MINORS;
  	g->driverfs_dev = &drive->gendev;
  	g->flags |= GENHD_FL_EXT_DEVT;
  	if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
  		g->flags = GENHD_FL_REMOVABLE;
  	g->fops = &ide_gd_ops;
  	add_disk(g);
  	return 0;
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
396
397
  out_free_disk:
  	put_disk(g);
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
398
399
400
401
402
403
404
405
  out_free_idkp:
  	kfree(idkp);
  failed:
  	return -ENODEV;
  }
  
  static int __init ide_gd_init(void)
  {
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
406
407
  	printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "
  ");
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
408
409
410
411
412
413
414
415
416
417
  	return driver_register(&ide_gd_driver.gen_driver);
  }
  
  static void __exit ide_gd_exit(void)
  {
  	driver_unregister(&ide_gd_driver.gen_driver);
  }
  
  MODULE_ALIAS("ide:*m-disk*");
  MODULE_ALIAS("ide-disk");
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
418
419
  MODULE_ALIAS("ide:*m-floppy*");
  MODULE_ALIAS("ide-floppy");
5fef0e5c0   Bartlomiej Zolnierkiewicz   ide-disk: factor ...
420
421
422
  module_init(ide_gd_init);
  module_exit(ide_gd_exit);
  MODULE_LICENSE("GPL");
806f80a6f   Bartlomiej Zolnierkiewicz   ide: add generic ...
423
  MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");