[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cam/scsi/scsi_low.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*      $NecBSD: scsi_low.c,v 1.24.10.8 2001/06/26 07:39:44 honda Exp $ */
  2 /*      $NetBSD$        */
  3 
  4 #include <sys/cdefs.h>
  5 __FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_low.c,v 1.29 2007/06/17 05:55:54 scottl Exp $");
  6 
  7 #define SCSI_LOW_STATICS
  8 #define SCSI_LOW_DEBUG
  9 #define SCSI_LOW_NEGOTIATE_BEFORE_SENSE
 10 #define SCSI_LOW_START_UP_CHECK
 11 
 12 /* #define      SCSI_LOW_INFO_DETAIL */
 13 
 14 /* #define      SCSI_LOW_QCLEAR_AFTER_CA */
 15 /* #define      SCSI_LOW_FLAGS_QUIRKS_OK */
 16 
 17 #ifdef __NetBSD__
 18 #define SCSI_LOW_TARGET_OPEN
 19 #endif  /* __NetBSD__ */
 20 
 21 #ifdef  __FreeBSD__
 22 #define SCSI_LOW_FLAGS_QUIRKS_OK
 23 #endif  /* __FreeBSD__ */
 24 
 25 /*-
 26  * [NetBSD for NEC PC-98 series]
 27  *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
 28  *      NetBSD/pc98 porting staff. All rights reserved.
 29  *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
 30  *      Naofumi HONDA. All rights reserved.
 31  *
 32  * [Ported for FreeBSD CAM]
 33  *  Copyright (c) 2000, 2001
 34  *      MITSUNAGA Noriaki, NOKUBI Hirotaka and TAKAHASHI Yoshihiro.
 35  *      All rights reserved.
 36  * 
 37  *  Redistribution and use in source and binary forms, with or without
 38  *  modification, are permitted provided that the following conditions
 39  *  are met:
 40  *  1. Redistributions of source code must retain the above copyright
 41  *     notice, this list of conditions and the following disclaimer.
 42  *  2. Redistributions in binary form must reproduce the above copyright
 43  *     notice, this list of conditions and the following disclaimer in the
 44  *     documentation and/or other materials provided with the distribution.
 45  *  3. The name of the author may not be used to endorse or promote products
 46  *     derived from this software without specific prior written permission.
 47  * 
 48  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 50  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 51  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 52  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 53  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 54  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 56  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 57  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 58  * POSSIBILITY OF SUCH DAMAGE.
 59  */
 60 
 61 /* <On the nexus establishment>
 62  * When our host is reselected, 
 63  * nexus establish processes are little complicated.
 64  * Normal steps are followings:
 65  * 1) Our host selected by target => target nexus (slp->sl_Tnexus) 
 66  * 2) Identify msgin => lun nexus (slp->sl_Lnexus)
 67  * 3) Qtag msg => ccb nexus (slp->sl_Qnexus)
 68  */
 69 #include "opt_ddb.h"
 70 
 71 #include <sys/param.h>
 72 #include <sys/systm.h>
 73 #include <sys/kernel.h>
 74 
 75 #ifdef __FreeBSD__
 76 #if __FreeBSD_version >= 500001
 77 #include <sys/bio.h>
 78 #else
 79 #include <machine/clock.h>
 80 #endif
 81 #endif  /* __FreeBSD__ */
 82 
 83 #include <sys/buf.h>
 84 #include <sys/queue.h>
 85 #include <sys/malloc.h>
 86 #include <sys/errno.h>
 87 
 88 #ifdef  __NetBSD__
 89 #include <sys/device.h>
 90 #include <vm/vm.h>
 91 
 92 #include <machine/bus.h>
 93 #include <machine/intr.h>
 94 #include <machine/dvcfg.h>
 95 
 96 #include <dev/cons.h>
 97 
 98 #include <dev/scsipi/scsipi_all.h>
 99 #include <dev/scsipi/scsipiconf.h>
100 #include <dev/scsipi/scsipi_disk.h>
101 #include <dev/scsipi/scsi_all.h>
102 #include <dev/scsipi/scsiconf.h>
103 #include <sys/scsiio.h>
104 
105 #include <i386/Cbus/dev/scsi_low.h>
106 #endif  /* __NetBSD__ */
107 
108 #ifdef __FreeBSD__
109 #include <cam/cam.h>
110 #include <cam/cam_ccb.h>
111 #include <cam/cam_sim.h>
112 #include <cam/cam_debug.h>
113 #include <cam/cam_periph.h>
114 #include <cam/cam_xpt_periph.h>
115 
116 #include <cam/scsi/scsi_all.h>
117 #include <cam/scsi/scsi_message.h>
118 
119 #include <cam/scsi/scsi_low.h>
120 
121 #include <sys/cons.h>
122 #endif  /* __FreeBSD__ */
123 
124 /**************************************************************
125  * Constants
126  **************************************************************/
127 #define SCSI_LOW_POLL_HZ        1000
128 
129 /* functions return values */
130 #define SCSI_LOW_START_NO_QTAG  0
131 #define SCSI_LOW_START_QTAG     1
132 
133 #define SCSI_LOW_DONE_COMPLETE  0
134 #define SCSI_LOW_DONE_RETRY     1
135 
136 /* internal disk flags */
137 #define SCSI_LOW_DISK_DISC      0x00000001
138 #define SCSI_LOW_DISK_QTAG      0x00000002
139 #define SCSI_LOW_DISK_LINK      0x00000004
140 #define SCSI_LOW_DISK_PARITY    0x00000008
141 #define SCSI_LOW_DISK_SYNC      0x00010000
142 #define SCSI_LOW_DISK_WIDE_16   0x00020000
143 #define SCSI_LOW_DISK_WIDE_32   0x00040000
144 #define SCSI_LOW_DISK_WIDE      (SCSI_LOW_DISK_WIDE_16 | SCSI_LOW_DISK_WIDE_32)
145 #define SCSI_LOW_DISK_LFLAGS    0x0000ffff
146 #define SCSI_LOW_DISK_TFLAGS    0xffff0000
147 
148 MALLOC_DEFINE(M_SCSILOW, "SCSI low", "SCSI low buffers");
149 
150 /**************************************************************
151  * Declarations
152  **************************************************************/
153 /* static */ void scsi_low_info(struct scsi_low_softc *, struct targ_info *, u_char *);
154 static void scsi_low_engage(void *);
155 static struct slccb *scsi_low_establish_ccb(struct targ_info *, struct lun_info *, scsi_low_tag_t);
156 static int scsi_low_done(struct scsi_low_softc *, struct slccb *);
157 static int scsi_low_setup_done(struct scsi_low_softc *, struct slccb *);
158 static void scsi_low_bus_release(struct scsi_low_softc *, struct targ_info *);
159 static void scsi_low_twiddle_wait(void);
160 static struct lun_info *scsi_low_alloc_li(struct targ_info *, int, int);
161 static struct targ_info *scsi_low_alloc_ti(struct scsi_low_softc *, int);
162 static void scsi_low_calcf_lun(struct lun_info *);
163 static void scsi_low_calcf_target(struct targ_info *);
164 static void scsi_low_calcf_show(struct lun_info *);
165 static void scsi_low_reset_nexus(struct scsi_low_softc *, int);
166 static void scsi_low_reset_nexus_target(struct scsi_low_softc *, struct targ_info *, int);
167 static void scsi_low_reset_nexus_lun(struct scsi_low_softc *, struct lun_info *, int);
168 static int scsi_low_init(struct scsi_low_softc *, u_int);
169 static void scsi_low_start(struct scsi_low_softc *);
170 static void scsi_low_free_ti(struct scsi_low_softc *);
171 
172 static int scsi_low_alloc_qtag(struct slccb *);
173 static int scsi_low_dealloc_qtag(struct slccb *);
174 static int scsi_low_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *, u_int, u_int);
175 static int scsi_low_message_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, u_int);
176 static void scsi_low_unit_ready_cmd(struct slccb *);
177 static void scsi_low_timeout(void *);
178 static int scsi_low_timeout_check(struct scsi_low_softc *);
179 #ifdef  SCSI_LOW_START_UP_CHECK
180 static int scsi_low_start_up(struct scsi_low_softc *);
181 #endif  /* SCSI_LOW_START_UP_CHECK */
182 static int scsi_low_abort_ccb(struct scsi_low_softc *, struct slccb *);
183 static struct slccb *scsi_low_revoke_ccb(struct scsi_low_softc *, struct slccb *, int);
184 
185 int scsi_low_version_major = 2;
186 int scsi_low_version_minor = 17;
187 
188 static struct scsi_low_softc_tab sl_tab = LIST_HEAD_INITIALIZER(sl_tab);
189 
190 /**************************************************************
191  * Debug, Run test and Statics
192  **************************************************************/
193 #ifdef  SCSI_LOW_INFO_DETAIL
194 #define SCSI_LOW_INFO(slp, ti, s) scsi_low_info((slp), (ti), (s))
195 #else   /* !SCSI_LOW_INFO_DETAIL */
196 #define SCSI_LOW_INFO(slp, ti, s) printf("%s: %s\n", (slp)->sl_xname, (s))
197 #endif  /* !SCSI_LOW_INFO_DETAIL */
198 
199 #ifdef  SCSI_LOW_STATICS
200 static struct scsi_low_statics {
201         int nexus_win;
202         int nexus_fail;
203         int nexus_disconnected;
204         int nexus_reselected;
205         int nexus_conflict;
206 } scsi_low_statics;
207 #endif  /* SCSI_LOW_STATICS */
208 
209 #ifdef  SCSI_LOW_DEBUG
210 #define SCSI_LOW_DEBUG_DONE     0x00001
211 #define SCSI_LOW_DEBUG_DISC     0x00002
212 #define SCSI_LOW_DEBUG_SENSE    0x00004
213 #define SCSI_LOW_DEBUG_CALCF    0x00008
214 #define SCSI_LOW_DEBUG_ACTION   0x10000
215 int scsi_low_debug = 0;
216 
217 #define SCSI_LOW_MAX_ATTEN_CHECK        32
218 #define SCSI_LOW_ATTEN_CHECK    0x0001
219 #define SCSI_LOW_CMDLNK_CHECK   0x0002
220 #define SCSI_LOW_ABORT_CHECK    0x0004
221 #define SCSI_LOW_NEXUS_CHECK    0x0008
222 int scsi_low_test = 0;
223 int scsi_low_test_id = 0;
224 
225 static void scsi_low_test_abort(struct scsi_low_softc *, struct targ_info *, struct lun_info *);
226 static void scsi_low_test_cmdlnk(struct scsi_low_softc *, struct slccb *);
227 static void scsi_low_test_atten(struct scsi_low_softc *, struct targ_info *, u_int);
228 #define SCSI_LOW_DEBUG_TEST_GO(fl, id) \
229         ((scsi_low_test & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0)
230 #define SCSI_LOW_DEBUG_GO(fl, id) \
231         ((scsi_low_debug & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0)
232 #endif  /* SCSI_LOW_DEBUG */
233 
234 /**************************************************************
235  * CCB
236  **************************************************************/
237 GENERIC_CCB_STATIC_ALLOC(scsi_low, slccb)
238 GENERIC_CCB(scsi_low, slccb, ccb_chain)
239 
240 /**************************************************************
241  * Inline functions
242  **************************************************************/
243 #define SCSI_LOW_INLINE static __inline
244 SCSI_LOW_INLINE void scsi_low_activate_qtag(struct slccb *);
245 SCSI_LOW_INLINE void scsi_low_deactivate_qtag(struct slccb *);
246 SCSI_LOW_INLINE void scsi_low_ccb_message_assert(struct slccb *, u_int);
247 SCSI_LOW_INLINE void scsi_low_ccb_message_exec(struct scsi_low_softc *, struct slccb *);
248 SCSI_LOW_INLINE void scsi_low_ccb_message_retry(struct slccb *);
249 SCSI_LOW_INLINE void scsi_low_ccb_message_clear(struct slccb *);
250 SCSI_LOW_INLINE void scsi_low_init_msgsys(struct scsi_low_softc *, struct targ_info *);
251 
252 SCSI_LOW_INLINE void
253 scsi_low_activate_qtag(cb)
254         struct slccb *cb;
255 {
256         struct lun_info *li = cb->li;
257 
258         if (cb->ccb_tag != SCSI_LOW_UNKTAG)
259                 return;
260 
261         li->li_nqio ++;
262         cb->ccb_tag = cb->ccb_otag;
263 }
264         
265 SCSI_LOW_INLINE void
266 scsi_low_deactivate_qtag(cb)
267         struct slccb *cb;
268 {
269         struct lun_info *li = cb->li;
270 
271         if (cb->ccb_tag == SCSI_LOW_UNKTAG)
272                 return;
273 
274         li->li_nqio --;
275         cb->ccb_tag = SCSI_LOW_UNKTAG;
276 }
277         
278 SCSI_LOW_INLINE void
279 scsi_low_ccb_message_exec(slp, cb)
280         struct scsi_low_softc *slp;
281         struct slccb *cb;
282 {
283 
284         scsi_low_assert_msg(slp, cb->ti, cb->ccb_msgoutflag, 0);
285         cb->ccb_msgoutflag = 0;
286 }
287 
288 SCSI_LOW_INLINE void
289 scsi_low_ccb_message_assert(cb, msg)
290         struct slccb *cb;
291         u_int msg;
292 {
293 
294         cb->ccb_msgoutflag = cb->ccb_omsgoutflag = msg;
295 }
296 
297 SCSI_LOW_INLINE void
298 scsi_low_ccb_message_retry(cb)
299         struct slccb *cb;
300 {
301         cb->ccb_msgoutflag = cb->ccb_omsgoutflag;
302 }
303 
304 SCSI_LOW_INLINE void
305 scsi_low_ccb_message_clear(cb)
306         struct slccb *cb;
307 {
308         cb->ccb_msgoutflag = 0;
309 }
310 
311 SCSI_LOW_INLINE void
312 scsi_low_init_msgsys(slp, ti)
313         struct scsi_low_softc *slp;
314         struct targ_info *ti;
315 {
316 
317         ti->ti_msginptr = 0;
318         ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0;
319         SCSI_LOW_DEASSERT_ATN(slp);
320         SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL);
321 }
322 
323 /*=============================================================
324  * START OF OS switch  (All OS depend fucntions should be here)
325  =============================================================*/
326 /* common os depend utitlities */
327 #define SCSI_LOW_CMD_RESIDUAL_CHK       0x0001
328 #define SCSI_LOW_CMD_ORDERED_QTAG       0x0002
329 #define SCSI_LOW_CMD_ABORT_WARNING      0x0004
330 
331 static u_int8_t scsi_low_cmd_flags[256] = {
332 /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
333 /**/   0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0,
334 /*1*/   0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
335 /*2*/   0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 5, 5,
336 /*3*/   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5,
337 };
338 
339 struct scsi_low_error_code {
340         int error_bits;
341         int error_code;
342 };
343 
344 static struct slccb *scsi_low_find_ccb(struct scsi_low_softc *, u_int, u_int, void *);
345 static int scsi_low_translate_error_code(struct slccb *, struct scsi_low_error_code *);
346 
347 static struct slccb *
348 scsi_low_find_ccb(slp, target, lun, osdep)
349         struct scsi_low_softc *slp;
350         u_int target, lun;
351         void *osdep;
352 {
353         struct targ_info *ti;
354         struct lun_info *li;
355         struct slccb *cb;
356 
357         ti = slp->sl_ti[target];
358         li = scsi_low_alloc_li(ti, lun, 0);
359         if (li == NULL)
360                 return NULL;
361 
362         if ((cb = slp->sl_Qnexus) != NULL && cb->osdep == osdep)
363                 return cb;
364 
365         for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL;
366              cb = TAILQ_NEXT(cb, ccb_chain))
367         {
368                 if (cb->osdep == osdep)
369                         return cb;
370         }
371 
372         for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL;
373              cb = TAILQ_NEXT(cb, ccb_chain))
374         {
375                 if (cb->osdep == osdep)
376                         return cb;
377         }
378         return NULL;
379 }
380 
381 static int 
382 scsi_low_translate_error_code(cb, tp)
383         struct slccb *cb;
384         struct scsi_low_error_code *tp;
385 {
386 
387         if (cb->ccb_error == 0)
388                 return tp->error_code;
389 
390         for (tp ++; (cb->ccb_error & tp->error_bits) == 0; tp ++)
391                 ;
392         return tp->error_code;
393 }
394 
395 #ifdef SCSI_LOW_INTERFACE_XS
396 /**************************************************************
397  * SCSI INTERFACE (XS)
398  **************************************************************/
399 #define SCSI_LOW_MINPHYS                0x10000
400 #define SCSI_LOW_MALLOC(size)           malloc((size), M_SCSILOW, M_NOWAIT)
401 #define SCSI_LOW_FREE(pt)               free((pt), M_SCSILOW)
402 #define SCSI_LOW_ALLOC_CCB(flags)       scsi_low_get_ccb((flags))
403 #define SCSI_LOW_XS_POLL_HZ             1000
404 
405 static int scsi_low_poll_xs(struct scsi_low_softc *, struct slccb *);
406 static void scsi_low_scsi_minphys_xs(struct buf *);
407 #ifdef  SCSI_LOW_TARGET_OPEN
408 static int scsi_low_target_open(struct scsipi_link *, struct cfdata *);
409 #endif  /* SCSI_LOW_TARGET_OPEN */
410 static int scsi_low_scsi_cmd_xs(struct scsipi_xfer *);
411 static int scsi_low_enable_xs(void *, int);
412 static int scsi_low_ioctl_xs(struct scsipi_link *, u_long, caddr_t, int, struct proc *);
413 
414 static int scsi_low_attach_xs(struct scsi_low_softc *);
415 static int scsi_low_world_start_xs(struct scsi_low_softc *);
416 static int scsi_low_dettach_xs(struct scsi_low_softc *);
417 static int scsi_low_ccb_setup_xs(struct scsi_low_softc *, struct slccb *);
418 static int scsi_low_done_xs(struct scsi_low_softc *, struct slccb *);
419 static void scsi_low_timeout_xs(struct scsi_low_softc *, int, int);
420 static u_int scsi_low_translate_quirks_xs(u_int);
421 static void scsi_low_setup_quirks_xs(struct targ_info *, struct lun_info *, u_int);
422 
423 struct scsi_low_osdep_funcs scsi_low_osdep_funcs_xs = {
424         scsi_low_attach_xs,
425         scsi_low_world_start_xs,
426         scsi_low_dettach_xs,
427         scsi_low_ccb_setup_xs,
428         scsi_low_done_xs,
429         scsi_low_timeout_xs
430 };
431         
432 struct scsipi_device scsi_low_dev = {
433         NULL,   /* Use default error handler */
434         NULL,   /* have a queue, served by this */
435         NULL,   /* have no async handler */
436         NULL,   /* Use default 'done' routine */
437 };
438 
439 struct scsi_low_error_code scsi_low_error_code_xs[] = {
440         {0,             XS_NOERROR},
441         {SENSEIO,       XS_SENSE},
442         {BUSYERR,       XS_BUSY },
443         {SELTIMEOUTIO,  XS_SELTIMEOUT},
444         {TIMEOUTIO,     XS_TIMEOUT},
445         {-1,            XS_DRIVER_STUFFUP}
446 };
447 
448 static int
449 scsi_low_ioctl_xs(link, cmd, addr, flag, p)
450         struct scsipi_link *link;
451         u_long cmd;
452         caddr_t addr;
453         int flag;
454         struct proc *p;
455 {
456         struct scsi_low_softc *slp;
457         int s, error = ENOTTY;
458 
459         slp = (struct scsi_low_softc *) link->adapter_softc;
460         if ((slp->sl_flags & HW_INACTIVE) != 0)
461                 return ENXIO;
462 
463         if (cmd == SCBUSIORESET)
464         {
465                 s = SCSI_LOW_SPLSCSI();
466                 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL);
467                 splx(s);
468                 error = 0;
469         }
470         else if (slp->sl_funcs->scsi_low_ioctl != 0)
471         {
472                 error = (*slp->sl_funcs->scsi_low_ioctl)
473                                 (slp, cmd, addr, flag, p);
474         }
475 
476         return error;
477 }
478 
479 static int
480 scsi_low_enable_xs(arg, enable)
481         void *arg;
482         int enable;
483 {
484         struct scsi_low_softc *slp = arg;
485 
486         if (enable != 0)
487         {
488                 if ((slp->sl_flags & HW_INACTIVE) != 0)
489                         return ENXIO;
490         }
491         else
492         {
493                 if ((slp->sl_flags & HW_INACTIVE) != 0 ||
494                     (slp->sl_flags & HW_POWERCTRL) == 0)
495                         return 0;
496 
497                 slp->sl_flags |= HW_POWDOWN;
498                 if (slp->sl_funcs->scsi_low_power != NULL)
499                 {
500                         (*slp->sl_funcs->scsi_low_power)
501                                         (slp, SCSI_LOW_POWDOWN);
502                 }
503         }
504         return 0;
505 }
506 
507 static void
508 scsi_low_scsi_minphys_xs(bp)
509         struct buf *bp;
510 {
511 
512         if (bp->b_bcount > SCSI_LOW_MINPHYS)
513                 bp->b_bcount = SCSI_LOW_MINPHYS;
514         minphys(bp);
515 }
516 
517 static int
518 scsi_low_poll_xs(slp, cb)
519         struct scsi_low_softc *slp;
520         struct slccb *cb;
521 {
522         struct scsipi_xfer *xs = cb->osdep;
523         int tcount;
524 
525         cb->ccb_flags |= CCB_NOSDONE;
526         tcount = 0;
527 
528         while (slp->sl_nio > 0)
529         {
530                 SCSI_LOW_DELAY((1000 * 1000) / SCSI_LOW_XS_POLL_HZ);
531 
532                 (*slp->sl_funcs->scsi_low_poll) (slp);
533 
534                 if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0)
535                 {
536                         cb->ccb_flags |= CCB_NORETRY;
537                         cb->ccb_error |= FATALIO;
538                         (void) scsi_low_revoke_ccb(slp, cb, 1);
539                         printf("%s: hardware inactive in poll mode\n", 
540                                 slp->sl_xname);
541                 }
542 
543                 if ((xs->flags & ITSDONE) != 0)
544                         break;
545 
546                 if (tcount ++ < SCSI_LOW_XS_POLL_HZ / SCSI_LOW_TIMEOUT_HZ)
547                         continue;
548 
549                 tcount = 0;
550                 scsi_low_timeout_check(slp);
551         }
552 
553         xs->flags |= ITSDONE;
554         scsipi_done(xs);
555         return COMPLETE;
556 }
557 
558 static int
559 scsi_low_scsi_cmd_xs(xs)
560         struct scsipi_xfer *xs;
561 {
562         struct scsipi_link *splp = xs->sc_link;
563         struct scsi_low_softc *slp = splp->adapter_softc;
564         struct targ_info *ti;
565         struct lun_info *li;
566         struct slccb *cb;
567         int s, targ, lun, flags, rv;
568 
569         if ((cb = SCSI_LOW_ALLOC_CCB(xs->flags & SCSI_NOSLEEP)) == NULL)
570                 return TRY_AGAIN_LATER;
571 
572         targ = splp->scsipi_scsi.target,
573         lun = splp->scsipi_scsi.lun;
574         ti = slp->sl_ti[targ];
575 
576         cb->osdep = xs;
577         cb->bp = xs->bp;
578 
579         if ((xs->flags & SCSI_POLL) == 0)
580                 flags = CCB_AUTOSENSE;
581         else
582                 flags = CCB_AUTOSENSE | CCB_POLLED;
583                 
584 
585         s = SCSI_LOW_SPLSCSI();
586         li = scsi_low_alloc_li(ti, lun, 1);
587         if ((u_int) splp->quirks != li->li_sloi.sloi_quirks)
588         {
589                 scsi_low_setup_quirks_xs(ti, li, (u_int) splp->quirks);
590         }
591 
592         if ((xs->flags & SCSI_RESET) != 0)
593         {
594                 flags |= CCB_NORETRY | CCB_URGENT;
595                 scsi_low_enqueue(slp, ti, li, cb, flags, SCSI_LOW_MSG_RESET);
596         }
597         else
598         {
599                 if (ti->ti_setup_msg != 0)
600                 {
601                         scsi_low_message_enqueue(slp, ti, li, flags);
602                 }
603 
604                 flags |= CCB_SCSIIO;
605                 scsi_low_enqueue(slp, ti, li, cb, flags, 0);
606         }
607 
608 #ifdef  SCSI_LOW_DEBUG
609         if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, ti->ti_id) != 0)
610         {
611                 scsi_low_test_abort(slp, ti, li);
612         }
613 #endif  /* SCSI_LOW_DEBUG */
614 
615         if ((cb->ccb_flags & CCB_POLLED) != 0)
616         {
617                 rv = scsi_low_poll_xs(slp, cb);
618         }
619         else
620         {
621                 rv = SUCCESSFULLY_QUEUED;
622         }
623         splx(s);
624         return rv;
625 }
626 
627 static int
628 scsi_low_attach_xs(slp)
629         struct scsi_low_softc *slp;
630 {
631         struct scsipi_adapter *sap;
632         struct scsipi_link *splp;
633 
634         strncpy(slp->sl_xname, slp->sl_dev.dv_xname, 16);
635 
636         sap = SCSI_LOW_MALLOC(sizeof(*sap));
637         if (sap == NULL)
638                 return ENOMEM;
639         splp = SCSI_LOW_MALLOC(sizeof(*splp));
640         if (splp == NULL)
641                 return ENOMEM;
642 
643         SCSI_LOW_BZERO(sap, sizeof(*sap));
644         SCSI_LOW_BZERO(splp, sizeof(*splp));
645 
646         sap->scsipi_cmd = scsi_low_scsi_cmd_xs;
647         sap->scsipi_minphys = scsi_low_scsi_minphys_xs;
648         sap->scsipi_enable = scsi_low_enable_xs;
649         sap->scsipi_ioctl = scsi_low_ioctl_xs;
650 #ifdef  SCSI_LOW_TARGET_OPEN
651         sap->open_target_lu = scsi_low_target_open;
652 #endif  /* SCSI_LOW_TARGET_OPEN */
653 
654         splp->adapter_softc = slp;
655         splp->scsipi_scsi.adapter_target = slp->sl_hostid;
656         splp->scsipi_scsi.max_target = slp->sl_ntargs - 1;
657         splp->scsipi_scsi.max_lun = slp->sl_nluns - 1;
658         splp->scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
659         splp->openings = slp->sl_openings;
660         splp->type = BUS_SCSI;
661         splp->adapter_softc = slp;
662         splp->adapter = sap;
663         splp->device = &scsi_low_dev;
664 
665         slp->sl_si.si_splp = splp;
666         slp->sl_show_result = SHOW_ALL_NEG;
667         return 0;
668 }
669 
670 static int
671 scsi_low_world_start_xs(slp)
672         struct scsi_low_softc *slp;
673 {
674 
675         return 0;
676 }
677 
678 static int
679 scsi_low_dettach_xs(slp)
680         struct scsi_low_softc *slp;
681 {
682 
683         /*
684          * scsipi does not have dettach bus fucntion.
685          *
686         scsipi_dettach_scsibus(slp->sl_si.si_splp);
687         */
688         return 0;
689 }
690 
691 static int
692 scsi_low_ccb_setup_xs(slp, cb)
693         struct scsi_low_softc *slp;
694         struct slccb *cb;
695 {
696         struct scsipi_xfer *xs = (struct scsipi_xfer *) cb->osdep;
697 
698         if ((cb->ccb_flags & CCB_SCSIIO) != 0)
699         {
700                 cb->ccb_scp.scp_cmd = (u_int8_t *) xs->cmd;
701                 cb->ccb_scp.scp_cmdlen = xs->cmdlen;
702                 cb->ccb_scp.scp_data = xs->data;
703                 cb->ccb_scp.scp_datalen = xs->datalen;
704                 cb->ccb_scp.scp_direction = (xs->flags & SCSI_DATA_OUT) ? 
705                                         SCSI_LOW_WRITE : SCSI_LOW_READ;
706                 cb->ccb_tcmax = xs->timeout / 1000;
707         }
708         else
709         {
710                 scsi_low_unit_ready_cmd(cb);
711         }
712         return SCSI_LOW_START_QTAG;
713 }
714 
715 static int
716 scsi_low_done_xs(slp, cb)
717         struct scsi_low_softc *slp;
718         struct slccb *cb;
719 {
720         struct scsipi_xfer *xs;
721 
722         xs = (struct scsipi_xfer *) cb->osdep;
723         if (cb->ccb_error == 0)
724         {
725                 xs->error = XS_NOERROR;
726                 xs->resid = 0;
727         }
728         else    
729         {
730                 if (cb->ccb_rcnt >= slp->sl_max_retry)
731                         cb->ccb_error |= ABORTIO;
732 
733                 if ((cb->ccb_flags & CCB_NORETRY) == 0 &&
734                     (cb->ccb_error & ABORTIO) == 0)
735                         return EJUSTRETURN;
736 
737                 if ((cb->ccb_error & SENSEIO) != 0)
738                 {
739                         xs->sense.scsi_sense = cb->ccb_sense;
740                 }
741 
742                 xs->error = scsi_low_translate_error_code(cb,
743                                 &scsi_low_error_code_xs[0]);
744         
745 #ifdef  SCSI_LOW_DIAGNOSTIC
746                 if ((cb->ccb_flags & CCB_SILENT) == 0 &&
747                     cb->ccb_scp.scp_cmdlen > 0 &&
748                     (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] &
749                      SCSI_LOW_CMD_ABORT_WARNING) != 0)
750                 {
751                         printf("%s: WARNING: scsi_low IO abort\n",
752                                 slp->sl_xname);
753                         scsi_low_print(slp, NULL);
754                 }
755 #endif  /* SCSI_LOW_DIAGNOSTIC */
756         }
757 
758         if (cb->ccb_scp.scp_status == ST_UNKNOWN)
759                 xs->status = 0; /* XXX */
760         else
761                 xs->status = cb->ccb_scp.scp_status;
762 
763         xs->flags |= ITSDONE;
764         if ((cb->ccb_flags & CCB_NOSDONE) == 0)
765                 scsipi_done(xs);
766 
767         return 0;
768 }
769 
770 static void
771 scsi_low_timeout_xs(slp, ch, action)
772         struct scsi_low_softc *slp;
773         int ch;
774         int action;
775 {
776 
777         switch (ch)
778         {
779         case SCSI_LOW_TIMEOUT_CH_IO:
780                 switch (action)
781                 {
782                 case SCSI_LOW_TIMEOUT_START:
783                         timeout(scsi_low_timeout, slp,
784                                 hz / SCSI_LOW_TIMEOUT_HZ);
785                         break;
786                 case SCSI_LOW_TIMEOUT_STOP:
787                         untimeout(scsi_low_timeout, slp);
788                         break;
789                 }
790                 break;
791 
792         case SCSI_LOW_TIMEOUT_CH_ENGAGE:
793                 switch (action)
794                 {
795                 case SCSI_LOW_TIMEOUT_START:
796                         timeout(scsi_low_engage, slp, 1);
797                         break;
798                 case SCSI_LOW_TIMEOUT_STOP:
799                         untimeout(scsi_low_engage, slp);
800                         break;
801                 }
802                 break;
803 
804         case SCSI_LOW_TIMEOUT_CH_RECOVER:
805                 break;
806         }
807 }
808 
809 u_int
810 scsi_low_translate_quirks_xs(quirks)
811         u_int quirks;
812 {
813         u_int flags;
814         
815         flags = SCSI_LOW_DISK_LFLAGS | SCSI_LOW_DISK_TFLAGS;
816 
817 #ifdef  SDEV_NODISC
818         if (quirks & SDEV_NODISC)
819                 flags &= ~SCSI_LOW_DISK_DISC;
820 #endif  /* SDEV_NODISC */
821 #ifdef  SDEV_NOPARITY
822         if (quirks & SDEV_NOPARITY)
823                 flags &= ~SCSI_LOW_DISK_PARITY;
824 #endif  /* SDEV_NOPARITY */
825 #ifdef  SDEV_NOCMDLNK
826         if (quirks & SDEV_NOCMDLNK)
827                 flags &= ~SCSI_LOW_DISK_LINK;
828 #endif  /* SDEV_NOCMDLNK */
829 #ifdef  SDEV_NOTAG
830         if (quirks & SDEV_NOTAG)
831                 flags &= ~SCSI_LOW_DISK_QTAG;
832 #endif  /* SDEV_NOTAG */
833 #ifdef  SDEV_NOSYNC
834         if (quirks & SDEV_NOSYNC)
835                 flags &= ~SCSI_LOW_DISK_SYNC;
836 #endif  /* SDEV_NOSYNC */
837 
838         return flags;
839 }
840 
841 static void
842 scsi_low_setup_quirks_xs(ti, li, flags)
843         struct targ_info *ti;
844         struct lun_info *li;
845         u_int flags;
846 {
847         u_int quirks;
848 
849         li->li_sloi.sloi_quirks = flags;
850         quirks = scsi_low_translate_quirks_xs(flags);
851         ti->ti_quirks = quirks & SCSI_LOW_DISK_TFLAGS;
852         li->li_quirks = quirks & SCSI_LOW_DISK_LFLAGS;
853         ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID;
854         li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID;
855         scsi_low_calcf_target(ti);
856         scsi_low_calcf_lun(li);
857         scsi_low_calcf_show(li);
858 }
859 
860 #ifdef  SCSI_LOW_TARGET_OPEN
861 static int
862 scsi_low_target_open(link, cf)
863         struct scsipi_link *link;
864         struct cfdata *cf;
865 {
866         u_int target = link->scsipi_scsi.target;
867         u_int lun = link->scsipi_scsi.lun;
868         struct scsi_low_softc *slp;
869         struct targ_info *ti;
870         struct lun_info *li;
871 
872         slp = (struct scsi_low_softc *) link->adapter_softc;
873         ti = slp->sl_ti[target];
874         li = scsi_low_alloc_li(ti, lun, 0);
875         if (li == NULL)
876                 return 0;
877 
878         li->li_cfgflags = cf->cf_flags;
879         scsi_low_setup_quirks_xs(ti, li, (u_int) link->quirks);
880         return 0;
881 }
882 #endif  /* SCSI_LOW_TARGET_OPEN */
883 
884 #endif  /* SCSI_LOW_INTERFACE_XS */
885 
886 #ifdef SCSI_LOW_INTERFACE_CAM
887 /**************************************************************
888  * SCSI INTERFACE (CAM)
889  **************************************************************/
890 #define SCSI_LOW_MALLOC(size)           malloc((size), M_SCSILOW, M_NOWAIT)
891 #define SCSI_LOW_FREE(pt)               free((pt), M_SCSILOW)
892 #define SCSI_LOW_ALLOC_CCB(flags)       scsi_low_get_ccb()
893 
894 static void scsi_low_poll_cam(struct cam_sim *);
895 static void scsi_low_cam_rescan_callback(struct cam_periph *, union ccb *);
896 static void scsi_low_rescan_bus_cam(struct scsi_low_softc *);
897 void scsi_low_scsi_action_cam(struct cam_sim *, union ccb *);
898 
899 static int scsi_low_attach_cam(struct scsi_low_softc *);
900 static int scsi_low_world_start_cam(struct scsi_low_softc *);
901 static int scsi_low_dettach_cam(struct scsi_low_softc *);
902 static int scsi_low_ccb_setup_cam(struct scsi_low_softc *, struct slccb *);
903 static int scsi_low_done_cam(struct scsi_low_softc *, struct slccb *);
904 static void scsi_low_timeout_cam(struct scsi_low_softc *, int, int);
905 
906 struct scsi_low_osdep_funcs scsi_low_osdep_funcs_cam = {
907         scsi_low_attach_cam,
908         scsi_low_world_start_cam,
909         scsi_low_dettach_cam,
910         scsi_low_ccb_setup_cam,
911         scsi_low_done_cam,
912         scsi_low_timeout_cam
913 };
914         
915 struct scsi_low_error_code scsi_low_error_code_cam[] = {
916         {0,                     CAM_REQ_CMP},
917         {SENSEIO,               CAM_AUTOSNS_VALID | CAM_REQ_CMP_ERR},
918         {SENSEERR,              CAM_AUTOSENSE_FAIL},
919         {UACAERR,               CAM_SCSI_STATUS_ERROR},
920         {BUSYERR | STATERR,     CAM_SCSI_STATUS_ERROR},
921         {SELTIMEOUTIO,          CAM_SEL_TIMEOUT},       
922         {TIMEOUTIO,             CAM_CMD_TIMEOUT},
923         {PDMAERR,               CAM_DATA_RUN_ERR},
924         {PARITYERR,             CAM_UNCOR_PARITY},
925         {UBFERR,                CAM_UNEXP_BUSFREE},
926         {ABORTIO,               CAM_REQ_ABORTED},
927         {-1,                    CAM_UNREC_HBA_ERROR}
928 };
929 
930 #define SIM2SLP(sim)    ((struct scsi_low_softc *) cam_sim_softc((sim)))
931 
932 /* XXX:
933  * Please check a polling hz, currently we assume scsi_low_poll() is
934  * called each 1 ms.
935  */
936 #define SCSI_LOW_CAM_POLL_HZ    1000    /* OK ? */
937 
938 static void
939 scsi_low_poll_cam(sim)
940         struct cam_sim *sim;
941 {
942         struct scsi_low_softc *slp = SIM2SLP(sim);
943 
944         (*slp->sl_funcs->scsi_low_poll) (slp);
945 
946         if (slp->sl_si.si_poll_count ++ >= 
947             SCSI_LOW_CAM_POLL_HZ / SCSI_LOW_TIMEOUT_HZ)
948         {
949                 slp->sl_si.si_poll_count = 0;
950                 scsi_low_timeout_check(slp);
951         }
952 }
953 
954 static void
955 scsi_low_cam_rescan_callback(periph, ccb)
956         struct cam_periph *periph;
957         union ccb *ccb;
958 {
959 
960         xpt_free_path(ccb->ccb_h.path);
961         xpt_free_ccb(ccb);
962 }
963 
964 static void
965 scsi_low_rescan_bus_cam(slp)
966         struct scsi_low_softc *slp;
967 {
968         struct cam_path *path;
969         union ccb *ccb = xpt_alloc_ccb();
970         cam_status status;
971 
972         bzero(ccb, sizeof(union ccb));
973 
974         status = xpt_create_path(&path, xpt_periph,
975                                  cam_sim_path(slp->sl_si.sim), -1, 0);
976         if (