cleanup some odd uses of curproc. Remove PHOLD/PRELE around physical I/O
[dragonfly.git] / sys / bus / cam / cam_periph.c
1 /*
2  * Common functions for CAM "type" (peripheral) drivers.
3  *
4  * Copyright (c) 1997, 1998 Justin T. Gibbs.
5  * Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions, and the following disclaimer,
13  *    without modification, immediately at the beginning of the file.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/cam/cam_periph.c,v 1.24.2.3 2003/01/25 19:04:40 dillon Exp $
30  * $DragonFly: src/sys/bus/cam/cam_periph.c,v 1.3 2003/06/26 20:27:44 dillon Exp $
31  */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/types.h>
36 #include <sys/malloc.h>
37 #include <sys/linker_set.h>
38 #include <sys/buf.h>
39 #include <sys/proc.h>
40 #include <sys/devicestat.h>
41 #include <sys/bus.h>
42 #include <vm/vm.h>
43 #include <vm/vm_extern.h>
44
45 #include <cam/cam.h>
46 #include <cam/cam_ccb.h>
47 #include <cam/cam_xpt_periph.h>
48 #include <cam/cam_periph.h>
49 #include <cam/cam_debug.h>
50
51 #include <cam/scsi/scsi_all.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55
56 static  u_int           camperiphnextunit(struct periph_driver *p_drv,
57                                           u_int newunit, int wired,
58                                           path_id_t pathid, target_id_t target,
59                                           lun_id_t lun);
60 static  u_int           camperiphunit(struct periph_driver *p_drv,
61                                       path_id_t pathid, target_id_t target,
62                                       lun_id_t lun); 
63 static  void            camperiphdone(struct cam_periph *periph, 
64                                         union ccb *done_ccb);
65 static  void            camperiphfree(struct cam_periph *periph);
66
67 cam_status
68 cam_periph_alloc(periph_ctor_t *periph_ctor,
69                  periph_oninv_t *periph_oninvalidate,
70                  periph_dtor_t *periph_dtor, periph_start_t *periph_start,
71                  char *name, cam_periph_type type, struct cam_path *path,
72                  ac_callback_t *ac_callback, ac_code code, void *arg)
73 {
74         struct          periph_driver **p_drv;
75         struct          cam_periph *periph;
76         struct          cam_periph *cur_periph;
77         path_id_t       path_id;
78         target_id_t     target_id;
79         lun_id_t        lun_id;
80         cam_status      status;
81         u_int           init_level;
82         int s;
83
84         init_level = 0;
85         /*
86          * Handle Hot-Plug scenarios.  If there is already a peripheral
87          * of our type assigned to this path, we are likely waiting for
88          * final close on an old, invalidated, peripheral.  If this is
89          * the case, queue up a deferred call to the peripheral's async
90          * handler.  If it looks like a mistaken re-alloation, complain.
91          */
92         if ((periph = cam_periph_find(path, name)) != NULL) {
93
94                 if ((periph->flags & CAM_PERIPH_INVALID) != 0
95                  && (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) == 0) {
96                         periph->flags |= CAM_PERIPH_NEW_DEV_FOUND;
97                         periph->deferred_callback = ac_callback;
98                         periph->deferred_ac = code;
99                         return (CAM_REQ_INPROG);
100                 } else {
101                         printf("cam_periph_alloc: attempt to re-allocate "
102                                "valid device %s%d rejected\n",
103                                periph->periph_name, periph->unit_number);
104                 }
105                 return (CAM_REQ_INVALID);
106         }
107         
108         periph = (struct cam_periph *)malloc(sizeof(*periph), M_DEVBUF,
109                                              M_NOWAIT);
110
111         if (periph == NULL)
112                 return (CAM_RESRC_UNAVAIL);
113         
114         init_level++;
115
116         for (p_drv = (struct periph_driver **)periphdriver_set.ls_items;
117              *p_drv != NULL; p_drv++) {
118                 if (strcmp((*p_drv)->driver_name, name) == 0)
119                         break;
120         }
121         
122         path_id = xpt_path_path_id(path);
123         target_id = xpt_path_target_id(path);
124         lun_id = xpt_path_lun_id(path);
125         bzero(periph, sizeof(*periph));
126         cam_init_pinfo(&periph->pinfo);
127         periph->periph_start = periph_start;
128         periph->periph_dtor = periph_dtor;
129         periph->periph_oninval = periph_oninvalidate;
130         periph->type = type;
131         periph->periph_name = name;
132         periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
133         periph->immediate_priority = CAM_PRIORITY_NONE;
134         periph->refcount = 0;
135         SLIST_INIT(&periph->ccb_list);
136         status = xpt_create_path(&path, periph, path_id, target_id, lun_id);
137         if (status != CAM_REQ_CMP)
138                 goto failure;
139
140         periph->path = path;
141         init_level++;
142
143         status = xpt_add_periph(periph);
144
145         if (status != CAM_REQ_CMP)
146                 goto failure;
147
148         s = splsoftcam();
149         cur_periph = TAILQ_FIRST(&(*p_drv)->units);
150         while (cur_periph != NULL
151             && cur_periph->unit_number < periph->unit_number)
152                 cur_periph = TAILQ_NEXT(cur_periph, unit_links);
153
154         if (cur_periph != NULL)
155                 TAILQ_INSERT_BEFORE(cur_periph, periph, unit_links);
156         else {
157                 TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links);
158                 (*p_drv)->generation++;
159         }
160
161         splx(s);
162
163         init_level++;
164
165         status = periph_ctor(periph, arg);
166
167         if (status == CAM_REQ_CMP)
168                 init_level++;
169
170 failure:
171         switch (init_level) {
172         case 4:
173                 /* Initialized successfully */
174                 break;
175         case 3:
176                 s = splsoftcam();
177                 TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
178                 splx(s);
179                 xpt_remove_periph(periph);
180         case 2:
181                 xpt_free_path(periph->path);
182         case 1:
183                 free(periph, M_DEVBUF);
184         case 0:
185                 /* No cleanup to perform. */
186                 break;
187         default:
188                 panic("cam_periph_alloc: Unkown init level");
189         }
190         return(status);
191 }
192
193 /*
194  * Find a peripheral structure with the specified path, target, lun, 
195  * and (optionally) type.  If the name is NULL, this function will return
196  * the first peripheral driver that matches the specified path.
197  */
198 struct cam_periph *
199 cam_periph_find(struct cam_path *path, char *name)
200 {
201         struct periph_driver **p_drv;
202         struct cam_periph *periph;
203         int s;
204
205         for (p_drv = (struct periph_driver **)periphdriver_set.ls_items;
206              *p_drv != NULL; p_drv++) {
207
208                 if (name != NULL && (strcmp((*p_drv)->driver_name, name) != 0))
209                         continue;
210
211                 s = splsoftcam();
212                 for (periph = TAILQ_FIRST(&(*p_drv)->units); periph != NULL;
213                      periph = TAILQ_NEXT(periph, unit_links)) {
214                         if (xpt_path_comp(periph->path, path) == 0) {
215                                 splx(s);
216                                 return(periph);
217                         }
218                 }
219                 splx(s);
220                 if (name != NULL)
221                         return(NULL);
222         }
223         return(NULL);
224 }
225
226 cam_status
227 cam_periph_acquire(struct cam_periph *periph)
228 {
229         int s;
230
231         if (periph == NULL)
232                 return(CAM_REQ_CMP_ERR);
233
234         s = splsoftcam();
235         periph->refcount++;
236         splx(s);
237
238         return(CAM_REQ_CMP);
239 }
240
241 void
242 cam_periph_release(struct cam_periph *periph)
243 {
244         int s;
245
246         if (periph == NULL)
247                 return;
248
249         s = splsoftcam();
250         if ((--periph->refcount == 0)
251          && (periph->flags & CAM_PERIPH_INVALID)) {
252                 camperiphfree(periph);
253         }
254         splx(s);
255
256 }
257
258 /*
259  * Look for the next unit number that is not currently in use for this
260  * peripheral type starting at "newunit".  Also exclude unit numbers that
261  * are reserved by for future "hardwiring" unless we already know that this
262  * is a potential wired device.  Only assume that the device is "wired" the
263  * first time through the loop since after that we'll be looking at unit
264  * numbers that did not match a wiring entry.
265  */
266 static u_int
267 camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
268                   path_id_t pathid, target_id_t target, lun_id_t lun)
269 {
270         struct  cam_periph *periph;
271         char    *periph_name, *strval;
272         int     s;
273         int     i, val, dunit;
274         const char *dname;
275
276         s = splsoftcam();
277         periph_name = p_drv->driver_name;
278         for (;;newunit++) {
279
280                 for (periph = TAILQ_FIRST(&p_drv->units);
281                      periph != NULL && periph->unit_number != newunit;
282                      periph = TAILQ_NEXT(periph, unit_links))
283                         ;
284
285                 if (periph != NULL && periph->unit_number == newunit) {
286                         if (wired != 0) {
287                                 xpt_print_path(periph->path);
288                                 printf("Duplicate Wired Device entry!\n");
289                                 xpt_print_path(periph->path);
290                                 printf("Second device (%s device at scbus%d "
291                                        "target %d lun %d) will not be wired\n",
292                                        periph_name, pathid, target, lun);
293                                 wired = 0;
294                         }
295                         continue;
296                 }
297                 if (wired)
298                         break;
299
300                 /*
301                  * Don't match entries like "da 4" as a wired down
302                  * device, but do match entries like "da 4 target 5"
303                  * or even "da 4 scbus 1". 
304                  */
305                 i = -1;
306                 while ((i = resource_locate(i, periph_name)) != -1) {
307                         dname = resource_query_name(i);
308                         dunit = resource_query_unit(i);
309                         /* if no "target" and no specific scbus, skip */
310                         if (resource_int_value(dname, dunit, "target", &val) &&
311                             (resource_string_value(dname, dunit, "at",&strval)||
312                              strcmp(strval, "scbus") == 0))
313                                 continue;
314                         if (newunit == dunit)
315                                 break;
316                 }
317                 if (i == -1)
318                         break;
319         }
320         splx(s);
321         return (newunit);
322 }
323
324 static u_int
325 camperiphunit(struct periph_driver *p_drv, path_id_t pathid,
326               target_id_t target, lun_id_t lun)
327 {
328         u_int   unit;
329         int     hit, i, val, dunit;
330         const char *dname;
331         char    pathbuf[32], *strval, *periph_name;
332
333         unit = 0;
334
335         periph_name = p_drv->driver_name;
336         snprintf(pathbuf, sizeof(pathbuf), "scbus%d", pathid);
337         i = -1;
338         for (hit = 0; (i = resource_locate(i, periph_name)) != -1; hit = 0) {
339                 dname = resource_query_name(i);
340                 dunit = resource_query_unit(i);
341                 if (resource_string_value(dname, dunit, "at", &strval) == 0) {
342                         if (strcmp(strval, pathbuf) != 0)
343                                 continue;
344                         hit++;
345                 }
346                 if (resource_int_value(dname, dunit, "target", &val) == 0) {
347                         if (val != target)
348                                 continue;
349                         hit++;
350                 }
351                 if (resource_int_value(dname, dunit, "lun", &val) == 0) {
352                         if (val != lun)
353                                 continue;
354                         hit++;
355                 }
356                 if (hit != 0) {
357                         unit = dunit;
358                         break;
359                 }
360         }
361
362         /*
363          * Either start from 0 looking for the next unit or from
364          * the unit number given in the resource config.  This way,
365          * if we have wildcard matches, we don't return the same
366          * unit number twice.
367          */
368         unit = camperiphnextunit(p_drv, unit, /*wired*/hit, pathid,
369                                  target, lun);
370
371         return (unit);
372 }
373
374 void
375 cam_periph_invalidate(struct cam_periph *periph)
376 {
377         int s;
378
379         s = splsoftcam();
380         /*
381          * We only call this routine the first time a peripheral is
382          * invalidated.  The oninvalidate() routine is always called at
383          * splsoftcam().
384          */
385         if (((periph->flags & CAM_PERIPH_INVALID) == 0)
386          && (periph->periph_oninval != NULL))
387                 periph->periph_oninval(periph);
388
389         periph->flags |= CAM_PERIPH_INVALID;
390         periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
391
392         if (periph->refcount == 0)
393                 camperiphfree(periph);
394         else if (periph->refcount < 0)
395                 printf("cam_invalidate_periph: refcount < 0!!\n");
396         splx(s);
397 }
398
399 static void
400 camperiphfree(struct cam_periph *periph)
401 {
402         int s;
403         struct periph_driver **p_drv;
404
405         for (p_drv = (struct periph_driver **)periphdriver_set.ls_items;
406              *p_drv != NULL; p_drv++) {
407                 if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0)
408                         break;
409         }
410         
411         if (periph->periph_dtor != NULL)
412                 periph->periph_dtor(periph);
413         
414         s = splsoftcam();
415         TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
416         (*p_drv)->generation++;
417         splx(s);
418
419         xpt_remove_periph(periph);
420
421         if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) {
422                 union ccb ccb;
423                 void *arg;
424
425                 switch (periph->deferred_ac) {
426                 case AC_FOUND_DEVICE:
427                         ccb.ccb_h.func_code = XPT_GDEV_TYPE;
428                         xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/ 1);
429                         xpt_action(&ccb);
430                         arg = &ccb;
431                         break;
432                 case AC_PATH_REGISTERED:
433                         ccb.ccb_h.func_code = XPT_PATH_INQ;
434                         xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/ 1);
435                         xpt_action(&ccb);
436                         arg = &ccb;
437                         break;
438                 default:
439                         arg = NULL;
440                         break;
441                 }
442                 periph->deferred_callback(NULL, periph->deferred_ac,
443                                           periph->path, arg);
444         }
445         xpt_free_path(periph->path);
446         free(periph, M_DEVBUF);
447 }
448
449 /*
450  * Wait interruptibly for an exclusive lock.
451  */
452 int
453 cam_periph_lock(struct cam_periph *periph, int priority)
454 {
455         int error;
456
457         while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
458                 periph->flags |= CAM_PERIPH_LOCK_WANTED;
459                 if ((error = tsleep(periph, priority, "caplck", 0)) != 0)
460                         return error;
461         }
462
463         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
464                 return(ENXIO);
465
466         periph->flags |= CAM_PERIPH_LOCKED;
467         return 0;
468 }
469
470 /*
471  * Unlock and wake up any waiters.
472  */
473 void
474 cam_periph_unlock(struct cam_periph *periph)
475 {
476         periph->flags &= ~CAM_PERIPH_LOCKED;
477         if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) {
478                 periph->flags &= ~CAM_PERIPH_LOCK_WANTED;
479                 wakeup(periph);
480         }
481
482         cam_periph_release(periph);
483 }
484
485 /*
486  * Map user virtual pointers into kernel virtual address space, so we can
487  * access the memory.  This won't work on physical pointers, for now it's
488  * up to the caller to check for that.  (XXX KDM -- should we do that here
489  * instead?)  This also only works for up to MAXPHYS memory.  Since we use
490  * buffers to map stuff in and out, we're limited to the buffer size.
491  */
492 int
493 cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
494 {
495         int numbufs, i, j;
496         int flags[CAM_PERIPH_MAXMAPS];
497         u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
498         u_int32_t lengths[CAM_PERIPH_MAXMAPS];
499         u_int32_t dirs[CAM_PERIPH_MAXMAPS];
500
501         switch(ccb->ccb_h.func_code) {
502         case XPT_DEV_MATCH:
503                 if (ccb->cdm.match_buf_len == 0) {
504                         printf("cam_periph_mapmem: invalid match buffer "
505                                "length 0\n");
506                         return(EINVAL);
507                 }
508                 if (ccb->cdm.pattern_buf_len > 0) {
509                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
510                         lengths[0] = ccb->cdm.pattern_buf_len;
511                         dirs[0] = CAM_DIR_OUT;
512                         data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
513                         lengths[1] = ccb->cdm.match_buf_len;
514                         dirs[1] = CAM_DIR_IN;
515                         numbufs = 2;
516                 } else {
517                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
518                         lengths[0] = ccb->cdm.match_buf_len;
519                         dirs[0] = CAM_DIR_IN;
520                         numbufs = 1;
521                 }
522                 break;
523         case XPT_SCSI_IO:
524         case XPT_CONT_TARGET_IO:
525                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
526                         return(0);
527
528                 data_ptrs[0] = &ccb->csio.data_ptr;
529                 lengths[0] = ccb->csio.dxfer_len;
530                 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
531                 numbufs = 1;
532                 break;
533         default:
534                 return(EINVAL);
535                 break; /* NOTREACHED */
536         }
537
538         /*
539          * Check the transfer length and permissions first, so we don't
540          * have to unmap any previously mapped buffers.
541          */
542         for (i = 0; i < numbufs; i++) {
543
544                 flags[i] = 0;
545
546                 /*
547                  * The userland data pointer passed in may not be page
548                  * aligned.  vmapbuf() truncates the address to a page
549                  * boundary, so if the address isn't page aligned, we'll
550                  * need enough space for the given transfer length, plus
551                  * whatever extra space is necessary to make it to the page
552                  * boundary.
553                  */
554                 if ((lengths[i] +
555                     (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > DFLTPHYS){
556                         printf("cam_periph_mapmem: attempt to map %lu bytes, "
557                                "which is greater than DFLTPHYS(%d)\n",
558                                (long)(lengths[i] +
559                                (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)),
560                                DFLTPHYS);
561                         return(E2BIG);
562                 }
563
564                 if (dirs[i] & CAM_DIR_OUT) {
565                         flags[i] = B_WRITE;
566                         if (!useracc(*data_ptrs[i], lengths[i], 
567                                      VM_PROT_READ)) {
568                                 printf("cam_periph_mapmem: error, "
569                                         "address %p, length %lu isn't "
570                                         "user accessible for READ\n",
571                                         (void *)*data_ptrs[i],
572                                         (u_long)lengths[i]);
573                                 return(EACCES);
574                         }
575                 }
576
577                 /*
578                  * XXX this check is really bogus, since B_WRITE currently
579                  * is all 0's, and so it is "set" all the time.
580                  */
581                 if (dirs[i] & CAM_DIR_IN) {
582                         flags[i] |= B_READ;
583                         if (!useracc(*data_ptrs[i], lengths[i], 
584                                      VM_PROT_WRITE)) {
585                                 printf("cam_periph_mapmem: error, "
586                                         "address %p, length %lu isn't "
587                                         "user accessible for WRITE\n",
588                                         (void *)*data_ptrs[i],
589                                         (u_long)lengths[i]);
590
591                                 return(EACCES);
592                         }
593                 }
594
595         }
596
597         for (i = 0; i < numbufs; i++) {
598                 /*
599                  * Get the buffer.
600                  */
601                 mapinfo->bp[i] = getpbuf(NULL);
602
603                 /* save the buffer's data address */
604                 mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data;
605
606                 /* put our pointer in the data slot */
607                 mapinfo->bp[i]->b_data = *data_ptrs[i];
608
609                 /* set the transfer length, we know it's < DFLTPHYS */
610                 mapinfo->bp[i]->b_bufsize = lengths[i];
611
612                 /* set the flags */
613                 mapinfo->bp[i]->b_flags = flags[i] | B_PHYS;
614
615                 /* map the buffer into kernel memory */
616                 if (vmapbuf(mapinfo->bp[i]) < 0) {
617                         printf("cam_periph_mapmem: error, "
618                                 "address %p, length %lu isn't "
619                                 "user accessible any more\n",
620                                 (void *)*data_ptrs[i],
621                                 (u_long)lengths[i]);
622                         for (j = 0; j < i; ++j) {
623                                 *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr;
624                                 mapinfo->bp[j]->b_flags &= ~B_PHYS;
625                                 relpbuf(mapinfo->bp[j], NULL);
626                         }
627                         return(EACCES);
628                 }
629
630                 /* set our pointer to the new mapped area */
631                 *data_ptrs[i] = mapinfo->bp[i]->b_data;
632
633                 mapinfo->num_bufs_used++;
634         }
635
636         return(0);
637 }
638
639 /*
640  * Unmap memory segments mapped into kernel virtual address space by
641  * cam_periph_mapmem().
642  */
643 void
644 cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
645 {
646         int numbufs, i;
647         u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
648
649         if (mapinfo->num_bufs_used <= 0) {
650                 /* allow ourselves to be swapped once again */
651                 return;
652         }
653
654         switch (ccb->ccb_h.func_code) {
655         case XPT_DEV_MATCH:
656                 numbufs = min(mapinfo->num_bufs_used, 2);
657
658                 if (numbufs == 1) {
659                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
660                 } else {
661                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
662                         data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
663                 }
664                 break;
665         case XPT_SCSI_IO:
666         case XPT_CONT_TARGET_IO:
667                 data_ptrs[0] = &ccb->csio.data_ptr;
668                 numbufs = min(mapinfo->num_bufs_used, 1);
669                 break;
670         default:
671                 /* allow ourselves to be swapped once again */
672                 return;
673                 break; /* NOTREACHED */ 
674         }
675
676         for (i = 0; i < numbufs; i++) {
677                 /* Set the user's pointer back to the original value */
678                 *data_ptrs[i] = mapinfo->bp[i]->b_saveaddr;
679
680                 /* unmap the buffer */
681                 vunmapbuf(mapinfo->bp[i]);
682
683                 /* clear the flags we set above */
684                 mapinfo->bp[i]->b_flags &= ~B_PHYS;
685
686                 /* release the buffer */
687                 relpbuf(mapinfo->bp[i], NULL);
688         }
689
690         /* allow ourselves to be swapped once again */
691 }
692
693 union ccb *
694 cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
695 {
696         struct ccb_hdr *ccb_h;
697         int s;
698
699         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n"));
700
701         s = splsoftcam();
702         
703         while (periph->ccb_list.slh_first == NULL) {
704                 if (periph->immediate_priority > priority)
705                         periph->immediate_priority = priority;
706                 xpt_schedule(periph, priority);
707                 if ((periph->ccb_list.slh_first != NULL)
708                  && (periph->ccb_list.slh_first->pinfo.priority == priority))
709                         break;
710                 tsleep(&periph->ccb_list, PRIBIO, "cgticb", 0);
711         }
712
713         ccb_h = periph->ccb_list.slh_first;
714         SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle);
715         splx(s);
716         return ((union ccb *)ccb_h);
717 }
718
719 void
720 cam_periph_ccbwait(union ccb *ccb)
721 {
722         int s;
723
724         s = splsoftcam();
725         if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
726          || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
727                 tsleep(&ccb->ccb_h.cbfcnp, PRIBIO, "cbwait", 0);
728
729         splx(s);
730 }
731
732 int
733 cam_periph_ioctl(struct cam_periph *periph, int cmd, caddr_t addr,
734                  int (*error_routine)(union ccb *ccb, 
735                                       cam_flags camflags,
736                                       u_int32_t sense_flags))
737 {
738         union ccb            *ccb;
739         int                  error;
740         int                  found;
741
742         error = found = 0;
743
744         switch(cmd){
745         case CAMGETPASSTHRU:
746                 ccb = cam_periph_getccb(periph, /* priority */ 1);
747                 xpt_setup_ccb(&ccb->ccb_h,
748                               ccb->ccb_h.path,
749                               /*priority*/1);
750                 ccb->ccb_h.func_code = XPT_GDEVLIST;
751
752                 /*
753                  * Basically, the point of this is that we go through
754                  * getting the list of devices, until we find a passthrough
755                  * device.  In the current version of the CAM code, the
756                  * only way to determine what type of device we're dealing
757                  * with is by its name.
758                  */
759                 while (found == 0) {
760                         ccb->cgdl.index = 0;
761                         ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
762                         while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
763
764                                 /* we want the next device in the list */
765                                 xpt_action(ccb);
766                                 if (strncmp(ccb->cgdl.periph_name, 
767                                     "pass", 4) == 0){
768                                         found = 1;
769                                         break;
770                                 }
771                         }
772                         if ((ccb->cgdl.status == CAM_GDEVLIST_LAST_DEVICE) &&
773                             (found == 0)) {
774                                 ccb->cgdl.periph_name[0] = '\0';
775                                 ccb->cgdl.unit_number = 0;
776                                 break;
777                         }
778                 }
779
780                 /* copy the result back out */  
781                 bcopy(ccb, addr, sizeof(union ccb));
782
783                 /* and release the ccb */
784                 xpt_release_ccb(ccb);
785
786                 break;
787         default:
788                 error = ENOTTY;
789                 break;
790         }
791         return(error);
792 }
793
794 int
795 cam_periph_runccb(union ccb *ccb,
796                   int (*error_routine)(union ccb *ccb,
797                                        cam_flags camflags,
798                                        u_int32_t sense_flags),
799                   cam_flags camflags, u_int32_t sense_flags,
800                   struct devstat *ds)
801 {
802         int error;
803  
804         error = 0;
805         
806         /*
807          * If the user has supplied a stats structure, and if we understand
808          * this particular type of ccb, record the transaction start.
809          */
810         if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO))
811                 devstat_start_transaction(ds);
812
813         xpt_action(ccb);
814  
815         do {
816                 cam_periph_ccbwait(ccb);
817                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
818                         error = 0;
819                 else if (error_routine != NULL)
820                         error = (*error_routine)(ccb, camflags, sense_flags);
821                 else
822                         error = 0;
823
824         } while (error == ERESTART);
825           
826         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 
827                 cam_release_devq(ccb->ccb_h.path,
828                                  /* relsim_flags */0,
829                                  /* openings */0,
830                                  /* timeout */0,
831                                  /* getcount_only */ FALSE);
832
833         if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO))
834                 devstat_end_transaction(ds,
835                                         ccb->csio.dxfer_len,
836                                         ccb->csio.tag_action & 0xf,
837                                         ((ccb->ccb_h.flags & CAM_DIR_MASK) ==
838                                         CAM_DIR_NONE) ?  DEVSTAT_NO_DATA : 
839                                         (ccb->ccb_h.flags & CAM_DIR_OUT) ?
840                                         DEVSTAT_WRITE : 
841                                         DEVSTAT_READ);
842
843         return(error);
844 }
845
846 void
847 cam_freeze_devq(struct cam_path *path)
848 {
849         struct ccb_hdr ccb_h;
850
851         xpt_setup_ccb(&ccb_h, path, /*priority*/1);
852         ccb_h.func_code = XPT_NOOP;
853         ccb_h.flags = CAM_DEV_QFREEZE;
854         xpt_action((union ccb *)&ccb_h);
855 }
856
857 u_int32_t
858 cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
859                  u_int32_t openings, u_int32_t timeout,
860                  int getcount_only)
861 {
862         struct ccb_relsim crs;
863
864         xpt_setup_ccb(&crs.ccb_h, path,
865                       /*priority*/1);
866         crs.ccb_h.func_code = XPT_REL_SIMQ;
867         crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0;
868         crs.release_flags = relsim_flags;
869         crs.openings = openings;
870         crs.release_timeout = timeout;
871         xpt_action((union ccb *)&crs);
872         return (crs.qfrozen_cnt);
873 }
874
875 #define saved_ccb_ptr ppriv_ptr0
876 static void
877 camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
878 {
879         cam_status      status;
880         int             frozen;
881         int             sense;
882         struct scsi_start_stop_unit *scsi_cmd;
883         u_int32_t       relsim_flags, timeout;
884         u_int32_t       qfrozen_cnt;
885
886         status = done_ccb->ccb_h.status;
887         frozen = (status & CAM_DEV_QFRZN) != 0;
888         sense  = (status & CAM_AUTOSNS_VALID) != 0;
889         status &= CAM_STATUS_MASK;
890
891         timeout = 0;
892         relsim_flags = 0;
893
894         /* 
895          * Unfreeze the queue once if it is already frozen..
896          */
897         if (frozen != 0) {
898                 qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path,
899                                               /*relsim_flags*/0,
900                                               /*openings*/0,
901                                               /*timeout*/0,
902                                               /*getcount_only*/0);
903         }
904
905         switch (status) {
906
907         case CAM_REQ_CMP:
908
909                 /*
910                  * If we have successfully taken a device from the not
911                  * ready to ready state, re-scan the device and re-get the
912                  * inquiry information.  Many devices (mostly disks) don't
913                  * properly report their inquiry information unless they
914                  * are spun up.
915                  */
916                 if (done_ccb->ccb_h.func_code == XPT_SCSI_IO) {
917                         scsi_cmd = (struct scsi_start_stop_unit *)
918                                         &done_ccb->csio.cdb_io.cdb_bytes;
919
920                         if (scsi_cmd->opcode == START_STOP_UNIT)
921                                 xpt_async(AC_INQ_CHANGED,
922                                           done_ccb->ccb_h.path, NULL);
923                 }
924                 bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
925                       sizeof(union ccb));
926
927                 periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
928
929                 xpt_action(done_ccb);
930
931                 break;
932         case CAM_SCSI_STATUS_ERROR:
933                 scsi_cmd = (struct scsi_start_stop_unit *)
934                                 &done_ccb->csio.cdb_io.cdb_bytes;
935                 if (sense != 0) {
936                         struct scsi_sense_data *sense;
937                         int    error_code, sense_key, asc, ascq;        
938
939                         sense = &done_ccb->csio.sense_data;
940                         scsi_extract_sense(sense, &error_code, 
941                                            &sense_key, &asc, &ascq);
942
943                         /*
944                          * If the error is "invalid field in CDB", 
945                          * and the load/eject flag is set, turn the 
946                          * flag off and try again.  This is just in 
947                          * case the drive in question barfs on the 
948                          * load eject flag.  The CAM code should set 
949                          * the load/eject flag by default for 
950                          * removable media.
951                          */
952
953                         /* XXX KDM 
954                          * Should we check to see what the specific
955                          * scsi status is??  Or does it not matter
956                          * since we already know that there was an
957                          * error, and we know what the specific
958                          * error code was, and we know what the
959                          * opcode is..
960                          */
961                         if ((scsi_cmd->opcode == START_STOP_UNIT) &&
962                             ((scsi_cmd->how & SSS_LOEJ) != 0) &&
963                              (asc == 0x24) && (ascq == 0x00) &&
964                              (done_ccb->ccb_h.retry_count > 0)) {
965
966                                 scsi_cmd->how &= ~SSS_LOEJ;
967
968                                 xpt_action(done_ccb);
969
970                         } else if (done_ccb->ccb_h.retry_count > 0) {
971                                 /*
972                                  * In this case, the error recovery
973                                  * command failed, but we've got 
974                                  * some retries left on it.  Give
975                                  * it another try.
976                                  */
977
978                                 /* set the timeout to .5 sec */
979                                 relsim_flags =
980                                         RELSIM_RELEASE_AFTER_TIMEOUT;
981                                 timeout = 500;
982
983                                 xpt_action(done_ccb);
984
985                                 break;
986
987                         } else {
988                                 /* 
989                                  * Copy the original CCB back and
990                                  * send it back to the caller.
991                                  */
992                                 bcopy(done_ccb->ccb_h.saved_ccb_ptr,            
993                                       done_ccb, sizeof(union ccb));
994
995                                 periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
996
997                                 xpt_action(done_ccb);
998                         }
999                 } else {
1000                         /*
1001                          * Eh??  The command failed, but we don't
1002                          * have any sense.  What's up with that?
1003                          * Fire the CCB again to return it to the
1004                          * caller.
1005                          */
1006                         bcopy(done_ccb->ccb_h.saved_ccb_ptr,
1007                               done_ccb, sizeof(union ccb));
1008
1009                         periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
1010
1011                         xpt_action(done_ccb);
1012
1013                 }
1014                 break;
1015         default:
1016                 bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
1017                       sizeof(union ccb));
1018
1019                 periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
1020
1021                 xpt_action(done_ccb);
1022
1023                 break;
1024         }
1025
1026         /* decrement the retry count */
1027         if (done_ccb->ccb_h.retry_count > 0)
1028                 done_ccb->ccb_h.retry_count--;
1029
1030         qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path,
1031                                       /*relsim_flags*/relsim_flags,
1032                                       /*openings*/0,
1033                                       /*timeout*/timeout,
1034                                       /*getcount_only*/0);
1035 }
1036
1037 /*
1038  * Generic Async Event handler.  Peripheral drivers usually
1039  * filter out the events that require personal attention,
1040  * and leave the rest to this function.
1041  */
1042 void
1043 cam_periph_async(struct cam_periph *periph, u_int32_t code,
1044                  struct cam_path *path, void *arg)
1045 {
1046         switch (code) {
1047         case AC_LOST_DEVICE:
1048                 cam_periph_invalidate(periph);
1049                 break; 
1050         case AC_SENT_BDR:
1051         case AC_BUS_RESET:
1052         {
1053                 cam_periph_bus_settle(periph, SCSI_DELAY);
1054                 break;
1055         }
1056         default:
1057                 break;
1058         }
1059 }
1060
1061 void
1062 cam_periph_bus_settle(struct cam_periph *periph, u_int bus_settle)
1063 {
1064         struct ccb_getdevstats cgds;
1065
1066         xpt_setup_ccb(&cgds.ccb_h, periph->path, /*priority*/1);
1067         cgds.ccb_h.func_code = XPT_GDEV_STATS;
1068         xpt_action((union ccb *)&cgds);
1069         cam_periph_freeze_after_event(periph, &cgds.last_reset, bus_settle);
1070 }
1071
1072 void
1073 cam_periph_freeze_after_event(struct cam_periph *periph,
1074                               struct timeval* event_time, u_int duration_ms)
1075 {
1076         struct timeval delta;
1077         struct timeval duration_tv;
1078         int s;
1079
1080         s = splclock();
1081         microtime(&delta);
1082         splx(s);
1083         timevalsub(&delta, event_time);
1084         duration_tv.tv_sec = duration_ms / 1000;
1085         duration_tv.tv_usec = (duration_ms % 1000) * 1000;
1086         if (timevalcmp(&delta, &duration_tv, <)) {
1087                 timevalsub(&duration_tv, &delta);
1088
1089                 duration_ms = duration_tv.tv_sec * 1000;
1090                 duration_ms += duration_tv.tv_usec / 1000;
1091                 cam_freeze_devq(periph->path); 
1092                 cam_release_devq(periph->path,
1093                                 RELSIM_RELEASE_AFTER_TIMEOUT,
1094                                 /*reduction*/0,
1095                                 /*timeout*/duration_ms,
1096                                 /*getcount_only*/0);
1097         }
1098
1099 }
1100
1101 /*
1102  * Generic error handler.  Peripheral drivers usually filter
1103  * out the errors that they handle in a unique mannor, then
1104  * call this function.
1105  */
1106 int
1107 cam_periph_error(union ccb *ccb, cam_flags camflags,
1108                  u_int32_t sense_flags, union ccb *save_ccb)
1109 {
1110         cam_status status;
1111         int        frozen;
1112         int        sense;
1113         int        error;
1114         int        openings;
1115         int        retry;
1116         u_int32_t  relsim_flags;
1117         u_int32_t  timeout;
1118         
1119         status = ccb->ccb_h.status;
1120         frozen = (status & CAM_DEV_QFRZN) != 0;
1121         sense  = (status & CAM_AUTOSNS_VALID) != 0;
1122         status &= CAM_STATUS_MASK;
1123         relsim_flags = 0;
1124
1125         switch (status) {
1126         case CAM_REQ_CMP:
1127                 /* decrement the number of retries */
1128                 retry = ccb->ccb_h.retry_count > 0;
1129                 if (retry)
1130                         ccb->ccb_h.retry_count--;
1131                 error = 0;
1132                 break;
1133         case CAM_AUTOSENSE_FAIL:
1134         case CAM_SCSI_STATUS_ERROR:
1135
1136                 switch (ccb->csio.scsi_status) {
1137                 case SCSI_STATUS_OK:
1138                 case SCSI_STATUS_COND_MET:
1139                 case SCSI_STATUS_INTERMED:
1140                 case SCSI_STATUS_INTERMED_COND_MET:
1141                         error = 0;
1142                         break;
1143                 case SCSI_STATUS_CMD_TERMINATED:
1144                 case SCSI_STATUS_CHECK_COND:
1145                         if (sense != 0) {
1146                                 struct scsi_sense_data *sense;
1147                                 int    error_code, sense_key, asc, ascq;
1148                                 struct cam_periph *periph;
1149                                 scsi_sense_action err_action;
1150                                 struct ccb_getdev cgd;
1151
1152                                 sense = &ccb->csio.sense_data;
1153                                 scsi_extract_sense(sense, &error_code,
1154                                                    &sense_key, &asc, &ascq);
1155                                 periph = xpt_path_periph(ccb->ccb_h.path);
1156
1157                                 /*
1158                                  * Grab the inquiry data for this device.
1159                                  */
1160                                 xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path,
1161                                               /*priority*/ 1);
1162                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1163                                 xpt_action((union ccb *)&cgd);
1164
1165                                 err_action = scsi_error_action(asc, ascq, 
1166                                                                &cgd.inq_data);
1167
1168                                 /*
1169                                  * Send a Test Unit Ready to the device.
1170                                  * If the 'many' flag is set, we send 120
1171                                  * test unit ready commands, one every half 
1172                                  * second.  Otherwise, we just send one TUR.
1173                                  * We only want to do this if the retry 
1174                                  * count has not been exhausted.
1175                                  */
1176                                 if (((err_action & SS_MASK) == SS_TUR)
1177                                  && save_ccb != NULL 
1178                                  && ccb->ccb_h.retry_count > 0) {
1179
1180                                         /*
1181                                          * Since error recovery is already
1182                                          * in progress, don't attempt to
1183                                          * process this error.  It is probably
1184                                          * related to the error that caused
1185                                          * the currently active error recovery
1186                                          * action.  Also, we only have
1187                                          * space for one saved CCB, so if we
1188                                          * had two concurrent error recovery
1189                                          * actions, we would end up
1190                                          * over-writing one error recovery
1191                                          * CCB with another one.
1192                                          */
1193                                         if (periph->flags &
1194                                             CAM_PERIPH_RECOVERY_INPROG) {
1195                                                 error = ERESTART;
1196                                                 break;
1197                                         }
1198
1199                                         periph->flags |=
1200                                                 CAM_PERIPH_RECOVERY_INPROG;
1201
1202                                         /* decrement the number of retries */
1203                                         if ((err_action & 
1204                                              SSQ_DECREMENT_COUNT) != 0) {
1205                                                 retry = 1;
1206                                                 ccb->ccb_h.retry_count--;
1207                                         }
1208
1209                                         bcopy(ccb, save_ccb, sizeof(*save_ccb));
1210
1211                                         /*
1212                                          * We retry this one every half
1213                                          * second for a minute.  If the
1214                                          * device hasn't become ready in a
1215                                          * minute's time, it's unlikely to
1216                                          * ever become ready.  If the table
1217                                          * doesn't specify SSQ_MANY, we can
1218                                          * only try this once.  Oh well.
1219                                          */
1220                                         if ((err_action & SSQ_MANY) != 0)
1221                                                 scsi_test_unit_ready(&ccb->csio,
1222                                                                /*retries*/120,
1223                                                                camperiphdone,
1224                                                                MSG_SIMPLE_Q_TAG,
1225                                                                SSD_FULL_SIZE,
1226                                                                /*timeout*/5000);
1227                                         else
1228                                                 scsi_test_unit_ready(&ccb->csio,
1229                                                                /*retries*/1,
1230                                                                camperiphdone,
1231                                                                MSG_SIMPLE_Q_TAG,
1232                                                                SSD_FULL_SIZE,
1233                                                                /*timeout*/5000);
1234
1235                                         /* release the queue after .5 sec.  */
1236                                         relsim_flags = 
1237                                                 RELSIM_RELEASE_AFTER_TIMEOUT;
1238                                         timeout = 500;
1239                                         /*
1240                                          * Drop the priority to 0 so that 
1241                                          * we are the first to execute.  Also 
1242                                          * freeze the queue after this command 
1243                                          * is sent so that we can restore the 
1244                                          * old csio and have it queued in the 
1245                                          * proper order before we let normal 
1246                                          * transactions go to the drive.
1247                                          */
1248                                         ccb->ccb_h.pinfo.priority = 0;
1249                                         ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
1250
1251                                         /*
1252                                          * Save a pointer to the original
1253                                          * CCB in the new CCB.
1254                                          */
1255                                         ccb->ccb_h.saved_ccb_ptr = save_ccb;
1256
1257                                         error = ERESTART;
1258                                 }
1259                                 /*
1260                                  * Send a start unit command to the device,
1261                                  * and then retry the command.  We only 
1262                                  * want to do this if the retry count has 
1263                                  * not been exhausted.  If the user 
1264                                  * specified 0 retries, then we follow 
1265                                  * their request and do not retry.
1266                                  */
1267                                 else if (((err_action & SS_MASK) == SS_START)
1268                                       && save_ccb != NULL 
1269                                       && ccb->ccb_h.retry_count > 0) {
1270                                         int le;
1271
1272                                         /*
1273                                          * Only one error recovery action
1274                                          * at a time.  See above.
1275                                          */
1276                                         if (periph->flags &
1277                                             CAM_PERIPH_RECOVERY_INPROG) {
1278                                                 error = ERESTART;
1279                                                 break;
1280                                         }
1281
1282                                         periph->flags |=
1283                                                 CAM_PERIPH_RECOVERY_INPROG;
1284
1285                                         /* decrement the number of retries */
1286                                         retry = 1;
1287                                         ccb->ccb_h.retry_count--;
1288
1289                                         /*
1290                                          * Check for removable media and
1291                                          * set load/eject flag
1292                                          * appropriately.
1293                                          */
1294                                         if (SID_IS_REMOVABLE(&cgd.inq_data))
1295                                                 le = TRUE;
1296                                         else
1297                                                 le = FALSE;
1298
1299                                         /*
1300                                          * Attempt to start the drive up.
1301                                          *
1302                                          * Save the current ccb so it can 
1303                                          * be restored and retried once the 
1304                                          * drive is started up.
1305                                          */
1306                                         bcopy(ccb, save_ccb, sizeof(*save_ccb));
1307
1308                                         scsi_start_stop(&ccb->csio,
1309                                                         /*retries*/1,
1310                                                         camperiphdone,
1311                                                         MSG_SIMPLE_Q_TAG,
1312                                                         /*start*/TRUE,
1313                                                         /*load/eject*/le,
1314                                                         /*immediate*/FALSE,
1315                                                         SSD_FULL_SIZE,
1316                                                         /*timeout*/50000);
1317                                         /*
1318                                          * Drop the priority to 0 so that 
1319                                          * we are the first to execute.  Also 
1320                                          * freeze the queue after this command 
1321                                          * is sent so that we can restore the 
1322                                          * old csio and have it queued in the 
1323                                          * proper order before we let normal 
1324                                          * transactions go to the drive.
1325                                          */
1326                                         ccb->ccb_h.pinfo.priority = 0;
1327                                         ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
1328
1329                                         /*
1330                                          * Save a pointer to the original
1331                                          * CCB in the new CCB.
1332                                          */
1333                                         ccb->ccb_h.saved_ccb_ptr = save_ccb;
1334
1335                                         error = ERESTART;
1336                                 } else if ((sense_flags & SF_RETRY_UA) != 0) {
1337                                         /*
1338                                          * XXX KDM this is a *horrible*
1339                                          * hack.  
1340                                          */
1341                                         error = scsi_interpret_sense(ccb,
1342                                                                   sense_flags,
1343                                                                   &relsim_flags,
1344                                                                   &openings,
1345                                                                   &timeout,
1346                                                                   err_action);
1347                                 } 
1348
1349                                 /*
1350                                  * Theoretically, this code should send a
1351                                  * test unit ready to the given device, and 
1352                                  * if it returns and error, send a start 
1353                                  * unit command.  Since we don't yet have
1354                                  * the capability to do two-command error
1355                                  * recovery, just send a start unit.
1356                                  * XXX KDM fix this!
1357                                  */
1358                                 else if (((err_action & SS_MASK) == SS_TURSTART)
1359                                       && save_ccb != NULL
1360                                       && ccb->ccb_h.retry_count > 0) {
1361                                         int le;
1362
1363                                         /*
1364                                          * Only one error recovery action
1365                                          * at a time.  See above.
1366                                          */
1367                                         if (periph->flags &
1368                                             CAM_PERIPH_RECOVERY_INPROG) {
1369                                                 error = ERESTART;
1370                                                 break;
1371                                         }
1372
1373                                         periph->flags |=
1374                                                 CAM_PERIPH_RECOVERY_INPROG;
1375
1376                                         /* decrement the number of retries */
1377                                         retry = 1;
1378                                         ccb->ccb_h.retry_count--;
1379
1380                                         /*
1381                                          * Check for removable media and
1382                                          * set load/eject flag
1383                                          * appropriately.
1384                                          */
1385                                         if (SID_IS_REMOVABLE(&cgd.inq_data))
1386                                                 le = TRUE;
1387                                         else
1388                                                 le = FALSE;
1389
1390                                         /*
1391                                          * Attempt to start the drive up.
1392                                          *
1393                                          * Save the current ccb so it can 
1394                                          * be restored and retried once the 
1395                                          * drive is started up.
1396                                          */
1397                                         bcopy(ccb, save_ccb, sizeof(*save_ccb));
1398
1399                                         scsi_start_stop(&ccb->csio,
1400                                                         /*retries*/1,
1401                                                         camperiphdone,
1402                                                         MSG_SIMPLE_Q_TAG,
1403                                                         /*start*/TRUE,
1404                                                         /*load/eject*/le,
1405                                                         /*immediate*/FALSE,
1406                                                         SSD_FULL_SIZE,
1407                                                         /*timeout*/50000);
1408
1409                                         /* release the queue after .5 sec.  */
1410                                         relsim_flags = 
1411                                                 RELSIM_RELEASE_AFTER_TIMEOUT;
1412                                         timeout = 500;
1413                                         /*
1414                                          * Drop the priority to 0 so that 
1415                                          * we are the first to execute.  Also 
1416                                          * freeze the queue after this command 
1417                                          * is sent so that we can restore the 
1418                                          * old csio and have it queued in the 
1419                                          * proper order before we let normal 
1420                                          * transactions go to the drive.
1421                                          */
1422                                         ccb->ccb_h.pinfo.priority = 0;
1423                                         ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
1424
1425                                         /*
1426                                          * Save a pointer to the original
1427                                          * CCB in the new CCB.
1428                                          */
1429                                         ccb->ccb_h.saved_ccb_ptr = save_ccb;
1430
1431                                         error = ERESTART;
1432                                 } else {
1433                                         error = scsi_interpret_sense(ccb,
1434                                                                   sense_flags,
1435                                                                   &relsim_flags,
1436                                                                   &openings,
1437                                                                   &timeout,
1438                                                                   err_action);
1439                                 }
1440                         } else if (ccb->csio.scsi_status == 
1441                                    SCSI_STATUS_CHECK_COND
1442                                 && status != CAM_AUTOSENSE_FAIL) {
1443                                 /* no point in decrementing the retry count */
1444                                 panic("cam_periph_error: scsi status of "
1445                                       "CHECK COND returned but no sense "
1446                                       "information is availible.  "
1447                                       "Controller should have returned "
1448                                       "CAM_AUTOSENSE_FAILED");
1449                                 /* NOTREACHED */
1450                                 error = EIO;
1451                         } else if (ccb->ccb_h.retry_count == 0) {
1452                                 /*
1453                                  * XXX KDM shouldn't there be a better
1454                                  * argument to return??
1455                                  */
1456                                 error = EIO;
1457                         } else {
1458                                 /* decrement the number of retries */
1459                                 retry = ccb->ccb_h.retry_count > 0;
1460                                 if (retry)
1461                                         ccb->ccb_h.retry_count--;
1462                                 /*
1463                                  * If it was aborted with no
1464                                  * clue as to the reason, just
1465                                  * retry it again.
1466                                  */
1467                                 error = ERESTART;
1468                         }
1469                         break;
1470                 case SCSI_STATUS_QUEUE_FULL:
1471                 {
1472                         /* no decrement */
1473                         struct ccb_getdevstats cgds;
1474
1475                         /*
1476                          * First off, find out what the current
1477                          * transaction counts are.
1478                          */
1479                         xpt_setup_ccb(&cgds.ccb_h,
1480                                       ccb->ccb_h.path,
1481                                       /*priority*/1);
1482                         cgds.ccb_h.func_code = XPT_GDEV_STATS;
1483                         xpt_action((union ccb *)&cgds);
1484
1485                         /*
1486                          * If we were the only transaction active, treat
1487                          * the QUEUE FULL as if it were a BUSY condition.
1488                          */
1489                         if (cgds.dev_active != 0) {
1490                                 int total_openings;
1491
1492                                 /*
1493                                  * Reduce the number of openings to
1494                                  * be 1 less than the amount it took
1495                                  * to get a queue full bounded by the
1496                                  * minimum allowed tag count for this
1497                                  * device.
1498                                  */
1499                                 total_openings =
1500                                     cgds.dev_active+cgds.dev_openings;
1501                                 openings = cgds.dev_active;
1502                                 if (openings < cgds.mintags)
1503                                         openings = cgds.mintags;
1504                                 if (openings < total_openings)
1505                                         relsim_flags = RELSIM_ADJUST_OPENINGS;
1506                                 else {
1507                                         /*
1508                                          * Some devices report queue full for
1509                                          * temporary resource shortages.  For
1510                                          * this reason, we allow a minimum
1511                                          * tag count to be entered via a
1512                                          * quirk entry to prevent the queue
1513                                          * count on these devices from falling
1514                                          * to a pessimisticly low value.  We
1515                                          * still wait for the next successful
1516                                          * completion, however, before queueing
1517                                          * more transactions to the device.
1518                                          */
1519                                         relsim_flags =
1520                                             RELSIM_RELEASE_AFTER_CMDCMPLT;
1521                                 }
1522                                 timeout = 0;
1523                                 error = ERESTART;
1524                                 break;
1525                         }
1526                         /* FALLTHROUGH */
1527                 }
1528                 case SCSI_STATUS_BUSY:
1529                         /*
1530                          * Restart the queue after either another
1531                          * command completes or a 1 second timeout.
1532                          * If we have any retries left, that is.
1533                          */
1534                         retry = ccb->ccb_h.retry_count > 0;
1535                         if (retry) {
1536                                 ccb->ccb_h.retry_count--;
1537                                 error = ERESTART;
1538                                 relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT
1539                                              | RELSIM_RELEASE_AFTER_CMDCMPLT;
1540                                 timeout = 1000;
1541                         } else {
1542                                 error = EIO;
1543                         }
1544                         break;
1545                 case SCSI_STATUS_RESERV_CONFLICT:
1546                         error = EIO;
1547                         break;
1548                 default:
1549                         error = EIO;
1550                         break;
1551                 }
1552                 break;
1553         case CAM_REQ_CMP_ERR:
1554         case CAM_CMD_TIMEOUT:
1555         case CAM_UNEXP_BUSFREE:
1556         case CAM_UNCOR_PARITY:
1557         case CAM_DATA_RUN_ERR:
1558                 /* decrement the number of retries */
1559                 retry = ccb->ccb_h.retry_count > 0;
1560                 if (retry) {
1561                         ccb->ccb_h.retry_count--;
1562                         error = ERESTART;
1563                 } else {
1564                         error = EIO;
1565                 }
1566                 break;
1567         case CAM_UA_ABORT:
1568         case CAM_UA_TERMIO:
1569         case CAM_MSG_REJECT_REC:
1570                 /* XXX Don't know that these are correct */
1571                 error = EIO;
1572                 break;
1573         case CAM_SEL_TIMEOUT:
1574         {
1575                 /*
1576                  * XXX
1577                  * A single selection timeout should not be enough
1578                  * to invalidate a device.  We should retry for multiple
1579                  * seconds assuming this isn't a probe.  We'll probably
1580                  * need a special flag for that.
1581                  */
1582 #if 0
1583                 struct cam_path *newpath;
1584
1585                 /* Should we do more if we can't create the path?? */
1586                 if (xpt_create_path(&newpath, xpt_path_periph(ccb->ccb_h.path),
1587                                     xpt_path_path_id(ccb->ccb_h.path),
1588                                     xpt_path_target_id(ccb->ccb_h.path),
1589                                     CAM_LUN_WILDCARD) != CAM_REQ_CMP) 
1590                         break;
1591                 /*
1592                  * Let peripheral drivers know that this device has gone
1593                  * away.
1594                  */
1595                 xpt_async(AC_LOST_DEVICE, newpath, NULL);
1596                 xpt_free_path(newpath);
1597 #endif
1598                 if ((sense_flags & SF_RETRY_SELTO) != 0) {
1599                         retry = ccb->ccb_h.retry_count > 0;
1600                         if (retry) {
1601                                 ccb->ccb_h.retry_count--;
1602                                 error = ERESTART;
1603                                 /*
1604                                  * Wait half a second to give the device
1605                                  * time to recover before we try again.
1606                                  */
1607                                 relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
1608                                 timeout = 500;
1609                         } else {
1610                                 error = ENXIO;
1611                         }
1612                 } else {
1613                         error = ENXIO;
1614                 }
1615                 break;
1616         }
1617         case CAM_REQ_INVALID:
1618         case CAM_PATH_INVALID:
1619         case CAM_DEV_NOT_THERE:
1620         case CAM_NO_HBA:
1621         case CAM_PROVIDE_FAIL:
1622         case CAM_REQ_TOO_BIG:           
1623                 error = EINVAL;
1624                 break;
1625         case CAM_SCSI_BUS_RESET:
1626         case CAM_BDR_SENT:              
1627         case CAM_REQUEUE_REQ:
1628                 /* Unconditional requeue, dammit */
1629                 error = ERESTART;
1630                 break;
1631         case CAM_RESRC_UNAVAIL:
1632         case CAM_BUSY:
1633                 /* timeout??? */
1634         default:
1635                 /* decrement the number of retries */
1636                 retry = ccb->ccb_h.retry_count > 0;
1637                 if (retry) {
1638                         ccb->ccb_h.retry_count--;
1639                         error = ERESTART;
1640                 } else {
1641                         /* Check the sense codes */
1642                         error = EIO;
1643                 }
1644                 break;
1645         }
1646
1647         /* Attempt a retry */
1648         if (error == ERESTART || error == 0) {  
1649                 if (frozen != 0)
1650                         ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
1651
1652                 if (error == ERESTART)
1653                         xpt_action(ccb);
1654                 
1655                 if (frozen != 0) {
1656                         cam_release_devq(ccb->ccb_h.path,
1657                                          relsim_flags,
1658                                          openings,
1659                                          timeout,
1660                                          /*getcount_only*/0);
1661                 }
1662         }
1663
1664
1665         return (error);
1666 }