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 + -
显示快捷键?