aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/dec_esp.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2007-02-05 19:28:29 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-09 11:23:17 -0500
commit4df4db5c6c6daeb10a8693d09ce872bce8cd84e6 (patch)
tree7ec7632d88253f41c4b4a2faf0f404f661ed6f50 /drivers/scsi/dec_esp.c
parent335dc50cec2891026bd51e46769fc12365b6e475 (diff)
[TC] dec_esp: Driver model for the PMAZ-A
This is a set of changes that converts the PMAZ-A support to the driver model. The use of the driver model required switching to the hotplug SCSI initialization model, which in turn required a change to the core NCR53C9x driver. I decided not to break all the frontend drivers and introduced an additional parameter for esp_allocate() to select between the old and the new model. I hope this is OK, but I would be fine with converting NCR53C9x to the new model unconditionally as long as I do not have to fix all the other frontends (OK, perhaps I could do some of them ;-) ). Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: James Bottomley <James.Bottomley@steeleye.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/scsi/dec_esp.c')
-rw-r--r--drivers/scsi/dec_esp.c355
1 files changed, 232 insertions, 123 deletions
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index c29ccbc44693..d42ad663ffee 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -18,7 +18,7 @@
18 * 20001005 - Initialization fixes for 2.4.0-test9 18 * 20001005 - Initialization fixes for 2.4.0-test9
19 * Florian Lohoff <flo@rfc822.org> 19 * Florian Lohoff <flo@rfc822.org>
20 * 20 *
21 * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki 21 * Copyright (C) 2002, 2003, 2005, 2006 Maciej W. Rozycki
22 */ 22 */
23 23
24#include <linux/kernel.h> 24#include <linux/kernel.h>
@@ -30,6 +30,7 @@
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/stat.h> 32#include <linux/stat.h>
33#include <linux/tc.h>
33 34
34#include <asm/dma.h> 35#include <asm/dma.h>
35#include <asm/irq.h> 36#include <asm/irq.h>
@@ -42,7 +43,6 @@
42#include <asm/dec/ioasic_ints.h> 43#include <asm/dec/ioasic_ints.h>
43#include <asm/dec/machtype.h> 44#include <asm/dec/machtype.h>
44#include <asm/dec/system.h> 45#include <asm/dec/system.h>
45#include <asm/dec/tc.h>
46 46
47#define DEC_SCSI_SREG 0 47#define DEC_SCSI_SREG 0
48#define DEC_SCSI_DMAREG 0x40000 48#define DEC_SCSI_DMAREG 0x40000
@@ -98,51 +98,33 @@ static irqreturn_t scsi_dma_merr_int(int, void *);
98static irqreturn_t scsi_dma_err_int(int, void *); 98static irqreturn_t scsi_dma_err_int(int, void *);
99static irqreturn_t scsi_dma_int(int, void *); 99static irqreturn_t scsi_dma_int(int, void *);
100 100
101static int dec_esp_detect(struct scsi_host_template * tpnt); 101static struct scsi_host_template dec_esp_template = {
102 102 .module = THIS_MODULE,
103static int dec_esp_release(struct Scsi_Host *shost)
104{
105 if (shost->irq)
106 free_irq(shost->irq, NULL);
107 if (shost->io_port && shost->n_io_port)
108 release_region(shost->io_port, shost->n_io_port);
109 scsi_unregister(shost);
110 return 0;
111}
112
113static struct scsi_host_template driver_template = {
114 .proc_name = "dec_esp",
115 .proc_info = esp_proc_info,
116 .name = "NCR53C94", 103 .name = "NCR53C94",
117 .detect = dec_esp_detect,
118 .slave_alloc = esp_slave_alloc,
119 .slave_destroy = esp_slave_destroy,
120 .release = dec_esp_release,
121 .info = esp_info, 104 .info = esp_info,
122 .queuecommand = esp_queue, 105 .queuecommand = esp_queue,
123 .eh_abort_handler = esp_abort, 106 .eh_abort_handler = esp_abort,
124 .eh_bus_reset_handler = esp_reset, 107 .eh_bus_reset_handler = esp_reset,
108 .slave_alloc = esp_slave_alloc,
109 .slave_destroy = esp_slave_destroy,
110 .proc_info = esp_proc_info,
111 .proc_name = "dec_esp",
125 .can_queue = 7, 112 .can_queue = 7,
126 .this_id = 7,
127 .sg_tablesize = SG_ALL, 113 .sg_tablesize = SG_ALL,
128 .cmd_per_lun = 1, 114 .cmd_per_lun = 1,
129 .use_clustering = DISABLE_CLUSTERING, 115 .use_clustering = DISABLE_CLUSTERING,
130}; 116};
131 117
132 118static struct NCR_ESP *dec_esp_platform;
133#include "scsi_module.c"
134 119
135/***************************************************************** Detection */ 120/***************************************************************** Detection */
136static int dec_esp_detect(struct scsi_host_template * tpnt) 121static int dec_esp_platform_probe(void)
137{ 122{
138 struct NCR_ESP *esp; 123 struct NCR_ESP *esp;
139 struct ConfigDev *esp_dev; 124 int err = 0;
140 int slot;
141 unsigned long mem_start;
142 125
143 if (IOASIC) { 126 if (IOASIC) {
144 esp_dev = 0; 127 esp = esp_allocate(&dec_esp_template, NULL, 1);
145 esp = esp_allocate(tpnt, (void *) esp_dev);
146 128
147 /* Do command transfer with programmed I/O */ 129 /* Do command transfer with programmed I/O */
148 esp->do_pio_cmds = 1; 130 esp->do_pio_cmds = 1;
@@ -200,112 +182,175 @@ static int dec_esp_detect(struct scsi_host_template * tpnt)
200 /* Check for differential SCSI-bus */ 182 /* Check for differential SCSI-bus */
201 esp->diff = 0; 183 esp->diff = 0;
202 184
185 err = request_irq(esp->irq, esp_intr, IRQF_DISABLED,
186 "ncr53c94", esp->ehost);
187 if (err)
188 goto err_alloc;
189 err = request_irq(dec_interrupt[DEC_IRQ_ASC_MERR],
190 scsi_dma_merr_int, IRQF_DISABLED,
191 "ncr53c94 error", esp->ehost);
192 if (err)
193 goto err_irq;
194 err = request_irq(dec_interrupt[DEC_IRQ_ASC_ERR],
195 scsi_dma_err_int, IRQF_DISABLED,
196 "ncr53c94 overrun", esp->ehost);
197 if (err)
198 goto err_irq_merr;
199 err = request_irq(dec_interrupt[DEC_IRQ_ASC_DMA], scsi_dma_int,
200 IRQF_DISABLED, "ncr53c94 dma", esp->ehost);
201 if (err)
202 goto err_irq_err;
203
203 esp_initialize(esp); 204 esp_initialize(esp);
204 205
205 if (request_irq(esp->irq, esp_intr, IRQF_DISABLED, 206 err = scsi_add_host(esp->ehost, NULL);
206 "ncr53c94", esp->ehost)) 207 if (err) {
207 goto err_dealloc; 208 printk(KERN_ERR "ESP: Unable to register adapter\n");
208 if (request_irq(dec_interrupt[DEC_IRQ_ASC_MERR], 209 goto err_irq_dma;
209 scsi_dma_merr_int, IRQF_DISABLED, 210 }
210 "ncr53c94 error", esp->ehost)) 211
211 goto err_free_irq; 212 scsi_scan_host(esp->ehost);
212 if (request_irq(dec_interrupt[DEC_IRQ_ASC_ERR],
213 scsi_dma_err_int, IRQF_DISABLED,
214 "ncr53c94 overrun", esp->ehost))
215 goto err_free_irq_merr;
216 if (request_irq(dec_interrupt[DEC_IRQ_ASC_DMA],
217 scsi_dma_int, IRQF_DISABLED,
218 "ncr53c94 dma", esp->ehost))
219 goto err_free_irq_err;
220 213
214 dec_esp_platform = esp;
221 } 215 }
222 216
223 if (TURBOCHANNEL) { 217 return 0;
224 while ((slot = search_tc_card("PMAZ-AA")) >= 0) { 218
225 claim_tc_card(slot); 219err_irq_dma:
226 220 free_irq(dec_interrupt[DEC_IRQ_ASC_DMA], esp->ehost);
227 esp_dev = 0; 221err_irq_err:
228 esp = esp_allocate(tpnt, (void *) esp_dev); 222 free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], esp->ehost);
229 223err_irq_merr:
230 mem_start = get_tc_base_addr(slot); 224 free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], esp->ehost);
231 225err_irq:
232 /* Store base addr into esp struct */ 226 free_irq(esp->irq, esp->ehost);
233 esp->slot = CPHYSADDR(mem_start); 227err_alloc:
234 228 esp_deallocate(esp);
235 esp->dregs = 0; 229 scsi_host_put(esp->ehost);
236 esp->eregs = (void *)CKSEG1ADDR(mem_start + 230 return err;
237 DEC_SCSI_SREG); 231}
238 esp->do_pio_cmds = 1; 232
239 233static int __init dec_esp_probe(struct device *dev)
240 /* Set the command buffer */ 234{
241 esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer; 235 struct NCR_ESP *esp;
242 236 resource_size_t start, len;
243 /* get virtual dma address for command buffer */ 237 int err;
244 esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer); 238
245 239 esp = esp_allocate(&dec_esp_template, NULL, 1);
246 esp->cfreq = get_tc_speed(); 240
247 241 dev_set_drvdata(dev, esp);
248 esp->irq = get_tc_irq_nr(slot); 242
249 243 start = to_tc_dev(dev)->resource.start;
250 /* Required functions */ 244 len = to_tc_dev(dev)->resource.end - start + 1;
251 esp->dma_bytes_sent = &dma_bytes_sent; 245
252 esp->dma_can_transfer = &dma_can_transfer; 246 if (!request_mem_region(start, len, dev->bus_id)) {
253 esp->dma_dump_state = &dma_dump_state; 247 printk(KERN_ERR "%s: Unable to reserve MMIO resource\n",
254 esp->dma_init_read = &pmaz_dma_init_read; 248 dev->bus_id);
255 esp->dma_init_write = &pmaz_dma_init_write; 249 err = -EBUSY;
256 esp->dma_ints_off = &pmaz_dma_ints_off; 250 goto err_alloc;
257 esp->dma_ints_on = &pmaz_dma_ints_on;
258 esp->dma_irq_p = &dma_irq_p;
259 esp->dma_ports_p = &dma_ports_p;
260 esp->dma_setup = &pmaz_dma_setup;
261
262 /* Optional functions */
263 esp->dma_barrier = 0;
264 esp->dma_drain = &pmaz_dma_drain;
265 esp->dma_invalidate = 0;
266 esp->dma_irq_entry = 0;
267 esp->dma_irq_exit = 0;
268 esp->dma_poll = 0;
269 esp->dma_reset = 0;
270 esp->dma_led_off = 0;
271 esp->dma_led_on = 0;
272
273 esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
274 esp->dma_mmu_get_scsi_sgl = 0;
275 esp->dma_mmu_release_scsi_one = 0;
276 esp->dma_mmu_release_scsi_sgl = 0;
277 esp->dma_advance_sg = 0;
278
279 if (request_irq(esp->irq, esp_intr, IRQF_DISABLED,
280 "PMAZ_AA", esp->ehost)) {
281 esp_deallocate(esp);
282 release_tc_card(slot);
283 continue;
284 }
285 esp->scsi_id = 7;
286 esp->diff = 0;
287 esp_initialize(esp);
288 }
289 } 251 }
290 252
291 if(nesps) { 253 /* Store base addr into esp struct. */
292 printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); 254 esp->slot = start;
293 esps_running = esps_in_use; 255
294 return esps_in_use; 256 esp->dregs = 0;
257 esp->eregs = (void *)CKSEG1ADDR(start + DEC_SCSI_SREG);
258 esp->do_pio_cmds = 1;
259
260 /* Set the command buffer. */
261 esp->esp_command = (volatile unsigned char *)pmaz_cmd_buffer;
262
263 /* Get virtual dma address for command buffer. */
264 esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer);
265
266 esp->cfreq = tc_get_speed(to_tc_dev(dev)->bus);
267
268 esp->irq = to_tc_dev(dev)->interrupt;
269
270 /* Required functions. */
271 esp->dma_bytes_sent = &dma_bytes_sent;
272 esp->dma_can_transfer = &dma_can_transfer;
273 esp->dma_dump_state = &dma_dump_state;
274 esp->dma_init_read = &pmaz_dma_init_read;
275 esp->dma_init_write = &pmaz_dma_init_write;
276 esp->dma_ints_off = &pmaz_dma_ints_off;
277 esp->dma_ints_on = &pmaz_dma_ints_on;
278 esp->dma_irq_p = &dma_irq_p;
279 esp->dma_ports_p = &dma_ports_p;
280 esp->dma_setup = &pmaz_dma_setup;
281
282 /* Optional functions. */
283 esp->dma_barrier = 0;
284 esp->dma_drain = &pmaz_dma_drain;
285 esp->dma_invalidate = 0;
286 esp->dma_irq_entry = 0;
287 esp->dma_irq_exit = 0;
288 esp->dma_poll = 0;
289 esp->dma_reset = 0;
290 esp->dma_led_off = 0;
291 esp->dma_led_on = 0;
292
293 esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
294 esp->dma_mmu_get_scsi_sgl = 0;
295 esp->dma_mmu_release_scsi_one = 0;
296 esp->dma_mmu_release_scsi_sgl = 0;
297 esp->dma_advance_sg = 0;
298
299 err = request_irq(esp->irq, esp_intr, IRQF_DISABLED, "PMAZ_AA",
300 esp->ehost);
301 if (err) {
302 printk(KERN_ERR "%s: Unable to get IRQ %d\n",
303 dev->bus_id, esp->irq);
304 goto err_resource;
305 }
306
307 esp->scsi_id = 7;
308 esp->diff = 0;
309 esp_initialize(esp);
310
311 err = scsi_add_host(esp->ehost, dev);
312 if (err) {
313 printk(KERN_ERR "%s: Unable to register adapter\n",
314 dev->bus_id);
315 goto err_irq;
295 } 316 }
317
318 scsi_scan_host(esp->ehost);
319
296 return 0; 320 return 0;
297 321
298err_free_irq_err: 322err_irq:
299 free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], scsi_dma_err_int); 323 free_irq(esp->irq, esp->ehost);
300err_free_irq_merr: 324
301 free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], scsi_dma_merr_int); 325err_resource:
302err_free_irq: 326 release_mem_region(start, len);
303 free_irq(esp->irq, esp_intr); 327
304err_dealloc: 328err_alloc:
305 esp_deallocate(esp); 329 esp_deallocate(esp);
306 return 0; 330 scsi_host_put(esp->ehost);
331 return err;
332}
333
334static void __exit dec_esp_platform_remove(void)
335{
336 struct NCR_ESP *esp = dec_esp_platform;
337
338 free_irq(esp->irq, esp->ehost);
339 esp_deallocate(esp);
340 scsi_host_put(esp->ehost);
341 dec_esp_platform = NULL;
307} 342}
308 343
344static void __exit dec_esp_remove(struct device *dev)
345{
346 struct NCR_ESP *esp = dev_get_drvdata(dev);
347
348 free_irq(esp->irq, esp->ehost);
349 esp_deallocate(esp);
350 scsi_host_put(esp->ehost);
351}
352
353
309/************************************************************* DMA Functions */ 354/************************************************************* DMA Functions */
310static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id) 355static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id)
311{ 356{
@@ -576,3 +621,67 @@ static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp
576{ 621{
577 sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer); 622 sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
578} 623}
624
625
626#ifdef CONFIG_TC
627static int __init dec_esp_tc_probe(struct device *dev);
628static int __exit dec_esp_tc_remove(struct device *dev);
629
630static const struct tc_device_id dec_esp_tc_table[] = {
631 { "DEC ", "PMAZ-AA " },
632 { }
633};
634MODULE_DEVICE_TABLE(tc, dec_esp_tc_table);
635
636static struct tc_driver dec_esp_tc_driver = {
637 .id_table = dec_esp_tc_table,
638 .driver = {
639 .name = "dec_esp",
640 .bus = &tc_bus_type,
641 .probe = dec_esp_tc_probe,
642 .remove = __exit_p(dec_esp_tc_remove),
643 },
644};
645
646static int __init dec_esp_tc_probe(struct device *dev)
647{
648 int status = dec_esp_probe(dev);
649 if (!status)
650 get_device(dev);
651 return status;
652}
653
654static int __exit dec_esp_tc_remove(struct device *dev)
655{
656 put_device(dev);
657 dec_esp_remove(dev);
658 return 0;
659}
660#endif
661
662static int __init dec_esp_init(void)
663{
664 int status;
665
666 status = tc_register_driver(&dec_esp_tc_driver);
667 if (!status)
668 dec_esp_platform_probe();
669
670 if (nesps) {
671 pr_info("ESP: Total of %d ESP hosts found, "
672 "%d actually in use.\n", nesps, esps_in_use);
673 esps_running = esps_in_use;
674 }
675
676 return status;
677}
678
679static void __exit dec_esp_exit(void)
680{
681 dec_esp_platform_remove();
682 tc_unregister_driver(&dec_esp_tc_driver);
683}
684
685
686module_init(dec_esp_init);
687module_exit(dec_esp_exit);