aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mac_esp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mac_esp.c')
-rw-r--r--drivers/scsi/mac_esp.c152
1 files changed, 54 insertions, 98 deletions
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index c24e86f07804..4a90eaf7cb63 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -22,7 +22,6 @@
22 22
23#include <asm/irq.h> 23#include <asm/irq.h>
24#include <asm/dma.h> 24#include <asm/dma.h>
25
26#include <asm/macints.h> 25#include <asm/macints.h>
27#include <asm/macintosh.h> 26#include <asm/macintosh.h>
28 27
@@ -53,7 +52,6 @@ struct mac_esp_priv {
53 void __iomem *pdma_io; 52 void __iomem *pdma_io;
54 int error; 53 int error;
55}; 54};
56static struct platform_device *internal_pdev, *external_pdev;
57static struct esp *esp_chips[2]; 55static struct esp *esp_chips[2];
58 56
59#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ 57#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
@@ -279,24 +277,27 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
279 * Programmed IO routines follow. 277 * Programmed IO routines follow.
280 */ 278 */
281 279
282static inline int mac_esp_wait_for_fifo(struct esp *esp) 280static inline unsigned int mac_esp_wait_for_fifo(struct esp *esp)
283{ 281{
284 int i = 500000; 282 int i = 500000;
285 283
286 do { 284 do {
287 if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) 285 unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
288 return 0; 286
287 if (fbytes)
288 return fbytes;
289 289
290 udelay(2); 290 udelay(2);
291 } while (--i); 291 } while (--i);
292 292
293 printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n", 293 printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
294 esp_read8(ESP_STATUS)); 294 esp_read8(ESP_STATUS));
295 return 1; 295 return 0;
296} 296}
297 297
298static inline int mac_esp_wait_for_intr(struct esp *esp) 298static inline int mac_esp_wait_for_intr(struct esp *esp)
299{ 299{
300 struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
300 int i = 500000; 301 int i = 500000;
301 302
302 do { 303 do {
@@ -308,6 +309,7 @@ static inline int mac_esp_wait_for_intr(struct esp *esp)
308 } while (--i); 309 } while (--i);
309 310
310 printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg); 311 printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
312 mep->error = 1;
311 return 1; 313 return 1;
312} 314}
313 315
@@ -347,11 +349,10 @@ static inline int mac_esp_wait_for_intr(struct esp *esp)
347static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, 349static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
348 u32 dma_count, int write, u8 cmd) 350 u32 dma_count, int write, u8 cmd)
349{ 351{
350 unsigned long flags;
351 struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); 352 struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
352 u8 *fifo = esp->regs + ESP_FDATA * 16; 353 u8 *fifo = esp->regs + ESP_FDATA * 16;
353 354
354 local_irq_save(flags); 355 disable_irq(esp->host->irq);
355 356
356 cmd &= ~ESP_CMD_DMA; 357 cmd &= ~ESP_CMD_DMA;
357 mep->error = 0; 358 mep->error = 0;
@@ -359,11 +360,35 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
359 if (write) { 360 if (write) {
360 scsi_esp_cmd(esp, cmd); 361 scsi_esp_cmd(esp, cmd);
361 362
362 if (!mac_esp_wait_for_intr(esp)) { 363 while (1) {
363 if (mac_esp_wait_for_fifo(esp)) 364 unsigned int n;
364 esp_count = 0; 365
365 } else { 366 n = mac_esp_wait_for_fifo(esp);
366 esp_count = 0; 367 if (!n)
368 break;
369
370 if (n > esp_count)
371 n = esp_count;
372 esp_count -= n;
373
374 MAC_ESP_PIO_LOOP("%2@,%0@+", n);
375
376 if (!esp_count)
377 break;
378
379 if (mac_esp_wait_for_intr(esp))
380 break;
381
382 if (((esp->sreg & ESP_STAT_PMASK) != ESP_DIP) &&
383 ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP))
384 break;
385
386 esp->ireg = esp_read8(ESP_INTRPT);
387 if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) !=
388 ESP_INTR_BSERV)
389 break;
390
391 scsi_esp_cmd(esp, ESP_CMD_TI);
367 } 392 }
368 } else { 393 } else {
369 scsi_esp_cmd(esp, ESP_CMD_FLUSH); 394 scsi_esp_cmd(esp, ESP_CMD_FLUSH);
@@ -374,47 +399,24 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
374 MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count); 399 MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
375 400
376 scsi_esp_cmd(esp, cmd); 401 scsi_esp_cmd(esp, cmd);
377 }
378
379 while (esp_count) {
380 unsigned int n;
381 402
382 if (mac_esp_wait_for_intr(esp)) { 403 while (esp_count) {
383 mep->error = 1; 404 unsigned int n;
384 break;
385 }
386
387 if (esp->sreg & ESP_STAT_SPAM) {
388 printk(KERN_ERR PFX "gross error\n");
389 mep->error = 1;
390 break;
391 }
392
393 n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
394
395 if (write) {
396 if (n > esp_count)
397 n = esp_count;
398 esp_count -= n;
399
400 MAC_ESP_PIO_LOOP("%2@,%0@+", n);
401 405
402 if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP) 406 if (mac_esp_wait_for_intr(esp))
403 break; 407 break;
404 408
405 if (esp_count) { 409 if (((esp->sreg & ESP_STAT_PMASK) != ESP_DOP) &&
406 esp->ireg = esp_read8(ESP_INTRPT); 410 ((esp->sreg & ESP_STAT_PMASK) != ESP_MOP))
407 if (esp->ireg & ESP_INTR_DC) 411 break;
408 break;
409 412
410 scsi_esp_cmd(esp, ESP_CMD_TI);
411 }
412 } else {
413 esp->ireg = esp_read8(ESP_INTRPT); 413 esp->ireg = esp_read8(ESP_INTRPT);
414 if (esp->ireg & ESP_INTR_DC) 414 if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) !=
415 ESP_INTR_BSERV)
415 break; 416 break;
416 417
417 n = MAC_ESP_FIFO_SIZE - n; 418 n = MAC_ESP_FIFO_SIZE -
419 (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES);
418 if (n > esp_count) 420 if (n > esp_count)
419 n = esp_count; 421 n = esp_count;
420 422
@@ -429,7 +431,7 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
429 } 431 }
430 } 432 }
431 433
432 local_irq_restore(flags); 434 enable_irq(esp->host->irq);
433} 435}
434 436
435static int mac_esp_irq_pending(struct esp *esp) 437static int mac_esp_irq_pending(struct esp *esp)
@@ -492,29 +494,12 @@ static int __devinit esp_mac_probe(struct platform_device *dev)
492 struct Scsi_Host *host; 494 struct Scsi_Host *host;
493 struct esp *esp; 495 struct esp *esp;
494 int err; 496 int err;
495 int chips_present;
496 struct mac_esp_priv *mep; 497 struct mac_esp_priv *mep;
497 498
498 if (!MACH_IS_MAC) 499 if (!MACH_IS_MAC)
499 return -ENODEV; 500 return -ENODEV;
500 501
501 switch (macintosh_config->scsi_type) { 502 if (dev->id > 1)
502 case MAC_SCSI_QUADRA:
503 case MAC_SCSI_QUADRA3:
504 chips_present = 1;
505 break;
506 case MAC_SCSI_QUADRA2:
507 if ((macintosh_config->ident == MAC_MODEL_Q900) ||
508 (macintosh_config->ident == MAC_MODEL_Q950))
509 chips_present = 2;
510 else
511 chips_present = 1;
512 break;
513 default:
514 chips_present = 0;
515 }
516
517 if (dev->id + 1 > chips_present)
518 return -ENODEV; 503 return -ENODEV;
519 504
520 host = scsi_host_alloc(tpnt, sizeof(struct esp)); 505 host = scsi_host_alloc(tpnt, sizeof(struct esp));
@@ -639,55 +624,26 @@ static struct platform_driver esp_mac_driver = {
639 .probe = esp_mac_probe, 624 .probe = esp_mac_probe,
640 .remove = __devexit_p(esp_mac_remove), 625 .remove = __devexit_p(esp_mac_remove),
641 .driver = { 626 .driver = {
642 .name = DRV_MODULE_NAME, 627 .name = DRV_MODULE_NAME,
628 .owner = THIS_MODULE,
643 }, 629 },
644}; 630};
645 631
646static int __init mac_esp_init(void) 632static int __init mac_esp_init(void)
647{ 633{
648 int err; 634 return platform_driver_register(&esp_mac_driver);
649
650 err = platform_driver_register(&esp_mac_driver);
651 if (err)
652 return err;
653
654 internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0);
655 if (internal_pdev && platform_device_add(internal_pdev)) {
656 platform_device_put(internal_pdev);
657 internal_pdev = NULL;
658 }
659 external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1);
660 if (external_pdev && platform_device_add(external_pdev)) {
661 platform_device_put(external_pdev);
662 external_pdev = NULL;
663 }
664
665 if (internal_pdev || external_pdev) {
666 return 0;
667 } else {
668 platform_driver_unregister(&esp_mac_driver);
669 return -ENOMEM;
670 }
671} 635}
672 636
673static void __exit mac_esp_exit(void) 637static void __exit mac_esp_exit(void)
674{ 638{
675 platform_driver_unregister(&esp_mac_driver); 639 platform_driver_unregister(&esp_mac_driver);
676
677 if (internal_pdev) {
678 platform_device_unregister(internal_pdev);
679 internal_pdev = NULL;
680 }
681 if (external_pdev) {
682 platform_device_unregister(external_pdev);
683 external_pdev = NULL;
684 }
685} 640}
686 641
687MODULE_DESCRIPTION("Mac ESP SCSI driver"); 642MODULE_DESCRIPTION("Mac ESP SCSI driver");
688MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>"); 643MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>");
689MODULE_LICENSE("GPL v2"); 644MODULE_LICENSE("GPL v2");
690MODULE_VERSION(DRV_VERSION); 645MODULE_VERSION(DRV_VERSION);
646MODULE_ALIAS("platform:" DRV_MODULE_NAME);
691 647
692module_init(mac_esp_init); 648module_init(mac_esp_init);
693module_exit(mac_esp_exit); 649module_exit(mac_esp_exit);