1 | /* $NetBSD: adw.c,v 1.54 2016/07/14 04:19:26 msaitoh Exp $ */ |
2 | |
3 | /* |
4 | * Generic driver for the Advanced Systems Inc. SCSI controllers |
5 | * |
6 | * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. |
7 | * All rights reserved. |
8 | * |
9 | * Author: Baldassare Dante Profeta <dante@mclink.it> |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. |
19 | * 3. All advertising materials mentioning features or use of this software |
20 | * must display the following acknowledgement: |
21 | * This product includes software developed by the NetBSD |
22 | * Foundation, Inc. and its contributors. |
23 | * 4. Neither the name of The NetBSD Foundation nor the names of its |
24 | * contributors may be used to endorse or promote products derived |
25 | * from this software without specific prior written permission. |
26 | * |
27 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
28 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
29 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
31 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | * POSSIBILITY OF SUCH DAMAGE. |
38 | */ |
39 | |
40 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: adw.c,v 1.54 2016/07/14 04:19:26 msaitoh Exp $" ); |
42 | |
43 | #include <sys/param.h> |
44 | #include <sys/systm.h> |
45 | #include <sys/callout.h> |
46 | #include <sys/kernel.h> |
47 | #include <sys/errno.h> |
48 | #include <sys/ioctl.h> |
49 | #include <sys/device.h> |
50 | #include <sys/malloc.h> |
51 | #include <sys/buf.h> |
52 | #include <sys/proc.h> |
53 | |
54 | #include <sys/bus.h> |
55 | #include <sys/intr.h> |
56 | |
57 | #include <dev/scsipi/scsi_all.h> |
58 | #include <dev/scsipi/scsipi_all.h> |
59 | #include <dev/scsipi/scsiconf.h> |
60 | |
61 | #include <dev/ic/adwlib.h> |
62 | #include <dev/ic/adwmcode.h> |
63 | #include <dev/ic/adw.h> |
64 | |
65 | #ifndef DDB |
66 | #define Debugger() panic("should call debugger here (adw.c)") |
67 | #endif /* ! DDB */ |
68 | |
69 | /******************************************************************************/ |
70 | |
71 | |
72 | static int adw_alloc_controls(ADW_SOFTC *); |
73 | static int adw_alloc_carriers(ADW_SOFTC *); |
74 | static int adw_create_ccbs(ADW_SOFTC *, ADW_CCB *, int); |
75 | static void adw_free_ccb(ADW_SOFTC *, ADW_CCB *); |
76 | static void adw_reset_ccb(ADW_CCB *); |
77 | static int adw_init_ccb(ADW_SOFTC *, ADW_CCB *); |
78 | static ADW_CCB *adw_get_ccb(ADW_SOFTC *); |
79 | static int adw_queue_ccb(ADW_SOFTC *, ADW_CCB *); |
80 | |
81 | static void adw_scsipi_request(struct scsipi_channel *, |
82 | scsipi_adapter_req_t, void *); |
83 | static int adw_build_req(ADW_SOFTC *, ADW_CCB *); |
84 | static void adw_build_sglist(ADW_CCB *, ADW_SCSI_REQ_Q *, ADW_SG_BLOCK *); |
85 | static void adwminphys(struct buf *); |
86 | static void adw_isr_callback(ADW_SOFTC *, ADW_SCSI_REQ_Q *); |
87 | static void adw_async_callback(ADW_SOFTC *, u_int8_t); |
88 | |
89 | static void adw_print_info(ADW_SOFTC *, int); |
90 | |
91 | static int adw_poll(ADW_SOFTC *, struct scsipi_xfer *, int); |
92 | static void adw_timeout(void *); |
93 | static void adw_reset_bus(ADW_SOFTC *); |
94 | |
95 | |
96 | /******************************************************************************/ |
97 | /* DMA Mapping for Control Blocks */ |
98 | /******************************************************************************/ |
99 | |
100 | |
101 | static int |
102 | adw_alloc_controls(ADW_SOFTC *sc) |
103 | { |
104 | bus_dma_segment_t seg; |
105 | int error, rseg; |
106 | |
107 | /* |
108 | * Allocate the control structure. |
109 | */ |
110 | if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct adw_control), |
111 | PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { |
112 | aprint_error_dev(sc->sc_dev, "unable to allocate control " |
113 | "structures, error = %d\n" , error); |
114 | return (error); |
115 | } |
116 | if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, |
117 | sizeof(struct adw_control), (void **) & sc->sc_control, |
118 | BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { |
119 | aprint_error_dev(sc->sc_dev, |
120 | "unable to map control structures, error = %d\n" , error); |
121 | return (error); |
122 | } |
123 | |
124 | /* |
125 | * Create and load the DMA map used for the control blocks. |
126 | */ |
127 | if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct adw_control), |
128 | 1, sizeof(struct adw_control), 0, BUS_DMA_NOWAIT, |
129 | &sc->sc_dmamap_control)) != 0) { |
130 | aprint_error_dev(sc->sc_dev, |
131 | "unable to create control DMA map, error = %d\n" , error); |
132 | return (error); |
133 | } |
134 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control, |
135 | sc->sc_control, sizeof(struct adw_control), NULL, |
136 | BUS_DMA_NOWAIT)) != 0) { |
137 | aprint_error_dev(sc->sc_dev, |
138 | "unable to load control DMA map, error = %d\n" , error); |
139 | return (error); |
140 | } |
141 | |
142 | return (0); |
143 | } |
144 | |
145 | |
146 | static int |
147 | adw_alloc_carriers(ADW_SOFTC *sc) |
148 | { |
149 | bus_dma_segment_t seg; |
150 | int error, rseg; |
151 | |
152 | /* |
153 | * Allocate the control structure. |
154 | */ |
155 | sc->sc_control->carriers = malloc(sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, |
156 | M_DEVBUF, M_WAITOK); |
157 | if(!sc->sc_control->carriers) { |
158 | aprint_error_dev(sc->sc_dev, |
159 | "malloc() failed in allocating carrier structures\n" ); |
160 | return (ENOMEM); |
161 | } |
162 | |
163 | if ((error = bus_dmamem_alloc(sc->sc_dmat, |
164 | sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, |
165 | 0x10, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { |
166 | aprint_error_dev(sc->sc_dev, "unable to allocate carrier " |
167 | "structures, error = %d\n" , error); |
168 | return (error); |
169 | } |
170 | if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, |
171 | sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, |
172 | (void **)&sc->sc_control->carriers, |
173 | BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { |
174 | aprint_error_dev(sc->sc_dev, |
175 | "unable to map carrier structures, error = %d\n" , error); |
176 | return (error); |
177 | } |
178 | |
179 | /* |
180 | * Create and load the DMA map used for the control blocks. |
181 | */ |
182 | if ((error = bus_dmamap_create(sc->sc_dmat, |
183 | sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 1, |
184 | sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 0,BUS_DMA_NOWAIT, |
185 | &sc->sc_dmamap_carrier)) != 0) { |
186 | aprint_error_dev(sc->sc_dev, |
187 | "unable to create carriers DMA map, error = %d\n" , error); |
188 | return (error); |
189 | } |
190 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_carrier, |
191 | sc->sc_control->carriers, sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, |
192 | NULL, BUS_DMA_NOWAIT)) != 0) { |
193 | aprint_error_dev(sc->sc_dev, |
194 | "unable to load carriers DMA map, error = %d\n" , error); |
195 | return (error); |
196 | } |
197 | |
198 | return (0); |
199 | } |
200 | |
201 | |
202 | /******************************************************************************/ |
203 | /* Control Blocks routines */ |
204 | /******************************************************************************/ |
205 | |
206 | |
207 | /* |
208 | * Create a set of ccbs and add them to the free list. Called once |
209 | * by adw_init(). We return the number of CCBs successfully created. |
210 | */ |
211 | static int |
212 | adw_create_ccbs(ADW_SOFTC *sc, ADW_CCB *ccbstore, int count) |
213 | { |
214 | ADW_CCB *ccb; |
215 | int i, error; |
216 | |
217 | for (i = 0; i < count; i++) { |
218 | ccb = &ccbstore[i]; |
219 | if ((error = adw_init_ccb(sc, ccb)) != 0) { |
220 | aprint_error_dev(sc->sc_dev, |
221 | "unable to initialize ccb, error = %d\n" , error); |
222 | return (i); |
223 | } |
224 | TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain); |
225 | } |
226 | |
227 | return (i); |
228 | } |
229 | |
230 | |
231 | /* |
232 | * A ccb is put onto the free list. |
233 | */ |
234 | static void |
235 | adw_free_ccb(ADW_SOFTC *sc, ADW_CCB *ccb) |
236 | { |
237 | int s; |
238 | |
239 | s = splbio(); |
240 | |
241 | adw_reset_ccb(ccb); |
242 | TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); |
243 | |
244 | splx(s); |
245 | } |
246 | |
247 | |
248 | static void |
249 | adw_reset_ccb(ADW_CCB *ccb) |
250 | { |
251 | |
252 | ccb->flags = 0; |
253 | } |
254 | |
255 | |
256 | static int |
257 | adw_init_ccb(ADW_SOFTC *sc, ADW_CCB *ccb) |
258 | { |
259 | int hashnum, error; |
260 | |
261 | /* |
262 | * Create the DMA map for this CCB. |
263 | */ |
264 | error = bus_dmamap_create(sc->sc_dmat, |
265 | (ADW_MAX_SG_LIST - 1) * PAGE_SIZE, ADW_MAX_SG_LIST, |
266 | (ADW_MAX_SG_LIST - 1) * PAGE_SIZE, 0, |
267 | BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer); |
268 | if (error) { |
269 | aprint_error_dev(sc->sc_dev, |
270 | "unable to create CCB DMA map, error = %d\n" , error); |
271 | return (error); |
272 | } |
273 | |
274 | /* |
275 | * put in the phystokv hash table |
276 | * Never gets taken out. |
277 | */ |
278 | ccb->hashkey = htole32(sc->sc_dmamap_control->dm_segs[0].ds_addr + |
279 | ADW_CCB_OFF(ccb)); |
280 | hashnum = CCB_HASH(ccb->hashkey); |
281 | ccb->nexthash = sc->sc_ccbhash[hashnum]; |
282 | sc->sc_ccbhash[hashnum] = ccb; |
283 | adw_reset_ccb(ccb); |
284 | return (0); |
285 | } |
286 | |
287 | |
288 | /* |
289 | * Get a free ccb |
290 | * |
291 | * If there are none, see if we can allocate a new one |
292 | */ |
293 | static ADW_CCB * |
294 | adw_get_ccb(ADW_SOFTC *sc) |
295 | { |
296 | ADW_CCB *ccb = 0; |
297 | int s; |
298 | |
299 | s = splbio(); |
300 | |
301 | ccb = sc->sc_free_ccb.tqh_first; |
302 | if (ccb != NULL) { |
303 | TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); |
304 | ccb->flags |= CCB_ALLOC; |
305 | } |
306 | splx(s); |
307 | return (ccb); |
308 | } |
309 | |
310 | |
311 | /* |
312 | * Given a physical address, find the ccb that it corresponds to. |
313 | */ |
314 | ADW_CCB * |
315 | adw_ccb_phys_kv(ADW_SOFTC *sc, u_int32_t ccb_phys) |
316 | { |
317 | int hashnum = CCB_HASH(ccb_phys); |
318 | ADW_CCB *ccb = sc->sc_ccbhash[hashnum]; |
319 | |
320 | while (ccb) { |
321 | if (ccb->hashkey == ccb_phys) |
322 | break; |
323 | ccb = ccb->nexthash; |
324 | } |
325 | return (ccb); |
326 | } |
327 | |
328 | |
329 | /* |
330 | * Queue a CCB to be sent to the controller, and send it if possible. |
331 | */ |
332 | static int |
333 | adw_queue_ccb(ADW_SOFTC *sc, ADW_CCB *ccb) |
334 | { |
335 | int errcode = ADW_SUCCESS; |
336 | |
337 | TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain); |
338 | |
339 | while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) { |
340 | |
341 | TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain); |
342 | errcode = AdwExeScsiQueue(sc, &ccb->scsiq); |
343 | switch(errcode) { |
344 | case ADW_SUCCESS: |
345 | break; |
346 | |
347 | case ADW_BUSY: |
348 | printf("ADW_BUSY\n" ); |
349 | return(ADW_BUSY); |
350 | |
351 | case ADW_ERROR: |
352 | printf("ADW_ERROR\n" ); |
353 | return(ADW_ERROR); |
354 | } |
355 | |
356 | TAILQ_INSERT_TAIL(&sc->sc_pending_ccb, ccb, chain); |
357 | |
358 | if ((ccb->xs->xs_control & XS_CTL_POLL) == 0) |
359 | callout_reset(&ccb->xs->xs_callout, |
360 | mstohz(ccb->timeout), adw_timeout, ccb); |
361 | } |
362 | |
363 | return(errcode); |
364 | } |
365 | |
366 | |
367 | /******************************************************************************/ |
368 | /* SCSI layer interfacing routines */ |
369 | /******************************************************************************/ |
370 | |
371 | |
372 | int |
373 | adw_init(ADW_SOFTC *sc) |
374 | { |
375 | u_int16_t warn_code; |
376 | |
377 | |
378 | sc->cfg.lib_version = (ADW_LIB_VERSION_MAJOR << 8) | |
379 | ADW_LIB_VERSION_MINOR; |
380 | sc->cfg.chip_version = |
381 | ADW_GET_CHIP_VERSION(sc->sc_iot, sc->sc_ioh, sc->bus_type); |
382 | |
383 | /* |
384 | * Reset the chip to start and allow register writes. |
385 | */ |
386 | if (ADW_FIND_SIGNATURE(sc->sc_iot, sc->sc_ioh) == 0) { |
387 | panic("adw_init: adw_find_signature failed" ); |
388 | } else { |
389 | AdwResetChip(sc->sc_iot, sc->sc_ioh); |
390 | |
391 | warn_code = AdwInitFromEEPROM(sc); |
392 | |
393 | if (warn_code & ADW_WARN_EEPROM_CHKSUM) |
394 | aprint_error_dev(sc->sc_dev, "Bad checksum found. " |
395 | "Setting default values\n" ); |
396 | if (warn_code & ADW_WARN_EEPROM_TERMINATION) |
397 | aprint_error_dev(sc->sc_dev, "Bad bus termination " |
398 | "setting. Using automatic termination.\n" ); |
399 | } |
400 | |
401 | sc->isr_callback = (ADW_CALLBACK) adw_isr_callback; |
402 | sc->async_callback = (ADW_CALLBACK) adw_async_callback; |
403 | |
404 | return 0; |
405 | } |
406 | |
407 | |
408 | void |
409 | adw_attach(ADW_SOFTC *sc) |
410 | { |
411 | struct scsipi_adapter *adapt = &sc->sc_adapter; |
412 | struct scsipi_channel *chan = &sc->sc_channel; |
413 | int ncontrols, error; |
414 | |
415 | TAILQ_INIT(&sc->sc_free_ccb); |
416 | TAILQ_INIT(&sc->sc_waiting_ccb); |
417 | TAILQ_INIT(&sc->sc_pending_ccb); |
418 | |
419 | /* |
420 | * Allocate the Control Blocks. |
421 | */ |
422 | error = adw_alloc_controls(sc); |
423 | if (error) |
424 | return; /* (error) */ ; |
425 | |
426 | memset(sc->sc_control, 0, sizeof(struct adw_control)); |
427 | |
428 | /* |
429 | * Create and initialize the Control Blocks. |
430 | */ |
431 | ncontrols = adw_create_ccbs(sc, sc->sc_control->ccbs, ADW_MAX_CCB); |
432 | if (ncontrols == 0) { |
433 | aprint_error_dev(sc->sc_dev, |
434 | "unable to create Control Blocks\n" ); |
435 | return; /* (ENOMEM) */ ; |
436 | } else if (ncontrols != ADW_MAX_CCB) { |
437 | aprint_error_dev(sc->sc_dev, |
438 | "WARNING: only %d of %d Control Blocks created\n" , |
439 | ncontrols, ADW_MAX_CCB); |
440 | } |
441 | |
442 | /* |
443 | * Create and initialize the Carriers. |
444 | */ |
445 | error = adw_alloc_carriers(sc); |
446 | if (error) |
447 | return; /* (error) */ ; |
448 | |
449 | /* |
450 | * Zero's the freeze_device status |
451 | */ |
452 | memset(sc->sc_freeze_dev, 0, sizeof(sc->sc_freeze_dev)); |
453 | |
454 | /* |
455 | * Initialize the adapter |
456 | */ |
457 | switch (AdwInitDriver(sc)) { |
458 | case ADW_IERR_BIST_PRE_TEST: |
459 | panic("%s: BIST pre-test error" , |
460 | device_xname(sc->sc_dev)); |
461 | break; |
462 | |
463 | case ADW_IERR_BIST_RAM_TEST: |
464 | panic("%s: BIST RAM test error" , |
465 | device_xname(sc->sc_dev)); |
466 | break; |
467 | |
468 | case ADW_IERR_MCODE_CHKSUM: |
469 | panic("%s: Microcode checksum error" , |
470 | device_xname(sc->sc_dev)); |
471 | break; |
472 | |
473 | case ADW_IERR_ILLEGAL_CONNECTION: |
474 | panic("%s: All three connectors are in use" , |
475 | device_xname(sc->sc_dev)); |
476 | break; |
477 | |
478 | case ADW_IERR_REVERSED_CABLE: |
479 | panic("%s: Cable is reversed" , |
480 | device_xname(sc->sc_dev)); |
481 | break; |
482 | |
483 | case ADW_IERR_HVD_DEVICE: |
484 | panic("%s: HVD attached to LVD connector" , |
485 | device_xname(sc->sc_dev)); |
486 | break; |
487 | |
488 | case ADW_IERR_SINGLE_END_DEVICE: |
489 | panic("%s: single-ended device is attached to" |
490 | " one of the connectors" , |
491 | device_xname(sc->sc_dev)); |
492 | break; |
493 | |
494 | case ADW_IERR_NO_CARRIER: |
495 | panic("%s: unable to create Carriers" , |
496 | device_xname(sc->sc_dev)); |
497 | break; |
498 | |
499 | case ADW_WARN_BUSRESET_ERROR: |
500 | aprint_error_dev(sc->sc_dev, "WARNING: Bus Reset Error\n" ); |
501 | break; |
502 | } |
503 | |
504 | /* |
505 | * Fill in the scsipi_adapter. |
506 | */ |
507 | memset(adapt, 0, sizeof(*adapt)); |
508 | adapt->adapt_dev = sc->sc_dev; |
509 | adapt->adapt_nchannels = 1; |
510 | adapt->adapt_openings = ncontrols; |
511 | adapt->adapt_max_periph = adapt->adapt_openings; |
512 | adapt->adapt_request = adw_scsipi_request; |
513 | adapt->adapt_minphys = adwminphys; |
514 | |
515 | /* |
516 | * Fill in the scsipi_channel. |
517 | */ |
518 | memset(chan, 0, sizeof(*chan)); |
519 | chan->chan_adapter = adapt; |
520 | chan->chan_bustype = &scsi_bustype; |
521 | chan->chan_channel = 0; |
522 | chan->chan_ntargets = ADW_MAX_TID + 1; |
523 | chan->chan_nluns = 8; |
524 | chan->chan_id = sc->chip_scsi_id; |
525 | |
526 | config_found(sc->sc_dev, &sc->sc_channel, scsiprint); |
527 | } |
528 | |
529 | |
530 | static void |
531 | adwminphys(struct buf *bp) |
532 | { |
533 | |
534 | if (bp->b_bcount > ((ADW_MAX_SG_LIST - 1) * PAGE_SIZE)) |
535 | bp->b_bcount = ((ADW_MAX_SG_LIST - 1) * PAGE_SIZE); |
536 | minphys(bp); |
537 | } |
538 | |
539 | |
540 | /* |
541 | * start a scsi operation given the command and the data address. |
542 | * Also needs the unit, target and lu. |
543 | */ |
544 | static void |
545 | adw_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, |
546 | void *arg) |
547 | { |
548 | struct scsipi_xfer *xs; |
549 | ADW_SOFTC *sc = device_private(chan->chan_adapter->adapt_dev); |
550 | ADW_CCB *ccb; |
551 | int s, retry; |
552 | |
553 | switch (req) { |
554 | case ADAPTER_REQ_RUN_XFER: |
555 | xs = arg; |
556 | |
557 | /* |
558 | * get a ccb to use. If the transfer |
559 | * is from a buf (possibly from interrupt time) |
560 | * then we can't allow it to sleep |
561 | */ |
562 | |
563 | ccb = adw_get_ccb(sc); |
564 | #ifdef DIAGNOSTIC |
565 | /* |
566 | * This should never happen as we track the resources |
567 | * in the mid-layer. |
568 | */ |
569 | if (ccb == NULL) { |
570 | scsipi_printaddr(xs->xs_periph); |
571 | printf("unable to allocate ccb\n" ); |
572 | panic("adw_scsipi_request" ); |
573 | } |
574 | #endif |
575 | |
576 | ccb->xs = xs; |
577 | ccb->timeout = xs->timeout; |
578 | |
579 | if (adw_build_req(sc, ccb)) { |
580 | s = splbio(); |
581 | retry = adw_queue_ccb(sc, ccb); |
582 | splx(s); |
583 | |
584 | switch(retry) { |
585 | case ADW_BUSY: |
586 | xs->error = XS_RESOURCE_SHORTAGE; |
587 | adw_free_ccb(sc, ccb); |
588 | scsipi_done(xs); |
589 | return; |
590 | |
591 | case ADW_ERROR: |
592 | xs->error = XS_DRIVER_STUFFUP; |
593 | adw_free_ccb(sc, ccb); |
594 | scsipi_done(xs); |
595 | return; |
596 | } |
597 | if ((xs->xs_control & XS_CTL_POLL) == 0) |
598 | return; |
599 | /* |
600 | * Not allowed to use interrupts, poll for completion. |
601 | */ |
602 | if (adw_poll(sc, xs, ccb->timeout)) { |
603 | adw_timeout(ccb); |
604 | if (adw_poll(sc, xs, ccb->timeout)) |
605 | adw_timeout(ccb); |
606 | } |
607 | } |
608 | return; |
609 | |
610 | case ADAPTER_REQ_GROW_RESOURCES: |
611 | /* XXX Not supported. */ |
612 | return; |
613 | |
614 | case ADAPTER_REQ_SET_XFER_MODE: |
615 | /* XXX XXX XXX */ |
616 | return; |
617 | } |
618 | } |
619 | |
620 | |
621 | /* |
622 | * Build a request structure for the Wide Boards. |
623 | */ |
624 | static int |
625 | adw_build_req(ADW_SOFTC *sc, ADW_CCB *ccb) |
626 | { |
627 | struct scsipi_xfer *xs = ccb->xs; |
628 | struct scsipi_periph *periph = xs->xs_periph; |
629 | bus_dma_tag_t dmat = sc->sc_dmat; |
630 | ADW_SCSI_REQ_Q *scsiqp; |
631 | int error; |
632 | |
633 | scsiqp = &ccb->scsiq; |
634 | memset(scsiqp, 0, sizeof(ADW_SCSI_REQ_Q)); |
635 | |
636 | /* |
637 | * Set the ADW_SCSI_REQ_Q 'ccb_ptr' to point to the |
638 | * physical CCB structure. |
639 | */ |
640 | scsiqp->ccb_ptr = ccb->hashkey; |
641 | |
642 | /* |
643 | * Build the ADW_SCSI_REQ_Q request. |
644 | */ |
645 | |
646 | /* |
647 | * Set CDB length and copy it to the request structure. |
648 | * For wide boards a CDB length maximum of 16 bytes |
649 | * is supported. |
650 | */ |
651 | memcpy(&scsiqp->cdb, xs->cmd, ((scsiqp->cdb_len = xs->cmdlen) <= 12)? |
652 | xs->cmdlen : 12 ); |
653 | if(xs->cmdlen > 12) |
654 | memcpy(&scsiqp->cdb16, &(xs->cmd[12]), xs->cmdlen - 12); |
655 | |
656 | scsiqp->target_id = periph->periph_target; |
657 | scsiqp->target_lun = periph->periph_lun; |
658 | |
659 | scsiqp->vsense_addr = &ccb->scsi_sense; |
660 | scsiqp->sense_addr = htole32(sc->sc_dmamap_control->dm_segs[0].ds_addr + |
661 | ADW_CCB_OFF(ccb) + offsetof(struct adw_ccb, scsi_sense)); |
662 | scsiqp->sense_len = sizeof(struct scsi_sense_data); |
663 | |
664 | /* |
665 | * Build ADW_SCSI_REQ_Q for a scatter-gather buffer command. |
666 | */ |
667 | if (xs->datalen) { |
668 | /* |
669 | * Map the DMA transfer. |
670 | */ |
671 | #ifdef TFS |
672 | if (xs->xs_control & SCSI_DATA_UIO) { |
673 | error = bus_dmamap_load_uio(dmat, |
674 | ccb->dmamap_xfer, (struct uio *) xs->data, |
675 | ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : |
676 | BUS_DMA_WAITOK) | BUS_DMA_STREAMING | |
677 | ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : |
678 | BUS_DMA_WRITE)); |
679 | } else |
680 | #endif /* TFS */ |
681 | { |
682 | error = bus_dmamap_load(dmat, |
683 | ccb->dmamap_xfer, xs->data, xs->datalen, NULL, |
684 | ((xs->xs_control & XS_CTL_NOSLEEP) ? |
685 | BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | |
686 | BUS_DMA_STREAMING | |
687 | ((xs->xs_control & XS_CTL_DATA_IN) ? |
688 | BUS_DMA_READ : BUS_DMA_WRITE)); |
689 | } |
690 | |
691 | switch (error) { |
692 | case 0: |
693 | break; |
694 | case ENOMEM: |
695 | case EAGAIN: |
696 | xs->error = XS_RESOURCE_SHORTAGE; |
697 | goto out_bad; |
698 | |
699 | default: |
700 | xs->error = XS_DRIVER_STUFFUP; |
701 | aprint_error_dev(sc->sc_dev, |
702 | "error %d loading DMA map\n" , error); |
703 | out_bad: |
704 | adw_free_ccb(sc, ccb); |
705 | scsipi_done(xs); |
706 | return(0); |
707 | } |
708 | |
709 | bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, |
710 | ccb->dmamap_xfer->dm_mapsize, |
711 | (xs->xs_control & XS_CTL_DATA_IN) ? |
712 | BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); |
713 | |
714 | /* |
715 | * Build scatter-gather list. |
716 | */ |
717 | scsiqp->data_cnt = htole32(xs->datalen); |
718 | scsiqp->vdata_addr = xs->data; |
719 | scsiqp->data_addr = htole32(ccb->dmamap_xfer->dm_segs[0].ds_addr); |
720 | memset(ccb->sg_block, 0, |
721 | sizeof(ADW_SG_BLOCK) * ADW_NUM_SG_BLOCK); |
722 | adw_build_sglist(ccb, scsiqp, ccb->sg_block); |
723 | } else { |
724 | /* |
725 | * No data xfer, use non S/G values. |
726 | */ |
727 | scsiqp->data_cnt = 0; |
728 | scsiqp->vdata_addr = 0; |
729 | scsiqp->data_addr = 0; |
730 | } |
731 | |
732 | return (1); |
733 | } |
734 | |
735 | |
736 | /* |
737 | * Build scatter-gather list for Wide Boards. |
738 | */ |
739 | static void |
740 | adw_build_sglist(ADW_CCB *ccb, ADW_SCSI_REQ_Q *scsiqp, ADW_SG_BLOCK *sg_block) |
741 | { |
742 | u_long sg_block_next_addr; /* block and its next */ |
743 | u_int32_t sg_block_physical_addr; |
744 | int i; /* how many SG entries */ |
745 | bus_dma_segment_t *sg_list = &ccb->dmamap_xfer->dm_segs[0]; |
746 | int sg_elem_cnt = ccb->dmamap_xfer->dm_nsegs; |
747 | |
748 | |
749 | sg_block_next_addr = (u_long) sg_block; /* allow math operation */ |
750 | sg_block_physical_addr = le32toh(ccb->hashkey) + |
751 | offsetof(struct adw_ccb, sg_block[0]); |
752 | scsiqp->sg_real_addr = htole32(sg_block_physical_addr); |
753 | |
754 | /* |
755 | * If there are more than NO_OF_SG_PER_BLOCK DMA segments (hw sg-list) |
756 | * then split the request into multiple sg-list blocks. |
757 | */ |
758 | |
759 | do { |
760 | for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { |
761 | sg_block->sg_list[i].sg_addr = htole32(sg_list->ds_addr); |
762 | sg_block->sg_list[i].sg_count = htole32(sg_list->ds_len); |
763 | |
764 | if (--sg_elem_cnt == 0) { |
765 | /* last entry, get out */ |
766 | sg_block->sg_cnt = i + 1; |
767 | sg_block->sg_ptr = 0; /* next link = NULL */ |
768 | return; |
769 | } |
770 | sg_list++; |
771 | } |
772 | sg_block_next_addr += sizeof(ADW_SG_BLOCK); |
773 | sg_block_physical_addr += sizeof(ADW_SG_BLOCK); |
774 | |
775 | sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; |
776 | sg_block->sg_ptr = htole32(sg_block_physical_addr); |
777 | sg_block = (ADW_SG_BLOCK *) sg_block_next_addr; /* virt. addr */ |
778 | } while (1); |
779 | } |
780 | |
781 | |
782 | /******************************************************************************/ |
783 | /* Interrupts and TimeOut routines */ |
784 | /******************************************************************************/ |
785 | |
786 | |
787 | int |
788 | adw_intr(void *arg) |
789 | { |
790 | ADW_SOFTC *sc = arg; |
791 | |
792 | |
793 | if(AdwISR(sc) != ADW_FALSE) { |
794 | return (1); |
795 | } |
796 | |
797 | return (0); |
798 | } |
799 | |
800 | |
801 | /* |
802 | * Poll a particular unit, looking for a particular xs |
803 | */ |
804 | static int |
805 | adw_poll(ADW_SOFTC *sc, struct scsipi_xfer *xs, int count) |
806 | { |
807 | |
808 | /* timeouts are in msec, so we loop in 1000 usec cycles */ |
809 | while (count) { |
810 | adw_intr(sc); |
811 | if (xs->xs_status & XS_STS_DONE) |
812 | return (0); |
813 | delay(1000); /* only happens in boot so ok */ |
814 | count--; |
815 | } |
816 | return (1); |
817 | } |
818 | |
819 | |
820 | static void |
821 | adw_timeout(void *arg) |
822 | { |
823 | ADW_CCB *ccb = arg; |
824 | struct scsipi_xfer *xs = ccb->xs; |
825 | struct scsipi_periph *periph = xs->xs_periph; |
826 | ADW_SOFTC *sc = |
827 | device_private(periph->periph_channel->chan_adapter->adapt_dev); |
828 | int s; |
829 | |
830 | scsipi_printaddr(periph); |
831 | printf("timed out" ); |
832 | |
833 | s = splbio(); |
834 | |
835 | if (ccb->flags & CCB_ABORTED) { |
836 | /* |
837 | * Abort Timed Out |
838 | * |
839 | * No more opportunities. Lets try resetting the bus and |
840 | * reinitialize the host adapter. |
841 | */ |
842 | callout_stop(&xs->xs_callout); |
843 | printf(" AGAIN. Resetting SCSI Bus\n" ); |
844 | adw_reset_bus(sc); |
845 | splx(s); |
846 | return; |
847 | } else if (ccb->flags & CCB_ABORTING) { |
848 | /* |
849 | * Abort the operation that has timed out. |
850 | * |
851 | * Second opportunity. |
852 | */ |
853 | printf("\n" ); |
854 | xs->error = XS_TIMEOUT; |
855 | ccb->flags |= CCB_ABORTED; |
856 | #if 0 |
857 | /* |
858 | * - XXX - 3.3a microcode is BROKEN!!! |
859 | * |
860 | * We cannot abort a CCB, so we can only hope the command |
861 | * get completed before the next timeout, otherwise a |
862 | * Bus Reset will arrive inexorably. |
863 | */ |
864 | /* |
865 | * ADW_ABORT_CCB() makes the board to generate an interrupt |
866 | * |
867 | * - XXX - The above assertion MUST be verified (and this |
868 | * code changed as well [callout_*()]), when the |
869 | * ADW_ABORT_CCB will be working again |
870 | */ |
871 | ADW_ABORT_CCB(sc, ccb); |
872 | #endif |
873 | /* |
874 | * waiting for multishot callout_reset() let's restart it |
875 | * by hand so the next time a timeout event will occur |
876 | * we will reset the bus. |
877 | */ |
878 | callout_reset(&xs->xs_callout, |
879 | mstohz(ccb->timeout), adw_timeout, ccb); |
880 | } else { |
881 | /* |
882 | * Abort the operation that has timed out. |
883 | * |
884 | * First opportunity. |
885 | */ |
886 | printf("\n" ); |
887 | xs->error = XS_TIMEOUT; |
888 | ccb->flags |= CCB_ABORTING; |
889 | #if 0 |
890 | /* |
891 | * - XXX - 3.3a microcode is BROKEN!!! |
892 | * |
893 | * We cannot abort a CCB, so we can only hope the command |
894 | * get completed before the next 2 timeout, otherwise a |
895 | * Bus Reset will arrive inexorably. |
896 | */ |
897 | /* |
898 | * ADW_ABORT_CCB() makes the board to generate an interrupt |
899 | * |
900 | * - XXX - The above assertion MUST be verified (and this |
901 | * code changed as well [callout_*()]), when the |
902 | * ADW_ABORT_CCB will be working again |
903 | */ |
904 | ADW_ABORT_CCB(sc, ccb); |
905 | #endif |
906 | /* |
907 | * waiting for multishot callout_reset() let's restart it |
908 | * by hand so to give a second opportunity to the command |
909 | * which timed-out. |
910 | */ |
911 | callout_reset(&xs->xs_callout, |
912 | mstohz(ccb->timeout), adw_timeout, ccb); |
913 | } |
914 | |
915 | splx(s); |
916 | } |
917 | |
918 | |
919 | static void |
920 | adw_reset_bus(ADW_SOFTC *sc) |
921 | { |
922 | ADW_CCB *ccb; |
923 | int s; |
924 | struct scsipi_xfer *xs; |
925 | |
926 | s = splbio(); |
927 | AdwResetSCSIBus(sc); |
928 | while((ccb = TAILQ_LAST(&sc->sc_pending_ccb, |
929 | adw_pending_ccb)) != NULL) { |
930 | callout_stop(&ccb->xs->xs_callout); |
931 | TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain); |
932 | xs = ccb->xs; |
933 | adw_free_ccb(sc, ccb); |
934 | xs->error = XS_RESOURCE_SHORTAGE; |
935 | scsipi_done(xs); |
936 | } |
937 | splx(s); |
938 | } |
939 | |
940 | |
941 | /******************************************************************************/ |
942 | /* Host Adapter and Peripherals Information Routines */ |
943 | /******************************************************************************/ |
944 | |
945 | |
946 | static void |
947 | adw_print_info(ADW_SOFTC *sc, int tid) |
948 | { |
949 | bus_space_tag_t iot = sc->sc_iot; |
950 | bus_space_handle_t ioh = sc->sc_ioh; |
951 | u_int16_t wdtr_able, wdtr_done, wdtr; |
952 | u_int16_t sdtr_able, sdtr_done, sdtr, period; |
953 | static int wdtr_reneg = 0, sdtr_reneg = 0; |
954 | |
955 | if (tid == 0){ |
956 | wdtr_reneg = sdtr_reneg = 0; |
957 | } |
958 | |
959 | printf("%s: target %d " , device_xname(sc->sc_dev), tid); |
960 | |
961 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, wdtr_able); |
962 | if(wdtr_able & ADW_TID_TO_TIDMASK(tid)) { |
963 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE, wdtr_done); |
964 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_DEVICE_HSHK_CFG_TABLE + |
965 | (2 * tid), wdtr); |
966 | printf("using %d-bits wide, " , (wdtr & 0x8000)? 16 : 8); |
967 | if((wdtr_done & ADW_TID_TO_TIDMASK(tid)) == 0) |
968 | wdtr_reneg = 1; |
969 | } else { |
970 | printf("wide transfers disabled, " ); |
971 | } |
972 | |
973 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_ABLE, sdtr_able); |
974 | if(sdtr_able & ADW_TID_TO_TIDMASK(tid)) { |
975 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_SDTR_DONE, sdtr_done); |
976 | ADW_READ_WORD_LRAM(iot, ioh, ADW_MC_DEVICE_HSHK_CFG_TABLE + |
977 | (2 * tid), sdtr); |
978 | sdtr &= ~0x8000; |
979 | if((sdtr & 0x1F) != 0) { |
980 | if((sdtr & 0x1F00) == 0x1100){ |
981 | printf("80.0 MHz" ); |
982 | } else if((sdtr & 0x1F00) == 0x1000){ |
983 | printf("40.0 MHz" ); |
984 | } else { |
985 | /* <= 20.0 MHz */ |
986 | period = (((sdtr >> 8) * 25) + 50)/4; |
987 | if(period == 0) { |
988 | /* Should never happen. */ |
989 | printf("? MHz" ); |
990 | } else { |
991 | printf("%d.%d MHz" , 250/period, |
992 | ADW_TENTHS(250, period)); |
993 | } |
994 | } |
995 | printf(" synchronous transfers\n" ); |
996 | } else { |
997 | printf("asynchronous transfers\n" ); |
998 | } |
999 | if((sdtr_done & ADW_TID_TO_TIDMASK(tid)) == 0) |
1000 | sdtr_reneg = 1; |
1001 | } else { |
1002 | printf("synchronous transfers disabled\n" ); |
1003 | } |
1004 | |
1005 | if(wdtr_reneg || sdtr_reneg) { |
1006 | printf("%s: target %d %s" , device_xname(sc->sc_dev), tid, |
1007 | (wdtr_reneg)? ((sdtr_reneg)? "wide/sync" : "wide" ) : |
1008 | ((sdtr_reneg)? "sync" : "" ) ); |
1009 | printf(" renegotiation pending before next command.\n" ); |
1010 | } |
1011 | } |
1012 | |
1013 | |
1014 | /******************************************************************************/ |
1015 | /* WIDE boards Interrupt callbacks */ |
1016 | /******************************************************************************/ |
1017 | |
1018 | |
1019 | /* |
1020 | * adw_isr_callback() - Second Level Interrupt Handler called by AdwISR() |
1021 | * |
1022 | * Interrupt callback function for the Wide SCSI Adv Library. |
1023 | * |
1024 | * Notice: |
1025 | * Interrupts are disabled by the caller (AdwISR() function), and will be |
1026 | * enabled at the end of the caller. |
1027 | */ |
1028 | static void |
1029 | adw_isr_callback(ADW_SOFTC *sc, ADW_SCSI_REQ_Q *scsiq) |
1030 | { |
1031 | bus_dma_tag_t dmat = sc->sc_dmat; |
1032 | ADW_CCB *ccb; |
1033 | struct scsipi_xfer *xs; |
1034 | struct scsi_sense_data *s1, *s2; |
1035 | |
1036 | |
1037 | ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr); |
1038 | |
1039 | callout_stop(&ccb->xs->xs_callout); |
1040 | |
1041 | xs = ccb->xs; |
1042 | |
1043 | /* |
1044 | * If we were a data transfer, unload the map that described |
1045 | * the data buffer. |
1046 | */ |
1047 | if (xs->datalen) { |
1048 | bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, |
1049 | ccb->dmamap_xfer->dm_mapsize, |
1050 | (xs->xs_control & XS_CTL_DATA_IN) ? |
1051 | BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
1052 | bus_dmamap_unload(dmat, ccb->dmamap_xfer); |
1053 | } |
1054 | |
1055 | if ((ccb->flags & CCB_ALLOC) == 0) { |
1056 | aprint_error_dev(sc->sc_dev, "exiting ccb not allocated!\n" ); |
1057 | Debugger(); |
1058 | return; |
1059 | } |
1060 | |
1061 | /* |
1062 | * 'done_status' contains the command's ending status. |
1063 | * 'host_status' contains the host adapter status. |
1064 | * 'scsi_status' contains the scsi peripheral status. |
1065 | */ |
1066 | if ((scsiq->host_status == QHSTA_NO_ERROR) && |
1067 | ((scsiq->done_status == QD_NO_ERROR) || |
1068 | (scsiq->done_status == QD_WITH_ERROR))) { |
1069 | switch (scsiq->scsi_status) { |
1070 | case SCSI_STATUS_GOOD: |
1071 | if ((scsiq->cdb[0] == INQUIRY) && |
1072 | (scsiq->target_lun == 0)) { |
1073 | adw_print_info(sc, scsiq->target_id); |
1074 | } |
1075 | xs->error = XS_NOERROR; |
1076 | xs->resid = le32toh(scsiq->data_cnt); |
1077 | sc->sc_freeze_dev[scsiq->target_id] = 0; |
1078 | break; |
1079 | |
1080 | case SCSI_STATUS_CHECK_CONDITION: |
1081 | case SCSI_STATUS_CMD_TERMINATED: |
1082 | s1 = &ccb->scsi_sense; |
1083 | s2 = &xs->sense.scsi_sense; |
1084 | *s2 = *s1; |
1085 | xs->error = XS_SENSE; |
1086 | sc->sc_freeze_dev[scsiq->target_id] = 1; |
1087 | break; |
1088 | |
1089 | default: |
1090 | xs->error = XS_BUSY; |
1091 | sc->sc_freeze_dev[scsiq->target_id] = 1; |
1092 | break; |
1093 | } |
1094 | } else if (scsiq->done_status == QD_ABORTED_BY_HOST) { |
1095 | xs->error = XS_DRIVER_STUFFUP; |
1096 | } else { |
1097 | switch (scsiq->host_status) { |
1098 | case QHSTA_M_SEL_TIMEOUT: |
1099 | xs->error = XS_SELTIMEOUT; |
1100 | break; |
1101 | |
1102 | case QHSTA_M_SXFR_OFF_UFLW: |
1103 | case QHSTA_M_SXFR_OFF_OFLW: |
1104 | case QHSTA_M_DATA_OVER_RUN: |
1105 | aprint_error_dev(sc->sc_dev, |
1106 | "Overrun/Overflow/Underflow condition\n" ); |
1107 | xs->error = XS_DRIVER_STUFFUP; |
1108 | break; |
1109 | |
1110 | case QHSTA_M_SXFR_DESELECTED: |
1111 | case QHSTA_M_UNEXPECTED_BUS_FREE: |
1112 | aprint_error_dev(sc->sc_dev, "Unexpected BUS free\n" ); |
1113 | xs->error = XS_DRIVER_STUFFUP; |
1114 | break; |
1115 | |
1116 | case QHSTA_M_SCSI_BUS_RESET: |
1117 | case QHSTA_M_SCSI_BUS_RESET_UNSOL: |
1118 | aprint_error_dev(sc->sc_dev, "BUS Reset\n" ); |
1119 | xs->error = XS_DRIVER_STUFFUP; |
1120 | break; |
1121 | |
1122 | case QHSTA_M_BUS_DEVICE_RESET: |
1123 | aprint_error_dev(sc->sc_dev, "Device Reset\n" ); |
1124 | xs->error = XS_DRIVER_STUFFUP; |
1125 | break; |
1126 | |
1127 | case QHSTA_M_QUEUE_ABORTED: |
1128 | aprint_error_dev(sc->sc_dev, "Queue Aborted\n" ); |
1129 | xs->error = XS_DRIVER_STUFFUP; |
1130 | break; |
1131 | |
1132 | case QHSTA_M_SXFR_SDMA_ERR: |
1133 | case QHSTA_M_SXFR_SXFR_PERR: |
1134 | case QHSTA_M_RDMA_PERR: |
1135 | /* |
1136 | * DMA Error. This should *NEVER* happen! |
1137 | * |
1138 | * Lets try resetting the bus and reinitialize |
1139 | * the host adapter. |
1140 | */ |
1141 | aprint_error_dev(sc->sc_dev, |
1142 | "DMA Error. Reseting bus\n" ); |
1143 | TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain); |
1144 | adw_reset_bus(sc); |
1145 | xs->error = XS_BUSY; |
1146 | goto done; |
1147 | |
1148 | case QHSTA_M_WTM_TIMEOUT: |
1149 | case QHSTA_M_SXFR_WD_TMO: |
1150 | /* The SCSI bus hung in a phase */ |
1151 | printf("%s: Watch Dog timer expired. Reseting bus\n" , |
1152 | device_xname(sc->sc_dev)); |
1153 | TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain); |
1154 | adw_reset_bus(sc); |
1155 | xs->error = XS_BUSY; |
1156 | goto done; |
1157 | |
1158 | case QHSTA_M_SXFR_XFR_PH_ERR: |
1159 | aprint_error_dev(sc->sc_dev, "Transfer Error\n" ); |
1160 | xs->error = XS_DRIVER_STUFFUP; |
1161 | break; |
1162 | |
1163 | case QHSTA_M_BAD_CMPL_STATUS_IN: |
1164 | /* No command complete after a status message */ |
1165 | printf("%s: Bad Completion Status\n" , |
1166 | device_xname(sc->sc_dev)); |
1167 | xs->error = XS_DRIVER_STUFFUP; |
1168 | break; |
1169 | |
1170 | case QHSTA_M_AUTO_REQ_SENSE_FAIL: |
1171 | aprint_error_dev(sc->sc_dev, "Auto Sense Failed\n" ); |
1172 | xs->error = XS_DRIVER_STUFFUP; |
1173 | break; |
1174 | |
1175 | case QHSTA_M_INVALID_DEVICE: |
1176 | aprint_error_dev(sc->sc_dev, "Invalid Device\n" ); |
1177 | xs->error = XS_DRIVER_STUFFUP; |
1178 | break; |
1179 | |
1180 | case QHSTA_M_NO_AUTO_REQ_SENSE: |
1181 | /* |
1182 | * User didn't request sense, but we got a |
1183 | * check condition. |
1184 | */ |
1185 | aprint_error_dev(sc->sc_dev, |
1186 | "Unexpected Check Condition\n" ); |
1187 | xs->error = XS_DRIVER_STUFFUP; |
1188 | break; |
1189 | |
1190 | case QHSTA_M_SXFR_UNKNOWN_ERROR: |
1191 | aprint_error_dev(sc->sc_dev, "Unknown Error\n" ); |
1192 | xs->error = XS_DRIVER_STUFFUP; |
1193 | break; |
1194 | |
1195 | default: |
1196 | panic("%s: Unhandled Host Status Error %x" , |
1197 | device_xname(sc->sc_dev), scsiq->host_status); |
1198 | } |
1199 | } |
1200 | |
1201 | TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain); |
1202 | done: adw_free_ccb(sc, ccb); |
1203 | scsipi_done(xs); |
1204 | } |
1205 | |
1206 | |
1207 | /* |
1208 | * adw_async_callback() - Adv Library asynchronous event callback function. |
1209 | */ |
1210 | static void |
1211 | adw_async_callback(ADW_SOFTC *sc, u_int8_t code) |
1212 | { |
1213 | switch (code) { |
1214 | case ADV_ASYNC_SCSI_BUS_RESET_DET: |
1215 | /* The firmware detected a SCSI Bus reset. */ |
1216 | printf("%s: SCSI Bus reset detected\n" , |
1217 | device_xname(sc->sc_dev)); |
1218 | break; |
1219 | |
1220 | case ADV_ASYNC_RDMA_FAILURE: |
1221 | /* |
1222 | * Handle RDMA failure by resetting the SCSI Bus and |
1223 | * possibly the chip if it is unresponsive. |
1224 | */ |
1225 | printf("%s: RDMA failure. Resetting the SCSI Bus and" |
1226 | " the adapter\n" , device_xname(sc->sc_dev)); |
1227 | AdwResetSCSIBus(sc); |
1228 | break; |
1229 | |
1230 | case ADV_HOST_SCSI_BUS_RESET: |
1231 | /* Host generated SCSI bus reset occurred. */ |
1232 | printf("%s: Host generated SCSI bus reset occurred\n" , |
1233 | device_xname(sc->sc_dev)); |
1234 | break; |
1235 | |
1236 | case ADV_ASYNC_CARRIER_READY_FAILURE: |
1237 | /* Carrier Ready failure. */ |
1238 | printf("%s: Carrier Ready failure!\n" , |
1239 | device_xname(sc->sc_dev)); |
1240 | break; |
1241 | |
1242 | default: |
1243 | break; |
1244 | } |
1245 | } |
1246 | |