From cbad48deb38d8e442db9760ca1f950cd24429707 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 12 Nov 2014 16:12:07 +1100 Subject: mac_scsi: Convert to platform device Convert mac_scsi to platform device and eliminate scsi_register(). Platform resources for chip registers now follow the documentation. This should fix issues with the Mac IIci (and possibly other models too). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Acked-by: Geert Uytterhoeven Signed-off-by: Christoph Hellwig --- arch/m68k/include/asm/macintosh.h | 4 ++ arch/m68k/mac/config.c | 146 ++++++++++++++++++++++++++++++++++---- 2 files changed, 136 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index d323b2c2d07d..29c7c6c3a5f2 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -53,6 +53,10 @@ struct mac_model #define MAC_SCSI_QUADRA 2 #define MAC_SCSI_QUADRA2 3 #define MAC_SCSI_QUADRA3 4 +#define MAC_SCSI_IIFX 5 +#define MAC_SCSI_DUO 6 +#define MAC_SCSI_CCL 7 +#define MAC_SCSI_LATE 8 #define MAC_IDE_NONE 0 #define MAC_IDE_QUADRA 1 diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index a471eab1a4dd..e9c3756139fc 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -278,7 +278,7 @@ static struct mac_model mac_data_table[] = { .name = "IIfx", .adb_type = MAC_ADB_IOP, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_IIFX, .scc_type = MAC_SCC_IOP, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_IOP, @@ -329,7 +329,7 @@ static struct mac_model mac_data_table[] = { .name = "Color Classic", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_CCL, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -338,7 +338,7 @@ static struct mac_model mac_data_table[] = { .name = "Color Classic II", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_CCL, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -526,7 +526,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 520", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_CCL, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -535,7 +535,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 550", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_CCL, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -567,7 +567,7 @@ static struct mac_model mac_data_table[] = { .name = "TV", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_CCL, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -712,7 +712,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook 190", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_QUADRA, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LATE, .ide_type = MAC_IDE_BABOON, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, @@ -722,7 +722,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook 520", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_QUADRA, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LATE, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, .nubus_type = MAC_NUBUS, @@ -740,7 +740,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 210", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -749,7 +749,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 230", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -758,7 +758,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 250", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -767,7 +767,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 270c", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -776,7 +776,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 280", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -785,7 +785,7 @@ static struct mac_model mac_data_table[] = { .name = "PowerBook Duo 280c", .adb_type = MAC_ADB_PB2, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -929,6 +929,70 @@ static struct platform_device swim_pdev = { .resource = &swim_rsrc, }; +static const struct resource mac_scsi_iifx_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAC_SCSI, + .end = IRQ_MAC_SCSI, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50008000, + .end = 0x50009FFF, + }, +}; + +static const struct resource mac_scsi_duo_rsrc[] __initconst = { + { + .flags = IORESOURCE_MEM, + .start = 0xFEE02000, + .end = 0xFEE03FFF, + }, +}; + +static const struct resource mac_scsi_old_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAC_SCSI, + .end = IRQ_MAC_SCSI, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50010000, + .end = 0x50011FFF, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50006000, + .end = 0x50007FFF, + }, +}; + +static const struct resource mac_scsi_late_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAC_SCSI, + .end = IRQ_MAC_SCSI, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50010000, + .end = 0x50011FFF, + }, +}; + +static const struct resource mac_scsi_ccl_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAC_SCSI, + .end = IRQ_MAC_SCSI, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50F10000, + .end = 0x50F11FFF, + }, { + .flags = IORESOURCE_MEM, + .start = 0x50F06000, + .end = 0x50F07FFF, + }, +}; + static struct platform_device esp_0_pdev = { .name = "mac_esp", .id = 0, @@ -1000,6 +1064,60 @@ int __init mac_platform_init(void) (macintosh_config->ident == MAC_MODEL_Q950)) platform_device_register(&esp_1_pdev); break; + case MAC_SCSI_IIFX: + /* Addresses from The Guide to Mac Family Hardware. + * $5000 8000 - $5000 9FFF: SCSI DMA + * $5000 C000 - $5000 DFFF: Alternate SCSI (DMA) + * $5000 E000 - $5000 FFFF: Alternate SCSI (Hsk) + * The SCSI DMA custom IC embeds the 53C80 core. mac_scsi does + * not make use of its DMA or hardware handshaking logic. + */ + platform_device_register_simple("mac_scsi", 0, + mac_scsi_iifx_rsrc, ARRAY_SIZE(mac_scsi_iifx_rsrc)); + break; + case MAC_SCSI_DUO: + /* Addresses from the Duo Dock II Developer Note. + * $FEE0 2000 - $FEE0 3FFF: normal mode + * $FEE0 4000 - $FEE0 5FFF: pseudo DMA without /DRQ + * $FEE0 6000 - $FEE0 7FFF: pseudo DMA with /DRQ + * The NetBSD code indicates that both 5380 chips share + * an IRQ (?) which would need careful handling (see mac_esp). + */ + platform_device_register_simple("mac_scsi", 1, + mac_scsi_duo_rsrc, ARRAY_SIZE(mac_scsi_duo_rsrc)); + /* fall through */ + case MAC_SCSI_OLD: + /* Addresses from Developer Notes for Duo System, + * PowerBook 180 & 160, 140 & 170, Macintosh IIsi + * and also from The Guide to Mac Family Hardware for + * SE/30, II, IIx, IIcx, IIci. + * $5000 6000 - $5000 7FFF: pseudo-DMA with /DRQ + * $5001 0000 - $5001 1FFF: normal mode + * $5001 2000 - $5001 3FFF: pseudo-DMA without /DRQ + * GMFH says that $5000 0000 - $50FF FFFF "wraps + * $5000 0000 - $5001 FFFF eight times" (!) + * mess.org says IIci and Color Classic do not alias + * I/O address space. + */ + platform_device_register_simple("mac_scsi", 0, + mac_scsi_old_rsrc, ARRAY_SIZE(mac_scsi_old_rsrc)); + break; + case MAC_SCSI_LATE: + /* PDMA logic in 68040 PowerBooks is somehow different to + * '030 models. It's probably more like Quadras (see mac_esp). + */ + platform_device_register_simple("mac_scsi", 0, + mac_scsi_late_rsrc, ARRAY_SIZE(mac_scsi_late_rsrc)); + break; + case MAC_SCSI_CCL: + /* Addresses from the Color Classic Developer Note. + * $50F0 6000 - $50F0 7FFF: SCSI handshake + * $50F1 0000 - $50F1 1FFF: SCSI + * $50F1 2000 - $50F1 3FFF: SCSI DMA + */ + platform_device_register_simple("mac_scsi", 0, + mac_scsi_ccl_rsrc, ARRAY_SIZE(mac_scsi_ccl_rsrc)); + break; } /* -- cgit v1.2.3 From 16b29e75a78ae03250233468b68f7ae467d3dc7a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 12 Nov 2014 16:12:08 +1100 Subject: atari_scsi: Fix atari_scsi deadlocks on Falcon Don't disable irqs when waiting for the ST DMA "lock"; its release may require an interrupt. Introduce stdma_try_lock() for use in soft irq context. atari_scsi now tells the SCSI mid-layer to defer queueing a command if the ST DMA lock is not available, as per Michael's patch: http://marc.info/?l=linux-m68k&m=139095335824863&w=2 The falcon_got_lock variable is race prone: we can't disable IRQs while waiting to acquire the lock, so after acquiring it there must be some interval during which falcon_got_lock remains false. Introduce stdma_is_locked_by() to replace falcon_got_lock. The falcon_got_lock tests in the EH handlers are incorrect these days. It can happen that an EH handler is called after a command completes normally. Remove these checks along with falcon_got_lock. Also remove the complicated and racy fairness wait queues. If fairness is an issue (when SCSI competes with IDE for the ST DMA interrupt), the solution is likely to be a lower value for host->can_queue. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Acked-by: Geert Uytterhoeven Signed-off-by: Christoph Hellwig --- arch/m68k/atari/stdma.c | 61 +++++++++++++++++++----------- arch/m68k/include/asm/atari_stdma.h | 4 +- drivers/scsi/atari_NCR5380.c | 33 +++++----------- drivers/scsi/atari_scsi.c | 75 +++++++------------------------------ 4 files changed, 66 insertions(+), 107 deletions(-) (limited to 'arch') diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c index ddbf43ca8858..e5a66596b116 100644 --- a/arch/m68k/atari/stdma.c +++ b/arch/m68k/atari/stdma.c @@ -59,6 +59,31 @@ static irqreturn_t stdma_int (int irq, void *dummy); /************************* End of Prototypes **************************/ +/** + * stdma_try_lock - attempt to acquire ST DMA interrupt "lock" + * @handler: interrupt handler to use after acquisition + * + * Returns !0 if lock was acquired; otherwise 0. + */ + +int stdma_try_lock(irq_handler_t handler, void *data) +{ + unsigned long flags; + + local_irq_save(flags); + if (stdma_locked) { + local_irq_restore(flags); + return 0; + } + + stdma_locked = 1; + stdma_isr = handler; + stdma_isr_data = data; + local_irq_restore(flags); + return 1; +} +EXPORT_SYMBOL(stdma_try_lock); + /* * Function: void stdma_lock( isrfunc isr, void *data ) @@ -78,19 +103,10 @@ static irqreturn_t stdma_int (int irq, void *dummy); void stdma_lock(irq_handler_t handler, void *data) { - unsigned long flags; - - local_irq_save(flags); /* protect lock */ - /* Since the DMA is used for file system purposes, we have to sleep uninterruptible (there may be locked buffers) */ - wait_event(stdma_wait, !stdma_locked); - - stdma_locked = 1; - stdma_isr = handler; - stdma_isr_data = data; - local_irq_restore(flags); + wait_event(stdma_wait, stdma_try_lock(handler, data)); } EXPORT_SYMBOL(stdma_lock); @@ -122,22 +138,25 @@ void stdma_release(void) EXPORT_SYMBOL(stdma_release); -/* - * Function: int stdma_others_waiting( void ) - * - * Purpose: Check if someone waits for the ST-DMA lock. - * - * Inputs: none - * - * Returns: 0 if no one is waiting, != 0 otherwise +/** + * stdma_is_locked_by - allow lock holder to check whether it needs to release. + * @handler: interrupt handler previously used to acquire lock. * + * Returns !0 if locked for the given handler; 0 otherwise. */ -int stdma_others_waiting(void) +int stdma_is_locked_by(irq_handler_t handler) { - return waitqueue_active(&stdma_wait); + unsigned long flags; + int result; + + local_irq_save(flags); + result = stdma_locked && (stdma_isr == handler); + local_irq_restore(flags); + + return result; } -EXPORT_SYMBOL(stdma_others_waiting); +EXPORT_SYMBOL(stdma_is_locked_by); /* diff --git a/arch/m68k/include/asm/atari_stdma.h b/arch/m68k/include/asm/atari_stdma.h index 8e389b7fa70c..d24e34d870dc 100644 --- a/arch/m68k/include/asm/atari_stdma.h +++ b/arch/m68k/include/asm/atari_stdma.h @@ -8,11 +8,11 @@ /***************************** Prototypes *****************************/ +int stdma_try_lock(irq_handler_t, void *); void stdma_lock(irq_handler_t handler, void *data); void stdma_release( void ); -int stdma_others_waiting( void ); int stdma_islocked( void ); -void *stdma_locked_by( void ); +int stdma_is_locked_by(irq_handler_t); void stdma_init( void ); /************************* End of Prototypes **************************/ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 4eeb9684977b..7a6f90ce0316 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -879,10 +879,10 @@ static void NCR5380_exit(struct Scsi_Host *instance) * */ -static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) +static int NCR5380_queue_command(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { - SETUP_HOSTDATA(cmd->device->host); + struct NCR5380_hostdata *hostdata = shost_priv(instance); struct scsi_cmnd *tmp; unsigned long flags; @@ -893,7 +893,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n", H_NO(cmd)); cmd->result = (DID_ERROR << 16); - done(cmd); + cmd->scsi_done(cmd); return 0; } #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ @@ -904,8 +904,6 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, */ SET_NEXT(cmd, NULL); - cmd->scsi_done = done; - cmd->result = 0; /* @@ -915,7 +913,6 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, * sense data is only guaranteed to be valid while the condition exists. */ - local_irq_save(flags); /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA. * Otherwise a running NCR5380_main may steal the lock. * Lock before actually inserting due to fairness reasons explained in @@ -928,11 +925,11 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, * because also a timer int can trigger an abort or reset, which would * alter queues and touch the lock. */ - if (!IS_A_TT()) { - /* perhaps stop command timer here */ - falcon_get_lock(); - /* perhaps restart command timer here */ - } + if (!falcon_get_lock()) + return SCSI_MLQUEUE_HOST_BUSY; + + local_irq_save(flags); + if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { LIST(cmd, hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue); @@ -956,15 +953,13 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, * If we're not in an interrupt, we can call NCR5380_main() * unconditionally, because it cannot be already running. */ - if (in_interrupt() || ((flags >> 8) & 7) >= 6) + if (in_interrupt() || irqs_disabled()) queue_main(); else NCR5380_main(NULL); return 0; } -static DEF_SCSI_QCMD(NCR5380_queue_command) - /* * Function : NCR5380_main (void) * @@ -2554,10 +2549,6 @@ int NCR5380_abort(struct scsi_cmnd *cmd) local_irq_save(flags); - if (!IS_A_TT() && !falcon_got_lock) - printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n", - HOSTNO); - dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); @@ -2756,10 +2747,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) struct scsi_cmnd *connected, *disconnected_queue; #endif - if (!IS_A_TT() && !falcon_got_lock) - printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n", - H_NO(cmd)); - NCR5380_print_status(cmd->device->host); /* get in phase */ diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 48fabebdbbb0..b2e86d0630ce 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -184,7 +184,7 @@ static void atari_scsi_fetch_restbytes(void); static irqreturn_t scsi_tt_intr(int irq, void *dummy); static irqreturn_t scsi_falcon_intr(int irq, void *dummy); static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata); -static void falcon_get_lock(void); +static int falcon_get_lock(void); #ifdef CONFIG_ATARI_SCSI_RESET_BOOT static void atari_scsi_reset_boot(void); #endif @@ -473,17 +473,10 @@ static void atari_scsi_fetch_restbytes(void) #endif /* REAL_DMA */ -static int falcon_got_lock = 0; -static DECLARE_WAIT_QUEUE_HEAD(falcon_fairness_wait); -static int falcon_trying_lock = 0; -static DECLARE_WAIT_QUEUE_HEAD(falcon_try_wait); static int falcon_dont_release = 0; /* This function releases the lock on the DMA chip if there is no - * connected command and the disconnected queue is empty. On - * releasing, instances of falcon_get_lock are awoken, that put - * themselves to sleep for fairness. They can now try to get the lock - * again (but others waiting longer more probably will win). + * connected command and the disconnected queue is empty. */ static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata) @@ -495,20 +488,12 @@ static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata) local_irq_save(flags); - if (falcon_got_lock && !hostdata->disconnected_queue && - !hostdata->issue_queue && !hostdata->connected) { - - if (falcon_dont_release) { -#if 0 - printk("WARNING: Lock release not allowed. Ignored\n"); -#endif - local_irq_restore(flags); - return; - } - falcon_got_lock = 0; + if (!hostdata->disconnected_queue && + !hostdata->issue_queue && + !hostdata->connected && + !falcon_dont_release && + stdma_is_locked_by(scsi_falcon_intr)) stdma_release(); - wake_up(&falcon_fairness_wait); - } local_irq_restore(flags); } @@ -517,51 +502,19 @@ static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata) * If the DMA isn't locked already for SCSI, it tries to lock it by * calling stdma_lock(). But if the DMA is locked by the SCSI code and * there are other drivers waiting for the chip, we do not issue the - * command immediately but wait on 'falcon_fairness_queue'. We will be - * waked up when the DMA is unlocked by some SCSI interrupt. After that - * we try to get the lock again. - * But we must be prepared that more than one instance of - * falcon_get_lock() is waiting on the fairness queue. They should not - * try all at once to call stdma_lock(), one is enough! For that, the - * first one sets 'falcon_trying_lock', others that see that variable - * set wait on the queue 'falcon_try_wait'. - * Complicated, complicated.... Sigh... + * command immediately but tell the SCSI mid-layer to defer. */ -static void falcon_get_lock(void) +static int falcon_get_lock(void) { - unsigned long flags; - if (IS_A_TT()) - return; + return 1; - local_irq_save(flags); + if (in_interrupt()) + return stdma_try_lock(scsi_falcon_intr, NULL); - wait_event_cmd(falcon_fairness_wait, - in_interrupt() || !falcon_got_lock || !stdma_others_waiting(), - local_irq_restore(flags), - local_irq_save(flags)); - - while (!falcon_got_lock) { - if (in_irq()) - panic("Falcon SCSI hasn't ST-DMA lock in interrupt"); - if (!falcon_trying_lock) { - falcon_trying_lock = 1; - stdma_lock(scsi_falcon_intr, NULL); - falcon_got_lock = 1; - falcon_trying_lock = 0; - wake_up(&falcon_try_wait); - } else { - wait_event_cmd(falcon_try_wait, - falcon_got_lock && !falcon_trying_lock, - local_irq_restore(flags), - local_irq_save(flags)); - } - } - - local_irq_restore(flags); - if (!falcon_got_lock) - panic("Falcon SCSI: someone stole the lock :-(\n"); + stdma_lock(scsi_falcon_intr, NULL); + return 1; } -- cgit v1.2.3 From 3ff228af84b57767645d81a89c166c777646ad61 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 12 Nov 2014 16:12:09 +1100 Subject: atari_scsi: Convert to platform device Convert atari_scsi to platform device and eliminate scsi_register(). Validate __setup options later on so that module options are checked as well. Remove the comment about the scsi mid-layer disabling the host irq as it is no longer true (AFAICT). Also remove the obsolete slow interrupt stuff (IRQ_TYPE_SLOW == 0 anyway). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Acked-by: Geert Uytterhoeven Signed-off-by: Christoph Hellwig --- arch/m68k/atari/config.c | 27 +++ drivers/scsi/atari_scsi.c | 424 +++++++++++++++++++++++----------------------- drivers/scsi/atari_scsi.h | 17 -- 3 files changed, 237 insertions(+), 231 deletions(-) (limited to 'arch') diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 01a62161b08a..192b00f098f4 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -858,6 +858,24 @@ static struct platform_device *atari_netusbee_devices[] __initdata = { }; #endif /* CONFIG_ATARI_ETHERNEC */ +#ifdef CONFIG_ATARI_SCSI +static const struct resource atari_scsi_st_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_MFP_FSCSI, + .end = IRQ_MFP_FSCSI, + }, +}; + +static const struct resource atari_scsi_tt_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = IRQ_TT_MFP_SCSI, + .end = IRQ_TT_MFP_SCSI, + }, +}; +#endif + int __init atari_platform_init(void) { int rv = 0; @@ -892,6 +910,15 @@ int __init atari_platform_init(void) } #endif +#ifdef CONFIG_ATARI_SCSI + if (ATARIHW_PRESENT(ST_SCSI)) + platform_device_register_simple("atari_scsi", -1, + atari_scsi_st_rsrc, ARRAY_SIZE(atari_scsi_st_rsrc)); + else if (ATARIHW_PRESENT(TT_SCSI)) + platform_device_register_simple("atari_scsi", -1, + atari_scsi_tt_rsrc, ARRAY_SIZE(atari_scsi_tt_rsrc)); +#endif + return rv; } diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index b2e86d0630ce..b765e1c2277f 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -74,33 +74,26 @@ #define MAX_TAGS 32 #include -#include -#include #include -#include #include #include #include #include #include #include +#include #include #include #include -#include -#include -#include -#include - -#include -#include "atari_scsi.h" -#include "NCR5380.h" #include #include #include -#include +#include + +#include "atari_scsi.h" +#include "NCR5380.h" #define IS_A_TT() ATARIHW_PRESENT(TT_SCSI) @@ -176,25 +169,9 @@ static inline void DISABLE_IRQ(void) #define AFTER_RESET_DELAY (5*HZ/2) #endif -/***************************** Prototypes *****************************/ - #ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void); #endif -static irqreturn_t scsi_tt_intr(int irq, void *dummy); -static irqreturn_t scsi_falcon_intr(int irq, void *dummy); -static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata); -static int falcon_get_lock(void); -#ifdef CONFIG_ATARI_SCSI_RESET_BOOT -static void atari_scsi_reset_boot(void); -#endif -static unsigned char atari_scsi_tt_reg_read(unsigned char reg); -static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value); -static unsigned char atari_scsi_falcon_reg_read(unsigned char reg); -static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value); - -/************************* End of Prototypes **************************/ - static struct Scsi_Host *atari_scsi_host; static unsigned char (*atari_scsi_reg_read)(unsigned char reg); @@ -517,160 +494,12 @@ static int falcon_get_lock(void) return 1; } - -static int __init atari_scsi_detect(struct scsi_host_template *host) -{ - static int called = 0; - struct Scsi_Host *instance; - - if (!MACH_IS_ATARI || - (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) || - called) - return 0; - - host->proc_name = "Atari"; - - atari_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read : - atari_scsi_falcon_reg_read; - atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write : - atari_scsi_falcon_reg_write; - - /* setup variables */ - host->can_queue = - (setup_can_queue > 0) ? setup_can_queue : - IS_A_TT() ? ATARI_TT_CAN_QUEUE : ATARI_FALCON_CAN_QUEUE; - host->cmd_per_lun = - (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : - IS_A_TT() ? ATARI_TT_CMD_PER_LUN : ATARI_FALCON_CMD_PER_LUN; - /* Force sg_tablesize to 0 on a Falcon! */ - host->sg_tablesize = - !IS_A_TT() ? ATARI_FALCON_SG_TABLESIZE : - (setup_sg_tablesize >= 0) ? setup_sg_tablesize : ATARI_TT_SG_TABLESIZE; - - if (setup_hostid >= 0) - host->this_id = setup_hostid; - else { - /* use 7 as default */ - host->this_id = 7; - /* Test if a host id is set in the NVRam */ - if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) { - unsigned char b = nvram_read_byte( 14 ); - /* Arbitration enabled? (for TOS) If yes, use configured host ID */ - if (b & 0x80) - host->this_id = b & 7; - } - } - -#ifdef SUPPORT_TAGS - if (setup_use_tagged_queuing < 0) - setup_use_tagged_queuing = 0; -#endif -#ifdef REAL_DMA - /* If running on a Falcon and if there's TT-Ram (i.e., more than one - * memory block, since there's always ST-Ram in a Falcon), then allocate a - * STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative - * Ram. - */ - if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) && - !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) { - atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); - if (!atari_dma_buffer) { - printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM " - "double buffer\n"); - return 0; - } - atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); - atari_dma_orig_addr = 0; - } -#endif - instance = scsi_register(host, sizeof(struct NCR5380_hostdata)); - if (instance == NULL) { - atari_stram_free(atari_dma_buffer); - atari_dma_buffer = 0; - return 0; - } - atari_scsi_host = instance; - /* - * Set irq to 0, to avoid that the mid-level code disables our interrupt - * during queue_command calls. This is completely unnecessary, and even - * worse causes bad problems on the Falcon, where the int is shared with - * IDE and floppy! - */ - instance->irq = 0; - -#ifdef CONFIG_ATARI_SCSI_RESET_BOOT - atari_scsi_reset_boot(); -#endif - NCR5380_init(instance, 0); - - if (IS_A_TT()) { - - /* This int is actually "pseudo-slow", i.e. it acts like a slow - * interrupt after having cleared the pending flag for the DMA - * interrupt. */ - if (request_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW, - "SCSI NCR5380", instance)) { - printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting",IRQ_TT_MFP_SCSI); - scsi_unregister(atari_scsi_host); - atari_stram_free(atari_dma_buffer); - atari_dma_buffer = 0; - return 0; - } - tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ -#ifdef REAL_DMA - tt_scsi_dma.dma_ctrl = 0; - atari_dma_residual = 0; - - if (MACH_IS_MEDUSA) { - /* While the read overruns (described by Drew Eckhardt in - * NCR5380.c) never happened on TTs, they do in fact on the Medusa - * (This was the cause why SCSI didn't work right for so long - * there.) Since handling the overruns slows down a bit, I turned - * the #ifdef's into a runtime condition. - * - * In principle it should be sufficient to do max. 1 byte with - * PIO, but there is another problem on the Medusa with the DMA - * rest data register. So 'atari_read_overruns' is currently set - * to 4 to avoid having transfers that aren't a multiple of 4. If - * the rest data bug is fixed, this can be lowered to 1. - */ - atari_read_overruns = 4; - } -#endif /*REAL_DMA*/ - } else { /* ! IS_A_TT */ - - /* Nothing to do for the interrupt: the ST-DMA is initialized - * already by atari_init_INTS() - */ - -#ifdef REAL_DMA - atari_dma_residual = 0; - atari_dma_active = 0; - atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 - : 0xff000000); -#endif - } - - called = 1; - return 1; -} - -static int atari_scsi_release(struct Scsi_Host *sh) -{ - if (IS_A_TT()) - free_irq(IRQ_TT_MFP_SCSI, sh); - if (atari_dma_buffer) - atari_stram_free(atari_dma_buffer); - NCR5380_exit(sh); - return 1; -} - #ifndef MODULE static int __init atari_scsi_setup(char *str) { /* Format of atascsi parameter is: * atascsi=,,,, - * Defaults depend on TT or Falcon, hostid determined at run time. + * Defaults depend on TT or Falcon, determined at run time. * Negative values mean don't change. */ int ints[6]; @@ -681,36 +510,17 @@ static int __init atari_scsi_setup(char *str) printk("atari_scsi_setup: no arguments!\n"); return 0; } - - if (ints[0] >= 1) { - if (ints[1] > 0) - /* no limits on this, just > 0 */ - setup_can_queue = ints[1]; - } - if (ints[0] >= 2) { - if (ints[2] > 0) - setup_cmd_per_lun = ints[2]; - } - if (ints[0] >= 3) { - if (ints[3] >= 0) { - setup_sg_tablesize = ints[3]; - /* Must be <= SG_ALL (255) */ - if (setup_sg_tablesize > SG_ALL) - setup_sg_tablesize = SG_ALL; - } - } - if (ints[0] >= 4) { - /* Must be between 0 and 7 */ - if (ints[4] >= 0 && ints[4] <= 7) - setup_hostid = ints[4]; - else if (ints[4] > 7) - printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]); - } + if (ints[0] >= 1) + setup_can_queue = ints[1]; + if (ints[0] >= 2) + setup_cmd_per_lun = ints[2]; + if (ints[0] >= 3) + setup_sg_tablesize = ints[3]; + if (ints[0] >= 4) + setup_hostid = ints[4]; #ifdef SUPPORT_TAGS - if (ints[0] >= 5) { - if (ints[5] >= 0) - setup_use_tagged_queuing = !!ints[5]; - } + if (ints[0] >= 5) + setup_use_tagged_queuing = ints[5]; #endif return 1; @@ -1019,23 +829,209 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) return rv; } -static struct scsi_host_template driver_template = { +#define DRV_MODULE_NAME "atari_scsi" +#define PFX DRV_MODULE_NAME ": " + +static struct scsi_host_template atari_scsi_template = { + .module = THIS_MODULE, + .proc_name = DRV_MODULE_NAME, .show_info = atari_scsi_show_info, .name = "Atari native SCSI", - .detect = atari_scsi_detect, - .release = atari_scsi_release, .info = atari_scsi_info, .queuecommand = atari_scsi_queue_command, .eh_abort_handler = atari_scsi_abort, .eh_bus_reset_handler = atari_scsi_bus_reset, - .can_queue = 0, /* initialized at run-time */ - .this_id = 0, /* initialized at run-time */ - .sg_tablesize = 0, /* initialized at run-time */ - .cmd_per_lun = 0, /* initialized at run-time */ + .this_id = 7, .use_clustering = DISABLE_CLUSTERING }; +static int __init atari_scsi_probe(struct platform_device *pdev) +{ + struct Scsi_Host *instance; + int error; + struct resource *irq; + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) + return -ENODEV; + + if (ATARIHW_PRESENT(TT_SCSI)) { + atari_scsi_reg_read = atari_scsi_tt_reg_read; + atari_scsi_reg_write = atari_scsi_tt_reg_write; + } else { + atari_scsi_reg_read = atari_scsi_falcon_reg_read; + atari_scsi_reg_write = atari_scsi_falcon_reg_write; + } + + /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. + * Higher values should work, too; try it! + * (But cmd_per_lun costs memory!) + * + * But there seems to be a bug somewhere that requires CAN_QUEUE to be + * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since + * changed CMD_PER_LUN... + * + * Note: The Falcon currently uses 8/1 setting due to unsolved problems + * with cmd_per_lun != 1 + */ + if (ATARIHW_PRESENT(TT_SCSI)) { + atari_scsi_template.can_queue = 16; + atari_scsi_template.cmd_per_lun = 8; + atari_scsi_template.sg_tablesize = SG_ALL; + } else { + atari_scsi_template.can_queue = 8; + atari_scsi_template.cmd_per_lun = 1; + atari_scsi_template.sg_tablesize = SG_NONE; + } + + if (setup_can_queue > 0) + atari_scsi_template.can_queue = setup_can_queue; + + if (setup_cmd_per_lun > 0) + atari_scsi_template.cmd_per_lun = setup_cmd_per_lun; + + /* Leave sg_tablesize at 0 on a Falcon! */ + if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0) + atari_scsi_template.sg_tablesize = setup_sg_tablesize; + + if (setup_hostid >= 0) { + atari_scsi_template.this_id = setup_hostid & 7; + } else { + /* Test if a host id is set in the NVRam */ + if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) { + unsigned char b = nvram_read_byte(14); + + /* Arbitration enabled? (for TOS) + * If yes, use configured host ID + */ + if (b & 0x80) + atari_scsi_template.this_id = b & 7; + } + } + +#ifdef SUPPORT_TAGS + if (setup_use_tagged_queuing < 0) + setup_use_tagged_queuing = 0; +#endif + +#ifdef REAL_DMA + /* If running on a Falcon and if there's TT-Ram (i.e., more than one + * memory block, since there's always ST-Ram in a Falcon), then + * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers + * from/to alternative Ram. + */ + if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) && + m68k_num_memory > 1) { + atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); + if (!atari_dma_buffer) { + pr_err(PFX "can't allocate ST-RAM double buffer\n"); + return -ENOMEM; + } + atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); + atari_dma_orig_addr = 0; + } +#endif + + instance = scsi_host_alloc(&atari_scsi_template, + sizeof(struct NCR5380_hostdata)); + if (!instance) { + error = -ENOMEM; + goto fail_alloc; + } + atari_scsi_host = instance; + +#ifdef CONFIG_ATARI_SCSI_RESET_BOOT + atari_scsi_reset_boot(); +#endif + + instance->irq = irq->start; + + NCR5380_init(instance, 0); + + if (IS_A_TT()) { + error = request_irq(instance->irq, scsi_tt_intr, 0, + "NCR5380", instance); + if (error) { + pr_err(PFX "request irq %d failed, aborting\n", + instance->irq); + goto fail_irq; + } + tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ +#ifdef REAL_DMA + tt_scsi_dma.dma_ctrl = 0; + atari_dma_residual = 0; + + /* While the read overruns (described by Drew Eckhardt in + * NCR5380.c) never happened on TTs, they do in fact on the + * Medusa (This was the cause why SCSI didn't work right for + * so long there.) Since handling the overruns slows down + * a bit, I turned the #ifdef's into a runtime condition. + * + * In principle it should be sufficient to do max. 1 byte with + * PIO, but there is another problem on the Medusa with the DMA + * rest data register. So 'atari_read_overruns' is currently set + * to 4 to avoid having transfers that aren't a multiple of 4. + * If the rest data bug is fixed, this can be lowered to 1. + */ + if (MACH_IS_MEDUSA) + atari_read_overruns = 4; +#endif + } else { + /* Nothing to do for the interrupt: the ST-DMA is initialized + * already. + */ +#ifdef REAL_DMA + atari_dma_residual = 0; + atari_dma_active = 0; + atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 + : 0xff000000); +#endif + } + + error = scsi_add_host(instance, NULL); + if (error) + goto fail_host; + + platform_set_drvdata(pdev, instance); + + scsi_scan_host(instance); + return 0; + +fail_host: + if (IS_A_TT()) + free_irq(instance->irq, instance); +fail_irq: + NCR5380_exit(instance); + scsi_host_put(instance); +fail_alloc: + if (atari_dma_buffer) + atari_stram_free(atari_dma_buffer); + return error; +} + +static int __exit atari_scsi_remove(struct platform_device *pdev) +{ + struct Scsi_Host *instance = platform_get_drvdata(pdev); + + scsi_remove_host(instance); + if (IS_A_TT()) + free_irq(instance->irq, instance); + NCR5380_exit(instance); + scsi_host_put(instance); + if (atari_dma_buffer) + atari_stram_free(atari_dma_buffer); + return 0; +} + +static struct platform_driver atari_scsi_driver = { + .remove = __exit_p(atari_scsi_remove), + .driver = { + .name = DRV_MODULE_NAME, + .owner = THIS_MODULE, + }, +}; -#include "scsi_module.c" +module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe); +MODULE_ALIAS("platform:" DRV_MODULE_NAME); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h index 41b7cd7d36b8..ff329f9f1b98 100644 --- a/drivers/scsi/atari_scsi.h +++ b/drivers/scsi/atari_scsi.h @@ -18,23 +18,6 @@ /* (I_HAVE_OVERRUNS stuff removed) */ #ifndef ASM -/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher - * values should work, too; try it! (but cmd_per_lun costs memory!) */ - -/* But there seems to be a bug somewhere that requires CAN_QUEUE to be - * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since - * changed CMD_PER_LUN... */ - -/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with - * cmd_per_lun != 1 */ - -#define ATARI_TT_CAN_QUEUE 16 -#define ATARI_TT_CMD_PER_LUN 8 -#define ATARI_TT_SG_TABLESIZE SG_ALL - -#define ATARI_FALCON_CAN_QUEUE 8 -#define ATARI_FALCON_CMD_PER_LUN 1 -#define ATARI_FALCON_SG_TABLESIZE SG_NONE #define NCR5380_implementation_fields /* none */ -- cgit v1.2.3 From 0d31f8759109cbc1e6fc196d08e6b0e8a9e93b3f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Thu, 13 Nov 2014 12:21:28 +1100 Subject: sun3_scsi: Convert to platform device Convert sun3_scsi to platform device and eliminate scsi_register(). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Acked-by: Geert Uytterhoeven Signed-off-by: Christoph Hellwig --- arch/m68k/sun3/config.c | 60 ++++++++ drivers/scsi/sun3_scsi.c | 390 ++++++++++++++++++++++------------------------- drivers/scsi/sun3_scsi.h | 17 --- 3 files changed, 245 insertions(+), 222 deletions(-) (limited to 'arch') diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c index f59ec58083f8..a8b942bf7163 100644 --- a/arch/m68k/sun3/config.c +++ b/arch/m68k/sun3/config.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -169,3 +171,61 @@ static void __init sun3_sched_init(irq_handler_t timer_routine) intersil_clear(); } +#ifdef CONFIG_SUN3_SCSI + +static const struct resource sun3_scsi_vme_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = SUN3_VEC_VMESCSI0, + .end = SUN3_VEC_VMESCSI0, + }, { + .flags = IORESOURCE_MEM, + .start = 0xff200000, + .end = 0xff200021, + }, { + .flags = IORESOURCE_IRQ, + .start = SUN3_VEC_VMESCSI1, + .end = SUN3_VEC_VMESCSI1, + }, { + .flags = IORESOURCE_MEM, + .start = 0xff204000, + .end = 0xff204021, + }, +}; + +/* + * Int: level 2 autovector + * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0> + */ +static const struct resource sun3_scsi_rsrc[] __initconst = { + { + .flags = IORESOURCE_IRQ, + .start = 2, + .end = 2, + }, { + .flags = IORESOURCE_MEM, + .start = 0x00140000, + .end = 0x0014001f, + }, +}; + +int __init sun3_platform_init(void) +{ + switch (idprom->id_machtype) { + case SM_SUN3 | SM_3_160: + case SM_SUN3 | SM_3_260: + platform_device_register_simple("sun3_scsi_vme", -1, + sun3_scsi_vme_rsrc, ARRAY_SIZE(sun3_scsi_vme_rsrc)); + break; + case SM_SUN3 | SM_3_50: + case SM_SUN3 | SM_3_60: + platform_device_register_simple("sun3_scsi", -1, + sun3_scsi_rsrc, ARRAY_SIZE(sun3_scsi_rsrc)); + break; + } + return 0; +} + +arch_initcall(sun3_platform_init); + +#endif diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index bb660fe4739d..ba5169982706 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -23,22 +23,15 @@ */ #include -#include -#include #include - #include -#include #include #include #include +#include #include - -#include #include -#include -#include /* dma on! */ #define REAL_DMA @@ -59,8 +52,6 @@ extern int sun3_map_test(unsigned long, char *); #endif -static irqreturn_t scsi_sun3_intr(int irq, void *dummy); - static int setup_can_queue = -1; module_param(setup_can_queue, int, 0); static int setup_cmd_per_lun = -1; @@ -89,15 +80,14 @@ static struct scsi_cmnd *sun3_dma_setup_done = NULL; /* minimum number of bytes to do dma on */ #define SUN3_DMA_MINSIZE 128 -static volatile unsigned char *sun3_scsi_regp; +static unsigned char *sun3_scsi_regp; static volatile struct sun3_dma_regs *dregs; -#ifndef SUN3_SCSI_VME -static struct sun3_udc_regs *udc_regs = NULL; -#endif +static struct sun3_udc_regs *udc_regs; static unsigned char *sun3_dma_orig_addr = NULL; static unsigned long sun3_dma_orig_count = 0; static int sun3_dma_active = 0; static unsigned long last_residual = 0; +static struct Scsi_Host *default_instance; /* * NCR 5380 register access functions @@ -105,12 +95,12 @@ static unsigned long last_residual = 0; static inline unsigned char sun3scsi_read(int reg) { - return( sun3_scsi_regp[reg] ); + return in_8(sun3_scsi_regp + reg); } static inline void sun3scsi_write(int reg, int value) { - sun3_scsi_regp[reg] = value; + out_8(sun3_scsi_regp + reg, value); } #ifndef SUN3_SCSI_VME @@ -137,192 +127,7 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg) } #endif -/* - * XXX: status debug - */ -static struct Scsi_Host *default_instance; - -/* - * Function : int sun3scsi_detect(struct scsi_host_template * tpnt) - * - * Purpose : initializes mac NCR5380 driver based on the - * command line / compile time port and irq definitions. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -static int __init sun3scsi_detect(struct scsi_host_template *tpnt) -{ - unsigned long ioaddr, irq; - static int called = 0; - struct Scsi_Host *instance; -#ifdef SUN3_SCSI_VME - int i; - unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI, - IOBASE_SUN3_VMESCSI + 0x4000, - 0 }; - unsigned long vecs[3] = { SUN3_VEC_VMESCSI0, - SUN3_VEC_VMESCSI1, - 0 }; -#endif - - /* check that this machine has an onboard 5380 */ - switch(idprom->id_machtype) { -#ifdef SUN3_SCSI_VME - case SM_SUN3|SM_3_160: - case SM_SUN3|SM_3_260: - break; -#else - case SM_SUN3|SM_3_50: - case SM_SUN3|SM_3_60: - break; -#endif - - default: - return 0; - } - - if(called) - return 0; - -#ifdef SUN3_SCSI_VME - tpnt->proc_name = "Sun3 5380 VME SCSI"; -#else - tpnt->proc_name = "Sun3 5380 SCSI"; -#endif - - /* setup variables */ - if (setup_can_queue > 0) - tpnt->can_queue = setup_can_queue; - if (setup_cmd_per_lun > 0) - tpnt->cmd_per_lun = setup_cmd_per_lun; - if (setup_sg_tablesize >= 0) - tpnt->sg_tablesize = setup_sg_tablesize; - - if (setup_hostid >= 0) - tpnt->this_id = setup_hostid; - else { - /* use 7 as default */ - tpnt->this_id = 7; - } - -#ifdef SUN3_SCSI_VME - ioaddr = 0; - for (i = 0; addrs[i] != 0; i++) { - unsigned char x; - - ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE, - SUN3_PAGE_TYPE_VME16); - irq = vecs[i]; - sun3_scsi_regp = (unsigned char *)ioaddr; - - dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8); - - if (sun3_map_test((unsigned long)dregs, &x)) { - unsigned short oldcsr; - - oldcsr = dregs->csr; - dregs->csr = 0; - udelay(SUN3_DMA_DELAY); - if (dregs->csr == 0x1400) - break; - - dregs->csr = oldcsr; - } - - iounmap((void *)ioaddr); - ioaddr = 0; - } - - if (!ioaddr) - return 0; -#else - irq = IRQ_SUN3_SCSI; - ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE); - sun3_scsi_regp = (unsigned char *)ioaddr; - - dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8); - - if((udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs))) - == NULL) { - printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); - return 0; - } -#endif -#ifdef SUPPORT_TAGS - if (setup_use_tagged_queuing < 0) - setup_use_tagged_queuing = 1; -#endif - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if(instance == NULL) - return 0; - - default_instance = instance; - - instance->io_port = (unsigned long) ioaddr; - instance->irq = irq; - - NCR5380_init(instance, 0); - - instance->n_io_port = 32; - - if (request_irq(instance->irq, scsi_sun3_intr, - 0, "Sun3SCSI-5380", instance)) { -#ifndef REAL_DMA - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; -#else - printk("scsi%d: IRQ%d not free, bailing out\n", - instance->host_no, instance->irq); - return 0; -#endif - } - - dregs->csr = 0; - udelay(SUN3_DMA_DELAY); - dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; - udelay(SUN3_DMA_DELAY); - dregs->fifo_count = 0; -#ifdef SUN3_SCSI_VME - dregs->fifo_count_hi = 0; - dregs->dma_addr_hi = 0; - dregs->dma_addr_lo = 0; - dregs->dma_count_hi = 0; - dregs->dma_count_lo = 0; - - dregs->ivect = VME_DATA24 | (instance->irq & 0xff); -#endif - - called = 1; - -#ifdef RESET_BOOT - sun3_scsi_reset_boot(instance); -#endif - - return 1; -} - -static int sun3scsi_release(struct Scsi_Host *shpnt) -{ - if (shpnt->irq != NO_IRQ) - free_irq(shpnt->irq, shpnt); - - iounmap((void *)sun3_scsi_regp); - - NCR5380_exit(shpnt); - return 0; -} - #ifdef RESET_BOOT -/* - * Our 'bus reset on boot' function - */ - static void sun3_scsi_reset_boot(struct Scsi_Host *instance) { unsigned long end; @@ -671,11 +476,21 @@ static int sun3scsi_dma_finish(int write_flag) #include "sun3_NCR5380.c" -static struct scsi_host_template driver_template = { +#ifdef SUN3_SCSI_VME +#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" +#define DRV_MODULE_NAME "sun3_scsi_vme" +#else +#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI" +#define DRV_MODULE_NAME "sun3_scsi" +#endif + +#define PFX DRV_MODULE_NAME ": " + +static struct scsi_host_template sun3_scsi_template = { + .module = THIS_MODULE, + .proc_name = DRV_MODULE_NAME, .show_info = sun3scsi_show_info, .name = SUN3_SCSI_NAME, - .detect = sun3scsi_detect, - .release = sun3scsi_release, .info = sun3scsi_info, .queuecommand = sun3scsi_queue_command, .eh_abort_handler = sun3scsi_abort, @@ -687,7 +502,172 @@ static struct scsi_host_template driver_template = { .use_clustering = DISABLE_CLUSTERING }; +static int __init sun3_scsi_probe(struct platform_device *pdev) +{ + struct Scsi_Host *instance; + int error; + struct resource *irq, *mem; + unsigned char *ioaddr; +#ifdef SUN3_SCSI_VME + int i; +#endif + + if (setup_can_queue > 0) + sun3_scsi_template.can_queue = setup_can_queue; + if (setup_cmd_per_lun > 0) + sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun; + if (setup_sg_tablesize >= 0) + sun3_scsi_template.sg_tablesize = setup_sg_tablesize; + if (setup_hostid >= 0) + sun3_scsi_template.this_id = setup_hostid & 7; + +#ifdef SUPPORT_TAGS + if (setup_use_tagged_queuing < 0) + setup_use_tagged_queuing = 1; +#endif + +#ifdef SUN3_SCSI_VME + ioaddr = NULL; + for (i = 0; i < 2; i++) { + unsigned char x; + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, i); + mem = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!irq || !mem) + break; + + ioaddr = sun3_ioremap(mem->start, resource_size(mem), + SUN3_PAGE_TYPE_VME16); + dregs = (struct sun3_dma_regs *)(ioaddr + 8); + + if (sun3_map_test((unsigned long)dregs, &x)) { + unsigned short oldcsr; + + oldcsr = dregs->csr; + dregs->csr = 0; + udelay(SUN3_DMA_DELAY); + if (dregs->csr == 0x1400) + break; + + dregs->csr = oldcsr; + } + + iounmap(ioaddr); + ioaddr = NULL; + } + if (!ioaddr) + return -ENODEV; +#else + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!irq || !mem) + return -ENODEV; + + ioaddr = ioremap(mem->start, resource_size(mem)); + dregs = (struct sun3_dma_regs *)(ioaddr + 8); + + udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)); + if (!udc_regs) { + pr_err(PFX "couldn't allocate DVMA memory!\n"); + iounmap(ioaddr); + return -ENOMEM; + } +#endif + + sun3_scsi_regp = ioaddr; + + instance = scsi_host_alloc(&sun3_scsi_template, + sizeof(struct NCR5380_hostdata)); + if (!instance) { + error = -ENOMEM; + goto fail_alloc; + } + default_instance = instance; + + instance->io_port = (unsigned long)ioaddr; + instance->irq = irq->start; + + NCR5380_init(instance, 0); + + error = request_irq(instance->irq, scsi_sun3_intr, 0, + "NCR5380", instance); + if (error) { +#ifdef REAL_DMA + pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n", + instance->host_no, instance->irq); + goto fail_irq; +#else + pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n", + instance->host_no, instance->irq); + instance->irq = NO_IRQ; +#endif + } + + dregs->csr = 0; + udelay(SUN3_DMA_DELAY); + dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; + udelay(SUN3_DMA_DELAY); + dregs->fifo_count = 0; +#ifdef SUN3_SCSI_VME + dregs->fifo_count_hi = 0; + dregs->dma_addr_hi = 0; + dregs->dma_addr_lo = 0; + dregs->dma_count_hi = 0; + dregs->dma_count_lo = 0; + + dregs->ivect = VME_DATA24 | (instance->irq & 0xff); +#endif + +#ifdef RESET_BOOT + sun3_scsi_reset_boot(instance); +#endif + + error = scsi_add_host(instance, NULL); + if (error) + goto fail_host; + + platform_set_drvdata(pdev, instance); + + scsi_scan_host(instance); + return 0; + +fail_host: + if (instance->irq != NO_IRQ) + free_irq(instance->irq, instance); +fail_irq: + NCR5380_exit(instance); + scsi_host_put(instance); +fail_alloc: + if (udc_regs) + dvma_free(udc_regs); + iounmap(sun3_scsi_regp); + return error; +} + +static int __exit sun3_scsi_remove(struct platform_device *pdev) +{ + struct Scsi_Host *instance = platform_get_drvdata(pdev); + + scsi_remove_host(instance); + if (instance->irq != NO_IRQ) + free_irq(instance->irq, instance); + NCR5380_exit(instance); + scsi_host_put(instance); + if (udc_regs) + dvma_free(udc_regs); + iounmap(sun3_scsi_regp); + return 0; +} + +static struct platform_driver sun3_scsi_driver = { + .remove = __exit_p(sun3_scsi_remove), + .driver = { + .name = DRV_MODULE_NAME, + .owner = THIS_MODULE, + }, +}; -#include "scsi_module.c" +module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe); +MODULE_ALIAS("platform:" DRV_MODULE_NAME); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h index f2f16378f9fa..653aab113a21 100644 --- a/drivers/scsi/sun3_scsi.h +++ b/drivers/scsi/sun3_scsi.h @@ -18,25 +18,8 @@ #ifndef SUN3_SCSI_H #define SUN3_SCSI_H -/* - * Int: level 2 autovector - * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0> - */ -#define IRQ_SUN3_SCSI 2 -#define IOBASE_SUN3_SCSI 0x00140000 - -#define IOBASE_SUN3_VMESCSI 0xff200000 - #define MAX_TAGS 32 -#include - -#ifdef SUN3_SCSI_VME -#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" -#else -#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI" -#endif - #define NCR5380_implementation_fields /* none */ #define NCR5380_local_declare() \ -- cgit v1.2.3