summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/NCR53C9x.h
blob: 06e7edf2332645a60c4547b182e2a386b0275fd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
/* NCR53C9x.c:  Defines and structures for the NCR53C9x generic driver.
 *
 * Originaly esp.h:  Defines and structures for the Sparc ESP 
 *                   (Enhanced SCSI Processor) driver under Linux.
 *
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 *
 * Generalization by Jesper Skov (jskov@cygnus.co.uk)
 *
 * More generalization (for i386 stuff) by Tymm Twillman (tymm@computer.org)
 */

#ifndef NCR53C9X_H
#define NCR53C9X_H

#include <linux/config.h>
#include <linux/interrupt.h>

/* djweis for mac driver */
#if defined(CONFIG_MAC)
#define PAD_SIZE 15
#else
#define PAD_SIZE 3
#endif

/* Handle multiple hostadapters on Amiga
 * generally PAD_SIZE = 3
 * but there is one exception: Oktagon (PAD_SIZE = 1) */
#if defined(CONFIG_OKTAGON_SCSI) || defined(CONFIG_OKTAGON_SCSI_MODULE)
#undef PAD_SIZE
#if defined(CONFIG_BLZ1230_SCSI) || defined(CONFIG_BLZ1230_SCSI_MODULE) || \
    defined(CONFIG_BLZ2060_SCSI) || defined(CONFIG_BLZ2060_SCSI_MODULE) || \
    defined(CONFIG_CYBERSTORM_SCSI) || defined(CONFIG_CYBERSTORM_SCSI_MODULE) || \
    defined(CONFIG_CYBERSTORMII_SCSI) || defined(CONFIG_CYBERSTORMII_SCSI_MODULE) || \
    defined(CONFIG_FASTLANE_SCSI) || defined(CONFIG_FASTLANE_SCSI_MODULE)
#define MULTIPLE_PAD_SIZES
#else
#define PAD_SIZE 1
#endif
#endif

/* Macros for debugging messages */

#define DEBUG_ESP
/* #define DEBUG_ESP_DATA */
/* #define DEBUG_ESP_QUEUE */
/* #define DEBUG_ESP_DISCONNECT */
/* #define DEBUG_ESP_STATUS */
/* #define DEBUG_ESP_PHASES */
/* #define DEBUG_ESP_WORKBUS */
/* #define DEBUG_STATE_MACHINE */
/* #define DEBUG_ESP_CMDS */
/* #define DEBUG_ESP_IRQS */
/* #define DEBUG_SDTR */
/* #define DEBUG_ESP_SG */

/* Use the following to sprinkle debugging messages in a way which
 * suits you if combinations of the above become too verbose when
 * trying to track down a specific problem.
 */
/* #define DEBUG_ESP_MISC */

#if defined(DEBUG_ESP)
#define ESPLOG(foo)  printk foo
#else
#define ESPLOG(foo)
#endif /* (DEBUG_ESP) */

#if defined(DEBUG_ESP_DATA)
#define ESPDATA(foo)  printk foo
#else
#define ESPDATA(foo)
#endif

#if defined(DEBUG_ESP_QUEUE)
#define ESPQUEUE(foo)  printk foo
#else
#define ESPQUEUE(foo)
#endif

#if defined(DEBUG_ESP_DISCONNECT)
#define ESPDISC(foo)  printk foo
#else
#define ESPDISC(foo)
#endif

#if defined(DEBUG_ESP_STATUS)
#define ESPSTAT(foo)  printk foo
#else
#define ESPSTAT(foo)
#endif

#if defined(DEBUG_ESP_PHASES)
#define ESPPHASE(foo)  printk foo
#else
#define ESPPHASE(foo)
#endif

#if defined(DEBUG_ESP_WORKBUS)
#define ESPBUS(foo)  printk foo
#else
#define ESPBUS(foo)
#endif

#if defined(DEBUG_ESP_IRQS)
#define ESPIRQ(foo)  printk foo
#else
#define ESPIRQ(foo)
#endif

