diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/mac_esp.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/mac_esp.c')
-rw-r--r-- | drivers/scsi/mac_esp.c | 153 |
1 files changed, 55 insertions, 98 deletions
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index c24e86f07804..3893337e3dd3 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c | |||
@@ -19,10 +19,10 @@ | |||
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/nubus.h> | 21 | #include <linux/nubus.h> |
22 | #include <linux/slab.h> | ||
22 | 23 | ||
23 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
24 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
25 | |||
26 | #include <asm/macints.h> | 26 | #include <asm/macints.h> |
27 | #include <asm/macintosh.h> | 27 | #include <asm/macintosh.h> |
28 | 28 | ||
@@ -53,7 +53,6 @@ struct mac_esp_priv { | |||
53 | void __iomem *pdma_io; | 53 | void __iomem *pdma_io; |
54 | int error; | 54 | int error; |
55 | }; | 55 | }; |
56 | static struct platform_device *internal_pdev, *external_pdev; | ||
57 | static struct esp *esp_chips[2]; | 56 | static struct esp *esp_chips[2]; |
58 | 57 | ||
59 | #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ | 58 | #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ |
@@ -279,24 +278,27 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
279 | * Programmed IO routines follow. | 278 | * Programmed IO routines follow. |
280 | */ | 279 | */ |
281 | 280 | ||
282 | static inline int mac_esp_wait_for_fifo(struct esp *esp) | 281 | static inline unsigned int mac_esp_wait_for_fifo(struct esp *esp) |
283 | { | 282 | { |
284 | int i = 500000; | 283 | int i = 500000; |
285 | 284 | ||
286 | do { | 285 | do { |
287 | if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) | 286 | unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES; |
288 | return 0; | 287 | |
288 | if (fbytes) | ||
289 | return fbytes; | ||
289 | 290 | ||
290 | udelay(2); | 291 | udelay(2); |
291 | } while (--i); | 292 | } while (--i); |
292 | 293 | ||
293 | printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n", | 294 | printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n", |
294 | esp_read8(ESP_STATUS)); | 295 | esp_read8(ESP_STATUS)); |
295 | return 1; | 296 | return 0; |
296 | } | 297 | } |
297 | 298 | ||
298 | static inline int mac_esp_wait_for_intr(struct esp *esp) | 299 | static inline int mac_esp_wait_for_intr(struct esp *esp) |
299 | { | 300 | { |
301 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); | ||
300 | int i = 500000; | 302 | int i = 500000; |
301 | 303 | ||
302 | do { | 304 | do { |
@@ -308,6 +310,7 @@ static inline int mac_esp_wait_for_intr(struct esp *esp) | |||
308 | } while (--i); | 310 | } while (--i); |
309 | 311 | ||
310 | printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg); | 312 | printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg); |
313 | mep->error = 1; | ||
311 | return 1; | 314 | return 1; |
312 | } | 315 | } |
313 | 316 | ||
@@ -347,11 +350,10 @@ static inline int mac_esp_wait_for_intr(struct esp *esp) | |||
347 | static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | 350 | static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, |
348 | u32 dma_count, int write, u8 cmd) | 351 | u32 dma_count, int write, u8 cmd) |
349 | { | 352 | { |
350 | unsigned long flags; | ||
351 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); | 353 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); |
352 | u8 *fifo = esp->regs + ESP_FDATA * 16; | 354 | u8 *fifo = esp->regs + ESP_FDATA * 16; |
353 | 355 | ||
354 | local_irq_save(flags); | 356 | disable_irq(esp->host->irq); |
355 | 357 | ||
356 | cmd &= ~ESP_CMD_DMA; | 358 | cmd &= ~ESP_CMD_DMA; |
357 | mep->error = 0; | 359 | mep->error = 0; |
@@ -359,11 +361,35 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
359 | if (write) { | 361 | if (write) { |
360 | scsi_esp_cmd(esp, cmd); | 362 | scsi_esp_cmd(esp, cmd); |
361 | 363 | ||
362 | if (!mac_esp_wait_for_intr(esp)) { | 364 | while (1) { |
363 | if (mac_esp_wait_for_fifo(esp)) | 365 | unsigned int n; |
364 | esp_count = 0; | 366 | |
365 | } else { | 367 | n = mac_esp_wait_for_fifo(esp); |
366 | esp_count = 0; | 368 | if (!n) |
369 | break; | ||
370 | |||
371 | if (n > esp_count) | ||
372 | n = esp_count; | ||
373 | esp_count -= n; | ||
374 | |||
375 | MAC_ESP_PIO_LOOP("%2@,%0@+", n); | ||
376 | |||
377 | if (!esp_count) | ||
378 | break; | ||
379 | |||
380 | if (mac_esp_wait_for_intr(esp)) | ||
381 | break; | ||
382 | |||
383 | if (((esp->sreg & ESP_STAT_PMASK) != ESP_DIP) && | ||
384 | ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)) | ||
385 | break; | ||
386 | |||
387 | esp->ireg = esp_read8(ESP_INTRPT); | ||
388 | if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) != | ||
389 | ESP_INTR_BSERV) | ||
390 | break; | ||
391 | |||
392 | scsi_esp_cmd(esp, ESP_CMD_TI); | ||
367 | } | 393 | } |
368 | } else { | 394 | } else { |
369 | scsi_esp_cmd(esp, ESP_CMD_FLUSH); | 395 | scsi_esp_cmd(esp, ESP_CMD_FLUSH); |
@@ -374,47 +400,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); | 400 | MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count); |
375 | 401 | ||
376 | scsi_esp_cmd(esp, cmd); | 402 | scsi_esp_cmd(esp, cmd); |
377 | } | ||
378 | |||
379 | while (esp_count) { | ||
380 | unsigned int n; | ||
381 | 403 | ||
382 | if (mac_esp_wait_for_intr(esp)) { | 404 | while (esp_count) { |
383 | mep->error = 1; | 405 | 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 | 406 | ||
402 | if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP) | 407 | if (mac_esp_wait_for_intr(esp)) |
403 | break; | 408 | break; |
404 | 409 | ||
405 | if (esp_count) { | 410 | if (((esp->sreg & ESP_STAT_PMASK) != ESP_DOP) && |
406 | esp->ireg = esp_read8(ESP_INTRPT); | 411 | ((esp->sreg & ESP_STAT_PMASK) != ESP_MOP)) |
407 | if (esp->ireg & ESP_INTR_DC) | 412 | break; |
408 | break; | ||
409 | 413 | ||
410 | scsi_esp_cmd(esp, ESP_CMD_TI); | ||
411 | } | ||
412 | } else { | ||
413 | esp->ireg = esp_read8(ESP_INTRPT); | 414 | esp->ireg = esp_read8(ESP_INTRPT); |
414 | if (esp->ireg & ESP_INTR_DC) | 415 | if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) != |
416 | ESP_INTR_BSERV) | ||
415 | break; | 417 | break; |
416 | 418 | ||
417 | n = MAC_ESP_FIFO_SIZE - n; | 419 | n = MAC_ESP_FIFO_SIZE - |
420 | (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES); | ||
418 | if (n > esp_count) | 421 | if (n > esp_count) |
419 | n = esp_count; | 422 | n = esp_count; |
420 | 423 | ||
@@ -429,7 +432,7 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
429 | } | 432 | } |
430 | } | 433 | } |
431 | 434 | ||
432 | local_irq_restore(flags); | 435 | enable_irq(esp->host->irq); |
433 | } | 436 | } |
434 | 437 | ||
435 | static int mac_esp_irq_pending(struct esp *esp) | 438 | static int mac_esp_irq_pending(struct esp *esp) |
@@ -492,29 +495,12 @@ static int __devinit esp_mac_probe(struct platform_device *dev) | |||
492 | struct Scsi_Host *host; | 495 | struct Scsi_Host *host; |
493 | struct esp *esp; | 496 | struct esp *esp; |
494 | int err; | 497 | int err; |
495 | int chips_present; | ||
496 | struct mac_esp_priv *mep; | 498 | struct mac_esp_priv *mep; |
497 | 499 | ||
498 | if (!MACH_IS_MAC) | 500 | if (!MACH_IS_MAC) |
499 | return -ENODEV; | 501 | return -ENODEV; |
500 | 502 | ||
501 | switch (macintosh_config->scsi_type) { | 503 | 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; | 504 | return -ENODEV; |
519 | 505 | ||
520 | host = scsi_host_alloc(tpnt, sizeof(struct esp)); | 506 | host = scsi_host_alloc(tpnt, sizeof(struct esp)); |
@@ -639,55 +625,26 @@ static struct platform_driver esp_mac_driver = { | |||
639 | .probe = esp_mac_probe, | 625 | .probe = esp_mac_probe, |
640 | .remove = __devexit_p(esp_mac_remove), | 626 | .remove = __devexit_p(esp_mac_remove), |
641 | .driver = { | 627 | .driver = { |
642 | .name = DRV_MODULE_NAME, | 628 | .name = DRV_MODULE_NAME, |
629 | .owner = THIS_MODULE, | ||
643 | }, | 630 | }, |
644 | }; | 631 | }; |
645 | 632 | ||
646 | static int __init mac_esp_init(void) | 633 | static int __init mac_esp_init(void) |
647 | { | 634 | { |
648 | int err; | 635 | 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 | } | 636 | } |
672 | 637 | ||
673 | static void __exit mac_esp_exit(void) | 638 | static void __exit mac_esp_exit(void) |
674 | { | 639 | { |
675 | platform_driver_unregister(&esp_mac_driver); | 640 | 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 | } | 641 | } |
686 | 642 | ||
687 | MODULE_DESCRIPTION("Mac ESP SCSI driver"); | 643 | MODULE_DESCRIPTION("Mac ESP SCSI driver"); |
688 | MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>"); | 644 | MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>"); |
689 | MODULE_LICENSE("GPL v2"); | 645 | MODULE_LICENSE("GPL v2"); |
690 | MODULE_VERSION(DRV_VERSION); | 646 | MODULE_VERSION(DRV_VERSION); |
647 | MODULE_ALIAS("platform:" DRV_MODULE_NAME); | ||
691 | 648 | ||
692 | module_init(mac_esp_init); | 649 | module_init(mac_esp_init); |
693 | module_exit(mac_esp_exit); | 650 | module_exit(mac_esp_exit); |