static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) { int sz = sp->SCp.buffers_residual; struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer; while (sz >= 0) { sg[sz].dvma_addr = dvma_map((unsigned long)sg[sz].addr, sg[sz].len); sz--; } sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address); }
static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) { int sz = sp->SCp.buffers_residual; struct scatterlist *sg = sp->SCp.buffer; while (sz >= 0) { sg[sz].dvma_address = dvma_map((unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); sz--; } sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address); }
/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) { #ifdef OLDDMA if(write_flag) memcpy(dmabuf, data, count); else { sun3_dma_orig_addr = data; sun3_dma_orig_count = count; } #else void *addr; if(sun3_dma_orig_addr != NULL) dvma_unmap(sun3_dma_orig_addr); // addr = sun3_dvma_page((unsigned long)data, (unsigned long)dmabuf); addr = (void *)dvma_map((unsigned long) data, count); sun3_dma_orig_addr = addr; sun3_dma_orig_count = count; #endif dregs->fifo_count = 0; sun3_udc_write(UDC_RESET, UDC_CSR); /* reset fifo */ dregs->csr &= ~CSR_FIFO; dregs->csr |= CSR_FIFO; /* set direction */ if(write_flag) dregs->csr |= CSR_SEND; else dregs->csr &= ~CSR_SEND; /* byte count for fifo */ dregs->fifo_count = count; sun3_udc_write(UDC_RESET, UDC_CSR); /* reset fifo */ dregs->csr &= ~CSR_FIFO; dregs->csr |= CSR_FIFO; if(dregs->fifo_count != count) { printk("scsi%d: fifo_mismatch %04x not %04x\n", default_instance->host_no, dregs->fifo_count, (unsigned int) count); NCR5380_print(default_instance); } /* setup udc */ #ifdef OLDDMA udc_regs->addr_hi = ((dvma_vtob(dmabuf) & 0xff0000) >> 8); udc_regs->addr_lo = (dvma_vtob(dmabuf) & 0xffff); #else udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); #endif udc_regs->count = count/2; /* count in words */ udc_regs->mode_hi = UDC_MODE_HIWORD; if(write_flag) { if(count & 1) udc_regs->count++; udc_regs->mode_lo = UDC_MODE_LSEND; udc_regs->rsel = UDC_RSEL_SEND; } else { udc_regs->mode_lo = UDC_MODE_LRECV; udc_regs->rsel = UDC_RSEL_RECV; } /* announce location of regs block */ sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8), UDC_CHN_HI); sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO); /* set dma master on */ sun3_udc_write(0xd, UDC_MODE); /* interrupt enable */ sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); return count; }
/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) { void *addr; if(sun3_dma_orig_addr != NULL) dvma_unmap(sun3_dma_orig_addr); #ifdef SUN3_SCSI_VME addr = (void *)dvma_map_vme((unsigned long) data, count); #else addr = (void *)dvma_map((unsigned long) data, count); #endif sun3_dma_orig_addr = addr; sun3_dma_orig_count = count; #ifndef SUN3_SCSI_VME dregs->fifo_count = 0; sun3_udc_write(UDC_RESET, UDC_CSR); /* reset fifo */ dregs->csr &= ~CSR_FIFO; dregs->csr |= CSR_FIFO; #endif /* set direction */ if(write_flag) dregs->csr |= CSR_SEND; else dregs->csr &= ~CSR_SEND; #ifdef SUN3_SCSI_VME dregs->csr |= CSR_PACK_ENABLE; dregs->dma_addr_hi = ((unsigned long)addr >> 16); dregs->dma_addr_lo = ((unsigned long)addr & 0xffff); dregs->dma_count_hi = 0; dregs->dma_count_lo = 0; dregs->fifo_count_hi = 0; dregs->fifo_count = 0; #else /* byte count for fifo */ dregs->fifo_count = count; sun3_udc_write(UDC_RESET, UDC_CSR); /* reset fifo */ dregs->csr &= ~CSR_FIFO; dregs->csr |= CSR_FIFO; if(dregs->fifo_count != count) { printk("scsi%d: fifo_mismatch %04x not %04x\n", default_instance->host_no, dregs->fifo_count, (unsigned int) count); NCR5380_dprint(NDEBUG_DMA, default_instance); } /* setup udc */ udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); udc_regs->count = count/2; /* count in words */ udc_regs->mode_hi = UDC_MODE_HIWORD; if(write_flag) { if(count & 1) udc_regs->count++; udc_regs->mode_lo = UDC_MODE_LSEND; udc_regs->rsel = UDC_RSEL_SEND; } else { udc_regs->mode_lo = UDC_MODE_LRECV; udc_regs->rsel = UDC_RSEL_RECV; } /* announce location of regs block */ sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8), UDC_CHN_HI); sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO); /* set dma master on */ sun3_udc_write(0xd, UDC_MODE); /* interrupt enable */ sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); #endif return count; }
static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) { sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer, sp->SCp.this_residual); sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in); }
/* Detecting ESP chips on the machine. This is the simple and easy * version. */ int sun3x_esp_detect(Scsi_Host_Template *tpnt) { struct NCR_ESP *esp; struct ConfigDev *esp_dev; esp_dev = 0; esp = esp_allocate(tpnt, (void *) esp_dev); /* Do command transfer with DMA */ esp->do_pio_cmds = 0; /* Required functions */ esp->dma_bytes_sent = &dma_bytes_sent; esp->dma_can_transfer = &dma_can_transfer; esp->dma_dump_state = &dma_dump_state; esp->dma_init_read = &dma_init_read; esp->dma_init_write = &dma_init_write; esp->dma_ints_off = &dma_ints_off; esp->dma_ints_on = &dma_ints_on; esp->dma_irq_p = &dma_irq_p; esp->dma_ports_p = &dma_ports_p; esp->dma_setup = &dma_setup; /* Optional functions */ esp->dma_barrier = &dma_barrier; esp->dma_invalidate = &dma_invalidate; esp->dma_drain = &dma_drain; esp->dma_irq_entry = 0; esp->dma_irq_exit = 0; esp->dma_led_on = 0; esp->dma_led_off = 0; esp->dma_poll = &dma_poll; esp->dma_reset = &dma_reset; /* virtual DMA functions */ esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one; esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl; esp->dma_advance_sg = &dma_advance_sg; /* SCSI chip speed */ esp->cfreq = 20000000; esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE); esp->dregs = (void *)SUN3X_ESP_DMA; #if 0 esp->esp_command = (volatile unsigned char *)cmd_buffer; esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer, sizeof (cmd_buffer)); #else esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE); esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command); #endif esp->irq = 2; if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, "SUN3X SCSI", NULL)) { esp_deallocate(esp); return 0; } esp->scsi_id = 7; esp->diff = 0; esp_initialize(esp); /* for reasons beyond my knowledge (and which should likely be fixed) sync mode doesn't work on a 3/80 at 5mhz. but it does at 4. */ esp->sync_defp = 0x3f; printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); esps_running = esps_in_use; return esps_in_use; }