#if defined(DEBUG_SDTR)
#define ESPSDTR(foo)  printk foo
#else
#define ESPSDTR(foo)
#endif

#if defined(DEBUG_ESP_MISC)
#define ESPMISC(foo)  printk foo
#else
#define ESPMISC(foo)
#endif

/*
 * padding for register structure
 */
#ifdef CONFIG_JAZZ_ESP
#define EREGS_PAD(n)
#else
#ifndef MULTIPLE_PAD_SIZES
#define EREGS_PAD(n)    unchar n[PAD_SIZE];
#endif
#endif

/* The ESP SCSI controllers have their register sets in three
 * "classes":
 *
 * 1) Registers which are both read and write.
 * 2) Registers which are read only.
 * 3) Registers which are write only.
 *
 * Yet, they all live within the same IO space.
 */

#if !defined(__i386__) && !defined(__x86_64__)

#ifndef MULTIPLE_PAD_SIZES

#ifdef CONFIG_CPU_HAS_WB
#include <asm/wbflush.h>
#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
#else
#define esp_write(__reg, __val) ((__reg) = (__val))
#endif
#define esp_read(__reg) (__reg)

struct ESP_regs {
                                /* Access    Description              Offset */
    volatile unchar esp_tclow;  /* rw  Low bits of the transfer count 0x00   */
                                EREGS_PAD(tlpad1);
    volatile unchar esp_tcmed;  /* rw  Mid bits of the transfer count 0x04   */
                                EREGS_PAD(fdpad);
    volatile unchar esp_fdata;  /* rw  FIFO data bits                 0x08   */
                                EREGS_PAD(cbpad);
    volatile unchar esp_cmnd;   /* rw  SCSI command bits              0x0c   */
                                EREGS_PAD(stpad);
    volatile unchar esp_status; /* ro  ESP status register            0x10   */
#define esp_busid   esp_status  /* wo  Bus ID for select/reselect     0x10   */
                                EREGS_PAD(irqpd);
    volatile unchar esp_intrpt; /* ro  Kind of interrupt              0x14   */
#define esp_timeo   esp_intrpt  /* wo  Timeout value for select/resel 0x14   */
                                EREGS_PAD(sspad);
    volatile unchar esp_sstep;  /* ro  Sequence step register         0x18   */
#define esp_stp     esp_sstep   /* wo  Transfer period per sync       0x18   */
                                EREGS_PAD(ffpad);
    volatile unchar esp_fflags; /* ro  Bits of current FIFO info      0x1c   */
#define esp_soff    esp_fflags  /* wo  Sync offset                    0x1c   */
                                EREGS_PAD(cf1pd);
    volatile unchar esp_cfg1;   /* rw  First configuration register   0x20   */
                                EREGS_PAD(cfpad);
    volatile unchar esp_cfact;  /* wo  Clock conversion factor        0x24   */
                                EREGS_PAD(ctpad);
    volatile unchar esp_ctest;  /* wo  Chip test register             0x28   */
                                EREGS_PAD(cf2pd);
    volatile unchar esp_cfg2;   /* rw  Second configuration register  0x2c   */
                                EREGS_PAD(cf3pd);

    /* The following is only found on the 53C9X series SCSI chips */
    volatile unchar esp_cfg3;   /* rw  Third configuration register   0x30  */
                                EREGS_PAD(cf4pd);
    volatile unchar esp_cfg4;   /* rw  Fourth configuration register  0x34  */
                                EREGS_PAD(thpd);
    /* The following is found on all chips except the NCR53C90 (ESP100) */
    volatile unchar esp_tchi;   /* rw  High bits of transfer count    0x38  */
#define esp_uid     esp_tchi    /* ro  Unique ID code                 0x38  */
                                EREGS_PAD(fgpad);    
    volatile unchar esp_fgrnd;  /* rw  Data base for fifo             0x3c  */
};

#else /* MULTIPLE_PAD_SIZES */

#define esp_write(__reg, __val) (*(__reg) = (__val))
#define esp_read(__reg) (*(__reg))

