|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7: #include "devtab.h"
8: #include "io.h"
9:
10: #define DPRINT if(debug)print
11:
12: int scsiownid = 7;
13: int scsidebugs[8];
14:
15: typedef struct SCSIdma SCSIdma;
16: typedef struct SCSIdev SCSIdev;
17:
18: void crankfifo(int);
19: void Xdelay(int);
20:
21: enum
22: {
23: DmaFifoOvflw = 16, /* Amount of extra buffer for crankfifo overflow */
24:
25: Dma = 0x80,
26: Nop = 0x00,
27: Flush = 0x01,
28: Reset = 0x02,
29: Select = 0x41,
30: Transfer = 0x10,
31: Cmdcomplete = 0x11,
32: Msgaccept = 0x12
33: };
34:
35: static QLock scsilock; /* access to device */
36: static Rendez scsirendez; /* sleep/wakeup for requesting process */
37: static Scsi * curcmd; /* currently executing command */
38: static int debug;
39:
40: /* NCR 53C90 device registers */
41: struct SCSIdev
42: {
43: uchar countlo;
44: uchar counthi;
45: uchar fifo;
46: uchar cmd;
47: union {
48: struct { /* Registers when READ */
49: uchar status;
50: uchar intr;
51: uchar step;
52: uchar fflags;
53: uchar config;
54: uchar Reserved1;
55: uchar Reserved2;
56: };
57: struct { /* Registers when WRITTEN */
58: uchar destid;
59: uchar timeout;
60: uchar syncperiod;
61: uchar syncoffset;
62: uchar XXX;
63: uchar clkconf;
64: uchar test;
65: };
66: };
67: };
68:
69: /*
70: * allocate a scsi buf of any length
71: * must be called at ialloc time and never freed
72: */
73: Scsibuf *
74: scsialloc(ulong n)
75: {
76: Scsibuf *b;
77: ulong l, p;
78:
79: b = xalloc(sizeof(Scsibuf));
80: p = (ulong)xspanalloc(n + 2*DmaFifoOvflw, BY2PG, 0);
81: b->virt = (uchar *)kmappa(p);
82: for(l = BY2PG; l < n + 2*DmaFifoOvflw + BY2PG; l += BY2PG)
83: kmappa(p+l);
84: b->phys = (uchar*)p;
85: return b;
86: }
87:
88: void
89: initscsi(void)
90: {
91: }
92:
93: void
94: resetscsi(void)
95: {
96: SCSIdev *dev = (SCSIdev *)SCSI;
97:
98: INITCTL(0x80);
99: SETCTL(Int_mask);
100: CLRCTL(Cpu_dma);
101:
102: dev->cmd = Reset;
103: dev->cmd = Nop;
104: dev->countlo = 0;
105: dev->counthi = 0;
106: dev->timeout = 146;
107: dev->syncperiod = 0;
108: dev->syncoffset = 0;
109: dev->config = 0x10|(scsiownid&7); /* Parity on | Bus id */
110: dev->cmd = Dma|Nop;
111: }
112:
113: static int
114: scsidone(void *arg)
115: {
116: USED(arg);
117: return (curcmd == 0);
118: }
119:
120: int
121: scsiexec(Scsi *p, int rflag)
122: {
123: SCSIdev *dev = (SCSIdev *)SCSI;
124: SCSIdma *dma = (SCSIdma *)SCSIDMA;
125: ulong n, up;
126:
127: debug = scsidebugs[p->target&7];
128: DPRINT("scsi %d.%d cmd=0x%2.2ux ", p->target, p->lun, *(p->cmd.ptr));
129: qlock(&scsilock);
130: qlock(&dmalock);
131:
132: p->rflag = rflag;
133: p->status = 0;
134:
135: CLRCTL(Cpu_dma);
136:
137: dma->chainbase = 0;
138: dma->chainlimit = 0;
139: dma->csr = Dinit | Dcreset | Dclrcint;
140:
141: dev->counthi = 0;
142: dev->countlo = 0;
143: dev->cmd = Dma|Nop;
144: dev->cmd = Flush; /* clear scsi fifo */
145:
146: while(p->cmd.ptr < p->cmd.lim)
147: dev->fifo = *(p->cmd.ptr)++;
148:
149: dev->destid = p->target&7;
150: n = p->data.lim - p->data.ptr;
151: dev->counthi = n>>8;
152: dev->countlo = n;
153: dev->cmd = Dma|Nop;
154: if(n) {
155: up = (ulong)p->b->phys;
156: dma->base = up;
157: dma->limit = up + ((n + 0xf)&~0xf);
158: if(!rflag)
159: dma->limit += DmaFifoOvflw; /* NeXT brain damage */
160: }
161:
162: curcmd = p;
163: dev->cmd = Select;
164:
165: while(waserror())
166: ;
167: DPRINT("S<");
168: sleep(&scsirendez, scsidone, 0);
169: poperror();
170: qunlock(&dmalock);
171: qunlock(&scsilock);
172: debug = 0;
173: return p->status;
174: }
175:
176: void
177: scsiintr(int type)
178: {
179: SCSIdev *dev = (SCSIdev *)SCSI;
180: SCSIdma *dma = (SCSIdma *)SCSIDMA;
181: Scsi *p = curcmd;
182: int status, step, intr, n;
183: ulong m, csr;
184:
185: USED(type);
186: csr = dma->csr;
187:
188: CLRCTL(Cpu_dma); /* Access the registers */
189:
190: /* Read cause */
191: status = dev->status;
192: step = dev->step;
193: intr = dev->intr;
194:
195: intr |= ((step&7)<<8);
196:
197: DPRINT("\n\t[ status=%2.2ux step/intr=%3.3ux", status, intr);
198: DPRINT(" dma=%8.8ux cmd status=%4.4ux ]", csr, p ? p->status : 0xffff);
199:
200: if(p == 0 || (intr & 0x80)) { /* SCSI bus reset */
201: dev->cmd = Nop;
202: goto Done;
203: }
204:
205: switch(p->status>>8){
206: case 0x00: /* Select was issued */
207: switch(intr){
208: default:
209: print("devscsi: bad case\n");
210: goto Done;
211: case 0x020: /* arbitration complete, selection timed out */
212: goto Done;
213: case 0x218: /* selection complete, no command phase */
214: p->status = 0x1000;
215: goto Done;
216: case 0x318: /* command phase ended prematurely */
217: n = (p->cmd.lim - p->cmd.base) - (dev->fflags & 0x1f);
218: p->status = (0x30+n)<<8;
219: goto Done;
220: case 0x418: /* select sequence complete */
221: p->status = 0x4100;
222: if((status & 0x07) == p->rflag){
223: DPRINT(" Dma|Transfer ");
224: dma->csr = Dcreset|Dinit;
225: dma->csr = 0;
226: if(p->rflag) {
227: SETCTL(Dmadir);
228: dma->csr = Dseten|Dsetread|Dinit;
229: }
230: else {
231: CLRCTL(Dmadir);
232: dma->csr = Dseten|Dinit;
233: }
234: dev->cmd = Dma|Transfer;
235: SETCTL(Cpu_dma);
236: return;
237: }
238: else if((status & 0x07) != 3)
239: goto Done;
240: /* else fall through */
241: }
242:
243: case 0x41: /* data transfer, if any, is finished */
244: p->status = 0x4600;
245: p->data.ptr = p->data.lim - ((dev->counthi<<8)|dev->countlo);
246: if((status & 0x07) != 3)
247: goto Done;
248: crankfifo(dma->limit - dma->base);
249: dma->csr = Dcreset;
250: DPRINT(" Cmdcomplete");
251: dev->cmd = Cmdcomplete;
252: return;
253:
254: case 0x46: /* Cmdcomplete was issued */
255: p->status = 0x6000|dev->fifo;
256: m = dev->fifo;
257: DPRINT(" end status=0x%2.2ux msg=0x%2.2ux", p->status, m);
258: DPRINT(" Msgaccept");
259: dev->cmd = Msgaccept;
260: return;
261:
262: case 0x60: /* Msgaccept was issued */
263: goto Done;
264: }
265: Done:
266: DPRINT(" Done");
267: curcmd = 0;
268: wakeup(&scsirendez);
269: }
270:
271: void
272: crankfifo(int n)
273: {
274: if(n <= 0)
275: return;
276:
277: n = n>>2;
278: SETCTL(Cpu_dma);
279: while(n--) {
280: CLRCTL(Fifofl);
281: SETCTL(Fifofl);
282: CLRCTL(Fifofl);
283: }
284: CLRCTL(Cpu_dma);
285: }
286:
287: void
288: Xdelay(int time)
289: {
290: time *= 100;
291: while(time--)
292: ;
293: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.