jazz_esp.c
来自「linux 内核源代码」· C语言 代码 · 共 245 行
C
245 行
/* jazz_esp.c: ESP front-end for MIPS JAZZ systems. * * Copyright (C) 2007 Thomas Bogend鰎fer (tsbogend@alpha.frankende) */#include <linux/kernel.h>#include <linux/types.h>#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/platform_device.h>#include <linux/dma-mapping.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/jazz.h>#include <asm/jazzdma.h>#include <scsi/scsi_host.h>#include "esp_scsi.h"#define DRV_MODULE_NAME "jazz_esp"#define PFX DRV_MODULE_NAME ": "#define DRV_VERSION "1.000"#define DRV_MODULE_RELDATE "May 19, 2007"static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg){ *(volatile u8 *)(esp->regs + reg) = val;}static u8 jazz_esp_read8(struct esp *esp, unsigned long reg){ return *(volatile u8 *)(esp->regs + reg);}static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf, size_t sz, int dir){ return dma_map_single(esp->dev, buf, sz, dir);}static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir){ return dma_map_sg(esp->dev, sg, num_sg, dir);}static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr, size_t sz, int dir){ dma_unmap_single(esp->dev, addr, sz, dir);}static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir){ dma_unmap_sg(esp->dev, sg, num_sg, dir);}static int jazz_esp_irq_pending(struct esp *esp){ if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) return 1; return 0;}static void jazz_esp_reset_dma(struct esp *esp){ vdma_disable ((int)esp->dma_regs);}static void jazz_esp_dma_drain(struct esp *esp){ /* nothing to do */}static void jazz_esp_dma_invalidate(struct esp *esp){ vdma_disable ((int)esp->dma_regs);}static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, u32 dma_count, int write, u8 cmd){ BUG_ON(!(cmd & ESP_CMD_DMA)); jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); vdma_disable ((int)esp->dma_regs); if (write) vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ); else vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE); vdma_set_addr ((int)esp->dma_regs, addr); vdma_set_count ((int)esp->dma_regs, dma_count); vdma_enable ((int)esp->dma_regs); scsi_esp_cmd(esp, cmd);}static int jazz_esp_dma_error(struct esp *esp){ u32 enable = vdma_get_enable((int)esp->dma_regs); if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR)) return 1; return 0;}static const struct esp_driver_ops jazz_esp_ops = { .esp_write8 = jazz_esp_write8, .esp_read8 = jazz_esp_read8, .map_single = jazz_esp_map_single, .map_sg = jazz_esp_map_sg, .unmap_single = jazz_esp_unmap_single, .unmap_sg = jazz_esp_unmap_sg, .irq_pending = jazz_esp_irq_pending, .reset_dma = jazz_esp_reset_dma, .dma_drain = jazz_esp_dma_drain, .dma_invalidate = jazz_esp_dma_invalidate, .send_dma_cmd = jazz_esp_send_dma_cmd, .dma_error = jazz_esp_dma_error,};static int __devinit esp_jazz_probe(struct platform_device *dev){ struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; struct resource *res; int err; host = scsi_host_alloc(tpnt, sizeof(struct esp)); err = -ENOMEM; if (!host) goto fail; host->max_id = 8; esp = shost_priv(host); esp->host = host; esp->dev = dev; esp->ops = &jazz_esp_ops; res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) goto fail_unlink; esp->regs = (void __iomem *)res->start; if (!esp->regs) goto fail_unlink; res = platform_get_resource(dev, IORESOURCE_MEM, 1); if (!res) goto fail_unlink; esp->dma_regs = (void __iomem *)res->start; esp->command_block = dma_alloc_coherent(esp->dev, 16, &esp->command_block_dma, GFP_KERNEL); if (!esp->command_block) goto fail_unmap_regs; host->irq = platform_get_irq(dev, 0); err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); if (err < 0) goto fail_unmap_command_block; esp->scsi_id = 7; esp->host->this_id = esp->scsi_id; esp->scsi_id_mask = (1 << esp->scsi_id); esp->cfreq = 40000000; dev_set_drvdata(&dev->dev, esp); err = scsi_esp_register(esp, &dev->dev); if (err) goto fail_free_irq; return 0;fail_free_irq: free_irq(host->irq, esp);fail_unmap_command_block: dma_free_coherent(esp->dev, 16, esp->command_block, esp->command_block_dma);fail_unmap_regs:fail_unlink: scsi_host_put(host);fail: return err;}static int __devexit esp_jazz_remove(struct platform_device *dev){ struct esp *esp = dev_get_drvdata(&dev->dev); unsigned int irq = esp->host->irq; scsi_esp_unregister(esp); free_irq(irq, esp); dma_free_coherent(esp->dev, 16, esp->command_block, esp->command_block_dma); scsi_host_put(esp->host); return 0;}static struct platform_driver esp_jazz_driver = { .probe = esp_jazz_probe, .remove = __devexit_p(esp_jazz_remove), .driver = { .name = "jazz_esp", },};static int __init jazz_esp_init(void){ return platform_driver_register(&esp_jazz_driver);}static void __exit jazz_esp_exit(void){ platform_driver_unregister(&esp_jazz_driver);}MODULE_DESCRIPTION("JAZZ ESP SCSI driver");MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);module_init(jazz_esp_init);module_exit(jazz_esp_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?