]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/scsi/sun3_scsi.c
sun3_scsi: Move macro definitions
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / sun3_scsi.c
CommitLineData
1da177e4
LT
1/*
2 * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl)
3 *
4 * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net)
5 *
757f5bad
FT
6 * VME support added by Sam Creasey
7 *
8 * TODO: modify this driver to support multiple Sun3 SCSI VME boards
9 *
1da177e4
LT
10 * Adapted from mac_scsinew.c:
11 */
12/*
13 * Generic Macintosh NCR5380 driver
14 *
15 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
16 *
17 * derived in part from:
18 */
19/*
20 * Generic Generic NCR5380 driver
21 *
22 * Copyright 1995, Russell King
1da177e4
LT
23 */
24
1da177e4 25#include <linux/types.h>
1da177e4 26#include <linux/delay.h>
1da177e4 27#include <linux/module.h>
1da177e4
LT
28#include <linux/ioport.h>
29#include <linux/init.h>
30#include <linux/blkdev.h>
0d31f875 31#include <linux/platform_device.h>
1da177e4
LT
32
33#include <asm/io.h>
1da177e4 34#include <asm/dvma.h>
1da177e4 35
1da177e4
LT
36#include <scsi/scsi_host.h>
37#include "sun3_scsi.h"
1da177e4 38
2231ef87 39/* Definitions for the core NCR5380 driver. */
1da177e4 40
2231ef87
FT
41#define REAL_DMA
42#define RESET_RUN_DONE
1da177e4
LT
43/* #define SUPPORT_TAGS */
44
2231ef87
FT
45/* #define MAX_TAGS 32 */
46
47#define NCR5380_implementation_fields /* none */
48
49#define NCR5380_read(reg) sun3scsi_read(reg)
50#define NCR5380_write(reg, value) sun3scsi_write(reg, value)
51
52#define NCR5380_queue_command sun3scsi_queue_command
53#define NCR5380_bus_reset sun3scsi_bus_reset
54#define NCR5380_abort sun3scsi_abort
55#define NCR5380_show_info sun3scsi_show_info
56#define NCR5380_info sun3scsi_info
57
58#define NCR5380_dma_read_setup(instance, data, count) \
59 sun3scsi_dma_setup(data, count, 0)
60#define NCR5380_dma_write_setup(instance, data, count) \
61 sun3scsi_dma_setup(data, count, 1)
62#define NCR5380_dma_residual(instance) \
63 sun3scsi_dma_residual(instance)
64#define NCR5380_dma_xfer_len(instance, cmd, phase) \
65 sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
66
67#include "NCR5380.h"
68
69
70extern int sun3_map_test(unsigned long, char *);
71
757f5bad
FT
72#ifdef SUN3_SCSI_VME
73#define ENABLE_IRQ()
74#else
1da177e4 75#define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI );
757f5bad 76#endif
1da177e4
LT
77
78
1da177e4
LT
79static int setup_can_queue = -1;
80module_param(setup_can_queue, int, 0);
81static int setup_cmd_per_lun = -1;
82module_param(setup_cmd_per_lun, int, 0);
83static int setup_sg_tablesize = -1;
84module_param(setup_sg_tablesize, int, 0);
85#ifdef SUPPORT_TAGS
86static int setup_use_tagged_queuing = -1;
87module_param(setup_use_tagged_queuing, int, 0);
88#endif
89static int setup_hostid = -1;
90module_param(setup_hostid, int, 0);
91
2231ef87 92/* #define RESET_BOOT */
2b0f834c 93
1da177e4
LT
94#define AFTER_RESET_DELAY (HZ/2)
95
96/* ms to wait after hitting dma regs */
97#define SUN3_DMA_DELAY 10
98
99/* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
100#define SUN3_DVMA_BUFSIZE 0xe000
101
102/* minimum number of bytes to do dma on */
103#define SUN3_DMA_MINSIZE 128
104
2231ef87 105static struct scsi_cmnd *sun3_dma_setup_done;
0d31f875 106static unsigned char *sun3_scsi_regp;
1da177e4 107static volatile struct sun3_dma_regs *dregs;
0d31f875 108static struct sun3_udc_regs *udc_regs;
1da177e4
LT
109static unsigned char *sun3_dma_orig_addr = NULL;
110static unsigned long sun3_dma_orig_count = 0;
111static int sun3_dma_active = 0;
112static unsigned long last_residual = 0;
0d31f875 113static struct Scsi_Host *default_instance;
1da177e4
LT
114
115/*
116 * NCR 5380 register access functions
117 */
118
119static inline unsigned char sun3scsi_read(int reg)
120{
0d31f875 121 return in_8(sun3_scsi_regp + reg);
1da177e4
LT
122}
123
124static inline void sun3scsi_write(int reg, int value)
125{
0d31f875 126 out_8(sun3_scsi_regp + reg, value);
1da177e4
LT
127}
128
757f5bad 129#ifndef SUN3_SCSI_VME
1da177e4
LT
130/* dma controller register access functions */
131
132static inline unsigned short sun3_udc_read(unsigned char reg)
133{
134 unsigned short ret;
135
136 dregs->udc_addr = UDC_CSR;
137 udelay(SUN3_DMA_DELAY);
138 ret = dregs->udc_data;
139 udelay(SUN3_DMA_DELAY);
140
141 return ret;
142}
143
144static inline void sun3_udc_write(unsigned short val, unsigned char reg)
145{
146 dregs->udc_addr = reg;
147 udelay(SUN3_DMA_DELAY);
148 dregs->udc_data = val;
149 udelay(SUN3_DMA_DELAY);
150}
757f5bad 151#endif
1da177e4 152
1da177e4 153#ifdef RESET_BOOT
1da177e4
LT
154static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
155{
156 unsigned long end;
1da177e4
LT
157
158 /*
159 * Do a SCSI reset to clean up the bus during initialization. No
160 * messing with the queues, interrupts, or locks necessary here.
161 */
162
163 printk( "Sun3 SCSI: resetting the SCSI bus..." );
164
165 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
166// sun3_disable_irq( IRQ_SUN3_SCSI );
167
168 /* get in phase */
169 NCR5380_write( TARGET_COMMAND_REG,
170 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
171
172 /* assert RST */
173 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
174
175 /* The min. reset hold time is 25us, so 40us should be enough */
176 udelay( 50 );
177
178 /* reset RST and interrupt */
179 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
180 NCR5380_read( RESET_PARITY_INTERRUPT_REG );
181
182 for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
183 barrier();
184
185 /* switch on SCSI IRQ again */
186// sun3_enable_irq( IRQ_SUN3_SCSI );
187
188 printk( " done\n" );
189}
190#endif
191
1da177e4
LT
192// safe bits for the CSR
193#define CSR_GOOD 0x060f
194
7d12e780 195static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
1da177e4
LT
196{
197 unsigned short csr = dregs->csr;
198 int handled = 0;
199
757f5bad
FT
200#ifdef SUN3_SCSI_VME
201 dregs->csr &= ~CSR_DMA_ENABLE;
202#endif
203
1da177e4
LT
204 if(csr & ~CSR_GOOD) {
205 if(csr & CSR_DMA_BUSERR) {
206 printk("scsi%d: bus error in dma\n", default_instance->host_no);
207 }
208
209 if(csr & CSR_DMA_CONFLICT) {
210 printk("scsi%d: dma conflict\n", default_instance->host_no);
211 }
212 handled = 1;
213 }
214
215 if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
7d12e780 216 NCR5380_intr(irq, dummy);
1da177e4
LT
217 handled = 1;
218 }
219
220 return IRQ_RETVAL(handled);
221}
222
223/*
224 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
225 * reentering NCR5380_print_status seems to have ugly side effects
226 */
227
228/* this doesn't seem to get used at all -- sam */
229#if 0
230void sun3_sun3_debug (void)
231{
232 unsigned long flags;
1da177e4
LT
233
234 if (default_instance) {
235 local_irq_save(flags);
236 NCR5380_print_status(default_instance);
237 local_irq_restore(flags);
238 }
239}
240#endif
241
242
243/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
244static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag)
245{
1da177e4
LT
246 void *addr;
247
248 if(sun3_dma_orig_addr != NULL)
249 dvma_unmap(sun3_dma_orig_addr);
250
757f5bad
FT
251#ifdef SUN3_SCSI_VME
252 addr = (void *)dvma_map_vme((unsigned long) data, count);
253#else
1da177e4 254 addr = (void *)dvma_map((unsigned long) data, count);
757f5bad 255#endif
1da177e4
LT
256
257 sun3_dma_orig_addr = addr;
258 sun3_dma_orig_count = count;
757f5bad
FT
259
260#ifndef SUN3_SCSI_VME
1da177e4
LT
261 dregs->fifo_count = 0;
262 sun3_udc_write(UDC_RESET, UDC_CSR);
263
264 /* reset fifo */
265 dregs->csr &= ~CSR_FIFO;
266 dregs->csr |= CSR_FIFO;
757f5bad 267#endif
1da177e4
LT
268
269 /* set direction */
270 if(write_flag)
271 dregs->csr |= CSR_SEND;
272 else
273 dregs->csr &= ~CSR_SEND;
274
757f5bad
FT
275#ifdef SUN3_SCSI_VME
276 dregs->csr |= CSR_PACK_ENABLE;
277
278 dregs->dma_addr_hi = ((unsigned long)addr >> 16);
279 dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
280
281 dregs->dma_count_hi = 0;
282 dregs->dma_count_lo = 0;
283 dregs->fifo_count_hi = 0;
284 dregs->fifo_count = 0;
285#else
1da177e4
LT
286 /* byte count for fifo */
287 dregs->fifo_count = count;
288
289 sun3_udc_write(UDC_RESET, UDC_CSR);
290
291 /* reset fifo */
292 dregs->csr &= ~CSR_FIFO;
293 dregs->csr |= CSR_FIFO;
294
295 if(dregs->fifo_count != count) {
296 printk("scsi%d: fifo_mismatch %04x not %04x\n",
297 default_instance->host_no, dregs->fifo_count,
298 (unsigned int) count);
d614f068 299 NCR5380_dprint(NDEBUG_DMA, default_instance);
1da177e4
LT
300 }
301
302 /* setup udc */
1da177e4
LT
303 udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8);
304 udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff);
1da177e4
LT
305 udc_regs->count = count/2; /* count in words */
306 udc_regs->mode_hi = UDC_MODE_HIWORD;
307 if(write_flag) {
308 if(count & 1)
309 udc_regs->count++;
310 udc_regs->mode_lo = UDC_MODE_LSEND;
311 udc_regs->rsel = UDC_RSEL_SEND;
312 } else {
313 udc_regs->mode_lo = UDC_MODE_LRECV;
314 udc_regs->rsel = UDC_RSEL_RECV;
315 }
316
317 /* announce location of regs block */
318 sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8),
319 UDC_CHN_HI);
320
321 sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO);
322
323 /* set dma master on */
324 sun3_udc_write(0xd, UDC_MODE);
325
326 /* interrupt enable */
327 sun3_udc_write(UDC_INT_ENABLE, UDC_CSR);
757f5bad 328#endif
1da177e4
LT
329
330 return count;
331
332}
333
757f5bad 334#ifndef SUN3_SCSI_VME
1da177e4
LT
335static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance)
336{
337 unsigned short resid;
338
339 dregs->udc_addr = 0x32;
340 udelay(SUN3_DMA_DELAY);
341 resid = dregs->udc_data;
342 udelay(SUN3_DMA_DELAY);
343 resid *= 2;
344
345 return (unsigned long) resid;
346}
757f5bad 347#endif
1da177e4
LT
348
349static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
350{
351 return last_residual;
352}
353
811c9366
HK
354static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted,
355 struct scsi_cmnd *cmd,
356 int write_flag)
1da177e4 357{
33659ebb 358 if (cmd->request->cmd_type == REQ_TYPE_FS)
1da177e4
LT
359 return wanted;
360 else
361 return 0;
362}
363
364static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
365{
757f5bad
FT
366#ifdef SUN3_SCSI_VME
367 unsigned short csr;
368
369 csr = dregs->csr;
370
371 dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
372 dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
1da177e4 373
757f5bad
FT
374 dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
375 dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
376
377/* if(!(csr & CSR_DMA_ENABLE))
378 * dregs->csr |= CSR_DMA_ENABLE;
379 */
380#else
1da177e4 381 sun3_udc_write(UDC_CHN_START, UDC_CSR);
757f5bad 382#endif
1da177e4
LT
383
384 return 0;
385}
386
387/* clean up after our dma is done */
388static int sun3scsi_dma_finish(int write_flag)
389{
757f5bad 390 unsigned short __maybe_unused count;
1da177e4
LT
391 unsigned short fifo;
392 int ret = 0;
393
394 sun3_dma_active = 0;
757f5bad
FT
395
396#ifdef SUN3_SCSI_VME
397 dregs->csr &= ~CSR_DMA_ENABLE;
398
399 fifo = dregs->fifo_count;
400 if (write_flag) {
401 if ((fifo > 0) && (fifo < sun3_dma_orig_count))
402 fifo++;
403 }
404
405 last_residual = fifo;
406 /* empty bytes from the fifo which didn't make it */
407 if ((!write_flag) && (dregs->csr & CSR_LEFT)) {
408 unsigned char *vaddr;
409
410 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
411
412 vaddr += (sun3_dma_orig_count - fifo);
413 vaddr--;
414
415 switch (dregs->csr & CSR_LEFT) {
416 case CSR_LEFT_3:
417 *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
418 vaddr--;
419
420 case CSR_LEFT_2:
421 *vaddr = (dregs->bpack_hi & 0x00ff);
422 vaddr--;
423
424 case CSR_LEFT_1:
425 *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
426 break;
427 }
428 }
429#else
1da177e4
LT
430 // check to empty the fifo on a read
431 if(!write_flag) {
432 int tmo = 20000; /* .2 sec */
433
434 while(1) {
435 if(dregs->csr & CSR_FIFO_EMPTY)
436 break;
437
438 if(--tmo <= 0) {
439 printk("sun3scsi: fifo failed to empty!\n");
440 return 1;
441 }
442 udelay(10);
443 }
444 }
1da177e4
LT
445
446 count = sun3scsi_dma_count(default_instance);
1da177e4
LT
447
448 fifo = dregs->fifo_count;
449 last_residual = fifo;
450
451 /* empty bytes from the fifo which didn't make it */
452 if((!write_flag) && (count - fifo) == 2) {
453 unsigned short data;
454 unsigned char *vaddr;
455
456 data = dregs->fifo_data;
457 vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
458
459 vaddr += (sun3_dma_orig_count - fifo);
460
461 vaddr[-2] = (data & 0xff00) >> 8;
462 vaddr[-1] = (data & 0xff);
463 }
757f5bad 464#endif
1da177e4
LT
465
466 dvma_unmap(sun3_dma_orig_addr);
467 sun3_dma_orig_addr = NULL;
757f5bad
FT
468
469#ifdef SUN3_SCSI_VME
470 dregs->dma_addr_hi = 0;
471 dregs->dma_addr_lo = 0;
472 dregs->dma_count_hi = 0;
473 dregs->dma_count_lo = 0;
474
475 dregs->fifo_count = 0;
476 dregs->fifo_count_hi = 0;
477
478 dregs->csr &= ~CSR_SEND;
479/* dregs->csr |= CSR_DMA_ENABLE; */
480#else
1da177e4
LT
481 sun3_udc_write(UDC_RESET, UDC_CSR);
482 dregs->fifo_count = 0;
483 dregs->csr &= ~CSR_SEND;
484
485 /* reset fifo */
486 dregs->csr &= ~CSR_FIFO;
487 dregs->csr |= CSR_FIFO;
757f5bad 488#endif
1da177e4
LT
489
490 sun3_dma_setup_done = NULL;
491
492 return ret;
493
494}
495
496#include "sun3_NCR5380.c"
497
0d31f875
FT
498#ifdef SUN3_SCSI_VME
499#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI"
500#define DRV_MODULE_NAME "sun3_scsi_vme"
501#else
502#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI"
503#define DRV_MODULE_NAME "sun3_scsi"
504#endif
505
506#define PFX DRV_MODULE_NAME ": "
507
508static struct scsi_host_template sun3_scsi_template = {
509 .module = THIS_MODULE,
510 .proc_name = DRV_MODULE_NAME,
9dcc26cf 511 .show_info = sun3scsi_show_info,
1da177e4 512 .name = SUN3_SCSI_NAME,
1da177e4
LT
513 .info = sun3scsi_info,
514 .queuecommand = sun3scsi_queue_command,
515 .eh_abort_handler = sun3scsi_abort,
516 .eh_bus_reset_handler = sun3scsi_bus_reset,
d572f65f 517 .can_queue = 16,
1da177e4 518 .this_id = 7,
d572f65f
FT
519 .sg_tablesize = SG_NONE,
520 .cmd_per_lun = 2,
1da177e4
LT
521 .use_clustering = DISABLE_CLUSTERING
522};
523
0d31f875
FT
524static int __init sun3_scsi_probe(struct platform_device *pdev)
525{
526 struct Scsi_Host *instance;
527 int error;
528 struct resource *irq, *mem;
529 unsigned char *ioaddr;
530#ifdef SUN3_SCSI_VME
531 int i;
532#endif
533
534 if (setup_can_queue > 0)
535 sun3_scsi_template.can_queue = setup_can_queue;
536 if (setup_cmd_per_lun > 0)
537 sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun;
538 if (setup_sg_tablesize >= 0)
539 sun3_scsi_template.sg_tablesize = setup_sg_tablesize;
540 if (setup_hostid >= 0)
541 sun3_scsi_template.this_id = setup_hostid & 7;
542
543#ifdef SUPPORT_TAGS
544 if (setup_use_tagged_queuing < 0)
545 setup_use_tagged_queuing = 1;
546#endif
547
548#ifdef SUN3_SCSI_VME
549 ioaddr = NULL;
550 for (i = 0; i < 2; i++) {
551 unsigned char x;
552
553 irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
554 mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
555 if (!irq || !mem)
556 break;
557
558 ioaddr = sun3_ioremap(mem->start, resource_size(mem),
559 SUN3_PAGE_TYPE_VME16);
560 dregs = (struct sun3_dma_regs *)(ioaddr + 8);
561
562 if (sun3_map_test((unsigned long)dregs, &x)) {
563 unsigned short oldcsr;
564
565 oldcsr = dregs->csr;
566 dregs->csr = 0;
567 udelay(SUN3_DMA_DELAY);
568 if (dregs->csr == 0x1400)
569 break;
570
571 dregs->csr = oldcsr;
572 }
573
574 iounmap(ioaddr);
575 ioaddr = NULL;
576 }
577 if (!ioaddr)
578 return -ENODEV;
579#else
580 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
581 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
582 if (!irq || !mem)
583 return -ENODEV;
584
585 ioaddr = ioremap(mem->start, resource_size(mem));
586 dregs = (struct sun3_dma_regs *)(ioaddr + 8);
587
588 udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs));
589 if (!udc_regs) {
590 pr_err(PFX "couldn't allocate DVMA memory!\n");
591 iounmap(ioaddr);
592 return -ENOMEM;
593 }
594#endif
595
596 sun3_scsi_regp = ioaddr;
597
598 instance = scsi_host_alloc(&sun3_scsi_template,
599 sizeof(struct NCR5380_hostdata));
600 if (!instance) {
601 error = -ENOMEM;
602 goto fail_alloc;
603 }
604 default_instance = instance;
605
606 instance->io_port = (unsigned long)ioaddr;
607 instance->irq = irq->start;
608
609 NCR5380_init(instance, 0);
610
611 error = request_irq(instance->irq, scsi_sun3_intr, 0,
612 "NCR5380", instance);
613 if (error) {
614#ifdef REAL_DMA
615 pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n",
616 instance->host_no, instance->irq);
617 goto fail_irq;
618#else
619 pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n",
620 instance->host_no, instance->irq);
621 instance->irq = NO_IRQ;
622#endif
623 }
624
625 dregs->csr = 0;
626 udelay(SUN3_DMA_DELAY);
627 dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
628 udelay(SUN3_DMA_DELAY);
629 dregs->fifo_count = 0;
630#ifdef SUN3_SCSI_VME
631 dregs->fifo_count_hi = 0;
632 dregs->dma_addr_hi = 0;
633 dregs->dma_addr_lo = 0;
634 dregs->dma_count_hi = 0;
635 dregs->dma_count_lo = 0;
636
637 dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
638#endif
639
640#ifdef RESET_BOOT
641 sun3_scsi_reset_boot(instance);
642#endif
643
644 error = scsi_add_host(instance, NULL);
645 if (error)
646 goto fail_host;
647
648 platform_set_drvdata(pdev, instance);
649
650 scsi_scan_host(instance);
651 return 0;
652
653fail_host:
654 if (instance->irq != NO_IRQ)
655 free_irq(instance->irq, instance);
656fail_irq:
657 NCR5380_exit(instance);
658 scsi_host_put(instance);
659fail_alloc:
660 if (udc_regs)
661 dvma_free(udc_regs);
662 iounmap(sun3_scsi_regp);
663 return error;
664}
665
666static int __exit sun3_scsi_remove(struct platform_device *pdev)
667{
668 struct Scsi_Host *instance = platform_get_drvdata(pdev);
669
670 scsi_remove_host(instance);
671 if (instance->irq != NO_IRQ)
672 free_irq(instance->irq, instance);
673 NCR5380_exit(instance);
674 scsi_host_put(instance);
675 if (udc_regs)
676 dvma_free(udc_regs);
677 iounmap(sun3_scsi_regp);
678 return 0;
679}
680
681static struct platform_driver sun3_scsi_driver = {
682 .remove = __exit_p(sun3_scsi_remove),
683 .driver = {
684 .name = DRV_MODULE_NAME,
685 .owner = THIS_MODULE,
686 },
687};
1da177e4 688
0d31f875 689module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe);
1da177e4 690
0d31f875 691MODULE_ALIAS("platform:" DRV_MODULE_NAME);
1da177e4 692MODULE_LICENSE("GPL");