Beispiel #1
0
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);
}
Beispiel #2
0
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;

}
Beispiel #4
0
/* 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;

}
Beispiel #5
0
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);
}
Beispiel #6
0
/* 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;
}