| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /************************************************************************** |
| 2 | ** | |
| 3 | ** $FreeBSD: src/sys/pci/ncr.c,v 1.155.2.3 2001/03/05 13:09:10 obrien Exp $ | |
| 1c8b7a9a | 4 | ** $DragonFly: src/sys/dev/disk/ncr/ncr.c,v 1.22 2008/05/18 20:30:22 pavalos Exp $ |
| 984263bc MD |
5 | ** |
| 6 | ** Device driver for the NCR 53C8XX PCI-SCSI-Controller Family. | |
| 7 | ** | |
| 8 | **------------------------------------------------------------------------- | |
| 9 | ** | |
| 10 | ** Written for 386bsd and FreeBSD by | |
| 11 | ** Wolfgang Stanglmeier <wolf@cologne.de> | |
| 12 | ** Stefan Esser <se@mi.Uni-Koeln.de> | |
| 13 | ** | |
| 14 | **------------------------------------------------------------------------- | |
| 15 | ** | |
| 16 | ** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. | |
| 17 | ** | |
| 18 | ** Redistribution and use in source and binary forms, with or without | |
| 19 | ** modification, are permitted provided that the following conditions | |
| 20 | ** are met: | |
| 21 | ** 1. Redistributions of source code must retain the above copyright | |
| 22 | ** notice, this list of conditions and the following disclaimer. | |
| 23 | ** 2. Redistributions in binary form must reproduce the above copyright | |
| 24 | ** notice, this list of conditions and the following disclaimer in the | |
| 25 | ** documentation and/or other materials provided with the distribution. | |
| 26 | ** 3. The name of the author may not be used to endorse or promote products | |
| 27 | ** derived from this software without specific prior written permission. | |
| 28 | ** | |
| 29 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
| 30 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
| 31 | ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
| 32 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 33 | ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
| 34 | ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 35 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 36 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 37 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
| 38 | ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 39 | ** | |
| 40 | *************************************************************************** | |
| 41 | */ | |
| 42 | ||
| 43 | #define NCR_DATE "pl30 98/1/1" | |
| 44 | ||
| 45 | #define NCR_VERSION (2) | |
| 46 | #define MAX_UNITS (16) | |
| 47 | ||
| 48 | #define NCR_GETCC_WITHMSG | |
| 49 | ||
| 84754cd0 | 50 | #if (defined(__DragonFly__) || defined (__FreeBSD__)) && defined(_KERNEL) |
| 984263bc MD |
51 | #include "opt_ncr.h" |
| 52 | #endif | |
| 53 | ||
| 54 | /*========================================================== | |
| 55 | ** | |
| 56 | ** Configuration and Debugging | |
| 57 | ** | |
| 58 | ** May be overwritten in <arch/conf/xxxx> | |
| 59 | ** | |
| 60 | **========================================================== | |
| 61 | */ | |
| 62 | ||
| 63 | /* | |
| 64 | ** SCSI address of this device. | |
| 65 | ** The boot routines should have set it. | |
| 66 | ** If not, use this. | |
| 67 | */ | |
| 68 | ||
| 69 | #ifndef SCSI_NCR_MYADDR | |
| 70 | #define SCSI_NCR_MYADDR (7) | |
| 71 | #endif /* SCSI_NCR_MYADDR */ | |
| 72 | ||
| 73 | /* | |
| 74 | ** The default synchronous period factor | |
| 75 | ** (0=asynchronous) | |
| 76 | ** If maximum synchronous frequency is defined, use it instead. | |
| 77 | */ | |
| 78 | ||
| 79 | #ifndef SCSI_NCR_MAX_SYNC | |
| 80 | ||
| 81 | #ifndef SCSI_NCR_DFLT_SYNC | |
| 82 | #define SCSI_NCR_DFLT_SYNC (12) | |
| 83 | #endif /* SCSI_NCR_DFLT_SYNC */ | |
| 84 | ||
| 85 | #else | |
| 86 | ||
| 87 | #if SCSI_NCR_MAX_SYNC == 0 | |
| 88 | #define SCSI_NCR_DFLT_SYNC 0 | |
| 89 | #else | |
| 90 | #define SCSI_NCR_DFLT_SYNC (250000 / SCSI_NCR_MAX_SYNC) | |
| 91 | #endif | |
| 92 | ||
| 93 | #endif | |
| 94 | ||
| 95 | /* | |
| 96 | ** The minimal asynchronous pre-scaler period (ns) | |
| 97 | ** Shall be 40. | |
| 98 | */ | |
| 99 | ||
| 100 | #ifndef SCSI_NCR_MIN_ASYNC | |
| 101 | #define SCSI_NCR_MIN_ASYNC (40) | |
| 102 | #endif /* SCSI_NCR_MIN_ASYNC */ | |
| 103 | ||
| 104 | /* | |
| 105 | ** The maximal bus with (in log2 byte) | |
| 106 | ** (0=8 bit, 1=16 bit) | |
| 107 | */ | |
| 108 | ||
| 109 | #ifndef SCSI_NCR_MAX_WIDE | |
| 110 | #define SCSI_NCR_MAX_WIDE (1) | |
| 111 | #endif /* SCSI_NCR_MAX_WIDE */ | |
| 112 | ||
| 113 | /*========================================================== | |
| 114 | ** | |
| 115 | ** Configuration and Debugging | |
| 116 | ** | |
| 117 | **========================================================== | |
| 118 | */ | |
| 119 | ||
| 120 | /* | |
| 121 | ** Number of targets supported by the driver. | |
| 122 | ** n permits target numbers 0..n-1. | |
| 123 | ** Default is 7, meaning targets #0..#6. | |
| 124 | ** #7 .. is myself. | |
| 125 | */ | |
| 126 | ||
| 127 | #define MAX_TARGET (16) | |
| 128 | ||
| 129 | /* | |
| 130 | ** Number of logic units supported by the driver. | |
| 131 | ** n enables logic unit numbers 0..n-1. | |
| 132 | ** The common SCSI devices require only | |
| 133 | ** one lun, so take 1 as the default. | |
| 134 | */ | |
| 135 | ||
| 136 | #ifndef MAX_LUN | |
| 137 | #define MAX_LUN (8) | |
| 138 | #endif /* MAX_LUN */ | |
| 139 | ||
| 140 | /* | |
| 141 | ** The maximum number of jobs scheduled for starting. | |
| 142 | ** There should be one slot per target, and one slot | |
| 143 | ** for each tag of each target in use. | |
| 144 | */ | |
| 145 | ||
| 146 | #define MAX_START (256) | |
| 147 | ||
| 148 | /* | |
| 149 | ** The maximum number of segments a transfer is split into. | |
| 150 | */ | |
| 151 | ||
| 152 | #define MAX_SCATTER (33) | |
| 153 | ||
| 154 | /* | |
| 155 | ** The maximum transfer length (should be >= 64k). | |
| 156 | ** MUST NOT be greater than (MAX_SCATTER-1) * PAGE_SIZE. | |
| 157 | */ | |
| 158 | ||
| 159 | #define MAX_SIZE ((MAX_SCATTER-1) * (long) PAGE_SIZE) | |
| 160 | ||
| 161 | /* | |
| 162 | ** other | |
| 163 | */ | |
| 164 | ||
| 165 | #define NCR_SNOOP_TIMEOUT (1000000) | |
| 166 | ||
| 167 | /*========================================================== | |
| 168 | ** | |
| 169 | ** Include files | |
| 170 | ** | |
| 171 | **========================================================== | |
| 172 | */ | |
| 173 | ||
| 174 | #include <sys/param.h> | |
| 175 | #include <sys/time.h> | |
| 176 | ||
| 177 | #ifdef _KERNEL | |
| 178 | #include <sys/systm.h> | |
| 179 | #include <sys/malloc.h> | |
| 180 | #include <sys/buf.h> | |
| 181 | #include <sys/kernel.h> | |
| 182 | #include <sys/sysctl.h> | |
| 183 | #include <sys/bus.h> | |
| 2c9868e4 | 184 | #include <sys/thread2.h> |
| 984263bc MD |
185 | #include <machine/clock.h> |
| 186 | #include <machine/md_var.h> | |
| 984263bc MD |
187 | #include <sys/rman.h> |
| 188 | #include <vm/vm.h> | |
| 189 | #include <vm/pmap.h> | |
| 190 | #include <vm/vm_extern.h> | |
| 191 | #endif | |
| 192 | ||
| 1f2de5d4 MD |
193 | #include <bus/pci/pcivar.h> |
| 194 | #include <bus/pci/pcireg.h> | |
| 195 | #include "ncrreg.h" | |
| 984263bc | 196 | |
| 1f2de5d4 MD |
197 | #include <bus/cam/cam.h> |
| 198 | #include <bus/cam/cam_ccb.h> | |
| 199 | #include <bus/cam/cam_sim.h> | |
| 200 | #include <bus/cam/cam_xpt_sim.h> | |
| 201 | #include <bus/cam/cam_debug.h> | |
| 984263bc | 202 | |
| 1f2de5d4 MD |
203 | #include <bus/cam/scsi/scsi_all.h> |
| 204 | #include <bus/cam/scsi/scsi_message.h> | |
| 984263bc MD |
205 | |
| 206 | /*========================================================== | |
| 207 | ** | |
| 208 | ** Debugging tags | |
| 209 | ** | |
| 210 | **========================================================== | |
| 211 | */ | |
| 212 | ||
| 213 | #define DEBUG_ALLOC (0x0001) | |
| 214 | #define DEBUG_PHASE (0x0002) | |
| 215 | #define DEBUG_POLL (0x0004) | |
| 216 | #define DEBUG_QUEUE (0x0008) | |
| 217 | #define DEBUG_RESULT (0x0010) | |
| 218 | #define DEBUG_SCATTER (0x0020) | |
| 219 | #define DEBUG_SCRIPT (0x0040) | |
| 220 | #define DEBUG_TINY (0x0080) | |
| 221 | #define DEBUG_TIMING (0x0100) | |
| 222 | #define DEBUG_NEGO (0x0200) | |
| 223 | #define DEBUG_TAGS (0x0400) | |
| 224 | #define DEBUG_FREEZE (0x0800) | |
| 225 | #define DEBUG_RESTART (0x1000) | |
| 226 | ||
| 227 | /* | |
| 228 | ** Enable/Disable debug messages. | |
| 229 | ** Can be changed at runtime too. | |
| 230 | */ | |
| 231 | #ifdef SCSI_NCR_DEBUG | |
| 232 | #define DEBUG_FLAGS ncr_debug | |
| 233 | #else /* SCSI_NCR_DEBUG */ | |
| 234 | #define SCSI_NCR_DEBUG 0 | |
| 235 | #define DEBUG_FLAGS 0 | |
| 236 | #endif /* SCSI_NCR_DEBUG */ | |
| 237 | ||
| 238 | ||
| 239 | ||
| 240 | /*========================================================== | |
| 241 | ** | |
| 242 | ** assert () | |
| 243 | ** | |
| 244 | **========================================================== | |
| 245 | ** | |
| 246 | ** modified copy from 386bsd:/usr/include/sys/assert.h | |
| 247 | ** | |
| 248 | **---------------------------------------------------------- | |
| 249 | */ | |
| 250 | ||
| 251 | #ifdef DIAGNOSTIC | |
| 252 | #define assert(expression) { \ | |
| 253 | if (!(expression)) { \ | |
| e3869ec7 | 254 | (void)kprintf("assertion \"%s\" failed: " \ |
| 984263bc MD |
255 | "file \"%s\", line %d\n", \ |
| 256 | #expression, __FILE__, __LINE__); \ | |
| 257 | Debugger(""); \ | |
| 258 | } \ | |
| 259 | } | |
| 260 | #else | |
| 261 | #define assert(expression) { \ | |
| 262 | if (!(expression)) { \ | |
| e3869ec7 | 263 | (void)kprintf("assertion \"%s\" failed: " \ |
| 984263bc MD |
264 | "file \"%s\", line %d\n", \ |
| 265 | #expression, __FILE__, __LINE__); \ | |
| 266 | } \ | |
| 267 | } | |
| 268 | #endif | |
| 269 | ||
| 270 | /*========================================================== | |
| 271 | ** | |
| 272 | ** Access to the controller chip. | |
| 273 | ** | |
| 274 | **========================================================== | |
| 275 | */ | |
| 276 | ||
| 984263bc MD |
277 | #define INB(r) bus_space_read_1(np->bst, np->bsh, offsetof(struct ncr_reg, r)) |
| 278 | #define INW(r) bus_space_read_2(np->bst, np->bsh, offsetof(struct ncr_reg, r)) | |
| 279 | #define INL(r) bus_space_read_4(np->bst, np->bsh, offsetof(struct ncr_reg, r)) | |
| 280 | ||
| 281 | #define OUTB(r, val) bus_space_write_1(np->bst, np->bsh, \ | |
| 282 | offsetof(struct ncr_reg, r), val) | |
| 283 | #define OUTW(r, val) bus_space_write_2(np->bst, np->bsh, \ | |
| 284 | offsetof(struct ncr_reg, r), val) | |
| 285 | #define OUTL(r, val) bus_space_write_4(np->bst, np->bsh, \ | |
| 286 | offsetof(struct ncr_reg, r), val) | |
| 287 | #define OUTL_OFF(o, val) bus_space_write_4(np->bst, np->bsh, o, val) | |
| 288 | ||
| 289 | #define INB_OFF(o) bus_space_read_1(np->bst, np->bsh, o) | |
| 290 | #define INW_OFF(o) bus_space_read_2(np->bst, np->bsh, o) | |
| 291 | #define INL_OFF(o) bus_space_read_4(np->bst, np->bsh, o) | |
| 292 | ||
| 293 | #define READSCRIPT_OFF(base, off) \ | |
| 294 | (base ? *((volatile u_int32_t *)((volatile char *)base + (off))) : \ | |
| 295 | bus_space_read_4(np->bst2, np->bsh2, off)) | |
| 296 | ||
| 297 | #define WRITESCRIPT_OFF(base, off, val) \ | |
| 298 | do { \ | |
| 299 | if (base) \ | |
| 300 | *((volatile u_int32_t *) \ | |
| 301 | ((volatile char *)base + (off))) = (val); \ | |
| 302 | else \ | |
| 303 | bus_space_write_4(np->bst2, np->bsh2, off, val); \ | |
| 304 | } while (0) | |
| 305 | ||
| 306 | #define READSCRIPT(r) \ | |
| 307 | READSCRIPT_OFF(np->script, offsetof(struct script, r)) | |
| 308 | ||
| 309 | #define WRITESCRIPT(r, val) \ | |
| 310 | WRITESCRIPT_OFF(np->script, offsetof(struct script, r), val) | |
| 311 | ||
| 312 | /* | |
| 313 | ** Set bit field ON, OFF | |
| 314 | */ | |
| 315 | ||
| 316 | #define OUTONB(r, m) OUTB(r, INB(r) | (m)) | |
| 317 | #define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m)) | |
| 318 | #define OUTONW(r, m) OUTW(r, INW(r) | (m)) | |
| 319 | #define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m)) | |
| 320 | #define OUTONL(r, m) OUTL(r, INL(r) | (m)) | |
| 321 | #define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) | |
| 322 | ||
| 323 | /*========================================================== | |
| 324 | ** | |
| 325 | ** Command control block states. | |
| 326 | ** | |
| 327 | **========================================================== | |
| 328 | */ | |
| 329 | ||
| 330 | #define HS_IDLE (0) | |
| 331 | #define HS_BUSY (1) | |
| 332 | #define HS_NEGOTIATE (2) /* sync/wide data transfer*/ | |
| 333 | #define HS_DISCONNECT (3) /* Disconnected by target */ | |
| 334 | ||
| 335 | #define HS_COMPLETE (4) | |
| 336 | #define HS_SEL_TIMEOUT (5) /* Selection timeout */ | |
| 337 | #define HS_RESET (6) /* SCSI reset */ | |
| 338 | #define HS_ABORTED (7) /* Transfer aborted */ | |
| 339 | #define HS_TIMEOUT (8) /* Software timeout */ | |
| 340 | #define HS_FAIL (9) /* SCSI or PCI bus errors */ | |
| 341 | #define HS_UNEXPECTED (10) /* Unexpected disconnect */ | |
| 342 | #define HS_STALL (11) /* QUEUE FULL or BUSY */ | |
| 343 | ||
| 344 | #define HS_DONEMASK (0xfc) | |
| 345 | ||
| 346 | /*========================================================== | |
| 347 | ** | |
| 348 | ** Software Interrupt Codes | |
| 349 | ** | |
| 350 | **========================================================== | |
| 351 | */ | |
| 352 | ||
| 353 | #define SIR_SENSE_RESTART (1) | |
| 354 | #define SIR_SENSE_FAILED (2) | |
| 355 | #define SIR_STALL_RESTART (3) | |
| 356 | #define SIR_STALL_QUEUE (4) | |
| 357 | #define SIR_NEGO_SYNC (5) | |
| 358 | #define SIR_NEGO_WIDE (6) | |
| 359 | #define SIR_NEGO_FAILED (7) | |
| 360 | #define SIR_NEGO_PROTO (8) | |
| 361 | #define SIR_REJECT_RECEIVED (9) | |
| 362 | #define SIR_REJECT_SENT (10) | |
| 363 | #define SIR_IGN_RESIDUE (11) | |
| 364 | #define SIR_MISSING_SAVE (12) | |
| 365 | #define SIR_MAX (12) | |
| 366 | ||
| 367 | /*========================================================== | |
| 368 | ** | |
| 369 | ** Extended error codes. | |
| 370 | ** xerr_status field of struct nccb. | |
| 371 | ** | |
| 372 | **========================================================== | |
| 373 | */ | |
| 374 | ||
| 375 | #define XE_OK (0) | |
| 376 | #define XE_EXTRA_DATA (1) /* unexpected data phase */ | |
| 377 | #define XE_BAD_PHASE (2) /* illegal phase (4/5) */ | |
| 378 | ||
| 379 | /*========================================================== | |
| 380 | ** | |
| 381 | ** Negotiation status. | |
| 382 | ** nego_status field of struct nccb. | |
| 383 | ** | |
| 384 | **========================================================== | |
| 385 | */ | |
| 386 | ||
| 387 | #define NS_SYNC (1) | |
| 388 | #define NS_WIDE (2) | |
| 389 | ||
| 390 | /*========================================================== | |
| 391 | ** | |
| 392 | ** XXX These are no longer used. Remove once the | |
| 393 | ** script is updated. | |
| 394 | ** "Special features" of targets. | |
| 395 | ** quirks field of struct tcb. | |
| 396 | ** actualquirks field of struct nccb. | |
| 397 | ** | |
| 398 | **========================================================== | |
| 399 | */ | |
| 400 | ||
| 401 | #define QUIRK_AUTOSAVE (0x01) | |
| 402 | #define QUIRK_NOMSG (0x02) | |
| 403 | #define QUIRK_NOSYNC (0x10) | |
| 404 | #define QUIRK_NOWIDE16 (0x20) | |
| 405 | #define QUIRK_NOTAGS (0x40) | |
| 406 | #define QUIRK_UPDATE (0x80) | |
| 407 | ||
| 408 | /*========================================================== | |
| 409 | ** | |
| 410 | ** Misc. | |
| 411 | ** | |
| 412 | **========================================================== | |
| 413 | */ | |
| 414 | ||
| 415 | #define CCB_MAGIC (0xf2691ad2) | |
| 416 | #define MAX_TAGS (32) /* hard limit */ | |
| 417 | ||
| 418 | /*========================================================== | |
| 419 | ** | |
| 420 | ** OS dependencies. | |
| 421 | ** | |
| 422 | **========================================================== | |
| 423 | */ | |
| 424 | ||
| 425 | #define PRINT_ADDR(ccb) xpt_print_path((ccb)->ccb_h.path) | |
| 426 | ||
| 427 | /*========================================================== | |
| 428 | ** | |
| 429 | ** Declaration of structs. | |
| 430 | ** | |
| 431 | **========================================================== | |
| 432 | */ | |
| 433 | ||
| 434 | struct tcb; | |
| 435 | struct lcb; | |
| 436 | struct nccb; | |
| 437 | struct ncb; | |
| 438 | struct script; | |
| 439 | ||
| 440 | typedef struct ncb * ncb_p; | |
| 441 | typedef struct tcb * tcb_p; | |
| 442 | typedef struct lcb * lcb_p; | |
| 443 | typedef struct nccb * nccb_p; | |
| 444 | ||
| 445 | struct link { | |
| 446 | ncrcmd l_cmd; | |
| 447 | ncrcmd l_paddr; | |
| 448 | }; | |
| 449 | ||
| 450 | struct usrcmd { | |
| 451 | u_long target; | |
| 452 | u_long lun; | |
| 453 | u_long data; | |
| 454 | u_long cmd; | |
| 455 | }; | |
| 456 | ||
| 457 | #define UC_SETSYNC 10 | |
| 458 | #define UC_SETTAGS 11 | |
| 459 | #define UC_SETDEBUG 12 | |
| 460 | #define UC_SETORDER 13 | |
| 461 | #define UC_SETWIDE 14 | |
| 462 | #define UC_SETFLAG 15 | |
| 463 | ||
| 464 | #define UF_TRACE (0x01) | |
| 465 | ||
| 466 | /*--------------------------------------- | |
| 467 | ** | |
| 468 | ** Timestamps for profiling | |
| 469 | ** | |
| 470 | **--------------------------------------- | |
| 471 | */ | |
| 472 | ||
| 473 | /* Type of the kernel variable `ticks'. XXX should be declared with the var. */ | |
| 474 | typedef int ticks_t; | |
| 475 | ||
| 476 | struct tstamp { | |
| 477 | ticks_t start; | |
| 478 | ticks_t end; | |
| 479 | ticks_t select; | |
| 480 | ticks_t command; | |
| 481 | ticks_t data; | |
| 482 | ticks_t status; | |
| 483 | ticks_t disconnect; | |
| 484 | }; | |
| 485 | ||
| 486 | /* | |
| 487 | ** profiling data (per device) | |
| 488 | */ | |
| 489 | ||
| 490 | struct profile { | |
| 491 | u_long num_trans; | |
| 492 | u_long num_bytes; | |
| 493 | u_long num_disc; | |
| 494 | u_long num_break; | |
| 495 | u_long num_int; | |
| 496 | u_long num_fly; | |
| 497 | u_long ms_setup; | |
| 498 | u_long ms_data; | |
| 499 | u_long ms_disc; | |
| 500 | u_long ms_post; | |
| 501 | }; | |
| 502 | ||
| 503 | /*========================================================== | |
| 504 | ** | |
| 505 | ** Declaration of structs: target control block | |
| 506 | ** | |
| 507 | **========================================================== | |
| 508 | */ | |
| 509 | ||
| 510 | #define NCR_TRANS_CUR 0x01 /* Modify current neogtiation status */ | |
| 511 | #define NCR_TRANS_ACTIVE 0x03 /* Assume this is the active target */ | |
| 512 | #define NCR_TRANS_GOAL 0x04 /* Modify negotiation goal */ | |
| 513 | #define NCR_TRANS_USER 0x08 /* Modify user negotiation settings */ | |
| 514 | ||
| 515 | struct ncr_transinfo { | |
| 516 | u_int8_t width; | |
| 517 | u_int8_t period; | |
| 518 | u_int8_t offset; | |
| 519 | }; | |
| 520 | ||
| 521 | struct ncr_target_tinfo { | |
| 522 | /* Hardware version of our sync settings */ | |
| 523 | u_int8_t disc_tag; | |
| 524 | #define NCR_CUR_DISCENB 0x01 | |
| 525 | #define NCR_CUR_TAGENB 0x02 | |
| 526 | #define NCR_USR_DISCENB 0x04 | |
| 527 | #define NCR_USR_TAGENB 0x08 | |
| 528 | u_int8_t sval; | |
| 529 | struct ncr_transinfo current; | |
| 530 | struct ncr_transinfo goal; | |
| 531 | struct ncr_transinfo user; | |
| 532 | /* Hardware version of our wide settings */ | |
| 533 | u_int8_t wval; | |
| 534 | }; | |
| 535 | ||
| 536 | struct tcb { | |
| 537 | /* | |
| 538 | ** during reselection the ncr jumps to this point | |
| 539 | ** with SFBR set to the encoded target number | |
| 540 | ** with bit 7 set. | |
| 541 | ** if it's not this target, jump to the next. | |
| 542 | ** | |
| 543 | ** JUMP IF (SFBR != #target#) | |
| 544 | ** @(next tcb) | |
| 545 | */ | |
| 546 | ||
| 547 | struct link jump_tcb; | |
| 548 | ||
| 549 | /* | |
| 550 | ** load the actual values for the sxfer and the scntl3 | |
| 551 | ** register (sync/wide mode). | |
| 552 | ** | |
| 553 | ** SCR_COPY (1); | |
| 554 | ** @(sval field of this tcb) | |
| 555 | ** @(sxfer register) | |
| 556 | ** SCR_COPY (1); | |
| 557 | ** @(wval field of this tcb) | |
| 558 | ** @(scntl3 register) | |
| 559 | */ | |
| 560 | ||
| 561 | ncrcmd getscr[6]; | |
| 562 | ||
| 563 | /* | |
| 564 | ** if next message is "identify" | |
| 565 | ** then load the message to SFBR, | |
| 566 | ** else load 0 to SFBR. | |
| 567 | ** | |
| 568 | ** CALL | |
| 569 | ** <RESEL_LUN> | |
| 570 | */ | |
| 571 | ||
| 572 | struct link call_lun; | |
| 573 | ||
| 574 | /* | |
| 575 | ** now look for the right lun. | |
| 576 | ** | |
| 577 | ** JUMP | |
| 578 | ** @(first nccb of this lun) | |
| 579 | */ | |
| 580 | ||
| 581 | struct link jump_lcb; | |
| 582 | ||
| 583 | /* | |
| 584 | ** pointer to interrupted getcc nccb | |
| 585 | */ | |
| 586 | ||
| 587 | nccb_p hold_cp; | |
| 588 | ||
| 589 | /* | |
| 590 | ** pointer to nccb used for negotiating. | |
| 591 | ** Avoid to start a nego for all queued commands | |
| 592 | ** when tagged command queuing is enabled. | |
| 593 | */ | |
| 594 | ||
| 595 | nccb_p nego_cp; | |
| 596 | ||
| 597 | /* | |
| 598 | ** statistical data | |
| 599 | */ | |
| 600 | ||
| 601 | u_long transfers; | |
| 602 | u_long bytes; | |
| 603 | ||
| 604 | /* | |
| 605 | ** user settable limits for sync transfer | |
| 606 | ** and tagged commands. | |
| 607 | */ | |
| 608 | ||
| 609 | struct ncr_target_tinfo tinfo; | |
| 610 | ||
| 611 | /* | |
| 612 | ** the lcb's of this tcb | |
| 613 | */ | |
| 614 | ||
| 615 | lcb_p lp[MAX_LUN]; | |
| 616 | }; | |
| 617 | ||
| 618 | /*========================================================== | |
| 619 | ** | |
| 620 | ** Declaration of structs: lun control block | |
| 621 | ** | |
| 622 | **========================================================== | |
| 623 | */ | |
| 624 | ||
| 625 | struct lcb { | |
| 626 | /* | |
| 627 | ** during reselection the ncr jumps to this point | |
| 628 | ** with SFBR set to the "Identify" message. | |
| 629 | ** if it's not this lun, jump to the next. | |
| 630 | ** | |
| 631 | ** JUMP IF (SFBR != #lun#) | |
| 632 | ** @(next lcb of this target) | |
| 633 | */ | |
| 634 | ||
| 635 | struct link jump_lcb; | |
| 636 | ||
| 637 | /* | |
| 638 | ** if next message is "simple tag", | |
| 639 | ** then load the tag to SFBR, | |
| 640 | ** else load 0 to SFBR. | |
| 641 | ** | |
| 642 | ** CALL | |
| 643 | ** <RESEL_TAG> | |
| 644 | */ | |
| 645 | ||
| 646 | struct link call_tag; | |
| 647 | ||
| 648 | /* | |
| 649 | ** now look for the right nccb. | |
| 650 | ** | |
| 651 | ** JUMP | |
| 652 | ** @(first nccb of this lun) | |
| 653 | */ | |
| 654 | ||
| 655 | struct link jump_nccb; | |
| 656 | ||
| 657 | /* | |
| 658 | ** start of the nccb chain | |
| 659 | */ | |
| 660 | ||
| 661 | nccb_p next_nccb; | |
| 662 | ||
| 663 | /* | |
| 664 | ** Control of tagged queueing | |
| 665 | */ | |
| 666 | ||
| 667 | u_char reqnccbs; | |
| 668 | u_char reqlink; | |
| 669 | u_char actlink; | |
| 670 | u_char usetags; | |
| 671 | u_char lasttag; | |
| 672 | }; | |
| 673 | ||
| 674 | /*========================================================== | |
| 675 | ** | |
| 676 | ** Declaration of structs: COMMAND control block | |
| 677 | ** | |
| 678 | **========================================================== | |
| 679 | ** | |
| 680 | ** This substructure is copied from the nccb to a | |
| 681 | ** global address after selection (or reselection) | |
| 682 | ** and copied back before disconnect. | |
| 683 | ** | |
| 684 | ** These fields are accessible to the script processor. | |
| 685 | ** | |
| 686 | **---------------------------------------------------------- | |
| 687 | */ | |
| 688 | ||
| 689 | struct head { | |
| 690 | /* | |
| 691 | ** Execution of a nccb starts at this point. | |
| 692 | ** It's a jump to the "SELECT" label | |
| 693 | ** of the script. | |
| 694 | ** | |
| 695 | ** After successful selection the script | |
| 696 | ** processor overwrites it with a jump to | |
| 697 | ** the IDLE label of the script. | |
| 698 | */ | |
| 699 | ||
| 700 | struct link launch; | |
| 701 | ||
| 702 | /* | |
| 703 | ** Saved data pointer. | |
| 704 | ** Points to the position in the script | |
| 705 | ** responsible for the actual transfer | |
| 706 | ** of data. | |
| 707 | ** It's written after reception of a | |
| 708 | ** "SAVE_DATA_POINTER" message. | |
| 709 | ** The goalpointer points after | |
| 710 | ** the last transfer command. | |
| 711 | */ | |
| 712 | ||
| 713 | u_int32_t savep; | |
| 714 | u_int32_t lastp; | |
| 715 | u_int32_t goalp; | |
| 716 | ||
| 717 | /* | |
| 718 | ** The virtual address of the nccb | |
| 719 | ** containing this header. | |
| 720 | */ | |
| 721 | ||
| 722 | nccb_p cp; | |
| 723 | ||
| 724 | /* | |
| 725 | ** space for some timestamps to gather | |
| 726 | ** profiling data about devices and this driver. | |
| 727 | */ | |
| 728 | ||
| 729 | struct tstamp stamp; | |
| 730 | ||
| 731 | /* | |
| 732 | ** status fields. | |
| 733 | */ | |
| 734 | ||
| 735 | u_char status[8]; | |
| 736 | }; | |
| 737 | ||
| 738 | /* | |
| 739 | ** The status bytes are used by the host and the script processor. | |
| 740 | ** | |
| 741 | ** The first four byte are copied to the scratchb register | |
| 742 | ** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, | |
| 743 | ** and copied back just after disconnecting. | |
| 744 | ** Inside the script the XX_REG are used. | |
| 745 | ** | |
| 746 | ** The last four bytes are used inside the script by "COPY" commands. | |
| 747 | ** Because source and destination must have the same alignment | |
| 748 | ** in a longword, the fields HAVE to be at the choosen offsets. | |
| 749 | ** xerr_st (4) 0 (0x34) scratcha | |
| 750 | ** sync_st (5) 1 (0x05) sxfer | |
| 751 | ** wide_st (7) 3 (0x03) scntl3 | |
| 752 | */ | |
| 753 | ||
| 754 | /* | |
| 755 | ** First four bytes (script) | |
| 756 | */ | |
| 757 | #define QU_REG scr0 | |
| 758 | #define HS_REG scr1 | |
| 759 | #define HS_PRT nc_scr1 | |
| 760 | #define SS_REG scr2 | |
| 761 | #define PS_REG scr3 | |
| 762 | ||
| 763 | /* | |
| 764 | ** First four bytes (host) | |
| 765 | */ | |
| 766 | #define actualquirks phys.header.status[0] | |
| 767 | #define host_status phys.header.status[1] | |
| 768 | #define s_status phys.header.status[2] | |
| 769 | #define parity_status phys.header.status[3] | |
| 770 | ||
| 771 | /* | |
| 772 | ** Last four bytes (script) | |
| 773 | */ | |
| 774 | #define xerr_st header.status[4] /* MUST be ==0 mod 4 */ | |
| 775 | #define sync_st header.status[5] /* MUST be ==1 mod 4 */ | |
| 776 | #define nego_st header.status[6] | |
| 777 | #define wide_st header.status[7] /* MUST be ==3 mod 4 */ | |
| 778 | ||
| 779 | /* | |
| 780 | ** Last four bytes (host) | |
| 781 | */ | |
| 782 | #define xerr_status phys.xerr_st | |
| 783 | #define sync_status phys.sync_st | |
| 784 | #define nego_status phys.nego_st | |
| 785 | #define wide_status phys.wide_st | |
| 786 | ||
| 787 | /*========================================================== | |
| 788 | ** | |
| 789 | ** Declaration of structs: Data structure block | |
| 790 | ** | |
| 791 | **========================================================== | |
| 792 | ** | |
| 793 | ** During execution of a nccb by the script processor, | |
| 794 | ** the DSA (data structure address) register points | |
| 795 | ** to this substructure of the nccb. | |
| 796 | ** This substructure contains the header with | |
| 797 | ** the script-processor-changable data and | |
| 798 | ** data blocks for the indirect move commands. | |
| 799 | ** | |
| 800 | **---------------------------------------------------------- | |
| 801 | */ | |
| 802 | ||
| 803 | struct dsb { | |
| 804 | ||
| 805 | /* | |
| 806 | ** Header. | |
| 807 | ** Has to be the first entry, | |
| 808 | ** because it's jumped to by the | |
| 809 | ** script processor | |
| 810 | */ | |
| 811 | ||
| 812 | struct head header; | |
| 813 | ||
| 814 | /* | |
| 815 | ** Table data for Script | |
| 816 | */ | |
| 817 | ||
| 818 | struct scr_tblsel select; | |
| 819 | struct scr_tblmove smsg ; | |
| 820 | struct scr_tblmove smsg2 ; | |
| 821 | struct scr_tblmove cmd ; | |
| 822 | struct scr_tblmove scmd ; | |
| 823 | struct scr_tblmove sense ; | |
| 824 | struct scr_tblmove data [MAX_SCATTER]; | |
| 825 | }; | |
| 826 | ||
| 827 | /*========================================================== | |
| 828 | ** | |
| 829 | ** Declaration of structs: Command control block. | |
| 830 | ** | |
| 831 | **========================================================== | |
| 832 | ** | |
| 833 | ** During execution of a nccb by the script processor, | |
| 834 | ** the DSA (data structure address) register points | |
| 835 | ** to this substructure of the nccb. | |
| 836 | ** This substructure contains the header with | |
| 837 | ** the script-processor-changable data and then | |
| 838 | ** data blocks for the indirect move commands. | |
| 839 | ** | |
| 840 | **---------------------------------------------------------- | |
| 841 | */ | |
| 842 | ||
| 843 | ||
| 844 | struct nccb { | |
| 845 | /* | |
| 846 | ** This filler ensures that the global header is | |
| 847 | ** cache line size aligned. | |
| 848 | */ | |
| 849 | ncrcmd filler[4]; | |
| 850 | ||
| 851 | /* | |
| 852 | ** during reselection the ncr jumps to this point. | |
| 853 | ** If a "SIMPLE_TAG" message was received, | |
| 854 | ** then SFBR is set to the tag. | |
| 855 | ** else SFBR is set to 0 | |
| 856 | ** If looking for another tag, jump to the next nccb. | |
| 857 | ** | |
| 858 | ** JUMP IF (SFBR != #TAG#) | |
| 859 | ** @(next nccb of this lun) | |
| 860 | */ | |
| 861 | ||
| 862 | struct link jump_nccb; | |
| 863 | ||
| 864 | /* | |
| 865 | ** After execution of this call, the return address | |
| 866 | ** (in the TEMP register) points to the following | |
| 867 | ** data structure block. | |
| 868 | ** So copy it to the DSA register, and start | |
| 869 | ** processing of this data structure. | |
| 870 | ** | |
| 871 | ** CALL | |
| 872 | ** <RESEL_TMP> | |
| 873 | */ | |
| 874 | ||
| 875 | struct link call_tmp; | |
| 876 | ||
| 877 | /* | |
| 878 | ** This is the data structure which is | |
| 879 | ** to be executed by the script processor. | |
| 880 | */ | |
| 881 | ||
| 882 | struct dsb phys; | |
| 883 | ||
| 884 | /* | |
| 885 | ** If a data transfer phase is terminated too early | |
| 886 | ** (after reception of a message (i.e. DISCONNECT)), | |
| 887 | ** we have to prepare a mini script to transfer | |
| 888 | ** the rest of the data. | |
| 889 | */ | |
| 890 | ||
| 891 | ncrcmd patch[8]; | |
| 892 | ||
| 893 | /* | |
| 894 | ** The general SCSI driver provides a | |
| 895 | ** pointer to a control block. | |
| 896 | */ | |
| 897 | ||
| 898 | union ccb *ccb; | |
| 899 | ||
| 900 | /* | |
| 901 | ** We prepare a message to be sent after selection, | |
| 902 | ** and a second one to be sent after getcc selection. | |
| 903 | ** Contents are IDENTIFY and SIMPLE_TAG. | |
| 904 | ** While negotiating sync or wide transfer, | |
| 905 | ** a SDTM or WDTM message is appended. | |
| 906 | */ | |
| 907 | ||
| 908 | u_char scsi_smsg [8]; | |
| 909 | u_char scsi_smsg2[8]; | |
| 910 | ||
| 911 | /* | |
| 912 | ** Lock this nccb. | |
| 913 | ** Flag is used while looking for a free nccb. | |
| 914 | */ | |
| 915 | ||
| 916 | u_long magic; | |
| 917 | ||
| 918 | /* | |
| 919 | ** Physical address of this instance of nccb | |
| 920 | */ | |
| 921 | ||
| 922 | u_long p_nccb; | |
| 923 | ||
| 924 | /* | |
| 925 | ** Completion time out for this job. | |
| 926 | ** It's set to time of start + allowed number of seconds. | |
| 927 | */ | |
| 928 | ||
| 929 | time_t tlimit; | |
| 930 | ||
| 931 | /* | |
| 932 | ** All nccbs of one hostadapter are chained. | |
| 933 | */ | |
| 934 | ||
| 935 | nccb_p link_nccb; | |
| 936 | ||
| 937 | /* | |
| 938 | ** All nccbs of one target/lun are chained. | |
| 939 | */ | |
| 940 | ||
| 941 | nccb_p next_nccb; | |
| 942 | ||
| 943 | /* | |
| 944 | ** Sense command | |
| 945 | */ | |
| 946 | ||
| 947 | u_char sensecmd[6]; | |
| 948 | ||
| 949 | /* | |
| 950 | ** Tag for this transfer. | |
| 951 | ** It's patched into jump_nccb. | |
| 952 | ** If it's not zero, a SIMPLE_TAG | |
| 953 | ** message is included in smsg. | |
| 954 | */ | |
| 955 | ||
| 956 | u_char tag; | |
| 957 | }; | |
| 958 | ||
| 959 | #define CCB_PHYS(cp,lbl) (cp->p_nccb + offsetof(struct nccb, lbl)) | |
| 960 | ||
| 961 | /*========================================================== | |
| 962 | ** | |
| 963 | ** Declaration of structs: NCR device descriptor | |
| 964 | ** | |
| 965 | **========================================================== | |
| 966 | */ | |
| 967 | ||
| 968 | struct ncb { | |
| 969 | /* | |
| 970 | ** The global header. | |
| 971 | ** Accessible to both the host and the | |
| 972 | ** script-processor. | |
| 973 | ** We assume it is cache line size aligned. | |
| 974 | */ | |
| 975 | struct head header; | |
| 976 | ||
| 977 | int unit; | |
| 978 | ||
| 979 | /*----------------------------------------------- | |
| 980 | ** Scripts .. | |
| 981 | **----------------------------------------------- | |
| 982 | ** | |
| 983 | ** During reselection the ncr jumps to this point. | |
| 984 | ** The SFBR register is loaded with the encoded target id. | |
| 985 | ** | |
| 986 | ** Jump to the first target. | |
| 987 | ** | |
| 988 | ** JUMP | |
| 989 | ** @(next tcb) | |
| 990 | */ | |
| 991 | struct link jump_tcb; | |
| 992 | ||
| 993 | /*----------------------------------------------- | |
| 994 | ** Configuration .. | |
| 995 | **----------------------------------------------- | |
| 996 | ** | |
| 997 | ** virtual and physical addresses | |
| 998 | ** of the 53c810 chip. | |
| 999 | */ | |
| 1000 | int reg_rid; | |
| 1001 | struct resource *reg_res; | |
| 1002 | bus_space_tag_t bst; | |
| 1003 | bus_space_handle_t bsh; | |
| 1004 | ||
| 1005 | int sram_rid; | |
| 1006 | struct resource *sram_res; | |
| 1007 | bus_space_tag_t bst2; | |
| 1008 | bus_space_handle_t bsh2; | |
| 1009 | ||
| 1010 | struct resource *irq_res; | |
| 1011 | void *irq_handle; | |
| 1012 | ||
| 1013 | /* | |
| 1014 | ** Scripts instance virtual address. | |
| 1015 | */ | |
| 1016 | struct script *script; | |
| 1017 | struct scripth *scripth; | |
| 1018 | ||
| 1019 | /* | |
| 1020 | ** Scripts instance physical address. | |
| 1021 | */ | |
| 1022 | u_long p_script; | |
| 1023 | u_long p_scripth; | |
| 1024 | ||
| 1025 | /* | |
| 1026 | ** The SCSI address of the host adapter. | |
| 1027 | */ | |
| 1028 | u_char myaddr; | |
| 1029 | ||
| 1030 | /* | |
| 1031 | ** timing parameters | |
| 1032 | */ | |
| 1033 | u_char minsync; /* Minimum sync period factor */ | |
| 1034 | u_char maxsync; /* Maximum sync period factor */ | |
| 1035 | u_char maxoffs; /* Max scsi offset */ | |
| 1036 | u_char clock_divn; /* Number of clock divisors */ | |
| 1037 | u_long clock_khz; /* SCSI clock frequency in KHz */ | |
| 1038 | u_long features; /* Chip features map */ | |
| 1039 | u_char multiplier; /* Clock multiplier (1,2,4) */ | |
| 1040 | ||
| 1041 | u_char maxburst; /* log base 2 of dwords burst */ | |
| 1042 | ||
| 1043 | /* | |
| 1044 | ** BIOS supplied PCI bus options | |
| 1045 | */ | |
| 1046 | u_char rv_scntl3; | |
| 1047 | u_char rv_dcntl; | |
| 1048 | u_char rv_dmode; | |
| 1049 | u_char rv_ctest3; | |
| 1050 | u_char rv_ctest4; | |
| 1051 | u_char rv_ctest5; | |
| 1052 | u_char rv_gpcntl; | |
| 1053 | u_char rv_stest2; | |
| 1054 | ||
| 1055 | /*----------------------------------------------- | |
| 1056 | ** CAM SIM information for this instance | |
| 1057 | **----------------------------------------------- | |
| 1058 | */ | |
| 1059 | ||
| 1060 | struct cam_sim *sim; | |
| 1061 | struct cam_path *path; | |
| 1062 | ||
| 1063 | /*----------------------------------------------- | |
| 1064 | ** Job control | |
| 1065 | **----------------------------------------------- | |
| 1066 | ** | |
| 1067 | ** Commands from user | |
| 1068 | */ | |
| 1069 | struct usrcmd user; | |
| 1070 | ||
| 1071 | /* | |
| 1072 | ** Target data | |
| 1073 | */ | |
| 1074 | struct tcb target[MAX_TARGET]; | |
| 1075 | ||
| 1076 | /* | |
| 1077 | ** Start queue. | |
| 1078 | */ | |
| 1079 | u_int32_t squeue [MAX_START]; | |
| 1080 | u_short squeueput; | |
| 1081 | ||
| 1082 | /* | |
| 1083 | ** Timeout handler | |
| 1084 | */ | |
| 1085 | time_t heartbeat; | |
| 1086 | u_short ticks; | |
| 1087 | u_short latetime; | |
| 1088 | time_t lasttime; | |
| 7ed1b850 | 1089 | struct callout timeout_ch; |
| 984263bc MD |
1090 | |
| 1091 | /*----------------------------------------------- | |
| 1092 | ** Debug and profiling | |
| 1093 | **----------------------------------------------- | |
| 1094 | ** | |
| 1095 | ** register dump | |
| 1096 | */ | |
| 1097 | struct ncr_reg regdump; | |
| 1098 | time_t regtime; | |
| 1099 | ||
| 1100 | /* | |
| 1101 | ** Profiling data | |
| 1102 | */ | |
| 1103 | struct profile profile; | |
| 1104 | u_long disc_phys; | |
| 1105 | u_long disc_ref; | |
| 1106 | ||
| 1107 | /* | |
| 1108 | ** Head of list of all nccbs for this controller. | |
| 1109 | */ | |
| 1110 | nccb_p link_nccb; | |
| 1111 | ||
| 1112 | /* | |
| 1113 | ** message buffers. | |
| 1114 | ** Should be longword aligned, | |
| 1115 | ** because they're written with a | |
| 1116 | ** COPY script command. | |
| 1117 | */ | |
| 1118 | u_char msgout[8]; | |
| 1119 | u_char msgin [8]; | |
| 1120 | u_int32_t lastmsg; | |
| 1121 | ||
| 1122 | /* | |
| 1123 | ** Buffer for STATUS_IN phase. | |
| 1124 | */ | |
| 1125 | u_char scratch; | |
| 1126 | ||
| 1127 | /* | |
| 1128 | ** controller chip dependent maximal transfer width. | |
| 1129 | */ | |
| 1130 | u_char maxwide; | |
| 1131 | ||
| 1132 | #ifdef NCR_IOMAPPED | |
| 1133 | /* | |
| 1134 | ** address of the ncr control registers in io space | |
| 1135 | */ | |
| 1136 | pci_port_t port; | |
| 1137 | #endif | |
| 1138 | }; | |
| 1139 | ||
| 1140 | #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) | |
| 1141 | #define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl)) | |
| 1142 | ||
| 1143 | /*========================================================== | |
| 1144 | ** | |
| 1145 | ** | |
| 1146 | ** Script for NCR-Processor. | |
| 1147 | ** | |
| 1148 | ** Use ncr_script_fill() to create the variable parts. | |
| 1149 | ** Use ncr_script_copy_and_bind() to make a copy and | |
| 1150 | ** bind to physical addresses. | |
| 1151 | ** | |
| 1152 | ** | |
| 1153 | **========================================================== | |
| 1154 | ** | |
| 1155 | ** We have to know the offsets of all labels before | |
| 1156 | ** we reach them (for forward jumps). | |
| 1157 | ** Therefore we declare a struct here. | |
| 1158 | ** If you make changes inside the script, | |
| 1159 | ** DONT FORGET TO CHANGE THE LENGTHS HERE! | |
| 1160 | ** | |
| 1161 | **---------------------------------------------------------- | |
| 1162 | */ | |
| 1163 | ||
| 1164 | /* | |
| 1165 | ** Script fragments which are loaded into the on-board RAM | |
| 1166 | ** of 825A, 875 and 895 chips. | |
| 1167 | */ | |
| 1168 | struct script { | |
| 1169 | ncrcmd start [ 7]; | |
| 1170 | ncrcmd start0 [ 2]; | |
| 1171 | ncrcmd start1 [ 3]; | |
| 1172 | ncrcmd startpos [ 1]; | |
| 1173 | ncrcmd trysel [ 8]; | |
| 1174 | ncrcmd skip [ 8]; | |
| 1175 | ncrcmd skip2 [ 3]; | |
| 1176 | ncrcmd idle [ 2]; | |
| 1177 | ncrcmd select [ 18]; | |
| 1178 | ncrcmd prepare [ 4]; | |
| 1179 | ncrcmd loadpos [ 14]; | |
| 1180 | ncrcmd prepare2 [ 24]; | |
| 1181 | ncrcmd setmsg [ 5]; | |
| 1182 | ncrcmd clrack [ 2]; | |
| 1183 | ncrcmd dispatch [ 33]; | |
| 1184 | ncrcmd no_data [ 17]; | |
| 1185 | ncrcmd checkatn [ 10]; | |
| 1186 | ncrcmd command [ 15]; | |
| 1187 | ncrcmd status [ 27]; | |
| 1188 | ncrcmd msg_in [ 26]; | |
| 1189 | ncrcmd msg_bad [ 6]; | |
| 1190 | ncrcmd complete [ 13]; | |
| 1191 | ncrcmd cleanup [ 12]; | |
| 1192 | ncrcmd cleanup0 [ 9]; | |
| 1193 | ncrcmd signal [ 12]; | |
| 1194 | ncrcmd save_dp [ 5]; | |
| 1195 | ncrcmd restore_dp [ 5]; | |
| 1196 | ncrcmd disconnect [ 12]; | |
| 1197 | ncrcmd disconnect0 [ 5]; | |
| 1198 | ncrcmd disconnect1 [ 23]; | |
| 1199 | ncrcmd msg_out [ 9]; | |
| 1200 | ncrcmd msg_out_done [ 7]; | |
| 1201 | ncrcmd badgetcc [ 6]; | |
| 1202 | ncrcmd reselect [ 8]; | |
| 1203 | ncrcmd reselect1 [ 8]; | |
| 1204 | ncrcmd reselect2 [ 8]; | |
| 1205 | ncrcmd resel_tmp [ 5]; | |
| 1206 | ncrcmd resel_lun [ 18]; | |
| 1207 | ncrcmd resel_tag [ 24]; | |
| 1208 | ncrcmd data_in [MAX_SCATTER * 4 + 7]; | |
| 1209 | ncrcmd data_out [MAX_SCATTER * 4 + 7]; | |
| 1210 | }; | |
| 1211 | ||
| 1212 | /* | |
| 1213 | ** Script fragments which stay in main memory for all chips. | |
| 1214 | */ | |
| 1215 | struct scripth { | |
| 1216 | ncrcmd tryloop [MAX_START*5+2]; | |
| 1217 | ncrcmd msg_parity [ 6]; | |
| 1218 | ncrcmd msg_reject [ 8]; | |
| 1219 | ncrcmd msg_ign_residue [ 32]; | |
| 1220 | ncrcmd msg_extended [ 18]; | |
| 1221 | ncrcmd msg_ext_2 [ 18]; | |
| 1222 | ncrcmd msg_wdtr [ 27]; | |
| 1223 | ncrcmd msg_ext_3 [ 18]; | |
| 1224 | ncrcmd msg_sdtr [ 27]; | |
| 1225 | ncrcmd msg_out_abort [ 10]; | |
| 1226 | ncrcmd getcc [ 4]; | |
| 1227 | ncrcmd getcc1 [ 5]; | |
| 1228 | #ifdef NCR_GETCC_WITHMSG | |
| 1229 | ncrcmd getcc2 [ 29]; | |
| 1230 | #else | |
| 1231 | ncrcmd getcc2 [ 14]; | |
| 1232 | #endif | |
| 1233 | ncrcmd getcc3 [ 6]; | |
| 1234 | ncrcmd aborttag [ 4]; | |
| 1235 | ncrcmd abort [ 22]; | |
| 1236 | ncrcmd snooptest [ 9]; | |
| 1237 | ncrcmd snoopend [ 2]; | |
| 1238 | }; | |
| 1239 | ||
| 1240 | /*========================================================== | |
| 1241 | ** | |
| 1242 | ** | |
| 1243 | ** Function headers. | |
| 1244 | ** | |
| 1245 | ** | |
| 1246 | **========================================================== | |
| 1247 | */ | |
| 1248 | ||
| 1249 | #ifdef _KERNEL | |
| 1250 | static nccb_p ncr_alloc_nccb (ncb_p np, u_long target, u_long lun); | |
| 1251 | static void ncr_complete (ncb_p np, nccb_p cp); | |
| 1252 | static int ncr_delta (int * from, int * to); | |
| 1253 | static void ncr_exception (ncb_p np); | |
| 1254 | static void ncr_free_nccb (ncb_p np, nccb_p cp); | |
| 1255 | static void ncr_freeze_devq (ncb_p np, struct cam_path *path); | |
| 1256 | static void ncr_selectclock (ncb_p np, u_char scntl3); | |
| 1257 | static void ncr_getclock (ncb_p np, u_char multiplier); | |
| 1258 | static nccb_p ncr_get_nccb (ncb_p np, u_long t,u_long l); | |
| 1259 | #if 0 | |
| 1260 | static u_int32_t ncr_info (int unit); | |
| 1261 | #endif | |
| 1262 | static void ncr_init (ncb_p np, char * msg, u_long code); | |
| 1263 | static void ncr_intr (void *vnp); | |
| 1264 | static void ncr_int_ma (ncb_p np, u_char dstat); | |
| 1265 | static void ncr_int_sir (ncb_p np); | |
| 1266 | static void ncr_int_sto (ncb_p np); | |
| 1267 | #if 0 | |
| 1268 | static void ncr_min_phys (struct buf *bp); | |
| 1269 | #endif | |
| 1270 | static void ncr_poll (struct cam_sim *sim); | |
| 1271 | static void ncb_profile (ncb_p np, nccb_p cp); | |
| 1272 | static void ncr_script_copy_and_bind | |
| 1273 | (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); | |
| 1274 | static void ncr_script_fill (struct script * scr, struct scripth *scrh); | |
| 1275 | static int ncr_scatter (struct dsb* phys, vm_offset_t vaddr, | |
| 1276 | vm_size_t datalen); | |
| 1277 | static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, | |
| 1278 | u_char *scntl3p); | |
| 1279 | static void ncr_setsync (ncb_p np, nccb_p cp,u_char scntl3,u_char sxfer, | |
| 1280 | u_char period); | |
| 1281 | static void ncr_setwide (ncb_p np, nccb_p cp, u_char wide, u_char ack); | |
| 1282 | static int ncr_show_msg (u_char * msg); | |
| 1283 | static int ncr_snooptest (ncb_p np); | |
| 1284 | static void ncr_action (struct cam_sim *sim, union ccb *ccb); | |
| 1285 | static void ncr_timeout (void *arg); | |
| 1286 | static void ncr_wakeup (ncb_p np, u_long code); | |
| 1287 | ||
| 1288 | static int ncr_probe (device_t dev); | |
| 1289 | static int ncr_attach (device_t dev); | |
| 1290 | ||
| 1291 | #endif /* _KERNEL */ | |
| 1292 | ||
| 1293 | /*========================================================== | |
| 1294 | ** | |
| 1295 | ** | |
| 1296 | ** Global static data. | |
| 1297 | ** | |
| 1298 | ** | |
| 1299 | **========================================================== | |
| 1300 | */ | |
| 1301 | ||
| 1302 | ||
| 1de703da MD |
1303 | /* |
| 1304 | * $FreeBSD: src/sys/pci/ncr.c,v 1.155.2.3 2001/03/05 13:09:10 obrien Exp $ | |
| 1305 | */ | |
| 984263bc MD |
1306 | static const u_long ncr_version = NCR_VERSION * 11 |
| 1307 | + (u_long) sizeof (struct ncb) * 7 | |
| 1308 | + (u_long) sizeof (struct nccb) * 5 | |
| 1309 | + (u_long) sizeof (struct lcb) * 3 | |
| 1310 | + (u_long) sizeof (struct tcb) * 2; | |
| 1311 | ||
| 1312 | #ifdef _KERNEL | |
| 1313 | ||
| 1314 | static int ncr_debug = SCSI_NCR_DEBUG; | |
| 0c52fa62 SG |
1315 | SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, |
| 1316 | "Driver debug flags"); | |
| 984263bc MD |
1317 | |
| 1318 | static int ncr_cache; /* to be aligned _NOT_ static */ | |
| 1319 | ||
| 1320 | /*========================================================== | |
| 1321 | ** | |
| 1322 | ** | |
| 1323 | ** Global static data: auto configure | |
| 1324 | ** | |
| 1325 | ** | |
| 1326 | **========================================================== | |
| 1327 | */ | |
| 1328 | ||
| 1329 | #define NCR_810_ID (0x00011000ul) | |
| 1330 | #define NCR_815_ID (0x00041000ul) | |
| 1331 | #define NCR_820_ID (0x00021000ul) | |
| 1332 | #define NCR_825_ID (0x00031000ul) | |
| 1333 | #define NCR_860_ID (0x00061000ul) | |
| 1334 | #define NCR_875_ID (0x000f1000ul) | |
| 1335 | #define NCR_875_ID2 (0x008f1000ul) | |
| 1336 | #define NCR_885_ID (0x000d1000ul) | |
| 1337 | #define NCR_895_ID (0x000c1000ul) | |
| 1338 | #define NCR_896_ID (0x000b1000ul) | |
| 1339 | #define NCR_895A_ID (0x00121000ul) | |
| 1340 | #define NCR_1510D_ID (0x000a1000ul) | |
| 1341 | ||
| 1342 | ||
| 1343 | static char *ncr_name (ncb_p np) | |
| 1344 | { | |
| 1345 | static char name[10]; | |
| f8c7a42d | 1346 | ksnprintf(name, sizeof(name), "ncr%d", np->unit); |
| 984263bc MD |
1347 | return (name); |
| 1348 | } | |
| 1349 | ||
| 1350 | /*========================================================== | |
| 1351 | ** | |
| 1352 | ** | |
| 1353 | ** Scripts for NCR-Processor. | |
| 1354 | ** | |
| 1355 | ** Use ncr_script_bind for binding to physical addresses. | |
| 1356 | ** | |
| 1357 | ** | |
| 1358 | **========================================================== | |
| 1359 | ** | |
| 1360 | ** NADDR generates a reference to a field of the controller data. | |
| 1361 | ** PADDR generates a reference to another part of the script. | |
| 1362 | ** RADDR generates a reference to a script processor register. | |
| 1363 | ** FADDR generates a reference to a script processor register | |
| 1364 | ** with offset. | |
| 1365 | ** | |
| 1366 | **---------------------------------------------------------- | |
| 1367 | */ | |
| 1368 | ||
| 1369 | #define RELOC_SOFTC 0x40000000 | |
| 1370 | #define RELOC_LABEL 0x50000000 | |
| 1371 | #define RELOC_REGISTER 0x60000000 | |
| 1372 | #define RELOC_KVAR 0x70000000 | |
| 1373 | #define RELOC_LABELH 0x80000000 | |
| 1374 | #define RELOC_MASK 0xf0000000 | |
| 1375 | ||
| 1376 | #define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label)) | |
| 1377 | #define PADDR(label) (RELOC_LABEL | offsetof(struct script, label)) | |
| 1378 | #define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label)) | |
| 1379 | #define RADDR(label) (RELOC_REGISTER | REG(label)) | |
| 1380 | #define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs))) | |
| 1381 | #define KVAR(which) (RELOC_KVAR | (which)) | |
| 1382 | ||
| 1383 | #define KVAR_SECOND (0) | |
| 1384 | #define KVAR_TICKS (1) | |
| 1385 | #define KVAR_NCR_CACHE (2) | |
| 1386 | ||
| 1387 | #define SCRIPT_KVAR_FIRST (0) | |
| 1388 | #define SCRIPT_KVAR_LAST (3) | |
| 1389 | ||
| 1390 | /* | |
| 1391 | * Kernel variables referenced in the scripts. | |
| 1392 | * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. | |
| 1393 | */ | |
| 1394 | static void *script_kvars[] = | |
| 1395 | { &time_second, &ticks, &ncr_cache }; | |
| 1396 | ||
| 1397 | static struct script script0 = { | |
| 1398 | /*--------------------------< START >-----------------------*/ { | |
| 1399 | /* | |
| 1400 | ** Claim to be still alive ... | |
| 1401 | */ | |
| 1402 | SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), | |
| 1403 | KVAR (KVAR_SECOND), | |
| 1404 | NADDR (heartbeat), | |
| 1405 | /* | |
| 1406 | ** Make data structure address invalid. | |
| 1407 | ** clear SIGP. | |
| 1408 | */ | |
| 1409 | SCR_LOAD_REG (dsa, 0xff), | |
| 1410 | 0, | |
| 1411 | SCR_FROM_REG (ctest2), | |
| 1412 | 0, | |
| 1413 | }/*-------------------------< START0 >----------------------*/,{ | |
| 1414 | /* | |
| 1415 | ** Hook for interrupted GetConditionCode. | |
| 1416 | ** Will be patched to ... IFTRUE by | |
| 1417 | ** the interrupt handler. | |
| 1418 | */ | |
| 1419 | SCR_INT ^ IFFALSE (0), | |
| 1420 | SIR_SENSE_RESTART, | |
| 1421 | ||
| 1422 | }/*-------------------------< START1 >----------------------*/,{ | |
| 1423 | /* | |
| 1424 | ** Hook for stalled start queue. | |
| 1425 | ** Will be patched to IFTRUE by the interrupt handler. | |
| 1426 | */ | |
| 1427 | SCR_INT ^ IFFALSE (0), | |
| 1428 | SIR_STALL_RESTART, | |
| 1429 | /* | |
| 1430 | ** Then jump to a certain point in tryloop. | |
| 1431 | ** Due to the lack of indirect addressing the code | |
| 1432 | ** is self modifying here. | |
| 1433 | */ | |
| 1434 | SCR_JUMP, | |
| 1435 | }/*-------------------------< STARTPOS >--------------------*/,{ | |
| 1436 | PADDRH(tryloop), | |
| 1437 | ||
| 1438 | }/*-------------------------< TRYSEL >----------------------*/,{ | |
| 1439 | /* | |
| 1440 | ** Now: | |
| 1441 | ** DSA: Address of a Data Structure | |
| 1442 | ** or Address of the IDLE-Label. | |
| 1443 | ** | |
| 1444 | ** TEMP: Address of a script, which tries to | |
| 1445 | ** start the NEXT entry. | |
| 1446 | ** | |
| 1447 | ** Save the TEMP register into the SCRATCHA register. | |
| 1448 | ** Then copy the DSA to TEMP and RETURN. | |
| 1449 | ** This is kind of an indirect jump. | |
| 1450 | ** (The script processor has NO stack, so the | |
| 1451 | ** CALL is actually a jump and link, and the | |
| 1452 | ** RETURN is an indirect jump.) | |
| 1453 | ** | |
| 1454 | ** If the slot was empty, DSA contains the address | |
| 1455 | ** of the IDLE part of this script. The processor | |
| 1456 | ** jumps to IDLE and waits for a reselect. | |
| 1457 | ** It will wake up and try the same slot again | |
| 1458 | ** after the SIGP bit becomes set by the host. | |
| 1459 | ** | |
| 1460 | ** If the slot was not empty, DSA contains | |
| 1461 | ** the address of the phys-part of a nccb. | |
| 1462 | ** The processor jumps to this address. | |
| 1463 | ** phys starts with head, | |
| 1464 | ** head starts with launch, | |
| 1465 | ** so actually the processor jumps to | |
| 1466 | ** the lauch part. | |
| 1467 | ** If the entry is scheduled for execution, | |
| 1468 | ** then launch contains a jump to SELECT. | |
| 1469 | ** If it's not scheduled, it contains a jump to IDLE. | |
| 1470 | */ | |
| 1471 | SCR_COPY (4), | |
| 1472 | RADDR (temp), | |
| 1473 | RADDR (scratcha), | |
| 1474 | SCR_COPY (4), | |
| 1475 | RADDR (dsa), | |
| 1476 | RADDR (temp), | |
| 1477 | SCR_RETURN, | |
| 1478 | 0 | |
| 1479 | ||
| 1480 | }/*-------------------------< SKIP >------------------------*/,{ | |
| 1481 | /* | |
| 1482 | ** This entry has been canceled. | |
| 1483 | ** Next time use the next slot. | |
| 1484 | */ | |
| 1485 | SCR_COPY (4), | |
| 1486 | RADDR (scratcha), | |
| 1487 | PADDR (startpos), | |
| 1488 | /* | |
| 1489 | ** patch the launch field. | |
| 1490 | ** should look like an idle process. | |
| 1491 | */ | |
| 1492 | SCR_COPY_F (4), | |
| 1493 | RADDR (dsa), | |
| 1494 | PADDR (skip2), | |
| 1495 | SCR_COPY (8), | |
| 1496 | PADDR (idle), | |
| 1497 | }/*-------------------------< SKIP2 >-----------------------*/,{ | |
| 1498 | 0, | |
| 1499 | SCR_JUMP, | |
| 1500 | PADDR(start), | |
| 1501 | }/*-------------------------< IDLE >------------------------*/,{ | |
| 1502 | /* | |
| 1503 | ** Nothing to do? | |
| 1504 | ** Wait for reselect. | |
| 1505 | */ | |
| 1506 | SCR_JUMP, | |
| 1507 | PADDR(reselect), | |
| 1508 | ||
| 1509 | }/*-------------------------< SELECT >----------------------*/,{ | |
| 1510 | /* | |
| 1511 | ** DSA contains the address of a scheduled | |
| 1512 | ** data structure. | |
| 1513 | ** | |
| 1514 | ** SCRATCHA contains the address of the script, | |
| 1515 | ** which starts the next entry. | |
| 1516 | ** | |
| 1517 | ** Set Initiator mode. | |
| 1518 | ** | |
| 1519 | ** (Target mode is left as an exercise for the reader) | |
| 1520 | */ | |
| 1521 | ||
| 1522 | SCR_CLR (SCR_TRG), | |
| 1523 | 0, | |
| 1524 | SCR_LOAD_REG (HS_REG, 0xff), | |
| 1525 | 0, | |
| 1526 | ||
| 1527 | /* | |
| 1528 | ** And try to select this target. | |
| 1529 | */ | |
| 1530 | SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), | |
| 1531 | PADDR (reselect), | |
| 1532 | ||
| 1533 | /* | |
| 1534 | ** Now there are 4 possibilities: | |
| 1535 | ** | |
| 1536 | ** (1) The ncr looses arbitration. | |
| 1537 | ** This is ok, because it will try again, | |
| 1538 | ** when the bus becomes idle. | |
| 1539 | ** (But beware of the timeout function!) | |
| 1540 | ** | |
| 1541 | ** (2) The ncr is reselected. | |
| 1542 | ** Then the script processor takes the jump | |
| 1543 | ** to the RESELECT label. | |
| 1544 | ** | |
| 1545 | ** (3) The ncr completes the selection. | |
| 1546 | ** Then it will execute the next statement. | |
| 1547 | ** | |
| 1548 | ** (4) There is a selection timeout. | |
| 1549 | ** Then the ncr should interrupt the host and stop. | |
| 1550 | ** Unfortunately, it seems to continue execution | |
| 1551 | ** of the script. But it will fail with an | |
| 1552 | ** IID-interrupt on the next WHEN. | |
| 1553 | */ | |
| 1554 | ||
| 1555 | SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), | |
| 1556 | 0, | |
| 1557 | ||
| 1558 | /* | |
| 1559 | ** Send the IDENTIFY and SIMPLE_TAG messages | |
| 1560 | ** (and the MSG_EXT_SDTR message) | |
| 1561 | */ | |
| 1562 | SCR_MOVE_TBL ^ SCR_MSG_OUT, | |
| 1563 | offsetof (struct dsb, smsg), | |
| 1564 | #ifdef undef /* XXX better fail than try to deal with this ... */ | |
| 1565 | SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)), | |
| 1566 | -16, | |
| 1567 | #endif | |
| 1568 | SCR_CLR (SCR_ATN), | |
| 1569 | 0, | |
| 1570 | SCR_COPY (1), | |
| 1571 | RADDR (sfbr), | |
| 1572 | NADDR (lastmsg), | |
| 1573 | /* | |
| 1574 | ** Selection complete. | |
| 1575 | ** Next time use the next slot. | |
| 1576 | */ | |
| 1577 | SCR_COPY (4), | |
| 1578 | RADDR (scratcha), | |
| 1579 | PADDR (startpos), | |
| 1580 | }/*-------------------------< PREPARE >----------------------*/,{ | |
| 1581 | /* | |
| 1582 | ** The ncr doesn't have an indirect load | |
| 1583 | ** or store command. So we have to | |
| 1584 | ** copy part of the control block to a | |
| 1585 | ** fixed place, where we can access it. | |
| 1586 | ** | |
| 1587 | ** We patch the address part of a | |
| 1588 | ** COPY command with the DSA-register. | |
| 1589 | */ | |
| 1590 | SCR_COPY_F (4), | |
| 1591 | RADDR (dsa), | |
| 1592 | PADDR (loadpos), | |
| 1593 | /* | |
| 1594 | ** then we do the actual copy. | |
| 1595 | */ | |
| 1596 | SCR_COPY (sizeof (struct head)), | |
| 1597 | /* | |
| 1598 | ** continued after the next label ... | |
| 1599 | */ | |
| 1600 | ||
| 1601 | }/*-------------------------< LOADPOS >---------------------*/,{ | |
| 1602 | 0, | |
| 1603 | NADDR (header), | |
| 1604 | /* | |
| 1605 | ** Mark this nccb as not scheduled. | |
| 1606 | */ | |
| 1607 | SCR_COPY (8), | |
| 1608 | PADDR (idle), | |
| 1609 | NADDR (header.launch), | |
| 1610 | /* | |
| 1611 | ** Set a time stamp for this selection | |
| 1612 | */ | |
| 1613 | SCR_COPY (sizeof (ticks)), | |
| 1614 | KVAR (KVAR_TICKS), | |
| 1615 | NADDR (header.stamp.select), | |
| 1616 | /* | |
| 1617 | ** load the savep (saved pointer) into | |
| 1618 | ** the TEMP register (actual pointer) | |
| 1619 | */ | |
| 1620 | SCR_COPY (4), | |
| 1621 | NADDR (header.savep), | |
| 1622 | RADDR (temp), | |
| 1623 | /* | |
| 1624 | ** Initialize the status registers | |
| 1625 | */ | |
| 1626 | SCR_COPY (4), | |
| 1627 | NADDR (header.status), | |
| 1628 | RADDR (scr0), | |
| 1629 | ||
| 1630 | }/*-------------------------< PREPARE2 >---------------------*/,{ | |
| 1631 | /* | |
| 1632 | ** Load the synchronous mode register | |
| 1633 | */ | |
| 1634 | SCR_COPY (1), | |
| 1635 | NADDR (sync_st), | |
| 1636 | RADDR (sxfer), | |
| 1637 | /* | |
| 1638 | ** Load the wide mode and timing register | |
| 1639 | */ | |
| 1640 | SCR_COPY (1), | |
| 1641 | NADDR (wide_st), | |
| 1642 | RADDR (scntl3), | |
| 1643 | /* | |
| 1644 | ** Initialize the msgout buffer with a NOOP message. | |
| 1645 | */ | |
| 1646 | SCR_LOAD_REG (scratcha, MSG_NOOP), | |
| 1647 | 0, | |
| 1648 | SCR_COPY (1), | |
| 1649 | RADDR (scratcha), | |
| 1650 | NADDR (msgout), | |
| 1651 | SCR_COPY (1), | |
| 1652 | RADDR (scratcha), | |
| 1653 | NADDR (msgin), | |
| 1654 | /* | |
| 1655 | ** Message in phase ? | |
| 1656 | */ | |
| 1657 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 1658 | PADDR (dispatch), | |
| 1659 | /* | |
| 1660 | ** Extended or reject message ? | |
| 1661 | */ | |
| 1662 | SCR_FROM_REG (sbdl), | |
| 1663 | 0, | |
| 1664 | SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), | |
| 1665 | PADDR (msg_in), | |
| 1666 | SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), | |
| 1667 | PADDRH (msg_reject), | |
| 1668 | /* | |
| 1669 | ** normal processing | |
| 1670 | */ | |
| 1671 | SCR_JUMP, | |
| 1672 | PADDR (dispatch), | |
| 1673 | }/*-------------------------< SETMSG >----------------------*/,{ | |
| 1674 | SCR_COPY (1), | |
| 1675 | RADDR (scratcha), | |
| 1676 | NADDR (msgout), | |
| 1677 | SCR_SET (SCR_ATN), | |
| 1678 | 0, | |
| 1679 | }/*-------------------------< CLRACK >----------------------*/,{ | |
| 1680 | /* | |
| 1681 | ** Terminate possible pending message phase. | |
| 1682 | */ | |
| 1683 | SCR_CLR (SCR_ACK), | |
| 1684 | 0, | |
| 1685 | ||
| 1686 | }/*-----------------------< DISPATCH >----------------------*/,{ | |
| 1687 | SCR_FROM_REG (HS_REG), | |
| 1688 | 0, | |
| 1689 | SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), | |
| 1690 | SIR_NEGO_FAILED, | |
| 1691 | /* | |
| 1692 | ** remove bogus output signals | |
| 1693 | */ | |
| 1694 | SCR_REG_REG (socl, SCR_AND, CACK|CATN), | |
| 1695 | 0, | |
| 1696 | SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)), | |
| 1697 | 0, | |
| 1698 | SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)), | |
| 1699 | 0, | |
| 1700 | SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), | |
| 1701 | PADDR (msg_out), | |
| 1702 | SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)), | |
| 1703 | PADDR (msg_in), | |
| 1704 | SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), | |
| 1705 | PADDR (command), | |
| 1706 | SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), | |
| 1707 | PADDR (status), | |
| 1708 | /* | |
| 1709 | ** Discard one illegal phase byte, if required. | |
| 1710 | */ | |
| 1711 | SCR_LOAD_REG (scratcha, XE_BAD_PHASE), | |
| 1712 | 0, | |
| 1713 | SCR_COPY (1), | |
| 1714 | RADDR (scratcha), | |
| 1715 | NADDR (xerr_st), | |
| 1716 | SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)), | |
| 1717 | 8, | |
| 1718 | SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, | |
| 1719 | NADDR (scratch), | |
| 1720 | SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)), | |
| 1721 | 8, | |
| 1722 | SCR_MOVE_ABS (1) ^ SCR_ILG_IN, | |
| 1723 | NADDR (scratch), | |
| 1724 | SCR_JUMP, | |
| 1725 | PADDR (dispatch), | |
| 1726 | ||
| 1727 | }/*-------------------------< NO_DATA >--------------------*/,{ | |
| 1728 | /* | |
| 1729 | ** The target wants to tranfer too much data | |
| 1730 | ** or in the wrong direction. | |
| 1731 | ** Remember that in extended error. | |
| 1732 | */ | |
| 1733 | SCR_LOAD_REG (scratcha, XE_EXTRA_DATA), | |
| 1734 | 0, | |
| 1735 | SCR_COPY (1), | |
| 1736 | RADDR (scratcha), | |
| 1737 | NADDR (xerr_st), | |
| 1738 | /* | |
| 1739 | ** Discard one data byte, if required. | |
| 1740 | */ | |
| 1741 | SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), | |
| 1742 | 8, | |
| 1743 | SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, | |
| 1744 | NADDR (scratch), | |
| 1745 | SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), | |
| 1746 | 8, | |
| 1747 | SCR_MOVE_ABS (1) ^ SCR_DATA_IN, | |
| 1748 | NADDR (scratch), | |
| 1749 | /* | |
| 1750 | ** .. and repeat as required. | |
| 1751 | */ | |
| 1752 | SCR_CALL, | |
| 1753 | PADDR (dispatch), | |
| 1754 | SCR_JUMP, | |
| 1755 | PADDR (no_data), | |
| 1756 | }/*-------------------------< CHECKATN >--------------------*/,{ | |
| 1757 | /* | |
| 1758 | ** If AAP (bit 1 of scntl0 register) is set | |
| 1759 | ** and a parity error is detected, | |
| 1760 | ** the script processor asserts ATN. | |
| 1761 | ** | |
| 1762 | ** The target should switch to a MSG_OUT phase | |
| 1763 | ** to get the message. | |
| 1764 | */ | |
| 1765 | SCR_FROM_REG (socl), | |
| 1766 | 0, | |
| 1767 | SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)), | |
| 1768 | PADDR (dispatch), | |
| 1769 | /* | |
| 1770 | ** count it | |
| 1771 | */ | |
| 1772 | SCR_REG_REG (PS_REG, SCR_ADD, 1), | |
| 1773 | 0, | |
| 1774 | /* | |
| 1775 | ** Prepare a MSG_INITIATOR_DET_ERR message | |
| 1776 | ** (initiator detected error). | |
| 1777 | ** The target should retry the transfer. | |
| 1778 | */ | |
| 1779 | SCR_LOAD_REG (scratcha, MSG_INITIATOR_DET_ERR), | |
| 1780 | 0, | |
| 1781 | SCR_JUMP, | |
| 1782 | PADDR (setmsg), | |
| 1783 | ||
| 1784 | }/*-------------------------< COMMAND >--------------------*/,{ | |
| 1785 | /* | |
| 1786 | ** If this is not a GETCC transfer ... | |
| 1787 | */ | |
| 1788 | SCR_FROM_REG (SS_REG), | |
| 1789 | 0, | |
| 1790 | /*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), | |
| 1791 | 28, | |
| 1792 | /* | |
| 1793 | ** ... set a timestamp ... | |
| 1794 | */ | |
| 1795 | SCR_COPY (sizeof (ticks)), | |
| 1796 | KVAR (KVAR_TICKS), | |
| 1797 | NADDR (header.stamp.command), | |
| 1798 | /* | |
| 1799 | ** ... and send the command | |
| 1800 | */ | |
| 1801 | SCR_MOVE_TBL ^ SCR_COMMAND, | |
| 1802 | offsetof (struct dsb, cmd), | |
| 1803 | SCR_JUMP, | |
| 1804 | PADDR (dispatch), | |
| 1805 | /* | |
| 1806 | ** Send the GETCC command | |
| 1807 | */ | |
| 1808 | /*>>>*/ SCR_MOVE_TBL ^ SCR_COMMAND, | |
| 1809 | offsetof (struct dsb, scmd), | |
| 1810 | SCR_JUMP, | |
| 1811 | PADDR (dispatch), | |
| 1812 | ||
| 1813 | }/*-------------------------< STATUS >--------------------*/,{ | |
| 1814 | /* | |
| 1815 | ** set the timestamp. | |
| 1816 | */ | |
| 1817 | SCR_COPY (sizeof (ticks)), | |
| 1818 | KVAR (KVAR_TICKS), | |
| 1819 | NADDR (header.stamp.status), | |
| 1820 | /* | |
| 1821 | ** If this is a GETCC transfer, | |
| 1822 | */ | |
| 1823 | SCR_FROM_REG (SS_REG), | |
| 1824 | 0, | |
| 1825 | /*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (SCSI_STATUS_CHECK_COND)), | |
| 1826 | 40, | |
| 1827 | /* | |
| 1828 | ** get the status | |
| 1829 | */ | |
| 1830 | SCR_MOVE_ABS (1) ^ SCR_STATUS, | |
| 1831 | NADDR (scratch), | |
| 1832 | /* | |
| 1833 | ** Save status to scsi_status. | |
| 1834 | ** Mark as complete. | |
| 1835 | ** And wait for disconnect. | |
| 1836 | */ | |
| 1837 | SCR_TO_REG (SS_REG), | |
| 1838 | 0, | |
| 1839 | SCR_REG_REG (SS_REG, SCR_OR, SCSI_STATUS_SENSE), | |
| 1840 | 0, | |
| 1841 | SCR_LOAD_REG (HS_REG, HS_COMPLETE), | |
| 1842 | 0, | |
| 1843 | SCR_JUMP, | |
| 1844 | PADDR (checkatn), | |
| 1845 | /* | |
| 1846 | ** If it was no GETCC transfer, | |
| 1847 | ** save the status to scsi_status. | |
| 1848 | */ | |
| 1849 | /*>>>*/ SCR_MOVE_ABS (1) ^ SCR_STATUS, | |
| 1850 | NADDR (scratch), | |
| 1851 | SCR_TO_REG (SS_REG), | |
| 1852 | 0, | |
| 1853 | /* | |
| 1854 | ** if it was no check condition ... | |
| 1855 | */ | |
| 1856 | SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), | |
| 1857 | PADDR (checkatn), | |
| 1858 | /* | |
| 1859 | ** ... mark as complete. | |
| 1860 | */ | |
| 1861 | SCR_LOAD_REG (HS_REG, HS_COMPLETE), | |
| 1862 | 0, | |
| 1863 | SCR_JUMP, | |
| 1864 | PADDR (checkatn), | |
| 1865 | ||
| 1866 | }/*-------------------------< MSG_IN >--------------------*/,{ | |
| 1867 | /* | |
| 1868 | ** Get the first byte of the message | |
| 1869 | ** and save it to SCRATCHA. | |
| 1870 | ** | |
| 1871 | ** The script processor doesn't negate the | |
| 1872 | ** ACK signal after this transfer. | |
| 1873 | */ | |
| 1874 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 1875 | NADDR (msgin[0]), | |
| 1876 | /* | |
| 1877 | ** Check for message parity error. | |
| 1878 | */ | |
| 1879 | SCR_TO_REG (scratcha), | |
| 1880 | 0, | |
| 1881 | SCR_FROM_REG (socl), | |
| 1882 | 0, | |
| 1883 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 1884 | PADDRH (msg_parity), | |
| 1885 | SCR_FROM_REG (scratcha), | |
| 1886 | 0, | |
| 1887 | /* | |
| 1888 | ** Parity was ok, handle this message. | |
| 1889 | */ | |
| 1890 | SCR_JUMP ^ IFTRUE (DATA (MSG_CMDCOMPLETE)), | |
| 1891 | PADDR (complete), | |
| 1892 | SCR_JUMP ^ IFTRUE (DATA (MSG_SAVEDATAPOINTER)), | |
| 1893 | PADDR (save_dp), | |
| 1894 | SCR_JUMP ^ IFTRUE (DATA (MSG_RESTOREPOINTERS)), | |
| 1895 | PADDR (restore_dp), | |
| 1896 | SCR_JUMP ^ IFTRUE (DATA (MSG_DISCONNECT)), | |
| 1897 | PADDR (disconnect), | |
| 1898 | SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), | |
| 1899 | PADDRH (msg_extended), | |
| 1900 | SCR_JUMP ^ IFTRUE (DATA (MSG_NOOP)), | |
| 1901 | PADDR (clrack), | |
| 1902 | SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), | |
| 1903 | PADDRH (msg_reject), | |
| 1904 | SCR_JUMP ^ IFTRUE (DATA (MSG_IGN_WIDE_RESIDUE)), | |
| 1905 | PADDRH (msg_ign_residue), | |
| 1906 | /* | |
| 1907 | ** Rest of the messages left as | |
| 1908 | ** an exercise ... | |
| 1909 | ** | |
| 1910 | ** Unimplemented messages: | |
| 1911 | ** fall through to MSG_BAD. | |
| 1912 | */ | |
| 1913 | }/*-------------------------< MSG_BAD >------------------*/,{ | |
| 1914 | /* | |
| 1915 | ** unimplemented message - reject it. | |
| 1916 | */ | |
| 1917 | SCR_INT, | |
| 1918 | SIR_REJECT_SENT, | |
| 1919 | SCR_LOAD_REG (scratcha, MSG_MESSAGE_REJECT), | |
| 1920 | 0, | |
| 1921 | SCR_JUMP, | |
| 1922 | PADDR (setmsg), | |
| 1923 | ||
| 1924 | }/*-------------------------< COMPLETE >-----------------*/,{ | |
| 1925 | /* | |
| 1926 | ** Complete message. | |
| 1927 | ** | |
| 1928 | ** If it's not the get condition code, | |
| 1929 | ** copy TEMP register to LASTP in header. | |
| 1930 | */ | |
| 1931 | SCR_FROM_REG (SS_REG), | |
| 1932 | 0, | |
| 1933 | /*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (SCSI_STATUS_SENSE, SCSI_STATUS_SENSE)), | |
| 1934 | 12, | |
| 1935 | SCR_COPY (4), | |
| 1936 | RADDR (temp), | |
| 1937 | NADDR (header.lastp), | |
| 1938 | /*>>>*/ /* | |
| 1939 | ** When we terminate the cycle by clearing ACK, | |
| 1940 | ** the target may disconnect immediately. | |
| 1941 | ** | |
| 1942 | ** We don't want to be told of an | |
| 1943 | ** "unexpected disconnect", | |
| 1944 | ** so we disable this feature. | |
| 1945 | */ | |
| 1946 | SCR_REG_REG (scntl2, SCR_AND, 0x7f), | |
| 1947 | 0, | |
| 1948 | /* | |
| 1949 | ** Terminate cycle ... | |
| 1950 | */ | |
| 1951 | SCR_CLR (SCR_ACK|SCR_ATN), | |
| 1952 | 0, | |
| 1953 | /* | |
| 1954 | ** ... and wait for the disconnect. | |
| 1955 | */ | |
| 1956 | SCR_WAIT_DISC, | |
| 1957 | 0, | |
| 1958 | }/*-------------------------< CLEANUP >-------------------*/,{ | |
| 1959 | /* | |
| 1960 | ** dsa: Pointer to nccb | |
| 1961 | ** or xxxxxxFF (no nccb) | |
| 1962 | ** | |
| 1963 | ** HS_REG: Host-Status (<>0!) | |
| 1964 | */ | |
| 1965 | SCR_FROM_REG (dsa), | |
| 1966 | 0, | |
| 1967 | SCR_JUMP ^ IFTRUE (DATA (0xff)), | |
| 1968 | PADDR (signal), | |
| 1969 | /* | |
| 1970 | ** dsa is valid. | |
| 1971 | ** save the status registers | |
| 1972 | */ | |
| 1973 | SCR_COPY (4), | |
| 1974 | RADDR (scr0), | |
| 1975 | NADDR (header.status), | |
| 1976 | /* | |
| 1977 | ** and copy back the header to the nccb. | |
| 1978 | */ | |
| 1979 | SCR_COPY_F (4), | |
| 1980 | RADDR (dsa), | |
| 1981 | PADDR (cleanup0), | |
| 1982 | SCR_COPY (sizeof (struct head)), | |
| 1983 | NADDR (header), | |
| 1984 | }/*-------------------------< CLEANUP0 >--------------------*/,{ | |
| 1985 | 0, | |
| 1986 | ||
| 1987 | /* | |
| 1988 | ** If command resulted in "check condition" | |
| 1989 | ** status and is not yet completed, | |
| 1990 | ** try to get the condition code. | |
| 1991 | */ | |
| 1992 | SCR_FROM_REG (HS_REG), | |
| 1993 | 0, | |
| 1994 | /*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), | |
| 1995 | 16, | |
| 1996 | SCR_FROM_REG (SS_REG), | |
| 1997 | 0, | |
| 1998 | SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), | |
| 1999 | PADDRH(getcc2), | |
| 2000 | }/*-------------------------< SIGNAL >----------------------*/,{ | |
| 2001 | /* | |
| 2002 | ** if status = queue full, | |
| 2003 | ** reinsert in startqueue and stall queue. | |
| 2004 | */ | |
| 2005 | /*>>>*/ SCR_FROM_REG (SS_REG), | |
| 2006 | 0, | |
| 2007 | SCR_INT ^ IFTRUE (DATA (SCSI_STATUS_QUEUE_FULL)), | |
| 2008 | SIR_STALL_QUEUE, | |
| 2009 | /* | |
| 2010 | ** And make the DSA register invalid. | |
| 2011 | */ | |
| 2012 | SCR_LOAD_REG (dsa, 0xff), /* invalid */ | |
| 2013 | 0, | |
| 2014 | /* | |
| 2015 | ** if job completed ... | |
| 2016 | */ | |
| 2017 | SCR_FROM_REG (HS_REG), | |
| 2018 | 0, | |
| 2019 | /* | |
| 2020 | ** ... signal completion to the host | |
| 2021 | */ | |
| 2022 | SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), | |
| 2023 | 0, | |
| 2024 | /* | |
| 2025 | ** Auf zu neuen Schandtaten! | |
| 2026 | */ | |
| 2027 | SCR_JUMP, | |
| 2028 | PADDR(start), | |
| 2029 | ||
| 2030 | }/*-------------------------< SAVE_DP >------------------*/,{ | |
| 2031 | /* | |
| 2032 | ** SAVE_DP message: | |
| 2033 | ** Copy TEMP register to SAVEP in header. | |
| 2034 | */ | |
| 2035 | SCR_COPY (4), | |
| 2036 | RADDR (temp), | |
| 2037 | NADDR (header.savep), | |
| 2038 | SCR_JUMP, | |
| 2039 | PADDR (clrack), | |
| 2040 | }/*-------------------------< RESTORE_DP >---------------*/,{ | |
| 2041 | /* | |
| 2042 | ** RESTORE_DP message: | |
| 2043 | ** Copy SAVEP in header to TEMP register. | |
| 2044 | */ | |
| 2045 | SCR_COPY (4), | |
| 2046 | NADDR (header.savep), | |
| 2047 | RADDR (temp), | |
| 2048 | SCR_JUMP, | |
| 2049 | PADDR (clrack), | |
| 2050 | ||
| 2051 | }/*-------------------------< DISCONNECT >---------------*/,{ | |
| 2052 | /* | |
| 2053 | ** If QUIRK_AUTOSAVE is set, | |
| 2054 | ** do an "save pointer" operation. | |
| 2055 | */ | |
| 2056 | SCR_FROM_REG (QU_REG), | |
| 2057 | 0, | |
| 2058 | /*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), | |
| 2059 | 12, | |
| 2060 | /* | |
| 2061 | ** like SAVE_DP message: | |
| 2062 | ** Copy TEMP register to SAVEP in header. | |
| 2063 | */ | |
| 2064 | SCR_COPY (4), | |
| 2065 | RADDR (temp), | |
| 2066 | NADDR (header.savep), | |
| 2067 | /*>>>*/ /* | |
| 2068 | ** Check if temp==savep or temp==goalp: | |
| 2069 | ** if not, log a missing save pointer message. | |
| 2070 | ** In fact, it's a comparison mod 256. | |
| 2071 | ** | |
| 2072 | ** Hmmm, I hadn't thought that I would be urged to | |
| 2073 | ** write this kind of ugly self modifying code. | |
| 2074 | ** | |
| 2075 | ** It's unbelievable, but the ncr53c8xx isn't able | |
| 2076 | ** to subtract one register from another. | |
| 2077 | */ | |
| 2078 | SCR_FROM_REG (temp), | |
| 2079 | 0, | |
| 2080 | /* | |
| 2081 | ** You are not expected to understand this .. | |
| 2082 | ** | |
| 2083 | ** CAUTION: only little endian architectures supported! XXX | |
| 2084 | */ | |
| 2085 | SCR_COPY_F (1), | |
| 2086 | NADDR (header.savep), | |
| 2087 | PADDR (disconnect0), | |
| 2088 | }/*-------------------------< DISCONNECT0 >--------------*/,{ | |
| 2089 | /*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), | |
| 2090 | 20, | |
| 2091 | /* | |
| 2092 | ** neither this | |
| 2093 | */ | |
| 2094 | SCR_COPY_F (1), | |
| 2095 | NADDR (header.goalp), | |
| 2096 | PADDR (disconnect1), | |
| 2097 | }/*-------------------------< DISCONNECT1 >--------------*/,{ | |
| 2098 | SCR_INT ^ IFFALSE (DATA (1)), | |
| 2099 | SIR_MISSING_SAVE, | |
| 2100 | /*>>>*/ | |
| 2101 | ||
| 2102 | /* | |
| 2103 | ** DISCONNECTing ... | |
| 2104 | ** | |
| 2105 | ** disable the "unexpected disconnect" feature, | |
| 2106 | ** and remove the ACK signal. | |
| 2107 | */ | |
| 2108 | SCR_REG_REG (scntl2, SCR_AND, 0x7f), | |
| 2109 | 0, | |
| 2110 | SCR_CLR (SCR_ACK|SCR_ATN), | |
| 2111 | 0, | |
| 2112 | /* | |
| 2113 | ** Wait for the disconnect. | |
| 2114 | */ | |
| 2115 | SCR_WAIT_DISC, | |
| 2116 | 0, | |
| 2117 | /* | |
| 2118 | ** Profiling: | |
| 2119 | ** Set a time stamp, | |
| 2120 | ** and count the disconnects. | |
| 2121 | */ | |
| 2122 | SCR_COPY (sizeof (ticks)), | |
| 2123 | KVAR (KVAR_TICKS), | |
| 2124 | NADDR (header.stamp.disconnect), | |
| 2125 | SCR_COPY (4), | |
| 2126 | NADDR (disc_phys), | |
| 2127 | RADDR (temp), | |
| 2128 | SCR_REG_REG (temp, SCR_ADD, 0x01), | |
| 2129 | 0, | |
| 2130 | SCR_COPY (4), | |
| 2131 | RADDR (temp), | |
| 2132 | NADDR (disc_phys), | |
| 2133 | /* | |
| 2134 | ** Status is: DISCONNECTED. | |
| 2135 | */ | |
| 2136 | SCR_LOAD_REG (HS_REG, HS_DISCONNECT), | |
| 2137 | 0, | |
| 2138 | SCR_JUMP, | |
| 2139 | PADDR (cleanup), | |
| 2140 | ||
| 2141 | }/*-------------------------< MSG_OUT >-------------------*/,{ | |
| 2142 | /* | |
| 2143 | ** The target requests a message. | |
| 2144 | */ | |
| 2145 | SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, | |
| 2146 | NADDR (msgout), | |
| 2147 | SCR_COPY (1), | |
| 2148 | RADDR (sfbr), | |
| 2149 | NADDR (lastmsg), | |
| 2150 | /* | |
| 2151 | ** If it was no ABORT message ... | |
| 2152 | */ | |
| 2153 | SCR_JUMP ^ IFTRUE (DATA (MSG_ABORT)), | |
| 2154 | PADDRH (msg_out_abort), | |
| 2155 | /* | |
| 2156 | ** ... wait for the next phase | |
| 2157 | ** if it's a message out, send it again, ... | |
| 2158 | */ | |
| 2159 | SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), | |
| 2160 | PADDR (msg_out), | |
| 2161 | }/*-------------------------< MSG_OUT_DONE >--------------*/,{ | |
| 2162 | /* | |
| 2163 | ** ... else clear the message ... | |
| 2164 | */ | |
| 2165 | SCR_LOAD_REG (scratcha, MSG_NOOP), | |
| 2166 | 0, | |
| 2167 | SCR_COPY (4), | |
| 2168 | RADDR (scratcha), | |
| 2169 | NADDR (msgout), | |
| 2170 | /* | |
| 2171 | ** ... and process the next phase | |
| 2172 | */ | |
| 2173 | SCR_JUMP, | |
| 2174 | PADDR (dispatch), | |
| 2175 | ||
| 2176 | }/*------------------------< BADGETCC >---------------------*/,{ | |
| 2177 | /* | |
| 2178 | ** If SIGP was set, clear it and try again. | |
| 2179 | */ | |
| 2180 | SCR_FROM_REG (ctest2), | |
| 2181 | 0, | |
| 2182 | SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), | |
| 2183 | PADDRH (getcc2), | |
| 2184 | SCR_INT, | |
| 2185 | SIR_SENSE_FAILED, | |
| 2186 | }/*-------------------------< RESELECT >--------------------*/,{ | |
| 2187 | /* | |
| 2188 | ** This NOP will be patched with LED OFF | |
| 2189 | ** SCR_REG_REG (gpreg, SCR_OR, 0x01) | |
| 2190 | */ | |
| 2191 | SCR_NO_OP, | |
| 2192 | 0, | |
| 2193 | ||
| 2194 | /* | |
| 2195 | ** make the DSA invalid. | |
| 2196 | */ | |
| 2197 | SCR_LOAD_REG (dsa, 0xff), | |
| 2198 | 0, | |
| 2199 | SCR_CLR (SCR_TRG), | |
| 2200 | 0, | |
| 2201 | /* | |
| 2202 | ** Sleep waiting for a reselection. | |
| 2203 | ** If SIGP is set, special treatment. | |
| 2204 | ** | |
| 2205 | ** Zu allem bereit .. | |
| 2206 | */ | |
| 2207 | SCR_WAIT_RESEL, | |
| 2208 | PADDR(reselect2), | |
| 2209 | }/*-------------------------< RESELECT1 >--------------------*/,{ | |
| 2210 | /* | |
| 2211 | ** This NOP will be patched with LED ON | |
| 2212 | ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) | |
| 2213 | */ | |
| 2214 | SCR_NO_OP, | |
| 2215 | 0, | |
| 2216 | /* | |
| 2217 | ** ... zu nichts zu gebrauchen ? | |
| 2218 | ** | |
| 2219 | ** load the target id into the SFBR | |
| 2220 | ** and jump to the control block. | |
| 2221 | ** | |
| 2222 | ** Look at the declarations of | |
| 2223 | ** - struct ncb | |
| 2224 | ** - struct tcb | |
| 2225 | ** - struct lcb | |
| 2226 | ** - struct nccb | |
| 2227 | ** to understand what's going on. | |
| 2228 | */ | |
| 2229 | SCR_REG_SFBR (ssid, SCR_AND, 0x8F), | |
| 2230 | 0, | |
| 2231 | SCR_TO_REG (sdid), | |
| 2232 | 0, | |
| 2233 | SCR_JUMP, | |
| 2234 | NADDR (jump_tcb), | |
| 2235 | }/*-------------------------< RESELECT2 >-------------------*/,{ | |
| 2236 | /* | |
| 2237 | ** This NOP will be patched with LED ON | |
| 2238 | ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) | |
| 2239 | */ | |
| 2240 | SCR_NO_OP, | |
| 2241 | 0, | |
| 2242 | /* | |
| 2243 | ** If it's not connected :( | |
| 2244 | ** -> interrupted by SIGP bit. | |
| 2245 | ** Jump to start. | |
| 2246 | */ | |
| 2247 | SCR_FROM_REG (ctest2), | |
| 2248 | 0, | |
| 2249 | SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), | |
| 2250 | PADDR (start), | |
| 2251 | SCR_JUMP, | |
| 2252 | PADDR (reselect), | |
| 2253 | ||
| 2254 | }/*-------------------------< RESEL_TMP >-------------------*/,{ | |
| 2255 | /* | |
| 2256 | ** The return address in TEMP | |
| 2257 | ** is in fact the data structure address, | |
| 2258 | ** so copy it to the DSA register. | |
| 2259 | */ | |
| 2260 | SCR_COPY (4), | |
| 2261 | RADDR (temp), | |
| 2262 | RADDR (dsa), | |
| 2263 | SCR_JUMP, | |
| 2264 | PADDR (prepare), | |
| 2265 | ||
| 2266 | }/*-------------------------< RESEL_LUN >-------------------*/,{ | |
| 2267 | /* | |
| 2268 | ** come back to this point | |
| 2269 | ** to get an IDENTIFY message | |
| 2270 | ** Wait for a msg_in phase. | |
| 2271 | */ | |
| 2272 | /*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2273 | 48, | |
| 2274 | /* | |
| 2275 | ** message phase | |
| 2276 | ** It's not a sony, it's a trick: | |
| 2277 | ** read the data without acknowledging it. | |
| 2278 | */ | |
| 2279 | SCR_FROM_REG (sbdl), | |
| 2280 | 0, | |
| 2281 | /*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (MSG_IDENTIFYFLAG, 0x98)), | |
| 2282 | 32, | |
| 2283 | /* | |
| 2284 | ** It WAS an Identify message. | |
| 2285 | ** get it and ack it! | |
| 2286 | */ | |
| 2287 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2288 | NADDR (msgin), | |
| 2289 | SCR_CLR (SCR_ACK), | |
| 2290 | 0, | |
| 2291 | /* | |
| 2292 | ** Mask out the lun. | |
| 2293 | */ | |
| 2294 | SCR_REG_REG (sfbr, SCR_AND, 0x07), | |
| 2295 | 0, | |
| 2296 | SCR_RETURN, | |
| 2297 | 0, | |
| 2298 | /* | |
| 2299 | ** No message phase or no IDENTIFY message: | |
| 2300 | ** return 0. | |
| 2301 | */ | |
| 2302 | /*>>>*/ SCR_LOAD_SFBR (0), | |
| 2303 | 0, | |
| 2304 | SCR_RETURN, | |
| 2305 | 0, | |
| 2306 | ||
| 2307 | }/*-------------------------< RESEL_TAG >-------------------*/,{ | |
| 2308 | /* | |
| 2309 | ** come back to this point | |
| 2310 | ** to get a SIMPLE_TAG message | |
| 2311 | ** Wait for a MSG_IN phase. | |
| 2312 | */ | |
| 2313 | /*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2314 | 64, | |
| 2315 | /* | |
| 2316 | ** message phase | |
| 2317 | ** It's a trick - read the data | |
| 2318 | ** without acknowledging it. | |
| 2319 | */ | |
| 2320 | SCR_FROM_REG (sbdl), | |
| 2321 | 0, | |
| 2322 | /*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (MSG_SIMPLE_Q_TAG)), | |
| 2323 | 48, | |
| 2324 | /* | |
| 2325 | ** It WAS a SIMPLE_TAG message. | |
| 2326 | ** get it and ack it! | |
| 2327 | */ | |
| 2328 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2329 | NADDR (msgin), | |
| 2330 | SCR_CLR (SCR_ACK), | |
| 2331 | 0, | |
| 2332 | /* | |
| 2333 | ** Wait for the second byte (the tag) | |
| 2334 | */ | |
| 2335 | /*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2336 | 24, | |
| 2337 | /* | |
| 2338 | ** Get it and ack it! | |
| 2339 | */ | |
| 2340 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2341 | NADDR (msgin), | |
| 2342 | SCR_CLR (SCR_ACK|SCR_CARRY), | |
| 2343 | 0, | |
| 2344 | SCR_RETURN, | |
| 2345 | 0, | |
| 2346 | /* | |
| 2347 | ** No message phase or no SIMPLE_TAG message | |
| 2348 | ** or no second byte: return 0. | |
| 2349 | */ | |
| 2350 | /*>>>*/ SCR_LOAD_SFBR (0), | |
| 2351 | 0, | |
| 2352 | SCR_SET (SCR_CARRY), | |
| 2353 | 0, | |
| 2354 | SCR_RETURN, | |
| 2355 | 0, | |
| 2356 | ||
| 2357 | }/*-------------------------< DATA_IN >--------------------*/,{ | |
| 2358 | /* | |
| 2359 | ** Because the size depends on the | |
| 2360 | ** #define MAX_SCATTER parameter, | |
| 2361 | ** it is filled in at runtime. | |
| 2362 | ** | |
| 2363 | ** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), | |
| 2364 | ** PADDR (no_data), | |
| 2365 | ** SCR_COPY (sizeof (ticks)), | |
| 2366 | ** KVAR (KVAR_TICKS), | |
| 2367 | ** NADDR (header.stamp.data), | |
| 2368 | ** SCR_MOVE_TBL ^ SCR_DATA_IN, | |
| 2369 | ** offsetof (struct dsb, data[ 0]), | |
| 2370 | ** | |
| 2371 | ** ##===========< i=1; i<MAX_SCATTER >========= | |
| 2372 | ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), | |
| 2373 | ** || PADDR (checkatn), | |
| 2374 | ** || SCR_MOVE_TBL ^ SCR_DATA_IN, | |
| 2375 | ** || offsetof (struct dsb, data[ i]), | |
| 2376 | ** ##========================================== | |
| 2377 | ** | |
| 2378 | ** SCR_CALL, | |
| 2379 | ** PADDR (checkatn), | |
| 2380 | ** SCR_JUMP, | |
| 2381 | ** PADDR (no_data), | |
| 2382 | */ | |
| 2383 | 0 | |
| 2384 | }/*-------------------------< DATA_OUT >-------------------*/,{ | |
| 2385 | /* | |
| 2386 | ** Because the size depends on the | |
| 2387 | ** #define MAX_SCATTER parameter, | |
| 2388 | ** it is filled in at runtime. | |
| 2389 | ** | |
| 2390 | ** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)), | |
| 2391 | ** PADDR (no_data), | |
| 2392 | ** SCR_COPY (sizeof (ticks)), | |
| 2393 | ** KVAR (KVAR_TICKS), | |
| 2394 | ** NADDR (header.stamp.data), | |
| 2395 | ** SCR_MOVE_TBL ^ SCR_DATA_OUT, | |
| 2396 | ** offsetof (struct dsb, data[ 0]), | |
| 2397 | ** | |
| 2398 | ** ##===========< i=1; i<MAX_SCATTER >========= | |
| 2399 | ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), | |
| 2400 | ** || PADDR (dispatch), | |
| 2401 | ** || SCR_MOVE_TBL ^ SCR_DATA_OUT, | |
| 2402 | ** || offsetof (struct dsb, data[ i]), | |
| 2403 | ** ##========================================== | |
| 2404 | ** | |
| 2405 | ** SCR_CALL, | |
| 2406 | ** PADDR (dispatch), | |
| 2407 | ** SCR_JUMP, | |
| 2408 | ** PADDR (no_data), | |
| 2409 | ** | |
| 2410 | **--------------------------------------------------------- | |
| 2411 | */ | |
| 2412 | (u_long)0 | |
| 2413 | ||
| 2414 | }/*--------------------------------------------------------*/ | |
| 2415 | }; | |
| 2416 | ||
| 2417 | ||
| 2418 | static struct scripth scripth0 = { | |
| 2419 | /*-------------------------< TRYLOOP >---------------------*/{ | |
| 2420 | /* | |
| 2421 | ** Load an entry of the start queue into dsa | |
| 2422 | ** and try to start it by jumping to TRYSEL. | |
| 2423 | ** | |
| 2424 | ** Because the size depends on the | |
| 2425 | ** #define MAX_START parameter, it is filled | |
| 2426 | ** in at runtime. | |
| 2427 | ** | |
| 2428 | **----------------------------------------------------------- | |
| 2429 | ** | |
| 2430 | ** ##===========< I=0; i<MAX_START >=========== | |
| 2431 | ** || SCR_COPY (4), | |
| 2432 | ** || NADDR (squeue[i]), | |
| 2433 | ** || RADDR (dsa), | |
| 2434 | ** || SCR_CALL, | |
| 2435 | ** || PADDR (trysel), | |
| 2436 | ** ##========================================== | |
| 2437 | ** | |
| 2438 | ** SCR_JUMP, | |
| 2439 | ** PADDRH(tryloop), | |
| 2440 | ** | |
| 2441 | **----------------------------------------------------------- | |
| 2442 | */ | |
| 2443 | 0 | |
| 2444 | }/*-------------------------< MSG_PARITY >---------------*/,{ | |
| 2445 | /* | |
| 2446 | ** count it | |
| 2447 | */ | |
| 2448 | SCR_REG_REG (PS_REG, SCR_ADD, 0x01), | |
| 2449 | 0, | |
| 2450 | /* | |
| 2451 | ** send a "message parity error" message. | |
| 2452 | */ | |
| 2453 | SCR_LOAD_REG (scratcha, MSG_PARITY_ERROR), | |
| 2454 | 0, | |
| 2455 | SCR_JUMP, | |
| 2456 | PADDR (setmsg), | |
| 2457 | }/*-------------------------< MSG_MESSAGE_REJECT >---------------*/,{ | |
| 2458 | /* | |
| 2459 | ** If a negotiation was in progress, | |
| 2460 | ** negotiation failed. | |
| 2461 | */ | |
| 2462 | SCR_FROM_REG (HS_REG), | |
| 2463 | 0, | |
| 2464 | SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), | |
| 2465 | SIR_NEGO_FAILED, | |
| 2466 | /* | |
| 2467 | ** else make host log this message | |
| 2468 | */ | |
| 2469 | SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), | |
| 2470 | SIR_REJECT_RECEIVED, | |
| 2471 | SCR_JUMP, | |
| 2472 | PADDR (clrack), | |
| 2473 | ||
| 2474 | }/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ | |
| 2475 | /* | |
| 2476 | ** Terminate cycle | |
| 2477 | */ | |
| 2478 | SCR_CLR (SCR_ACK), | |
| 2479 | 0, | |
| 2480 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2481 | PADDR (dispatch), | |
| 2482 | /* | |
| 2483 | ** get residue size. | |
| 2484 | */ | |
| 2485 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2486 | NADDR (msgin[1]), | |
| 2487 | /* | |
| 2488 | ** Check for message parity error. | |
| 2489 | */ | |
| 2490 | SCR_TO_REG (scratcha), | |
| 2491 | 0, | |
| 2492 | SCR_FROM_REG (socl), | |
| 2493 | 0, | |
| 2494 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2495 | PADDRH (msg_parity), | |
| 2496 | SCR_FROM_REG (scratcha), | |
| 2497 | 0, | |
| 2498 | /* | |
| 2499 | ** Size is 0 .. ignore message. | |
| 2500 | */ | |
| 2501 | SCR_JUMP ^ IFTRUE (DATA (0)), | |
| 2502 | PADDR (clrack), | |
| 2503 | /* | |
| 2504 | ** Size is not 1 .. have to interrupt. | |
| 2505 | */ | |
| 2506 | /*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (1)), | |
| 2507 | 40, | |
| 2508 | /* | |
| 2509 | ** Check for residue byte in swide register | |
| 2510 | */ | |
| 2511 | SCR_FROM_REG (scntl2), | |
| 2512 | 0, | |
| 2513 | /*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), | |
| 2514 | 16, | |
| 2515 | /* | |
| 2516 | ** There IS data in the swide register. | |
| 2517 | ** Discard it. | |
| 2518 | */ | |
| 2519 | SCR_REG_REG (scntl2, SCR_OR, WSR), | |
| 2520 | 0, | |
| 2521 | SCR_JUMP, | |
| 2522 | PADDR (clrack), | |
| 2523 | /* | |
| 2524 | ** Load again the size to the sfbr register. | |
| 2525 | */ | |
| 2526 | /*>>>*/ SCR_FROM_REG (scratcha), | |
| 2527 | 0, | |
| 2528 | /*>>>*/ SCR_INT, | |
| 2529 | SIR_IGN_RESIDUE, | |
| 2530 | SCR_JUMP, | |
| 2531 | PADDR (clrack), | |
| 2532 | ||
| 2533 | }/*-------------------------< MSG_EXTENDED >-------------*/,{ | |
| 2534 | /* | |
| 2535 | ** Terminate cycle | |
| 2536 | */ | |
| 2537 | SCR_CLR (SCR_ACK), | |
| 2538 | 0, | |
| 2539 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2540 | PADDR (dispatch), | |
| 2541 | /* | |
| 2542 | ** get length. | |
| 2543 | */ | |
| 2544 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2545 | NADDR (msgin[1]), | |
| 2546 | /* | |
| 2547 | ** Check for message parity error. | |
| 2548 | */ | |
| 2549 | SCR_TO_REG (scratcha), | |
| 2550 | 0, | |
| 2551 | SCR_FROM_REG (socl), | |
| 2552 | 0, | |
| 2553 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2554 | PADDRH (msg_parity), | |
| 2555 | SCR_FROM_REG (scratcha), | |
| 2556 | 0, | |
| 2557 | /* | |
| 2558 | */ | |
| 2559 | SCR_JUMP ^ IFTRUE (DATA (3)), | |
| 2560 | PADDRH (msg_ext_3), | |
| 2561 | SCR_JUMP ^ IFFALSE (DATA (2)), | |
| 2562 | PADDR (msg_bad), | |
| 2563 | }/*-------------------------< MSG_EXT_2 >----------------*/,{ | |
| 2564 | SCR_CLR (SCR_ACK), | |
| 2565 | 0, | |
| 2566 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2567 | PADDR (dispatch), | |
| 2568 | /* | |
| 2569 | ** get extended message code. | |
| 2570 | */ | |
| 2571 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2572 | NADDR (msgin[2]), | |
| 2573 | /* | |
| 2574 | ** Check for message parity error. | |
| 2575 | */ | |
| 2576 | SCR_TO_REG (scratcha), | |
| 2577 | 0, | |
| 2578 | SCR_FROM_REG (socl), | |
| 2579 | 0, | |
| 2580 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2581 | PADDRH (msg_parity), | |
| 2582 | SCR_FROM_REG (scratcha), | |
| 2583 | 0, | |
| 2584 | SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_WDTR)), | |
| 2585 | PADDRH (msg_wdtr), | |
| 2586 | /* | |
| 2587 | ** unknown extended message | |
| 2588 | */ | |
| 2589 | SCR_JUMP, | |
| 2590 | PADDR (msg_bad) | |
| 2591 | }/*-------------------------< MSG_WDTR >-----------------*/,{ | |
| 2592 | SCR_CLR (SCR_ACK), | |
| 2593 | 0, | |
| 2594 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2595 | PADDR (dispatch), | |
| 2596 | /* | |
| 2597 | ** get data bus width | |
| 2598 | */ | |
| 2599 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2600 | NADDR (msgin[3]), | |
| 2601 | SCR_FROM_REG (socl), | |
| 2602 | 0, | |
| 2603 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2604 | PADDRH (msg_parity), | |
| 2605 | /* | |
| 2606 | ** let the host do the real work. | |
| 2607 | */ | |
| 2608 | SCR_INT, | |
| 2609 | SIR_NEGO_WIDE, | |
| 2610 | /* | |
| 2611 | ** let the target fetch our answer. | |
| 2612 | */ | |
| 2613 | SCR_SET (SCR_ATN), | |
| 2614 | 0, | |
| 2615 | SCR_CLR (SCR_ACK), | |
| 2616 | 0, | |
| 2617 | ||
| 2618 | SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), | |
| 2619 | SIR_NEGO_PROTO, | |
| 2620 | /* | |
| 2621 | ** Send the MSG_EXT_WDTR | |
| 2622 | */ | |
| 2623 | SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, | |
| 2624 | NADDR (msgout), | |
| 2625 | SCR_CLR (SCR_ATN), | |
| 2626 | 0, | |
| 2627 | SCR_COPY (1), | |
| 2628 | RADDR (sfbr), | |
| 2629 | NADDR (lastmsg), | |
| 2630 | SCR_JUMP, | |
| 2631 | PADDR (msg_out_done), | |
| 2632 | ||
| 2633 | }/*-------------------------< MSG_EXT_3 >----------------*/,{ | |
| 2634 | SCR_CLR (SCR_ACK), | |
| 2635 | 0, | |
| 2636 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2637 | PADDR (dispatch), | |
| 2638 | /* | |
| 2639 | ** get extended message code. | |
| 2640 | */ | |
| 2641 | SCR_MOVE_ABS (1) ^ SCR_MSG_IN, | |
| 2642 | NADDR (msgin[2]), | |
| 2643 | /* | |
| 2644 | ** Check for message parity error. | |
| 2645 | */ | |
| 2646 | SCR_TO_REG (scratcha), | |
| 2647 | 0, | |
| 2648 | SCR_FROM_REG (socl), | |
| 2649 | 0, | |
| 2650 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2651 | PADDRH (msg_parity), | |
| 2652 | SCR_FROM_REG (scratcha), | |
| 2653 | 0, | |
| 2654 | SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_SDTR)), | |
| 2655 | PADDRH (msg_sdtr), | |
| 2656 | /* | |
| 2657 | ** unknown extended message | |
| 2658 | */ | |
| 2659 | SCR_JUMP, | |
| 2660 | PADDR (msg_bad) | |
| 2661 | ||
| 2662 | }/*-------------------------< MSG_SDTR >-----------------*/,{ | |
| 2663 | SCR_CLR (SCR_ACK), | |
| 2664 | 0, | |
| 2665 | SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), | |
| 2666 | PADDR (dispatch), | |
| 2667 | /* | |
| 2668 | ** get period and offset | |
| 2669 | */ | |
| 2670 | SCR_MOVE_ABS (2) ^ SCR_MSG_IN, | |
| 2671 | NADDR (msgin[3]), | |
| 2672 | SCR_FROM_REG (socl), | |
| 2673 | 0, | |
| 2674 | SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), | |
| 2675 | PADDRH (msg_parity), | |
| 2676 | /* | |
| 2677 | ** let the host do the real work. | |
| 2678 | */ | |
| 2679 | SCR_INT, | |
| 2680 | SIR_NEGO_SYNC, | |
| 2681 | /* | |
| 2682 | ** let the target fetch our answer. | |
| 2683 | */ | |
| 2684 | SCR_SET (SCR_ATN), | |
| 2685 | 0, | |
| 2686 | SCR_CLR (SCR_ACK), | |
| 2687 | 0, | |
| 2688 | ||
| 2689 | SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), | |
| 2690 | SIR_NEGO_PROTO, | |
| 2691 | /* | |
| 2692 | ** Send the MSG_EXT_SDTR | |
| 2693 | */ | |
| 2694 | SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, | |
| 2695 | NADDR (msgout), | |
| 2696 | SCR_CLR (SCR_ATN), | |
| 2697 | 0, | |
| 2698 | SCR_COPY (1), | |
| 2699 | RADDR (sfbr), | |
| 2700 | NADDR (lastmsg), | |
| 2701 | SCR_JUMP, | |
| 2702 | PADDR (msg_out_done), | |
| 2703 | ||
| 2704 | }/*-------------------------< MSG_OUT_ABORT >-------------*/,{ | |
| 2705 | /* | |
| 2706 | ** After ABORT message, | |
| 2707 | ** | |
| 2708 | ** expect an immediate disconnect, ... | |
| 2709 | */ | |
| 2710 | SCR_REG_REG (scntl2, SCR_AND, 0x7f), | |
| 2711 | 0, | |
| 2712 | SCR_CLR (SCR_ACK|SCR_ATN), | |
| 2713 | 0, | |
| 2714 | SCR_WAIT_DISC, | |
| 2715 | 0, | |
| 2716 | /* | |
| 2717 | ** ... and set the status to "ABORTED" | |
| 2718 | */ | |
| 2719 | SCR_LOAD_REG (HS_REG, HS_ABORTED), | |
| 2720 | 0, | |
| 2721 | SCR_JUMP, | |
| 2722 | PADDR (cleanup), | |
| 2723 | ||
| 2724 | }/*-------------------------< GETCC >-----------------------*/,{ | |
| 2725 | /* | |
| 2726 | ** The ncr doesn't have an indirect load | |
| 2727 | ** or store command. So we have to | |
| 2728 | ** copy part of the control block to a | |
| 2729 | ** fixed place, where we can modify it. | |
| 2730 | ** | |
| 2731 | ** We patch the address part of a COPY command | |
| 2732 | ** with the address of the dsa register ... | |
| 2733 | */ | |
| 2734 | SCR_COPY_F (4), | |
| 2735 | RADDR (dsa), | |
| 2736 | PADDRH (getcc1), | |
| 2737 | /* | |
| 2738 | ** ... then we do the actual copy. | |
| 2739 | */ | |
| 2740 | SCR_COPY (sizeof (struct head)), | |
| 2741 | }/*-------------------------< GETCC1 >----------------------*/,{ | |
| 2742 | 0, | |
| 2743 | NADDR (header), | |
| 2744 | /* | |
| 2745 | ** Initialize the status registers | |
| 2746 | */ | |
| 2747 | SCR_COPY (4), | |
| 2748 | NADDR (header.status), | |
| 2749 | RADDR (scr0), | |
| 2750 | }/*-------------------------< GETCC2 >----------------------*/,{ | |
| 2751 | /* | |
| 2752 | ** Get the condition code from a target. | |
| 2753 | ** | |
| 2754 | ** DSA points to a data structure. | |
| 2755 | ** Set TEMP to the script location | |
| 2756 | ** that receives the condition code. | |
| 2757 | ** | |
| 2758 | ** Because there is no script command | |
| 2759 | ** to load a longword into a register, | |
| 2760 | ** we use a CALL command. | |
| 2761 | */ | |
| 2762 | /*<<<*/ SCR_CALLR, | |
| 2763 | 24, | |
| 2764 | /* | |
| 2765 | ** Get the condition code. | |
| 2766 | */ | |
| 2767 | SCR_MOVE_TBL ^ SCR_DATA_IN, | |
| 2768 | offsetof (struct dsb, sense), | |
| 2769 | /* | |
| 2770 | ** No data phase may follow! | |
| 2771 | */ | |
| 2772 | SCR_CALL, | |
| 2773 | PADDR (checkatn), | |
| 2774 | SCR_JUMP, | |
| 2775 | PADDR (no_data), | |
| 2776 | /*>>>*/ | |
| 2777 | ||
| 2778 | /* | |
| 2779 | ** The CALL jumps to this point. | |
| 2780 | ** Prepare for a RESTORE_POINTER message. | |
| 2781 | ** Save the TEMP register into the saved pointer. | |
| 2782 | */ | |
| 2783 | SCR_COPY (4), | |
| 2784 | RADDR (temp), | |
| 2785 | NADDR (header.savep), | |
| 2786 | /* | |
| 2787 | ** Load scratcha, because in case of a selection timeout, | |
| 2788 | ** the host will expect a new value for startpos in | |
| 2789 | ** the scratcha register. | |
| 2790 | */ | |
| 2791 | SCR_COPY (4), | |
| 2792 | PADDR (startpos), | |
| 2793 | RADDR (scratcha), | |
| 2794 | #ifdef NCR_GETCC_WITHMSG | |
| 2795 | /* | |
| 2796 | ** If QUIRK_NOMSG is set, select without ATN. | |
| 2797 | ** and don't send a message. | |
| 2798 | */ | |
| 2799 | SCR_FROM_REG (QU_REG), | |
| 2800 | 0, | |
| 2801 | SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), | |
| 2802 | PADDRH(getcc3), | |
| 2803 | /* | |
| 2804 | ** Then try to connect to the target. | |
| 2805 | ** If we are reselected, special treatment | |
| 2806 | ** of the current job is required before | |
| 2807 | ** accepting the reselection. | |
| 2808 | */ | |
| 2809 | SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), | |
| 2810 | PADDR(badgetcc), | |
| 2811 | /* | |
| 2812 | ** Send the IDENTIFY message. | |
| 2813 | ** In case of short transfer, remove ATN. | |
| 2814 | */ | |
| 2815 | SCR_MOVE_TBL ^ SCR_MSG_OUT, | |
| 2816 | offsetof (struct dsb, smsg2), | |
| 2817 | SCR_CLR (SCR_ATN), | |
| 2818 | 0, | |
| 2819 | /* | |
| 2820 | ** save the first byte of the message. | |
| 2821 | */ | |
| 2822 | SCR_COPY (1), | |
| 2823 | RADDR (sfbr), | |
| 2824 | NADDR (lastmsg), | |
| 2825 | SCR_JUMP, | |
| 2826 | PADDR (prepare2), | |
| 2827 | ||
| 2828 | #endif | |
| 2829 | }/*-------------------------< GETCC3 >----------------------*/,{ | |
| 2830 | /* | |
| 2831 | ** Try to connect to the target. | |
| 2832 | ** If we are reselected, special treatment | |
| 2833 | ** of the current job is required before | |
| 2834 | ** accepting the reselection. | |
| 2835 | ** | |
| 2836 | ** Silly target won't accept a message. | |
| 2837 | ** Select without ATN. | |
| 2838 | */ | |
| 2839 | SCR_SEL_TBL ^ offsetof (struct dsb, select), | |
| 2840 | PADDR(badgetcc), | |
| 2841 | /* | |
| 2842 | ** Force error if selection timeout | |
| 2843 | */ | |
| 2844 | SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), | |
| 2845 | 0, | |
| 2846 | /* | |
| 2847 | ** don't negotiate. | |
| 2848 | */ | |
| 2849 | SCR_JUMP, | |
| 2850 | PADDR (prepare2), | |
| 2851 | }/*-------------------------< ABORTTAG >-------------------*/,{ | |
| 2852 | /* | |
| 2853 | ** Abort a bad reselection. | |
| 2854 | ** Set the message to ABORT vs. ABORT_TAG | |
| 2855 | */ | |
| 2856 | SCR_LOAD_REG (scratcha, MSG_ABORT_TAG), | |
| 2857 | 0, | |
| 2858 | SCR_JUMPR ^ IFFALSE (CARRYSET), | |
| 2859 | 8, | |
| 2860 | }/*-------------------------< ABORT >----------------------*/,{ | |
| 2861 | SCR_LOAD_REG (scratcha, MSG_ABORT), | |
| 2862 | 0, | |
| 2863 | SCR_COPY (1), | |
| 2864 | RADDR (scratcha), | |
| 2865 | NADDR (msgout), | |
| 2866 | SCR_SET (SCR_ATN), | |
| 2867 | 0, | |
| 2868 | SCR_CLR (SCR_ACK), | |
| 2869 | 0, | |
| 2870 | /* | |
| 2871 | ** and send it. | |
| 2872 | ** we expect an immediate disconnect | |
| 2873 | */ | |
| 2874 | SCR_REG_REG (scntl2, SCR_AND, 0x7f), | |
| 2875 | 0, | |
| 2876 | SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, | |
| 2877 | NADDR (msgout), | |
| 2878 | SCR_COPY (1), | |
| 2879 | RADDR (sfbr), | |
| 2880 | NADDR (lastmsg), | |
| 2881 | SCR_CLR (SCR_ACK|SCR_ATN), | |
| 2882 | 0, | |
| 2883 | SCR_WAIT_DISC, | |
| 2884 | 0, | |
| 2885 | SCR_JUMP, | |
| 2886 | PADDR (start), | |
| 2887 | }/*-------------------------< SNOOPTEST >-------------------*/,{ | |
| 2888 | /* | |
| 2889 | ** Read the variable. | |
| 2890 | */ | |
| 2891 | SCR_COPY (4), | |
| 2892 | KVAR (KVAR_NCR_CACHE), | |
| 2893 | RADDR (scratcha), | |
| 2894 | /* | |
| 2895 | ** Write the variable. | |
| 2896 | */ | |
| 2897 | SCR_COPY (4), | |
| 2898 | RADDR (temp), | |
| 2899 | KVAR (KVAR_NCR_CACHE), | |
| 2900 | /* | |
| 2901 | ** Read back the variable. | |
| 2902 | */ | |
| 2903 | SCR_COPY (4), | |
| 2904 | KVAR (KVAR_NCR_CACHE), | |
| 2905 | RADDR (temp), | |
| 2906 | }/*-------------------------< SNOOPEND >-------------------*/,{ | |
| 2907 | /* | |
| 2908 | ** And stop. | |
| 2909 | */ | |
| 2910 | SCR_INT, | |
| 2911 | 99, | |
| 2912 | }/*--------------------------------------------------------*/ | |
| 2913 | }; | |
| 2914 | ||
| 2915 | ||
| 2916 | /*========================================================== | |
| 2917 | ** | |
| 2918 | ** | |
| 2919 | ** Fill in #define dependent parts of the script | |
| 2920 | ** | |
| 2921 | ** | |
| 2922 | **========================================================== | |
| 2923 | */ | |
| 2924 | ||
| 2925 | void ncr_script_fill (struct script * scr, struct scripth * scrh) | |
| 2926 | { | |
| 2927 | int i; | |
| 2928 | ncrcmd *p; | |
| 2929 | ||
| 2930 | p = scrh->tryloop; | |
| 2931 | for (i=0; i<MAX_START; i++) { | |
| 2932 | *p++ =SCR_COPY (4); | |
| 2933 | *p++ =NADDR (squeue[i]); | |
| 2934 | *p++ =RADDR (dsa); | |
| 2935 | *p++ =SCR_CALL; | |
| 2936 | *p++ =PADDR (trysel); | |
| 2937 | }; | |
| 2938 | *p++ =SCR_JUMP; | |
| 2939 | *p++ =PADDRH(tryloop); | |
| 2940 | ||
| 2941 | assert ((char *)p == (char *)&scrh->tryloop + sizeof (scrh->tryloop)); | |
| 2942 | ||
| 2943 | p = scr->data_in; | |
| 2944 | ||
| 2945 | *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); | |
| 2946 | *p++ =PADDR (no_data); | |
| 2947 | *p++ =SCR_COPY (sizeof (ticks)); | |
| 2948 | *p++ =(ncrcmd) KVAR (KVAR_TICKS); | |
| 2949 | *p++ =NADDR (header.stamp.data); | |
| 2950 | *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; | |
| 2951 | *p++ =offsetof (struct dsb, data[ 0]); | |
| 2952 | ||
| 2953 | for (i=1; i<MAX_SCATTER; i++) { | |
| 2954 | *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)); | |
| 2955 | *p++ =PADDR (checkatn); | |
| 2956 | *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; | |
| 2957 | *p++ =offsetof (struct dsb, data[i]); | |
| 2958 | }; | |
| 2959 | ||
| 2960 | *p++ =SCR_CALL; | |
| 2961 | *p++ =PADDR (checkatn); | |
| 2962 | *p++ =SCR_JUMP; | |
| 2963 | *p++ =PADDR (no_data); | |
| 2964 | ||
| 2965 | assert ((char *)p == (char *)&scr->data_in + sizeof (scr->data_in)); | |
| 2966 | ||
| 2967 | p = scr->data_out; | |
| 2968 | ||
| 2969 | *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)); | |
| 2970 | *p++ =PADDR (no_data); | |
| 2971 | *p++ =SCR_COPY (sizeof (ticks)); | |
| 2972 | *p++ =(ncrcmd) KVAR (KVAR_TICKS); | |
| 2973 | *p++ =NADDR (header.stamp.data); | |
| 2974 | *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; | |
| 2975 | *p++ =offsetof (struct dsb, data[ 0]); | |
| 2976 | ||
| 2977 | for (i=1; i<MAX_SCATTER; i++) { | |
| 2978 | *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)); | |
| 2979 | *p++ =PADDR (dispatch); | |
| 2980 | *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; | |
| 2981 | *p++ =offsetof (struct dsb, data[i]); | |
| 2982 | }; | |
| 2983 | ||
| 2984 | *p++ =SCR_CALL; | |
| 2985 | *p++ =PADDR (dispatch); | |
| 2986 | *p++ =SCR_JUMP; | |
| 2987 | *p++ =PADDR (no_data); | |
| 2988 | ||
| 2989 | assert ((char *)p == (char *)&scr->data_out + sizeof (scr->data_out)); | |
| 2990 | } | |
| 2991 | ||
| 2992 | /*========================================================== | |
| 2993 | ** | |
| 2994 | ** | |
| 2995 | ** Copy and rebind a script. | |
| 2996 | ** | |
| 2997 | ** | |
| 2998 | **========================================================== | |
| 2999 | */ | |
| 3000 | ||
| 3001 | static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) | |
| 3002 | { | |
| 3003 | ncrcmd opcode, new, old, tmp1, tmp2; | |
| 3004 | ncrcmd *start, *end; | |
| 3005 | int relocs, offset; | |
| 3006 | ||
| 3007 | start = src; | |
| 3008 | end = src + len/4; | |
| 3009 | offset = 0; | |
| 3010 | ||
| 3011 | while (src < end) { | |
| 3012 | ||
| 3013 | opcode = *src++; | |
| 3014 | WRITESCRIPT_OFF(dst, offset, opcode); | |
| 3015 | offset += 4; | |
| 3016 | ||
| 3017 | /* | |
| 3018 | ** If we forget to change the length | |
| 3019 | ** in struct script, a field will be | |
| 3020 | ** padded with 0. This is an illegal | |
| 3021 | ** command. | |
| 3022 | */ | |
| 3023 | ||
| 3024 | if (opcode == 0) { | |
| e3869ec7 | 3025 | kprintf ("%s: ERROR0 IN SCRIPT at %d.\n", |
| 984263bc MD |
3026 | ncr_name(np), (int) (src-start-1)); |
| 3027 | DELAY (1000000); | |
| 3028 | }; | |
| 3029 | ||
| 3030 | if (DEBUG_FLAGS & DEBUG_SCRIPT) | |
| e3869ec7 | 3031 | kprintf ("%p: <%x>\n", |
| 984263bc MD |
3032 | (src-1), (unsigned)opcode); |
| 3033 | ||
| 3034 | /* | |
| 3035 | ** We don't have to decode ALL commands | |
| 3036 | */ | |
| 3037 | switch (opcode >> 28) { | |
| 3038 | ||
| 3039 | case 0xc: | |
| 3040 | /* | |
| 3041 | ** COPY has TWO arguments. | |
| 3042 | */ | |
| 3043 | relocs = 2; | |
| 3044 | tmp1 = src[0]; | |
| 3045 | if ((tmp1 & RELOC_MASK) == RELOC_KVAR) | |
| 3046 | tmp1 = 0; | |
| 3047 | tmp2 = src[1]; | |
| 3048 | if ((tmp2 & RELOC_MASK) == RELOC_KVAR) | |
| 3049 | tmp2 = 0; | |
| 3050 | if ((tmp1 ^ tmp2) & 3) { | |
| e3869ec7 | 3051 | kprintf ("%s: ERROR1 IN SCRIPT at %d.\n", |
| 984263bc MD |
3052 | ncr_name(np), (int) (src-start-1)); |
| 3053 | DELAY (1000000); | |
| 3054 | } | |
| 3055 | /* | |
| 3056 | ** If PREFETCH feature not enabled, remove | |
| 3057 | ** the NO FLUSH bit if present. | |
| 3058 | */ | |
| 3059 | if ((opcode & SCR_NO_FLUSH) && !(np->features&FE_PFEN)) | |
| 3060 | WRITESCRIPT_OFF(dst, offset - 4, | |
| 3061 | (opcode & ~SCR_NO_FLUSH)); | |
| 3062 | break; | |
| 3063 | ||
| 3064 | case 0x0: | |
| 3065 | /* | |
| 3066 | ** MOVE (absolute address) | |
| 3067 | */ | |
| 3068 | relocs = 1; | |
| 3069 | break; | |
| 3070 | ||
| 3071 | case 0x8: | |
| 3072 | /* | |
| 3073 | ** JUMP / CALL | |
| 3074 | ** dont't relocate if relative :-) | |
| 3075 | */ | |
| 3076 | if (opcode & 0x00800000) | |
| 3077 | relocs = 0; | |
| 3078 | else | |
| 3079 | relocs = 1; | |
| 3080 | break; | |
| 3081 | ||
| 3082 | case 0x4: | |
| 3083 | case 0x5: | |
| 3084 | case 0x6: | |
| 3085 | case 0x7: | |
| 3086 | relocs = 1; | |
| 3087 | break; | |
| 3088 | ||
| 3089 | default: | |
| 3090 | relocs = 0; | |
| 3091 | break; | |
| 3092 | }; | |
| 3093 | ||
| 3094 | if (relocs) { | |
| 3095 | while (relocs--) { | |
| 3096 | old = *src++; | |
| 3097 | ||
| 3098 | switch (old & RELOC_MASK) { | |
| 3099 | case RELOC_REGISTER: | |
| 3100 | new = (old & ~RELOC_MASK) + rman_get_start(np->reg_res); | |
| 3101 | break; | |
| 3102 | case RELOC_LABEL: | |
| 3103 | new = (old & ~RELOC_MASK) + np->p_script; | |
| 3104 | break; | |
| 3105 | case RELOC_LABELH: | |
| 3106 | new = (old & ~RELOC_MASK) + np->p_scripth; | |
| 3107 | break; | |
| 3108 | case RELOC_SOFTC: | |
| 3109 | new = (old & ~RELOC_MASK) + vtophys(np); | |
| 3110 | break; | |
| 3111 | case RELOC_KVAR: | |
| 3112 | if (((old & ~RELOC_MASK) < | |
| 3113 | SCRIPT_KVAR_FIRST) || | |
| 3114 | ((old & ~RELOC_MASK) > | |
| 3115 | SCRIPT_KVAR_LAST)) | |
| 3116 | panic("ncr KVAR out of range"); | |
| 3117 | new = vtophys(script_kvars[old & | |
| 3118 | ~RELOC_MASK]); | |
| 3119 | break; | |
| 3120 | case 0: | |
| 3121 | /* Don't relocate a 0 address. */ | |
| 3122 | if (old == 0) { | |
| 3123 | new = old; | |
| 3124 | break; | |
| 3125 | } | |
| 3126 | /* fall through */ | |
| 3127 | default: | |
| 3128 | panic("ncr_script_copy_and_bind: weird relocation %x @ %d\n", old, (int)(src - start)); | |
| 3129 | break; | |
| 3130 | } | |
| 3131 | ||
| 3132 | WRITESCRIPT_OFF(dst, offset, new); | |
| 3133 | offset += 4; | |
| 3134 | } | |
| 3135 | } else { | |
| 3136 | WRITESCRIPT_OFF(dst, offset, *src++); | |
| 3137 | offset += 4; | |
| 3138 | } | |
| 3139 | ||
| 3140 | }; | |
| 3141 | } | |
| 3142 | ||
| 3143 | /*========================================================== | |
| 3144 | ** | |
| 3145 | ** | |
| 3146 | ** Auto configuration. | |
| 3147 | ** | |
| 3148 | ** | |
| 3149 | **========================================================== | |
| 3150 | */ | |
| 3151 | ||
| 3152 | #if 0 | |
| 3153 | /*---------------------------------------------------------- | |
| 3154 | ** | |
| 3155 | ** Reduce the transfer length to the max value | |
| 3156 | ** we can transfer safely. | |
| 3157 | ** | |
| 3158 | ** Reading a block greater then MAX_SIZE from the | |
| 3159 | ** raw (character) device exercises a memory leak | |
| 3160 | ** in the vm subsystem. This is common to ALL devices. | |
| 3161 | ** We have submitted a description of this bug to | |
| 3162 | ** <FreeBSD-bugs@freefall.cdrom.com>. | |
| 3163 | ** It should be fixed in the current release. | |
| 3164 | ** | |
| 3165 | **---------------------------------------------------------- | |
| 3166 | */ | |
| 3167 | ||
| 3168 | void ncr_min_phys (struct buf *bp) | |
| 3169 | { | |
| 3170 | if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; | |
| 3171 | } | |
| 3172 | ||
| 3173 | #endif | |
| 3174 | ||
| 3175 | #if 0 | |
| 3176 | /*---------------------------------------------------------- | |
| 3177 | ** | |
| 3178 | ** Maximal number of outstanding requests per target. | |
| 3179 | ** | |
| 3180 | **---------------------------------------------------------- | |
| 3181 | */ | |
| 3182 | ||
| 3183 | u_int32_t ncr_info (int unit) | |
| 3184 | { | |
| 3185 | return (1); /* may be changed later */ | |
| 3186 | } | |
| 3187 | ||
| 3188 | #endif | |
| 3189 | ||
| 3190 | /*---------------------------------------------------------- | |
| 3191 | ** | |
| 3192 | ** NCR chip devices table and chip look up function. | |
| 3193 | ** Features bit are defined in ncrreg.h. Is it the | |
| 3194 | ** right place? | |
| 3195 | ** | |
| 3196 | **---------------------------------------------------------- | |
| 3197 | */ | |
| 3198 | typedef struct { | |
| 3199 | unsigned long device_id; | |
| 3200 | unsigned short minrevid; | |
| 3201 | char *name; | |
| 3202 | unsigned char maxburst; | |
| 3203 | unsigned char maxoffs; | |
| 3204 | unsigned char clock_divn; | |
| 3205 | unsigned int features; | |
| 3206 | } ncr_chip; | |
| 3207 | ||
| 3208 | static ncr_chip ncr_chip_table[] = { | |
| 3209 | {NCR_810_ID, 0x00, "ncr 53c810 fast10 scsi", 4, 8, 4, | |
| 3210 | FE_ERL} | |
| 3211 | , | |
| 3212 | {NCR_810_ID, 0x10, "ncr 53c810a fast10 scsi", 4, 8, 4, | |
| 3213 | FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF} | |
| 3214 | , | |
| 3215 | {NCR_815_ID, 0x00, "ncr 53c815 fast10 scsi", 4, 8, 4, | |
| 3216 | FE_ERL|FE_BOF} | |
| 3217 | , | |
| 3218 | {NCR_820_ID, 0x00, "ncr 53c820 fast10 wide scsi", 4, 8, 4, | |
| 3219 | FE_WIDE|FE_ERL} | |
| 3220 | , | |
| 3221 | {NCR_825_ID, 0x00, "ncr 53c825 fast10 wide scsi", 4, 8, 4, | |
| 3222 | FE_WIDE|FE_ERL|FE_BOF} | |
| 3223 | , | |
| 3224 | {NCR_825_ID, 0x10, "ncr 53c825a fast10 wide scsi", 7, 8, 4, | |
| 3225 | FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3226 | , | |
| 3227 | {NCR_860_ID, 0x00, "ncr 53c860 fast20 scsi", 4, 8, 5, | |
| 3228 | FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN} | |
| 3229 | , | |
| 3230 | {NCR_875_ID, 0x00, "ncr 53c875 fast20 wide scsi", 7, 16, 5, | |
| 3231 | FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3232 | , | |
| 3233 | {NCR_875_ID, 0x02, "ncr 53c875 fast20 wide scsi", 7, 16, 5, | |
| 3234 | FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3235 | , | |
| 3236 | {NCR_875_ID2, 0x00, "ncr 53c875j fast20 wide scsi", 7, 16, 5, | |
| 3237 | FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3238 | , | |
| 3239 | {NCR_885_ID, 0x00, "ncr 53c885 fast20 wide scsi", 7, 16, 5, | |
| 3240 | FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3241 | , | |
| 3242 | {NCR_895_ID, 0x00, "ncr 53c895 fast40 wide scsi", 7, 31, 7, | |
| 3243 | FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3244 | , | |
| 3245 | {NCR_896_ID, 0x00, "ncr 53c896 fast40 wide scsi", 7, 31, 7, | |
| 3246 | FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3247 | , | |
| 3248 | {NCR_895A_ID, 0x00, "ncr 53c895a fast40 wide scsi", 7, 31, 7, | |
| 3249 | FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3250 | , | |
| 3251 | {NCR_1510D_ID, 0x00, "ncr 53c1510d fast40 wide scsi", 7, 31, 7, | |
| 3252 | FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} | |
| 3253 | }; | |
| 3254 | ||
| 3255 | static int ncr_chip_lookup(u_long device_id, u_char revision_id) | |
| 3256 | { | |
| 3257 | int i, found; | |
| 3258 | ||
| 3259 | found = -1; | |
| 3260 | for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { | |
| 3261 | if (device_id == ncr_chip_table[i].device_id && | |
| 3262 | ncr_chip_table[i].minrevid <= revision_id) { | |
| 3263 | if (found < 0 || | |
| 3264 | ncr_chip_table[found].minrevid | |
| 3265 | < ncr_chip_table[i].minrevid) { | |
| 3266 | found = i; | |
| 3267 | } | |
| 3268 | } | |
| 3269 | } | |
| 3270 | return found; | |
| 3271 | } | |
| 3272 | ||
| 3273 | /*---------------------------------------------------------- | |
| 3274 | ** | |
| 3275 | ** Probe the hostadapter. | |
| 3276 | ** | |
| 3277 | **---------------------------------------------------------- | |
| 3278 | */ | |
| 3279 | ||
| 3280 | ||
| 3281 | ||
| 3282 | static int ncr_probe (device_t dev) | |
| 3283 | { | |
| 3284 | int i; | |
| 3285 | ||
| 3286 | i = ncr_chip_lookup(pci_get_devid(dev), pci_get_revid(dev)); | |
| 3287 | if (i >= 0) { | |
| 3288 | device_set_desc(dev, ncr_chip_table[i].name); | |
| 3289 | return (-1000); /* Allows to use both ncr and sym */ | |
| 3290 | } | |
| 3291 | ||
| 3292 | return (ENXIO); | |
| 3293 | } | |
| 3294 | ||
| 3295 | ||
| 3296 | ||
| 3297 | /*========================================================== | |
| 3298 | ** | |
| 3299 | ** NCR chip clock divisor table. | |
| 3300 | ** Divisors are multiplied by 10,000,000 in order to make | |
| 3301 | ** calculations more simple. | |
| 3302 | ** | |
| 3303 | **========================================================== | |
| 3304 | */ | |
| 3305 | ||
| 3306 | #define _5M 5000000 | |
| 3307 | static u_long div_10M[] = | |
| 3308 | {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; | |
| 3309 | ||
| 3310 | /*=============================================================== | |
| 3311 | ** | |
| 3312 | ** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 | |
| 3313 | ** transfers. 32,64,128 are only supported by 875 and 895 chips. | |
| 3314 | ** We use log base 2 (burst length) as internal code, with | |
| 3315 | ** value 0 meaning "burst disabled". | |
| 3316 | ** | |
| 3317 | **=============================================================== | |
| 3318 | */ | |
| 3319 | ||
| 3320 | /* | |
| 3321 | * Burst length from burst code. | |
| 3322 | */ | |
| 3323 | #define burst_length(bc) (!(bc))? 0 : 1 << (bc) | |
| 3324 | ||
| 3325 | /* | |
| 3326 | * Burst code from io register bits. | |
| 3327 | */ | |
| 3328 | #define burst_code(dmode, ctest4, ctest5) \ | |
| 3329 | (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 | |
| 3330 | ||
| 3331 | /* | |
| 3332 | * Set initial io register bits from burst code. | |
| 3333 | */ | |
| 3334 | static void | |
| 3335 | ncr_init_burst(ncb_p np, u_char bc) | |
| 3336 | { | |
| 3337 | np->rv_ctest4 &= ~0x80; | |
| 3338 | np->rv_dmode &= ~(0x3 << 6); | |
| 3339 | np->rv_ctest5 &= ~0x4; | |
| 3340 | ||
| 3341 | if (!bc) { | |
| 3342 | np->rv_ctest4 |= 0x80; | |
| 3343 | } | |
| 3344 | else { | |
| 3345 | --bc; | |
| 3346 | np->rv_dmode |= ((bc & 0x3) << 6); | |
| 3347 | np->rv_ctest5 |= (bc & 0x4); | |
| 3348 | } | |
| 3349 | } | |
| 3350 | ||
| 3351 | /*========================================================== | |
| 3352 | ** | |
| 3353 | ** | |
| 3354 | ** Auto configuration: attach and init a host adapter. | |
| 3355 | ** | |
| 3356 | ** | |
| 3357 | **========================================================== | |
| 3358 | */ | |
| 3359 | ||
| 3360 | ||
| 3361 | static int | |
| 3362 | ncr_attach (device_t dev) | |
| 3363 | { | |
| 3364 | ncb_p np = (struct ncb*) device_get_softc(dev); | |
| 3365 | u_char rev = 0; | |
| 3366 | u_long period; | |
| 3367 | int i, rid; | |
| 3368 | u_int8_t usrsync; | |
| 3369 | u_int8_t usrwide; | |
| 3370 | struct cam_devq *devq; | |
| 3371 | ||
| 3372 | /* | |
| 3373 | ** allocate and initialize structures. | |
| 3374 | */ | |
| 3375 | ||
| 3376 | np->unit = device_get_unit(dev); | |
| 3377 | ||
| 3378 | /* | |
| 3379 | ** Try to map the controller chip to | |
| 3380 | ** virtual and physical memory. | |
| 3381 | */ | |
| 3382 | ||
| 3383 | np->reg_rid = 0x14; | |
| 3384 | np->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &np->reg_rid, | |
| 3385 | 0, ~0, 1, RF_ACTIVE); | |
| 3386 | if (!np->reg_res) { | |
| 3387 | device_printf(dev, "could not map memory\n"); | |
| 3388 | return ENXIO; | |
| 3389 | } | |
| 3390 | ||
| 3391 | /* | |
| 3392 | ** Make the controller's registers available. | |
| 3393 | ** Now the INB INW INL OUTB OUTW OUTL macros | |
| 3394 | ** can be used safely. | |
| 3395 | */ | |
| 3396 | ||
| 3397 | np->bst = rman_get_bustag(np->reg_res); | |
| 3398 | np->bsh = rman_get_bushandle(np->reg_res); | |
| 3399 | ||
| 3400 | ||
| 3401 | #ifdef NCR_IOMAPPED | |
| 3402 | /* | |
| 3403 | ** Try to map the controller chip into iospace. | |
| 3404 | */ | |
| 3405 | ||
| 3406 | if (!pci_map_port (config_id, 0x10, &np->port)) | |
| 3407 | return; | |
| 3408 | #endif | |
| 3409 | ||
| 3410 | ||
| 3411 | /* | |
| 3412 | ** Save some controller register default values | |
| 3413 | */ | |
| 3414 | ||
| 3415 | np->rv_scntl3 = INB(nc_scntl3) & 0x77; | |
| 3416 | np->rv_dmode = INB(nc_dmode) & 0xce; | |
| 3417 | np->rv_dcntl = INB(nc_dcntl) & 0xa9; | |
| 3418 | np->rv_ctest3 = INB(nc_ctest3) & 0x01; | |
| 3419 | np->rv_ctest4 = INB(nc_ctest4) & 0x88; | |
| 3420 | np->rv_ctest5 = INB(nc_ctest5) & 0x24; | |
| 3421 | np->rv_gpcntl = INB(nc_gpcntl); | |
| 3422 | np->rv_stest2 = INB(nc_stest2) & 0x20; | |
| 3423 | ||
| 3424 | if (bootverbose >= 2) { | |
| e3869ec7 | 3425 | kprintf ("\tBIOS values: SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", |
| 984263bc | 3426 | np->rv_scntl3, np->rv_dmode, np->rv_dcntl); |
| e3869ec7 | 3427 | kprintf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", |
| 984263bc MD |
3428 | np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); |
| 3429 | } | |
| 3430 | ||
| 3431 | np->rv_dcntl |= NOCOM; | |
| 3432 | ||
| 3433 | /* | |
| 3434 | ** Do chip dependent initialization. | |
| 3435 | */ | |
| 3436 | ||
| 3437 | rev = pci_get_revid(dev); | |
| 3438 | ||
| 3439 | /* | |
| 3440 | ** Get chip features from chips table. | |
| 3441 | */ | |
| 3442 | i = ncr_chip_lookup(pci_get_devid(dev), rev); | |
| 3443 | ||
| 3444 | if (i >= 0) { | |
| 3445 | np->maxburst = ncr_chip_table[i].maxburst; | |
| 3446 | np->maxoffs = ncr_chip_table[i].maxoffs; | |
| 3447 | np->clock_divn = ncr_chip_table[i].clock_divn; | |
| 3448 | np->features = ncr_chip_table[i].features; | |
| 3449 | } else { /* Should'nt happen if probe() is ok */ | |
| 3450 | np->maxburst = 4; | |
| 3451 | np->maxoffs = 8; | |
| 3452 | np->clock_divn = 4; | |
| 3453 | np->features = FE_ERL; | |
| 3454 | } | |
| 3455 | ||
| 3456 | np->maxwide = np->features & FE_WIDE ? 1 : 0; | |
| 3457 | np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; | |
| 3458 | if (np->features & FE_QUAD) np->multiplier = 4; | |
| 3459 | else if (np->features & FE_DBLR) np->multiplier = 2; | |
| 3460 | else np->multiplier = 1; | |
| 3461 | ||
| 3462 | /* | |
| 3463 | ** Get the frequency of the chip's clock. | |
| 3464 | ** Find the right value for scntl3. | |
| 3465 | */ | |
| 3466 | if (np->features & (FE_ULTRA|FE_ULTRA2)) | |
| 3467 | ncr_getclock(np, np->multiplier); | |
| 3468 | ||
| 3469 | #ifdef NCR_TEKRAM_EEPROM | |
| 3470 | if (bootverbose) { | |
| e3869ec7 | 3471 | kprintf ("%s: Tekram EEPROM read %s\n", |
| 984263bc MD |
3472 | ncr_name(np), |
| 3473 | read_tekram_eeprom (np, NULL) ? | |
| 3474 | "succeeded" : "failed"); | |
| 3475 | } | |
| 3476 | #endif /* NCR_TEKRAM_EEPROM */ | |
| 3477 | ||
| 3478 | /* | |
| 3479 | * If scntl3 != 0, we assume BIOS is present. | |
| 3480 | */ | |
| 3481 | if (np->rv_scntl3) | |
| 3482 | np->features |= FE_BIOS; | |
| 3483 | ||
| 3484 | /* | |
| 3485 | * Divisor to be used for async (timer pre-scaler). | |
| 3486 | */ | |
| 3487 | i = np->clock_divn - 1; | |
| 3488 | while (i >= 0) { | |
| 3489 | --i; | |
| 3490 | if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { | |
| 3491 | ++i; | |
| 3492 | break; | |
| 3493 | } | |
| 3494 | } | |
| 3495 | np->rv_scntl3 = i+1; | |
| 3496 | ||
| 3497 | /* | |
| 3498 | * Minimum synchronous period factor supported by the chip. | |
| 3499 | * Btw, 'period' is in tenths of nanoseconds. | |
| 3500 | */ | |
| 3501 | ||
| 3502 | period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; | |
| 3503 | if (period <= 250) np->minsync = 10; | |
| 3504 | else if (period <= 303) np->minsync = 11; | |
| 3505 | else if (period <= 500) np->minsync = 12; | |
| 3506 | else np->minsync = (period + 40 - 1) / 40; | |
| 3507 | ||
| 3508 | /* | |
| 3509 | * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). | |
| 3510 | */ | |
| 3511 | ||
| 3512 | if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) | |
| 3513 | np->minsync = 25; | |
| 3514 | else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) | |
| 3515 | np->minsync = 12; | |
| 3516 | ||
| 3517 | /* | |
| 3518 | * Maximum synchronous period factor supported by the chip. | |
| 3519 | */ | |
| 3520 | ||
| 3521 | period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz); | |
| 3522 | np->maxsync = period > 2540 ? 254 : period / 10; | |
| 3523 | ||
| 3524 | /* | |
| 3525 | * Now, some features available with Symbios compatible boards. | |
| 3526 | * LED support through GPIO0 and DIFF support. | |
| 3527 | */ | |
| 3528 | ||
| 3529 | #ifdef SCSI_NCR_SYMBIOS_COMPAT | |
| 3530 | if (!(np->rv_gpcntl & 0x01)) | |
| 3531 | np->features |= FE_LED0; | |
| 3532 | #if 0 /* Not safe enough without NVRAM support or user settable option */ | |
| 3533 | if (!(INB(nc_gpreg) & 0x08)) | |
| 3534 | np->features |= FE_DIFF; | |
| 3535 | #endif | |
| 3536 | #endif /* SCSI_NCR_SYMBIOS_COMPAT */ | |
| 3537 | ||
| 3538 | /* | |
| 3539 | * Prepare initial IO registers settings. | |
| 3540 | * Trust BIOS only if we believe we have one and if we want to. | |
| 3541 | */ | |
| 3542 | #ifdef SCSI_NCR_TRUST_BIOS | |
| 3543 | if (!(np->features & FE_BIOS)) { | |
| 3544 | #else | |
| 3545 | if (1) { | |
| 3546 | #endif | |
| 3547 | np->rv_dmode = 0; | |
| 3548 | np->rv_dcntl = NOCOM; | |
| 3549 | np->rv_ctest3 = 0; | |
| 3550 | np->rv_ctest4 = MPEE; | |
| 3551 | np->rv_ctest5 = 0; | |
| 3552 | np->rv_stest2 = 0; | |
| 3553 | ||
| 3554 | if (np->features & FE_ERL) | |
| 3555 | np->rv_dmode |= ERL; /* Enable Read Line */ | |
| 3556 | if (np->features & FE_BOF) | |
| 3557 | np->rv_dmode |= BOF; /* Burst Opcode Fetch */ | |
| 3558 | if (np->features & FE_ERMP) | |
| 3559 | np->rv_dmode |= ERMP; /* Enable Read Multiple */ | |
| 3560 | if (np->features & FE_CLSE) | |
| 3561 | np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ | |
| 3562 | if (np->features & FE_WRIE) | |
| 3563 | np->rv_ctest3 |= WRIE; /* Write and Invalidate */ | |
| 3564 | if (np->features & FE_PFEN) | |
| 3565 | np->rv_dcntl |= PFEN; /* Prefetch Enable */ | |
| 3566 | if (np->features & FE_DFS) | |
| 3567 | np->rv_ctest5 |= DFS; /* Dma Fifo Size */ | |
| 3568 | if (np->features & FE_DIFF) | |
| 3569 | np->rv_stest2 |= 0x20; /* Differential mode */ | |
| 3570 | ncr_init_burst(np, np->maxburst); /* Max dwords burst length */ | |
| 3571 | } else { | |
| 3572 | np->maxburst = | |
| 3573 | burst_code(np->rv_dmode, np->rv_ctest4, np->rv_ctest5); | |
| 3574 | } | |
| 3575 | ||
| 3576 | /* | |
| 3577 | ** Get on-chip SRAM address, if supported | |
| 3578 | */ | |
| 3579 | if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) { | |
| 3580 | np->sram_rid = 0x18; | |
| 3581 | np->sram_res = bus_alloc_resource(dev, SYS_RES_MEMORY, | |
| 3582 | &np->sram_rid, | |
| 3583 | 0, ~0, 1, RF_ACTIVE); | |
| 3584 | } | |
| 3585 | ||
| 3586 | /* | |
| 3587 | ** Allocate structure for script relocation. | |
| 3588 | */ | |
| 3589 | if (np->sram_res != NULL) { | |
| 3590 | np->script = NULL; | |
| 3591 | np->p_script = rman_get_start(np->sram_res); | |
| 3592 | np->bst2 = rman_get_bustag(np->sram_res); | |
| 3593 | np->bsh2 = rman_get_bushandle(np->sram_res); | |
| 3594 | } else if (sizeof (struct script) > PAGE_SIZE) { | |
| 3595 | np->script = (struct script*) vm_page_alloc_contig | |
| 3596 | (round_page(sizeof (struct script)), | |
| 3597 | 0, 0xffffffff, PAGE_SIZE); | |
| 3598 | } else { | |
| 3599 | np->script = (struct script *) | |
| efda3bd0 | 3600 | kmalloc (sizeof (struct script), M_DEVBUF, M_WAITOK); |
| 984263bc MD |
3601 | } |
| 3602 | ||
| 3603 | /* XXX JGibbs - Use contigmalloc */ | |
| 3604 | if (sizeof (struct scripth) > PAGE_SIZE) { | |
| 3605 | np->scripth = (struct scripth*) vm_page_alloc_contig | |
| 3606 | (round_page(sizeof (struct scripth)), | |
| 3607 | 0, 0xffffffff, PAGE_SIZE); | |
| 3608 | } else | |
| 3609 | { | |
| 3610 | np->scripth = (struct scripth *) | |
| efda3bd0 | 3611 | kmalloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK); |
| 984263bc MD |
3612 | } |
| 3613 | ||
| 3614 | #ifdef SCSI_NCR_PCI_CONFIG_FIXUP | |
| 3615 | /* | |
| 3616 | ** If cache line size is enabled, check PCI config space and | |
| 3617 | ** try to fix it up if necessary. | |
| 3618 | */ | |
| 3619 | #ifdef PCIR_CACHELNSZ /* To be sure that new PCI stuff is present */ | |
| 3620 | { | |
| 3621 | u_char cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); | |
| 3622 | u_short command = pci_read_config(dev, PCIR_COMMAND, 2); | |
| 3623 | ||
| 3624 | if (!cachelnsz) { | |
| 3625 | cachelnsz = 8; | |
| e3869ec7 | 3626 | kprintf("%s: setting PCI cache line size register to %d.\n", |
| 984263bc MD |
3627 | ncr_name(np), (int)cachelnsz); |
| 3628 | pci_write_config(dev, PCIR_CACHELNSZ, cachelnsz, 1); | |
| 3629 | } | |
| 3630 | ||
| 3631 | if (!(command & (1<<4))) { | |
| 3632 | command |= (1<<4); | |
| e3869ec7 | 3633 | kprintf("%s: setting PCI command write and invalidate.\n", |
| 984263bc MD |
3634 | ncr_name(np)); |
| 3635 | pci_write_config(dev, PCIR_COMMAND, command, 2); | |
| 3636 | } | |
| 3637 | } | |
| 3638 | #endif /* PCIR_CACHELNSZ */ | |
| 3639 | ||
| 3640 | #endif /* SCSI_NCR_PCI_CONFIG_FIXUP */ | |
| 3641 | ||
| 3642 | /* Initialize per-target user settings */ | |
| 3643 | usrsync = 0; | |
| 3644 | if (SCSI_NCR_DFLT_SYNC) { | |
| 3645 | usrsync = SCSI_NCR_DFLT_SYNC; | |
| 3646 | if (usrsync > np->maxsync) | |
| 3647 | usrsync = np->maxsync; | |
| 3648 | if (usrsync < np->minsync) | |
| 3649 | usrsync = np->minsync; | |
| 3650 | }; | |
| 3651 | ||
| 3652 | usrwide = (SCSI_NCR_MAX_WIDE); | |
| 3653 | if (usrwide > np->maxwide) usrwide=np->maxwide; | |
| 3654 | ||
| 3655 | for (i=0;i<MAX_TARGET;i++) { | |
| 3656 | tcb_p tp = &np->target[i]; | |
| 3657 | ||
| 3658 | tp->tinfo.user.period = usrsync; | |
| 3659 | tp->tinfo.user.offset = usrsync != 0 ? np->maxoffs : 0; | |
| 3660 | tp->tinfo.user.width = usrwide; | |
| 3661 | tp->tinfo.disc_tag = NCR_CUR_DISCENB | |
| 3662 | | NCR_CUR_TAGENB | |
| 3663 | | NCR_USR_DISCENB | |
| 3664 | | NCR_USR_TAGENB; | |
| 3665 | } | |
| 3666 | ||
| 3667 | /* | |
| 3668 | ** Bells and whistles ;-) | |
| 3669 | */ | |
| 3670 | if (bootverbose) | |
| e3869ec7 | 3671 | kprintf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n", |
| 984263bc MD |
3672 | ncr_name(np), np->minsync, np->maxsync, np->maxoffs, |
| 3673 | burst_length(np->maxburst), | |
| 3674 | (np->rv_ctest5 & DFS) ? "large" : "normal"); | |
| 3675 | ||
| 3676 | /* | |
| 3677 | ** Print some complementary information that can be helpfull. | |
| 3678 | */ | |
| 3679 | if (bootverbose) | |
| e3869ec7 | 3680 | kprintf("%s: %s, %s IRQ driver%s\n", |
| 984263bc MD |
3681 | ncr_name(np), |
| 3682 | np->rv_stest2 & 0x20 ? "differential" : "single-ended", | |
| 3683 | np->rv_dcntl & IRQM ? "totem pole" : "open drain", | |
| 3684 | np->sram_res ? ", using on-chip SRAM" : ""); | |
| 3685 | ||
| 3686 | /* | |
| 3687 | ** Patch scripts to physical addresses | |
| 3688 | */ | |
| 3689 | ncr_script_fill (&script0, &scripth0); | |
| 3690 | ||
| 3691 | if (np->script) | |
| 3692 | np->p_script = vtophys(np->script); | |
| 3693 | np->p_scripth = vtophys(np->scripth); | |
| 3694 | ||
| 3695 | ncr_script_copy_and_bind (np, (ncrcmd *) &script0, | |
| 3696 | (ncrcmd *) np->script, sizeof(struct script)); | |
| 3697 | ||
| 3698 | ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, | |
| 3699 | (ncrcmd *) np->scripth, sizeof(struct scripth)); | |
| 3700 | ||
| 3701 | /* | |
| 3702 | ** Patch the script for LED support. | |
| 3703 | */ | |
| 3704 | ||
| 3705 | if (np->features & FE_LED0) { | |
| 3706 | WRITESCRIPT(reselect[0], SCR_REG_REG(gpreg, SCR_OR, 0x01)); | |
| 3707 | WRITESCRIPT(reselect1[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); | |
| 3708 | WRITESCRIPT(reselect2[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); | |
| 3709 | } | |
| 3710 | ||
| 3711 | /* | |
| 3712 | ** init data structure | |
| 3713 | */ | |
| 3714 | ||
| 3715 | np->jump_tcb.l_cmd = SCR_JUMP; | |
| 3716 | np->jump_tcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); | |
| 3717 | ||
| 3718 | /* | |
| 3719 | ** Get SCSI addr of host adapter (set by bios?). | |
| 3720 | */ | |
| 3721 | ||
| 3722 | np->myaddr = INB(nc_scid) & 0x07; | |
| 3723 | if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR; | |
| 3724 | ||
| 3725 | #ifdef NCR_DUMP_REG | |
| 3726 | /* | |
| 3727 | ** Log the initial register contents | |
| 3728 | */ | |
| 3729 | { | |
| 3730 | int reg; | |
| 3731 | for (reg=0; reg<256; reg+=4) { | |
| e3869ec7 SW |
3732 | if (reg%16==0) kprintf ("reg[%2x]", reg); |
| 3733 | kprintf (" %08x", (int)pci_conf_read (config_id, reg)); | |
| 3734 | if (reg%16==12) kprintf ("\n"); | |
| 984263bc MD |
3735 | } |
| 3736 | } | |
| 3737 | #endif /* NCR_DUMP_REG */ | |
| 3738 | ||
| 3739 | /* | |
| 3740 | ** Reset chip. | |
| 3741 | */ | |
| 3742 | ||
| 3743 | OUTB (nc_istat, SRST); | |
| 3744 | DELAY (1000); | |
| 3745 | OUTB (nc_istat, 0 ); | |
| 3746 | ||
| 3747 | ||
| 3748 | /* | |
| 3749 | ** Now check the cache handling of the pci chipset. | |
| 3750 | */ | |
| 3751 | ||
| 3752 | if (ncr_snooptest (np)) { | |
| e3869ec7 | 3753 | kprintf ("CACHE INCORRECTLY CONFIGURED.\n"); |
| 984263bc MD |
3754 | return EINVAL; |
| 3755 | }; | |
| 3756 | ||
| 3757 | /* | |
| 3758 | ** Install the interrupt handler. | |
| 3759 | */ | |
| 3760 | ||
| 3761 | rid = 0; | |
| 3762 | np->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, | |
| 3763 | RF_SHAREABLE | RF_ACTIVE); | |
| 3764 | if (np->irq_res == NULL) { | |
| 3765 | device_printf(dev, | |
| 3766 | "interruptless mode: reduced performance.\n"); | |
| 3767 | } else { | |
| ee61f228 | 3768 | bus_setup_intr(dev, np->irq_res, 0, |
| e9cb6d99 | 3769 | ncr_intr, np, &np->irq_handle, NULL); |
| 984263bc MD |
3770 | } |
| 3771 | ||
| 3772 | /* | |
| 3773 | ** Create the device queue. We only allow MAX_START-1 concurrent | |
| 3774 | ** transactions so we can be sure to have one element free in our | |
| 3775 | ** start queue to reset to the idle loop. | |
| 3776 | */ | |
| 3777 | devq = cam_simq_alloc(MAX_START - 1); | |
| 3778 | if (devq == NULL) | |
| 3779 | return ENOMEM; | |
| 3780 | ||
| 3781 | /* | |
| 3782 | ** Now tell the generic SCSI layer | |
| 3783 | ** about our bus. | |
| 3784 | */ | |
| 3785 | np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, np->unit, | |
| 1c8b7a9a | 3786 | &sim_mplock, 1, MAX_TAGS, devq); |
| 3aed1355 MD |
3787 | cam_simq_release(devq); |
| 3788 | if (np->sim == NULL) | |
| 984263bc | 3789 | return ENOMEM; |
| 984263bc MD |
3790 | |
| 3791 | ||
| 3792 | if (xpt_bus_register(np->sim, 0) != CAM_SUCCESS) { | |
| 3aed1355 | 3793 | cam_sim_free(np->sim); |
| 984263bc MD |
3794 | return ENOMEM; |
| 3795 | } | |
| 3796 | ||
| 3797 | if (xpt_create_path(&np->path, /*periph*/NULL, | |
| 3798 | cam_sim_path(np->sim), CAM_TARGET_WILDCARD, | |
| 3799 | CAM_LUN_WILDCARD) != CAM_REQ_CMP) { | |
| 3800 | xpt_bus_deregister(cam_sim_path(np->sim)); | |
| 3aed1355 | 3801 | cam_sim_free(np->sim); |
| 984263bc MD |
3802 | return ENOMEM; |
| 3803 | } | |
| 3804 | ||
| 3805 | /* | |
| 3806 | ** start the timeout daemon | |
| 3807 | */ | |
| 7ed1b850 | 3808 | callout_init(&np->timeout_ch); |
| 984263bc MD |
3809 | ncr_timeout (np); |
| 3810 | np->lasttime=0; | |
| 3811 | ||
| 3812 | return 0; | |
| 3813 | } | |
| 3814 | ||
| 3815 | /*========================================================== | |
| 3816 | ** | |
| 3817 | ** | |
| 3818 | ** Process pending device interrupts. | |
| 3819 | ** | |
| 3820 | ** | |
| 3821 | **========================================================== | |
| 3822 | */ | |
| 3823 | ||
| 3824 | static void | |
| 773330af | 3825 | ncr_intr(void *vnp) |
| 984263bc MD |
3826 | { |
| 3827 | ncb_p np = vnp; | |
| 2c9868e4 | 3828 | crit_enter(); |
| 984263bc | 3829 | |
| e3869ec7 | 3830 | if (DEBUG_FLAGS & DEBUG_TINY) kprintf ("["); |
| 984263bc MD |
3831 | |
| 3832 | if (INB(nc_istat) & (INTF|SIP|DIP)) { | |
| 3833 | /* | |
| 3834 | ** Repeat until no outstanding ints | |
| 3835 | */ | |
| 3836 | do { | |
| 3837 | ncr_exception (np); | |
| 3838 | } while (INB(nc_istat) & (INTF|SIP|DIP)); | |
| 3839 | ||
| 3840 | np->ticks = 100; | |
| 3841 | }; | |
| 3842 | ||
| e3869ec7 | 3843 | if (DEBUG_FLAGS & DEBUG_TINY) kprintf ("]\n"); |
| 984263bc | 3844 | |
| 2c9868e4 | 3845 | crit_exit(); |
| 984263bc MD |
3846 | } |
| 3847 | ||
| 3848 | /*========================================================== | |
| 3849 | ** | |
| 3850 | ** | |
| 3851 | ** Start execution of a SCSI command. | |
| 3852 | ** This is called from the generic SCSI driver. | |
| 3853 | ** | |
| 3854 | ** | |
| 3855 | **========================================================== | |
| 3856 | */ | |
| 3857 | ||
| 3858 | static void | |
| 3859 | ncr_action (struct cam_sim *sim, union ccb *ccb) | |
| 3860 | { | |
| 3861 | ncb_p np; | |
| 3862 | ||
| 3863 | np = (ncb_p) cam_sim_softc(sim); | |
| 3864 | ||
| 3865 | switch (ccb->ccb_h.func_code) { | |
| 3866 | /* Common cases first */ | |
| 3867 | case XPT_SCSI_IO: /* Execute the requested I/O operation */ | |
| 3868 | { | |
| 3869 | nccb_p cp; | |
| 3870 | lcb_p lp; | |
| 3871 | tcb_p tp; | |
| 984263bc MD |
3872 | struct ccb_scsiio *csio; |
| 3873 | u_int8_t *msgptr; | |
| 3874 | u_int msglen; | |
| 3875 | u_int msglen2; | |
| 3876 | int segments; | |
| 3877 | u_int8_t nego; | |
| 3878 | u_int8_t idmsg; | |
| 6b08710e | 3879 | int qidx; |
| 984263bc MD |
3880 | |
| 3881 | tp = &np->target[ccb->ccb_h.target_id]; | |
| 3882 | csio = &ccb->csio; | |
| 3883 | ||
| 2c9868e4 | 3884 | crit_enter(); |
| 984263bc MD |
3885 | |
| 3886 | /* | |
| 3887 | * Last time we need to check if this CCB needs to | |
| 3888 | * be aborted. | |
| 3889 | */ | |
| 3890 | if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { | |
| 3891 | xpt_done(ccb); | |
| 2c9868e4 | 3892 | crit_exit(); |
| 984263bc MD |
3893 | return; |
| 3894 | } | |
| 3895 | ccb->ccb_h.status |= CAM_SIM_QUEUED; | |
| 3896 | ||
| 3897 | /*--------------------------------------------------- | |
| 3898 | ** | |
| 3899 | ** Assign an nccb / bind ccb | |
| 3900 | ** | |
| 3901 | **---------------------------------------------------- | |
| 3902 | */ | |
| 3903 | cp = ncr_get_nccb (np, ccb->ccb_h.target_id, | |
| 3904 | ccb->ccb_h.target_lun); | |
| 3905 | if (cp == NULL) { | |
| 3906 | /* XXX JGibbs - Freeze SIMQ */ | |
| 3907 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; | |
| 3908 | xpt_done(ccb); | |
| 3909 | return; | |
| 3910 | }; | |
| 3911 | ||
| 3912 | cp->ccb = ccb; | |
| 3913 | ||
| 3914 | /*--------------------------------------------------- | |
| 3915 | ** | |
| 3916 | ** timestamp | |
| 3917 | ** | |
| 3918 | **---------------------------------------------------- | |
| 3919 | */ | |
| 3920 | /* | |
| 3921 | ** XXX JGibbs - Isn't this expensive | |
| 3922 | ** enough to be conditionalized?? | |
| 3923 | */ | |
| 3924 | ||
| 3925 | bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); | |
| 3926 | cp->phys.header.stamp.start = ticks; | |
| 3927 | ||
| 3928 | nego = 0; | |
| 3929 | if (tp->nego_cp == NULL) { | |
| 3930 | ||
| 3931 | if (tp->tinfo.current.width | |
| 3932 | != tp->tinfo.goal.width) { | |
| 3933 | tp->nego_cp = cp; | |
| 3934 | nego = NS_WIDE; | |
| 3935 | } else if ((tp->tinfo.current.period | |
| 3936 | != tp->tinfo.goal.period) | |
| 3937 | || (tp->tinfo.current.offset | |
| 3938 | != tp->tinfo.goal.offset)) { | |
| 3939 | tp->nego_cp = cp; | |
| 3940 | nego = NS_SYNC; | |
| 3941 | }; | |
| 3942 | }; | |
| 3943 | ||
| 3944 | /*--------------------------------------------------- | |
| 3945 | ** | |
| 3946 | ** choose a new tag ... | |
| 3947 | ** | |
| 3948 | **---------------------------------------------------- | |
| 3949 | */ | |
| 3950 | lp = tp->lp[ccb->ccb_h.target_lun]; | |
| 3951 | ||
| 3952 | if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0 | |
| 3953 | && (ccb->csio.tag_action != CAM_TAG_ACTION_NONE) | |
| 3954 | && (nego == 0)) { | |
| 3955 | /* | |
| 3956 | ** assign a tag to this nccb | |
| 3957 | */ | |
| 3958 | while (!cp->tag) { | |
| 3959 | nccb_p cp2 = lp->next_nccb; | |
| 3960 | lp->lasttag = lp->lasttag % 255 + 1; | |
| 3961 | while (cp2 && cp2->tag != lp->lasttag) | |
| 3962 | cp2 = cp2->next_nccb; | |
| 3963 | if (cp2) continue; | |
| 3964 | cp->tag=lp->lasttag; | |
| 3965 | if (DEBUG_FLAGS & DEBUG_TAGS) { | |
| 3966 | PRINT_ADDR(ccb); | |
| e3869ec7 | 3967 | kprintf ("using tag #%d.\n", cp->tag); |
| 984263bc MD |
3968 | }; |
| 3969 | }; | |
| 3970 | } else { | |
| 3971 | cp->tag=0; | |
| 3972 | }; | |
| 3973 | ||
| 3974 | /*---------------------------------------------------- | |
| 3975 | ** | |
| 3976 | ** Build the identify / tag / sdtr message | |
| 3977 | ** | |
| 3978 | **---------------------------------------------------- | |
| 3979 | */ | |
| 3980 | idmsg = MSG_IDENTIFYFLAG | ccb->ccb_h.target_lun; | |
| 3981 | if (tp->tinfo.disc_tag & NCR_CUR_DISCENB) | |
| 3982 | idmsg |= MSG_IDENTIFY_DISCFLAG; | |
| 3983 | ||
| 3984 | msgptr = cp->scsi_smsg; | |
| 3985 | msglen = 0; | |
| 3986 | msgptr[msglen++] = idmsg; | |
| 3987 | ||
| 3988 | if (cp->tag) { | |
| 3989 | msgptr[msglen++] = ccb->csio.tag_action; | |
| 3990 | msgptr[msglen++] = cp->tag; | |
| 3991 | } | |
| 3992 | ||
| 3993 | switch (nego) { | |
| 3994 | case NS_SYNC: | |
| 3995 | msgptr[msglen++] = MSG_EXTENDED; | |
| 3996 | msgptr[msglen++] = MSG_EXT_SDTR_LEN; | |
| 3997 | msgptr[msglen++] = MSG_EXT_SDTR; | |
| 3998 | msgptr[msglen++] = tp->tinfo.goal.period; | |
| fc6d0222 | 3999 | msgptr[msglen++] = tp->tinfo.goal.offset; |
| 984263bc MD |
4000 | if (DEBUG_FLAGS & DEBUG_NEGO) { |
| 4001 | PRINT_ADDR(ccb); | |
| e3869ec7 | 4002 | kprintf ("sync msgout: "); |
| 984263bc | 4003 | ncr_show_msg (&cp->scsi_smsg [msglen-5]); |
| e3869ec7 | 4004 | kprintf (".\n"); |
| 984263bc MD |
4005 | }; |
| 4006 | break; | |
| 4007 | case NS_WIDE: | |
| 4008 | msgptr[msglen++] = MSG_EXTENDED; | |
| 4009 | msgptr[msglen++] = MSG_EXT_WDTR_LEN; | |
| 4010 | msgptr[msglen++] = MSG_EXT_WDTR; | |
| 4011 | msgptr[msglen++] = tp->tinfo.goal.width; | |
| 4012 | if (DEBUG_FLAGS & DEBUG_NEGO) { | |
| 4013 | PRINT_ADDR(ccb); | |
| e3869ec7 | 4014 | kprintf ("wide msgout: "); |
| 984263bc | 4015 | ncr_show_msg (&cp->scsi_smsg [msglen-4]); |
| e3869ec7 | 4016 | kprintf (".\n"); |
| 984263bc MD |
4017 | }; |
| 4018 | break; | |
| 4019 | }; | |
| 4020 | ||
| 4021 | /*---------------------------------------------------- | |
| 4022 | ** | |
| 4023 | ** Build the identify message for getcc. | |
| 4024 | ** | |
| 4025 | **---------------------------------------------------- | |
| 4026 | */ | |
| 4027 | ||
| 4028 | cp->scsi_smsg2 [0] = idmsg; | |
| 4029 | msglen2 = 1; | |
| 4030 | ||
| 4031 | /*---------------------------------------------------- | |
| 4032 | ** | |
| 4033 | ** Build the data descriptors | |
| 4034 | ** | |
| 4035 | **---------------------------------------------------- | |
| 4036 | */ | |
| 4037 | ||
| 4038 | /* XXX JGibbs - Handle other types of I/O */ | |
| 4039 | if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { | |
| 4040 | segments = ncr_scatter(&cp->phys, | |
| 4041 | (vm_offset_t)csio->data_ptr, | |
| 4042 | (vm_size_t)csio->dxfer_len); | |
| 4043 | ||
| 4044 | if (segments < 0) { | |
| 4045 | ccb->ccb_h.status = CAM_REQ_TOO_BIG; | |
| 4046 | ncr_free_nccb(np, cp); | |
| 2c9868e4 | 4047 | crit_exit(); |
| 984263bc MD |
4048 | xpt_done(ccb); |
| 4049 | return; | |
| 4050 | } | |
| 4051 | if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { | |
| 4052 | cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in); | |
| 4053 | cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; | |
| 4054 | } else { /* CAM_DIR_OUT */ | |
| 4055 | cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_out); | |
| 4056 | cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; | |
| 4057 | } | |
| 4058 | } else { | |
| 4059 | cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data); | |
| 4060 | cp->phys.header.goalp = cp->phys.header.savep; | |
| 4061 | } | |
| 4062 | ||
| 4063 | cp->phys.header.lastp = cp->phys.header.savep; | |
| 4064 | ||
| 4065 | ||
| 4066 | /*---------------------------------------------------- | |
| 4067 | ** | |
| 4068 | ** fill in nccb | |
| 4069 | ** | |
| 4070 | **---------------------------------------------------- | |
| 4071 | ** | |
| 4072 | ** | |
| 4073 | ** physical -> virtual backlink | |
| 4074 | ** Generic SCSI command | |
| 4075 | */ | |
| 4076 | cp->phys.header.cp = cp; | |
| 4077 | /* | |
| 4078 | ** Startqueue | |
| 4079 | */ | |
| 4080 | cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, select); | |
| 4081 | cp->phys.header.launch.l_cmd = SCR_JUMP; | |
| 4082 | /* | |
| 4083 | ** select | |
| 4084 | */ | |
| 4085 | cp->phys.select.sel_id = ccb->ccb_h.target_id; | |
| 4086 | cp->phys.select.sel_scntl3 = tp->tinfo.wval; | |
| 4087 | cp->phys.select.sel_sxfer = tp->tinfo.sval; | |
| 4088 | /* | |
| 4089 | ** message | |
| 4090 | */ | |
| 4091 | cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg); | |
| 4092 | cp->phys.smsg.size = msglen; | |
| 4093 | ||
| 4094 | cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2); | |
| 4095 | cp->phys.smsg2.size = msglen2; | |
| 4096 | /* | |
| 4097 | ** command | |
| 4098 | */ | |
| 4099 | /* XXX JGibbs - Support other command types */ | |
| 4100 | cp->phys.cmd.addr = vtophys (csio->cdb_io.cdb_bytes); | |
| 4101 | cp->phys.cmd.size = csio->cdb_len; | |
| 4102 | /* | |
| 4103 | ** sense command | |
| 4104 | */ | |
| 4105 | cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd); | |
| 4106 | cp->phys.scmd.size = 6; | |
| 4107 | /* | |
| 4108 | ** patch requested size into sense command | |
| 4109 | */ | |
| 4110 | cp->sensecmd[0] = 0x03; | |
| 4111 | cp->sensecmd[1] = ccb->ccb_h.target_lun << 5; | |
| 4112 | cp->sensecmd[4] = sizeof(struct scsi_sense_data); | |
| 4113 | cp->sensecmd[4] = csio->sense_len; | |
| 4114 | /* | |
| 4115 | ** sense data | |
| 4116 | */ | |
| 4117 | cp->phys.sense.addr = vtophys (&csio->sense_data); | |
| 4118 | cp->phys.sense.size = csio->sense_len; | |
| 4119 | /* | |
| 4120 | ** status | |
| 4121 | */ | |
| 4122 | cp->actualquirks = QUIRK_NOMSG; | |
| 4123 | cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; | |
| 4124 | cp->s_status = SCSI_STAT |