aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/jazz_esp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/jazz_esp.c')
-rw-r--r--drivers/scsi/jazz_esp.c429
1 files changed, 183 insertions, 246 deletions
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 19dd4b962e18..81e497d9eae0 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -1,307 +1,244 @@
1/* 1/* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
2 * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture)
3 * 2 *
4 * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 3 * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
5 *
6 * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
7 */ 4 */
8 5
9#include <linux/init.h>
10#include <linux/kernel.h> 6#include <linux/kernel.h>
11#include <linux/delay.h>
12#include <linux/types.h> 7#include <linux/types.h>
13#include <linux/string.h> 8#include <linux/module.h>
14#include <linux/slab.h> 9#include <linux/init.h>
15#include <linux/blkdev.h> 10#include <linux/interrupt.h>
16#include <linux/proc_fs.h> 11#include <linux/platform_device.h>
17#include <linux/stat.h> 12#include <linux/dma-mapping.h>
18
19#include "scsi.h"
20#include <scsi/scsi_host.h>
21#include "NCR53C9x.h"
22 13
23#include <asm/irq.h> 14#include <asm/irq.h>
15#include <asm/io.h>
16#include <asm/dma.h>
17
24#include <asm/jazz.h> 18#include <asm/jazz.h>
25#include <asm/jazzdma.h> 19#include <asm/jazzdma.h>
26#include <asm/dma.h>
27 20
28#include <asm/pgtable.h> 21#include <scsi/scsi_host.h>
29
30static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
31static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp);
32static void dma_dump_state(struct NCR_ESP *esp);
33static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
34static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
35static void dma_ints_off(struct NCR_ESP *esp);
36static void dma_ints_on(struct NCR_ESP *esp);
37static int dma_irq_p(struct NCR_ESP *esp);
38static int dma_ports_p(struct NCR_ESP *esp);
39static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
40static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
41static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
42static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
43static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
44static void dma_advance_sg (struct scsi_cmnd *sp);
45static void dma_led_off(struct NCR_ESP *);
46static void dma_led_on(struct NCR_ESP *);
47
48
49static volatile unsigned char cmd_buffer[16];
50 /* This is where all commands are put
51 * before they are trasfered to the ESP chip
52 * via PIO.
53 */
54
55static int jazz_esp_release(struct Scsi_Host *shost)
56{
57 if (shost->irq)
58 free_irq(shost->irq, NULL);
59 if (shost->dma_channel != 0xff)
60 free_dma(shost->dma_channel);
61 if (shost->io_port && shost->n_io_port)
62 release_region(shost->io_port, shost->n_io_port);
63 scsi_unregister(shost);
64 return 0;
65}
66 22
67/***************************************************************** Detection */ 23#include "esp_scsi.h"
68static int jazz_esp_detect(struct scsi_host_template *tpnt)
69{
70 struct NCR_ESP *esp;
71 struct ConfigDev *esp_dev;
72
73 /*
74 * first assumption it is there:-)
75 */
76 if (1) {
77 esp_dev = NULL;
78 esp = esp_allocate(tpnt, esp_dev, 0);
79
80 /* Do command transfer with programmed I/O */
81 esp->do_pio_cmds = 1;
82
83 /* Required functions */
84 esp->dma_bytes_sent = &dma_bytes_sent;
85 esp->dma_can_transfer = &dma_can_transfer;
86 esp->dma_dump_state = &dma_dump_state;
87 esp->dma_init_read = &dma_init_read;
88 esp->dma_init_write = &dma_init_write;
89 esp->dma_ints_off = &dma_ints_off;
90 esp->dma_ints_on = &dma_ints_on;
91 esp->dma_irq_p = &dma_irq_p;
92 esp->dma_ports_p = &dma_ports_p;
93 esp->dma_setup = &dma_setup;
94
95 /* Optional functions */
96 esp->dma_barrier = NULL;
97 esp->dma_drain = NULL;
98 esp->dma_invalidate = NULL;
99 esp->dma_irq_entry = NULL;
100 esp->dma_irq_exit = NULL;
101 esp->dma_poll = NULL;
102 esp->dma_reset = NULL;
103 esp->dma_led_off = &dma_led_off;
104 esp->dma_led_on = &dma_led_on;
105
106 /* virtual DMA functions */
107 esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
108 esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
109 esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
110 esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
111 esp->dma_advance_sg = &dma_advance_sg;
112
113
114 /* SCSI chip speed */
115 esp->cfreq = 40000000;
116 24
117 /* 25#define DRV_MODULE_NAME "jazz_esp"
118 * we don't give the address of DMA channel, but the number 26#define PFX DRV_MODULE_NAME ": "
119 * of DMA channel, so we can use the jazz DMA functions 27#define DRV_VERSION "1.000"
120 * 28#define DRV_MODULE_RELDATE "May 19, 2007"
121 */
122 esp->dregs = (void *) JAZZ_SCSI_DMA;
123
124 /* ESP register base */
125 esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);
126
127 /* Set the command buffer */
128 esp->esp_command = (volatile unsigned char *)cmd_buffer;
129
130 /* get virtual dma address for command buffer */
131 esp->esp_command_dvma = vdma_alloc(CPHYSADDR(cmd_buffer), sizeof (cmd_buffer));
132
133 esp->irq = JAZZ_SCSI_IRQ;
134 request_irq(JAZZ_SCSI_IRQ, esp_intr, IRQF_DISABLED, "JAZZ SCSI",
135 esp->ehost);
136
137 /*
138 * FIXME, look if the scsi id is available from NVRAM
139 */
140 esp->scsi_id = 7;
141
142 /* Check for differential SCSI-bus */
143 /* What is this stuff? */
144 esp->diff = 0;
145
146 esp_initialize(esp);
147
148 printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
149 esps_running = esps_in_use;
150 return esps_in_use;
151 }
152 return 0;
153}
154 29
155/************************************************************* DMA Functions */ 30static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
156static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
157{ 31{
158 return fifo_count; 32 *(volatile u8 *)(esp->regs + reg) = val;
159} 33}
160 34
161static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp) 35static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
162{ 36{
163 /* 37 return *(volatile u8 *)(esp->regs + reg);
164 * maximum DMA size is 1MB
165 */
166 unsigned long sz = sp->SCp.this_residual;
167 if(sz > 0x100000)
168 sz = 0x100000;
169 return sz;
170} 38}
171 39
172static void dma_dump_state(struct NCR_ESP *esp) 40static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf,
41 size_t sz, int dir)
173{ 42{
174 43 return dma_map_single(esp->dev, buf, sz, dir);
175 ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
176 esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs)));
177} 44}
178 45
179static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) 46static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg,
47 int num_sg, int dir)
180{ 48{
181 dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length); 49 return dma_map_sg(esp->dev, sg, num_sg, dir);
182 vdma_disable ((int)esp->dregs);
183 vdma_set_mode ((int)esp->dregs, DMA_MODE_READ);
184 vdma_set_addr ((int)esp->dregs, vaddress);
185 vdma_set_count ((int)esp->dregs, length);
186 vdma_enable ((int)esp->dregs);
187} 50}
188 51
189static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) 52static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr,
53 size_t sz, int dir)
190{ 54{
191 dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length); 55 dma_unmap_single(esp->dev, addr, sz, dir);
192 vdma_disable ((int)esp->dregs);
193 vdma_set_mode ((int)esp->dregs, DMA_MODE_WRITE);
194 vdma_set_addr ((int)esp->dregs, vaddress);
195 vdma_set_count ((int)esp->dregs, length);
196 vdma_enable ((int)esp->dregs);
197} 56}
198 57
199static void dma_ints_off(struct NCR_ESP *esp) 58static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
59 int num_sg, int dir)
200{ 60{
201 disable_irq(esp->irq); 61 dma_unmap_sg(esp->dev, sg, num_sg, dir);
202} 62}
203 63
204static void dma_ints_on(struct NCR_ESP *esp) 64static int jazz_esp_irq_pending(struct esp *esp)
205{ 65{
206 enable_irq(esp->irq); 66 if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
67 return 1;
68 return 0;
207} 69}
208 70
209static int dma_irq_p(struct NCR_ESP *esp) 71static void jazz_esp_reset_dma(struct esp *esp)
210{ 72{
211 return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR); 73 vdma_disable ((int)esp->dma_regs);
212} 74}
213 75
214static int dma_ports_p(struct NCR_ESP *esp) 76static void jazz_esp_dma_drain(struct esp *esp)
215{ 77{
216 int enable = vdma_get_enable((int)esp->dregs); 78 /* nothing to do */
217
218 return (enable & R4030_CHNL_ENABLE);
219} 79}
220 80
221static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) 81static void jazz_esp_dma_invalidate(struct esp *esp)
222{ 82{
223 /* 83 vdma_disable ((int)esp->dma_regs);
224 * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
225 * so when (write) is true, it actually means READ!
226 */
227 if(write){
228 dma_init_read(esp, addr, count);
229 } else {
230 dma_init_write(esp, addr, count);
231 }
232} 84}
233 85
234static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp) 86static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
87 u32 dma_count, int write, u8 cmd)
235{ 88{
236 sp->SCp.have_data_in = vdma_alloc(CPHYSADDR(sp->SCp.buffer), sp->SCp.this_residual); 89 BUG_ON(!(cmd & ESP_CMD_DMA));
237 sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in); 90
91 jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
92 jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
93 vdma_disable ((int)esp->dma_regs);
94 if (write)
95 vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
96 else
97 vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
98
99 vdma_set_addr ((int)esp->dma_regs, addr);
100 vdma_set_count ((int)esp->dma_regs, dma_count);
101 vdma_enable ((int)esp->dma_regs);
102
103 scsi_esp_cmd(esp, cmd);
238} 104}
239 105
240static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp) 106static int jazz_esp_dma_error(struct esp *esp)
241{
242 int sz = sp->SCp.buffers_residual;
243 struct scatterlist *sg = (struct scatterlist *) sp->SCp.buffer;
244
245 while (sz >= 0) {
246 sg[sz].dma_address = vdma_alloc(CPHYSADDR(page_address(sg[sz].page) + sg[sz].offset), sg[sz].length);
247 sz--;
248 }
249 sp->SCp.ptr=(char *)(sp->SCp.buffer->dma_address);
250}
251
252static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
253{ 107{
254 vdma_free(sp->SCp.have_data_in); 108 u32 enable = vdma_get_enable((int)esp->dma_regs);
109
110 if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
111 return 1;
112
113 return 0;
255} 114}
256 115
257static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp) 116static const struct esp_driver_ops jazz_esp_ops = {
117 .esp_write8 = jazz_esp_write8,
118 .esp_read8 = jazz_esp_read8,
119 .map_single = jazz_esp_map_single,
120 .map_sg = jazz_esp_map_sg,
121 .unmap_single = jazz_esp_unmap_single,
122 .unmap_sg = jazz_esp_unmap_sg,
123 .irq_pending = jazz_esp_irq_pending,
124 .reset_dma = jazz_esp_reset_dma,
125 .dma_drain = jazz_esp_dma_drain,
126 .dma_invalidate = jazz_esp_dma_invalidate,
127 .send_dma_cmd = jazz_esp_send_dma_cmd,
128 .dma_error = jazz_esp_dma_error,
129};
130
131static int __devinit esp_jazz_probe(struct platform_device *dev)
258{ 132{
259 int sz = sp->use_sg - 1; 133 struct scsi_host_template *tpnt = &scsi_esp_template;
260 struct scatterlist *sg = (struct scatterlist *)sp->request_buffer; 134 struct Scsi_Host *host;
261 135 struct esp *esp;
262 while(sz >= 0) { 136 struct resource *res;
263 vdma_free(sg[sz].dma_address); 137 int err;
264 sz--; 138
265 } 139 host = scsi_host_alloc(tpnt, sizeof(struct esp));
140
141 err = -ENOMEM;
142 if (!host)
143 goto fail;
144
145 host->max_id = 8;
146 esp = host_to_esp(host);
147
148 esp->host = host;
149 esp->dev = dev;
150 esp->ops = &jazz_esp_ops;
151
152 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
153 if (!res)
154 goto fail_unlink;
155
156 esp->regs = (void __iomem *)res->start;
157 if (!esp->regs)
158 goto fail_unlink;
159
160 res = platform_get_resource(dev, IORESOURCE_MEM, 1);
161 if (!res)
162 goto fail_unlink;
163
164 esp->dma_regs = (void __iomem *)res->start;
165
166 esp->command_block = dma_alloc_coherent(esp->dev, 16,
167 &esp->command_block_dma,
168 GFP_KERNEL);
169 if (!esp->command_block)
170 goto fail_unmap_regs;
171
172 host->irq = platform_get_irq(dev, 0);
173 err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
174 if (err < 0)
175 goto fail_unmap_command_block;
176
177 esp->scsi_id = 7;
178 esp->host->this_id = esp->scsi_id;
179 esp->scsi_id_mask = (1 << esp->scsi_id);
180 esp->cfreq = 40000000;
181
182 dev_set_drvdata(&dev->dev, esp);
183
184 err = scsi_esp_register(esp, &dev->dev);
185 if (err)
186 goto fail_free_irq;
187
188 return 0;
189
190fail_free_irq:
191 free_irq(host->irq, esp);
192fail_unmap_command_block:
193 dma_free_coherent(esp->dev, 16,
194 esp->command_block,
195 esp->command_block_dma);
196fail_unmap_regs:
197fail_unlink:
198 scsi_host_put(host);
199fail:
200 return err;
266} 201}
267 202
268static void dma_advance_sg (struct scsi_cmnd *sp) 203static int __devexit esp_jazz_remove(struct platform_device *dev)
269{ 204{
270 sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address); 205 struct esp *esp = dev_get_drvdata(&dev->dev);
206 unsigned int irq = esp->host->irq;
207
208 scsi_esp_unregister(esp);
209
210 free_irq(irq, esp);
211 dma_free_coherent(esp->dev, 16,
212 esp->command_block,
213 esp->command_block_dma);
214
215 scsi_host_put(esp->host);
216
217 return 0;
271} 218}
272 219
273#define JAZZ_HDC_LED 0xe000d100 /* FIXME, find correct address */ 220static struct platform_driver esp_jazz_driver = {
221 .probe = esp_jazz_probe,
222 .remove = __devexit_p(esp_jazz_remove),
223 .driver = {
224 .name = "jazz_esp",
225 },
226};
274 227
275static void dma_led_off(struct NCR_ESP *esp) 228static int __init jazz_esp_init(void)
276{ 229{
277#if 0 230 return platform_driver_register(&esp_jazz_driver);
278 *(unsigned char *)JAZZ_HDC_LED = 0;
279#endif
280} 231}
281 232
282static void dma_led_on(struct NCR_ESP *esp) 233static void __exit jazz_esp_exit(void)
283{ 234{
284#if 0 235 platform_driver_unregister(&esp_jazz_driver);
285 *(unsigned char *)JAZZ_HDC_LED = 1;
286#endif
287} 236}
288 237
289static struct scsi_host_template driver_template = { 238MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
290 .proc_name = "jazz_esp", 239MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
291 .proc_info = esp_proc_info, 240MODULE_LICENSE("GPL");
292 .name = "ESP 100/100a/200", 241MODULE_VERSION(DRV_VERSION);
293 .detect = jazz_esp_detect, 242
294 .slave_alloc = esp_slave_alloc, 243module_init(jazz_esp_init);
295 .slave_destroy = esp_slave_destroy, 244module_exit(jazz_esp_exit);
296 .release = jazz_esp_release,
297 .info = esp_info,
298 .queuecommand = esp_queue,
299 .eh_abort_handler = esp_abort,
300 .eh_bus_reset_handler = esp_reset,
301 .can_queue = 7,
302 .this_id = 7,
303 .sg_tablesize = SG_ALL,
304 .cmd_per_lun = 1,
305 .use_clustering = DISABLE_CLUSTERING,
306};
307#include "scsi_module.c"