Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* |
2 | * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu) | |
3 | * Thanks to Julian Elischer for advice and help with this port. | |
4 | * | |
5 | * Written by Julian Elischer (julian@tfs.com) | |
6 | * for TRW Financial Systems for use under the MACH(2.5) operating system. | |
7 | * | |
8 | * TRW Financial Systems, in accordance with their agreement with Carnegie | |
9 | * Mellon University, makes this software available to CMU to distribute | |
10 | * or use in any manner that they see fit as long as this message is kept with | |
11 | * the software. For this reason TFS also grants any other persons or | |
12 | * organisations permission to use or modify this software. | |
13 | * | |
14 | * TFS supplies this software to be publicly redistributed | |
15 | * on the understanding that TFS is not responsible for the correct | |
16 | * functioning of this software in any circumstances. | |
17 | * | |
15637ed4 | 18 | * commenced: Sun Sep 27 18:14:01 PDT 1992 |
78ed81a3 | 19 | * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993 |
20 | * | |
21 | * $Id: ultra14f.c,v 1.9 1993/10/12 07:15:38 rgrimes Exp $ | |
15637ed4 RG |
22 | */ |
23 | ||
24 | #include <sys/types.h> | |
25 | #include <uha.h> | |
26 | ||
27 | #include <sys/param.h> | |
28 | #include <sys/systm.h> | |
29 | #include <sys/errno.h> | |
30 | #include <sys/ioctl.h> | |
31 | #include <sys/buf.h> | |
32 | #include <sys/proc.h> | |
33 | #include <sys/user.h> | |
34 | ||
35 | #ifdef MACH /* EITHER CMU OR OSF */ | |
36 | #include <i386/ipl.h> | |
37 | #include <i386at/scsi.h> | |
38 | #include <i386at/scsiconf.h> | |
39 | ||
40 | #ifdef OSF /* OSF ONLY */ | |
41 | #include <sys/table.h> | |
42 | #include <i386/handler.h> | |
43 | #include <i386/dispatcher.h> | |
44 | #include <i386/AT386/atbus.h> | |
45 | ||
46 | #else OSF /* CMU ONLY */ | |
47 | #include <i386at/atbus.h> | |
48 | #include <i386/pio.h> | |
49 | #endif OSF | |
50 | #endif MACH /* end of MACH specific */ | |
51 | ||
52 | #ifdef __386BSD__ /* 386BSD specific */ | |
53 | #define isa_dev isa_device | |
54 | #define dev_unit id_unit | |
55 | #define dev_addr id_iobase | |
56 | ||
57 | #include <i386/include/pio.h> | |
58 | #include <i386/isa/isa_device.h> | |
59 | #include <scsi/scsi_all.h> | |
60 | #include <scsi/scsiconf.h> | |
61 | #endif __386BSD__ | |
62 | ||
63 | /*\f*/ | |
64 | ||
65 | #ifdef __386BSD__ | |
66 | #include "ddb.h" | |
67 | #if NDDB > 0 | |
68 | int Debugger(); | |
69 | #else NDDB | |
70 | #define Debugger() panic("should call debugger here") | |
71 | #endif NDDB | |
72 | #endif __386BSD__ | |
73 | ||
74 | #ifdef MACH | |
75 | int Debugger(); | |
76 | #endif MACH | |
77 | ||
78 | typedef struct {unsigned char addr[4]; } physaddr; | |
79 | typedef struct {unsigned char len[4]; } physlen; | |
80 | ||
81 | ||
82 | #ifdef MACH | |
83 | extern physaddr kvtophys(); | |
84 | #define PHYSTOKV(x) phystokv(x) | |
85 | #define KVTOPHYS(x) kvtophys(x) | |
86 | #endif MACH | |
87 | ||
88 | #ifdef __386BSD__ | |
15637ed4 RG |
89 | #define KVTOPHYS(x) vtophys(x) |
90 | #endif __386BSD__ | |
91 | ||
78ed81a3 | 92 | extern int hz; |
15637ed4 RG |
93 | extern int delaycount; /* from clock setup code */ |
94 | #define NUM_CONCURRENT 16 /* number of concurrent ops per board */ | |
95 | #define UHA_NSEG 33 /* number of dma segments supported */ | |
96 | #define FUDGE(X) (X>>1) /* our loops are slower than spinwait() */ | |
97 | /*\f*/ | |
98 | /************************** board definitions *******************************/ | |
99 | /* | |
100 | * I/O Port Interface | |
101 | */ | |
102 | #define UHA_LMASK (0x000) /* local doorbell mask reg */ | |
103 | #define UHA_LINT (0x001) /* local doorbell int/stat reg */ | |
104 | #define UHA_SMASK (0x002) /* system doorbell mask reg */ | |
105 | #define UHA_SINT (0x003) /* system doorbell int/stat reg */ | |
106 | #define UHA_ID0 (0x004) /* product id reg 0 */ | |
107 | #define UHA_ID1 (0x005) /* product id reg 1 */ | |
108 | #define UHA_CONF1 (0x006) /* config reg 1 */ | |
109 | #define UHA_CONF2 (0x007) /* config reg 2 */ | |
110 | #define UHA_OGM0 (0x008) /* outgoing mail ptr 0 least sig */ | |
111 | #define UHA_OGM1 (0x009) /* outgoing mail ptr 1 least mid */ | |
112 | #define UHA_OGM2 (0x00a) /* outgoing mail ptr 2 most mid */ | |
113 | #define UHA_OGM3 (0x00b) /* outgoing mail ptr 3 most sig */ | |
114 | #define UHA_ICM0 (0x00c) /* incoming mail ptr 0 */ | |
115 | #define UHA_ICM1 (0x00d) /* incoming mail ptr 1 */ | |
116 | #define UHA_ICM2 (0x00e) /* incoming mail ptr 2 */ | |
117 | #define UHA_ICM3 (0x00f) /* incoming mail ptr 3 */ | |
118 | ||
119 | /* | |
120 | * UHA_LMASK bits (read only) | |
121 | */ | |
122 | ||
123 | #define UHA_LDIE 0x80 /* local doorbell int enabled */ | |
124 | #define UHA_SRSTE 0x40 /* soft reset enabled */ | |
125 | #define UHA_ABORTEN 0x10 /* abort MSCP enabled */ | |
126 | #define UHA_OGMINTEN 0x01 /* outgoing mail interrupt enabled */ | |
127 | ||
128 | /* | |
129 | * UHA_LINT bits (read) | |
130 | */ | |
131 | ||
132 | #define UHA_LDIP 0x80 /* local doorbell int pending */ | |
133 | ||
134 | /* | |
135 | * UHA_LINT bits (write) | |
136 | */ | |
137 | ||
138 | #define UHA_ADRST 0x40 /* adapter soft reset */ | |
139 | #define UHA_SBRST 0x20 /* scsi bus reset */ | |
140 | #define UHA_ASRST 0x60 /* adapter and scsi reset */ | |
141 | #define UHA_ABORT 0x10 /* abort MSCP */ | |
142 | #define UHA_OGMINT 0x01 /* tell adapter to get mail */ | |
143 | ||
144 | /* | |
145 | * UHA_SMASK bits (read) | |
146 | */ | |
147 | ||
148 | #define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */ | |
149 | #define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */ | |
150 | #define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled | |
151 | ||
152 | /* | |
153 | * UHA_SMASK bits (write) | |
154 | */ | |
155 | ||
156 | #define UHA_ENSINT 0x80 /* enable system doorbell interrupt */ | |
157 | #define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */ | |
158 | #define UHA_ENICM 0x01 /* enable ICM interrupt */ | |
159 | ||
160 | /* | |
161 | * UHA_SINT bits (read) | |
162 | */ | |
163 | ||
164 | #define UHA_SINTP 0x80 /* system doorbell int pending */ | |
165 | #define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */ | |
166 | #define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */ | |
167 | ||
168 | /* | |
169 | * UHA_SINT bits (write) | |
170 | */ | |
171 | ||
172 | #define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */ | |
173 | #define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */ | |
174 | ||
175 | /* | |
176 | * UHA_CONF1 bits (read only) | |
177 | */ | |
178 | ||
179 | #define UHA_DMA_CH5 0x00 /* DMA channel 5 */ | |
180 | #define UHA_DMA_CH6 0x40 /* 6 */ | |
181 | #define UHA_DMA_CH7 0x80 /* 7 */ | |
182 | #define UHA_IRQ15 0x00 /* IRQ 15 */ | |
183 | #define UHA_IRQ14 0x10 /* 14 */ | |
184 | #define UHA_IRQ11 0x20 /* 11 */ | |
185 | #define UHA_IRQ10 0x30 /* 10 */ | |
186 | ||
187 | /*********************************** | |
188 | * ha_status error codes | |
189 | \***********************************/ | |
190 | ||
191 | #define UHA_NO_ERR 0x00 /* No error supposedly */ | |
192 | #define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */ | |
193 | #define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */ | |
194 | #define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */ | |
195 | #define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */ | |
196 | #define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */ | |
197 | #define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */ | |
198 | #define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */ | |
199 | ||
200 | /*\f*/ | |
201 | ||
202 | struct uha_dma_seg | |
203 | { | |
204 | physaddr addr; | |
205 | physlen len; | |
206 | }; | |
207 | /*\f*/ | |
208 | ||
209 | struct mscp | |
210 | { | |
211 | unsigned char opcode:3; | |
212 | #define U14_HAC 0x01 /*host adapter command*/ | |
213 | #define U14_TSP 0x02 /*target scsi pass through command*/ | |
214 | #define U14_SDR 0x04 /*scsi device reset*/ | |
215 | unsigned char xdir:2; /*xfer direction*/ | |
216 | #define U14_SDET 0x00 /*determined by scsi command*/ | |
217 | #define U14_SDIN 0x01 /*scsi data in*/ | |
218 | #define U14_SDOUT 0x02 /*scsi data out*/ | |
219 | #define U14_NODATA 0x03 /*no data xfer*/ | |
220 | unsigned char dcn:1; /*disable disconnect for this command*/ | |
221 | unsigned char ca:1; /*Cache control*/ | |
222 | unsigned char sgth:1; /*scatter gather flag*/ | |
223 | unsigned char target:3; | |
224 | unsigned char chan:2; /*scsi channel (always 0 for 14f)*/ | |
225 | unsigned char lun:3; | |
226 | physaddr data; | |
227 | physlen datalen; | |
228 | physaddr link; | |
229 | unsigned char link_id; | |
230 | unsigned char sg_num; /*number of scat gath segs */ | |
231 | /*in s-g list if sg flag is*/ | |
232 | /*set. starts at 1, 8bytes per*/ | |
233 | unsigned char senselen; | |
234 | unsigned char cdblen; | |
235 | unsigned char cdb[12]; | |
236 | unsigned char ha_status; | |
237 | unsigned char targ_status; | |
238 | physaddr sense; /* if 0 no auto sense */ | |
239 | /*-----------------end of hardware supported fields----------------*/ | |
240 | struct mscp *next; /* in free list */ | |
241 | struct scsi_xfer *xs; /* the scsi_xfer for this cmd */ | |
15637ed4 RG |
242 | int flags; |
243 | #define MSCP_FREE 0 | |
244 | #define MSCP_ACTIVE 1 | |
245 | #define MSCP_ABORTED 2 | |
246 | struct uha_dma_seg uha_dma[UHA_NSEG]; | |
247 | struct scsi_sense_data mscp_sense; | |
248 | }; | |
249 | ||
15637ed4 RG |
250 | /*\f*/ |
251 | ||
252 | struct uha_data | |
253 | { | |
254 | int flags; | |
255 | #define UHA_INIT 0x01; | |
256 | int baseport; | |
257 | struct mscp mscps[NUM_CONCURRENT]; | |
258 | struct mscp *free_mscp; | |
259 | int our_id; /* our scsi id */ | |
260 | int vect; | |
261 | int dma; | |
262 | } uha_data[NUHA]; | |
263 | ||
264 | int uhaprobe(); | |
265 | int uha_attach(); | |
266 | int uhaintr(); | |
267 | int uha_scsi_cmd(); | |
268 | int uha_timeout(); | |
269 | int uha_abort(); | |
270 | struct mscp *cheat; | |
271 | void uhaminphys(); | |
272 | long int uha_adapter_info(); | |
273 | ||
274 | unsigned long int scratch; | |
275 | ||
276 | #ifdef MACH | |
277 | struct isa_driver uhadriver = { uhaprobe, 0, uha_attach, "uha", 0, 0, 0}; | |
278 | int (*uhaintrs[])() = {uhaintr, 0}; | |
279 | #endif MACH | |
280 | ||
281 | #ifdef __386BSD__ | |
282 | struct isa_driver uhadriver = { uhaprobe, uha_attach, "uha"}; | |
283 | #endif __386BSD__ | |
284 | ||
285 | static uha_unit = 0; | |
78ed81a3 | 286 | #ifdef UHADEBUG |
15637ed4 | 287 | int uha_debug = 0; |
78ed81a3 | 288 | #endif /*UHADEBUG*/ |
15637ed4 RG |
289 | #define UHA_SHOWMSCPS 0x01 |
290 | #define UHA_SHOWINTS 0x02 | |
291 | #define UHA_SHOWCMDS 0x04 | |
292 | #define UHA_SHOWMISC 0x08 | |
293 | #define FAIL 1 | |
294 | #define SUCCESS 0 | |
295 | #define PAGESIZ 4096 | |
296 | ||
297 | struct scsi_switch uha_switch = | |
298 | { | |
299 | uha_scsi_cmd, | |
300 | uhaminphys, | |
301 | 0, | |
302 | 0, | |
303 | uha_adapter_info, | |
78ed81a3 | 304 | "uha", |
305 | 0,0 | |
15637ed4 RG |
306 | }; |
307 | ||
308 | /*\f*/ | |
309 | /***********************************************************************\ | |
310 | * Function to send a command out through a mailbox * | |
311 | \***********************************************************************/ | |
312 | uha_send_mbox( int unit | |
313 | ,struct mscp *mscp) | |
314 | { | |
315 | int port = uha_data[unit].baseport; | |
78ed81a3 | 316 | int spincount = FUDGE(delaycount) * 1000; /* 1s should be enough */ |
15637ed4 RG |
317 | int s = splbio(); |
318 | ||
319 | while( ((inb(port + UHA_LINT) & (UHA_LDIP)) | |
320 | != (0)) | |
321 | && (spincount--)); | |
322 | if(spincount == -1) | |
323 | { | |
78ed81a3 | 324 | printf("uha%d: uha_send_mbox, board not responding\n",unit); |
15637ed4 RG |
325 | Debugger(); |
326 | } | |
327 | ||
328 | outl(port + UHA_OGM0,KVTOPHYS(mscp)); | |
329 | outb(port + UHA_LINT, (UHA_OGMINT)); | |
330 | splx(s); | |
331 | } | |
332 | ||
333 | /***********************************************************************\ | |
334 | * Function to send abort to 14f * | |
335 | \***********************************************************************/ | |
336 | ||
337 | uha_abort( int unit | |
338 | ,struct mscp *mscp) | |
339 | { | |
340 | int port = uha_data[unit].baseport; | |
341 | int spincount = FUDGE(delaycount) * 1; | |
342 | int abortcount = FUDGE(delaycount) * 2000; | |
343 | int s = splbio(); | |
344 | ||
345 | while(((inb(port + UHA_LINT) & (UHA_LDIP)) | |
346 | != (0)) | |
347 | && (spincount--)); | |
348 | if(spincount == -1); | |
349 | { | |
78ed81a3 | 350 | printf("uha%d: uha_abort, board not responding\n",unit); |
15637ed4 RG |
351 | Debugger(); |
352 | } | |
353 | ||
354 | outl(port + UHA_OGM0,KVTOPHYS(mscp)); | |
355 | outb(port + UHA_LINT,UHA_ABORT); | |
356 | ||
357 | while((abortcount--) && (!(inb(port + UHA_SINT) & UHA_ABORT_FAIL))); | |
358 | if(abortcount == -1) | |
359 | { | |
78ed81a3 | 360 | printf("uha%d: uha_abort, board not responding\n",unit); |
15637ed4 RG |
361 | Debugger(); |
362 | } | |
363 | if((inb(port + UHA_SINT) & 0x10) != 0) | |
364 | { | |
365 | outb(port + UHA_SINT,UHA_ABORT_ACK); | |
366 | return(1); | |
367 | } | |
368 | else | |
369 | { | |
370 | outb(port + UHA_SINT,UHA_ABORT_ACK); | |
371 | return(0); | |
372 | } | |
373 | } | |
374 | ||
375 | /***********************************************************************\ | |
376 | * Function to poll for command completion when in poll mode * | |
377 | \***********************************************************************/ | |
378 | uha_poll(int unit ,int wait) /* in msec */ | |
379 | { | |
380 | int port = uha_data[unit].baseport; | |
381 | int spincount = FUDGE(delaycount) * wait; /* in msec */ | |
382 | int stport = port + UHA_SINT; | |
383 | int start = spincount; | |
384 | ||
385 | retry: | |
386 | while( (spincount--) && (!(inb(stport) & UHA_SINTP))); | |
387 | if(spincount == -1) | |
388 | { | |
78ed81a3 | 389 | printf("uha%d: uha_poll, board not responding\n",unit); |
15637ed4 RG |
390 | return(EIO); |
391 | } | |
392 | if ((int)cheat != PHYSTOKV(inl(port + UHA_ICM0))) | |
393 | { | |
78ed81a3 | 394 | printf("uha%d: discarding %x\n",unit,inl(port + UHA_ICM0)); |
15637ed4 RG |
395 | outb(port + UHA_SINT, UHA_ICM_ACK); |
396 | spinwait(50); | |
397 | goto retry; | |
398 | }/* don't know this will work */ | |
399 | uhaintr(unit); | |
400 | return(0); | |
401 | } | |
402 | ||
403 | /*******************************************************\ | |
404 | * Check if the device can be found at the port given * | |
405 | * and if so, set it up ready for further work * | |
406 | * as an argument, takes the isa_dev structure from * | |
407 | * autoconf.c * | |
408 | \*******************************************************/ | |
409 | uhaprobe(dev) | |
410 | struct isa_dev *dev; | |
411 | { | |
412 | int unit = uha_unit; | |
413 | dev->dev_unit = unit; | |
414 | uha_data[unit].baseport = dev->dev_addr; | |
415 | if(unit >= NUHA) | |
416 | { | |
78ed81a3 | 417 | printf("uha%d: unit number too high\n",unit); |
15637ed4 RG |
418 | return(0); |
419 | } | |
420 | ||
421 | /*try and initialize unit at this location*/ | |
422 | if (uha_init(unit) != 0) | |
423 | { | |
424 | return(0); | |
425 | } | |
426 | ||
427 | /* if its there put in it's interrupt and DRQ vectors */ | |
428 | ||
429 | dev->id_irq = (1 << uha_data[unit].vect); | |
430 | dev->id_drq = uha_data[unit].dma; | |
431 | ||
432 | ||
433 | uha_unit ++; | |
434 | return(1); | |
435 | } | |
436 | ||
437 | /***********************************************\ | |
438 | * Attach all the sub-devices we can find * | |
439 | \***********************************************/ | |
440 | uha_attach(dev) | |
441 | struct isa_dev *dev; | |
442 | { | |
443 | int unit = dev->dev_unit; | |
444 | ||
445 | ||
15637ed4 RG |
446 | /***********************************************\ |
447 | * ask the adapter what subunits are present * | |
448 | \***********************************************/ | |
449 | scsi_attachdevs( unit, uha_data[unit].our_id, &uha_switch); | |
450 | ||
451 | #if defined(OSF) | |
452 | uha_attached[unit]=1; | |
453 | #endif /* defined(OSF) */ | |
15637ed4 RG |
454 | return; |
455 | } | |
456 | ||
457 | /***********************************************\ | |
458 | * Return some information to the caller about * | |
459 | * the adapter and it's capabilities * | |
460 | \***********************************************/ | |
461 | long int uha_adapter_info(unit) | |
462 | int unit; | |
463 | { | |
464 | return(2); /* 2 outstanding requests at a time per device */ | |
465 | } | |
466 | ||
467 | /***********************************************\ | |
468 | * Catch an interrupt from the adaptor * | |
469 | \***********************************************/ | |
470 | uhaintr(unit) | |
471 | { | |
472 | struct mscp *mscp; | |
473 | u_char uhastat; | |
474 | unsigned long int mboxval; | |
475 | ||
476 | int port = uha_data[unit].baseport; | |
477 | ||
478 | ||
78ed81a3 | 479 | #ifdef UHADEBUG |
15637ed4 RG |
480 | if(scsi_debug & PRINTROUTINES) |
481 | printf("uhaintr "); | |
78ed81a3 | 482 | #endif /*UHADEBUG*/ |
15637ed4 RG |
483 | |
484 | #if defined(OSF) | |
485 | if (!uha_attached[unit]) | |
486 | { | |
487 | return(1); | |
488 | } | |
489 | #endif /* defined(OSF) */ | |
490 | while(inb(port + UHA_SINT) & UHA_SINTP) | |
491 | { | |
492 | /***********************************************\ | |
493 | * First get all the information and then * | |
494 | * acknowlege the interrupt * | |
495 | \***********************************************/ | |
496 | uhastat = inb(port + UHA_SINT); | |
497 | mboxval = inl(port + UHA_ICM0); | |
498 | outb(port + UHA_SINT,UHA_ICM_ACK); | |
499 | ||
78ed81a3 | 500 | #ifdef UHADEBUG |
15637ed4 RG |
501 | if(scsi_debug & TRACEINTERRUPTS) |
502 | printf("status = 0x%x ",uhastat); | |
78ed81a3 | 503 | #endif /*UHADEBUG*/ |
15637ed4 RG |
504 | /***********************************************\ |
505 | * Process the completed operation * | |
506 | \***********************************************/ | |
507 | ||
508 | mscp = (struct mscp *)(PHYSTOKV(mboxval)); | |
509 | ||
78ed81a3 | 510 | #ifdef UHADEBUG |
15637ed4 RG |
511 | if(uha_debug & UHA_SHOWCMDS ) |
512 | { | |
513 | uha_show_scsi_cmd(mscp->xs); | |
514 | } | |
515 | if((uha_debug & UHA_SHOWMSCPS) && mscp) | |
516 | printf("<int mscp(%x)>",mscp); | |
78ed81a3 | 517 | #endif /*UHADEBUG*/ |
518 | untimeout(uha_timeout,mscp); | |
15637ed4 RG |
519 | |
520 | uha_done(unit,mscp); | |
521 | } | |
522 | return(1); | |
523 | } | |
524 | ||
525 | /***********************************************\ | |
526 | * We have a mscp which has been processed by the * | |
527 | * adaptor, now we look to see how the operation * | |
528 | * went. * | |
529 | \***********************************************/ | |
530 | ||
531 | uha_done(unit,mscp) | |
532 | int unit; | |
533 | struct mscp *mscp; | |
534 | { | |
535 | struct scsi_sense_data *s1,*s2; | |
536 | struct scsi_xfer *xs = mscp->xs; | |
537 | ||
78ed81a3 | 538 | #ifdef UHADEBUG |
15637ed4 RG |
539 | if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS)) |
540 | printf("uha_done "); | |
78ed81a3 | 541 | #endif /*UHADEBUG*/ |
15637ed4 RG |
542 | /***********************************************\ |
543 | * Otherwise, put the results of the operation * | |
544 | * into the xfer and call whoever started it * | |
545 | \***********************************************/ | |
546 | if ( (mscp->ha_status == UHA_NO_ERR) || (xs->flags & SCSI_ERR_OK)) | |
547 | { /* All went correctly OR errors expected */ | |
548 | xs->resid = 0; | |
549 | xs->error = 0; | |
550 | } | |
551 | else | |
552 | { | |
553 | ||
554 | s1 = &(mscp->mscp_sense); | |
555 | s2 = &(xs->sense); | |
556 | ||
557 | if(mscp->ha_status != UHA_NO_ERR) | |
558 | { | |
559 | switch(mscp->ha_status) | |
560 | { | |
561 | case UHA_SBUS_TIMEOUT: /* No response */ | |
78ed81a3 | 562 | #ifdef UHADEBUG |
15637ed4 RG |
563 | if (uha_debug & UHA_SHOWMISC) |
564 | { | |
565 | printf("timeout reported back\n"); | |
566 | } | |
78ed81a3 | 567 | #endif /*UHADEBUG*/ |
15637ed4 RG |
568 | xs->error = XS_TIMEOUT; |
569 | break; | |
570 | case UHA_SBUS_OVER_UNDER: | |
78ed81a3 | 571 | #ifdef UHADEBUG |
15637ed4 RG |
572 | if (uha_debug & UHA_SHOWMISC) |
573 | { | |
574 | printf("scsi bus xfer over/underrun\n"); | |
575 | } | |
78ed81a3 | 576 | #endif /*UHADEBUG*/ |
15637ed4 RG |
577 | xs->error = XS_DRIVER_STUFFUP; |
578 | break; | |
579 | case UHA_BAD_SG_LIST: | |
78ed81a3 | 580 | #ifdef UHADEBUG |
15637ed4 RG |
581 | if (uha_debug & UHA_SHOWMISC) |
582 | { | |
583 | printf("bad sg list reported back\n"); | |
584 | } | |
78ed81a3 | 585 | #endif /*UHADEBUG*/ |
15637ed4 RG |
586 | xs->error = XS_DRIVER_STUFFUP; |
587 | break; | |
588 | default: /* Other scsi protocol messes */ | |
589 | xs->error = XS_DRIVER_STUFFUP; | |
78ed81a3 | 590 | #ifdef UHADEBUG |
15637ed4 RG |
591 | if (uha_debug & UHA_SHOWMISC) |
592 | { | |
593 | printf("unexpected ha_status: %x\n", | |
594 | mscp->ha_status); | |
595 | } | |
78ed81a3 | 596 | #endif /*UHADEBUG*/ |
15637ed4 RG |
597 | } |
598 | ||
599 | } | |
600 | else | |
601 | { | |
602 | ||
603 | if (mscp->targ_status != 0) | |
604 | /**************************************************************************\ | |
605 | * I have no information for any possible value of target status field * | |
606 | * other than 0 means no error!! So I guess any error is unexpected in that * | |
607 | * event!! * | |
608 | \**************************************************************************/ | |
609 | ||
610 | { | |
78ed81a3 | 611 | #ifdef UHADEBUG |
15637ed4 RG |
612 | if (uha_debug & UHA_SHOWMISC) |
613 | { | |
614 | printf("unexpected targ_status: %x\n", | |
615 | mscp->targ_status); | |
616 | } | |
78ed81a3 | 617 | #endif /*UHADEBUG*/ |
15637ed4 RG |
618 | xs->error = XS_DRIVER_STUFFUP; |
619 | } | |
620 | } | |
621 | } | |
622 | done: xs->flags |= ITSDONE; | |
623 | uha_free_mscp(unit,mscp, xs->flags); | |
624 | if(xs->when_done) | |
625 | (*(xs->when_done))(xs->done_arg,xs->done_arg2); | |
626 | } | |
627 | ||
628 | /***********************************************\ | |
629 | * A mscp (and hence a mbx-out is put onto the * | |
630 | * free list. * | |
631 | \***********************************************/ | |
632 | uha_free_mscp(unit,mscp, flags) | |
633 | struct mscp *mscp; | |
634 | { | |
635 | unsigned int opri; | |
636 | ||
78ed81a3 | 637 | #ifdef UHADEBUG |
15637ed4 RG |
638 | if(scsi_debug & PRINTROUTINES) |
639 | printf("mscp%d(0x%x)> ",unit,flags); | |
78ed81a3 | 640 | #endif /*UHADEBUG*/ |
15637ed4 RG |
641 | if (!(flags & SCSI_NOMASK)) |
642 | opri = splbio(); | |
643 | ||
644 | mscp->next = uha_data[unit].free_mscp; | |
645 | uha_data[unit].free_mscp = mscp; | |
646 | mscp->flags = MSCP_FREE; | |
647 | /***********************************************\ | |
648 | * If there were none, wake abybody waiting for * | |
649 | * one to come free, starting with queued entries* | |
650 | \***********************************************/ | |
651 | if (!mscp->next) { | |
652 | wakeup(&uha_data[unit].free_mscp); | |
653 | } | |
654 | if (!(flags & SCSI_NOMASK)) | |
655 | splx(opri); | |
656 | } | |
657 | ||
658 | /***********************************************\ | |
659 | * Get a free mscp (and hence mbox-out entry) * | |
660 | \***********************************************/ | |
661 | struct mscp * | |
662 | uha_get_mscp(unit,flags) | |
663 | { | |
664 | unsigned opri; | |
665 | struct mscp *rc; | |
666 | ||
78ed81a3 | 667 | #ifdef UHADEBUG |
15637ed4 RG |
668 | if(scsi_debug & PRINTROUTINES) |
669 | printf("<mscp%d(0x%x) ",unit,flags); | |
78ed81a3 | 670 | #endif /*UHADEBUG*/ |
15637ed4 RG |
671 | if (!(flags & SCSI_NOMASK)) |
672 | opri = splbio(); | |
673 | /***********************************************\ | |
674 | * If we can and have to, sleep waiting for one * | |
675 | * to come free * | |
676 | \***********************************************/ | |
677 | while ((!(rc = uha_data[unit].free_mscp)) && (!(flags & SCSI_NOSLEEP))) | |
678 | { | |
679 | sleep(&uha_data[unit].free_mscp, PRIBIO); | |
680 | } | |
681 | if (rc) | |
682 | { | |
683 | uha_data[unit].free_mscp = rc->next; | |
684 | rc->flags = MSCP_ACTIVE; | |
685 | } | |
686 | if (!(flags & SCSI_NOMASK)) | |
687 | splx(opri); | |
688 | return(rc); | |
689 | } | |
690 | ||
691 | ||
692 | ||
693 | /***********************************************\ | |
694 | * Start the board, ready for normal operation * | |
695 | \***********************************************/ | |
696 | ||
697 | uha_init(unit) | |
698 | int unit; | |
699 | { | |
700 | unsigned char ad[4]; | |
701 | volatile unsigned char model; | |
702 | volatile unsigned char submodel; | |
703 | unsigned char config_reg1; | |
704 | unsigned char config_reg2; | |
705 | unsigned char dma_ch; | |
706 | unsigned char irq_ch; | |
707 | unsigned char uha_id; | |
708 | int port = uha_data[unit].baseport; | |
709 | int i; | |
710 | int resetcount = FUDGE(delaycount) * 4000; | |
711 | ||
712 | model = inb(port + UHA_ID0); | |
713 | submodel = inb(port + UHA_ID1); | |
78ed81a3 | 714 | if ((model != 0x56) & (submodel != 0x40)) { |
715 | #ifdef UHADEBUG | |
716 | printf("uha%d: uha_init, board not responding\n",unit); | |
717 | #endif /*UHADEBUG*/ | |
718 | return(ENXIO); | |
719 | } | |
15637ed4 | 720 | |
78ed81a3 | 721 | printf("uha%d: reading board settings, ",unit); |
15637ed4 RG |
722 | |
723 | config_reg1 = inb(port + UHA_CONF1); | |
724 | config_reg2 = inb(port + UHA_CONF2); | |
725 | dma_ch = (config_reg1 & 0xc0); | |
726 | irq_ch = (config_reg1 & 0x30); | |
727 | uha_id = (config_reg2 & 0x07); | |
728 | ||
729 | switch(dma_ch) | |
730 | { | |
731 | case UHA_DMA_CH5: | |
732 | uha_data[unit].dma = 5; | |
733 | printf("dma=5 "); | |
734 | break; | |
735 | case UHA_DMA_CH6: | |
736 | uha_data[unit].dma = 6; | |
737 | printf("dma=6 "); | |
738 | break; | |
739 | case UHA_DMA_CH7: | |
740 | uha_data[unit].dma = 7; | |
741 | printf("dma=7 "); | |
742 | break; | |
743 | default: | |
744 | printf("illegal dma jumper setting\n"); | |
745 | return(EIO); | |
746 | } | |
747 | switch(irq_ch) | |
748 | { | |
749 | case UHA_IRQ10: | |
750 | uha_data[unit].vect = 10; | |
751 | printf("int=10 "); | |
752 | break; | |
753 | case UHA_IRQ11: | |
754 | uha_data[unit].vect = 11; | |
755 | printf("int=11 "); | |
756 | break; | |
757 | case UHA_IRQ14: | |
758 | uha_data[unit].vect = 14; | |
759 | printf("int=14 "); | |
760 | break; | |
761 | case UHA_IRQ15: | |
762 | uha_data[unit].vect = 15; | |
763 | printf("int=15 "); | |
764 | break; | |
765 | default: | |
766 | printf("illegal int jumper setting\n"); | |
767 | return(EIO); | |
768 | } | |
769 | /* who are we on the scsi bus */ | |
770 | printf("id=%x\n",uha_id); | |
771 | uha_data[unit].our_id = uha_id; | |
772 | ||
773 | ||
774 | /***********************************************\ | |
775 | * link up all our MSCPs into a free list * | |
776 | \***********************************************/ | |
777 | for (i=0; i < NUM_CONCURRENT; i++) | |
778 | { | |
779 | uha_data[unit].mscps[i].next = uha_data[unit].free_mscp; | |
780 | uha_data[unit].free_mscp = &uha_data[unit].mscps[i]; | |
781 | uha_data[unit].free_mscp->flags = MSCP_FREE; | |
782 | } | |
783 | ||
784 | /***********************************************\ | |
785 | * Note that we are going and return (to probe) * | |
786 | \***********************************************/ | |
787 | outb(port + UHA_LINT, UHA_ASRST); | |
788 | while( (resetcount--) && (!(inb(port + UHA_LINT)))); | |
789 | if(resetcount == -1) | |
790 | { | |
791 | printf("uha%d: board timed out during reset\n",unit); | |
792 | return(ENXIO); | |
793 | } | |
794 | ||
795 | outb(port + UHA_SMASK, 0x81); /* make sure interrupts are enabled */ | |
796 | uha_data[unit].flags |= UHA_INIT; | |
797 | return(0); | |
798 | } | |
799 | ||
800 | ||
801 | ||
802 | #ifndef min | |
803 | #define min(x,y) (x < y ? x : y) | |
804 | #endif min | |
805 | ||
806 | ||
807 | void uhaminphys(bp) | |
808 | struct buf *bp; | |
809 | { | |
810 | #ifdef MACH | |
811 | #if !defined(OSF) | |
812 | bp->b_flags |= B_NPAGES; /* can support scat/gather */ | |
813 | #endif /* defined(OSF) */ | |
814 | #endif MACH | |
815 | if(bp->b_bcount > ((UHA_NSEG-1) * PAGESIZ)) | |
816 | { | |
817 | bp->b_bcount = ((UHA_NSEG-1) * PAGESIZ); | |
818 | } | |
819 | } | |
820 | ||
821 | /***********************************************\ | |
822 | * start a scsi operation given the command and * | |
823 | * the data address. Also needs the unit, target * | |
824 | * and lu * | |
825 | \***********************************************/ | |
826 | int uha_scsi_cmd(xs) | |
827 | struct scsi_xfer *xs; | |
828 | { | |
829 | struct scsi_sense_data *s1,*s2; | |
830 | struct mscp *mscp; | |
831 | struct uha_dma_seg *sg; | |
832 | int seg; /* scatter gather seg being worked on */ | |
833 | int i = 0; | |
834 | int rc = 0; | |
835 | int thiskv; | |
836 | unsigned long int thisphys,nextphys; | |
837 | int unit =xs->adapter; | |
838 | int bytes_this_seg,bytes_this_page,datalen,flags; | |
839 | struct iovec *iovp; | |
840 | int s; | |
841 | unsigned int stat; | |
842 | int port = uha_data[unit].baseport; | |
843 | unsigned long int templen; | |
844 | ||
845 | ||
78ed81a3 | 846 | #ifdef UHADEBUG |
15637ed4 RG |
847 | if(scsi_debug & PRINTROUTINES) |
848 | printf("uha_scsi_cmd "); | |
78ed81a3 | 849 | #endif /*UHADEBUG*/ |
15637ed4 RG |
850 | /***********************************************\ |
851 | * get a mscp (mbox-out) to use. If the transfer * | |
852 | * is from a buf (possibly from interrupt time) * | |
853 | * then we can't allow it to sleep * | |
854 | \***********************************************/ | |
855 | flags = xs->flags; | |
856 | if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */ | |
857 | if(flags & ITSDONE) | |
858 | { | |
78ed81a3 | 859 | printf("uha%d: Already done?",unit); |
15637ed4 RG |
860 | xs->flags &= ~ITSDONE; |
861 | } | |
862 | if(!(flags & INUSE)) | |
863 | { | |
78ed81a3 | 864 | printf("uha%d: Not in use?",unit); |
15637ed4 RG |
865 | xs->flags |= INUSE; |
866 | } | |
867 | if (!(mscp = uha_get_mscp(unit,flags))) | |
868 | { | |
869 | xs->error = XS_DRIVER_STUFFUP; | |
870 | return(TRY_AGAIN_LATER); | |
871 | } | |
872 | ||
873 | cheat = mscp; | |
78ed81a3 | 874 | #ifdef UHADEBUG |
15637ed4 RG |
875 | if(uha_debug & UHA_SHOWMSCPS) |
876 | printf("<start mscp(%x)>",mscp); | |
877 | if(scsi_debug & SHOWCOMMANDS) | |
878 | { | |
879 | uha_show_scsi_cmd(xs); | |
880 | } | |
78ed81a3 | 881 | #endif /*UHADEBUG*/ |
15637ed4 RG |
882 | mscp->xs = xs; |
883 | /***********************************************\ | |
884 | * Put all the arguments for the xfer in the mscp * | |
885 | \***********************************************/ | |
886 | ||
887 | if (flags & SCSI_RESET) | |
888 | { | |
889 | mscp->opcode = 0x04; | |
890 | mscp->ca = 0x01; | |
891 | } | |
892 | else | |
893 | { | |
894 | mscp->opcode = 0x02; | |
895 | mscp->ca = 0x01; | |
896 | } | |
897 | ||
898 | if (flags & SCSI_DATA_IN) | |
899 | { | |
900 | mscp->xdir = 0x01; | |
901 | } | |
902 | if (flags & SCSI_DATA_OUT) | |
903 | { | |
904 | mscp->xdir = 0x02; | |
905 | } | |
906 | ||
907 | if (xs->lu != 0) | |
908 | { | |
909 | xs->error = XS_DRIVER_STUFFUP; | |
910 | uha_free_mscp(unit,mscp,flags); | |
911 | return(HAD_ERROR); | |
912 | } | |
913 | ||
914 | mscp->dcn = 0x00; | |
915 | mscp->chan = 0x00; | |
916 | mscp->target = xs->targ; | |
917 | mscp->lun = xs->lu; | |
918 | mscp->link.addr[0] = 0x00; | |
919 | mscp->link.addr[1] = 0x00; | |
920 | mscp->link.addr[2] = 0x00; | |
921 | mscp->link.addr[3] = 0x00; | |
922 | mscp->link_id = 0x00; | |
923 | mscp->cdblen = xs->cmdlen; | |
924 | scratch = KVTOPHYS(&(mscp->mscp_sense)); | |
925 | mscp->sense.addr[0] = (scratch & 0xff); | |
926 | mscp->sense.addr[1] = ((scratch >> 8) & 0xff); | |
927 | mscp->sense.addr[2] = ((scratch >> 16) & 0xff); | |
928 | mscp->sense.addr[3] = ((scratch >> 24) & 0xff); | |
929 | mscp->senselen = sizeof(mscp->mscp_sense); | |
930 | mscp->ha_status = 0x00; | |
931 | mscp->targ_status = 0x00; | |
932 | ||
933 | if(xs->datalen) | |
934 | { /* should use S/G only if not zero length */ | |
935 | scratch = KVTOPHYS(mscp->uha_dma); | |
936 | mscp->data.addr[0] = (scratch & 0xff); | |
937 | mscp->data.addr[1] = ((scratch >> 8) & 0xff); | |
938 | mscp->data.addr[2] = ((scratch >> 16) & 0xff); | |
939 | mscp->data.addr[3] = ((scratch >> 24) & 0xff); | |
940 | sg = mscp->uha_dma ; | |
941 | seg = 0; | |
942 | mscp->sgth = 0x01; | |
943 | ||
944 | if(flags & SCSI_DATA_UIO) | |
945 | { | |
946 | iovp = ((struct uio *)xs->data)->uio_iov; | |
947 | datalen = ((struct uio *)xs->data)->uio_iovcnt; | |
948 | xs->datalen = 0; | |
949 | while ((datalen) && (seg < UHA_NSEG)) | |
950 | { | |
951 | scratch = (unsigned long)iovp->iov_base; | |
952 | sg->addr.addr[0] = (scratch & 0xff); | |
953 | sg->addr.addr[1] = ((scratch >> 8) & 0xff); | |
954 | sg->addr.addr[2] = ((scratch >> 16) & 0xff); | |
955 | sg->addr.addr[3] = ((scratch >> 24) & 0xff); | |
956 | xs->datalen += *(unsigned long *)sg->len.len = iovp->iov_len; | |
78ed81a3 | 957 | #ifdef UHADEBUG |
15637ed4 RG |
958 | if(scsi_debug & SHOWSCATGATH) |
959 | printf("(0x%x@0x%x)" | |
960 | ,iovp->iov_len | |
961 | ,iovp->iov_base); | |
78ed81a3 | 962 | #endif /*UHADEBUG*/ |
15637ed4 RG |
963 | sg++; |
964 | iovp++; | |
965 | seg++; | |
966 | datalen--; | |
967 | } | |
968 | } | |
969 | else | |
970 | { | |
971 | /***********************************************\ | |
972 | * Set up the scatter gather block * | |
973 | \***********************************************/ | |
974 | ||
78ed81a3 | 975 | #ifdef UHADEBUG |
15637ed4 RG |
976 | if(scsi_debug & SHOWSCATGATH) |
977 | printf("%d @0x%x:- ",xs->datalen,xs->data); | |
78ed81a3 | 978 | #endif /*UHADEBUG*/ |
15637ed4 RG |
979 | datalen = xs->datalen; |
980 | thiskv = (int)xs->data; | |
981 | thisphys = KVTOPHYS(thiskv); | |
982 | templen = 0; | |
983 | ||
984 | while ((datalen) && (seg < UHA_NSEG)) | |
985 | { | |
986 | bytes_this_seg = 0; | |
987 | ||
988 | /* put in the base address */ | |
989 | sg->addr.addr[0] = (thisphys & 0xff); | |
990 | sg->addr.addr[1] = ((thisphys >> 8) & 0xff); | |
991 | sg->addr.addr[2] = ((thisphys >> 16) & 0xff); | |
992 | sg->addr.addr[3] = ((thisphys >> 24) & 0xff); | |
993 | ||
78ed81a3 | 994 | #ifdef UHADEBUG |
15637ed4 RG |
995 | if(scsi_debug & SHOWSCATGATH) |
996 | printf("0x%x",thisphys); | |
78ed81a3 | 997 | #endif /*UHADEBUG*/ |
15637ed4 RG |
998 | |
999 | /* do it at least once */ | |
1000 | nextphys = thisphys; | |
1001 | while ((datalen) && (thisphys == nextphys)) | |
1002 | /*********************************************\ | |
1003 | * This page is contiguous (physically) with * | |
1004 | * the the last, just extend the length * | |
1005 | \*********************************************/ | |
1006 | { | |
1007 | /* how far to the end of the page */ | |
1008 | nextphys = (thisphys & (~(PAGESIZ - 1))) | |
1009 | + PAGESIZ; | |
1010 | bytes_this_page = nextphys - thisphys; | |
1011 | /**** or the data ****/ | |
1012 | bytes_this_page = min(bytes_this_page | |
1013 | ,datalen); | |
1014 | bytes_this_seg += bytes_this_page; | |
1015 | datalen -= bytes_this_page; | |
1016 | ||
1017 | /* get more ready for the next page */ | |
1018 | thiskv = (thiskv & (~(PAGESIZ - 1))) | |
1019 | + PAGESIZ; | |
1020 | if(datalen) | |
1021 | thisphys = KVTOPHYS(thiskv); | |
1022 | } | |
1023 | /********************************************\ | |
1024 | * next page isn't contiguous, finish the seg * | |
1025 | \********************************************/ | |
78ed81a3 | 1026 | #ifdef UHADEBUG |
15637ed4 RG |
1027 | if(scsi_debug & SHOWSCATGATH) |
1028 | printf("(0x%x)",bytes_this_seg); | |
78ed81a3 | 1029 | #endif /*UHADEBUG*/ |
15637ed4 RG |
1030 | sg->len.len[0] = (bytes_this_seg & 0xff); |
1031 | sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff); | |
1032 | sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff); | |
1033 | sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff); | |
1034 | templen += bytes_this_seg; | |
1035 | sg++; | |
1036 | seg++; | |
1037 | } | |
1038 | } /*end of iov/kv decision */ | |
1039 | mscp->datalen.len[0] = (templen & 0xff); | |
1040 | mscp->datalen.len[1] = ((templen >> 8) & 0xff); | |
1041 | mscp->datalen.len[2] = ((templen >> 16) & 0xff); | |
1042 | mscp->datalen.len[3] = ((templen >> 24) & 0xff); | |
1043 | mscp->sg_num = seg; | |
1044 | ||
78ed81a3 | 1045 | #ifdef UHADEBUG |
15637ed4 RG |
1046 | if(scsi_debug & SHOWSCATGATH) |
1047 | printf("\n"); | |
78ed81a3 | 1048 | #endif /*UHADEBUG*/ |
15637ed4 RG |
1049 | if (datalen) |
1050 | { /* there's still data, must have run out of segs! */ | |
78ed81a3 | 1051 | printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n", |
15637ed4 RG |
1052 | unit,UHA_NSEG); |
1053 | xs->error = XS_DRIVER_STUFFUP; | |
1054 | uha_free_mscp(unit,mscp,flags); | |
1055 | return(HAD_ERROR); | |
1056 | } | |
1057 | ||
1058 | } | |
1059 | else | |
1060 | { /* No data xfer, use non S/G values */ | |
1061 | mscp->data.addr[0] = 0x00; | |
1062 | mscp->data.addr[1] = 0x00; | |
1063 | mscp->data.addr[2] = 0x00; | |
1064 | mscp->data.addr[3] = 0x00; | |
1065 | mscp->datalen.len[0] = 0x00; | |
1066 | mscp->datalen.len[1] = 0x00; | |
1067 | mscp->datalen.len[2] = 0x00; | |
1068 | mscp->datalen.len[3] = 0x00; | |
1069 | mscp->xdir = 0x03; | |
1070 | mscp->sgth = 0x00; | |
1071 | mscp->sg_num = 0x00; | |
1072 | } | |
1073 | ||
1074 | /***********************************************\ | |
1075 | * Put the scsi command in the mscp and start it * | |
1076 | \***********************************************/ | |
1077 | bcopy(xs->cmd, mscp->cdb, xs->cmdlen); | |
1078 | ||
1079 | /***********************************************\ | |
1080 | * Usually return SUCCESSFULLY QUEUED * | |
1081 | \***********************************************/ | |
1082 | if (!(flags & SCSI_NOMASK)) | |
1083 | { | |
1084 | s = splbio(); | |
1085 | uha_send_mbox(unit,mscp); | |
78ed81a3 | 1086 | timeout(uha_timeout,mscp,(xs->timeout * hz) / 1000); |
15637ed4 | 1087 | splx(s); |
78ed81a3 | 1088 | #ifdef UHADEBUG |
15637ed4 RG |
1089 | if(scsi_debug & TRACEINTERRUPTS) |
1090 | printf("cmd_sent "); | |
78ed81a3 | 1091 | #endif /*UHADEBUG*/ |
15637ed4 RG |
1092 | return(SUCCESSFULLY_QUEUED); |
1093 | } | |
1094 | /***********************************************\ | |
1095 | * If we can't use interrupts, poll on completion* | |
1096 | \***********************************************/ | |
1097 | uha_send_mbox(unit,mscp); | |
78ed81a3 | 1098 | #ifdef UHADEBUG |
15637ed4 RG |
1099 | if(scsi_debug & TRACEINTERRUPTS) |
1100 | printf("cmd_wait "); | |
78ed81a3 | 1101 | #endif /*UHADEBUG*/ |
15637ed4 RG |
1102 | do |
1103 | { | |
1104 | if(uha_poll(unit,xs->timeout)) | |
1105 | { | |
78ed81a3 | 1106 | if (!(xs->flags & SCSI_SILENT)) |
1107 | printf("uha%d: cmd fail\n",unit); | |
15637ed4 RG |
1108 | if(!(uha_abort(unit,mscp))) |
1109 | { | |
78ed81a3 | 1110 | printf("uha%d: abort failed in wait\n",unit); |
15637ed4 RG |
1111 | uha_free_mscp(unit,mscp,flags); |
1112 | } | |
1113 | xs->error = XS_DRIVER_STUFFUP; | |
15637ed4 RG |
1114 | return(HAD_ERROR); |
1115 | } | |
1116 | } while (!(xs->flags & ITSDONE));/* something (?) else finished */ | |
15637ed4 RG |
1117 | if(xs->error) |
1118 | { | |
1119 | return(HAD_ERROR); | |
1120 | } | |
1121 | return(COMPLETE); | |
1122 | } | |
1123 | ||
15637ed4 | 1124 | |
78ed81a3 | 1125 | uha_timeout(struct mscp *mscp) |
15637ed4 | 1126 | { |
15637ed4 RG |
1127 | int unit; |
1128 | int s = splbio(); | |
15637ed4 RG |
1129 | int port = uha_data[unit].baseport; |
1130 | ||
78ed81a3 | 1131 | unit = mscp->xs->adapter; |
1132 | printf("uha%d:%d device timed out\n",unit | |
1133 | ,mscp->xs->targ); | |
1134 | #ifdef UHADEBUG | |
1135 | if(uha_debug & UHA_SHOWMSCPS) | |
1136 | uha_print_active_mscp(unit); | |
1137 | #endif /*UHADEBUG*/ | |
1138 | ||
1139 | if((uha_abort(unit,mscp) !=1) || (mscp->flags = MSCP_ABORTED)) | |
15637ed4 | 1140 | { |
78ed81a3 | 1141 | printf("AGAIN"); |
1142 | mscp->xs->retries = 0; /* I MEAN IT ! */ | |
1143 | uha_done(unit,mscp,FAIL); | |
1144 | } | |
1145 | else /* abort the operation that has timed out */ | |
1146 | { | |
1147 | printf("\n"); | |
1148 | timeout(uha_timeout,mscp,2 * hz); | |
1149 | mscp->flags = MSCP_ABORTED; | |
15637ed4 RG |
1150 | } |
1151 | splx(s); | |
15637ed4 RG |
1152 | } |
1153 | ||
1154 | uha_show_scsi_cmd(struct scsi_xfer *xs) | |
1155 | { | |
1156 | u_char *b = (u_char *)xs->cmd; | |
1157 | int i = 0; | |
1158 | if(!(xs->flags & SCSI_RESET)) | |
1159 | { | |
1160 | printf("uha%d:%d:%d-" | |
1161 | ,xs->adapter | |
1162 | ,xs->targ | |
1163 | ,xs->lu); | |
1164 | while(i < xs->cmdlen ) | |
1165 | { | |
1166 | if(i) printf(","); | |
1167 | printf("%x",b[i++]); | |
1168 | } | |
1169 | printf("-\n"); | |
1170 | } | |
1171 | else | |
1172 | { | |
1173 | printf("uha%d:%d:%d-RESET-\n" | |
1174 | ,xs->adapter | |
1175 | ,xs->targ | |
1176 | ,xs->lu | |
1177 | ); | |
1178 | } | |
1179 | } | |
1180 | uha_print_mscp(mscp) | |
1181 | struct mscp *mscp; | |
1182 | { | |
1183 | printf("mscp:%x op:%x cmdlen:%d senlen:%d\n" | |
1184 | ,mscp | |
1185 | ,mscp->opcode | |
1186 | ,mscp->cdblen | |
1187 | ,mscp->senselen); | |
78ed81a3 | 1188 | printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n" |
15637ed4 RG |
1189 | ,mscp->sgth |
1190 | ,mscp->sg_num | |
1191 | ,mscp->datalen | |
1192 | ,mscp->ha_status | |
1193 | ,mscp->targ_status | |
15637ed4 RG |
1194 | ,mscp->flags); |
1195 | uha_show_scsi_cmd(mscp->xs); | |
1196 | } | |
1197 | ||
78ed81a3 | 1198 | uha_print_active_mscp(int unit) |
15637ed4 | 1199 | { |
78ed81a3 | 1200 | struct mscp *mscp = uha_data[unit].mscps; |
1201 | int i = NUHA; | |
15637ed4 | 1202 | |
78ed81a3 | 1203 | while(i--) |
15637ed4 | 1204 | { |
78ed81a3 | 1205 | if(mscp->flags != MSCP_FREE) |
1206 | uha_print_mscp(mscp); | |
1207 | mscp++; | |
15637ed4 | 1208 | } |
15637ed4 | 1209 | } |