struct ESP_regs {
    unsigned char io_addr[64]; /* dummy */
                                                 /* Access    Description              Offset */
#define esp_tclow   io_addr                      /* rw  Low bits of the transfer count 0x00   */
#define esp_tcmed   io_addr + (1<<(esp->shift))  /* rw  Mid bits of the transfer count 0x04   */
#define esp_fdata   io_addr + (2<<(esp->shift))  /* rw  FIFO data bits                 0x08   */
#define esp_cmnd    io_addr + (3<<(esp->shift))  /* rw  SCSI command bits              0x0c   */
#define esp_status  io_addr + (4<<(esp->shift))  /* ro  ESP status register            0x10   */
#define esp_busid   esp_status                   /* wo  Bus ID for select/reselect     0x10   */
#define esp_intrpt  io_addr + (5<<(esp->shift))  /* ro  Kind of interrupt              0x14   */
#define esp_timeo   esp_intrpt                   /* wo  Timeout value for select/resel 0x14   */
#define esp_sstep   io_addr + (6<<(esp->shift))  /* ro  Sequence step register         0x18   */
#define esp_stp     esp_sstep                    /* wo  Transfer period per sync       0x18   */
#define esp_fflags  io_addr + (7<<(esp->shift))  /* ro  Bits of current FIFO info      0x1c   */
#define esp_soff    esp_fflags                   /* wo  Sync offset                    0x1c   */
#define esp_cfg1    io_addr + (8<<(esp->shift))  /* rw  First configuration register   0x20   */
#define esp_cfact   io_addr + (9<<(esp->shift))  /* wo  Clock conversion factor        0x24   */
#define esp_ctest   io_addr + (10<<(esp->shift)) /* wo  Chip test register             0x28   */
#define esp_cfg2    io_addr + (11<<(esp->shift)) /* rw  Second configuration register  0x2c   */

    /* The following is only found on the 53C9X series SCSI chips */
#define esp_cfg3    io_addr + (12<<(esp->shift)) /* rw  Third configuration register   0x30  */
#define esp_cfg4    io_addr + (13<<(esp->shift)) /* rw  Fourth configuration register  0x34  */

    /* The following is found on all chips except the NCR53C90 (ESP100) */
#define esp_tchi    io_addr + (14<<(esp->shift)) /* rw  High bits of transfer count    0x38  */
#define esp_uid     esp_tchi                     /* ro  Unique ID code                 0x38  */
#define esp_fgrnd   io_addr + (15<<(esp->shift)) /* rw  Data base for fifo             0x3c  */
};

#endif

#else /* !defined(__i386__) && !defined(__x86_64__) */

#define esp_write(__reg, __val) outb((__val), (__reg))
#define esp_read(__reg) inb((__reg))

struct ESP_regs {
    unsigned int io_addr;
                                 /* Access    Description              Offset */
#define esp_tclow   io_addr      /* rw  Low bits of the transfer count 0x00   */
#define esp_tcmed   io_addr + 1  /* rw  Mid bits of the transfer count 0x04   */
#define esp_fdata   io_addr + 2  /* rw  FIFO data bits                 0x08   */
#define esp_cmnd    io_addr + 3  /* rw  SCSI command bits              0x0c   */
#define esp_status  io_addr + 4  /* ro  ESP status register            0x10   */
#define esp_busid   esp_status   /* wo  Bus ID for select/reselect     0x10   */
#define esp_intrpt  io_addr + 5  /* ro  Kind of interrupt              0x14   */
#define esp_timeo   esp_intrpt   /* wo  Timeout value for select/resel 0x14   */
#define esp_sstep   io_addr + 6  /* ro  Sequence step register         0x18   */
#define esp_stp     esp_sstep    /* wo  Transfer period per sync       0x18   */
#define esp_fflags  io_addr + 7  /* ro  Bits of current FIFO info      0x1c   */
#define esp_soff    esp_fflags   /* wo  Sync offset                    0x1c   */
#define esp_cfg1    io_addr + 8  /* rw  First configuration register   0x20   */
#define esp_cfact   io_addr + 9  /* wo  Clock conversion factor        0x24   */
#define esp_ctest   io_addr + 10 /* wo  Chip test register             0x28   */
#define esp_cfg2    io_addr + 11 /* rw  Second configuration register  0x2c   */

