From: Richard B. <rb...@us...> - 2002-06-12 07:57:32
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/scsi In directory usw-pr-cvs1:/tmp/cvs-serv22878/drivers/scsi Modified Files: vax_esp.c vax_esp.h Log Message: Just a few updates for "safe keeping". Still trying to get my head around DMA Index: vax_esp.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/scsi/vax_esp.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- vax_esp.c 4 Jun 2002 07:20:28 -0000 1.2 +++ vax_esp.c 12 Jun 2002 07:57:26 -0000 1.3 @@ -1,16 +1,8 @@ /* - * vax_esp.c: Driver for SCSI chips on VAXStation 4000/200 and uVax3100/85 + * vax_esp.c: Driver for NCR53C94 SCSI chip on uVax3100/85 * - * based on dec_esp.c: - * VAX support by David Airlie & Richard Banks + * by David Airlie & Richard Banks * - * TURBOchannel changes by Harald Koerfgen - * PMAZ-A support by David Airlie - * - * based on jazz_esp.c: - * Copyright (C) 1997 Thomas Bogendoerfer (tsb...@al...) - * - * jazz_esp is based on David S. Miller's ESP driver and cyber_esp */ #include <linux/kernel.h> @@ -29,6 +21,9 @@ #include <asm/irq.h> #include <asm/dma.h> +#include <asm/pgalloc.h> +#include <asm/vsa.h> +#include <asm/mv.h> #include <asm/pgtable.h> @@ -47,20 +42,11 @@ static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_advance_sg(Scsi_Cmnd * sp); -#if 0 -volatile unsigned char *scsi_pmaz_dma_ptrs_tc[ESP_NCMD]; -unsigned char scsi_pmaz_dma_buff_used[ESP_NCMD]; -#endif unsigned char scsi_cur_buff = 1; /* Leave space for command buffer */ __u32 esp_virt_buffer; int scsi_current_length = 0; volatile unsigned char cmd_buffer[16]; -volatile unsigned char pmaz_cmd_buffer[16]; - /* This is where all commands are put - * before they are trasfered to the ESP chip - * via PIO. - */ volatile unsigned long *scsi_dma_ptr; volatile unsigned long *scsi_next_ptr; @@ -69,6 +55,12 @@ volatile unsigned long *scsi_sdr0; volatile unsigned long *scsi_sdr1; +volatile unsigned long *scsi_dma_address; +volatile unsigned long *scsi_dma_direction; + +struct vax_scsi_pte *esp_pte; +unsigned long esp_pte_offset; + static void scsi_dma_int(int, void *, struct pt_regs *); /***************************************************************** Detection */ @@ -77,15 +69,23 @@ struct NCR_ESP *esp; struct ConfigDev *esp_dev; unsigned long scsi_base; + struct vax_scsi_pte *pte; + unsigned long l; scsi_base = 0x200c0080; + + /* On the 3100/85 the SCSI DMA registers are at 0x25c00000 (address & direction + * The SCSI DMA Map registers are at 0x27000000-27007FFF (8K) + * The SCSI controller registers are at0X26000080-BF + */ + scsi_base = 0x26000080; /* hardcode for 3100/85 for now */ esp_dev = 0; esp = esp_allocate(tpnt, (void *) esp_dev); /* Do command transfer with programmed I/O */ - esp->do_pio_cmds = 1; + esp->do_pio_cmds = 0; /* Required functions */ esp->dma_bytes_sent = &dma_bytes_sent; @@ -133,10 +133,29 @@ /* Set the command buffer */ esp->esp_command = (volatile unsigned char *) cmd_buffer; + + /* Now we have to create and initialise our DMA area. + * Initially we need to allocate the memory and clear the page table entries for the device + */ + esp_pte = pte = (struct vax_scsi_pte *)ioremap (0x27000000,32767); + for (l=0; l<8192; l++){ + ((unsigned long *)pte)[l] = 0; /* can't use bzero as access must be via longword */ + } + esp_pte_offset = 0; + + /* now we need to create the dma area + * As we use memory we will map the PTE for this memory into the PTE's for the device + */ + esp->esp_command_dvma = (__u32) kmalloc (VAX_SCSI_MAX_TRANSFER,GFP_ATOMIC); - /* get virtual dma address for command buffer */ - // esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer); - + + + /* need to find address and direction scsi registers. + * on the KA55 they're just offsets from the base register location. + * -- ugly code -- should set this inside vsbus.c somewhere + */ + scsi_dma_address = (unsigned long *)ioremap(VSA_KA55_BASE_REGS,1); + scsi_dma_direction = (unsigned long *)((unsigned long)&scsi_dma_address + VAX_SCSI_DMA_DIRECTION); /* add offset */ // esp->irq = SCSI_INT; esp->irq = 255; @@ -169,30 +188,6 @@ unsigned int dummy; printk ("dma_int called\n"); -#if 0 - if (*isr & SCSI_PTR_LOADED) { - /* next page */ - *scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3; - *isr &= ~SCSI_PTR_LOADED; - } else { - if (*isr & SCSI_PAGOVRRUN) - *isr &= ~SCSI_PAGOVRRUN; - if (*isr & SCSI_DMA_MEMRDERR) { - printk("Got unexpected SCSI DMA Interrupt! < "); - printk("SCSI_DMA_MEMRDERR "); - printk(">\n"); - *isr &= ~SCSI_DMA_MEMRDERR; - } - } - - /* - * This routine will only work on IOASIC machines - * so we can avoid an indirect function call here - * and flush the writeback buffer the fast way - */ -// dummy = *isr; -// dummy = *isr; -#endif } static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) @@ -204,31 +199,8 @@ static void dma_drain(struct NCR_ESP *esp) { unsigned long nw = *scsi_scr; - // unsigned short *p = KSEG1ADDR((unsigned short *) ((*scsi_dma_ptr) >> 3)); printk ("dma_drain called\n"); - /* - * Is there something in the dma buffers left? - */ - /* if (nw) { - switch (nw) { - case 1: - *p = (unsigned short) *scsi_sdr0; - break; - case 2: - *p++ = (unsigned short) (*scsi_sdr0); - *p = (unsigned short) ((*scsi_sdr0) >> 16); - break; - case 3: - *p++ = (unsigned short) (*scsi_sdr0); - *p++ = (unsigned short) ((*scsi_sdr0) >> 16); - *p = (unsigned short) (*scsi_sdr1); - break; - default: - printk("Strange: %d words in dma buffer left\n", (int) nw); - break; - } - } */ } static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp) @@ -240,11 +212,6 @@ static void dma_dump_state(struct NCR_ESP *esp) { printk ("dma_dump_state called\n"); - -/* - ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n", - esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs))); - */ } static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) @@ -254,55 +221,22 @@ printk ("dma_init_read called\n"); -#if 0 - if (vaddress & 3) - panic("dec_efs.c: unable to handle partial word transfers, yet..."); - - dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); - - *ioasic_ssr &= ~SCSI_DMA_EN; - *scsi_scr = 0; - *scsi_dma_ptr = vaddress << 3; - - /* prepare for next page */ - *scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; - *ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN); - - /* - * see above - */ - dummy = *isr; - dummy = *isr; -#endif } static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) { - printk ("dma_init_write called\n"); - -#if 0 extern volatile unsigned int *isr; unsigned int dummy; + struct vax_scsi_pte *pte; - if (vaddress & 3) - panic("dec_efs.c: unable to handle partial word transfers, yet..."); - - dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); - - *ioasic_ssr &= ~(SCSI_DMA_DIR | SCSI_DMA_EN); - *scsi_scr = 0; - *scsi_dma_ptr = vaddress << 3; - - /* prepare for next page */ - *scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; - *ioasic_ssr |= SCSI_DMA_EN; - - /* - * see above - */ - dummy = *isr; - dummy = *isr; -#endif + printk ("dma_init_write called\n"); + printk (" vaddress = 0x%x, length = %d\n",vaddress,length); + /* need to get the PTE of the buffer and transfer it to the device PTE map */ + printk(" virt_to_page(vaddress) = 0x%x\n",(unsigned long)virt_to_page(vaddress)); + pte = (struct vax_scsi_pte *)virt_to_page(vaddress); + esp_pte[esp_pte_offset++] = pte[0]; + // scsi_dma_direction = scsi_dma_direction | VAX_SCSI_DMA_FROM_MEMORY; + } static void dma_ints_off(struct NCR_ESP *esp) @@ -348,29 +282,18 @@ #endif } -/* - * These aren't used yet - */ static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) { - sp->SCp.have_data_in = virt_to_phys(sp->SCp.buffer); - sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in); + printk("dma_mmu_get_scsi_one called\n"); + // sp->SCp.have_data_in = virt_to_phys(sp->SCp.buffer); + //sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in); } 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; - printk ("dma_mmu_get_scsi_sgl called\n"); - /* -#if 0 - while (sz >= 0) { - sg[sz].dvma_addr = virt_to_phys(sg[sz].addr); - sz--; - } - sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_addr); -#endif - */ + printk ("dma_mmu_get_scsi_sgl called\n"); } static void dma_advance_sg(Scsi_Cmnd * sp) @@ -378,71 +301,6 @@ printk ("dma_adavnce_sg called\n"); // sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_addr); } - -#if 0 - -static void pmaz_dma_drain(struct NCR_ESP *esp) -{ - memcpy((void *) (KSEG0ADDR(esp_virt_buffer)), - (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length); -} - -static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) -{ - - if (length > ESP_TGT_DMA_SIZE) - length = ESP_TGT_DMA_SIZE; - - *scsi_pmaz_dma_ptr_tc = TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]); - esp_virt_buffer = vaddress; - scsi_current_length = length; -} - -static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) -{ - memcpy((void *)scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length); - - *scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]); - -} - -static void pmaz_dma_ints_off(struct NCR_ESP *esp) -{ -} - -static void pmaz_dma_ints_on(struct NCR_ESP *esp) -{ -} - -static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) -{ - /* - * On the Sparc, DMA_ST_WRITE means "move data from device to memory" - * so when (write) is true, it actually means READ! - */ - if (write) { - pmaz_dma_init_read(esp, addr, count); - } else { - pmaz_dma_init_write(esp, addr, count); - } -} - -static void pmaz_dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) -{ - int x; - for (x = 1; x < 6; x++) - if (sp->SCp.have_data_in == PHYSADDR(scsi_pmaz_dma_ptrs_tc[x])) - scsi_pmaz_dma_buff_used[x] = 0; -} - -static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) -{ - sp->SCp.have_data_in = (int) sp->SCp.ptr = - (char *) KSEG0ADDR((sp->request_buffer)); -} - -#endif - static Scsi_Host_Template driver_template = SCSI_VAX_ESP; Index: vax_esp.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/scsi/vax_esp.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- vax_esp.h 4 Jun 2002 07:20:28 -0000 1.2 +++ vax_esp.h 12 Jun 2002 07:57:26 -0000 1.3 @@ -2,12 +2,8 @@ * * VS changes Copyright (C) 2001 David Airlie * - * based on dec_esp.h: - * VAXstation changes Copyright (C) 1998 Harald Koerfgen - * and David Airlie + * Other changes by Richard Banks * - * based on jazz_esp.h: - * Copyright (C) 1997 Thomas Bogendoerfer (tsb...@al...) */ #ifndef VAX_ESP_H @@ -20,6 +16,14 @@ #define VAX_SCSI_SRAM 0x80000 #define VAX_SCSI_DIAG 0xC0000 +#define VAX_SCSI_DMA_ADDRESS 0x00 +#define VAX_SCSI_DMA_DIRECTION 0x04 +#define VAX_SCSI_MAX_TRANSFER 65535 + +#define VAX_SCSI_DMA_FROM_MEMORY 0x00000001 +#define VAX_SCSI_DMA_ACTIVE 0x00000002 +#define VAX_SCSI_DMA_MAP_LOADED 0x00000004 + extern int vax_esp_detect(struct SHT *); extern const char *esp_info(struct Scsi_Host *); extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); @@ -29,6 +33,27 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); +/* according to pg 205 of the VARM devices which use DMA have a slightly different + * page table entry format and use. Below is the extended PTE structure + * + * PTE Types for devices are + * <31><26><22> + * 1 x x Valid PFN + * 0 0 0 Valid PFN + * 0 0 1 Global PT Index + * 0 1 x Invalid PTE, I/O Abort + */ +struct vax_scsi_pte { + unsigned int spte_pfn:21; /* <20:0> Page Frame Number */ + unsigned int spte_unused:1; /* <21> Don't use this bit */ + unsigned int spte_global:1; /* <22> Help for ref simulation */ + unsigned int spte_owner:2; /* <24:23> Owner flag */ + unsigned int spte_resv; /* <25> Reserved */ + unsigned int spte_modify:1; /* <26> Modified */ + unsigned int spte_prot:4; /* <30:27> memory protection */ + unsigned int spte_v:1; /* <31> valid bit */ + }; + #define SCSI_VAX_ESP { \ proc_name: "esp", \ proc_info: &esp_proc_info, \ @@ -49,3 +74,4 @@ // controller id is 6 on the 3100/85 #endif /* VAX_ESP_H */ + |