diff options
-rw-r--r-- | drivers/scsi/dec_esp.c | 183 | ||||
-rw-r--r-- | drivers/scsi/dec_esp.h | 7 | ||||
-rw-r--r-- | include/asm-mips/dec/ioasic_ints.h | 6 |
3 files changed, 179 insertions, 17 deletions
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c index f1c56cd16..47fc0037e 100644 --- a/drivers/scsi/dec_esp.c +++ b/drivers/scsi/dec_esp.c @@ -1,7 +1,9 @@ /* * dec_esp.c: Driver for SCSI chips on IOASIC based TURBOchannel DECstations + * and TURBOchannel PMAZ-A cards * * TURBOchannel changes by Harald Koerfgen + * PMAZ-A support by David Airlie * * based on jazz_esp.c: * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) @@ -38,21 +40,43 @@ static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); static void dma_drain(struct NCR_ESP *esp); +static void pmaz_dma_drain(struct NCR_ESP *esp); static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_dump_state(struct NCR_ESP *esp); static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); static void dma_ints_off(struct NCR_ESP *esp); static void dma_ints_on(struct NCR_ESP *esp); +static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); +static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); +static void pmaz_dma_ints_off(struct NCR_ESP *esp); +static void pmaz_dma_ints_on(struct NCR_ESP *esp); static int dma_irq_p(struct NCR_ESP *esp); static int dma_ports_p(struct NCR_ESP *esp); static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); +static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); +// static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_advance_sg(Scsi_Cmnd * sp); +#define TC_ESP_RAM_SIZE 0x20000 +#define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1)) +#define ESP_NCMD 7 + +#define TC_ESP_DMAR_MASK 0x1ffff +#define TC_ESP_DMAR_WRITE 0x80000000 +#define TC_ESP_DMA_ADDR(x) ((unsigned)(x) & TC_ESP_DMAR_MASK) + +volatile unsigned char *scsi_pmaz_dma_ptrs_tc[ESP_NCMD]; +unsigned char scsi_pmaz_dma_buff_used[ESP_NCMD]; +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. @@ -65,6 +89,8 @@ volatile unsigned long *ioasic_ssr; volatile unsigned long *scsi_sdr0; volatile unsigned long *scsi_sdr1; +volatile int *scsi_pmaz_dma_ptr_tc; + static void scsi_dma_int(int, void *, struct pt_regs *); /***************************************************************** Detection */ @@ -72,6 +98,9 @@ int dec_esp_detect(Scsi_Host_Template * tpnt) { struct NCR_ESP *esp; struct ConfigDev *esp_dev; + int slot, i; + unsigned long mem_start; + volatile unsigned char *buffer; if (IOASIC) { esp_dev = 0; @@ -143,21 +172,88 @@ int dec_esp_detect(Scsi_Host_Template * tpnt) request_irq(SCSI_DMA_INT, scsi_dma_int, SA_INTERRUPT, "JUNKIO SCSI DMA", NULL); - /* - * FIXME, look if the scsi id is availabe from NVRAM - */ esp->scsi_id = 7; /* Check for differential SCSI-bus */ - /* What is this stuff? */ esp->diff = 0; esp_initialize(esp); + } + + if (TURBOCHANNEL) { + while ((slot = search_tc_card("PMAZ-AA")) >= 0) { + claim_tc_card(slot); + mem_start = get_tc_base_addr(slot); + + esp_dev = 0; + esp = esp_allocate(tpnt, (void *) esp_dev); + + esp->dregs = 0; + esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG); + esp->do_pio_cmds = 1; + + /* Set the command buffer */ + esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer; + + /* get virtual dma address for command buffer */ + esp->esp_command_dvma = (__u32) KSEG0ADDR((volatile unsigned char *) pmaz_cmd_buffer); + + buffer = (volatile unsigned char *) (mem_start + DEC_SCSI_SRAM); + + scsi_pmaz_dma_ptr_tc = (volatile int *) (mem_start + DEC_SCSI_DMAREG); + + for (i = 0; i < ESP_NCMD; i++) { + scsi_pmaz_dma_ptrs_tc[i] = (volatile unsigned char *) (buffer + ESP_TGT_DMA_SIZE * i); + } + + scsi_pmaz_dma_buff_used[0] = 1; + + esp->cfreq = get_tc_speed(); + + esp->irq = get_tc_irq_nr(slot); + + /* 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 = &pmaz_dma_init_read; + esp->dma_init_write = &pmaz_dma_init_write; + esp->dma_ints_off = &pmaz_dma_ints_off; + esp->dma_ints_on = &pmaz_dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &pmaz_dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = &pmaz_dma_drain; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_poll = 0; + esp->dma_reset = 0; + esp->dma_led_off = 0; + esp->dma_led_on = 0; + + esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one; + esp->dma_mmu_get_scsi_sgl = 0; + esp->dma_mmu_release_scsi_one = 0; + esp->dma_mmu_release_scsi_sgl = 0; + esp->dma_advance_sg = 0; + + request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ-AA", NULL); + esp->scsi_id = 7; + esp->diff = 0; + esp_initialize(esp); + } + } + + if(nesps) { 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; - } + } else return 0; } @@ -172,18 +268,18 @@ static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs) *scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3; *isr &= ~SCSI_PTR_LOADED; } else { - printk("Got unexpected SCSI DMA Interrupt! < "); if (*isr & SCSI_PAGOVRRUN) - printk("SCSI_PAGOVRRUN "); - if (*isr & SCSI_DMA_MEMRDERR) + *isr &= ~SCSI_PAGOVRRUN; + if (*isr & SCSI_DMA_MEMRDERR) { + printk("Got unexpected SCSI DMA Interrupt! < "); printk("SCSI_DMA_MEMRDERR "); printk(">\n"); -// panic("stop"); - *isr &= ~(SCSI_PAGOVRRUN || SCSI_DMA_MEMRDERR); + *isr &= ~SCSI_DMA_MEMRDERR; + } } /* - * This driver will only work on IOASIC machines + * 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 */ @@ -198,13 +294,13 @@ static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) static void dma_drain(struct NCR_ESP *esp) { - unsigned long nw; + unsigned long nw = *scsi_scr; unsigned short *p = KSEG1ADDR((unsigned short *) ((*scsi_dma_ptr) >> 3)); /* * Is there something in the dma buffers left? */ - if (nw = *scsi_scr) { + if (nw) { switch (nw) { case 1: *p = (unsigned short) *scsi_sdr0; @@ -225,6 +321,12 @@ static void dma_drain(struct NCR_ESP *esp) } } +static void pmaz_dma_drain(struct NCR_ESP *esp) +{ + memcpy((volatile void *) (KSEG0ADDR(esp_virt_buffer)), + (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length); +} + static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp) { return sp->SCp.this_residual;; @@ -298,6 +400,33 @@ static void dma_ints_on(struct NCR_ESP *esp) enable_irq(SCSI_DMA_INT); } +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(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 int dma_irq_p(struct NCR_ESP *esp) { return (esp->eregs->esp_status & ESP_STAT_INTR); @@ -324,6 +453,34 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) } } +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)); +} + /* * These aren't used yet */ diff --git a/drivers/scsi/dec_esp.h b/drivers/scsi/dec_esp.h index 15a7bc14b..aae3a4a44 100644 --- a/drivers/scsi/dec_esp.h +++ b/drivers/scsi/dec_esp.h @@ -1,6 +1,7 @@ /* dec_esp.h: Defines and structures for the JAZZ SCSI driver. * * DECstation changes Copyright (C) 1998 Harald Koerfgen + * and David Airlie * * based on jazz_esp.h: * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) @@ -13,6 +14,10 @@ #include "NCR53C9x.h" +#define DEC_SCSI_SREG 0 +#define DEC_SCSI_DMAREG 0x40000 +#define DEC_SCSI_SRAM 0x80000 +#define DEC_SCSI_DIAG 0xC0000 extern int dec_esp_detect(struct SHT *); extern const char *esp_info(struct Scsi_Host *); @@ -26,7 +31,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, #define SCSI_DEC_ESP { \ proc_dir: &proc_scsi_esp, \ proc_info: &esp_proc_info, \ - name: "PMAZ-AA", \ + name: "NCR53C94", \ detect: dec_esp_detect, \ info: esp_info, \ command: esp_command, \ diff --git a/include/asm-mips/dec/ioasic_ints.h b/include/asm-mips/dec/ioasic_ints.h index e28e334b2..bd184d1c4 100644 --- a/include/asm-mips/dec/ioasic_ints.h +++ b/include/asm-mips/dec/ioasic_ints.h @@ -68,9 +68,9 @@ #define MAXINE_DTOP_RECV 0x00000001 /* DTI Recv-Available */ /* kn03 aka 3max+ aka DS5000_2x0 */ -#define KN03_TC2 0x00004000 -#define KN03_TC1 0x00002000 -#define KN03_TC0 0x00001000 +#define KN03_TC2 0x00002000 +#define KN03_TC1 0x00001000 +#define KN03_TC0 0x00000800 #define KN03_SCSI_FIFO 0x00000004 /* ??? Info from Mach */ /* |