]> git.karo-electronics.de Git - linux-beck.git/blob - drivers/scsi/sun3_scsi_vme.c
scsi/NCR5380: fix and standardize NDEBUG macros
[linux-beck.git] / drivers / scsi / sun3_scsi_vme.c
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  *
6  * VME support added by Sam Creasey
7  *
8  * Adapted from sun3_scsi.c -- see there for other headers
9  *
10  * TODO: modify this driver to support multiple Sun3 SCSI VME boards
11  *
12  */
13
14 #define AUTOSENSE
15
16 #include <linux/types.h>
17 #include <linux/stddef.h>
18 #include <linux/ctype.h>
19 #include <linux/delay.h>
20
21 #include <linux/module.h>
22 #include <linux/signal.h>
23 #include <linux/ioport.h>
24 #include <linux/init.h>
25 #include <linux/blkdev.h>
26
27 #include <asm/io.h>
28
29 #include <asm/sun3ints.h>
30 #include <asm/dvma.h>
31 #include <asm/idprom.h>
32 #include <asm/machines.h>
33
34 #define SUN3_SCSI_VME
35
36 #undef SUN3_SCSI_DEBUG
37
38 /* dma on! */
39 #define REAL_DMA
40
41 #include "scsi.h"
42 #include "initio.h"
43 #include <scsi/scsi_host.h>
44 #include "sun3_scsi.h"
45
46 extern int sun3_map_test(unsigned long, char *);
47
48 #define USE_WRAPPER
49 /*#define RESET_BOOT */
50 #define DRIVER_SETUP
51
52 /*
53  * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
54  */
55 #ifdef BUG
56 #undef RESET_BOOT
57 #undef DRIVER_SETUP
58 #endif
59
60 /* #define SUPPORT_TAGS */
61
62 //#define       ENABLE_IRQ()    enable_irq( SUN3_VEC_VMESCSI0 ); 
63 #define ENABLE_IRQ()
64
65
66 static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
67 static inline unsigned char sun3scsi_read(int reg);
68 static inline void sun3scsi_write(int reg, int value);
69
70 static int setup_can_queue = -1;
71 module_param(setup_can_queue, int, 0);
72 static int setup_cmd_per_lun = -1;
73 module_param(setup_cmd_per_lun, int, 0);
74 static int setup_sg_tablesize = -1;
75 module_param(setup_sg_tablesize, int, 0);
76 #ifdef SUPPORT_TAGS
77 static int setup_use_tagged_queuing = -1;
78 module_param(setup_use_tagged_queuing, int, 0);
79 #endif
80 static int setup_hostid = -1;
81 module_param(setup_hostid, int, 0);
82
83 static struct scsi_cmnd *sun3_dma_setup_done = NULL;
84
85 #define AFTER_RESET_DELAY       (HZ/2)
86
87 /* ms to wait after hitting dma regs */
88 #define SUN3_DMA_DELAY 10
89
90 /* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
91 #define SUN3_DVMA_BUFSIZE 0xe000
92
93 /* minimum number of bytes to do dma on */
94 #define SUN3_DMA_MINSIZE 128
95
96 static volatile unsigned char *sun3_scsi_regp;
97 static volatile struct sun3_dma_regs *dregs;
98 #ifdef OLDDMA
99 static unsigned char *dmabuf = NULL; /* dma memory buffer */
100 #endif
101 static unsigned char *sun3_dma_orig_addr = NULL;
102 static unsigned long sun3_dma_orig_count = 0;
103 static int sun3_dma_active = 0;
104 static unsigned long last_residual = 0;
105
106 /*
107  * NCR 5380 register access functions
108  */
109
110 static inline unsigned char sun3scsi_read(int reg)
111 {
112         return( sun3_scsi_regp[reg] );
113 }
114
115 static inline void sun3scsi_write(int reg, int value)
116 {
117         sun3_scsi_regp[reg] = value;
118 }
119
120 /*
121  * XXX: status debug
122  */
123 static struct Scsi_Host *default_instance;
124
125 /*
126  * Function : int sun3scsi_detect(struct scsi_host_template * tpnt)
127  *
128  * Purpose : initializes mac NCR5380 driver based on the
129  *      command line / compile time port and irq definitions.
130  *
131  * Inputs : tpnt - template for this SCSI adapter.
132  *
133  * Returns : 1 if a host adapter was found, 0 if not.
134  *
135  */
136  
137 static int __init sun3scsi_detect(struct scsi_host_template * tpnt)
138 {
139         unsigned long ioaddr, irq = 0;
140         static int called = 0;
141         struct Scsi_Host *instance;
142         int i;
143         unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI, 
144                                    IOBASE_SUN3_VMESCSI + 0x4000,
145                                    0 };
146         unsigned long vecs[3] = { SUN3_VEC_VMESCSI0,
147                                   SUN3_VEC_VMESCSI1,
148                                   0 };
149         /* check that this machine has an onboard 5380 */
150         switch(idprom->id_machtype) {
151         case SM_SUN3|SM_3_160:
152         case SM_SUN3|SM_3_260:
153                 break;
154
155         default:
156                 return 0;
157         }
158
159         if(called)
160                 return 0;
161
162         tpnt->proc_name = "Sun3 5380 VME SCSI";
163
164         /* setup variables */
165         tpnt->can_queue =
166                 (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
167         tpnt->cmd_per_lun =
168                 (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
169         tpnt->sg_tablesize = 
170                 (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
171         
172         if (setup_hostid >= 0)
173                 tpnt->this_id = setup_hostid;
174         else {
175                 /* use 7 as default */
176                 tpnt->this_id = 7;
177         }
178         
179         ioaddr = 0;
180         for(i = 0; addrs[i] != 0; i++) {
181                 unsigned char x;
182                 
183                 ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE,
184                                                      SUN3_PAGE_TYPE_VME16);
185                 irq = vecs[i];
186                 sun3_scsi_regp = (unsigned char *)ioaddr;
187                 
188                 dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
189                 
190                 if(sun3_map_test((unsigned long)dregs, &x)) {
191                         unsigned short oldcsr;
192
193                         oldcsr = dregs->csr;
194                         dregs->csr = 0;
195                         udelay(SUN3_DMA_DELAY);
196                         if(dregs->csr == 0x1400)
197                                 break;
198                         
199                         dregs->csr = oldcsr;
200                 }
201
202                 iounmap((void *)ioaddr);
203                 ioaddr = 0;
204         }
205
206         if(!ioaddr)
207                 return 0;
208         
209 #ifdef SUPPORT_TAGS
210         if (setup_use_tagged_queuing < 0)
211                 setup_use_tagged_queuing = USE_TAGGED_QUEUING;
212 #endif
213
214         instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
215         if(instance == NULL)
216                 return 0;
217                 
218         default_instance = instance;
219
220         instance->io_port = (unsigned long) ioaddr;
221         instance->irq = irq;
222
223         NCR5380_init(instance, 0);
224
225         instance->n_io_port = 32;
226
227         ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
228
229         if (request_irq(instance->irq, scsi_sun3_intr,
230                         0, "Sun3SCSI-5380VME", instance)) {
231 #ifndef REAL_DMA
232                 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
233                        instance->host_no, instance->irq);
234                 instance->irq = SCSI_IRQ_NONE;
235 #else
236                 printk("scsi%d: IRQ%d not free, bailing out\n",
237                        instance->host_no, instance->irq);
238                 return 0;
239 #endif
240         }
241
242         printk("scsi%d: Sun3 5380 VME at port %lX irq", instance->host_no, instance->io_port);
243         if (instance->irq == SCSI_IRQ_NONE)
244                 printk ("s disabled");
245         else
246                 printk (" %d", instance->irq);
247         printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
248                instance->can_queue, instance->cmd_per_lun,
249                SUN3SCSI_PUBLIC_RELEASE);
250         printk("\nscsi%d:", instance->host_no);
251         NCR5380_print_options(instance);
252         printk("\n");
253
254         dregs->csr = 0;
255         udelay(SUN3_DMA_DELAY);
256         dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
257         udelay(SUN3_DMA_DELAY);
258         dregs->fifo_count = 0;
259         dregs->fifo_count_hi = 0;
260         dregs->dma_addr_hi = 0;
261         dregs->dma_addr_lo = 0;
262         dregs->dma_count_hi = 0;
263         dregs->dma_count_lo = 0;
264
265         dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
266
267         called = 1;
268
269 #ifdef RESET_BOOT
270         sun3_scsi_reset_boot(instance);
271 #endif
272
273         return 1;
274 }
275
276 int sun3scsi_release (struct Scsi_Host *shpnt)
277 {
278         if (shpnt->irq != SCSI_IRQ_NONE)
279                 free_irq(shpnt->irq, shpnt);
280
281         iounmap((void *)sun3_scsi_regp);
282
283         NCR5380_exit(shpnt);
284         return 0;
285 }
286
287 #ifdef RESET_BOOT
288 /*
289  * Our 'bus reset on boot' function
290  */
291
292 static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
293 {
294         unsigned long end;
295
296         NCR5380_local_declare();
297         NCR5380_setup(instance);
298         
299         /*
300          * Do a SCSI reset to clean up the bus during initialization. No
301          * messing with the queues, interrupts, or locks necessary here.
302          */
303
304         printk( "Sun3 SCSI: resetting the SCSI bus..." );
305
306         /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
307 //              sun3_disable_irq( IRQ_SUN3_SCSI );
308
309         /* get in phase */
310         NCR5380_write( TARGET_COMMAND_REG,
311                       PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
312
313         /* assert RST */
314         NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
315
316         /* The min. reset hold time is 25us, so 40us should be enough */
317         udelay( 50 );
318
319         /* reset RST and interrupt */
320         NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
321         NCR5380_read( RESET_PARITY_INTERRUPT_REG );
322
323         for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
324                 barrier();
325
326         /* switch on SCSI IRQ again */
327 //              sun3_enable_irq( IRQ_SUN3_SCSI );
328
329         printk( " done\n" );
330 }
331 #endif
332
333 static const char * sun3scsi_info (struct Scsi_Host *spnt) {
334     return "";
335 }
336
337 // safe bits for the CSR
338 #define CSR_GOOD 0x060f
339
340 static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
341 {
342         unsigned short csr = dregs->csr;
343         int handled = 0;
344
345         dregs->csr &= ~CSR_DMA_ENABLE;
346
347
348 #ifdef SUN3_SCSI_DEBUG
349         printk("scsi_intr csr %x\n", csr);
350 #endif
351
352         if(csr & ~CSR_GOOD) {
353                 if(csr & CSR_DMA_BUSERR) {
354                         printk("scsi%d: bus error in dma\n", default_instance->host_no);
355 #ifdef SUN3_SCSI_DEBUG
356                         printk("scsi: residual %x count %x addr %p dmaaddr %x\n", 
357                                dregs->fifo_count,
358                                dregs->dma_count_lo | (dregs->dma_count_hi << 16),
359                                sun3_dma_orig_addr,
360                                dregs->dma_addr_lo | (dregs->dma_addr_hi << 16));
361 #endif
362                 }
363
364                 if(csr & CSR_DMA_CONFLICT) {
365                         printk("scsi%d: dma conflict\n", default_instance->host_no);
366                 }
367                 handled = 1;
368         }
369
370         if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
371                 NCR5380_intr(irq, dummy);
372                 handled = 1;
373         }
374
375         return IRQ_RETVAL(handled);
376 }
377
378 /*
379  * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 
380  * reentering NCR5380_print_status seems to have ugly side effects
381  */
382
383 /* this doesn't seem to get used at all -- sam */
384 #if 0
385 void sun3_sun3_debug (void)
386 {
387         unsigned long flags;
388         NCR5380_local_declare();
389
390         if (default_instance) {
391                         local_irq_save(flags);
392                         NCR5380_print_status(default_instance);
393                         local_irq_restore(flags);
394         }
395 }
396 #endif
397
398
399 /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
400 static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag)
401 {
402         void *addr;
403
404         if(sun3_dma_orig_addr != NULL)
405                 dvma_unmap(sun3_dma_orig_addr);
406
407 //      addr = sun3_dvma_page((unsigned long)data, (unsigned long)dmabuf);
408         addr = (void *)dvma_map_vme((unsigned long) data, count);
409                 
410         sun3_dma_orig_addr = addr;
411         sun3_dma_orig_count = count;
412         
413 #ifdef SUN3_SCSI_DEBUG
414         printk("scsi: dma_setup addr %p count %x\n", addr, count);
415 #endif
416
417 //      dregs->fifo_count = 0;
418 #if 0   
419         /* reset fifo */
420         dregs->csr &= ~CSR_FIFO;
421         dregs->csr |= CSR_FIFO;
422 #endif  
423         /* set direction */
424         if(write_flag)
425                 dregs->csr |= CSR_SEND;
426         else
427                 dregs->csr &= ~CSR_SEND;
428         
429         /* reset fifo */
430 //      dregs->csr &= ~CSR_FIFO;
431 //      dregs->csr |= CSR_FIFO;
432
433         dregs->csr |= CSR_PACK_ENABLE;
434
435         dregs->dma_addr_hi = ((unsigned long)addr >> 16);
436         dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
437         
438         dregs->dma_count_hi = 0;
439         dregs->dma_count_lo = 0;
440         dregs->fifo_count_hi = 0;
441         dregs->fifo_count = 0;
442                 
443 #ifdef SUN3_SCSI_DEBUG
444         printk("scsi: dma_setup done csr %x\n", dregs->csr);
445 #endif
446         return count;
447
448 }
449
450 static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
451 {
452         return last_residual;
453 }
454
455 static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted,
456                                                   struct scsi_cmnd *cmd,
457                                                   int write_flag)
458 {
459         if (cmd->request->cmd_type == REQ_TYPE_FS)
460                 return wanted;
461         else
462                 return 0;
463 }
464
465 static int sun3scsi_dma_start(unsigned long count, char *data)
466 {
467         
468         unsigned short csr;
469
470         csr = dregs->csr;
471 #ifdef SUN3_SCSI_DEBUG
472         printk("scsi: dma_start data %p count %x csr %x fifo %x\n", data, count, csr, dregs->fifo_count);
473 #endif
474         
475         dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
476         dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
477
478         dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
479         dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
480
481 //      if(!(csr & CSR_DMA_ENABLE))
482 //              dregs->csr |= CSR_DMA_ENABLE;
483
484         return 0;
485 }
486
487 /* clean up after our dma is done */
488 static int sun3scsi_dma_finish(int write_flag)
489 {
490         unsigned short fifo;
491         int ret = 0;
492         
493         sun3_dma_active = 0;
494
495         dregs->csr &= ~CSR_DMA_ENABLE;
496         
497         fifo = dregs->fifo_count;
498         if(write_flag) {
499                 if((fifo > 0) && (fifo < sun3_dma_orig_count))
500                         fifo++;
501         }
502
503         last_residual = fifo;
504 #ifdef SUN3_SCSI_DEBUG
505         printk("scsi: residual %x total %x\n", fifo, sun3_dma_orig_count);
506 #endif
507         /* empty bytes from the fifo which didn't make it */
508         if((!write_flag) && (dregs->csr & CSR_LEFT)) {
509                 unsigned char *vaddr;
510
511 #ifdef SUN3_SCSI_DEBUG
512                 printk("scsi: got left over bytes\n");
513 #endif
514
515                 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
516                 
517                 vaddr += (sun3_dma_orig_count - fifo);
518                 vaddr--;
519                 
520                 switch(dregs->csr & CSR_LEFT) {
521                 case CSR_LEFT_3:
522                         *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
523                         vaddr--;
524                         
525                 case CSR_LEFT_2:
526                         *vaddr = (dregs->bpack_hi & 0x00ff);
527                         vaddr--;
528                         
529                 case CSR_LEFT_1:
530                         *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
531                         break;
532                 }
533                 
534                 
535         }
536
537         dvma_unmap(sun3_dma_orig_addr);
538         sun3_dma_orig_addr = NULL;
539
540         dregs->dma_addr_hi = 0;
541         dregs->dma_addr_lo = 0;
542         dregs->dma_count_hi = 0;
543         dregs->dma_count_lo = 0;
544
545         dregs->fifo_count = 0;
546         dregs->fifo_count_hi = 0;
547
548         dregs->csr &= ~CSR_SEND;
549         
550 //      dregs->csr |= CSR_DMA_ENABLE;
551         
552 #if 0
553         /* reset fifo */
554         dregs->csr &= ~CSR_FIFO;
555         dregs->csr |= CSR_FIFO;
556 #endif  
557         sun3_dma_setup_done = NULL;
558
559         return ret;
560
561 }
562
563 #include "sun3_NCR5380.c"
564
565 static struct scsi_host_template driver_template = {
566         .name                   = SUN3_SCSI_NAME,
567         .detect                 = sun3scsi_detect,
568         .release                = sun3scsi_release,
569         .info                   = sun3scsi_info,
570         .queuecommand           = sun3scsi_queue_command,
571         .eh_abort_handler       = sun3scsi_abort,
572         .eh_bus_reset_handler   = sun3scsi_bus_reset,
573         .can_queue              = CAN_QUEUE,
574         .this_id                = 7,
575         .sg_tablesize           = SG_TABLESIZE,
576         .cmd_per_lun            = CMD_PER_LUN,
577         .use_clustering         = DISABLE_CLUSTERING
578 };
579
580
581 #include "scsi_module.c"
582
583 MODULE_LICENSE("GPL");