dec_esp.c
来自「linux 内核源代码」· C语言 代码 · 共 688 行 · 第 1/2 页
C
688 行
{ struct NCR_ESP *esp = dev_get_drvdata(dev); free_irq(esp->irq, esp->ehost); esp_deallocate(esp); scsi_host_put(esp->ehost);}/************************************************************* DMA Functions */static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id){ printk("Got unexpected SCSI DMA Interrupt! < "); printk("SCSI_DMA_MEMRDERR "); printk(">\n"); return IRQ_HANDLED;}static irqreturn_t scsi_dma_err_int(int irq, void *dev_id){ /* empty */ return IRQ_HANDLED;}static irqreturn_t scsi_dma_int(int irq, void *dev_id){ u32 scsi_next_ptr; scsi_next_ptr = ioasic_read(IO_REG_SCSI_DMA_P); /* next page */ scsi_next_ptr = (((scsi_next_ptr >> 3) + PAGE_SIZE) & PAGE_MASK) << 3; ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr); fast_iob(); return IRQ_HANDLED;}static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count){ return fifo_count;}static void dma_drain(struct NCR_ESP *esp){ u32 nw, data0, data1, scsi_data_ptr; u16 *p; nw = ioasic_read(IO_REG_SCSI_SCR); /* * Is there something in the dma buffers left? */ if (nw) { scsi_data_ptr = ioasic_read(IO_REG_SCSI_DMA_P) >> 3; p = phys_to_virt(scsi_data_ptr); switch (nw) { case 1: data0 = ioasic_read(IO_REG_SCSI_SDR0); p[0] = data0 & 0xffff; break; case 2: data0 = ioasic_read(IO_REG_SCSI_SDR0); p[0] = data0 & 0xffff; p[1] = (data0 >> 16) & 0xffff; break; case 3: data0 = ioasic_read(IO_REG_SCSI_SDR0); data1 = ioasic_read(IO_REG_SCSI_SDR1); p[0] = data0 & 0xffff; p[1] = (data0 >> 16) & 0xffff; p[2] = data1 & 0xffff; break; default: printk("Strange: %d words in dma buffer left\n", nw); break; } }}static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd * sp){ return sp->SCp.this_residual;}static void dma_dump_state(struct NCR_ESP *esp){}static void dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length){ u32 scsi_next_ptr, ioasic_ssr; unsigned long flags; if (vaddress & 3) panic("dec_esp.c: unable to handle partial word transfers, yet..."); dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); spin_lock_irqsave(&ioasic_ssr_lock, flags); fast_mb(); ioasic_ssr = ioasic_read(IO_REG_SSR); ioasic_ssr &= ~IO_SSR_SCSI_DMA_EN; ioasic_write(IO_REG_SSR, ioasic_ssr); fast_wmb(); ioasic_write(IO_REG_SCSI_SCR, 0); ioasic_write(IO_REG_SCSI_DMA_P, vaddress << 3); /* prepare for next page */ scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr); ioasic_ssr |= (IO_SSR_SCSI_DMA_DIR | IO_SSR_SCSI_DMA_EN); fast_wmb(); ioasic_write(IO_REG_SSR, ioasic_ssr); fast_iob(); spin_unlock_irqrestore(&ioasic_ssr_lock, flags);}static void dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length){ u32 scsi_next_ptr, ioasic_ssr; unsigned long flags; if (vaddress & 3) panic("dec_esp.c: unable to handle partial word transfers, yet..."); dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); spin_lock_irqsave(&ioasic_ssr_lock, flags); fast_mb(); ioasic_ssr = ioasic_read(IO_REG_SSR); ioasic_ssr &= ~(IO_SSR_SCSI_DMA_DIR | IO_SSR_SCSI_DMA_EN); ioasic_write(IO_REG_SSR, ioasic_ssr); fast_wmb(); ioasic_write(IO_REG_SCSI_SCR, 0); ioasic_write(IO_REG_SCSI_DMA_P, vaddress << 3); /* prepare for next page */ scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr); ioasic_ssr |= IO_SSR_SCSI_DMA_EN; fast_wmb(); ioasic_write(IO_REG_SSR, ioasic_ssr); fast_iob(); spin_unlock_irqrestore(&ioasic_ssr_lock, flags);}static void dma_ints_off(struct NCR_ESP *esp){ disable_irq(dec_interrupt[DEC_IRQ_ASC_DMA]);}static void dma_ints_on(struct NCR_ESP *esp){ enable_irq(dec_interrupt[DEC_IRQ_ASC_DMA]);}static int dma_irq_p(struct NCR_ESP *esp){ return (esp->eregs->esp_status & ESP_STAT_INTR);}static int dma_ports_p(struct NCR_ESP *esp){ /* * FIXME: what's this good for? */ return 1;}static void dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write){ /* * DMA_ST_WRITE means "move data from device to memory" * so when (write) is true, it actually means READ! */ if (write) dma_init_read(esp, addr, count); else dma_init_write(esp, addr, count);}static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp){ sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);}static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, struct scsi_cmnd * sp){ int sz = sp->SCp.buffers_residual; struct scatterlist *sg = sp->SCp.buffer; while (sz >= 0) { sg[sz].dma_address = page_to_phys(sg[sz].page) + sg[sz].offset; sz--; } sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);}static void dma_advance_sg(struct scsi_cmnd * sp){ sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);}static void pmaz_dma_drain(struct NCR_ESP *esp){ memcpy(phys_to_virt(esp_virt_buffer), (void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE), scsi_current_length);}static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length){ volatile u32 *dmareg = (volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG); if (length > ESP_TGT_DMA_SIZE) length = ESP_TGT_DMA_SIZE; *dmareg = TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE); iob(); esp_virt_buffer = vaddress; scsi_current_length = length;}static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length){ volatile u32 *dmareg = (volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG); memcpy((void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE), phys_to_virt(vaddress), length); wmb(); *dmareg = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE); iob();}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){ /* * 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_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp){ sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);}#ifdef CONFIG_TCstatic int __init dec_esp_tc_probe(struct device *dev);static int __exit dec_esp_tc_remove(struct device *dev);static const struct tc_device_id dec_esp_tc_table[] = { { "DEC ", "PMAZ-AA " }, { }};MODULE_DEVICE_TABLE(tc, dec_esp_tc_table);static struct tc_driver dec_esp_tc_driver = { .id_table = dec_esp_tc_table, .driver = { .name = "dec_esp", .bus = &tc_bus_type, .probe = dec_esp_tc_probe, .remove = __exit_p(dec_esp_tc_remove), },};static int __init dec_esp_tc_probe(struct device *dev){ int status = dec_esp_probe(dev); if (!status) get_device(dev); return status;}static int __exit dec_esp_tc_remove(struct device *dev){ put_device(dev); dec_esp_remove(dev); return 0;}#endifstatic int __init dec_esp_init(void){ int status; status = tc_register_driver(&dec_esp_tc_driver); if (!status) dec_esp_platform_probe(); if (nesps) { pr_info("ESP: Total of %d ESP hosts found, " "%d actually in use.\n", nesps, esps_in_use); esps_running = esps_in_use; } return status;}static void __exit dec_esp_exit(void){ dec_esp_platform_remove(); tc_unregister_driver(&dec_esp_tc_driver);}module_init(dec_esp_init);module_exit(dec_esp_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?