    /* The following is only found on the 53C9X series SCSI chips */
#define esp_cfg3    io_addr + 12 /* rw  Third configuration register   0x30  */
#define esp_cfg4    io_addr + 13 /* rw  Fourth configuration register  0x34  */

    /* The following is found on all chips except the NCR53C90 (ESP100) */
#define esp_tchi    io_addr + 14 /* rw  High bits of transfer count    0x38  */
#define esp_uid     esp_tchi     /* ro  Unique ID code                 0x38  */
#define esp_fgrnd   io_addr + 15 /* rw  Data base for fifo             0x3c  */
};

#endif /* !defined(__i386__) && !defined(__x86_64__) */

/* Various revisions of the ESP board. */
enum esp_rev {
  esp100     = 0x00,  /* NCR53C90 - very broken */
  esp100a    = 0x01,  /* NCR53C90A */
  esp236     = 0x02,
  fas236     = 0x03,
  fas100a    = 0x04,
  fast       = 0x05,
  fas366     = 0x06,
  fas216     = 0x07,
  fsc        = 0x08,  /* SYM53C94-2 */
  espunknown = 0x09
};

/* We allocate one of these for each scsi device and attach it to
 * SDptr->hostdata for use in the driver
 */
struct esp_device {
  unsigned char sync_min_period;
  unsigned char sync_max_offset;
  unsigned sync:1;
  unsigned wide:1;
  unsigned disconnect:1;
};

/* We get one of these for each ESP probed. */
struct NCR_ESP {
  struct NCR_ESP *next;                   /* Next ESP on probed or NULL */
  struct ESP_regs *eregs;	          /* All esp registers */
  int dma;                                /* Who I do transfers with. */
  void *dregs;		  		  /* And his registers. */
  struct Scsi_Host *ehost;                /* Backpointer to SCSI Host */

  void *edev;        		          /* Pointer to controller base/SBus */
  int esp_id;                             /* Unique per-ESP ID number */

  /* ESP Configuration Registers */
  unsigned char config1;                  /* Copy of the 1st config register */
  unsigned char config2;                  /* Copy of the 2nd config register */
  unsigned char config3[16];              /* Copy of the 3rd config register */

  /* The current command we are sending to the ESP chip.  This esp_command
   * ptr needs to be mapped in DVMA area so we can send commands and read
   * from the ESP fifo without burning precious CPU cycles.  Programmed I/O
   * sucks when we have the DVMA to do it for us.  The ESP is stupid and will
   * only send out 6, 10, and 12 byte SCSI commands, others we need to send
   * one byte at a time.  esp_slowcmd being set says that we are doing one
   * of the command types ESP doesn't understand, esp_scmdp keeps track of
   * which byte we are sending, esp_scmdleft says how many bytes to go.
   */
  volatile unchar *esp_command;           /* Location of command (CPU view)  */
  __u32            esp_command_dvma;      /* Location of command (DVMA view) */
  unsigned char esp_clen;                 /* Length of this command */
  unsigned char esp_slowcmd;
  unsigned char *esp_scmdp;
  unsigned char esp_scmdleft;

  /* The following are used to determine the cause of an IRQ. Upon every
   * IRQ entry we synchronize these with the hardware registers.
   */
  unchar ireg;                            /* Copy of ESP interrupt register */
  unchar sreg;                            /* Same for ESP status register */
  unchar seqreg;                          /* The ESP sequence register */

  /* The following is set when a premature interrupt condition is detected
   * in some FAS revisions.
   */
  unchar fas_premature_intr_workaround;

  /* To save register writes to the ESP, which can be expensive, we
   * keep track of the previous value that various registers had for
   * the last target we connected to.  If they are the same for the
   * current target, we skip the register writes as they are not needed.
   */
  unchar prev_soff, prev_stp, prev_cfg3;

  /* For each target we keep track of save/restore data