1 /* $NetBSD: scsipiconf.h,v 1.28 1998/12/17 13:05:06 bouyer Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Originally written by Julian Elischer (julian@tfs.com) 41 * for TRW Financial Systems for use under the MACH(2.5) operating system. 42 * 43 * TRW Financial Systems, in accordance with their agreement with Carnegie 44 * Mellon University, makes this software available to CMU to distribute 45 * or use in any manner that they see fit as long as this message is kept with 46 * the software. For this reason TFS also grants any other persons or 47 * organisations permission to use or modify this software. 48 * 49 * TFS supplies this software to be publicly redistributed 50 * on the understanding that TFS is not responsible for the correct 51 * functioning of this software in any circumstances. 52 * 53 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 54 */ 55 56 #ifndef _DEV_SCSIPI_SCSIPICONF_H_ 57 #define _DEV_SCSIPI_SCSIPICONF_H_ 58 59 typedef int boolean; 60 61 #include <sys/queue.h> 62 #include <machine/cpu.h> 63 #include <dev/scsipi/scsipi_debug.h> 64 65 /* 66 * The following documentation tries to describe the relationship between the 67 * various structures defined in this file: 68 * 69 * each adapter type has a scsipi_adapter struct. This describes the adapter 70 * and identifies routines that can be called to use the adapter. 71 * each device type has a scsipi_device struct. This describes the device and 72 * identifies routines that can be called to use the device. 73 * each existing device position (scsibus + target + lun or atapibus + drive) 74 * can be described by a scsipi_link struct. 75 * Only scsipi positions that actually have devices, have a scsipi_link 76 * structure assigned. so in effect each device has scsipi_link struct. 77 * The scsipi_link structure contains information identifying both the 78 * device driver and the adapter driver for that position on that scsipi 79 * bus, and can be said to 'link' the two. 80 * each individual scsipi bus has an array that points to all the scsipi_link 81 * structs associated with that scsipi bus. Slots with no device have 82 * a NULL pointer. 83 * each individual device also knows the address of it's own scsipi_link 84 * structure. 85 * 86 * ------------- 87 * 88 * The key to all this is the scsipi_link structure which associates all the 89 * other structures with each other in the correct configuration. The 90 * scsipi_link is the connecting information that allows each part of the 91 * scsipi system to find the associated other parts. 92 */ 93 94 struct buf; 95 struct proc; 96 struct scsipi_link; 97 struct scsipi_xfer; 98 99 struct scsipi_generic { 100 u_int8_t opcode; 101 u_int8_t bytes[15]; 102 }; 103 104 105 /* 106 * return values for scsipi_cmd() 107 */ 108 #define SUCCESSFULLY_QUEUED 0 109 #define TRY_AGAIN_LATER 1 110 #define COMPLETE 2 111 #define ESCAPE_NOT_SUPPORTED 3 112 113 /* 114 * Device Specific Sense Handlers return either an errno 115 * or one of these three items. 116 */ 117 118 #define SCSIRET_NOERROR 0 /* No Error */ 119 #define SCSIRET_RETRY -1 /* Retry the command that got this sense */ 120 #define SCSIRET_CONTINUE -2 /* Continue with standard sense processing */ 121 122 /* 123 * These entry points are called by the low-end drivers to get services from 124 * whatever high-end drivers they are attached to. Each device type has one 125 * of these statically allocated. 126 */ 127 struct scsipi_device { 128 int (*err_handler) __P((struct scsipi_xfer *)); 129 /* returns -1 to say err processing done */ 130 void (*start) __P((void *)); 131 132 int (*async) __P((void)); 133 /* 134 * When called with `0' as the second argument, we expect status 135 * back from the upper-level driver. When called with a `1', 136 * we're simply notifying the upper-level driver that the command 137 * is complete and expect no status back. 138 */ 139 void (*done) __P((struct scsipi_xfer *)); 140 }; 141 142 /* 143 * These entrypoints are called by the high-end drivers to get services from 144 * whatever low-end drivers they are attached to. Each adapter instance has 145 * one of these. 146 * 147 * scsipi_cmd required 148 * scsipi_minphys required 149 * scsipi_ioctl optional 150 * scsipi_enable optional 151 */ 152 struct scsipi_adapter { 153 int scsipi_refcnt; 154 int (*scsipi_cmd) __P((struct scsipi_xfer *)); 155 void (*scsipi_minphys) __P((struct buf *)); 156 int (*scsipi_ioctl) __P((struct scsipi_link *, u_long, 157 caddr_t, int, struct proc *)); 158 int (*scsipi_enable) __P((void *, int)); 159 }; 160 161 /* 162 * This structure describes the connection between an adapter driver and 163 * a device driver, and is used by each to call services provided by 164 * the other, and to allow generic scsipi glue code to call these services 165 * as well. 166 * 167 * XXX Given the way NetBSD's autoconfiguration works, this is ... 168 * XXX nasty. 169 */ 170 171 struct scsipi_link { 172 u_int8_t type; /* device type, i.e. SCSI, ATAPI, ...*/ 173 #define BUS_SCSI 0 174 #define BUS_ATAPI 1 175 u_int8_t openings; /* available operations */ 176 u_int8_t active; /* operations in progress */ 177 int flags; /* flags that all devices have */ 178 #define SDEV_REMOVABLE 0x01 /* media is removable */ 179 #define SDEV_MEDIA_LOADED 0x02 /* device figures are still valid */ 180 #define SDEV_WAITING 0x04 /* a process is waiting for this */ 181 #define SDEV_OPEN 0x08 /* at least 1 open session */ 182 #define SDEV_DBX 0xf0 /* debuging flags (scsipi_debug.h) */ 183 #define SDEV_WAITDRAIN 0x100 /* waiting for pending_xfers to drain */ 184 u_int16_t quirks; /* per-device oddities */ 185 #define SDEV_AUTOSAVE 0x0001 /* 186 * Do implicit SAVEDATAPOINTER on 187 * disconnect (ancient). 188 */ 189 #define SDEV_NOSYNC 0x0002 /* does not grok SDTR */ 190 #define SDEV_NOWIDE 0x0004 /* does not grok WDTR */ 191 #define SDEV_NOTAG 0x0008 /* does not do command tagging */ 192 #define SDEV_NOLUNS 0x0010 /* does not grok LUNs */ 193 #define SDEV_FORCELUNS 0x0020 /* prehistoric drive/ctlr groks LUNs */ 194 #define SDEV_NOMODESENSE 0x0040 /* removable media/optical drives */ 195 #define SDEV_NOSTARTUNIT 0x0080 /* 196 * Do not issue START UNIT 197 * requests in sd.c 198 */ 199 #define SDEV_NOSYNCCACHE 0x0100 /* does not grok SYNCHRONIZE CACHE */ 200 #define ADEV_CDROM 0x0200 /* device is a CD-ROM */ 201 #define ADEV_LITTLETOC 0x0400 /* Audio TOC uses wrong byte order */ 202 #define ADEV_NOCAPACITY 0x0800 /* no READ_CD_CAPACITY command */ 203 #define ADEV_NOTUR 0x1000 /* no TEST_UNIT_READY command */ 204 #define ADEV_NODOORLOCK 0x2000 /* device can't lock door */ 205 #define ADEV_NOSENSE 0x4000 /* device can't handle request sense */ 206 207 struct scsipi_device *device; /* device entry points etc. */ 208 void *device_softc; /* needed for call to foo_start */ 209 struct scsipi_adapter *adapter;/* adapter entry points etc. */ 210 void *adapter_softc; /* needed for call to foo_scsipi_cmd */ 211 union { /* needed for call to foo_scsipi_cmd */ 212 struct scsi_link { 213 int channel; /* channel, i.e. bus # on controller */ 214 215 u_int8_t scsi_version; /* SCSI-I, SCSI-II, etc. */ 216 u_int8_t scsibus; /* the Nth scsibus */ 217 u_int8_t target; /* targ of this dev */ 218 u_int8_t lun; /* lun of this dev */ 219 u_int8_t adapter_target;/* what are we on the scsi 220 bus */ 221 int16_t max_target; /* XXX max target supported 222 by adapter (inclusive) */ 223 int16_t max_lun; /* XXX number of luns supported 224 by adapter (inclusive) */ 225 } scsipi_scsi; 226 struct atapi_link { 227 u_int8_t drive; /* drive number on the bus */ 228 u_int8_t channel; /* channel, i.e. bus # on 229 controller */ 230 u_int8_t atapibus; 231 u_int8_t cap; /* drive capability */ 232 #define ACAP_DRQ_MPROC 0x0000 /* microprocessor DRQ */ 233 #define ACAP_DRQ_INTR 0x0200 /* interrupt DRQ */ 234 #define ACAP_DRQ_ACCEL 0x0400 /* accelerated DRQ */ 235 #define ACAP_DRQ_MASK 0x0600 /* same as in ataparams */ 236 #define ACAP_LEN 0x0100 /* 16 bit commands */ 237 } scsipi_atapi; 238 } _scsipi_link; 239 TAILQ_HEAD(, scsipi_xfer) pending_xfers; 240 int (*scsipi_cmd) __P((struct scsipi_link *, struct scsipi_generic *, 241 int cmdlen, u_char *data_addr, int datalen, int retries, 242 int timeout, struct buf *bp, int flags)); 243 int (*scsipi_interpret_sense) __P((struct scsipi_xfer *)); 244 void (*sc_print_addr) __P((struct scsipi_link *sc_link)); 245 }; 246 #define scsipi_scsi _scsipi_link.scsipi_scsi 247 #define scsipi_atapi _scsipi_link.scsipi_atapi 248 249 /* 250 * Each scsipi transaction is fully described by one of these structures 251 * It includes information about the source of the command and also the 252 * device and adapter for which the command is destined. 253 * (via the scsipi_link structure) 254 * 255 * The adapter_q member may be used by host adapter drivers to queue 256 * requests, if necessary. 257 * 258 * The device_q member is maintained by the scsipi middle layer. When 259 * a device issues a command, the xfer is placed on that device's 260 * pending commands queue. When an xfer is done and freed, it is taken 261 * off the device's queue. This allows for a device to wait for all of 262 * its pending commands to complete. 263 */ 264 struct scsipi_xfer { 265 TAILQ_ENTRY(scsipi_xfer) adapter_q; /* queue entry for use by adapter */ 266 TAILQ_ENTRY(scsipi_xfer) device_q; /* device's pending xfers */ 267 volatile int flags; /* 0x00ff0000 reserved for ATAPI */ 268 struct scsipi_link *sc_link; /* all about our device and adapter */ 269 int retries; /* the number of times to retry */ 270 int timeout; /* in milliseconds */ 271 struct scsipi_generic *cmd; /* The scsipi command to execute */ 272 int cmdlen; /* how long it is */ 273 u_char *data; /* dma address OR a uio address */ 274 int datalen; /* data len (blank if uio) */ 275 int resid; /* how much buffer was not touched */ 276 int error; /* an error value */ 277 struct buf *bp; /* If we need to associate with */ 278 /* a buf */ 279 union { 280 struct scsipi_sense_data scsi_sense; /* 32 bytes */ 281 u_int32_t atapi_sense; 282 } sense; 283 /* 284 * Believe it or not, Some targets fall on the ground with 285 * anything but a certain sense length. 286 */ 287 int req_sense_length; /* Explicit request sense length */ 288 u_int8_t status; /* SCSI status */ 289 struct scsipi_generic cmdstore 290 __attribute__ ((aligned (4)));/* stash the command in here */ 291 }; 292 293 /* 294 * Per-request Flag values 295 */ 296 #define SCSI_NOSLEEP 0x0001 /* don't sleep */ 297 #define SCSI_POLL 0x0002 /* poll for completion */ 298 #define SCSI_AUTOCONF (SCSI_NOSLEEP | SCSI_POLL) 299 #define SCSI_USER 0x0004 /* Is a user cmd, call scsipi_user_done */ 300 #define ITSDONE 0x0008 /* the transfer is as done as it gets */ 301 #define INUSE 0x0010 /* The scsipi_xfer block is in use */ 302 #define SCSI_SILENT 0x0020 /* don't announce NOT READY or MEDIA CHANGE */ 303 #define SCSI_IGNORE_NOT_READY 0x0040 /* ignore NOT READY */ 304 #define SCSI_IGNORE_MEDIA_CHANGE 0x0080 /* ignore MEDIA CHANGE */ 305 #define SCSI_IGNORE_ILLEGAL_REQUEST 0x0100 /* ignore ILLEGAL REQUEST */ 306 #define SCSI_RESET 0x0200 /* Reset the device in question */ 307 #define SCSI_DATA_UIO 0x0400 /* The data address refers to a UIO */ 308 #define SCSI_DATA_IN 0x0800 /* expect data to come INTO memory */ 309 #define SCSI_DATA_OUT 0x1000 /* expect data to flow OUT of memory */ 310 #define SCSI_TARGET 0x2000 /* This defines a TARGET mode op. */ 311 #define SCSI_ESCAPE 0x4000 /* Escape operation */ 312 #define SCSI_URGENT 0x8000 /* Urgent operation (e.g., HTAG) */ 313 /* 0x00ff0000 reserved for ATAPI. */ 314 315 /* 316 * Error values an adapter driver may return 317 */ 318 #define XS_NOERROR 0 /* there is no error, (sense is invalid) */ 319 #define XS_SENSE 1 /* Check the returned sense for the error */ 320 #define XS_SHORTSENSE 2 /* Check the ATAPI sense for the error */ 321 #define XS_DRIVER_STUFFUP 3 /* Driver failed to perform operation */ 322 #define XS_SELTIMEOUT 4 /* The device timed out.. turned off? */ 323 #define XS_TIMEOUT 5 /* The Timeout reported was caught by SW */ 324 #define XS_BUSY 7 /* The device busy, try again later? */ 325 #define XS_RESET 8 /* bus was reset; possible retry command */ 326 327 /* 328 * This describes matching information for scsipi_inqmatch(). The more things 329 * match, the higher the configuration priority. 330 */ 331 struct scsipi_inquiry_pattern { 332 u_int8_t type; 333 boolean removable; 334 char *vendor; 335 char *product; 336 char *revision; 337 }; 338 339 /* 340 * This is used to pass information from the high-level configuration code 341 * to the device-specific drivers. 342 */ 343 344 struct scsipibus_attach_args { 345 struct scsipi_link *sa_sc_link; 346 struct scsipi_inquiry_pattern sa_inqbuf; 347 union { /* bus-type specific infos */ 348 u_int8_t scsi_version; /* SCSI version */ 349 } scsipi_info; 350 }; 351 352 /* 353 * this describes a quirk entry 354 */ 355 356 struct scsi_quirk_inquiry_pattern { 357 struct scsipi_inquiry_pattern pattern; 358 u_int16_t quirks; 359 }; 360 361 /* 362 * Macro to issue a SCSI command. Treat it like a function: 363 * 364 * int scsipi_command __P((struct scsipi_link *link, 365 * struct scsipi_generic *scsipi_cmd, int cmdlen, 366 * u_char *data_addr, int datalen, int retries, 367 * int timeout, struct buf *bp, int flags)); 368 */ 369 #define scsipi_command(l, c, cl, da, dl, r, t, b, f) \ 370 (*(l)->scsipi_cmd)((l), (c), (cl), (da), (dl), (r), (t), (b), (f)) 371 372 /* 373 * Similar, but invoke the controller directly with a scsipi_xfer. 374 */ 375 #define scsipi_command_direct(xs) \ 376 (*(xs)->sc_link->adapter->scsipi_cmd)((xs)) 377 378 379 /* 380 * Macro to test whether a request will complete asynchronously. 381 */ 382 #define SCSIPI_XFER_ASYNC(xs) \ 383 ((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP) 384 385 #ifdef _KERNEL 386 void scsipi_init __P((void)); 387 caddr_t scsipi_inqmatch __P((struct scsipi_inquiry_pattern *, caddr_t, 388 int, int, int *)); 389 char *scsipi_dtype __P((int)); 390 void scsipi_strvis __P((u_char *, int, u_char *, int)); 391 int scsipi_execute_xs __P((struct scsipi_xfer *)); 392 u_long scsipi_size __P((struct scsipi_link *, int)); 393 int scsipi_test_unit_ready __P((struct scsipi_link *, int)); 394 int scsipi_prevent __P((struct scsipi_link *, int, int)); 395 int scsipi_inquire __P((struct scsipi_link *, 396 struct scsipi_inquiry_data *, int)); 397 int scsipi_start __P((struct scsipi_link *, int, int)); 398 void scsipi_done __P((struct scsipi_xfer *)); 399 void scsipi_user_done __P((struct scsipi_xfer *)); 400 int scsipi_interpret_sense __P((struct scsipi_xfer *)); 401 void scsipi_wait_drain __P((struct scsipi_link *)); 402 #ifdef SCSIVERBOSE 403 void scsipi_print_sense __P((struct scsipi_xfer *, int)); 404 void scsipi_print_sense_data __P((struct scsipi_sense_data *, int)); 405 char *scsipi_decode_sense __P((void *, int)); 406 #endif 407 int scsipi_do_ioctl __P((struct scsipi_link *, dev_t, u_long, caddr_t, 408 int, struct proc *)); 409 410 int scsipi_adapter_addref __P((struct scsipi_link *)); 411 void scsipi_adapter_delref __P((struct scsipi_link *)); 412 413 void show_scsipi_xs __P((struct scsipi_xfer *)); 414 void show_scsipi_cmd __P((struct scsipi_xfer *)); 415 void show_mem __P((u_char *, int)); 416 #endif /* _KERNEL */ 417 418 static __inline void _lto2b __P((u_int32_t val, u_int8_t *bytes)) 419 __attribute__ ((unused)); 420 static __inline void _lto3b __P((u_int32_t val, u_int8_t *bytes)) 421 __attribute__ ((unused)); 422 static __inline void _lto4b __P((u_int32_t val, u_int8_t *bytes)) 423 __attribute__ ((unused)); 424 static __inline u_int32_t _2btol __P((const u_int8_t *bytes)) 425 __attribute__ ((unused)); 426 static __inline u_int32_t _3btol __P((const u_int8_t *bytes)) 427 __attribute__ ((unused)); 428 static __inline u_int32_t _4btol __P((const u_int8_t *bytes)) 429 __attribute__ ((unused)); 430 431 static __inline void _lto2l __P((u_int32_t val, u_int8_t *bytes)) 432 __attribute__ ((unused)); 433 static __inline void _lto3l __P((u_int32_t val, u_int8_t *bytes)) 434 __attribute__ ((unused)); 435 static __inline void _lto4l __P((u_int32_t val, u_int8_t *bytes)) 436 __attribute__ ((unused)); 437 static __inline u_int32_t _2ltol __P((const u_int8_t *bytes)) 438 __attribute__ ((unused)); 439 static __inline u_int32_t _3ltol __P((const u_int8_t *bytes)) 440 __attribute__ ((unused)); 441 static __inline u_int32_t _4ltol __P((const u_int8_t *bytes)) 442 __attribute__ ((unused)); 443 static __inline void bswap __P((char *, int)) 444 __attribute__ ((unused)); 445 446 static __inline void 447 _lto2b(val, bytes) 448 u_int32_t val; 449 u_int8_t *bytes; 450 { 451 452 bytes[0] = (val >> 8) & 0xff; 453 bytes[1] = val & 0xff; 454 } 455 456 static __inline void 457 _lto3b(val, bytes) 458 u_int32_t val; 459 u_int8_t *bytes; 460 { 461 462 bytes[0] = (val >> 16) & 0xff; 463 bytes[1] = (val >> 8) & 0xff; 464 bytes[2] = val & 0xff; 465 } 466 467 static __inline void 468 _lto4b(val, bytes) 469 u_int32_t val; 470 u_int8_t *bytes; 471 { 472 473 bytes[0] = (val >> 24) & 0xff; 474 bytes[1] = (val >> 16) & 0xff; 475 bytes[2] = (val >> 8) & 0xff; 476 bytes[3] = val & 0xff; 477 } 478 479 static __inline u_int32_t 480 _2btol(bytes) 481 const u_int8_t *bytes; 482 { 483 register u_int32_t rv; 484 485 rv = (bytes[0] << 8) | 486 bytes[1]; 487 return (rv); 488 } 489 490 static __inline u_int32_t 491 _3btol(bytes) 492 const u_int8_t *bytes; 493 { 494 register u_int32_t rv; 495 496 rv = (bytes[0] << 16) | 497 (bytes[1] << 8) | 498 bytes[2]; 499 return (rv); 500 } 501 502 static __inline u_int32_t 503 _4btol(bytes) 504 const u_int8_t *bytes; 505 { 506 register u_int32_t rv; 507 508 rv = (bytes[0] << 24) | 509 (bytes[1] << 16) | 510 (bytes[2] << 8) | 511 bytes[3]; 512 return (rv); 513 } 514 515 static __inline void 516 _lto2l(val, bytes) 517 u_int32_t val; 518 u_int8_t *bytes; 519 { 520 521 bytes[0] = val & 0xff; 522 bytes[1] = (val >> 8) & 0xff; 523 } 524 525 static __inline void 526 _lto3l(val, bytes) 527 u_int32_t val; 528 u_int8_t *bytes; 529 { 530 531 bytes[0] = val & 0xff; 532 bytes[1] = (val >> 8) & 0xff; 533 bytes[2] = (val >> 16) & 0xff; 534 } 535 536 static __inline void 537 _lto4l(val, bytes) 538 u_int32_t val; 539 u_int8_t *bytes; 540 { 541 542 bytes[0] = val & 0xff; 543 bytes[1] = (val >> 8) & 0xff; 544 bytes[2] = (val >> 16) & 0xff; 545 bytes[3] = (val >> 24) & 0xff; 546 } 547 548 static __inline u_int32_t 549 _2ltol(bytes) 550 const u_int8_t *bytes; 551 { 552 register u_int32_t rv; 553 554 rv = bytes[0] | 555 (bytes[1] << 8); 556 return (rv); 557 } 558 559 static __inline u_int32_t 560 _3ltol(bytes) 561 const u_int8_t *bytes; 562 { 563 register u_int32_t rv; 564 565 rv = bytes[0] | 566 (bytes[1] << 8) | 567 (bytes[2] << 16); 568 return (rv); 569 } 570 571 static __inline u_int32_t 572 _4ltol(bytes) 573 const u_int8_t *bytes; 574 { 575 register u_int32_t rv; 576 577 rv = bytes[0] | 578 (bytes[1] << 8) | 579 (bytes[2] << 16) | 580 (bytes[3] << 24); 581 return (rv); 582 } 583 584 static __inline void 585 bswap (buf, len) 586 char *buf; 587 int len; 588 { 589 u_int16_t *p = (u_int16_t *)(buf + len); 590 591 while (--p >= (u_int16_t *)buf) 592 *p = (*p & 0xff) << 8 | (*p >> 8 & 0xff); 593 } 594 595 #endif /* _DEV_SCSIPI_SCSIPICONF_H_ */ 596