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.c100
1 files changed, 68 insertions, 32 deletions
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 887682a24e36..c24e86f07804 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -53,7 +53,8 @@ struct mac_esp_priv {
53 void __iomem *pdma_io; 53 void __iomem *pdma_io;
54 int error; 54 int error;
55}; 55};
56static struct platform_device *internal_esp, *external_esp; 56static struct platform_device *internal_pdev, *external_pdev;
57static struct esp *esp_chips[2];
57 58
58#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ 59#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
59 platform_get_drvdata((struct platform_device *) \ 60 platform_get_drvdata((struct platform_device *) \
@@ -170,7 +171,7 @@ static inline int mac_esp_wait_for_dreq(struct esp *esp)
170 171
171#define MAC_ESP_PDMA_LOOP(operands) \ 172#define MAC_ESP_PDMA_LOOP(operands) \
172 asm volatile ( \ 173 asm volatile ( \
173 " tstw %2 \n" \ 174 " tstw %1 \n" \
174 " jbeq 20f \n" \ 175 " jbeq 20f \n" \
175 "1: movew " operands " \n" \ 176 "1: movew " operands " \n" \
176 "2: movew " operands " \n" \ 177 "2: movew " operands " \n" \
@@ -188,14 +189,14 @@ static inline int mac_esp_wait_for_dreq(struct esp *esp)
188 "14: movew " operands " \n" \ 189 "14: movew " operands " \n" \
189 "15: movew " operands " \n" \ 190 "15: movew " operands " \n" \
190 "16: movew " operands " \n" \ 191 "16: movew " operands " \n" \
191 " subqw #1,%2 \n" \ 192 " subqw #1,%1 \n" \
192 " jbne 1b \n" \ 193 " jbne 1b \n" \
193 "20: tstw %3 \n" \ 194 "20: tstw %2 \n" \
194 " jbeq 30f \n" \ 195 " jbeq 30f \n" \
195 "21: movew " operands " \n" \ 196 "21: movew " operands " \n" \
196 " subqw #1,%3 \n" \ 197 " subqw #1,%2 \n" \
197 " jbne 21b \n" \ 198 " jbne 21b \n" \
198 "30: tstw %4 \n" \ 199 "30: tstw %3 \n" \
199 " jbeq 40f \n" \ 200 " jbeq 40f \n" \
200 "31: moveb " operands " \n" \ 201 "31: moveb " operands " \n" \
201 "32: nop \n" \ 202 "32: nop \n" \
@@ -223,8 +224,8 @@ static inline int mac_esp_wait_for_dreq(struct esp *esp)
223 " .long 31b,40b \n" \ 224 " .long 31b,40b \n" \
224 " .long 32b,40b \n" \ 225 " .long 32b,40b \n" \
225 " .previous \n" \ 226 " .previous \n" \
226 : "+a" (addr) \ 227 : "+a" (addr), "+r" (count32), "+r" (count2) \
227 : "a" (mep->pdma_io), "r" (count32), "r" (count2), "g" (esp_count)) 228 : "g" (count1), "a" (mep->pdma_io))
228 229
229static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count, 230static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
230 u32 dma_count, int write, u8 cmd) 231 u32 dma_count, int write, u8 cmd)
@@ -247,19 +248,20 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
247 do { 248 do {
248 unsigned int count32 = esp_count >> 5; 249 unsigned int count32 = esp_count >> 5;
249 unsigned int count2 = (esp_count & 0x1F) >> 1; 250 unsigned int count2 = (esp_count & 0x1F) >> 1;
251 unsigned int count1 = esp_count & 1;
250 unsigned int start_addr = addr; 252 unsigned int start_addr = addr;
251 253
252 if (mac_esp_wait_for_dreq(esp)) 254 if (mac_esp_wait_for_dreq(esp))
253 break; 255 break;
254 256
255 if (write) { 257 if (write) {
256 MAC_ESP_PDMA_LOOP("%1@,%0@+"); 258 MAC_ESP_PDMA_LOOP("%4@,%0@+");
257 259
258 esp_count -= addr - start_addr; 260 esp_count -= addr - start_addr;
259 } else { 261 } else {
260 unsigned int n; 262 unsigned int n;
261 263
262 MAC_ESP_PDMA_LOOP("%0@+,%1@"); 264 MAC_ESP_PDMA_LOOP("%0@+,%4@");
263 265
264 if (mac_esp_wait_for_empty_fifo(esp)) 266 if (mac_esp_wait_for_empty_fifo(esp))
265 break; 267 break;
@@ -442,6 +444,32 @@ static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
442 return dma_len > 0xFFFF ? 0xFFFF : dma_len; 444 return dma_len > 0xFFFF ? 0xFFFF : dma_len;
443} 445}
444 446
447static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id)
448{
449 int got_intr;
450
451 /*
452 * This is an edge triggered IRQ, so we have to be careful to
453 * avoid missing a transition when it is shared by two ESP devices.
454 */
455
456 do {
457 got_intr = 0;
458 if (esp_chips[0] &&
459 (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) {
460 (void)scsi_esp_intr(irq, esp_chips[0]);
461 got_intr = 1;
462 }
463 if (esp_chips[1] &&
464 (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) {
465 (void)scsi_esp_intr(irq, esp_chips[1]);
466 got_intr = 1;
467 }
468 } while (got_intr);
469
470 return IRQ_HANDLED;
471}
472
445static struct esp_driver_ops mac_esp_ops = { 473static struct esp_driver_ops mac_esp_ops = {
446 .esp_write8 = mac_esp_write8, 474 .esp_write8 = mac_esp_write8,
447 .esp_read8 = mac_esp_read8, 475 .esp_read8 = mac_esp_read8,
@@ -556,10 +584,16 @@ static int __devinit esp_mac_probe(struct platform_device *dev)
556 } 584 }
557 585
558 host->irq = IRQ_MAC_SCSI; 586 host->irq = IRQ_MAC_SCSI;
559 err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP", 587 esp_chips[dev->id] = esp;
560 esp); 588 mb();
561 if (err < 0) 589 if (esp_chips[!dev->id] == NULL) {
562 goto fail_free_priv; 590 err = request_irq(host->irq, mac_scsi_esp_intr, 0,
591 "Mac ESP", NULL);
592 if (err < 0) {
593 esp_chips[dev->id] = NULL;
594 goto fail_free_priv;
595 }
596 }
563 597
564 err = scsi_esp_register(esp, &dev->dev); 598 err = scsi_esp_register(esp, &dev->dev);
565 if (err) 599 if (err)
@@ -568,7 +602,8 @@ static int __devinit esp_mac_probe(struct platform_device *dev)
568 return 0; 602 return 0;
569 603
570fail_free_irq: 604fail_free_irq:
571 free_irq(host->irq, esp); 605 if (esp_chips[!dev->id] == NULL)
606 free_irq(host->irq, esp);
572fail_free_priv: 607fail_free_priv:
573 kfree(mep); 608 kfree(mep);
574fail_free_command_block: 609fail_free_command_block:
@@ -587,7 +622,9 @@ static int __devexit esp_mac_remove(struct platform_device *dev)
587 622
588 scsi_esp_unregister(esp); 623 scsi_esp_unregister(esp);
589 624
590 free_irq(irq, esp); 625 esp_chips[dev->id] = NULL;
626 if (!(esp_chips[0] || esp_chips[1]))
627 free_irq(irq, NULL);
591 628
592 kfree(mep); 629 kfree(mep);
593 630
@@ -614,19 +651,18 @@ static int __init mac_esp_init(void)
614 if (err) 651 if (err)
615 return err; 652 return err;
616 653
617 internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0); 654 internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0);
618 if (internal_esp && platform_device_add(internal_esp)) { 655 if (internal_pdev && platform_device_add(internal_pdev)) {
619 platform_device_put(internal_esp); 656 platform_device_put(internal_pdev);
620 internal_esp = NULL; 657 internal_pdev = NULL;
621 } 658 }
622 659 external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1);
623 external_esp = platform_device_alloc(DRV_MODULE_NAME, 1); 660 if (external_pdev && platform_device_add(external_pdev)) {
624 if (external_esp && platform_device_add(external_esp)) { 661 platform_device_put(external_pdev);
625 platform_device_put(external_esp); 662 external_pdev = NULL;
626 external_esp = NULL;
627 } 663 }
628 664
629 if (internal_esp || external_esp) { 665 if (internal_pdev || external_pdev) {
630 return 0; 666 return 0;
631 } else { 667 } else {
632 platform_driver_unregister(&esp_mac_driver); 668 platform_driver_unregister(&esp_mac_driver);
@@ -638,13 +674,13 @@ static void __exit mac_esp_exit(void)
638{ 674{
639 platform_driver_unregister(&esp_mac_driver); 675 platform_driver_unregister(&esp_mac_driver);
640 676
641 if (internal_esp) { 677 if (internal_pdev) {
642 platform_device_unregister(internal_esp); 678 platform_device_unregister(internal_pdev);
643 internal_esp = NULL; 679 internal_pdev = NULL;
644 } 680 }
645 if (external_esp) { 681 if (external_pdev) {
646 platform_device_unregister(external_esp); 682 platform_device_unregister(external_pdev);
647 external_esp = NULL; 683 external_pdev = NULL;
648 } 684 }
649} 685}
650 686