diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:14 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:14 -0400 |
commit | 806f80a6fc203ad0bde84e5a9e94572617d2ae45 (patch) | |
tree | 20c684323e6e9f24af96df84008f06425a67ec6a /drivers/ide/ide-gd.c | |
parent | 79cb380397c834a35952d8497651d93b543ef968 (diff) |
ide: add generic ATA/ATAPI disk driver
* Add struct ide_disk_ops containing protocol specific methods.
* Add 'struct ide_disk_ops *' to ide_drive_t.
* Convert ide-{disk,floppy} drivers to use struct ide_disk_ops.
* Merge ide-{disk,floppy} drivers into generic ide-gd driver.
While at it:
- ide_disk_init_capacity() -> ide_disk_get_capacity()
Acked-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-gd.c')
-rw-r--r-- | drivers/ide/ide-gd.c | 122 |
1 files changed, 104 insertions, 18 deletions
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index a3d4ad7db2af..d44898f46c33 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c | |||
@@ -15,9 +15,14 @@ | |||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #include "ide-disk.h" | 17 | #include "ide-disk.h" |
18 | #include "ide-floppy.h" | ||
18 | 19 | ||
19 | #define IDE_GD_VERSION "1.18" | 20 | #define IDE_GD_VERSION "1.18" |
20 | 21 | ||
22 | /* module parameters */ | ||
23 | static unsigned long debug_mask; | ||
24 | module_param(debug_mask, ulong, 0644); | ||
25 | |||
21 | static DEFINE_MUTEX(ide_disk_ref_mutex); | 26 | static DEFINE_MUTEX(ide_disk_ref_mutex); |
22 | 27 | ||
23 | static void ide_disk_release(struct kref *); | 28 | static void ide_disk_release(struct kref *); |
@@ -64,7 +69,7 @@ static void ide_gd_remove(ide_drive_t *drive) | |||
64 | 69 | ||
65 | del_gendisk(g); | 70 | del_gendisk(g); |
66 | 71 | ||
67 | ide_disk_flush(drive); | 72 | drive->disk_ops->flush(drive); |
68 | 73 | ||
69 | ide_disk_put(idkp); | 74 | ide_disk_put(idkp); |
70 | } | 75 | } |
@@ -75,6 +80,7 @@ static void ide_disk_release(struct kref *kref) | |||
75 | ide_drive_t *drive = idkp->drive; | 80 | ide_drive_t *drive = idkp->drive; |
76 | struct gendisk *g = idkp->disk; | 81 | struct gendisk *g = idkp->disk; |
77 | 82 | ||
83 | drive->disk_ops = NULL; | ||
78 | drive->driver_data = NULL; | 84 | drive->driver_data = NULL; |
79 | g->private_data = NULL; | 85 | g->private_data = NULL; |
80 | put_disk(g); | 86 | put_disk(g); |
@@ -89,7 +95,7 @@ static void ide_disk_release(struct kref *kref) | |||
89 | static void ide_gd_resume(ide_drive_t *drive) | 95 | static void ide_gd_resume(ide_drive_t *drive) |
90 | { | 96 | { |
91 | if (ata_id_hpa_enabled(drive->id)) | 97 | if (ata_id_hpa_enabled(drive->id)) |
92 | ide_disk_init_capacity(drive); | 98 | (void)drive->disk_ops->get_capacity(drive); |
93 | } | 99 | } |
94 | 100 | ||
95 | static void ide_gd_shutdown(ide_drive_t *drive) | 101 | static void ide_gd_shutdown(ide_drive_t *drive) |
@@ -110,7 +116,7 @@ static void ide_gd_shutdown(ide_drive_t *drive) | |||
110 | #else | 116 | #else |
111 | if (system_state == SYSTEM_RESTART) { | 117 | if (system_state == SYSTEM_RESTART) { |
112 | #endif | 118 | #endif |
113 | ide_disk_flush(drive); | 119 | drive->disk_ops->flush(drive); |
114 | return; | 120 | return; |
115 | } | 121 | } |
116 | 122 | ||
@@ -122,19 +128,31 @@ static void ide_gd_shutdown(ide_drive_t *drive) | |||
122 | #ifdef CONFIG_IDE_PROC_FS | 128 | #ifdef CONFIG_IDE_PROC_FS |
123 | static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive) | 129 | static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive) |
124 | { | 130 | { |
125 | return ide_disk_proc; | 131 | return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc; |
126 | } | 132 | } |
127 | 133 | ||
128 | static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive) | 134 | static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive) |
129 | { | 135 | { |
130 | return ide_disk_settings; | 136 | return (drive->media == ide_disk) ? ide_disk_settings |
137 | : ide_floppy_settings; | ||
131 | } | 138 | } |
132 | #endif | 139 | #endif |
133 | 140 | ||
141 | static ide_startstop_t ide_gd_do_request(ide_drive_t *drive, | ||
142 | struct request *rq, sector_t sector) | ||
143 | { | ||
144 | return drive->disk_ops->do_request(drive, rq, sector); | ||
145 | } | ||
146 | |||
147 | static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs) | ||
148 | { | ||
149 | return drive->disk_ops->end_request(drive, uptodate, nrsecs); | ||
150 | } | ||
151 | |||
134 | static ide_driver_t ide_gd_driver = { | 152 | static ide_driver_t ide_gd_driver = { |
135 | .gen_driver = { | 153 | .gen_driver = { |
136 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
137 | .name = "ide-disk", | 155 | .name = "ide-gd", |
138 | .bus = &ide_bus_type, | 156 | .bus = &ide_bus_type, |
139 | }, | 157 | }, |
140 | .probe = ide_gd_probe, | 158 | .probe = ide_gd_probe, |
@@ -142,8 +160,8 @@ static ide_driver_t ide_gd_driver = { | |||
142 | .resume = ide_gd_resume, | 160 | .resume = ide_gd_resume, |
143 | .shutdown = ide_gd_shutdown, | 161 | .shutdown = ide_gd_shutdown, |
144 | .version = IDE_GD_VERSION, | 162 | .version = IDE_GD_VERSION, |
145 | .do_request = ide_do_rw_disk, | 163 | .do_request = ide_gd_do_request, |
146 | .end_request = ide_end_request, | 164 | .end_request = ide_gd_end_request, |
147 | .error = __ide_error, | 165 | .error = __ide_error, |
148 | #ifdef CONFIG_IDE_PROC_FS | 166 | #ifdef CONFIG_IDE_PROC_FS |
149 | .proc_entries = ide_disk_proc_entries, | 167 | .proc_entries = ide_disk_proc_entries, |
@@ -156,6 +174,7 @@ static int ide_gd_open(struct inode *inode, struct file *filp) | |||
156 | struct gendisk *disk = inode->i_bdev->bd_disk; | 174 | struct gendisk *disk = inode->i_bdev->bd_disk; |
157 | struct ide_disk_obj *idkp; | 175 | struct ide_disk_obj *idkp; |
158 | ide_drive_t *drive; | 176 | ide_drive_t *drive; |
177 | int ret = 0; | ||
159 | 178 | ||
160 | idkp = ide_disk_get(disk); | 179 | idkp = ide_disk_get(disk); |
161 | if (idkp == NULL) | 180 | if (idkp == NULL) |
@@ -163,19 +182,49 @@ static int ide_gd_open(struct inode *inode, struct file *filp) | |||
163 | 182 | ||
164 | drive = idkp->drive; | 183 | drive = idkp->drive; |
165 | 184 | ||
185 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
186 | |||
166 | idkp->openers++; | 187 | idkp->openers++; |
167 | 188 | ||
168 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { | 189 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { |
190 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
191 | /* Just in case */ | ||
192 | |||
193 | ret = drive->disk_ops->init_media(drive, disk); | ||
194 | |||
195 | /* | ||
196 | * Allow O_NDELAY to open a drive without a disk, or with an | ||
197 | * unreadable disk, so that we can get the format capacity | ||
198 | * of the drive or begin the format - Sam | ||
199 | */ | ||
200 | if (ret && (filp->f_flags & O_NDELAY) == 0) { | ||
201 | ret = -EIO; | ||
202 | goto out_put_idkp; | ||
203 | } | ||
204 | |||
205 | if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) { | ||
206 | ret = -EROFS; | ||
207 | goto out_put_idkp; | ||
208 | } | ||
209 | |||
169 | /* | 210 | /* |
170 | * Ignore the return code from door_lock, | 211 | * Ignore the return code from door_lock, |
171 | * since the open() has already succeeded, | 212 | * since the open() has already succeeded, |
172 | * and the door_lock is irrelevant at this point. | 213 | * and the door_lock is irrelevant at this point. |
173 | */ | 214 | */ |
174 | ide_disk_set_doorlock(drive, 1); | 215 | drive->disk_ops->set_doorlock(drive, disk, 1); |
175 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | 216 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; |
176 | check_disk_change(inode->i_bdev); | 217 | check_disk_change(inode->i_bdev); |
218 | } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { | ||
219 | ret = -EBUSY; | ||
220 | goto out_put_idkp; | ||
177 | } | 221 | } |
178 | return 0; | 222 | return 0; |
223 | |||
224 | out_put_idkp: | ||
225 | idkp->openers--; | ||
226 | ide_disk_put(idkp); | ||
227 | return ret; | ||
179 | } | 228 | } |
180 | 229 | ||
181 | static int ide_gd_release(struct inode *inode, struct file *filp) | 230 | static int ide_gd_release(struct inode *inode, struct file *filp) |
@@ -184,11 +233,15 @@ static int ide_gd_release(struct inode *inode, struct file *filp) | |||
184 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); | 233 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); |
185 | ide_drive_t *drive = idkp->drive; | 234 | ide_drive_t *drive = idkp->drive; |
186 | 235 | ||
236 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
237 | |||
187 | if (idkp->openers == 1) | 238 | if (idkp->openers == 1) |
188 | ide_disk_flush(drive); | 239 | drive->disk_ops->flush(drive); |
189 | 240 | ||
190 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) | 241 | if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { |
191 | ide_disk_set_doorlock(drive, 0); | 242 | drive->disk_ops->set_doorlock(drive, disk, 0); |
243 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
244 | } | ||
192 | 245 | ||
193 | idkp->openers--; | 246 | idkp->openers--; |
194 | 247 | ||
@@ -233,11 +286,21 @@ static int ide_gd_revalidate_disk(struct gendisk *disk) | |||
233 | return 0; | 286 | return 0; |
234 | } | 287 | } |
235 | 288 | ||
289 | static int ide_gd_ioctl(struct inode *inode, struct file *file, | ||
290 | unsigned int cmd, unsigned long arg) | ||
291 | { | ||
292 | struct block_device *bdev = inode->i_bdev; | ||
293 | struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj); | ||
294 | ide_drive_t *drive = idkp->drive; | ||
295 | |||
296 | return drive->disk_ops->ioctl(drive, inode, file, cmd, arg); | ||
297 | } | ||
298 | |||
236 | static struct block_device_operations ide_gd_ops = { | 299 | static struct block_device_operations ide_gd_ops = { |
237 | .owner = THIS_MODULE, | 300 | .owner = THIS_MODULE, |
238 | .open = ide_gd_open, | 301 | .open = ide_gd_open, |
239 | .release = ide_gd_release, | 302 | .release = ide_gd_release, |
240 | .ioctl = ide_disk_ioctl, | 303 | .ioctl = ide_gd_ioctl, |
241 | .getgeo = ide_gd_getgeo, | 304 | .getgeo = ide_gd_getgeo, |
242 | .media_changed = ide_gd_media_changed, | 305 | .media_changed = ide_gd_media_changed, |
243 | .revalidate_disk = ide_gd_revalidate_disk | 306 | .revalidate_disk = ide_gd_revalidate_disk |
@@ -245,19 +308,37 @@ static struct block_device_operations ide_gd_ops = { | |||
245 | 308 | ||
246 | static int ide_gd_probe(ide_drive_t *drive) | 309 | static int ide_gd_probe(ide_drive_t *drive) |
247 | { | 310 | { |
311 | const struct ide_disk_ops *disk_ops = NULL; | ||
248 | struct ide_disk_obj *idkp; | 312 | struct ide_disk_obj *idkp; |
249 | struct gendisk *g; | 313 | struct gendisk *g; |
250 | 314 | ||
251 | /* strstr("foo", "") is non-NULL */ | 315 | /* strstr("foo", "") is non-NULL */ |
252 | if (!strstr("ide-disk", drive->driver_req)) | 316 | if (!strstr("ide-gd", drive->driver_req)) |
317 | goto failed; | ||
318 | |||
319 | #ifdef CONFIG_IDE_GD_ATA | ||
320 | if (drive->media == ide_disk) | ||
321 | disk_ops = &ide_ata_disk_ops; | ||
322 | #endif | ||
323 | #ifdef CONFIG_IDE_GD_ATAPI | ||
324 | if (drive->media == ide_floppy) | ||
325 | disk_ops = &ide_atapi_disk_ops; | ||
326 | #endif | ||
327 | if (disk_ops == NULL) | ||
253 | goto failed; | 328 | goto failed; |
254 | 329 | ||
255 | if (drive->media != ide_disk) | 330 | if (disk_ops->check(drive, DRV_NAME) == 0) { |
331 | printk(KERN_ERR PFX "%s: not supported by this driver\n", | ||
332 | drive->name); | ||
256 | goto failed; | 333 | goto failed; |
334 | } | ||
257 | 335 | ||
258 | idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); | 336 | idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); |
259 | if (!idkp) | 337 | if (!idkp) { |
338 | printk(KERN_ERR PFX "%s: can't allocate a disk structure\n", | ||
339 | drive->name); | ||
260 | goto failed; | 340 | goto failed; |
341 | } | ||
261 | 342 | ||
262 | g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); | 343 | g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); |
263 | if (!g) | 344 | if (!g) |
@@ -274,8 +355,10 @@ static int ide_gd_probe(ide_drive_t *drive) | |||
274 | g->private_data = &idkp->driver; | 355 | g->private_data = &idkp->driver; |
275 | 356 | ||
276 | drive->driver_data = idkp; | 357 | drive->driver_data = idkp; |
358 | drive->debug_mask = debug_mask; | ||
359 | drive->disk_ops = disk_ops; | ||
277 | 360 | ||
278 | ide_disk_setup(drive); | 361 | disk_ops->setup(drive); |
279 | 362 | ||
280 | set_capacity(g, ide_gd_capacity(drive)); | 363 | set_capacity(g, ide_gd_capacity(drive)); |
281 | 364 | ||
@@ -296,6 +379,7 @@ failed: | |||
296 | 379 | ||
297 | static int __init ide_gd_init(void) | 380 | static int __init ide_gd_init(void) |
298 | { | 381 | { |
382 | printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n"); | ||
299 | return driver_register(&ide_gd_driver.gen_driver); | 383 | return driver_register(&ide_gd_driver.gen_driver); |
300 | } | 384 | } |
301 | 385 | ||
@@ -306,7 +390,9 @@ static void __exit ide_gd_exit(void) | |||
306 | 390 | ||
307 | MODULE_ALIAS("ide:*m-disk*"); | 391 | MODULE_ALIAS("ide:*m-disk*"); |
308 | MODULE_ALIAS("ide-disk"); | 392 | MODULE_ALIAS("ide-disk"); |
393 | MODULE_ALIAS("ide:*m-floppy*"); | ||
394 | MODULE_ALIAS("ide-floppy"); | ||
309 | module_init(ide_gd_init); | 395 | module_init(ide_gd_init); |
310 | module_exit(ide_gd_exit); | 396 | module_exit(ide_gd_exit); |
311 | MODULE_LICENSE("GPL"); | 397 | MODULE_LICENSE("GPL"); |
312 | MODULE_DESCRIPTION("ATA DISK Driver"); | 398 | MODULE_DESCRIPTION("generic ATA/ATAPI disk driver"); |