]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/sd53c8xx.c
perms
[plan9front.git] / sys / src / boot / pc / sd53c8xx.c
1 /*
2  * NCR 53c8xx driver for Plan 9
3  * Nigel Roles (ngr@cotswold.demon.co.uk)
4  *
5  * 08/07/99     Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics.
6  *
7  * 09/06/99     Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation,
8  *              though no device to test with yet.
9  *              Variant now contains the number of valid chip registers to assist
10  *              dumpncrregs() 
11  *
12  * 06/10/98     Various bug fixes and Brazil compiler inspired changes from jmk
13  *
14  * 05/10/98     Small fix to handle command length being greater than expected by device
15  *
16  * 04/08/98     Added missing locks to interrupt handler. Marked places where 
17  *              multiple controller extensions could go
18  *
19  * 18/05/97     Fixed overestimate in size of local SCRIPT RAM
20  *
21  * 17/05/97     Bug fix to return status
22  *
23  * 06/10/96     Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it
24  *              is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential
25  *              boards. This is Symbios specific, but since they are about the only suppliers of
26  *              differential cards.
27  *
28  * 23/9/96      Wide and Ultra supported. 825A and 860 added to variants. Dual compiling
29  *              version for fileserver and cpu. 80MHz default clock for 860
30  *              
31  * 5/8/96       Waits for an Inquiry message before initiating synchronous negotiation
32  *              in case capabilities byte [7] indicates device does not support it. Devices
33  *              which do target initiated negotiation will typically get in first; a few
34  *              bugs in handling this have been fixed
35  *
36  * 3/8/96       Added differential support (put scsi0=diff in plan9.ini)
37  *              Split exec() into exec() and io(). Exec() is small, and Io() does not
38  *              use any Plan 9 specific data structures, so alternate exec() functions
39  *              may be done for other environments, such as the fileserver
40  *
41  * GENERAL
42  *
43  * Works on 810 and 875
44  * Should work on 815, 825, 810A, 825A, 860A
45  * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset
46  * where applicable
47  * Supports multi-target, wide, Ultra
48  * Differential mode can be enabled by putting scsi0=diff in plan9.ini
49  * NO SUPPORT FOR tagged queuing (yet)
50  *
51  * Known problems
52  */
53
54 #define MAXTARGET       16              /* can be 8 or 16 */
55
56 #include "u.h"
57 #include "lib.h"
58 #include "mem.h"
59 #include "dat.h"
60 #include "fns.h"
61 #include "io.h"
62 #include "ureg.h"
63 #include "error.h"
64
65 #include "sd.h"
66 extern SDifc sd53c8xxifc;
67
68 #define waserror()      (0)
69 #define poperror()
70 typedef struct QLock{ int r; } QLock;
71 typedef struct Rendez{ int r; } Rendez;
72 #define intrenable(irq, f, c, tbdf, name)       setvec(VectorPIC+(irq), f, c);
73
74 /**********************************/
75 /* Portable configuration macros  */
76 /**********************************/
77
78 //#define BOOTDEBUG
79 //#define ASYNC_ONLY
80 //#define       INTERNAL_SCLK
81 //#define ALWAYS_DO_WDTR
82 #define WMR_DEBUG
83
84 /**********************************/
85 /* CPU specific macros            */
86 /**********************************/
87
88 #ifdef BOOTDEBUG
89
90 #define KPRINT oprint
91 #define IPRINT intrprint
92 #define DEBUG(n) 0
93 #define IFLUSH() iflush()
94
95 #else
96
97 #define KPRINT  if(0)print
98 #define IPRINT  if(0)print
99 #define DEBUG(n)        (0)
100 #define IFLUSH()
101
102 #endif /* BOOTDEBUG */
103
104 /*******************************/
105 /* General                     */
106 /*******************************/
107
108 #ifndef DMASEG
109 #define DMASEG(x) PADDR(x)
110 #define legetl(x) (*(ulong*)(x))
111 #define lesetl(x,v) (*(ulong*)(x) = (v))
112 #define swabl(a,b,c)
113 #else
114 #endif /*DMASEG */
115 #define DMASEG_TO_KADDR(x) KADDR(PADDR(x))
116 #define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
117
118 #define MEGA 1000000L
119 #ifdef INTERNAL_SCLK
120 #define SCLK (33 * MEGA)
121 #else
122 #define SCLK (40 * MEGA)
123 #endif /* INTERNAL_SCLK */
124 #define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
125
126 #define MAXSYNCSCSIRATE (5 * MEGA)
127 #define MAXFASTSYNCSCSIRATE (10 * MEGA)
128 #define MAXULTRASYNCSCSIRATE (20 * MEGA)
129 #define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
130 #define MAXASYNCCORERATE (25 * MEGA)
131 #define MAXSYNCCORERATE (25 * MEGA)
132 #define MAXFASTSYNCCORERATE (50 * MEGA)
133 #define MAXULTRASYNCCORERATE (80 * MEGA)
134 #define MAXULTRA2SYNCCORERATE (160 * MEGA)
135
136
137 #define X_MSG   1
138 #define X_MSG_SDTR 1
139 #define X_MSG_WDTR 3
140
141 struct na_patch {
142         unsigned lwoff;
143         unsigned char type;
144 };
145
146 typedef struct Ncr {
147         uchar scntl0;   /* 00 */
148         uchar scntl1;
149         uchar scntl2;
150         uchar scntl3;
151
152         uchar scid;     /* 04 */
153         uchar sxfer;
154         uchar sdid;
155         uchar gpreg;
156
157         uchar sfbr;     /* 08 */
158         uchar socl;
159         uchar ssid;
160         uchar sbcl;
161
162         uchar dstat;    /* 0c */
163         uchar sstat0;
164         uchar sstat1;
165         uchar sstat2;
166
167         uchar dsa[4];   /* 10 */
168
169         uchar istat;    /* 14 */
170         uchar istatpad[3];
171
172         uchar ctest0;   /* 18 */
173         uchar ctest1;
174         uchar ctest2;
175         uchar ctest3;
176
177         uchar temp[4];  /* 1c */
178
179         uchar dfifo;    /* 20 */
180         uchar ctest4;
181         uchar ctest5;
182         uchar ctest6;
183
184         uchar dbc[3];   /* 24 */
185         uchar dcmd;     /* 27 */
186
187         uchar dnad[4];  /* 28 */
188         uchar dsp[4];   /* 2c */
189         uchar dsps[4];  /* 30 */
190
191         uchar scratcha[4];      /* 34 */
192
193         uchar dmode;    /* 38 */
194         uchar dien;
195         uchar dwt;
196         uchar dcntl;
197
198         uchar adder[4]; /* 3c */
199
200         uchar sien0;    /* 40 */
201         uchar sien1;
202         uchar sist0;
203         uchar sist1;
204
205         uchar slpar;    /* 44 */
206         uchar slparpad0;
207         uchar macntl;
208         uchar gpcntl;
209
210         uchar stime0;   /* 48 */
211         uchar stime1;
212         uchar respid;
213         uchar respidpad0;
214
215         uchar stest0;   /* 4c */
216         uchar stest1;
217         uchar stest2;
218         uchar stest3;
219
220         uchar sidl;     /* 50 */
221         uchar sidlpad[3];
222
223         uchar sodl;     /* 54 */
224         uchar sodlpad[3];
225
226         uchar sbdl;     /* 58 */
227         uchar sbdlpad[3];
228
229         uchar scratchb[4];      /* 5c */
230 } Ncr;
231
232 typedef struct Movedata {
233         uchar dbc[4];
234         uchar pa[4];
235 } Movedata;
236
237 typedef enum NegoState {
238         NeitherDone, WideInit, WideResponse, WideDone,
239         SyncInit, SyncResponse, BothDone
240 } NegoState;
241
242 typedef enum State {
243         Allocated, Queued, Active, Done
244 } State;
245
246 typedef struct Dsa {
247         union {
248                 uchar state[4];
249                 struct {
250                         uchar stateb;
251                         uchar result;
252                         uchar dmablks;
253                         uchar flag;     /* setbyte(state,3,...) */
254                 };
255         };
256
257         union {
258                 ulong dmancr;           /* For block transfer: NCR order (little-endian) */
259                 uchar dmaaddr[4];
260         };
261
262         uchar target;                   /* Target */
263         uchar pad0[3];
264
265         uchar lun;                      /* Logical Unit Number */
266         uchar pad1[3];
267
268         uchar scntl3;
269         uchar sxfer;
270         uchar pad2[2];
271
272         uchar next[4];                  /* chaining for SCRIPT (NCR byte order) */
273         struct Dsa *freechain;          /* chaining for freelist */
274         Rendez;
275         uchar scsi_id_buf[4];
276         Movedata msg_out_buf;
277         Movedata cmd_buf;
278         Movedata data_buf;
279         Movedata status_buf;
280         uchar msg_out[10];              /* enough to include SDTR */
281         uchar status;
282         int p9status;
283         uchar parityerror;
284 } Dsa;
285
286 typedef enum Feature {
287         BigFifo = 1,                    /* 536 byte fifo */
288         BurstOpCodeFetch = 2,           /* burst fetch opcodes */
289         Prefetch = 4,                   /* prefetch 8 longwords */
290         LocalRAM = 8,                   /* 4K longwords of local RAM */
291         Differential = 16,              /* Differential support */
292         Wide = 32,                      /* Wide capable */
293         Ultra = 64,                     /* Ultra capable */
294         ClockDouble = 128,              /* Has clock doubler */
295         ClockQuad = 256,                /* Has clock quadrupler (same as Ultra2) */
296         Ultra2 = 256,
297 } Feature;
298
299 typedef enum Burst {
300         Burst2 = 0,
301         Burst4 = 1,
302         Burst8 = 2,
303         Burst16 = 3,
304         Burst32 = 4,
305         Burst64 = 5,
306         Burst128 = 6
307 } Burst;
308
309 typedef struct Variant {
310         ushort did;
311         uchar maxrid;                   /* maximum allowed revision ID */
312         char *name;
313         Burst burst;                    /* codings for max burst */
314         uchar maxsyncoff;               /* max synchronous offset */
315         uchar registers;                /* number of 32 bit registers */
316         unsigned feature;
317 } Variant;
318
319 static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
320 #define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
321 #define NULTRASCF (NULTRA2SCF - 2)
322 #define NSCF (NULTRASCF - 1)
323
324 typedef struct Controller {
325         Lock;
326         struct {
327                 uchar scntl3;
328                 uchar stest2;
329         } bios;
330         uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
331         NegoState s[MAXTARGET];
332         uchar scntl3[MAXTARGET];
333         uchar sxfer[MAXTARGET];
334         uchar cap[MAXTARGET];           /* capabilities byte from Identify */
335         ushort capvalid;                /* bit per target for validity of cap[] */
336         ushort wide;                    /* bit per target set if wide negotiated */
337         ulong sclk;                     /* clock speed of controller */
338         uchar clockmult;                /* set by synctabinit */
339         uchar ccf;                      /* CCF bits */
340         uchar tpf;                      /* best tpf value for this controller */
341         uchar feature;                  /* requested features */
342         int running;                    /* is the script processor running? */
343         int ssm;                        /* single step mode */
344         Ncr *n;                         /* pointer to registers */
345         Variant *v;                     /* pointer to variant type */
346         ulong *script;                  /* where the real script is */
347         ulong scriptpa;                 /* where the real script is */
348         Pcidev* pcidev;
349         SDev*   sdev;
350
351         struct {
352                 Lock;
353                 uchar head[4];          /* head of free list (NCR byte order) */
354                 Dsa     *tail;
355                 Dsa     *freechain;
356         } dsalist;
357
358         QLock q[MAXTARGET];             /* queues for each target */
359 } Controller;
360
361 static Controller controller;
362
363 /* ISTAT */
364 enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
365
366 /* DSTAT */
367 enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
368
369 /* SSTAT */
370 enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
371
372 static void setmovedata(Movedata*, ulong, ulong);
373 static void advancedata(Movedata*, long);
374 static int bios_set_differential(Controller *c);
375
376 static char *phase[] = {
377         "data out", "data in", "command", "status",
378         "reserved out", "reserved in", "message out", "message in"
379 };
380
381 #ifdef BOOTDEBUG
382 #define DEBUGSIZE 10240
383 char debugbuf[DEBUGSIZE];
384 char *debuglast;
385
386 static void
387 intrprint(char *format, ...)
388 {
389         if (debuglast == 0)
390                 debuglast = debugbuf;
391         debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
392 }
393
394 static void
395 iflush()
396 {
397         int s;
398         char *endp;
399         s = splhi();
400         if (debuglast == 0)
401                 debuglast = debugbuf;
402         if (debuglast == debugbuf) {
403                 splx(s);
404                 return;
405         }
406         endp = debuglast;
407         splx(s);
408         screenputs(debugbuf, endp - debugbuf);
409         s = splhi();
410         memmove(debugbuf, endp, debuglast - endp);
411         debuglast -= endp - debugbuf;
412         splx(s);
413 }
414
415 static void
416 oprint(char *format, ...)
417 {
418         int s;
419
420         iflush();
421         s = splhi();
422         if (debuglast == 0)
423                 debuglast = debugbuf;
424         debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
425         splx(s);
426         iflush();       
427 }
428 #endif
429
430 #include "sd53c8xx.i"
431
432 static Dsa *
433 dsaalloc(Controller *c, int target, int lun)
434 {
435         Dsa *d;
436
437         ilock(&c->dsalist);
438         if ((d = c->dsalist.freechain) == 0) {
439                 d = xalloc(sizeof(*d));
440                 if (DEBUG(1))
441                         KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d);
442                 lesetl(d->next, 0);
443                 lesetl(d->state, A_STATE_ALLOCATED);
444                 if (legetl(c->dsalist.head) == 0)
445                         lesetl(c->dsalist.head, DMASEG(d));     /* ATOMIC?!? */
446                 else
447                         lesetl(c->dsalist.tail->next, DMASEG(d));       /* ATOMIC?!? */
448                 c->dsalist.tail = d;
449         }
450         else {
451                 if (DEBUG(1))
452                         KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d);
453                 c->dsalist.freechain = d->freechain;
454                 lesetl(d->state, A_STATE_ALLOCATED);
455         }
456         iunlock(&c->dsalist);
457         d->target = target;
458         d->lun = lun;
459         return d;
460 }
461
462 static void
463 dsafree(Controller *c, Dsa *d)
464 {
465         ilock(&c->dsalist);
466         d->freechain = c->dsalist.freechain;
467         c->dsalist.freechain = d;
468         lesetl(d->state, A_STATE_FREE);
469         iunlock(&c->dsalist);
470 }
471
472 static Dsa *
473 dsafind(Controller *c, uchar target, uchar lun, uchar state)
474 {
475         Dsa *d;
476         for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
477                 if (d->target != 0xff && d->target != target)
478                         continue;
479                 if (lun != 0xff && d->lun != lun)
480                         continue;
481                 if (state != 0xff && d->stateb != state)
482                         continue;
483                 break;
484         }
485         return d;
486 }
487
488 static void
489 dumpncrregs(Controller *c, int intr)
490 {
491         int i;
492         Ncr *n = c->n;
493         int depth = c->v->registers / 4;
494
495         KPRINT("sa = %.8lux\n", c->scriptpa);
496         for (i = 0; i < depth; i++) {
497                 int j;
498                 for (j = 0; j < 4; j++) {
499                         int k = j * depth + i;
500                         uchar *p;
501
502                         /* display little-endian to make 32-bit values readable */
503                         p = (uchar*)n+k*4;
504                         if (intr)
505                                 IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
506                         else
507                                 KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
508                         USED(p);
509                 }
510                 if (intr)
511                         IPRINT("\n");
512                 else
513                         KPRINT("\n");
514         }
515 }       
516
517 static int
518 chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
519 {
520         /* find lowest entry >= tpf */
521         int besttpf = 1000;
522         int bestscfi = 0;
523         int bestxferp = 0;
524         int scf, xferp;
525         int maxscf;
526
527         if (c->v->feature & Ultra2)
528                 maxscf = NULTRA2SCF;
529         else if (c->v->feature & Ultra)
530                 maxscf = NULTRASCF;
531         else
532                 maxscf = NSCF;
533
534         /*
535          * search large clock factors first since this should
536          * result in more reliable transfers
537          */
538         for (scf = maxscf; scf >= 1; scf--) {
539                 for (xferp = 0; xferp < 8; xferp++) {
540                         unsigned char v = c->synctab[scf - 1][xferp];
541                         if (v == 0)
542                                 continue;
543                         if (v >= tpf && v < besttpf) {
544                                 besttpf = v;
545                                 bestscfi = scf;
546                                 bestxferp = xferp;
547                         }
548                 }
549         }
550         if (besttpf == 1000)
551                 return 0;
552         if (scfp)
553                 *scfp = bestscfi;
554         if (xferpp)
555                 *xferpp = bestxferp;
556         return besttpf;
557 }
558
559 static void
560 synctabinit(Controller *c)
561 {
562         int scf;
563         unsigned long scsilimit;
564         int xferp;
565         unsigned long cr, sr;
566         int tpf;
567         int fast;
568         int maxscf;
569
570         if (c->v->feature & Ultra2)
571                 maxscf = NULTRA2SCF;
572         else if (c->v->feature & Ultra)
573                 maxscf = NULTRASCF;
574         else
575                 maxscf = NSCF;
576
577         /*
578          * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
579          * first spin of the 875), assume 80MHz
580          * otherwise use the internal (33 Mhz) or external (40MHz) default
581          */
582
583         if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
584                 c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
585         else
586                 c->sclk = SCLK;
587
588         /*
589          * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
590          * invoke the doubler
591          */
592
593         if (SCLK <= 40000000) {
594                 if (c->v->feature & ClockDouble) {
595                         c->sclk *= 2;
596                         c->clockmult = 1;
597                 }
598                 else if (c->v->feature & ClockQuad) {
599                         c->sclk *= 4;
600                         c->clockmult = 1;
601                 }
602                 else
603                         c->clockmult = 0;
604         }
605         else
606                 c->clockmult = 0;
607
608         /* derive CCF from sclk */
609         /* woebetide anyone with SCLK < 16.7 or > 80MHz */
610         if (c->sclk <= 25 * MEGA)
611                 c->ccf = 1;
612         else if (c->sclk <= 3750000)
613                 c->ccf = 2;
614         else if (c->sclk <= 50 * MEGA)
615                 c->ccf = 3;
616         else if (c->sclk <= 75 * MEGA)
617                 c->ccf = 4;
618         else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
619                 c->ccf = 5;
620         else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
621                 c->ccf = 6;
622         else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
623                 c->ccf = 7;
624
625         for (scf = 1; scf < maxscf; scf++) {
626                 /* check for legal core rate */
627                 /* round up so we run slower for safety */
628                 cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
629                 if (cr <= MAXSYNCCORERATE) {
630                         scsilimit = MAXSYNCSCSIRATE;
631                         fast = 0;
632                 }
633                 else if (cr <= MAXFASTSYNCCORERATE) {
634                         scsilimit = MAXFASTSYNCSCSIRATE;
635                         fast = 1;
636                 }
637                 else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
638                         scsilimit = MAXULTRASYNCSCSIRATE;
639                         fast = 2;
640                 }
641                 else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
642                         scsilimit = MAXULTRA2SYNCSCSIRATE;
643                         fast = 3;
644                 }
645                 else
646                         continue;
647                 for (xferp = 11; xferp >= 4; xferp--) {
648                         int ok;
649                         int tp;
650                         /* calculate scsi rate - round up again */
651                         /* start from sclk for accuracy */
652                         int totaldivide = xferp * cf2[scf];
653                         sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
654                         if (sr > scsilimit)
655                                 break;
656                         /*
657                          * now work out transfer period
658                          * round down now so that period is pessimistic
659                          */
660                         tp = (MEGA * 1000) / sr;
661                         /*
662                          * bounds check it
663                          */
664                         if (tp < 25 || tp > 255 * 4)
665                                 continue;
666                         /*
667                          * spot stupid special case for Ultra or Ultra2
668                          * while working out factor
669                          */
670                         if (tp == 25)
671                                 tpf = 10;
672                         else if (tp == 50)
673                                 tpf = 12;
674                         else if (tp < 52)
675                                 continue;
676                         else
677                                 tpf = tp / 4;
678                         /*
679                          * now check tpf looks sensible
680                          * given core rate
681                          */
682                         switch (fast) {
683                         case 0:
684                                 /* scf must be ccf for SCSI 1 */
685                                 ok = tpf >= 50 && scf == c->ccf;
686                                 break;
687                         case 1:
688                                 ok = tpf >= 25 && tpf < 50;
689                                 break;
690                         case 2:
691                                 /*
692                                  * must use xferp of 4, or 5 at a pinch
693                                  * for an Ultra transfer
694                                  */
695                                 ok = xferp <= 5 && tpf >= 12 && tpf < 25;
696                                 break;
697                         case 3:
698                                 ok = xferp == 4 && (tpf == 10 || tpf == 11);
699                                 break;
700                         default:
701                                 ok = 0;
702                         }
703                         if (!ok)
704                                 continue;
705                         c->synctab[scf - 1][xferp - 4] = tpf;
706                 }
707         }
708
709 #ifndef NO_ULTRA2
710         if (c->v->feature & Ultra2)
711                 tpf = 10;
712         else
713 #endif
714         if (c->v->feature & Ultra)
715                 tpf = 12;
716         else
717                 tpf = 25;
718         for (; tpf < 256; tpf++) {
719                 if (chooserate(c, tpf, &scf, &xferp) == tpf) {
720                         unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
721                         unsigned long khz = (MEGA + tp - 1) / (tp);
722                         KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
723                             tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
724                             xferp + 4, khz / 1000, khz % 1000);
725                         USED(khz);
726                         if (c->tpf == 0)
727                                 c->tpf = tpf;   /* note lowest value for controller */
728                 }
729         }
730 }
731
732 static void
733 synctodsa(Dsa *dsa, Controller *c)
734 {
735 /*
736         KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
737             dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
738 */
739         dsa->scntl3 = c->scntl3[dsa->target];
740         dsa->sxfer = c->sxfer[dsa->target];
741 }
742
743 static void
744 setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
745 {
746         c->scntl3[target] =
747             (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
748         c->sxfer[target] = (xferp << 5) | reqack;
749         c->s[target] = BothDone;
750         if (dsa) {
751                 synctodsa(dsa, c);
752                 c->n->scntl3 = c->scntl3[target];
753                 c->n->sxfer = c->sxfer[target];
754         }
755 }
756
757 static void
758 setasync(Dsa *dsa, Controller *c, int target)
759 {
760         setsync(dsa, c, target, 0, c->ccf, 0, 0);
761 }
762
763 static void
764 setwide(Dsa *dsa, Controller *c, int target, uchar wide)
765 {
766         c->scntl3[target] = wide ? (1 << 3) : 0;
767         setasync(dsa, c, target);
768         c->s[target] = WideDone;
769 }
770
771 static int
772 buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
773 {
774         *buf++ = X_MSG;
775         *buf++ = 3;
776         *buf++ = X_MSG_SDTR;
777         *buf++ = tpf;
778         *buf = offset;
779         return 5;
780 }
781
782 static int
783 buildwdtrmsg(uchar *buf, uchar expo)
784 {
785         *buf++ = X_MSG;
786         *buf++ = 2;
787         *buf++ = X_MSG_WDTR;
788         *buf = expo;
789         return 4;
790 }
791
792 static void
793 start(Controller *c, long entry)
794 {
795         ulong p;
796
797         if (c->running)
798                 panic("sd53c8xx: start called while running");
799         c->running = 1;
800         p = c->scriptpa + entry;
801         lesetl(c->n->dsp, p);
802         if (c->ssm)
803                 c->n->dcntl |= 0x4;             /* start DMA in SSI mode */
804 }
805
806 static void
807 ncrcontinue(Controller *c)
808 {
809         if (c->running)
810                 panic("sd53c8xx: ncrcontinue called while running");
811         /* set the start DMA bit to continue execution */
812         c->running = 1;
813         c->n->dcntl |= 0x4;
814 }
815
816 static void
817 softreset(Controller *c)
818 {
819         Ncr *n = c->n;
820
821         n->istat = Srst;                /* software reset */
822         n->istat = 0;
823         /* general initialisation */
824         n->scid = (1 << 6) | 7;         /* respond to reselect, ID 7 */
825         n->respid = 1 << 7;             /* response ID = 7 */
826
827 #ifdef INTERNAL_SCLK
828         n->stest1 = 0x80;               /* disable external scsi clock */
829 #else
830         n->stest1 = 0x00;
831 #endif
832
833         n->stime0 = 0xdd;               /* about 0.5 second timeout on each device */
834         n->scntl0 |= 0x8;               /* Enable parity checking */
835
836         /* continued setup */
837         n->sien0 = 0x8f;
838         n->sien1 = 0x04;
839         n->dien = 0x7d;
840         n->stest3 = 0x80;               /* TolerANT enable */
841         c->running = 0;
842
843         if (c->v->feature & BigFifo)
844                 n->ctest5 = (1 << 5);
845         n->dmode = c->v->burst << 6;    /* set burst length bits */
846         if (c->v->burst & 4)
847                 n->ctest5 |= (1 << 2);  /* including overflow into ctest5 bit 2 */
848         if (c->v->feature & Prefetch)
849                 n->dcntl |= (1 << 5);   /* prefetch enable */
850         else if (c->v->feature & BurstOpCodeFetch)
851                 n->dmode |= (1 << 1);   /* burst opcode fetch */
852         if (c->v->feature & Differential) {
853                 /* chip capable */
854                 if ((c->feature & Differential) || bios_set_differential(c)) {
855                         /* user enabled, or some evidence bios set differential */
856                         if (n->sstat2 & (1 << 2))
857                                 print("sd53c8xx: can't go differential; wrong cable\n");
858                         else {
859                                 n->stest2 = (1 << 5);
860                                 print("sd53c8xx: differential mode set\n");
861                         }
862                 }
863         }
864         if (c->clockmult) {
865                 n->stest1 |= (1 << 3);  /* power up doubler */
866                 delay(2);
867                 n->stest3 |= (1 << 5);  /* stop clock */
868                 n->stest1 |= (1 << 2);  /* enable doubler */
869                 n->stest3 &= ~(1 << 5); /* start clock */
870                 /* pray */
871         }
872 }
873
874 static void
875 msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
876 {
877         uchar histpf, hisreqack;
878         int tpf;
879         int scf, xferp;
880         int len;
881
882         Ncr *n = c->n;
883
884         switch (c->s[dsa->target]) {
885         case SyncInit:
886                 switch (msg) {
887                 case A_SIR_MSG_SDTR:
888                         /* reply to my SDTR */
889                         histpf = n->scratcha[2];
890                         hisreqack = n->scratcha[3];
891                         KPRINT("sd53c8xx: %d: SDTN response %d %d\n",
892                             dsa->target, histpf, hisreqack);
893
894                         if (hisreqack == 0)
895                                 setasync(dsa, c, dsa->target);
896                         else {
897                                 /* hisreqack should be <= c->v->maxsyncoff */
898                                 tpf = chooserate(c, histpf, &scf, &xferp);
899                                 KPRINT("sd53c8xx: %d: SDTN: using %d %d\n",
900                                     dsa->target, tpf, hisreqack);
901                                 setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
902                         }
903                         *cont = -2;
904                         return;
905                 case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
906                         /* target ignored ATN for message after IDENTIFY - not SCSI-II */
907                         KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
908                         KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
909                         setasync(dsa, c, dsa->target);
910                         *cont = E_to_decisions;
911                         return;
912                 case A_SIR_MSG_REJECT:
913                         /* rejection of my SDTR */
914                         KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target);
915                 //async:
916                         KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
917                         setasync(dsa, c, dsa->target);
918                         *cont = -2;
919                         return;
920                 }
921                 break;
922         case WideInit:
923                 switch (msg) {
924                 case A_SIR_MSG_WDTR:
925                         /* reply to my WDTR */
926                         KPRINT("sd53c8xx: %d: WDTN: response %d\n",
927                             dsa->target, n->scratcha[2]);
928                         setwide(dsa, c, dsa->target, n->scratcha[2]);
929                         *cont = -2;
930                         return;
931                 case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
932                         /* target ignored ATN for message after IDENTIFY - not SCSI-II */
933                         KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
934                         setwide(dsa, c, dsa->target, 0);
935                         *cont = E_to_decisions;
936                         return;
937                 case A_SIR_MSG_REJECT:
938                         /* rejection of my SDTR */
939                         KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target);
940                         setwide(dsa, c, dsa->target, 0);
941                         *cont = -2;
942                         return;
943                 }
944                 break;
945
946         case NeitherDone:
947         case WideDone:
948         case BothDone:
949                 switch (msg) {
950                 case A_SIR_MSG_WDTR: {
951                         uchar hiswide, mywide;
952                         hiswide = n->scratcha[2];
953                         mywide = (c->v->feature & Wide) != 0;
954                         KPRINT("sd53c8xx: %d: WDTN: target init %d\n",
955                             dsa->target, hiswide);
956                         if (hiswide < mywide)
957                                 mywide = hiswide;
958                         KPRINT("sd53c8xx: %d: WDTN: responding %d\n",
959                             dsa->target, mywide);
960                         setwide(dsa, c, dsa->target, mywide);
961                         len = buildwdtrmsg(dsa->msg_out, mywide);
962                         setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
963                         *cont = E_response;
964                         c->s[dsa->target] = WideResponse;
965                         return;
966                 }
967                 case A_SIR_MSG_SDTR:
968 #ifdef ASYNC_ONLY
969                         *cont = E_reject;
970                         return;
971 #else
972                         /* target decides to renegotiate */
973                         histpf = n->scratcha[2];
974                         hisreqack = n->scratcha[3];
975                         KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n",
976                             dsa->target, histpf, hisreqack);
977                         if (hisreqack == 0) {
978                                 /* he wants asynchronous */
979                                 setasync(dsa, c, dsa->target);
980                                 tpf = 0;
981                         }
982                         else {
983                                 /* he wants synchronous */
984                                 tpf = chooserate(c, histpf, &scf, &xferp);
985                                 if (hisreqack > c->v->maxsyncoff)
986                                         hisreqack = c->v->maxsyncoff;
987                                 KPRINT("sd53c8xx: %d: using %d %d\n",
988                                     dsa->target, tpf, hisreqack);
989                                 setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
990                         }
991                         /* build my SDTR message */
992                         len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
993                         setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
994                         *cont = E_response;
995                         c->s[dsa->target] = SyncResponse;
996                         return;
997 #endif
998                 }
999                 break;
1000         case WideResponse:
1001                 switch (msg) {
1002                 case A_SIR_EV_RESPONSE_OK:
1003                         c->s[dsa->target] = WideDone;
1004                         KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target);
1005                         *cont = -2;
1006                         return;
1007                 case A_SIR_MSG_REJECT:
1008                         setwide(dsa, c, dsa->target, 0);
1009                         KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target);
1010                         *cont = -2;
1011                         return;
1012                 }
1013                 break;
1014         case SyncResponse:
1015                 switch (msg) {
1016                 case A_SIR_EV_RESPONSE_OK:
1017                         c->s[dsa->target] = BothDone;
1018                         KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n",
1019                             dsa->target, phase[n->sstat1 & 7]);
1020                         *cont = -2;
1021                         return; /* chf */
1022                 case A_SIR_MSG_REJECT:
1023                         setasync(dsa, c, dsa->target);
1024                         KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target);
1025                         *cont = -2;
1026                         return;
1027                 }
1028                 break;
1029         }
1030         KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n",
1031             dsa->target, c->s[dsa->target], msg);
1032         *wakeme = 1;
1033         return;
1034 }
1035
1036 static void
1037 calcblockdma(Dsa *d, ulong base, ulong count)
1038 {
1039         ulong blocks;
1040         if (DEBUG(3))
1041                 blocks = 0;
1042         else {
1043                 blocks = count / A_BSIZE;
1044                 if (blocks > 255)
1045                         blocks = 255;
1046         }
1047         d->dmablks = blocks;
1048         d->dmaaddr[0] = base;
1049         d->dmaaddr[1] = base >> 8;
1050         d->dmaaddr[2] = base >> 16;
1051         d->dmaaddr[3] = base >> 24;
1052         setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
1053         if (legetl(d->data_buf.dbc) == 0)
1054                 d->flag = 1;
1055 }
1056
1057 static ulong
1058 read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
1059 {
1060         ulong dbc;
1061         uchar dfifo = n->dfifo;
1062         int inchip;
1063
1064         dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
1065         if (n->ctest5 & (1 << 5))
1066                 inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
1067         else
1068                 inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
1069         if (inchip) {
1070                 IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n",
1071                     dsa->target, dsa->lun, inchip);
1072         }
1073         if (n->sxfer & 0xf) {
1074                 /* SCSI FIFO */
1075                 uchar fifo = n->sstat1 >> 4;
1076                 if (c->v->maxsyncoff > 8)
1077                         fifo |= (n->sstat2 & (1 << 4));
1078                 if (fifo) {
1079                         inchip += fifo;
1080                         IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
1081                             dsa->target, dsa->lun, fifo);
1082                 }
1083         }
1084         else {
1085                 if (n->sstat0 & (1 << 7)) {
1086                         inchip++;
1087                         IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n",
1088                             dsa->target, dsa->lun);
1089                 }
1090                 if (n->sstat2 & (1 << 7)) {
1091                         inchip++;
1092                         IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n",
1093                             dsa->target, dsa->lun);
1094                 }
1095         }
1096         USED(inchip);
1097         return dbc;
1098 }
1099
1100 static ulong
1101 write_mismatch_recover(Ncr *n, Dsa *dsa)
1102 {
1103         ulong dbc;
1104         uchar dfifo = n->dfifo;
1105         int inchip;
1106
1107         dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
1108         USED(dsa);
1109         if (n->ctest5 & (1 << 5))
1110                 inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
1111         else
1112                 inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
1113 #ifdef WMR_DEBUG
1114         if (inchip) {
1115                 IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n",
1116                     dsa->target, dsa->lun, inchip);
1117         }
1118 #endif
1119         if (n->sstat0 & (1 << 5)) {
1120                 inchip++;
1121 #ifdef WMR_DEBUG
1122                 IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
1123 #endif
1124         }
1125         if (n->sstat2 & (1 << 5)) {
1126                 inchip++;
1127 #ifdef WMR_DEBUG
1128                 IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
1129 #endif
1130         }
1131         if (n->sxfer & 0xf) {
1132                 /* synchronous SODR */
1133                 if (n->sstat0 & (1 << 6)) {
1134                         inchip++;
1135 #ifdef WMR_DEBUG
1136                         IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n",
1137                             dsa->target, dsa->lun);
1138 #endif
1139                 }
1140                 if (n->sstat2 & (1 << 6)) {
1141                         inchip++;
1142 #ifdef WMR_DEBUG
1143                         IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n",
1144                             dsa->target, dsa->lun);
1145 #endif
1146                 }
1147         }
1148         /* clear the dma fifo */
1149         n->ctest3 |= (1 << 2);
1150         /* wait till done */
1151         while ((n->dstat & Dfe) == 0)
1152                 ;
1153         return dbc + inchip;
1154 }
1155
1156 static void
1157 interrupt(Ureg *ur, void *a)
1158 {
1159         uchar istat;
1160         ushort sist;
1161         uchar dstat;
1162         int wakeme = 0;
1163         int cont = -1;
1164         Dsa *dsa;
1165         Controller *c = a;
1166         Ncr *n = c->n;
1167
1168         USED(ur);
1169         if (DEBUG(1))
1170                 IPRINT("sd53c8xx: int\n");
1171         ilock(c);
1172         istat = n->istat;
1173         if (istat & Intf) {
1174                 Dsa *d;
1175                 int wokesomething = 0;
1176                 if (DEBUG(1))
1177                         IPRINT("sd53c8xx: Intfly\n");
1178                 n->istat = Intf;
1179                 /* search for structures in A_STATE_DONE */
1180                 for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
1181                         if (d->stateb == A_STATE_DONE) {
1182                                 d->p9status = d->status;
1183                                 if (DEBUG(1))
1184                                         IPRINT("sd53c8xx: waking up dsa %lux\n", d);
1185                                 wakeup(d);
1186                                 wokesomething = 1;
1187                         }
1188                 }
1189                 if (!wokesomething)
1190                         IPRINT("sd53c8xx: nothing to wake up\n");
1191         }
1192
1193         if ((istat & (Sip | Dip)) == 0) {
1194                 if (DEBUG(1))
1195                         IPRINT("sd53c8xx: int end %x\n", istat);
1196                 iunlock(c);
1197                 return;
1198         }
1199
1200         sist = (n->sist1<<8)|n->sist0;  /* BUG? can two-byte read be inconsistent? */
1201         dstat = n->dstat;
1202         dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
1203         c->running = 0;
1204         if (istat & Sip) {
1205                 if (DEBUG(1))
1206                         IPRINT("sist = %.4x\n", sist);
1207                 if (sist & 0x80) {
1208                         ulong addr;
1209                         ulong sa;
1210                         ulong dbc;
1211                         ulong tbc;
1212                         int dmablks;
1213                         ulong dmaaddr;
1214
1215                         addr = legetl(n->dsp);
1216                         sa = addr - c->scriptpa;
1217                         if (DEBUG(1) || DEBUG(2))
1218                                 IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n",
1219                                     dsa->target, dsa->lun, sa);
1220                         /*
1221                          * now recover
1222                          */
1223                         if (sa == E_data_in_mismatch) {
1224                                 dbc = read_mismatch_recover(c, n, dsa);
1225                                 tbc = legetl(dsa->data_buf.dbc) - dbc;
1226                                 advancedata(&dsa->data_buf, tbc);
1227                                 if (DEBUG(1) || DEBUG(2))
1228                                         IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
1229                                             dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
1230                                 cont = E_to_decisions;
1231                         }
1232                         else if (sa == E_data_in_block_mismatch) {
1233                                 dbc = read_mismatch_recover(c, n, dsa);
1234                                 tbc = A_BSIZE - dbc;
1235                                 /* recover current state from registers */
1236                                 dmablks = n->scratcha[2];
1237                                 dmaaddr = legetl(n->scratchb);
1238                                 /* we have got to dmaaddr + tbc */
1239                                 /* we have dmablks * A_BSIZE - tbc + residue left to do */
1240                                 /* so remaining transfer is */
1241                                 IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
1242                                     dmaaddr, tbc, dmablks);
1243                                 calcblockdma(dsa, dmaaddr + tbc,
1244                                     dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
1245                                 /* copy changes into scratch registers */
1246                                 IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
1247                                     dsa->dmablks, legetl(dsa->dmaaddr),
1248                                     legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
1249                                 n->scratcha[2] = dsa->dmablks;
1250                                 lesetl(n->scratchb, dsa->dmancr);
1251                                 cont = E_data_block_mismatch_recover;
1252                         }
1253                         else if (sa == E_data_out_mismatch) {
1254                                 dbc = write_mismatch_recover(n, dsa);
1255                                 tbc = legetl(dsa->data_buf.dbc) - dbc;
1256                                 advancedata(&dsa->data_buf, tbc);
1257                                 if (DEBUG(1) || DEBUG(2))
1258                                         IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
1259                                             dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
1260                                 cont = E_to_decisions;
1261                         }
1262                         else if (sa == E_data_out_block_mismatch) {
1263                                 dbc = write_mismatch_recover(n, dsa);
1264                                 tbc = legetl(dsa->data_buf.dbc) - dbc;
1265                                 /* recover current state from registers */
1266                                 dmablks = n->scratcha[2];
1267                                 dmaaddr = legetl(n->scratchb);
1268                                 /* we have got to dmaaddr + tbc */
1269                                 /* we have dmablks blocks - tbc + residue left to do */
1270                                 /* so remaining transfer is */
1271                                 IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
1272                                     dmaaddr, tbc, dmablks);
1273                                 calcblockdma(dsa, dmaaddr + tbc,
1274                                     dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
1275                                 /* copy changes into scratch registers */
1276                                 n->scratcha[2] = dsa->dmablks;
1277                                 lesetl(n->scratchb, dsa->dmancr);
1278                                 cont = E_data_block_mismatch_recover;
1279                         }
1280                         else if (sa == E_id_out_mismatch) {
1281                                 /*
1282                                  * target switched phases while attention held during
1283                                  * message out. The possibilities are:
1284                                  * 1. It didn't like the last message. This is indicated
1285                                  *    by the new phase being message_in. Use script to recover
1286                                  *
1287                                  * 2. It's not SCSI-II compliant. The new phase will be other
1288                                  *    than message_in. We should also indicate that the device
1289                                  *    is asynchronous, if it's the SDTR that got ignored
1290                                  * 
1291                                  * For now, if the phase switch is not to message_in, and
1292                                  * and it happens after IDENTIFY and before SDTR, we
1293                                  * notify the negotiation state machine.
1294                                  */
1295                                 ulong lim = legetl(dsa->msg_out_buf.dbc);
1296                                 uchar p = n->sstat1 & 7;
1297                                 dbc = write_mismatch_recover(n, dsa);
1298                                 tbc = lim - dbc;
1299                                 IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
1300                                     dsa->target, dsa->lun, tbc, lim, phase[p]);
1301                                 if (p != MessageIn && tbc == 1) {
1302                                         msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
1303                                 }
1304                                 else
1305                                         cont = E_id_out_mismatch_recover;
1306                         }
1307                         else if (sa == E_cmd_out_mismatch) {
1308                                 /*
1309                                  * probably the command count is longer than the device wants ...
1310                                  */
1311                                 ulong lim = legetl(dsa->cmd_buf.dbc);
1312                                 uchar p = n->sstat1 & 7;
1313                                 dbc = write_mismatch_recover(n, dsa);
1314                                 tbc = lim - dbc;
1315                                 IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
1316                                     dsa->target, dsa->lun, tbc, lim, phase[p]);
1317                                 USED(p, tbc);
1318                                 cont = E_to_decisions;
1319                         }
1320                         else {
1321                                 IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n",
1322                                     dsa->target, dsa->lun, sa,
1323                                     phase[n->dcmd & 7],
1324                                     phase[n->sstat1 & 7]);
1325                                 dumpncrregs(c, 1);
1326                                 dsa->p9status = SDeio;  /* chf */
1327                                 wakeme = 1;
1328                         }
1329                 }
1330                 /*else*/ if (sist & 0x400) {
1331                         if (DEBUG(0))
1332                                 IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun);
1333                         dsa->p9status = SDtimeout;
1334                         dsa->stateb = A_STATE_DONE;
1335                         softreset(c);
1336                         cont = E_issue_check;
1337                         wakeme = 1;
1338                 }
1339                 if (sist & 0x1) {
1340                         IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun);
1341                         dsa->parityerror = 1;
1342                 }
1343                 if (sist & 0x4) {
1344                         IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n",
1345                             dsa->target, dsa->lun);
1346                         dumpncrregs(c, 1);
1347                         //wakeme = 1;
1348                         dsa->p9status = SDeio;
1349                 }
1350         }
1351         if (istat & Dip) {
1352                 if (DEBUG(1))
1353                         IPRINT("dstat = %.2x\n", dstat);
1354                 /*else*/ if (dstat & Ssi) {
1355                         ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
1356                         ulong w = (uchar *)p - (uchar *)c->script;
1357                         IPRINT("[%lux]", w);
1358                         USED(w);
1359                         cont = -2;      /* restart */
1360                 }
1361                 if (dstat & Sir) {
1362                         switch (legetl(n->dsps)) {
1363                         case A_SIR_MSG_IO_COMPLETE:
1364                                 dsa->p9status = dsa->status;
1365                                 wakeme = 1;
1366                                 break;
1367                         case A_SIR_MSG_SDTR:
1368                         case A_SIR_MSG_WDTR:
1369                         case A_SIR_MSG_REJECT:
1370                         case A_SIR_EV_RESPONSE_OK:
1371                                 msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
1372                                 break;
1373                         case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
1374                                 /* back up one in the data transfer */
1375                                 IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n",
1376                                     dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
1377                                 if (dsa->dmablks == 0 && dsa->flag)
1378                                         IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n",
1379                                             dsa->target, dsa->lun);
1380                                 else
1381                                         calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
1382                                             dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
1383                                 cont = -2;
1384                                 break;
1385                         case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
1386                                 IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)",
1387                                     n->ssid & 7, phase[n->sstat1 & 7]);
1388                                 dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED);
1389                                 dumpncrregs(c, 1);
1390                                 wakeme = 1;
1391                                 break;
1392                         case A_SIR_NOTIFY_MSG_IN:
1393                                 IPRINT("sd53c8xx: %d/%d: msg_in %d\n",
1394                                     dsa->target, dsa->lun, n->sfbr);
1395                                 cont = -2;
1396                                 break;
1397                         case A_SIR_NOTIFY_DISC:
1398                                 IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun);
1399                                 goto dsadump;
1400                         case A_SIR_NOTIFY_STATUS:
1401                                 IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun);
1402                                 cont = -2;
1403                                 break;
1404                         case A_SIR_NOTIFY_COMMAND:
1405                                 IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun);
1406                                 cont = -2;
1407                                 break;
1408                         case A_SIR_NOTIFY_DATA_IN:
1409                                 IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n",
1410                                     dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
1411                                 cont = -2;
1412                                 break;
1413                         case A_SIR_NOTIFY_BLOCK_DATA_IN:
1414                                 IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n",
1415                                     dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
1416                                 cont = -2;
1417                                 break;
1418                         case A_SIR_NOTIFY_DATA_OUT:
1419                                 IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun);
1420                                 cont = -2;
1421                                 break;
1422                         case A_SIR_NOTIFY_DUMP:
1423                                 IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun);
1424                                 dumpncrregs(c, 1);
1425                                 cont = -2;
1426                                 break;
1427                         case A_SIR_NOTIFY_DUMP2:
1428                                 IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun);
1429                                 IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
1430                                 IPRINT(" dsa %lux", legetl(n->dsa));
1431                                 IPRINT(" sfbr %ux", n->sfbr);
1432                                 IPRINT(" a %lux", n->scratcha);
1433                                 IPRINT(" b %lux", legetl(n->scratchb));
1434                                 IPRINT(" ssid %ux", n->ssid);
1435                                 IPRINT("\n");
1436                                 cont = -2;
1437                                 break;
1438                         case A_SIR_NOTIFY_WAIT_RESELECT:
1439                                 IPRINT("sd53c8xx: wait reselect\n");
1440                                 cont = -2;
1441                                 break;
1442                         case A_SIR_NOTIFY_RESELECT:
1443                                 IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n",
1444                                     n->ssid, n->sfbr, TK2MS(m->ticks));
1445                                 cont = -2;
1446                                 break;
1447                         case A_SIR_NOTIFY_ISSUE:
1448                                 IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun);
1449                         dsadump:
1450                                 IPRINT(" tgt=%d", dsa->target);
1451                                 IPRINT(" time=%ld", TK2MS(m->ticks));
1452                                 IPRINT("\n");
1453                                 cont = -2;
1454                                 break;
1455                         case A_SIR_NOTIFY_ISSUE_CHECK:
1456                                 IPRINT("sd53c8xx: issue check\n");
1457                                 cont = -2;
1458                                 break;
1459                         case A_SIR_NOTIFY_SIGP:
1460                                 IPRINT("sd53c8xx: responded to SIGP\n");
1461                                 cont = -2;
1462                                 break;
1463                         case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
1464                                 ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
1465                                 int x;
1466                                 IPRINT("sd53c8xx: code at %lux", dsp - c->script);
1467                                 for (x = 0; x < 6; x++)
1468                                         IPRINT(" %.8lux", dsp[x]);
1469                                 IPRINT("\n");
1470                                 USED(dsp);
1471                                 cont = -2;
1472                                 break;
1473                         }
1474                         case A_SIR_NOTIFY_WSR:
1475                                 IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun);
1476                                 cont = -2;
1477                                 break;
1478                         case A_SIR_NOTIFY_LOAD_SYNC:
1479                                 IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n",
1480                                     dsa->target, dsa->lun, n->scntl3, n->sxfer);
1481                                 cont = -2;
1482                                 break;
1483                         case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
1484                                 IPRINT("sd53c8xx: %d/%d: reselected during select\n",
1485                                     dsa->target, dsa->lun);
1486                                 cont = -2;
1487                                 break;
1488                         default:
1489                                 IPRINT("sd53c8xx: %d/%d: script error %ld\n",
1490                                         dsa->target, dsa->lun, legetl(n->dsps));
1491                                 dumpncrregs(c, 1);
1492                                 wakeme = 1;
1493                         }
1494                 }
1495                 /*else*/ if (dstat & Iid) {
1496                         ulong addr = legetl(n->dsp);
1497                         ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
1498                         IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
1499                             dsa->target, dsa->lun,
1500                             addr, addr - c->scriptpa, dbc);
1501                         addr = (ulong)DMASEG_TO_KADDR(addr);
1502                         IPRINT("%.8lux %.8lux %.8lux\n",
1503                             *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
1504                         USED(addr, dbc);
1505                         dsa->p9status = SDeio;
1506                         wakeme = 1;
1507                 }
1508                 /*else*/ if (dstat & Bf) {
1509                         IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun);
1510                         dumpncrregs(c, 1);
1511                         dsa->p9status = SDeio;
1512                         wakeme = 1;
1513                 }
1514         }
1515         if (cont == -2)
1516                 ncrcontinue(c);
1517         else if (cont >= 0)
1518                 start(c, cont);
1519         if (wakeme){
1520                 if(dsa->p9status == SDnostatus)
1521                         dsa->p9status = SDeio;
1522                 wakeup(dsa);
1523         }
1524         iunlock(c);
1525         if (DEBUG(1)) {
1526                 IPRINT("sd53c8xx: int end 1\n");
1527         }
1528 }
1529
1530 static int
1531 done(void *arg)
1532 {
1533         return ((Dsa *)arg)->p9status != SDnostatus;
1534 }
1535
1536 static void
1537 setmovedata(Movedata *d, ulong pa, ulong bc)
1538 {
1539         d->pa[0] = pa;
1540         d->pa[1] = pa>>8;
1541         d->pa[2] = pa>>16;
1542         d->pa[3] = pa>>24;
1543         d->dbc[0] = bc;
1544         d->dbc[1] = bc>>8;
1545         d->dbc[2] = bc>>16;
1546         d->dbc[3] = bc>>24;
1547 }
1548
1549 static void
1550 advancedata(Movedata *d, long v)
1551 {
1552         lesetl(d->pa, legetl(d->pa) + v);
1553         lesetl(d->dbc, legetl(d->dbc) - v);
1554 }
1555
1556 static void
1557 dumpwritedata(uchar *data, int datalen)
1558 {
1559         int i;
1560         uchar *bp;
1561         if (!DEBUG(0)){
1562                 USED(data, datalen);
1563                 return;
1564         }
1565
1566         if (datalen) {
1567                 KPRINT("sd53c8xx:write:");
1568                 for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
1569                         KPRINT("%.2ux", *bp);
1570                 if (i < datalen) {
1571                         KPRINT("...");
1572                 }
1573                 KPRINT("\n");
1574         }
1575 }
1576
1577 static void
1578 dumpreaddata(uchar *data, int datalen)
1579 {
1580         int i;
1581         uchar *bp;
1582         if (!DEBUG(0)){
1583                 USED(data, datalen);
1584                 return;
1585         }
1586
1587         if (datalen) {
1588                 KPRINT("sd53c8xx:read:");
1589                 for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
1590                         KPRINT("%.2ux", *bp);
1591                 if (i < datalen) {
1592                         KPRINT("...");
1593                 }
1594                 KPRINT("\n");
1595         }
1596 }
1597
1598 static void
1599 busreset(Controller *c)
1600 {
1601         int x, ntarget;
1602
1603         /* bus reset */
1604         c->n->scntl1 |= (1 << 3);
1605         delay(500);
1606         c->n->scntl1 &= ~(1 << 3);
1607         if(!(c->v->feature & Wide))
1608                 ntarget = 8;
1609         else
1610                 ntarget = MAXTARGET;
1611         for (x = 0; x < ntarget; x++) {
1612                 setwide(0, c, x, 0);
1613 #ifndef ASYNC_ONLY
1614                 c->s[x] = NeitherDone;
1615 #endif
1616         }
1617         c->capvalid = 0;
1618 }
1619
1620 static void
1621 reset(Controller *c)
1622 {
1623         /* should wakeup all pending tasks */
1624         softreset(c);
1625         busreset(c);
1626 }
1627
1628 static int
1629 symrio(SDreq* r)
1630 {
1631         Dsa *d;
1632         uchar *bp;
1633         Controller *c;
1634         uchar target_expo, my_expo;
1635         int bc, check, status, target;
1636
1637         if((target = r->unit->subno) == 0x07)
1638                 return r->status = SDtimeout;   /* assign */
1639         c = r->unit->dev->ctlr;
1640
1641         check = 0;
1642         d = dsaalloc(c, target, r->lun);
1643
1644         qlock(&c->q[target]);                   /* obtain access to target */
1645 docheck:
1646         /* load the transfer control stuff */
1647         d->scsi_id_buf[0] = 0;
1648         d->scsi_id_buf[1] = c->sxfer[target];
1649         d->scsi_id_buf[2] = target;
1650         d->scsi_id_buf[3] = c->scntl3[target];
1651         synctodsa(d, c);
1652
1653         bc = 0;
1654
1655         d->msg_out[bc] = 0x80 | r->lun;
1656
1657 #ifndef NO_DISCONNECT
1658         d->msg_out[bc] |= (1 << 6);
1659 #endif
1660         bc++;
1661
1662         /* work out what to do about negotiation */
1663         switch (c->s[target]) {
1664         default:
1665                 KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]);
1666                 c->s[target] = NeitherDone;
1667                 /* fall through */
1668         case NeitherDone:
1669                 if ((c->capvalid & (1 << target)) == 0)
1670                         break;
1671                 target_expo = (c->cap[target] >> 5) & 3;
1672                 my_expo = (c->v->feature & Wide) != 0;
1673                 if (target_expo < my_expo)
1674                         my_expo = target_expo;
1675 #ifdef ALWAYS_DO_WDTR
1676                 bc += buildwdtrmsg(d->msg_out + bc, my_expo);
1677                 KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
1678                 c->s[target] = WideInit;
1679                 break;
1680 #else
1681                 if (my_expo) {
1682                         bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
1683                         KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
1684                         c->s[target] = WideInit;
1685                         break;
1686                 }
1687                 KPRINT("sd53c8xx: %d: WDTN: narrow\n", target);
1688                 /* fall through */
1689 #endif
1690         case WideDone:
1691                 if (c->cap[target] & (1 << 4)) {
1692                         KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
1693                         bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
1694                         c->s[target] = SyncInit;
1695                         break;
1696                 }
1697                 KPRINT("sd53c8xx: %d: SDTN: async only\n", target);
1698                 c->s[target] = BothDone;
1699                 break;
1700
1701         case BothDone:
1702                 break;
1703         }
1704
1705         setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
1706         setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
1707         calcblockdma(d, DMASEG(r->data), r->dlen);
1708
1709         if (DEBUG(0)) {
1710                 KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun);
1711                 for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++)
1712                         KPRINT("%.2ux", *bp);
1713                 KPRINT("\n");
1714                 if (!r->write)
1715                         KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n",
1716                           target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
1717                 else
1718                         dumpwritedata(r->data, r->dlen);
1719         }
1720
1721         setmovedata(&d->status_buf, DMASEG(&d->status), 1);     
1722
1723         d->p9status = SDnostatus;
1724         d->parityerror = 0;
1725
1726         d->stateb = A_STATE_ISSUE;              /* start operation */
1727
1728         ilock(c);
1729         if (c->ssm)
1730                 c->n->dcntl |= 0x10;            /* SSI */
1731         if (c->running) {
1732                 c->n->istat |= Sigp;
1733         }
1734         else {
1735                 start(c, E_issue_check);
1736         }
1737         iunlock(c);
1738
1739         while(waserror())
1740                 ;
1741         tsleep(d, done, d, 30 * 1000);
1742         poperror();
1743
1744         if (!done(d)) {
1745                 KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun);
1746                 dumpncrregs(c, 0);
1747                 dsafree(c, d);
1748                 reset(c);
1749                 qunlock(&c->q[target]);
1750                 r->status = SDtimeout;
1751                 return r->status = SDtimeout;   /* assign */
1752         }
1753
1754         if((status = d->p9status) == SDeio)
1755                 c->s[target] = NeitherDone;
1756         if (d->parityerror) {
1757                 status = SDeio;
1758         }
1759
1760         /*
1761          * adjust datalen
1762          */
1763         r->rlen = r->dlen;
1764         if (d->dmablks > 0)
1765                 r->rlen -= d->dmablks * A_BSIZE;
1766         else if (d->flag == 0)
1767                 r->rlen -= legetl(d->data_buf.dbc);
1768         if(!r->write)
1769                 dumpreaddata(r->data, r->rlen);
1770         if (DEBUG(0))
1771                 KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n",
1772                     target, r->lun, d->p9status, status, r->rlen);
1773         /*
1774          * spot the identify
1775          */
1776         if ((c->capvalid & (1 << target)) == 0
1777          && (status == SDok || status == SDcheck)
1778          && r->cmd[0] == 0x12 && r->dlen >= 8) {
1779                 c->capvalid |= 1 << target;
1780                 bp = r->data;
1781                 c->cap[target] = bp[7];
1782                 KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]);
1783         }
1784         if(!check && status == SDcheck && !(r->flags & SDnosense)){
1785                 check = 1;
1786                 r->write = 0;
1787                 memset(r->cmd, 0, sizeof(r->cmd));
1788                 r->cmd[0] = 0x03;
1789                 r->cmd[1] = r->lun<<5;
1790                 r->cmd[4] = sizeof(r->sense)-1;
1791                 r->clen = 6;
1792                 r->data = r->sense;
1793                 r->dlen = sizeof(r->sense)-1;
1794                 /*
1795                  * Clear out the microcode state
1796                  * so the Dsa can be re-used.
1797                  */
1798                 lesetl(d->state, A_STATE_ALLOCATED);
1799                 goto docheck;
1800         }
1801         qunlock(&c->q[target]);
1802         dsafree(c, d);
1803
1804         if(status == SDok && check){
1805                 status = SDcheck;
1806                 r->flags |= SDvalidsense;
1807         }
1808         KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n",
1809                 target, r->flags, status, r->rlen);
1810         return r->status = status;
1811 }
1812
1813 static void
1814 cribbios(Controller *c)
1815 {
1816         c->bios.scntl3 = c->n->scntl3;
1817         c->bios.stest2 = c->n->stest2;
1818         print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
1819 }
1820
1821 static int
1822 bios_set_differential(Controller *c)
1823 {
1824         /* Concept lifted from FreeBSD - thanks Gerard */
1825         /* basically, if clock conversion factors are set, then there is
1826          * evidence the bios had a go at the chip, and if so, it would
1827          * have set the differential enable bit in stest2
1828          */
1829         return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
1830 }
1831
1832 #define NCR_VID         0x1000
1833 #define NCR_810_DID     0x0001
1834 #define NCR_820_DID     0x0002  /* don't know enough about this one to support it */
1835 #define NCR_825_DID     0x0003
1836 #define NCR_815_DID     0x0004
1837 #define SYM_810AP_DID   0x0005
1838 #define SYM_860_DID     0x0006
1839 #define SYM_896_DID     0x000b
1840 #define SYM_895_DID     0x000c
1841 #define SYM_885_DID     0x000d  /* ditto */
1842 #define SYM_875_DID     0x000f  /* ditto */
1843 #define SYM_1010_DID    0x0020
1844 #define SYM_1011_DID    0x0021
1845 #define SYM_875J_DID    0x008f
1846
1847 static Variant variant[] = {
1848 { NCR_810_DID,   0x0f, "NCR53C810",     Burst16,   8, 24, 0 },
1849 { NCR_810_DID,   0x1f, "SYM53C810ALV",  Burst16,   8, 24, Prefetch },
1850 { NCR_810_DID,   0xff, "SYM53C810A",    Burst16,   8, 24, Prefetch },
1851 { SYM_810AP_DID, 0xff, "SYM53C810AP",   Burst16,   8, 24, Prefetch },
1852 { NCR_815_DID,   0xff, "NCR53C815",     Burst16,   8, 24, BurstOpCodeFetch },
1853 { NCR_825_DID,   0x0f, "NCR53C825",     Burst16,   8, 24, Wide|BurstOpCodeFetch|Differential },
1854 { NCR_825_DID,   0xff, "SYM53C825A",    Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
1855 { SYM_860_DID,   0x0f, "SYM53C860",     Burst16,   8, 24, Prefetch|Ultra },
1856 { SYM_860_DID,   0xff, "SYM53C860LV",   Burst16,   8, 24, Prefetch|Ultra },
1857 { SYM_875_DID,   0x01, "SYM53C875r1",   Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
1858 { SYM_875_DID,   0xff, "SYM53C875",     Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
1859 { SYM_875J_DID,   0xff, "SYM53C875j",   Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
1860 { SYM_885_DID,   0xff, "SYM53C885",     Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
1861 { SYM_895_DID,   0xff, "SYM53C895",     Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
1862 { SYM_896_DID,   0xff, "SYM53C896",     Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
1863 { SYM_1010_DID,   0xff, "SYM53C1010",   Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
1864 { SYM_1011_DID,   0xff, "SYM53C1010",   Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
1865 };
1866
1867
1868 static int
1869 xfunc(Controller *c, enum na_external x, unsigned long *v)
1870 {
1871         switch (x) {
1872         default:
1873                 print("xfunc: can't find external %d\n", x);
1874                 return 0;
1875         case X_scsi_id_buf:
1876                 *v = offsetof(Dsa, scsi_id_buf[0]);
1877                 break;
1878         case X_msg_out_buf:
1879                 *v = offsetof(Dsa, msg_out_buf);
1880                 break;
1881         case X_cmd_buf:
1882                 *v = offsetof(Dsa, cmd_buf);
1883                 break;
1884         case X_data_buf:
1885                 *v = offsetof(Dsa, data_buf);
1886                 break;
1887         case X_status_buf:
1888                 *v = offsetof(Dsa, status_buf);
1889                 break;
1890         case X_dsa_head:
1891                 *v = DMASEG(&c->dsalist.head[0]);
1892                 break;
1893         }
1894         return 1;
1895 }
1896
1897 static int
1898 na_fixup(Controller *c, ulong pa_reg,
1899     struct na_patch *patch, int patches,
1900     int (*externval)(Controller*, int, ulong*))
1901 {
1902         int p;
1903         int v;
1904         ulong *script, pa_script;
1905         unsigned long lw, lv;
1906
1907         script = c->script;
1908         pa_script = c->scriptpa;
1909         for (p = 0; p < patches; p++) {
1910                 switch (patch[p].type) {
1911                 case 1:
1912                         /* script relative */
1913                         script[patch[p].lwoff] += pa_script;
1914                         break;
1915                 case 2:
1916                         /* register i/o relative */
1917                         script[patch[p].lwoff] += pa_reg;
1918                         break;
1919                 case 3:
1920                         /* data external */
1921                         lw = script[patch[p].lwoff];
1922                         v = (lw >> 8) & 0xff;
1923                         if (!(*externval)(c, v, &lv))
1924                                 return 0;
1925                         v = lv & 0xff;
1926                         script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
1927                         break;
1928                 case 4:
1929                         /* 32 bit external */
1930                         lw = script[patch[p].lwoff];
1931                         if (!(*externval)(c, lw, &lv))
1932                                 return 0;
1933                         script[patch[p].lwoff] = lv;
1934                         break;
1935                 case 5:
1936                         /* 24 bit external */
1937                         lw = script[patch[p].lwoff];
1938                         if (!(*externval)(c, lw & 0xffffff, &lv))
1939                                 return 0;
1940                         script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
1941                         break;
1942                 }
1943         }
1944         return 1;
1945 }
1946
1947 static SDev*
1948 sympnp(void)
1949 {
1950         int ba;
1951         Pcidev *p;
1952         Variant *v;
1953         void *scriptma;
1954         Controller *ctlr;
1955         SDev *sdev, *head, *tail;
1956         ulong regpa, *script, scriptpa;
1957
1958         p = nil;
1959         head = tail = nil;
1960
1961         /* native access to disks seems to interfere with bios loading */
1962         if (biosload)
1963                 return nil;
1964
1965         while(p = pcimatch(p, NCR_VID, 0)){
1966                 for(v = variant; v < &variant[nelem(variant)]; v++){
1967                         if(p->did == v->did && p->rid <= v->maxrid)
1968                                 break;
1969                 }
1970                 if(v >= &variant[nelem(variant)])
1971                         continue;
1972                 print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4uX\n",
1973                         v->name, p->rid, p->intl, p->pcr);
1974
1975                 regpa = p->mem[1].bar;
1976                 ba = 2;
1977                 if(regpa & 0x04){
1978                         if(p->mem[2].bar)
1979                                 continue;
1980                         ba++;
1981                 }
1982                 regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
1983                 if(regpa == 0)
1984                         continue;
1985
1986                 script = nil;
1987                 scriptpa = 0;
1988                 scriptma = nil;
1989                 if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
1990                         scriptpa = p->mem[ba].bar;
1991                         if((scriptpa & 0x04) && p->mem[ba+1].bar){
1992                                 upafree(regpa, p->mem[1].size);
1993                                 continue;
1994                         }
1995                         scriptpa = upamalloc(scriptpa & ~0x0F,
1996                                         p->mem[ba].size, 0);
1997                         if(scriptpa)
1998                                 script = KADDR(scriptpa);
1999                 }
2000                 if(scriptpa == 0){
2001                         /*
2002                          * Either the map failed, or this chip does not have
2003                          * local RAM. It will need a copy of the microcode.
2004                          */
2005                         scriptma = malloc(sizeof(na_script));
2006                         if(scriptma == nil){
2007                                 upafree(regpa, p->mem[1].size);
2008                                 continue;
2009                         }
2010                         scriptpa = DMASEG(scriptma);
2011                         script = scriptma;
2012                 }
2013
2014                 ctlr = malloc(sizeof(Controller));
2015                 sdev = malloc(sizeof(SDev));
2016                 if(ctlr == nil || sdev == nil){
2017 buggery:
2018                         if(ctlr)
2019                                 free(ctlr);
2020                         if(sdev)
2021                                 free(sdev);
2022                         if(scriptma)
2023                                 free(scriptma);
2024                         else
2025                                 upafree(scriptpa, p->mem[ba].size);
2026                         upafree(regpa, p->mem[1].size);
2027                         continue;
2028                 }
2029
2030                 ctlr->n = KADDR(regpa);
2031                 ctlr->v = v;
2032                 ctlr->script = script;
2033                 memmove(ctlr->script, na_script, sizeof(na_script));
2034                 ctlr->scriptpa = scriptpa;
2035                 if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
2036                         print("script fixup failed\n");
2037                         goto buggery;
2038                 }
2039                 swabl(ctlr->script, ctlr->script, sizeof(na_script));
2040
2041                 ctlr->dsalist.freechain = 0;
2042                 lesetl(ctlr->dsalist.head, 0);
2043
2044                 ctlr->pcidev = p;
2045
2046                 sdev->ifc = &sd53c8xxifc;
2047                 sdev->ctlr = ctlr;
2048                 if(!(v->feature & Wide))
2049                         sdev->nunit = 8;
2050                 else
2051                         sdev->nunit = MAXTARGET;
2052                 ctlr->sdev = sdev;
2053
2054                 if(head != nil)
2055                         tail->next = sdev;
2056                 else
2057                         head = sdev;
2058                 tail = sdev;
2059         }
2060
2061         return head;
2062 }
2063
2064 static SDev*
2065 symid(SDev* sdev)
2066 {
2067         return scsiid(sdev, &sd53c8xxifc);
2068 }
2069
2070 static int
2071 symenable(SDev* sdev)
2072 {
2073         Pcidev *pcidev;
2074         Controller *ctlr;
2075         //char name[NAMELEN];
2076
2077         ctlr = sdev->ctlr;
2078         pcidev = ctlr->pcidev;
2079
2080         pcisetbme(pcidev);
2081         //snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
2082         intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);
2083
2084         ilock(ctlr);
2085         synctabinit(ctlr);
2086         cribbios(ctlr);
2087         reset(ctlr);
2088         iunlock(ctlr);
2089
2090         return 1;
2091 }
2092
2093 static int
2094 symdisable(SDev* sdev)
2095 {
2096         Ncr *n;
2097         Controller *ctlr;
2098
2099         ctlr = sdev->ctlr;
2100         n = ctlr->n;
2101
2102         n->istat = Srst;                /* software reset */
2103         microdelay(1);
2104         n->istat = 0;
2105
2106         n->scntl1 |= (1 << 3);          /* bus reset */
2107         delay(500);
2108         n->scntl1 &= ~(1 << 3);
2109
2110         return 1;
2111 }
2112
2113 SDifc sd53c8xxifc = {
2114         "53c8xx",                       /* name */
2115
2116         sympnp,                         /* pnp */
2117         nil,                            /* legacy */
2118         symid,                          /* id */
2119         symenable,                      /* enable */
2120         symdisable,                     /* disable */
2121
2122         scsiverify,                     /* verify */
2123         scsionline,                     /* online */
2124         symrio,                         /* rio */
2125         nil,                            /* rctl */
2126         nil,                            /* wctl */
2127
2128         scsibio,                        /* bio */
2129 };