static int __init a2091_detect(struct scsi_host_template *tpnt) { static unsigned char called = 0; struct Scsi_Host *instance; unsigned long address; struct zorro_dev *z = NULL; wd33c93_regs regs; int num_a2091 = 0; if (!MACH_IS_AMIGA || called) return 0; called = 1; tpnt->proc_name = "A2091"; tpnt->proc_info = &wd33c93_proc_info; while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { if (z->id != ZORRO_PROD_CBM_A590_A2091_1 && z->id != ZORRO_PROD_CBM_A590_A2091_2) continue; address = z->resource.start; if (!request_mem_region(address, 256, "wd33c93")) continue; instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata)); if (instance == NULL) goto release; instance->base = ZTWO_VADDR(address); instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; DMA(instance)->DAWR = DAWR_A2091; regs.SASR = &(DMA(instance)->SASR); regs.SCMD = &(DMA(instance)->SCMD); HDATA(instance)->no_sync = 0xff; HDATA(instance)->fast = 0; HDATA(instance)->dma_mode = CTRL_DMA; wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10); if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI", instance)) goto unregister; DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; num_a2091++; continue; unregister: scsi_unregister(instance); wd33c93_release(); release: release_mem_region(address, 256); } return num_a2091; }
int mvme147_detect(struct scsi_host_template *tpnt) { static unsigned char called = 0; wd33c93_regs regs; if (!MACH_IS_MVME147 || called) return 0; called++; tpnt->proc_name = "MVME147"; tpnt->proc_info = &wd33c93_proc_info; mvme147_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); if (!mvme147_host) goto err_out; mvme147_host->base = 0xfffe4000; mvme147_host->irq = MVME147_IRQ_SCSI_PORT; regs.SASR = (volatile unsigned char *)0xfffe4000; regs.SCMD = (volatile unsigned char *)0xfffe4001; HDATA(mvme147_host)->no_sync = 0xff; HDATA(mvme147_host)->fast = 0; HDATA(mvme147_host)->dma_mode = CTRL_DMA; wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10); if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr)) goto err_unregister; if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, "MVME147 SCSI DMA", mvme147_intr)) goto err_free_irq; #if 0 /* Disabled; causes problems booting */ m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ udelay(100); m147_pcc->scsi_interrupt = 0x00; /* Negate SCSI bus reset */ udelay(2000); m147_pcc->scsi_interrupt = 0x40; /* Clear bus reset interrupt */ #endif m147_pcc->scsi_interrupt = 0x09; /* Enable interrupt */ m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */ m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ return 1; err_free_irq: free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); err_unregister: wd33c93_release(); scsi_unregister(mvme147_host); err_out: return 0; }
static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); /* * if the physical address has the wrong alignment, or if * physical address is bad, or if it is a write and at the * end of a physical memory chunk, then allocate a bounce * buffer */ if (addr & A3000_XFER_MASK) { HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; HDATA(a3000_host)->dma_bounce_buffer = kmalloc (HDATA(a3000_host)->dma_bounce_len, GFP_KERNEL); /* can't allocate memory; use PIO */ if (!HDATA(a3000_host)->dma_bounce_buffer) { HDATA(a3000_host)->dma_bounce_len = 0; return 1; } if (!dir_in) { /* copy to bounce buffer for a write */ memcpy (HDATA(a3000_host)->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } addr = virt_to_bus(HDATA(a3000_host)->dma_bounce_buffer); } /* setup dma direction */ if (!dir_in) cntr |= CNTR_DDIR; /* remember direction */ HDATA(a3000_host)->dma_dir = dir_in; DMA(a3000_host)->CNTR = cntr; /* setup DMA *physical* address */ DMA(a3000_host)->ACR = addr; if (dir_in) /* invalidate any cache */ cache_clear (addr, cmd->SCp.this_residual); else /* push any dirty cache */ cache_push (addr, cmd->SCp.this_residual); /* start DMA */ mb(); /* make sure setup is completed */ DMA(a3000_host)->ST_DMA = 1; mb(); /* make sure DMA has started before next IO */ /* return success */ return 0; }
static int dma_setup (Scsi_Cmnd *cmd, int dir_in) { unsigned char flags = 0x01; unsigned long addr = virt_to_bus(cmd->SCp.ptr); /* setup dma direction */ if (!dir_in) flags |= 0x04; /* remember direction */ HDATA(mvme147_host)->dma_dir = dir_in; if (dir_in) /* invalidate any cache */ cache_clear (addr, cmd->SCp.this_residual); else /* push any dirty cache */ cache_push (addr, cmd->SCp.this_residual); /* start DMA */ m147_pcc->dma_bcr = cmd->SCp.this_residual | (1<<24); m147_pcc->dma_dadr = addr; m147_pcc->dma_cntrl = flags; /* return success */ return 0; }
int __init a3000_detect(struct scsi_host_template *tpnt) { wd33c93_regs regs; if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) return 0; if (!request_mem_region(0xDD0000, 256, "wd33c93")) return 0; tpnt->proc_name = "A3000"; tpnt->proc_info = &wd33c93_proc_info; a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); if (a3000_host == NULL) goto fail_register; a3000_host->base = ZTWO_VADDR(0xDD0000); a3000_host->irq = IRQ_AMIGA_PORTS; DMA(a3000_host)->DAWR = DAWR_A3000; regs.SASR = &(DMA(a3000_host)->SASR); regs.SCMD = &(DMA(a3000_host)->SCMD); HDATA(a3000_host)->no_sync = 0xff; HDATA(a3000_host)->fast = 0; HDATA(a3000_host)->dma_mode = CTRL_DMA; wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15); if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", a3000_intr)) goto fail_irq; DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN; return 1; fail_irq: wd33c93_release(); scsi_unregister(a3000_host); fail_register: release_mem_region(0xDD0000, 256); return 0; }
static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; if (!HDATA(instance)->dma_dir) cntr |= CNTR_DDIR; /* disable SCSI interrupts */ DMA(instance)->CNTR = cntr; /* flush if we were reading */ if (HDATA(instance)->dma_dir) { DMA(instance)->FLUSH = 1; while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) ; } /* clear a possible interrupt */ DMA(instance)->CINT = 1; /* stop DMA */ DMA(instance)->SP_DMA = 1; /* restore the CONTROL bits (minus the direction flag) */ DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; /* copy from a bounce buffer, if necessary */ if (status && HDATA(instance)->dma_bounce_buffer) { if( HDATA(instance)->dma_dir ) memcpy (SCpnt->SCp.ptr, HDATA(instance)->dma_bounce_buffer, SCpnt->SCp.this_residual); kfree (HDATA(instance)->dma_bounce_buffer); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; } }
static int dma_setup (Scsi_Cmnd *cmd, int dir_in) { unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = VTOP(cmd->SCp.ptr); /* * if the physical address has the wrong alignment, or if * physical address is bad, or if it is a write and at the * end of a physical memory chunk, then allocate a bounce * buffer */ if (addr & A3000_XFER_MASK || (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) { HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; HDATA(a3000_host)->dma_bounce_buffer = scsi_malloc (HDATA(a3000_host)->dma_bounce_len); /* can't allocate memory; use PIO */ if (!HDATA(a3000_host)->dma_bounce_buffer) { HDATA(a3000_host)->dma_bounce_len = 0; return 1; } if (!dir_in) { /* copy to bounce buffer for a write */ if (cmd->use_sg) { memcpy (HDATA(a3000_host)->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } else memcpy (HDATA(a3000_host)->dma_bounce_buffer, cmd->request_buffer, cmd->request_bufflen); } addr = VTOP(HDATA(a3000_host)->dma_bounce_buffer); } /* setup dma direction */ if (!dir_in) cntr |= CNTR_DDIR; /* remember direction */ HDATA(a3000_host)->dma_dir = dir_in; DMA(a3000_host)->CNTR = cntr; /* setup DMA *physical* address */ DMA(a3000_host)->ACR = addr; if (dir_in) /* invalidate any cache */ cache_clear (addr, cmd->SCp.this_residual); else /* push any dirty cache */ cache_push (addr, cmd->SCp.this_residual); /* start DMA */ DMA(a3000_host)->ST_DMA = 1; /* return success */ return 0; }
static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, int status) { /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; if (!HDATA(instance)->dma_dir) cntr |= CNTR_DDIR; DMA(instance)->CNTR = cntr; /* flush if we were reading */ if (HDATA(instance)->dma_dir) { DMA(instance)->FLUSH = 1; while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) ; } /* clear a possible interrupt */ /* I think that this CINT is only necessary if you are * using the terminal count features. HM 7 Mar 1994 */ DMA(instance)->CINT = 1; /* stop DMA */ DMA(instance)->SP_DMA = 1; /* restore the CONTROL bits (minus the direction flag) */ DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; /* copy from a bounce buffer, if necessary */ if (status && HDATA(instance)->dma_bounce_buffer) { if (SCpnt && SCpnt->use_sg) { if (HDATA(instance)->dma_dir && SCpnt) memcpy (SCpnt->SCp.ptr, HDATA(instance)->dma_bounce_buffer, SCpnt->SCp.this_residual); scsi_free (HDATA(instance)->dma_bounce_buffer, HDATA(instance)->dma_bounce_len); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; } else { if (HDATA(instance)->dma_dir && SCpnt) memcpy (SCpnt->request_buffer, HDATA(instance)->dma_bounce_buffer, SCpnt->request_bufflen); scsi_free (HDATA(instance)->dma_bounce_buffer, HDATA(instance)->dma_bounce_len); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; } } }
static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); struct Scsi_Host *instance = cmd->device->host; /* don't allow DMA if the physical address is bad */ if (addr & A2091_XFER_MASK) { HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; HDATA(instance)->dma_bounce_buffer = kmalloc (HDATA(instance)->dma_bounce_len, GFP_KERNEL); /* can't allocate memory; use PIO */ if (!HDATA(instance)->dma_bounce_buffer) { HDATA(instance)->dma_bounce_len = 0; return 1; } /* get the physical address of the bounce buffer */ addr = virt_to_bus(HDATA(instance)->dma_bounce_buffer); /* the bounce buffer may not be in the first 16M of physmem */ if (addr & A2091_XFER_MASK) { /* we could use chipmem... maybe later */ kfree (HDATA(instance)->dma_bounce_buffer); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; return 1; } if (!dir_in) { /* copy to bounce buffer for a write */ memcpy (HDATA(instance)->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } } /* setup dma direction */ if (!dir_in) cntr |= CNTR_DDIR; /* remember direction */ HDATA(cmd->device->host)->dma_dir = dir_in; DMA(cmd->device->host)->CNTR = cntr; /* setup DMA *physical* address */ DMA(cmd->device->host)->ACR = addr; if (dir_in){ /* invalidate any cache */ cache_clear (addr, cmd->SCp.this_residual); }else{ /* push any dirty cache */ cache_push (addr, cmd->SCp.this_residual); } /* start DMA */ DMA(cmd->device->host)->ST_DMA = 1; /* return success */ return 0; }
static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; if (!HDATA(instance)->dma_dir) cntr |= CNTR_DDIR; DMA(instance)->CNTR = cntr; mb(); /* make sure CNTR is updated before next IO */ /* flush if we were reading */ if (HDATA(instance)->dma_dir) { DMA(instance)->FLUSH = 1; mb(); /* don't allow prefetch */ while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) barrier(); mb(); /* no IO until FLUSH is done */ } /* clear a possible interrupt */ /* I think that this CINT is only necessary if you are * using the terminal count features. HM 7 Mar 1994 */ DMA(instance)->CINT = 1; /* stop DMA */ DMA(instance)->SP_DMA = 1; mb(); /* make sure DMA is stopped before next IO */ /* restore the CONTROL bits (minus the direction flag) */ DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; mb(); /* make sure CNTR is updated before next IO */ /* copy from a bounce buffer, if necessary */ if (status && HDATA(instance)->dma_bounce_buffer) { if (SCpnt) { if (HDATA(instance)->dma_dir && SCpnt) memcpy (SCpnt->SCp.ptr, HDATA(instance)->dma_bounce_buffer, SCpnt->SCp.this_residual); kfree (HDATA(instance)->dma_bounce_buffer); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; } else { kfree (HDATA(instance)->dma_bounce_buffer); HDATA(instance)->dma_bounce_buffer = NULL; HDATA(instance)->dma_bounce_len = 0; } } }