11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/page.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mvme147hw.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi.h" 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "wd33c93.h" 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mvme147.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven#include <linux/stat.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 194616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoevenstatic irqreturn_t mvme147_intr(int irq, void *data) 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 214616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven struct Scsi_Host *instance = data; 224616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven 23be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (irq == MVME147_IRQ_SCSI_PORT) 244616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven wd33c93_intr(instance); 25be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven else 26be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ 27be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return IRQ_HANDLED; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3065396410af63db90d6428c678ff84aa652c3c1ecHenrik Kretzschmarstatic int dma_setup(struct scsi_cmnd *cmd, int dir_in) 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 324616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven struct Scsi_Host *instance = cmd->device->host; 334616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven struct WD33C93_hostdata *hdata = shost_priv(instance); 34be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven unsigned char flags = 0x01; 35be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven unsigned long addr = virt_to_bus(cmd->SCp.ptr); 36be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 37be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* setup dma direction */ 38be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (!dir_in) 39be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven flags |= 0x04; 40be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 41be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* remember direction */ 42ce195662bbc063c29294c11a57aa2db182a837eaGeert Uytterhoeven hdata->dma_dir = dir_in; 43be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 44be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (dir_in) { 45be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* invalidate any cache */ 46be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven cache_clear(addr, cmd->SCp.this_residual); 47be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven } else { 48be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* push any dirty cache */ 49be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven cache_push(addr, cmd->SCp.this_residual); 50be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven } 51be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 52be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* start DMA */ 53be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_bcr = cmd->SCp.this_residual | (1 << 24); 54be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_dadr = addr; 55be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_cntrl = flags; 56be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 57be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* return success */ 58be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return 0; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6165396410af63db90d6428c678ff84aa652c3c1ecHenrik Kretzschmarstatic void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, 62be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven int status) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 64be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_cntrl = 0; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67d0be4a7d29ad0bd3ce2209dd9e46d410b632db59Christoph Hellwigint mvme147_detect(struct scsi_host_template *tpnt) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 69be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven static unsigned char called = 0; 704616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven struct Scsi_Host *instance; 71be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven wd33c93_regs regs; 72ce195662bbc063c29294c11a57aa2db182a837eaGeert Uytterhoeven struct WD33C93_hostdata *hdata; 73be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 74be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (!MACH_IS_MVME147 || called) 75be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return 0; 76be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven called++; 77be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 78be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven tpnt->proc_name = "MVME147"; 79be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven tpnt->proc_info = &wd33c93_proc_info; 80be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 814616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); 824616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven if (!instance) 83be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven goto err_out; 84be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 854616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven instance->base = 0xfffe4000; 864616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven instance->irq = MVME147_IRQ_SCSI_PORT; 87be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven regs.SASR = (volatile unsigned char *)0xfffe4000; 88be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven regs.SCMD = (volatile unsigned char *)0xfffe4001; 894616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven hdata = shost_priv(instance); 90ce195662bbc063c29294c11a57aa2db182a837eaGeert Uytterhoeven hdata->no_sync = 0xff; 91ce195662bbc063c29294c11a57aa2db182a837eaGeert Uytterhoeven hdata->fast = 0; 92ce195662bbc063c29294c11a57aa2db182a837eaGeert Uytterhoeven hdata->dma_mode = CTRL_DMA; 934616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10); 94be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven 95be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, 964616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven "MVME147 SCSI PORT", instance)) 97be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven goto err_unregister; 98be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, 994616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven "MVME147 SCSI DMA", instance)) 100be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven goto err_free_irq; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* Disabled; causes problems booting */ 102be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ 103be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven udelay(100); 104be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->scsi_interrupt = 0x00; /* Negate SCSI bus reset */ 105be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven udelay(2000); 106be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->scsi_interrupt = 0x40; /* Clear bus reset interrupt */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 108be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->scsi_interrupt = 0x09; /* Enable interrupt */ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 110be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */ 111be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return 1; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoevenerr_free_irq: 116be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); 117be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoevenerr_unregister: 1184616ac7e84c58660a11b991460cf2611552faa76Geert Uytterhoeven scsi_unregister(instance); 119be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoevenerr_out: 120be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return 0; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12365396410af63db90d6428c678ff84aa652c3c1ecHenrik Kretzschmarstatic int mvme147_bus_reset(struct scsi_cmnd *cmd) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME perform bus-specific reset */ 12668b3aa7c9805aee9005a8ca53c5e99177961fbb9Jeff Garzik 127be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* FIXME 2: kill this function, and let midlayer fallback to 128df0ae2497ddefd72a87f3a3b34ff32455d7d4ae0Jeff Garzik the same result, calling wd33c93_host_reset() */ 129df0ae2497ddefd72a87f3a3b34ff32455d7d4ae0Jeff Garzik 13068b3aa7c9805aee9005a8ca53c5e99177961fbb9Jeff Garzik spin_lock_irq(cmd->device->host->host_lock); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wd33c93_host_reset(cmd); 13268b3aa7c9805aee9005a8ca53c5e99177961fbb9Jeff Garzik spin_unlock_irq(cmd->device->host->host_lock); 13368b3aa7c9805aee9005a8ca53c5e99177961fbb9Jeff Garzik 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138d0be4a7d29ad0bd3ce2209dd9e46d410b632db59Christoph Hellwigstatic struct scsi_host_template driver_template = { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc_name = "MVME147", 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "MVME147 built-in SCSI", 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .detect = mvme147_detect, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = mvme147_release, 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .queuecommand = wd33c93_queuecommand, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_abort_handler = wd33c93_abort, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_bus_reset_handler = mvme147_bus_reset, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_host_reset_handler = wd33c93_host_reset, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .can_queue = CAN_QUEUE, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .this_id = 7, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sg_tablesize = SG_ALL, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmd_per_lun = CMD_PER_LUN, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .use_clustering = ENABLE_CLUSTERING 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi_module.c" 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mvme147_release(struct Scsi_Host *instance) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 160be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven /* XXX Make sure DMA is stopped! */ 161be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); 162be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 164be4540db062975ce557daf0119153fb17ecd6693Geert Uytterhoeven return 1; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 166