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