static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, u32 dma_count, int write, u8 cmd) { u32 csr; BUG_ON(!(cmd & ESP_CMD_DMA)); sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); if (esp->rev == FASHME) { sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO); sbus_esp_write8(esp, 0, FAS_RHI); scsi_esp_cmd(esp, cmd); csr = esp->prev_hme_dmacsr; csr |= DMA_SCSI_DISAB | DMA_ENABLE; if (write) csr |= DMA_ST_WRITE; else csr &= ~DMA_ST_WRITE; esp->prev_hme_dmacsr = csr; dma_write32(dma_count, DMA_COUNT); dma_write32(addr, DMA_ADDR); dma_write32(csr, DMA_CSR); } else {
static void sun3x_esp_reset_dma(struct esp *esp) { u32 val; val = dma_read32(DMA_CSR); dma_write32(val | DMA_RST_SCSI, DMA_CSR); dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); /* Enable interrupts. */ val = dma_read32(DMA_CSR); dma_write32(val | DMA_INT_ENAB, DMA_CSR); }
static void sbus_esp_dma_drain(struct esp *esp) { u32 csr; int lim; if (esp->dmarev == dvmahme) return; csr = dma_read32(DMA_CSR); if (!(csr & DMA_FIFO_ISDRAIN)) return; if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1) dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); lim = 1000; while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) { if (--lim == 0) { printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n", esp->host->unique_id); break; } udelay(1); } }
static void sun3x_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, u32 dma_count, int write, u8 cmd) { u32 csr; BUG_ON(!(cmd & ESP_CMD_DMA)); sun3x_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); sun3x_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); csr = dma_read32(DMA_CSR); csr |= DMA_ENABLE; if (write) csr |= DMA_ST_WRITE; else csr &= ~DMA_ST_WRITE; dma_write32(csr, DMA_CSR); dma_write32(addr, DMA_ADDR); scsi_esp_cmd(esp, cmd); }
static void sun3x_esp_dma_invalidate(struct esp *esp) { u32 val; int lim; lim = 1000; while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) { if (--lim == 0) { printk(KERN_ALERT PFX "esp%d: DMA will not " "invalidate!\n", esp->host->unique_id); break; } udelay(1); } val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB); val |= DMA_FIFO_INV; dma_write32(val, DMA_CSR); val &= ~DMA_FIFO_INV; dma_write32(val, DMA_CSR); }
static int __devexit esp_sun3x_remove(struct platform_device *dev) { struct esp *esp = dev_get_drvdata(&dev->dev); unsigned int irq = esp->host->irq; u32 val; scsi_esp_unregister(esp); /* Disable interrupts. */ val = dma_read32(DMA_CSR); dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); free_irq(irq, esp); dma_free_coherent(esp->dev, 16, esp->command_block, esp->command_block_dma); scsi_host_put(esp->host); return 0; }
static void sbus_esp_dma_invalidate(struct esp *esp) { if (esp->dmarev == dvmahme) { dma_write32(DMA_RST_SCSI, DMA_CSR); esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | (DMA_PARITY_OFF | DMA_2CLKS | DMA_SCSI_DISAB | DMA_INT_ENAB)) & ~(DMA_ST_WRITE | DMA_ENABLE)); dma_write32(0, DMA_CSR); dma_write32(esp->prev_hme_dmacsr, DMA_CSR); /* This is necessary to avoid having the SCSI channel * engine lock up on us. */ dma_write32(0, DMA_ADDR); } else { u32 val; int lim; lim = 1000; while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) { if (--lim == 0) { printk(KERN_ALERT PFX "esp%d: DMA will not " "invalidate!\n", esp->host->unique_id); break; } udelay(1); } val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB); val |= DMA_FIFO_INV; dma_write32(val, DMA_CSR); val &= ~DMA_FIFO_INV; dma_write32(val, DMA_CSR); } }
static void sbus_esp_reset_dma(struct esp *esp) { int can_do_burst16, can_do_burst32, can_do_burst64; int can_do_sbus64, lim; struct platform_device *op; u32 val; can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; can_do_burst64 = 0; can_do_sbus64 = 0; op = esp->dev; if (sbus_can_dma_64bit()) can_do_sbus64 = 1; if (sbus_can_burst64()) can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; /* Put the DVMA into a known state. */ if (esp->dmarev != dvmahme) { val = dma_read32(DMA_CSR); dma_write32(val | DMA_RST_SCSI, DMA_CSR); dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); } switch (esp->dmarev) { case dvmahme: dma_write32(DMA_RESET_FAS366, DMA_CSR); dma_write32(DMA_RST_SCSI, DMA_CSR); esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS | DMA_SCSI_DISAB | DMA_INT_ENAB); esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BRST_SZ); if (can_do_burst64) esp->prev_hme_dmacsr |= DMA_BRST64; else if (can_do_burst32) esp->prev_hme_dmacsr |= DMA_BRST32; if (can_do_sbus64) { esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; sbus_set_sbus64(&op->dev, esp->bursts); } lim = 1000; while (dma_read32(DMA_CSR) & DMA_PEND_READ) { if (--lim == 0) { printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ " "will not clear!\n", esp->host->unique_id); break; } udelay(1); } dma_write32(0, DMA_CSR); dma_write32(esp->prev_hme_dmacsr, DMA_CSR); dma_write32(0, DMA_ADDR); break; case dvmarev2: if (esp->rev != ESP100) { val = dma_read32(DMA_CSR); dma_write32(val | DMA_3CLKS, DMA_CSR); } break; case dvmarev3: val = dma_read32(DMA_CSR); val &= ~DMA_3CLKS; val |= DMA_2CLKS; if (can_do_burst32) { val &= ~DMA_BRST_SZ; val |= DMA_BRST32; } dma_write32(val, DMA_CSR); break; case dvmaesc1: val = dma_read32(DMA_CSR); val |= DMA_ADD_ENABLE; val &= ~DMA_BCNT_ENAB; if (!can_do_burst32 && can_do_burst16) { val |= DMA_ESC_BURST; } else { val &= ~(DMA_ESC_BURST); } dma_write32(val, DMA_CSR); break; default: break; } /* Enable interrupts. */ val = dma_read32(DMA_CSR); dma_write32(val | DMA_INT_ENAB, DMA_CSR); }