OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [mac_scsi.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Generic Macintosh NCR5380 driver
3
 *
4
 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
5
 *
6
 * derived in part from:
7
 */
8
/*
9
 * Generic Generic NCR5380 driver
10
 *
11
 * Copyright 1995, Russell King
12
 *
13
 * ALPHA RELEASE 1.
14
 *
15
 * For more information, please consult
16
 *
17
 * NCR 5380 Family
18
 * SCSI Protocol Controller
19
 * Databook
20
 *
21
 * NCR Microelectronics
22
 * 1635 Aeroplaza Drive
23
 * Colorado Springs, CO 80916
24
 * 1+ (719) 578-3400
25
 * 1+ (800) 334-5454
26
 */
27
 
28
/*
29
 * $Log: not supported by cvs2svn $
30
 */
31
 
32
#include <linux/types.h>
33
#include <linux/stddef.h>
34
#include <linux/ctype.h>
35
#include <linux/delay.h>
36
 
37
#include <linux/module.h>
38
#include <linux/signal.h>
39
#include <linux/sched.h>
40
#include <linux/ioport.h>
41
#include <linux/init.h>
42
#include <linux/blk.h>
43
 
44
#include <asm/io.h>
45
#include <asm/irq.h>
46
#include <asm/system.h>
47
 
48
#include <asm/macintosh.h>
49
#include <asm/macints.h>
50
#include <asm/machw.h>
51
#include <asm/mac_via.h>
52
 
53
#include "scsi.h"
54
#include "hosts.h"
55
#include "mac_scsi.h"
56
#include "NCR5380.h"
57
#include "constants.h"
58
 
59
#if 0
60
#define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION)
61
#else
62
#define NDEBUG (NDEBUG_ABORT)
63
#endif
64
 
65
#define RESET_BOOT
66
#define DRIVER_SETUP
67
 
68
#define ENABLE_IRQ()    mac_enable_irq( IRQ_MAC_SCSI ); 
69
#define DISABLE_IRQ()   mac_disable_irq( IRQ_MAC_SCSI );
70
 
71
extern void via_scsi_clear(void);
72
 
73
#ifdef RESET_BOOT
74
static void mac_scsi_reset_boot(struct Scsi_Host *instance);
75
#endif
76
 
77
static int setup_called = 0;
78
static int setup_can_queue = -1;
79
static int setup_cmd_per_lun = -1;
80
static int setup_sg_tablesize = -1;
81
static int setup_use_pdma = -1;
82
#ifdef SUPPORT_TAGS
83
static int setup_use_tagged_queuing = -1;
84
#endif
85
static int setup_hostid = -1;
86
 
87
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
88
 * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
89
 * need ten times the standard value... */
90
#define TOSHIBA_DELAY
91
 
92
#ifdef TOSHIBA_DELAY
93
#define AFTER_RESET_DELAY       (5*HZ/2)
94
#else
95
#define AFTER_RESET_DELAY       (HZ/2)
96
#endif
97
 
98
static volatile unsigned char *mac_scsi_regp = NULL;
99
static volatile unsigned char *mac_scsi_drq  = NULL;
100
static volatile unsigned char *mac_scsi_nodrq = NULL;
101
 
102
 
103
/*
104
 * NCR 5380 register access functions
105
 */
106
 
107
#if 0
108
/* Debug versions */
109
#define CTRL(p,v) (*ctrl = (v))
110
 
111
static char macscsi_read(struct Scsi_Host *instance, int reg)
112
{
113
  int iobase = instance->io_port;
114
  int i;
115
  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
116
 
117
  CTRL(iobase, 0);
118
  i = in_8(iobase + (reg<<4));
119
  CTRL(iobase, 0x40);
120
 
121
  return i;
122
}
123
 
124
static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
125
{
126
  int iobase = instance->io_port;
127
  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
128
 
129
  CTRL(iobase, 0);
130
  out_8(iobase + (reg<<4), value);
131
  CTRL(iobase, 0x40);
132
}
133
#else
134
 
135
/* Fast versions */
136
static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
137
{
138
  return in_8(instance->io_port + (reg<<4));
139
}
140
 
141
static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
142
{
143
  out_8(instance->io_port + (reg<<4), value);
144
}
145
#endif
146
 
147
 
148
/*
149
 * Function : mac_scsi_setup(char *str)
150
 *
151
 * Purpose : booter command line initialization of the overrides array,
152
 *
153
 * Inputs : str - comma delimited list of options
154
 *
155
 */
156
 
157
static int __init mac_scsi_setup(char *str) {
158
#ifdef DRIVER_SETUP     
159
        int ints[7];
160
 
161
        (void)get_options( str, ARRAY_SIZE(ints), ints);
162
 
163
        if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
164
            printk(KERN_WARNING "scsi: <mac5380>"
165
                " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
166
            printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
167
            return 0;
168
        }
169
 
170
        if (ints[0] >= 1) {
171
                if (ints[1] > 0)
172
                        /* no limits on this, just > 0 */
173
                        setup_can_queue = ints[1];
174
        }
175
        if (ints[0] >= 2) {
176
                if (ints[2] > 0)
177
                        setup_cmd_per_lun = ints[2];
178
        }
179
        if (ints[0] >= 3) {
180
                if (ints[3] >= 0) {
181
                        setup_sg_tablesize = ints[3];
182
                        /* Must be <= SG_ALL (255) */
183
                        if (setup_sg_tablesize > SG_ALL)
184
                                setup_sg_tablesize = SG_ALL;
185
                }
186
        }
187
        if (ints[0] >= 4) {
188
                /* Must be between 0 and 7 */
189
                if (ints[4] >= 0 && ints[4] <= 7)
190
                        setup_hostid = ints[4];
191
                else if (ints[4] > 7)
192
                        printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
193
        }
194
#ifdef SUPPORT_TAGS     
195
        if (ints[0] >= 5) {
196
                if (ints[5] >= 0)
197
                        setup_use_tagged_queuing = !!ints[5];
198
        }
199
 
200
        if (ints[0] == 6) {
201
            if (ints[6] >= 0)
202
                setup_use_pdma = ints[6];
203
        }
204
#else
205
        if (ints[0] == 5) {
206
            if (ints[5] >= 0)
207
                setup_use_pdma = ints[5];
208
        }
209
#endif /* SUPPORT_TAGS */
210
 
211
#endif /* DRIVER_SETUP */
212
        return 1;
213
}
214
 
215
__setup("mac5380=", mac_scsi_setup);
216
 
217
/*
218
 * If you want to find the instance with (k)gdb ...
219
 */
220
#if NDEBUG
221
static struct Scsi_Host *default_instance;
222
#endif
223
 
224
/*
225
 * Function : int macscsi_detect(Scsi_Host_Template * tpnt)
226
 *
227
 * Purpose : initializes mac NCR5380 driver based on the
228
 *      command line / compile time port and irq definitions.
229
 *
230
 * Inputs : tpnt - template for this SCSI adapter.
231
 *
232
 * Returns : 1 if a host adapter was found, 0 if not.
233
 *
234
 */
235
 
236
int macscsi_detect(Scsi_Host_Template * tpnt)
237
{
238
    static int called = 0;
239
    int flags = 0;
240
    struct Scsi_Host *instance;
241
 
242
    if (!MACH_IS_MAC || called)
243
        return( 0 );
244
 
245
    if (macintosh_config->scsi_type != MAC_SCSI_OLD)
246
        return( 0 );
247
 
248
    /* setup variables */
249
    tpnt->can_queue =
250
        (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
251
    tpnt->cmd_per_lun =
252
        (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
253
    tpnt->sg_tablesize =
254
        (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
255
 
256
    if (setup_hostid >= 0)
257
        tpnt->this_id = setup_hostid;
258
    else {
259
        /* use 7 as default */
260
        tpnt->this_id = 7;
261
    }
262
 
263
#ifdef SUPPORT_TAGS
264
    if (setup_use_tagged_queuing < 0)
265
        setup_use_tagged_queuing = USE_TAGGED_QUEUING;
266
#endif
267
 
268
    /* Once we support multiple 5380s (e.g. DuoDock) we'll do
269
       something different here */
270
    instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
271
#if NDEBUG
272
    default_instance = instance;
273
#endif
274
 
275
    if (macintosh_config->ident == MAC_MODEL_IIFX) {
276
        mac_scsi_regp  = via1+0x8000;
277
        mac_scsi_drq   = via1+0xE000;
278
        mac_scsi_nodrq = via1+0xC000;
279
        /* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
280
        flags = FLAG_NO_PSEUDO_DMA;
281
    } else {
282
        mac_scsi_regp  = via1+0x10000;
283
        mac_scsi_drq   = via1+0x6000;
284
        mac_scsi_nodrq = via1+0x12000;
285
    }
286
 
287
    if (! setup_use_pdma)
288
        flags = FLAG_NO_PSEUDO_DMA;
289
 
290
    instance->io_port = (unsigned long) mac_scsi_regp;
291
    instance->irq = IRQ_MAC_SCSI;
292
 
293
#ifdef RESET_BOOT   
294
    mac_scsi_reset_boot(instance);
295
#endif
296
 
297
    NCR5380_init(instance, flags);
298
 
299
    instance->n_io_port = 255;
300
 
301
    ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
302
 
303
    if (instance->irq != SCSI_IRQ_NONE)
304
        if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
305
                "ncr5380", NCR5380_intr)) {
306
            printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
307
                   instance->host_no, instance->irq);
308
            instance->irq = SCSI_IRQ_NONE;
309
        }
310
 
311
    printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
312
    if (instance->irq == SCSI_IRQ_NONE)
313
        printk (KERN_INFO "s disabled");
314
    else
315
        printk (KERN_INFO " %d", instance->irq);
316
    printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
317
           instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
318
    printk(KERN_INFO "\nscsi%d:", instance->host_no);
319
    NCR5380_print_options(instance);
320
    printk("\n");
321
    called = 1;
322
    return 1;
323
}
324
 
325
int macscsi_release (struct Scsi_Host *shpnt)
326
{
327
        if (shpnt->irq != SCSI_IRQ_NONE)
328
                free_irq (shpnt->irq, NCR5380_intr);
329
 
330
        return 0;
331
}
332
 
333
#ifdef RESET_BOOT
334
/*
335
 * Our 'bus reset on boot' function
336
 */
337
 
338
static void mac_scsi_reset_boot(struct Scsi_Host *instance)
339
{
340
        unsigned long end;
341
 
342
        NCR5380_local_declare();
343
        NCR5380_setup(instance);
344
 
345
        /*
346
         * Do a SCSI reset to clean up the bus during initialization. No messing
347
         * with the queues, interrupts, or locks necessary here.
348
         */
349
 
350
        printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
351
 
352
        /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
353
        mac_disable_irq(IRQ_MAC_SCSI);
354
 
355
        /* get in phase */
356
        NCR5380_write( TARGET_COMMAND_REG,
357
                      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
358
 
359
        /* assert RST */
360
        NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
361
        /* The min. reset hold time is 25us, so 40us should be enough */
362
        udelay( 50 );
363
        /* reset RST and interrupt */
364
        NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
365
        NCR5380_read( RESET_PARITY_INTERRUPT_REG );
366
 
367
        for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
368
                barrier();
369
 
370
        /* switch on SCSI IRQ again */
371
        mac_enable_irq(IRQ_MAC_SCSI);
372
 
373
        printk(KERN_INFO " done\n" );
374
}
375
#endif
376
 
377
const char * macscsi_info (struct Scsi_Host *spnt) {
378
        return "";
379
}
380
 
381
/*
382
   Pseudo-DMA: (Ove Edlund)
383
   The code attempts to catch bus errors that occur if one for example
384
   "trips over the cable".
385
   XXX: Since bus errors in the PDMA routines never happen on my
386
   computer, the bus error code is untested.
387
   If the code works as intended, a bus error results in Pseudo-DMA
388
   beeing disabled, meaning that the driver switches to slow handshake.
389
   If bus errors are NOT extremely rare, this has to be changed.
390
*/
391
 
392
#define CP_IO_TO_MEM(s,d,len)                           \
393
__asm__ __volatile__                                    \
394
    ("    cmp.w  #4,%2\n"                               \
395
     "    bls    8f\n"                                  \
396
     "    move.w %1,%%d0\n"                             \
397
     "    neg.b  %%d0\n"                                \
398
     "    and.w  #3,%%d0\n"                             \
399
     "    sub.w  %%d0,%2\n"                             \
400
     "    bra    2f\n"                                  \
401
     " 1: move.b (%0),(%1)+\n"                          \
402
     " 2: dbf    %%d0,1b\n"                             \
403
     "    move.w %2,%%d0\n"                             \
404
     "    lsr.w  #5,%%d0\n"                             \
405
     "    bra    4f\n"                                  \
406
     " 3: move.l (%0),(%1)+\n"                          \
407
     "31: move.l (%0),(%1)+\n"                          \
408
     "32: move.l (%0),(%1)+\n"                          \
409
     "33: move.l (%0),(%1)+\n"                          \
410
     "34: move.l (%0),(%1)+\n"                          \
411
     "35: move.l (%0),(%1)+\n"                          \
412
     "36: move.l (%0),(%1)+\n"                          \
413
     "37: move.l (%0),(%1)+\n"                          \
414
     " 4: dbf    %%d0,3b\n"                             \
415
     "    move.w %2,%%d0\n"                             \
416
     "    lsr.w  #2,%%d0\n"                             \
417
     "    and.w  #7,%%d0\n"                             \
418
     "    bra    6f\n"                                  \
419
     " 5: move.l (%0),(%1)+\n"                          \
420
     " 6: dbf    %%d0,5b\n"                             \
421
     "    and.w  #3,%2\n"                               \
422
     "    bra    8f\n"                                  \
423
     " 7: move.b (%0),(%1)+\n"                          \
424
     " 8: dbf    %2,7b\n"                               \
425
     "    moveq.l #0, %2\n"                             \
426
     " 9: \n"                                           \
427
     ".section .fixup,\"ax\"\n"                         \
428
     "    .even\n"                                      \
429
     "90: moveq.l #1, %2\n"                             \
430
     "    jra 9b\n"                                     \
431
     ".previous\n"                                      \
432
     ".section __ex_table,\"a\"\n"                      \
433
     "   .align 4\n"                                    \
434
     "   .long  1b,90b\n"                               \
435
     "   .long  3b,90b\n"                               \
436
     "   .long 31b,90b\n"                               \
437
     "   .long 32b,90b\n"                               \
438
     "   .long 33b,90b\n"                               \
439
     "   .long 34b,90b\n"                               \
440
     "   .long 35b,90b\n"                               \
441
     "   .long 36b,90b\n"                               \
442
     "   .long 37b,90b\n"                               \
443
     "   .long  5b,90b\n"                               \
444
     "   .long  7b,90b\n"                               \
445
     ".previous"                                        \
446
     : "=a"(s), "=a"(d), "=d"(len)                      \
447
     : "0"(s), "1"(d), "2"(len)                          \
448
     : "d0")
449
 
450
 
451
static int macscsi_pread (struct Scsi_Host *instance,
452
                          unsigned char *dst, int len)
453
{
454
   unsigned char *d;
455
   volatile unsigned char *s;
456
 
457
   NCR5380_local_declare();
458
   NCR5380_setup(instance);
459
 
460
   s = mac_scsi_drq+0x60;
461
   d = dst;
462
 
463
/* These conditions are derived from MacOS */
464
 
465
   while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
466
         && !(NCR5380_read(STATUS_REG) & SR_REQ))
467
      ;
468
   if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
469
         && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
470
      printk(KERN_ERR "Error in macscsi_pread\n");
471
      return -1;
472
   }
473
 
474
   CP_IO_TO_MEM(s, d, len);
475
 
476
   if (len != 0) {
477
      printk(KERN_NOTICE "Bus error in macscsi_pread\n");
478
      return -1;
479
   }
480
 
481
   return 0;
482
}
483
 
484
 
485
#define CP_MEM_TO_IO(s,d,len)                           \
486
__asm__ __volatile__                                    \
487
    ("    cmp.w  #4,%2\n"                               \
488
     "    bls    8f\n"                                  \
489
     "    move.w %0,%%d0\n"                             \
490
     "    neg.b  %%d0\n"                                \
491
     "    and.w  #3,%%d0\n"                             \
492
     "    sub.w  %%d0,%2\n"                             \
493
     "    bra    2f\n"                                  \
494
     " 1: move.b (%0)+,(%1)\n"                          \
495
     " 2: dbf    %%d0,1b\n"                             \
496
     "    move.w %2,%%d0\n"                             \
497
     "    lsr.w  #5,%%d0\n"                             \
498
     "    bra    4f\n"                                  \
499
     " 3: move.l (%0)+,(%1)\n"                          \
500
     "31: move.l (%0)+,(%1)\n"                          \
501
     "32: move.l (%0)+,(%1)\n"                          \
502
     "33: move.l (%0)+,(%1)\n"                          \
503
     "34: move.l (%0)+,(%1)\n"                          \
504
     "35: move.l (%0)+,(%1)\n"                          \
505
     "36: move.l (%0)+,(%1)\n"                          \
506
     "37: move.l (%0)+,(%1)\n"                          \
507
     " 4: dbf    %%d0,3b\n"                             \
508
     "    move.w %2,%%d0\n"                             \
509
     "    lsr.w  #2,%%d0\n"                             \
510
     "    and.w  #7,%%d0\n"                             \
511
     "    bra    6f\n"                                  \
512
     " 5: move.l (%0)+,(%1)\n"                          \
513
     " 6: dbf    %%d0,5b\n"                             \
514
     "    and.w  #3,%2\n"                               \
515
     "    bra    8f\n"                                  \
516
     " 7: move.b (%0)+,(%1)\n"                          \
517
     " 8: dbf    %2,7b\n"                               \
518
     "    moveq.l #0, %2\n"                             \
519
     " 9: \n"                                           \
520
     ".section .fixup,\"ax\"\n"                         \
521
     "    .even\n"                                      \
522
     "90: moveq.l #1, %2\n"                             \
523
     "    jra 9b\n"                                     \
524
     ".previous\n"                                      \
525
     ".section __ex_table,\"a\"\n"                      \
526
     "   .align 4\n"                                    \
527
     "   .long  1b,90b\n"                               \
528
     "   .long  3b,90b\n"                               \
529
     "   .long 31b,90b\n"                               \
530
     "   .long 32b,90b\n"                               \
531
     "   .long 33b,90b\n"                               \
532
     "   .long 34b,90b\n"                               \
533
     "   .long 35b,90b\n"                               \
534
     "   .long 36b,90b\n"                               \
535
     "   .long 37b,90b\n"                               \
536
     "   .long  5b,90b\n"                               \
537
     "   .long  7b,90b\n"                               \
538
     ".previous"                                        \
539
     : "=a"(s), "=a"(d), "=d"(len)                      \
540
     : "0"(s), "1"(d), "2"(len)                          \
541
     : "d0")
542
 
543
static int macscsi_pwrite (struct Scsi_Host *instance,
544
                                  unsigned char *src, int len)
545
{
546
   unsigned char *s;
547
   volatile unsigned char *d;
548
 
549
   NCR5380_local_declare();
550
   NCR5380_setup(instance);
551
 
552
   s = src;
553
   d = mac_scsi_drq;
554
 
555
/* These conditions are derived from MacOS */
556
 
557
   while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
558
         && (!(NCR5380_read(STATUS_REG) & SR_REQ)
559
            || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
560
      ;
561
   if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
562
      printk(KERN_ERR "Error in macscsi_pwrite\n");
563
      return -1;
564
   }
565
 
566
   CP_MEM_TO_IO(s, d, len);
567
 
568
   if (len != 0) {
569
      printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
570
      return -1;
571
   }
572
 
573
   return 0;
574
}
575
 
576
 
577
/* These control the behaviour of the generic 5380 core */
578
#define AUTOSENSE
579
#define PSEUDO_DMA
580
 
581
#include "NCR5380.c"
582
 
583
static Scsi_Host_Template driver_template = MAC_NCR5380;
584
 
585
#include "scsi_module.c"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.