diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 437 |
1 files changed, 297 insertions, 140 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 235ebdb29b28..994e41099b42 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -39,8 +39,6 @@ | |||
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | 41 | ||
42 | static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ | ||
43 | |||
44 | /** | 42 | /** |
45 | * generic_id - add a generic drive id | 43 | * generic_id - add a generic drive id |
46 | * @drive: drive to make an ID block for | 44 | * @drive: drive to make an ID block for |
@@ -126,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
126 | 124 | ||
127 | id = drive->id; | 125 | id = drive->id; |
128 | /* read 512 bytes of id info */ | 126 | /* read 512 bytes of id info */ |
129 | hwif->input_data(drive, NULL, id, SECTOR_SIZE); | 127 | hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); |
130 | 128 | ||
131 | drive->id_read = 1; | 129 | drive->id_read = 1; |
132 | local_irq_enable(); | 130 | local_irq_enable(); |
@@ -136,18 +134,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
136 | #endif | 134 | #endif |
137 | ide_fix_driveid(id); | 135 | ide_fix_driveid(id); |
138 | 136 | ||
139 | #if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) | ||
140 | /* | ||
141 | * EATA SCSI controllers do a hardware ATA emulation: | ||
142 | * Ignore them if there is a driver for them available. | ||
143 | */ | ||
144 | if ((id->model[0] == 'P' && id->model[1] == 'M') || | ||
145 | (id->model[0] == 'S' && id->model[1] == 'K')) { | ||
146 | printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); | ||
147 | goto err_misc; | ||
148 | } | ||
149 | #endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */ | ||
150 | |||
151 | /* | 137 | /* |
152 | * WIN_IDENTIFY returns little-endian info, | 138 | * WIN_IDENTIFY returns little-endian info, |
153 | * WIN_PIDENTIFY *usually* returns little-endian info. | 139 | * WIN_PIDENTIFY *usually* returns little-endian info. |
@@ -169,7 +155,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
169 | if (strstr(id->model, "E X A B Y T E N E S T")) | 155 | if (strstr(id->model, "E X A B Y T E N E S T")) |
170 | goto err_misc; | 156 | goto err_misc; |
171 | 157 | ||
172 | printk("%s: %s, ", drive->name, id->model); | 158 | printk(KERN_INFO "%s: %s, ", drive->name, id->model); |
159 | |||
173 | drive->present = 1; | 160 | drive->present = 1; |
174 | drive->dead = 0; | 161 | drive->dead = 0; |
175 | 162 | ||
@@ -178,16 +165,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
178 | */ | 165 | */ |
179 | if (cmd == WIN_PIDENTIFY) { | 166 | if (cmd == WIN_PIDENTIFY) { |
180 | u8 type = (id->config >> 8) & 0x1f; | 167 | u8 type = (id->config >> 8) & 0x1f; |
181 | printk("ATAPI "); | 168 | |
169 | printk(KERN_CONT "ATAPI "); | ||
182 | switch (type) { | 170 | switch (type) { |
183 | case ide_floppy: | 171 | case ide_floppy: |
184 | if (!strstr(id->model, "CD-ROM")) { | 172 | if (!strstr(id->model, "CD-ROM")) { |
185 | if (!strstr(id->model, "oppy") && | 173 | if (!strstr(id->model, "oppy") && |
186 | !strstr(id->model, "poyp") && | 174 | !strstr(id->model, "poyp") && |
187 | !strstr(id->model, "ZIP")) | 175 | !strstr(id->model, "ZIP")) |
188 | printk("cdrom or floppy?, assuming "); | 176 | printk(KERN_CONT "cdrom or floppy?, assuming "); |
189 | if (drive->media != ide_cdrom) { | 177 | if (drive->media != ide_cdrom) { |
190 | printk ("FLOPPY"); | 178 | printk(KERN_CONT "FLOPPY"); |
191 | drive->removable = 1; | 179 | drive->removable = 1; |
192 | break; | 180 | break; |
193 | } | 181 | } |
@@ -200,25 +188,25 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
200 | /* kludge for Apple PowerBook internal zip */ | 188 | /* kludge for Apple PowerBook internal zip */ |
201 | if (!strstr(id->model, "CD-ROM") && | 189 | if (!strstr(id->model, "CD-ROM") && |
202 | strstr(id->model, "ZIP")) { | 190 | strstr(id->model, "ZIP")) { |
203 | printk ("FLOPPY"); | 191 | printk(KERN_CONT "FLOPPY"); |
204 | type = ide_floppy; | 192 | type = ide_floppy; |
205 | break; | 193 | break; |
206 | } | 194 | } |
207 | #endif | 195 | #endif |
208 | printk ("CD/DVD-ROM"); | 196 | printk(KERN_CONT "CD/DVD-ROM"); |
209 | break; | 197 | break; |
210 | case ide_tape: | 198 | case ide_tape: |
211 | printk ("TAPE"); | 199 | printk(KERN_CONT "TAPE"); |
212 | break; | 200 | break; |
213 | case ide_optical: | 201 | case ide_optical: |
214 | printk ("OPTICAL"); | 202 | printk(KERN_CONT "OPTICAL"); |
215 | drive->removable = 1; | 203 | drive->removable = 1; |
216 | break; | 204 | break; |
217 | default: | 205 | default: |
218 | printk("UNKNOWN (type %d)", type); | 206 | printk(KERN_CONT "UNKNOWN (type %d)", type); |
219 | break; | 207 | break; |
220 | } | 208 | } |
221 | printk (" drive\n"); | 209 | printk(KERN_CONT " drive\n"); |
222 | drive->media = type; | 210 | drive->media = type; |
223 | /* an ATAPI device ignores DRDY */ | 211 | /* an ATAPI device ignores DRDY */ |
224 | drive->ready_stat = 0; | 212 | drive->ready_stat = 0; |
@@ -238,7 +226,9 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
238 | drive->removable = 1; | 226 | drive->removable = 1; |
239 | 227 | ||
240 | drive->media = ide_disk; | 228 | drive->media = ide_disk; |
241 | printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); | 229 | |
230 | printk(KERN_CONT "%s DISK drive\n", | ||
231 | (id->config == 0x848a) ? "CFA" : "ATA"); | ||
242 | 232 | ||
243 | return; | 233 | return; |
244 | 234 | ||
@@ -267,6 +257,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
267 | { | 257 | { |
268 | ide_hwif_t *hwif = HWIF(drive); | 258 | ide_hwif_t *hwif = HWIF(drive); |
269 | struct ide_io_ports *io_ports = &hwif->io_ports; | 259 | struct ide_io_ports *io_ports = &hwif->io_ports; |
260 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
270 | int use_altstatus = 0, rc; | 261 | int use_altstatus = 0, rc; |
271 | unsigned long timeout; | 262 | unsigned long timeout; |
272 | u8 s = 0, a = 0; | 263 | u8 s = 0, a = 0; |
@@ -275,8 +266,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
275 | msleep(50); | 266 | msleep(50); |
276 | 267 | ||
277 | if (io_ports->ctl_addr) { | 268 | if (io_ports->ctl_addr) { |
278 | a = ide_read_altstatus(drive); | 269 | a = tp_ops->read_altstatus(hwif); |
279 | s = ide_read_status(drive); | 270 | s = tp_ops->read_status(hwif); |
280 | if ((a ^ s) & ~INDEX_STAT) | 271 | if ((a ^ s) & ~INDEX_STAT) |
281 | /* ancient Seagate drives, broken interfaces */ | 272 | /* ancient Seagate drives, broken interfaces */ |
282 | printk(KERN_INFO "%s: probing with STATUS(0x%02x) " | 273 | printk(KERN_INFO "%s: probing with STATUS(0x%02x) " |
@@ -290,12 +281,18 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
290 | /* set features register for atapi | 281 | /* set features register for atapi |
291 | * identify command to be sure of reply | 282 | * identify command to be sure of reply |
292 | */ | 283 | */ |
293 | if ((cmd == WIN_PIDENTIFY)) | 284 | if (cmd == WIN_PIDENTIFY) { |
294 | /* disable dma & overlap */ | 285 | ide_task_t task; |
295 | hwif->OUTB(0, io_ports->feature_addr); | 286 | |
287 | memset(&task, 0, sizeof(task)); | ||
288 | /* disable DMA & overlap */ | ||
289 | task.tf_flags = IDE_TFLAG_OUT_FEATURE; | ||
290 | |||
291 | tp_ops->tf_load(drive, &task); | ||
292 | } | ||
296 | 293 | ||
297 | /* ask drive for ID */ | 294 | /* ask drive for ID */ |
298 | hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr); | 295 | tp_ops->exec_command(hwif, cmd); |
299 | 296 | ||
300 | timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; | 297 | timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; |
301 | timeout += jiffies; | 298 | timeout += jiffies; |
@@ -306,13 +303,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
306 | } | 303 | } |
307 | /* give drive a breather */ | 304 | /* give drive a breather */ |
308 | msleep(50); | 305 | msleep(50); |
309 | s = use_altstatus ? ide_read_altstatus(drive) | 306 | s = use_altstatus ? tp_ops->read_altstatus(hwif) |
310 | : ide_read_status(drive); | 307 | : tp_ops->read_status(hwif); |
311 | } while (s & BUSY_STAT); | 308 | } while (s & BUSY_STAT); |
312 | 309 | ||
313 | /* wait for IRQ and DRQ_STAT */ | 310 | /* wait for IRQ and DRQ_STAT */ |
314 | msleep(50); | 311 | msleep(50); |
315 | s = ide_read_status(drive); | 312 | s = tp_ops->read_status(hwif); |
316 | 313 | ||
317 | if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) { | 314 | if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) { |
318 | unsigned long flags; | 315 | unsigned long flags; |
@@ -324,7 +321,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
324 | /* drive responded with ID */ | 321 | /* drive responded with ID */ |
325 | rc = 0; | 322 | rc = 0; |
326 | /* clear drive IRQ */ | 323 | /* clear drive IRQ */ |
327 | (void)ide_read_status(drive); | 324 | (void)tp_ops->read_status(hwif); |
328 | local_irq_restore(flags); | 325 | local_irq_restore(flags); |
329 | } else { | 326 | } else { |
330 | /* drive refused ID */ | 327 | /* drive refused ID */ |
@@ -346,6 +343,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
346 | static int try_to_identify (ide_drive_t *drive, u8 cmd) | 343 | static int try_to_identify (ide_drive_t *drive, u8 cmd) |
347 | { | 344 | { |
348 | ide_hwif_t *hwif = HWIF(drive); | 345 | ide_hwif_t *hwif = HWIF(drive); |
346 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
349 | int retval; | 347 | int retval; |
350 | int autoprobe = 0; | 348 | int autoprobe = 0; |
351 | unsigned long cookie = 0; | 349 | unsigned long cookie = 0; |
@@ -361,7 +359,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) | |||
361 | autoprobe = 1; | 359 | autoprobe = 1; |
362 | cookie = probe_irq_on(); | 360 | cookie = probe_irq_on(); |
363 | } | 361 | } |
364 | ide_set_irq(drive, autoprobe); | 362 | tp_ops->set_irq(hwif, autoprobe); |
365 | } | 363 | } |
366 | 364 | ||
367 | retval = actual_try_to_identify(drive, cmd); | 365 | retval = actual_try_to_identify(drive, cmd); |
@@ -369,9 +367,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) | |||
369 | if (autoprobe) { | 367 | if (autoprobe) { |
370 | int irq; | 368 | int irq; |
371 | 369 | ||
372 | ide_set_irq(drive, 0); | 370 | tp_ops->set_irq(hwif, 0); |
373 | /* clear drive IRQ */ | 371 | /* clear drive IRQ */ |
374 | (void)ide_read_status(drive); | 372 | (void)tp_ops->read_status(hwif); |
375 | udelay(5); | 373 | udelay(5); |
376 | irq = probe_irq_off(cookie); | 374 | irq = probe_irq_off(cookie); |
377 | if (!hwif->irq) { | 375 | if (!hwif->irq) { |
@@ -381,7 +379,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) | |||
381 | /* Mmmm.. multiple IRQs.. | 379 | /* Mmmm.. multiple IRQs.. |
382 | * don't know which was ours | 380 | * don't know which was ours |
383 | */ | 381 | */ |
384 | printk("%s: IRQ probe failed (0x%lx)\n", | 382 | printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n", |
385 | drive->name, cookie); | 383 | drive->name, cookie); |
386 | } | 384 | } |
387 | } | 385 | } |
@@ -396,7 +394,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif) | |||
396 | 394 | ||
397 | do { | 395 | do { |
398 | msleep(50); | 396 | msleep(50); |
399 | stat = hwif->INB(hwif->io_ports.status_addr); | 397 | stat = hwif->tp_ops->read_status(hwif); |
400 | if ((stat & BUSY_STAT) == 0) | 398 | if ((stat & BUSY_STAT) == 0) |
401 | return 0; | 399 | return 0; |
402 | } while (time_before(jiffies, timeout)); | 400 | } while (time_before(jiffies, timeout)); |
@@ -404,6 +402,18 @@ static int ide_busy_sleep(ide_hwif_t *hwif) | |||
404 | return 1; | 402 | return 1; |
405 | } | 403 | } |
406 | 404 | ||
405 | static u8 ide_read_device(ide_drive_t *drive) | ||
406 | { | ||
407 | ide_task_t task; | ||
408 | |||
409 | memset(&task, 0, sizeof(task)); | ||
410 | task.tf_flags = IDE_TFLAG_IN_DEVICE; | ||
411 | |||
412 | drive->hwif->tp_ops->tf_read(drive, &task); | ||
413 | |||
414 | return task.tf.device; | ||
415 | } | ||
416 | |||
407 | /** | 417 | /** |
408 | * do_probe - probe an IDE device | 418 | * do_probe - probe an IDE device |
409 | * @drive: drive to probe | 419 | * @drive: drive to probe |
@@ -428,7 +438,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif) | |||
428 | static int do_probe (ide_drive_t *drive, u8 cmd) | 438 | static int do_probe (ide_drive_t *drive, u8 cmd) |
429 | { | 439 | { |
430 | ide_hwif_t *hwif = HWIF(drive); | 440 | ide_hwif_t *hwif = HWIF(drive); |
431 | struct ide_io_ports *io_ports = &hwif->io_ports; | 441 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
432 | int rc; | 442 | int rc; |
433 | u8 stat; | 443 | u8 stat; |
434 | 444 | ||
@@ -438,7 +448,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
438 | return 4; | 448 | return 4; |
439 | } | 449 | } |
440 | #ifdef DEBUG | 450 | #ifdef DEBUG |
441 | printk("probing for %s: present=%d, media=%d, probetype=%s\n", | 451 | printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", |
442 | drive->name, drive->present, drive->media, | 452 | drive->name, drive->present, drive->media, |
443 | (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); | 453 | (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); |
444 | #endif | 454 | #endif |
@@ -449,8 +459,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
449 | msleep(50); | 459 | msleep(50); |
450 | SELECT_DRIVE(drive); | 460 | SELECT_DRIVE(drive); |
451 | msleep(50); | 461 | msleep(50); |
452 | if (hwif->INB(io_ports->device_addr) != drive->select.all && | 462 | |
453 | !drive->present) { | 463 | if (ide_read_device(drive) != drive->select.all && !drive->present) { |
454 | if (drive->select.b.unit != 0) { | 464 | if (drive->select.b.unit != 0) { |
455 | /* exit with drive0 selected */ | 465 | /* exit with drive0 selected */ |
456 | SELECT_DRIVE(&hwif->drives[0]); | 466 | SELECT_DRIVE(&hwif->drives[0]); |
@@ -461,7 +471,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
461 | return 3; | 471 | return 3; |
462 | } | 472 | } |
463 | 473 | ||
464 | stat = ide_read_status(drive); | 474 | stat = tp_ops->read_status(hwif); |
465 | 475 | ||
466 | if (OK_STAT(stat, READY_STAT, BUSY_STAT) || | 476 | if (OK_STAT(stat, READY_STAT, BUSY_STAT) || |
467 | drive->present || cmd == WIN_PIDENTIFY) { | 477 | drive->present || cmd == WIN_PIDENTIFY) { |
@@ -471,7 +481,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
471 | rc = try_to_identify(drive,cmd); | 481 | rc = try_to_identify(drive,cmd); |
472 | } | 482 | } |
473 | 483 | ||
474 | stat = ide_read_status(drive); | 484 | stat = tp_ops->read_status(hwif); |
475 | 485 | ||
476 | if (stat == (BUSY_STAT | READY_STAT)) | 486 | if (stat == (BUSY_STAT | READY_STAT)) |
477 | return 4; | 487 | return 4; |
@@ -482,13 +492,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
482 | msleep(50); | 492 | msleep(50); |
483 | SELECT_DRIVE(drive); | 493 | SELECT_DRIVE(drive); |
484 | msleep(50); | 494 | msleep(50); |
485 | hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr); | 495 | tp_ops->exec_command(hwif, WIN_SRST); |
486 | (void)ide_busy_sleep(hwif); | 496 | (void)ide_busy_sleep(hwif); |
487 | rc = try_to_identify(drive, cmd); | 497 | rc = try_to_identify(drive, cmd); |
488 | } | 498 | } |
489 | 499 | ||
490 | /* ensure drive IRQ is clear */ | 500 | /* ensure drive IRQ is clear */ |
491 | stat = ide_read_status(drive); | 501 | stat = tp_ops->read_status(hwif); |
492 | 502 | ||
493 | if (rc == 1) | 503 | if (rc == 1) |
494 | printk(KERN_ERR "%s: no response (status = 0x%02x)\n", | 504 | printk(KERN_ERR "%s: no response (status = 0x%02x)\n", |
@@ -502,7 +512,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
502 | SELECT_DRIVE(&hwif->drives[0]); | 512 | SELECT_DRIVE(&hwif->drives[0]); |
503 | msleep(50); | 513 | msleep(50); |
504 | /* ensure drive irq is clear */ | 514 | /* ensure drive irq is clear */ |
505 | (void)ide_read_status(drive); | 515 | (void)tp_ops->read_status(hwif); |
506 | } | 516 | } |
507 | return rc; | 517 | return rc; |
508 | } | 518 | } |
@@ -513,12 +523,14 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
513 | static void enable_nest (ide_drive_t *drive) | 523 | static void enable_nest (ide_drive_t *drive) |
514 | { | 524 | { |
515 | ide_hwif_t *hwif = HWIF(drive); | 525 | ide_hwif_t *hwif = HWIF(drive); |
526 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
516 | u8 stat; | 527 | u8 stat; |
517 | 528 | ||
518 | printk("%s: enabling %s -- ", hwif->name, drive->id->model); | 529 | printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model); |
530 | |||
519 | SELECT_DRIVE(drive); | 531 | SELECT_DRIVE(drive); |
520 | msleep(50); | 532 | msleep(50); |
521 | hwif->OUTBSYNC(hwif, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr); | 533 | tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST); |
522 | 534 | ||
523 | if (ide_busy_sleep(hwif)) { | 535 | if (ide_busy_sleep(hwif)) { |
524 | printk(KERN_CONT "failed (timeout)\n"); | 536 | printk(KERN_CONT "failed (timeout)\n"); |
@@ -527,7 +539,7 @@ static void enable_nest (ide_drive_t *drive) | |||
527 | 539 | ||
528 | msleep(50); | 540 | msleep(50); |
529 | 541 | ||
530 | stat = ide_read_status(drive); | 542 | stat = tp_ops->read_status(hwif); |
531 | 543 | ||
532 | if (!OK_STAT(stat, 0, BAD_STAT)) | 544 | if (!OK_STAT(stat, 0, BAD_STAT)) |
533 | printk(KERN_CONT "failed (status = 0x%02x)\n", stat); | 545 | printk(KERN_CONT "failed (status = 0x%02x)\n", stat); |
@@ -619,7 +631,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive) | |||
619 | return drive->present; | 631 | return drive->present; |
620 | } | 632 | } |
621 | 633 | ||
622 | static void hwif_release_dev (struct device *dev) | 634 | static void hwif_release_dev(struct device *dev) |
623 | { | 635 | { |
624 | ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev); | 636 | ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev); |
625 | 637 | ||
@@ -709,7 +721,7 @@ static int ide_port_wait_ready(ide_hwif_t *hwif) | |||
709 | /* Ignore disks that we will not probe for later. */ | 721 | /* Ignore disks that we will not probe for later. */ |
710 | if (!drive->noprobe || drive->present) { | 722 | if (!drive->noprobe || drive->present) { |
711 | SELECT_DRIVE(drive); | 723 | SELECT_DRIVE(drive); |
712 | ide_set_irq(drive, 1); | 724 | hwif->tp_ops->set_irq(hwif, 1); |
713 | mdelay(2); | 725 | mdelay(2); |
714 | rc = ide_wait_not_busy(hwif, 35000); | 726 | rc = ide_wait_not_busy(hwif, 35000); |
715 | if (rc) | 727 | if (rc) |
@@ -864,7 +876,7 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) | |||
864 | if (m && m->hwgroup && m->hwgroup != new->hwgroup) { | 876 | if (m && m->hwgroup && m->hwgroup != new->hwgroup) { |
865 | if (!new->hwgroup) | 877 | if (!new->hwgroup) |
866 | return; | 878 | return; |
867 | printk("%s: potential irq problem with %s and %s\n", | 879 | printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n", |
868 | hwif->name, new->name, m->name); | 880 | hwif->name, new->name, m->name); |
869 | } | 881 | } |
870 | if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ | 882 | if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ |
@@ -971,6 +983,45 @@ static void ide_port_setup_devices(ide_hwif_t *hwif) | |||
971 | mutex_unlock(&ide_cfg_mtx); | 983 | mutex_unlock(&ide_cfg_mtx); |
972 | } | 984 | } |
973 | 985 | ||
986 | static ide_hwif_t *ide_ports[MAX_HWIFS]; | ||
987 | |||
988 | void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | ||
989 | { | ||
990 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
991 | |||
992 | ide_ports[hwif->index] = NULL; | ||
993 | |||
994 | spin_lock_irq(&ide_lock); | ||
995 | /* | ||
996 | * Remove us from the hwgroup, and free | ||
997 | * the hwgroup if we were the only member | ||
998 | */ | ||
999 | if (hwif->next == hwif) { | ||
1000 | BUG_ON(hwgroup->hwif != hwif); | ||
1001 | kfree(hwgroup); | ||
1002 | } else { | ||
1003 | /* There is another interface in hwgroup. | ||
1004 | * Unlink us, and set hwgroup->drive and ->hwif to | ||
1005 | * something sane. | ||
1006 | */ | ||
1007 | ide_hwif_t *g = hwgroup->hwif; | ||
1008 | |||
1009 | while (g->next != hwif) | ||
1010 | g = g->next; | ||
1011 | g->next = hwif->next; | ||
1012 | if (hwgroup->hwif == hwif) { | ||
1013 | /* Chose a random hwif for hwgroup->hwif. | ||
1014 | * It's guaranteed that there are no drives | ||
1015 | * left in the hwgroup. | ||
1016 | */ | ||
1017 | BUG_ON(hwgroup->drive != NULL); | ||
1018 | hwgroup->hwif = g; | ||
1019 | } | ||
1020 | BUG_ON(hwgroup->hwif == hwif); | ||
1021 | } | ||
1022 | spin_unlock_irq(&ide_lock); | ||
1023 | } | ||
1024 | |||
974 | /* | 1025 | /* |
975 | * This routine sets up the irq for an ide interface, and creates a new | 1026 | * This routine sets up the irq for an ide interface, and creates a new |
976 | * hwgroup for the irq/hwif if none was previously assigned. | 1027 | * hwgroup for the irq/hwif if none was previously assigned. |
@@ -998,8 +1049,9 @@ static int init_irq (ide_hwif_t *hwif) | |||
998 | * Group up with any other hwifs that share our irq(s). | 1049 | * Group up with any other hwifs that share our irq(s). |
999 | */ | 1050 | */ |
1000 | for (index = 0; index < MAX_HWIFS; index++) { | 1051 | for (index = 0; index < MAX_HWIFS; index++) { |
1001 | ide_hwif_t *h = &ide_hwifs[index]; | 1052 | ide_hwif_t *h = ide_ports[index]; |
1002 | if (h->hwgroup) { /* scan only initialized hwif's */ | 1053 | |
1054 | if (h && h->hwgroup) { /* scan only initialized ports */ | ||
1003 | if (hwif->irq == h->irq) { | 1055 | if (hwif->irq == h->irq) { |
1004 | hwif->sharing_irq = h->sharing_irq = 1; | 1056 | hwif->sharing_irq = h->sharing_irq = 1; |
1005 | if (hwif->chipset != ide_pci || | 1057 | if (hwif->chipset != ide_pci || |
@@ -1053,6 +1105,8 @@ static int init_irq (ide_hwif_t *hwif) | |||
1053 | hwgroup->timer.data = (unsigned long) hwgroup; | 1105 | hwgroup->timer.data = (unsigned long) hwgroup; |
1054 | } | 1106 | } |
1055 | 1107 | ||
1108 | ide_ports[hwif->index] = hwif; | ||
1109 | |||
1056 | /* | 1110 | /* |
1057 | * Allocate the irq, if not already obtained for another hwif | 1111 | * Allocate the irq, if not already obtained for another hwif |
1058 | */ | 1112 | */ |
@@ -1066,8 +1120,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1066 | sa = IRQF_SHARED; | 1120 | sa = IRQF_SHARED; |
1067 | 1121 | ||
1068 | if (io_ports->ctl_addr) | 1122 | if (io_ports->ctl_addr) |
1069 | /* clear nIEN */ | 1123 | hwif->tp_ops->set_irq(hwif, 1); |
1070 | hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS, io_ports->ctl_addr); | ||
1071 | 1124 | ||
1072 | if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) | 1125 | if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) |
1073 | goto out_unlink; | 1126 | goto out_unlink; |
@@ -1082,17 +1135,17 @@ static int init_irq (ide_hwif_t *hwif) | |||
1082 | } | 1135 | } |
1083 | 1136 | ||
1084 | #if !defined(__mc68000__) | 1137 | #if !defined(__mc68000__) |
1085 | printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, | 1138 | printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, |
1086 | io_ports->data_addr, io_ports->status_addr, | 1139 | io_ports->data_addr, io_ports->status_addr, |
1087 | io_ports->ctl_addr, hwif->irq); | 1140 | io_ports->ctl_addr, hwif->irq); |
1088 | #else | 1141 | #else |
1089 | printk("%s at 0x%08lx on irq %d", hwif->name, | 1142 | printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name, |
1090 | io_ports->data_addr, hwif->irq); | 1143 | io_ports->data_addr, hwif->irq); |
1091 | #endif /* __mc68000__ */ | 1144 | #endif /* __mc68000__ */ |
1092 | if (match) | 1145 | if (match) |
1093 | printk(" (%sed with %s)", | 1146 | printk(KERN_CONT " (%sed with %s)", |
1094 | hwif->sharing_irq ? "shar" : "serializ", match->name); | 1147 | hwif->sharing_irq ? "shar" : "serializ", match->name); |
1095 | printk("\n"); | 1148 | printk(KERN_CONT "\n"); |
1096 | 1149 | ||
1097 | mutex_unlock(&ide_cfg_mtx); | 1150 | mutex_unlock(&ide_cfg_mtx); |
1098 | return 0; | 1151 | return 0; |
@@ -1227,7 +1280,7 @@ static int hwif_init(ide_hwif_t *hwif) | |||
1227 | if (!hwif->irq) { | 1280 | if (!hwif->irq) { |
1228 | hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); | 1281 | hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); |
1229 | if (!hwif->irq) { | 1282 | if (!hwif->irq) { |
1230 | printk("%s: DISABLED, NO IRQ\n", hwif->name); | 1283 | printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); |
1231 | return 0; | 1284 | return 0; |
1232 | } | 1285 | } |
1233 | } | 1286 | } |
@@ -1257,16 +1310,16 @@ static int hwif_init(ide_hwif_t *hwif) | |||
1257 | */ | 1310 | */ |
1258 | hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); | 1311 | hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); |
1259 | if (!hwif->irq) { | 1312 | if (!hwif->irq) { |
1260 | printk("%s: Disabled unable to get IRQ %d.\n", | 1313 | printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", |
1261 | hwif->name, old_irq); | 1314 | hwif->name, old_irq); |
1262 | goto out; | 1315 | goto out; |
1263 | } | 1316 | } |
1264 | if (init_irq(hwif)) { | 1317 | if (init_irq(hwif)) { |
1265 | printk("%s: probed IRQ %d and default IRQ %d failed.\n", | 1318 | printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n", |
1266 | hwif->name, old_irq, hwif->irq); | 1319 | hwif->name, old_irq, hwif->irq); |
1267 | goto out; | 1320 | goto out; |
1268 | } | 1321 | } |
1269 | printk("%s: probed IRQ %d failed, using default.\n", | 1322 | printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n", |
1270 | hwif->name, hwif->irq); | 1323 | hwif->name, hwif->irq); |
1271 | 1324 | ||
1272 | done: | 1325 | done: |
@@ -1345,6 +1398,9 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
1345 | hwif->host_flags |= d->host_flags; | 1398 | hwif->host_flags |= d->host_flags; |
1346 | hwif->pio_mask = d->pio_mask; | 1399 | hwif->pio_mask = d->pio_mask; |
1347 | 1400 | ||
1401 | if (d->tp_ops) | ||
1402 | hwif->tp_ops = d->tp_ops; | ||
1403 | |||
1348 | /* ->set_pio_mode for DTC2278 is currently limited to port 0 */ | 1404 | /* ->set_pio_mode for DTC2278 is currently limited to port 0 */ |
1349 | if (hwif->chipset != ide_dtc2278 || hwif->channel == 0) | 1405 | if (hwif->chipset != ide_dtc2278 || hwif->channel == 0) |
1350 | hwif->port_ops = d->port_ops; | 1406 | hwif->port_ops = d->port_ops; |
@@ -1363,6 +1419,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
1363 | 1419 | ||
1364 | if (rc < 0) { | 1420 | if (rc < 0) { |
1365 | printk(KERN_INFO "%s: DMA disabled\n", hwif->name); | 1421 | printk(KERN_INFO "%s: DMA disabled\n", hwif->name); |
1422 | hwif->dma_base = 0; | ||
1366 | hwif->swdma_mask = 0; | 1423 | hwif->swdma_mask = 0; |
1367 | hwif->mwdma_mask = 0; | 1424 | hwif->mwdma_mask = 0; |
1368 | hwif->ultra_mask = 0; | 1425 | hwif->ultra_mask = 0; |
@@ -1446,18 +1503,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif) | |||
1446 | return rc; | 1503 | return rc; |
1447 | } | 1504 | } |
1448 | 1505 | ||
1506 | static unsigned int ide_indexes; | ||
1507 | |||
1449 | /** | 1508 | /** |
1450 | * ide_find_port_slot - find free ide_hwifs[] slot | 1509 | * ide_find_port_slot - find free port slot |
1451 | * @d: IDE port info | 1510 | * @d: IDE port info |
1452 | * | 1511 | * |
1453 | * Return the new hwif. If we are out of free slots return NULL. | 1512 | * Return the new port slot index or -ENOENT if we are out of free slots. |
1454 | */ | 1513 | */ |
1455 | 1514 | ||
1456 | ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) | 1515 | static int ide_find_port_slot(const struct ide_port_info *d) |
1457 | { | 1516 | { |
1458 | ide_hwif_t *hwif; | 1517 | int idx = -ENOENT; |
1459 | int i; | ||
1460 | u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; | 1518 | u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; |
1519 | u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;; | ||
1461 | 1520 | ||
1462 | /* | 1521 | /* |
1463 | * Claim an unassigned slot. | 1522 | * Claim an unassigned slot. |
@@ -1469,51 +1528,114 @@ ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) | |||
1469 | * Unless there is a bootable card that does not use the standard | 1528 | * Unless there is a bootable card that does not use the standard |
1470 | * ports 0x1f0/0x170 (the ide0/ide1 defaults). | 1529 | * ports 0x1f0/0x170 (the ide0/ide1 defaults). |
1471 | */ | 1530 | */ |
1472 | if (bootable) { | 1531 | mutex_lock(&ide_cfg_mtx); |
1473 | i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0; | 1532 | if (MAX_HWIFS == 1) { |
1474 | 1533 | if (ide_indexes == 0 && i == 0) | |
1475 | for (; i < MAX_HWIFS; i++) { | 1534 | idx = 1; |
1476 | hwif = &ide_hwifs[i]; | ||
1477 | if (hwif->chipset == ide_unknown) | ||
1478 | goto out_found; | ||
1479 | } | ||
1480 | } else { | 1535 | } else { |
1481 | for (i = 2; i < MAX_HWIFS; i++) { | 1536 | if (bootable) { |
1482 | hwif = &ide_hwifs[i]; | 1537 | if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) |
1483 | if (hwif->chipset == ide_unknown) | 1538 | idx = ffz(ide_indexes | i); |
1484 | goto out_found; | 1539 | } else { |
1540 | if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) | ||
1541 | idx = ffz(ide_indexes | 3); | ||
1542 | else if ((ide_indexes & 3) != 3) | ||
1543 | idx = ffz(ide_indexes); | ||
1485 | } | 1544 | } |
1486 | for (i = 0; i < 2 && i < MAX_HWIFS; i++) { | 1545 | } |
1487 | hwif = &ide_hwifs[i]; | 1546 | if (idx >= 0) |
1488 | if (hwif->chipset == ide_unknown) | 1547 | ide_indexes |= (1 << idx); |
1489 | goto out_found; | 1548 | mutex_unlock(&ide_cfg_mtx); |
1549 | |||
1550 | return idx; | ||
1551 | } | ||
1552 | |||
1553 | static void ide_free_port_slot(int idx) | ||
1554 | { | ||
1555 | mutex_lock(&ide_cfg_mtx); | ||
1556 | ide_indexes &= ~(1 << idx); | ||
1557 | mutex_unlock(&ide_cfg_mtx); | ||
1558 | } | ||
1559 | |||
1560 | struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, | ||
1561 | hw_regs_t **hws) | ||
1562 | { | ||
1563 | struct ide_host *host; | ||
1564 | int i; | ||
1565 | |||
1566 | host = kzalloc(sizeof(*host), GFP_KERNEL); | ||
1567 | if (host == NULL) | ||
1568 | return NULL; | ||
1569 | |||
1570 | for (i = 0; i < MAX_HWIFS; i++) { | ||
1571 | ide_hwif_t *hwif; | ||
1572 | int idx; | ||
1573 | |||
1574 | if (hws[i] == NULL) | ||
1575 | continue; | ||
1576 | |||
1577 | hwif = kzalloc(sizeof(*hwif), GFP_KERNEL); | ||
1578 | if (hwif == NULL) | ||
1579 | continue; | ||
1580 | |||
1581 | idx = ide_find_port_slot(d); | ||
1582 | if (idx < 0) { | ||
1583 | printk(KERN_ERR "%s: no free slot for interface\n", | ||
1584 | d ? d->name : "ide"); | ||
1585 | kfree(hwif); | ||
1586 | continue; | ||
1490 | } | 1587 | } |
1588 | |||
1589 | ide_init_port_data(hwif, idx); | ||
1590 | |||
1591 | hwif->host = host; | ||
1592 | |||
1593 | host->ports[i] = hwif; | ||
1594 | host->n_ports++; | ||
1491 | } | 1595 | } |
1492 | 1596 | ||
1493 | printk(KERN_ERR "%s: no free slot for interface\n", | 1597 | if (host->n_ports == 0) { |
1494 | d ? d->name : "ide"); | 1598 | kfree(host); |
1599 | return NULL; | ||
1600 | } | ||
1495 | 1601 | ||
1496 | return NULL; | 1602 | if (hws[0]) |
1603 | host->dev[0] = hws[0]->dev; | ||
1604 | |||
1605 | if (d) | ||
1606 | host->host_flags = d->host_flags; | ||
1497 | 1607 | ||
1498 | out_found: | 1608 | return host; |
1499 | ide_init_port_data(hwif, i); | ||
1500 | return hwif; | ||
1501 | } | 1609 | } |
1502 | EXPORT_SYMBOL_GPL(ide_find_port_slot); | 1610 | EXPORT_SYMBOL_GPL(ide_host_alloc_all); |
1503 | 1611 | ||
1504 | int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | 1612 | struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) |
1613 | { | ||
1614 | hw_regs_t *hws_all[MAX_HWIFS]; | ||
1615 | int i; | ||
1616 | |||
1617 | for (i = 0; i < MAX_HWIFS; i++) | ||
1618 | hws_all[i] = (i < 4) ? hws[i] : NULL; | ||
1619 | |||
1620 | return ide_host_alloc_all(d, hws_all); | ||
1621 | } | ||
1622 | EXPORT_SYMBOL_GPL(ide_host_alloc); | ||
1623 | |||
1624 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | ||
1625 | hw_regs_t **hws) | ||
1505 | { | 1626 | { |
1506 | ide_hwif_t *hwif, *mate = NULL; | 1627 | ide_hwif_t *hwif, *mate = NULL; |
1507 | int i, rc = 0; | 1628 | int i, j = 0; |
1508 | 1629 | ||
1509 | for (i = 0; i < MAX_HWIFS; i++) { | 1630 | for (i = 0; i < MAX_HWIFS; i++) { |
1510 | if (idx[i] == 0xff) { | 1631 | hwif = host->ports[i]; |
1632 | |||
1633 | if (hwif == NULL) { | ||
1511 | mate = NULL; | 1634 | mate = NULL; |
1512 | continue; | 1635 | continue; |
1513 | } | 1636 | } |
1514 | 1637 | ||
1515 | hwif = &ide_hwifs[idx[i]]; | 1638 | ide_init_port_hw(hwif, hws[i]); |
1516 | |||
1517 | ide_port_apply_params(hwif); | 1639 | ide_port_apply_params(hwif); |
1518 | 1640 | ||
1519 | if (d == NULL) { | 1641 | if (d == NULL) { |
@@ -1534,10 +1656,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
1534 | } | 1656 | } |
1535 | 1657 | ||
1536 | for (i = 0; i < MAX_HWIFS; i++) { | 1658 | for (i = 0; i < MAX_HWIFS; i++) { |
1537 | if (idx[i] == 0xff) | 1659 | hwif = host->ports[i]; |
1538 | continue; | ||
1539 | 1660 | ||
1540 | hwif = &ide_hwifs[idx[i]]; | 1661 | if (hwif == NULL) |
1662 | continue; | ||
1541 | 1663 | ||
1542 | if (ide_probe_port(hwif) == 0) | 1664 | if (ide_probe_port(hwif) == 0) |
1543 | hwif->present = 1; | 1665 | hwif->present = 1; |
@@ -1551,19 +1673,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
1551 | } | 1673 | } |
1552 | 1674 | ||
1553 | for (i = 0; i < MAX_HWIFS; i++) { | 1675 | for (i = 0; i < MAX_HWIFS; i++) { |
1554 | if (idx[i] == 0xff) | 1676 | hwif = host->ports[i]; |
1555 | continue; | ||
1556 | 1677 | ||
1557 | hwif = &ide_hwifs[idx[i]]; | 1678 | if (hwif == NULL) |
1679 | continue; | ||
1558 | 1680 | ||
1559 | if (hwif_init(hwif) == 0) { | 1681 | if (hwif_init(hwif) == 0) { |
1560 | printk(KERN_INFO "%s: failed to initialize IDE " | 1682 | printk(KERN_INFO "%s: failed to initialize IDE " |
1561 | "interface\n", hwif->name); | 1683 | "interface\n", hwif->name); |
1562 | hwif->present = 0; | 1684 | hwif->present = 0; |
1563 | rc = -1; | ||
1564 | continue; | 1685 | continue; |
1565 | } | 1686 | } |
1566 | 1687 | ||
1688 | j++; | ||
1689 | |||
1567 | if (hwif->present) | 1690 | if (hwif->present) |
1568 | ide_port_setup_devices(hwif); | 1691 | ide_port_setup_devices(hwif); |
1569 | 1692 | ||
@@ -1574,10 +1697,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
1574 | } | 1697 | } |
1575 | 1698 | ||
1576 | for (i = 0; i < MAX_HWIFS; i++) { | 1699 | for (i = 0; i < MAX_HWIFS; i++) { |
1577 | if (idx[i] == 0xff) | 1700 | hwif = host->ports[i]; |
1578 | continue; | ||
1579 | 1701 | ||
1580 | hwif = &ide_hwifs[idx[i]]; | 1702 | if (hwif == NULL) |
1703 | continue; | ||
1581 | 1704 | ||
1582 | if (hwif->chipset == ide_unknown) | 1705 | if (hwif->chipset == ide_unknown) |
1583 | hwif->chipset = ide_generic; | 1706 | hwif->chipset = ide_generic; |
@@ -1587,10 +1710,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
1587 | } | 1710 | } |
1588 | 1711 | ||
1589 | for (i = 0; i < MAX_HWIFS; i++) { | 1712 | for (i = 0; i < MAX_HWIFS; i++) { |
1590 | if (idx[i] == 0xff) | 1713 | hwif = host->ports[i]; |
1591 | continue; | ||
1592 | 1714 | ||
1593 | hwif = &ide_hwifs[idx[i]]; | 1715 | if (hwif == NULL) |
1716 | continue; | ||
1594 | 1717 | ||
1595 | ide_sysfs_register_port(hwif); | 1718 | ide_sysfs_register_port(hwif); |
1596 | ide_proc_register_port(hwif); | 1719 | ide_proc_register_port(hwif); |
@@ -1599,21 +1722,64 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
1599 | ide_proc_port_register_devices(hwif); | 1722 | ide_proc_port_register_devices(hwif); |
1600 | } | 1723 | } |
1601 | 1724 | ||
1602 | return rc; | 1725 | return j ? 0 : -1; |
1603 | } | 1726 | } |
1604 | EXPORT_SYMBOL_GPL(ide_device_add_all); | 1727 | EXPORT_SYMBOL_GPL(ide_host_register); |
1605 | 1728 | ||
1606 | int ide_device_add(u8 idx[4], const struct ide_port_info *d) | 1729 | int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws, |
1730 | struct ide_host **hostp) | ||
1607 | { | 1731 | { |
1608 | u8 idx_all[MAX_HWIFS]; | 1732 | struct ide_host *host; |
1733 | int rc; | ||
1734 | |||
1735 | host = ide_host_alloc(d, hws); | ||
1736 | if (host == NULL) | ||
1737 | return -ENOMEM; | ||
1738 | |||
1739 | rc = ide_host_register(host, d, hws); | ||
1740 | if (rc) { | ||
1741 | ide_host_free(host); | ||
1742 | return rc; | ||
1743 | } | ||
1744 | |||
1745 | if (hostp) | ||
1746 | *hostp = host; | ||
1747 | |||
1748 | return 0; | ||
1749 | } | ||
1750 | EXPORT_SYMBOL_GPL(ide_host_add); | ||
1751 | |||
1752 | void ide_host_free(struct ide_host *host) | ||
1753 | { | ||
1754 | ide_hwif_t *hwif; | ||
1609 | int i; | 1755 | int i; |
1610 | 1756 | ||
1611 | for (i = 0; i < MAX_HWIFS; i++) | 1757 | for (i = 0; i < MAX_HWIFS; i++) { |
1612 | idx_all[i] = (i < 4) ? idx[i] : 0xff; | 1758 | hwif = host->ports[i]; |
1759 | |||
1760 | if (hwif == NULL) | ||
1761 | continue; | ||
1762 | |||
1763 | ide_free_port_slot(hwif->index); | ||
1764 | kfree(hwif); | ||
1765 | } | ||
1613 | 1766 | ||
1614 | return ide_device_add_all(idx_all, d); | 1767 | kfree(host); |
1615 | } | 1768 | } |
1616 | EXPORT_SYMBOL_GPL(ide_device_add); | 1769 | EXPORT_SYMBOL_GPL(ide_host_free); |
1770 | |||
1771 | void ide_host_remove(struct ide_host *host) | ||
1772 | { | ||
1773 | int i; | ||
1774 | |||
1775 | for (i = 0; i < MAX_HWIFS; i++) { | ||
1776 | if (host->ports[i]) | ||
1777 | ide_unregister(host->ports[i]); | ||
1778 | } | ||
1779 | |||
1780 | ide_host_free(host); | ||
1781 | } | ||
1782 | EXPORT_SYMBOL_GPL(ide_host_remove); | ||
1617 | 1783 | ||
1618 | void ide_port_scan(ide_hwif_t *hwif) | 1784 | void ide_port_scan(ide_hwif_t *hwif) |
1619 | { | 1785 | { |
@@ -1634,11 +1800,10 @@ void ide_port_scan(ide_hwif_t *hwif) | |||
1634 | } | 1800 | } |
1635 | EXPORT_SYMBOL_GPL(ide_port_scan); | 1801 | EXPORT_SYMBOL_GPL(ide_port_scan); |
1636 | 1802 | ||
1637 | static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, | 1803 | static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, |
1638 | const struct ide_port_info *d, | 1804 | u8 port_no, const struct ide_port_info *d, |
1639 | unsigned long config) | 1805 | unsigned long config) |
1640 | { | 1806 | { |
1641 | ide_hwif_t *hwif; | ||
1642 | unsigned long base, ctl; | 1807 | unsigned long base, ctl; |
1643 | int irq; | 1808 | int irq; |
1644 | 1809 | ||
@@ -1668,33 +1833,25 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, | |||
1668 | ide_std_init_ports(hw, base, ctl); | 1833 | ide_std_init_ports(hw, base, ctl); |
1669 | hw->irq = irq; | 1834 | hw->irq = irq; |
1670 | hw->chipset = d->chipset; | 1835 | hw->chipset = d->chipset; |
1836 | hw->config = config; | ||
1671 | 1837 | ||
1672 | hwif = ide_find_port_slot(d); | 1838 | hws[port_no] = hw; |
1673 | if (hwif) { | ||
1674 | ide_init_port_hw(hwif, hw); | ||
1675 | if (config) | ||
1676 | hwif->config_data = config; | ||
1677 | idx[port_no] = hwif->index; | ||
1678 | } | ||
1679 | } | 1839 | } |
1680 | 1840 | ||
1681 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | 1841 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) |
1682 | { | 1842 | { |
1683 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 1843 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; |
1684 | hw_regs_t hw[2]; | ||
1685 | 1844 | ||
1686 | memset(&hw, 0, sizeof(hw)); | 1845 | memset(&hw, 0, sizeof(hw)); |
1687 | 1846 | ||
1688 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) | 1847 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) |
1689 | ide_legacy_init_one(idx, &hw[0], 0, d, config); | 1848 | ide_legacy_init_one(hws, &hw[0], 0, d, config); |
1690 | ide_legacy_init_one(idx, &hw[1], 1, d, config); | 1849 | ide_legacy_init_one(hws, &hw[1], 1, d, config); |
1691 | 1850 | ||
1692 | if (idx[0] == 0xff && idx[1] == 0xff && | 1851 | if (hws[0] == NULL && hws[1] == NULL && |
1693 | (d->host_flags & IDE_HFLAG_SINGLE)) | 1852 | (d->host_flags & IDE_HFLAG_SINGLE)) |
1694 | return -ENOENT; | 1853 | return -ENOENT; |
1695 | 1854 | ||
1696 | ide_device_add(idx, d); | 1855 | return ide_host_add(d, hws, NULL); |
1697 | |||
1698 | return 0; | ||
1699 | } | 1856 | } |
1700 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); | 1857 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); |