1 /* $FreeBSD: src/sys/dev/asr/asr.c,v 1.3.2.2 2001/08/23 05:21:29 scottl Exp $ */ 2 /* $DragonFly: src/sys/dev/raid/asr/asr.c,v 1.36 2008/06/05 18:06:31 swildner Exp $ */ 3 /* 4 * Copyright (c) 1996-2000 Distributed Processing Technology Corporation 5 * Copyright (c) 2000-2001 Adaptec Corporation 6 * All rights reserved. 7 * 8 * TERMS AND CONDITIONS OF USE 9 * 10 * Redistribution and use in source form, with or without modification, are 11 * permitted provided that redistributions of source code must retain the 12 * above copyright notice, this list of conditions and the following disclaimer. 13 * 14 * This software is provided `as is' by Adaptec and any express or implied 15 * warranties, including, but not limited to, the implied warranties of 16 * merchantability and fitness for a particular purpose, are disclaimed. In no 17 * event shall Adaptec be liable for any direct, indirect, incidental, special, 18 * exemplary or consequential damages (including, but not limited to, 19 * procurement of substitute goods or services; loss of use, data, or profits; 20 * or business interruptions) however caused and on any theory of liability, 21 * whether in contract, strict liability, or tort (including negligence or 22 * otherwise) arising in any way out of the use of this driver software, even 23 * if advised of the possibility of such damage. 24 * 25 * SCSI I2O host adapter driver 26 * 27 * V1.08 2001/08/21 Mark_Salyzyn@adaptec.com 28 * - The 2000S and 2005S do not initialize on some machines, 29 * increased timeout to 255ms from 50ms for the StatusGet 30 * command. 31 * V1.07 2001/05/22 Mark_Salyzyn@adaptec.com 32 * - I knew this one was too good to be true. The error return 33 * on ioctl commands needs to be compared to CAM_REQ_CMP, not 34 * to the bit masked status. 35 * V1.06 2001/05/08 Mark_Salyzyn@adaptec.com 36 * - The 2005S that was supported is affectionately called the 37 * Conjoined BAR Firmware. In order to support RAID-5 in a 38 * 16MB low-cost configuration, Firmware was forced to go 39 * to a Split BAR Firmware. This requires a separate IOP and 40 * Messaging base address. 41 * V1.05 2001/04/25 Mark_Salyzyn@adaptec.com 42 * - Handle support for 2005S Zero Channel RAID solution. 43 * - System locked up if the Adapter locked up. Do not try 44 * to send other commands if the resetIOP command fails. The 45 * fail outstanding command discovery loop was flawed as the 46 * removal of the command from the list prevented discovering 47 * all the commands. 48 * - Comment changes to clarify driver. 49 * - SysInfo searched for an EATA SmartROM, not an I2O SmartROM. 50 * - We do not use the AC_FOUND_DEV event because of I2O. 51 * Removed asr_async. 52 * V1.04 2000/09/22 Mark_Salyzyn@adaptec.com, msmith@freebsd.org, 53 * lampa@fee.vutbr.cz and Scott_Long@adaptec.com. 54 * - Removed support for PM1554, PM2554 and PM2654 in Mode-0 55 * mode as this is confused with competitor adapters in run 56 * mode. 57 * - critical locking needed in ASR_ccbAdd and ASR_ccbRemove 58 * to prevent operating system panic. 59 * - moved default major number to 154 from 97. 60 * V1.03 2000/07/12 Mark_Salyzyn@adaptec.com 61 * - The controller is not actually an ASR (Adaptec SCSI RAID) 62 * series that is visible, it's more of an internal code name. 63 * remove any visible references within reason for now. 64 * - bus_ptr->LUN was not correctly zeroed when initially 65 * allocated causing a possible panic of the operating system 66 * during boot. 67 * V1.02 2000/06/26 Mark_Salyzyn@adaptec.com 68 * - Code always fails for ASR_getTid affecting performance. 69 * - initiated a set of changes that resulted from a formal 70 * code inspection by Mark_Salyzyn@adaptec.com, 71 * George_Dake@adaptec.com, Jeff_Zeak@adaptec.com, 72 * Martin_Wilson@adaptec.com and Vincent_Trandoan@adaptec.com. 73 * Their findings were focussed on the LCT & TID handler, and 74 * all resulting changes were to improve code readability, 75 * consistency or have a positive effect on performance. 76 * V1.01 2000/06/14 Mark_Salyzyn@adaptec.com 77 * - Passthrough returned an incorrect error. 78 * - Passthrough did not migrate the intrinsic scsi layer wakeup 79 * on command completion. 80 * - generate control device nodes using make_dev and delete_dev. 81 * - Performance affected by TID caching reallocing. 82 * - Made suggested changes by Justin_Gibbs@adaptec.com 83 * - use splcam instead of splbio. 84 * - use u_int8_t instead of u_char. 85 * - use u_int16_t instead of u_short. 86 * - use u_int32_t instead of u_long where appropriate. 87 * - use 64 bit context handler instead of 32 bit. 88 * - create_ccb should only allocate the worst case 89 * requirements for the driver since CAM may evolve 90 * making union ccb much larger than needed here. 91 * renamed create_ccb to asr_alloc_ccb. 92 * - go nutz justifying all debug prints as macros 93 * defined at the top and remove unsightly ifdefs. 94 * - INLINE STATIC viewed as confusing. Historically 95 * utilized to affect code performance and debug 96 * issues in OS, Compiler or OEM specific situations. 97 * V1.00 2000/05/31 Mark_Salyzyn@adaptec.com 98 * - Ported from FreeBSD 2.2.X DPT I2O driver. 99 * changed struct scsi_xfer to union ccb/struct ccb_hdr 100 * changed variable name xs to ccb 101 * changed struct scsi_link to struct cam_path 102 * changed struct scsibus_data to struct cam_sim 103 * stopped using fordriver for holding on to the TID 104 * use proprietary packet creation instead of scsi_inquire 105 * CAM layer sends synchronize commands. 106 */ 107 108 #define ASR_VERSION 1 109 #define ASR_REVISION '0' 110 #define ASR_SUBREVISION '8' 111 #define ASR_MONTH 8 112 #define ASR_DAY 21 113 #define ASR_YEAR 2001 - 1980 114 115 /* 116 * Debug macros to reduce the unsightly ifdefs 117 */ 118 #if (defined(DEBUG_ASR) || defined(DEBUG_ASR_USR_CMD) || defined(DEBUG_ASR_CMD)) 119 # define debug_asr_message(message) \ 120 { \ 121 u_int32_t * pointer = (u_int32_t *)message; \ 122 u_int32_t length = I2O_MESSAGE_FRAME_getMessageSize(message);\ 123 u_int32_t counter = 0; \ 124 \ 125 while (length--) { \ 126 kprintf ("%08lx%c", (u_long)*(pointer++), \ 127 (((++counter & 7) == 0) || (length == 0)) \ 128 ? '\n' \ 129 : ' '); \ 130 } \ 131 } 132 #endif /* DEBUG_ASR || DEBUG_ASR_USR_CMD || DEBUG_ASR_CMD */ 133 134 #if (defined(DEBUG_ASR)) 135 /* Breaks on none STDC based compilers :-( */ 136 # define debug_asr_printf(fmt,args...) kprintf(fmt, ##args) 137 # define debug_asr_dump_message(message) debug_asr_message(message) 138 # define debug_asr_print_path(ccb) xpt_print_path(ccb->ccb_h.path); 139 /* None fatal version of the ASSERT macro */ 140 # if (defined(__STDC__)) 141 # define ASSERT(phrase) if(!(phrase))kprintf(#phrase " at line %d file %s\n",__LINE__,__FILE__) 142 # else 143 # define ASSERT(phrase) if(!(phrase))kprintf("phrase" " at line %d file %s\n",__LINE__,__FILE__) 144 # endif 145 #else /* DEBUG_ASR */ 146 # define debug_asr_printf(fmt,args...) 147 # define debug_asr_dump_message(message) 148 # define debug_asr_print_path(ccb) 149 # define ASSERT(x) 150 #endif /* DEBUG_ASR */ 151 152 /* 153 * If DEBUG_ASR_CMD is defined: 154 * 0 - Display incoming SCSI commands 155 * 1 - add in a quick character before queueing. 156 * 2 - add in outgoing message frames. 157 */ 158 #if (defined(DEBUG_ASR_CMD)) 159 # define debug_asr_cmd_printf(fmt,args...) kprintf(fmt,##args) 160 # define debug_asr_dump_ccb(ccb) \ 161 { \ 162 u_int8_t * cp = (unsigned char *)&(ccb->csio.cdb_io); \ 163 int len = ccb->csio.cdb_len; \ 164 \ 165 while (len) { \ 166 debug_asr_cmd_printf (" %02x", *(cp++)); \ 167 --len; \ 168 } \ 169 } 170 # if (DEBUG_ASR_CMD > 0) 171 # define debug_asr_cmd1_printf debug_asr_cmd_printf 172 # else 173 # define debug_asr_cmd1_printf(fmt,args...) 174 # endif 175 # if (DEBUG_ASR_CMD > 1) 176 # define debug_asr_cmd2_printf debug_asr_cmd_printf 177 # define debug_asr_cmd2_dump_message(message) debug_asr_message(message) 178 # else 179 # define debug_asr_cmd2_printf(fmt,args...) 180 # define debug_asr_cmd2_dump_message(message) 181 # endif 182 #else /* DEBUG_ASR_CMD */ 183 # define debug_asr_cmd_printf(fmt,args...) 184 # define debug_asr_cmd_dump_ccb(ccb) 185 # define debug_asr_cmd1_printf(fmt,args...) 186 # define debug_asr_cmd2_printf(fmt,args...) 187 # define debug_asr_cmd2_dump_message(message) 188 #endif /* DEBUG_ASR_CMD */ 189 190 #if (defined(DEBUG_ASR_USR_CMD)) 191 # define debug_usr_cmd_printf(fmt,args...) kprintf(fmt,##args) 192 # define debug_usr_cmd_dump_message(message) debug_usr_message(message) 193 #else /* DEBUG_ASR_USR_CMD */ 194 # define debug_usr_cmd_printf(fmt,args...) 195 # define debug_usr_cmd_dump_message(message) 196 #endif /* DEBUG_ASR_USR_CMD */ 197 198 #define dsDescription_size 46 /* Snug as a bug in a rug */ 199 #include "dptsig.h" 200 201 static dpt_sig_S ASR_sig = { 202 { 'd', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, PROC_INTEL, 203 PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, FT_HBADRVR, 0, 204 OEM_DPT, OS_FREE_BSD, CAP_ABOVE16MB, DEV_ALL, 205 ADF_ALL_SC5, 206 0, 0, ASR_VERSION, ASR_REVISION, ASR_SUBREVISION, 207 ASR_MONTH, ASR_DAY, ASR_YEAR, 208 /* 01234567890123456789012345678901234567890123456789 < 50 chars */ 209 "Adaptec FreeBSD 4.0.0 Unix SCSI I2O HBA Driver" 210 /* ^^^^^ asr_attach alters these to match OS */ 211 }; 212 213 #include <sys/param.h> /* TRUE=1 and FALSE=0 defined here */ 214 #include <sys/kernel.h> 215 #include <sys/systm.h> 216 #include <sys/malloc.h> 217 #include <sys/proc.h> 218 #include <sys/priv.h> 219 #include <sys/conf.h> 220 #include <sys/bus.h> 221 #include <sys/rman.h> 222 #include <sys/stat.h> 223 #include <sys/device.h> 224 #include <sys/thread2.h> 225 #include <sys/ioccom.h> 226 227 #include <bus/cam/cam.h> 228 #include <bus/cam/cam_ccb.h> 229 #include <bus/cam/cam_sim.h> 230 #include <bus/cam/cam_xpt_sim.h> 231 #include <bus/cam/cam_xpt_periph.h> 232 233 #include <bus/cam/scsi/scsi_all.h> 234 #include <bus/cam/scsi/scsi_message.h> 235 236 #include <vm/vm.h> 237 #include <vm/pmap.h> 238 #include <machine/cputypes.h> 239 #include <machine/clock.h> 240 #include <machine/vmparam.h> 241 242 #include <bus/pci/pcivar.h> 243 #include <bus/pci/pcireg.h> 244 245 #define STATIC static 246 #define INLINE 247 248 #if (defined(DEBUG_ASR) && (DEBUG_ASR > 0)) 249 # undef STATIC 250 # define STATIC 251 # undef INLINE 252 # define INLINE 253 #endif 254 #define IN 255 #define OUT 256 #define INOUT 257 258 #define osdSwap4(x) ((u_long)ntohl((u_long)(x))) 259 #define KVTOPHYS(x) vtophys(x) 260 #include "dptalign.h" 261 #include "i2oexec.h" 262 #include "i2obscsi.h" 263 #include "i2odpt.h" 264 #include "i2oadptr.h" 265 #include "sys_info.h" 266 267 /* Configuration Definitions */ 268 269 #define SG_SIZE 58 /* Scatter Gather list Size */ 270 #define MAX_TARGET_ID 126 /* Maximum Target ID supported */ 271 #define MAX_LUN 255 /* Maximum LUN Supported */ 272 #define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */ 273 #define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */ 274 #define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */ 275 #define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */ 276 #define MAX_MAP 4194304L /* Maximum mapping size of IOP */ 277 /* Also serves as the minimum map for */ 278 /* the 2005S zero channel RAID product */ 279 280 /************************************************************************** 281 ** ASR Host Adapter structure - One Structure For Each Host Adapter That ** 282 ** Is Configured Into The System. The Structure Supplies Configuration ** 283 ** Information, Status Info, Queue Info And An Active CCB List Pointer. ** 284 ***************************************************************************/ 285 286 /* I2O register set */ 287 typedef struct { 288 U8 Address[0x30]; 289 volatile U32 Status; 290 volatile U32 Mask; 291 # define Mask_InterruptsDisabled 0x08 292 U32 x[2]; 293 volatile U32 ToFIFO; /* In Bound FIFO */ 294 volatile U32 FromFIFO; /* Out Bound FIFO */ 295 } i2oRegs_t; 296 297 /* 298 * A MIX of performance and space considerations for TID lookups 299 */ 300 typedef u_int16_t tid_t; 301 302 typedef struct { 303 u_int32_t size; /* up to MAX_LUN */ 304 tid_t TID[1]; 305 } lun2tid_t; 306 307 typedef struct { 308 u_int32_t size; /* up to MAX_TARGET */ 309 lun2tid_t * LUN[1]; 310 } target2lun_t; 311 312 /* 313 * To ensure that we only allocate and use the worst case ccb here, lets 314 * make our own local ccb union. If asr_alloc_ccb is utilized for another 315 * ccb type, ensure that you add the additional structures into our local 316 * ccb union. To ensure strict type checking, we will utilize the local 317 * ccb definition wherever possible. 318 */ 319 union asr_ccb { 320 struct ccb_hdr ccb_h; /* For convenience */ 321 struct ccb_scsiio csio; 322 struct ccb_setasync csa; 323 }; 324 325 typedef struct Asr_softc { 326 u_int16_t ha_irq; 327 void * ha_Base; /* base port for each board */ 328 u_int8_t * volatile ha_blinkLED; 329 i2oRegs_t * ha_Virt; /* Base address of IOP */ 330 U8 * ha_Fvirt; /* Base address of Frames */ 331 I2O_IOP_ENTRY ha_SystemTable; 332 LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */ 333 struct cam_path * ha_path[MAX_CHANNEL+1]; 334 struct cam_sim * ha_sim[MAX_CHANNEL+1]; 335 struct resource * ha_mem_res; 336 struct resource * ha_mes_res; 337 struct resource * ha_irq_res; 338 void * ha_intr; 339 PI2O_LCT ha_LCT; /* Complete list of devices */ 340 # define le_type IdentityTag[0] 341 # define I2O_BSA 0x20 342 # define I2O_FCA 0x40 343 # define I2O_SCSI 0x00 344 # define I2O_PORT 0x80 345 # define I2O_UNKNOWN 0x7F 346 # define le_bus IdentityTag[1] 347 # define le_target IdentityTag[2] 348 # define le_lun IdentityTag[3] 349 target2lun_t * ha_targets[MAX_CHANNEL+1]; 350 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs; 351 u_long ha_Msgs_Phys; 352 353 u_int8_t ha_in_reset; 354 # define HA_OPERATIONAL 0 355 # define HA_IN_RESET 1 356 # define HA_OFF_LINE 2 357 # define HA_OFF_LINE_RECOVERY 3 358 /* Configuration information */ 359 /* The target id maximums we take */ 360 u_int8_t ha_MaxBus; /* Maximum bus */ 361 u_int8_t ha_MaxId; /* Maximum target ID */ 362 u_int8_t ha_MaxLun; /* Maximum target LUN */ 363 u_int8_t ha_SgSize; /* Max SG elements */ 364 u_int8_t ha_pciBusNum; 365 u_int8_t ha_pciDeviceNum; 366 u_int8_t ha_adapter_target[MAX_CHANNEL+1]; 367 u_int16_t ha_QueueSize; /* Max outstanding commands */ 368 u_int16_t ha_Msgs_Count; 369 370 /* Links into other parents and HBAs */ 371 struct Asr_softc * ha_next; /* HBA list */ 372 } Asr_softc_t; 373 374 STATIC Asr_softc_t * Asr_softc; 375 376 /* 377 * Prototypes of the routines we have in this object. 378 */ 379 380 /* Externally callable routines */ 381 #define PROBE_ARGS IN device_t tag 382 #define PROBE_RET int 383 #define PROBE_SET() u_long id = (pci_get_device(tag)<<16)|pci_get_vendor(tag) 384 #define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);} 385 #define ATTACH_ARGS IN device_t tag 386 #define ATTACH_RET int 387 #define ATTACH_SET() int unit = device_get_unit(tag) 388 #define ATTACH_RETURN(retval) return(retval) 389 /* I2O HDM interface */ 390 STATIC PROBE_RET asr_probe (PROBE_ARGS); 391 STATIC ATTACH_RET asr_attach (ATTACH_ARGS); 392 /* DOMINO placeholder */ 393 STATIC PROBE_RET domino_probe (PROBE_ARGS); 394 STATIC ATTACH_RET domino_attach (ATTACH_ARGS); 395 /* MODE0 adapter placeholder */ 396 STATIC PROBE_RET mode0_probe (PROBE_ARGS); 397 STATIC ATTACH_RET mode0_attach (ATTACH_ARGS); 398 399 STATIC Asr_softc_t * ASR_get_sc (cdev_t dev); 400 STATIC d_ioctl_t asr_ioctl; 401 STATIC d_open_t asr_open; 402 STATIC d_close_t asr_close; 403 STATIC int asr_intr (IN Asr_softc_t *sc); 404 STATIC void asr_timeout (INOUT void *arg); 405 STATIC int ASR_init (IN Asr_softc_t *sc); 406 STATIC INLINE int ASR_acquireLct (INOUT Asr_softc_t *sc); 407 STATIC INLINE int ASR_acquireHrt (INOUT Asr_softc_t *sc); 408 STATIC void asr_action (IN struct cam_sim *sim, 409 IN union ccb *ccb); 410 STATIC void asr_poll (IN struct cam_sim * sim); 411 412 /* 413 * Here is the auto-probe structure used to nest our tests appropriately 414 * during the startup phase of the operating system. 415 */ 416 STATIC device_method_t asr_methods[] = { 417 DEVMETHOD(device_probe, asr_probe), 418 DEVMETHOD(device_attach, asr_attach), 419 { 0, 0 } 420 }; 421 422 STATIC driver_t asr_driver = { 423 "asr", 424 asr_methods, 425 sizeof(Asr_softc_t) 426 }; 427 428 STATIC devclass_t asr_devclass; 429 430 DECLARE_DUMMY_MODULE(asr); 431 DRIVER_MODULE(asr, pci, asr_driver, asr_devclass, 0, 0); 432 433 STATIC device_method_t domino_methods[] = { 434 DEVMETHOD(device_probe, domino_probe), 435 DEVMETHOD(device_attach, domino_attach), 436 { 0, 0 } 437 }; 438 439 STATIC driver_t domino_driver = { 440 "domino", 441 domino_methods, 442 0 443 }; 444 445 STATIC devclass_t domino_devclass; 446 447 DRIVER_MODULE(domino, pci, domino_driver, domino_devclass, 0, 0); 448 449 STATIC device_method_t mode0_methods[] = { 450 DEVMETHOD(device_probe, mode0_probe), 451 DEVMETHOD(device_attach, mode0_attach), 452 { 0, 0 } 453 }; 454 455 STATIC driver_t mode0_driver = { 456 "mode0", 457 mode0_methods, 458 0 459 }; 460 461 STATIC devclass_t mode0_devclass; 462 463 DRIVER_MODULE(mode0, pci, mode0_driver, mode0_devclass, 0, 0); 464 465 /* 466 * devsw for asr hba driver 467 * 468 * only ioctl is used. the sd driver provides all other access. 469 */ 470 STATIC struct dev_ops asr_ops = { 471 { "asr", -1, 0 }, 472 .d_open = asr_open, 473 .d_close = asr_close, 474 .d_ioctl = asr_ioctl, 475 }; 476 477 /* 478 * Initialize the dynamic dev_ops hooks. 479 */ 480 STATIC void 481 asr_drvinit (void * unused) 482 { 483 static int asr_devsw_installed = 0; 484 485 if (asr_devsw_installed) { 486 return; 487 } 488 asr_devsw_installed++; 489 490 /* 491 * Adding the ops will dynamically assign a major number. 492 */ 493 dev_ops_add(&asr_ops, 0, 0); 494 } /* asr_drvinit */ 495 496 /* XXX Must initialize before CAM layer picks up our HBA driver */ 497 SYSINIT(asrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,asr_drvinit,NULL) 498 499 /* I2O support routines */ 500 #define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)] 501 #define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME)) 502 503 /* 504 * Fill message with default. 505 */ 506 STATIC PI2O_MESSAGE_FRAME 507 ASR_fillMessage ( 508 IN char * Message, 509 IN u_int16_t size) 510 { 511 OUT PI2O_MESSAGE_FRAME Message_Ptr; 512 513 Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message); 514 bzero ((void *)Message_Ptr, size); 515 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11); 516 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, 517 (size + sizeof(U32) - 1) >> 2); 518 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); 519 return (Message_Ptr); 520 } /* ASR_fillMessage */ 521 522 #define EMPTY_QUEUE ((U32)-1L) 523 524 STATIC INLINE U32 525 ASR_getMessage( 526 IN i2oRegs_t * virt) 527 { 528 OUT U32 MessageOffset; 529 530 if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) { 531 MessageOffset = virt->ToFIFO; 532 } 533 return (MessageOffset); 534 } /* ASR_getMessage */ 535 536 /* Issue a polled command */ 537 STATIC U32 538 ASR_initiateCp ( 539 INOUT i2oRegs_t * virt, 540 INOUT U8 * fvirt, 541 IN PI2O_MESSAGE_FRAME Message) 542 { 543 OUT U32 Mask = -1L; 544 U32 MessageOffset; 545 u_int Delay = 1500; 546 547 /* 548 * ASR_initiateCp is only used for synchronous commands and will 549 * be made more resiliant to adapter delays since commands like 550 * resetIOP can cause the adapter to be deaf for a little time. 551 */ 552 while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE) 553 && (--Delay != 0)) { 554 DELAY (10000); 555 } 556 if (MessageOffset != EMPTY_QUEUE) { 557 bcopy (Message, fvirt + MessageOffset, 558 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); 559 /* 560 * Disable the Interrupts 561 */ 562 virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled; 563 virt->ToFIFO = MessageOffset; 564 } 565 return (Mask); 566 } /* ASR_initiateCp */ 567 568 /* 569 * Reset the adapter. 570 */ 571 STATIC U32 572 ASR_resetIOP ( 573 INOUT i2oRegs_t * virt, 574 INOUT U8 * fvirt) 575 { 576 struct resetMessage { 577 I2O_EXEC_IOP_RESET_MESSAGE M; 578 U32 R; 579 }; 580 defAlignLong(struct resetMessage,Message); 581 PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr; 582 OUT U32 * volatile Reply_Ptr; 583 U32 Old; 584 585 /* 586 * Build up our copy of the Message. 587 */ 588 Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message, 589 sizeof(I2O_EXEC_IOP_RESET_MESSAGE)); 590 I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET); 591 /* 592 * Reset the Reply Status 593 */ 594 *(Reply_Ptr = (U32 *)((char *)Message_Ptr 595 + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0; 596 I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr, 597 KVTOPHYS((void *)Reply_Ptr)); 598 /* 599 * Send the Message out 600 */ 601 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { 602 /* 603 * Wait for a response (Poll), timeouts are dangerous if 604 * the card is truly responsive. We assume response in 2s. 605 */ 606 u_int8_t Delay = 200; 607 608 while ((*Reply_Ptr == 0) && (--Delay != 0)) { 609 DELAY (10000); 610 } 611 /* 612 * Re-enable the interrupts. 613 */ 614 virt->Mask = Old; 615 ASSERT (*Reply_Ptr); 616 return (*Reply_Ptr); 617 } 618 ASSERT (Old != (U32)-1L); 619 return (0); 620 } /* ASR_resetIOP */ 621 622 /* 623 * Get the curent state of the adapter 624 */ 625 STATIC INLINE PI2O_EXEC_STATUS_GET_REPLY 626 ASR_getStatus ( 627 INOUT i2oRegs_t * virt, 628 INOUT U8 * fvirt, 629 OUT PI2O_EXEC_STATUS_GET_REPLY buffer) 630 { 631 defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message); 632 PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr; 633 U32 Old; 634 635 /* 636 * Build up our copy of the Message. 637 */ 638 Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message, 639 sizeof(I2O_EXEC_STATUS_GET_MESSAGE)); 640 I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr, 641 I2O_EXEC_STATUS_GET); 642 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr, 643 KVTOPHYS((void *)buffer)); 644 /* This one is a Byte Count */ 645 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr, 646 sizeof(I2O_EXEC_STATUS_GET_REPLY)); 647 /* 648 * Reset the Reply Status 649 */ 650 bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY)); 651 /* 652 * Send the Message out 653 */ 654 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { 655 /* 656 * Wait for a response (Poll), timeouts are dangerous if 657 * the card is truly responsive. We assume response in 50ms. 658 */ 659 u_int8_t Delay = 255; 660 661 while (*((U8 * volatile)&(buffer->SyncByte)) == 0) { 662 if (--Delay == 0) { 663 buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL; 664 break; 665 } 666 DELAY (1000); 667 } 668 /* 669 * Re-enable the interrupts. 670 */ 671 virt->Mask = Old; 672 return (buffer); 673 } 674 return ((PI2O_EXEC_STATUS_GET_REPLY)NULL); 675 } /* ASR_getStatus */ 676 677 /* 678 * Check if the device is a SCSI I2O HBA, and add it to the list. 679 */ 680 681 /* 682 * Probe for ASR controller. If we find it, we will use it. 683 * virtual adapters. 684 */ 685 STATIC PROBE_RET 686 asr_probe(PROBE_ARGS) 687 { 688 PROBE_SET(); 689 if ((id == 0xA5011044) || (id == 0xA5111044)) { 690 PROBE_RETURN ("Adaptec Caching SCSI RAID"); 691 } 692 PROBE_RETURN (NULL); 693 } /* asr_probe */ 694 695 /* 696 * Probe/Attach for DOMINO chipset. 697 */ 698 STATIC PROBE_RET 699 domino_probe(PROBE_ARGS) 700 { 701 PROBE_SET(); 702 if (id == 0x10121044) { 703 PROBE_RETURN ("Adaptec Caching Memory Controller"); 704 } 705 PROBE_RETURN (NULL); 706 } /* domino_probe */ 707 708 STATIC ATTACH_RET 709 domino_attach (ATTACH_ARGS) 710 { 711 ATTACH_RETURN (0); 712 } /* domino_attach */ 713 714 /* 715 * Probe/Attach for MODE0 adapters. 716 */ 717 STATIC PROBE_RET 718 mode0_probe(PROBE_ARGS) 719 { 720 PROBE_SET(); 721 722 /* 723 * If/When we can get a business case to commit to a 724 * Mode0 driver here, we can make all these tests more 725 * specific and robust. Mode0 adapters have their processors 726 * turned off, this the chips are in a raw state. 727 */ 728 729 /* This is a PLX9054 */ 730 if (id == 0x905410B5) { 731 PROBE_RETURN ("Adaptec Mode0 PM3757"); 732 } 733 /* This is a PLX9080 */ 734 if (id == 0x908010B5) { 735 PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755"); 736 } 737 /* This is a ZION 80303 */ 738 if (id == 0x53098086) { 739 PROBE_RETURN ("Adaptec Mode0 3010S"); 740 } 741 /* This is an i960RS */ 742 if (id == 0x39628086) { 743 PROBE_RETURN ("Adaptec Mode0 2100S"); 744 } 745 /* This is an i960RN */ 746 if (id == 0x19648086) { 747 PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S"); 748 } 749 #if 0 /* this would match any generic i960 -- mjs */ 750 /* This is an i960RP (typically also on Motherboards) */ 751 if (id == 0x19608086) { 752 PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654"); 753 } 754 #endif 755 PROBE_RETURN (NULL); 756 } /* mode0_probe */ 757 758 STATIC ATTACH_RET 759 mode0_attach (ATTACH_ARGS) 760 { 761 ATTACH_RETURN (0); 762 } /* mode0_attach */ 763 764 STATIC INLINE union asr_ccb * 765 asr_alloc_ccb ( 766 IN Asr_softc_t * sc) 767 { 768 OUT union asr_ccb * new_ccb; 769 770 new_ccb = (union asr_ccb *)kmalloc(sizeof(*new_ccb), M_DEVBUF, 771 M_WAITOK | M_ZERO); 772 new_ccb->ccb_h.pinfo.priority = 1; 773 new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 774 new_ccb->ccb_h.spriv_ptr0 = sc; 775 return (new_ccb); 776 } /* asr_alloc_ccb */ 777 778 STATIC INLINE void 779 asr_free_ccb ( 780 IN union asr_ccb * free_ccb) 781 { 782 kfree(free_ccb, M_DEVBUF); 783 } /* asr_free_ccb */ 784 785 /* 786 * Print inquiry data `carefully' 787 */ 788 STATIC void 789 ASR_prstring ( 790 u_int8_t * s, 791 int len) 792 { 793 while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) { 794 kprintf ("%c", *(s++)); 795 } 796 } /* ASR_prstring */ 797 798 /* 799 * Prototypes 800 */ 801 STATIC INLINE int ASR_queue ( 802 IN Asr_softc_t * sc, 803 IN PI2O_MESSAGE_FRAME Message); 804 /* 805 * Send a message synchronously and without Interrupt to a ccb. 806 */ 807 STATIC int 808 ASR_queue_s ( 809 INOUT union asr_ccb * ccb, 810 IN PI2O_MESSAGE_FRAME Message) 811 { 812 U32 Mask; 813 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); 814 815 /* 816 * We do not need any (optional byteswapping) method access to 817 * the Initiator context field. 818 */ 819 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); 820 821 /* Prevent interrupt service */ 822 crit_enter(); 823 sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask) 824 | Mask_InterruptsDisabled; 825 826 if (ASR_queue (sc, Message) == EMPTY_QUEUE) { 827 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 828 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 829 } 830 831 /* 832 * Wait for this board to report a finished instruction. 833 */ 834 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 835 (void)asr_intr (sc); 836 } 837 838 /* Re-enable Interrupts */ 839 sc->ha_Virt->Mask = Mask; 840 crit_exit(); 841 842 return (ccb->ccb_h.status); 843 } /* ASR_queue_s */ 844 845 /* 846 * Send a message synchronously to a Asr_softc_t 847 */ 848 STATIC int 849 ASR_queue_c ( 850 IN Asr_softc_t * sc, 851 IN PI2O_MESSAGE_FRAME Message) 852 { 853 union asr_ccb * ccb; 854 OUT int status; 855 856 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { 857 return (CAM_REQUEUE_REQ); 858 } 859 860 status = ASR_queue_s (ccb, Message); 861 862 asr_free_ccb(ccb); 863 864 return (status); 865 } /* ASR_queue_c */ 866 867 /* 868 * Add the specified ccb to the active queue 869 */ 870 STATIC INLINE void 871 ASR_ccbAdd ( 872 IN Asr_softc_t * sc, 873 INOUT union asr_ccb * ccb) 874 { 875 crit_enter(); 876 LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le); 877 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { 878 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) { 879 /* 880 * RAID systems can take considerable time to 881 * complete some commands given the large cache 882 * flashes switching from write back to write thru. 883 */ 884 ccb->ccb_h.timeout = 6 * 60 * 1000; 885 } 886 callout_reset(&ccb->ccb_h.timeout_ch, 887 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb); 888 } 889 crit_exit(); 890 } /* ASR_ccbAdd */ 891 892 /* 893 * Remove the specified ccb from the active queue. 894 */ 895 STATIC INLINE void 896 ASR_ccbRemove ( 897 IN Asr_softc_t * sc, 898 INOUT union asr_ccb * ccb) 899 { 900 crit_enter(); 901 callout_stop(&ccb->ccb_h.timeout_ch); 902 LIST_REMOVE(&(ccb->ccb_h), sim_links.le); 903 crit_exit(); 904 } /* ASR_ccbRemove */ 905 906 /* 907 * Fail all the active commands, so they get re-issued by the operating 908 * system. 909 */ 910 STATIC INLINE void 911 ASR_failActiveCommands ( 912 IN Asr_softc_t * sc) 913 { 914 struct ccb_hdr * ccb; 915 916 #if 0 /* Currently handled by callers, unnecessary paranoia currently */ 917 /* Left in for historical perspective. */ 918 defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message); 919 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; 920 921 /* Send a blind LCT command to wait for the enableSys to complete */ 922 Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message, 923 sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)); 924 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), 925 I2O_EXEC_LCT_NOTIFY); 926 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, 927 I2O_CLASS_MATCH_ANYCLASS); 928 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 929 #endif 930 931 crit_enter(); 932 /* 933 * We do not need to inform the CAM layer that we had a bus 934 * reset since we manage it on our own, this also prevents the 935 * SCSI_DELAY settling that would be required on other systems. 936 * The `SCSI_DELAY' has already been handled by the card via the 937 * acquisition of the LCT table while we are at CAM priority level. 938 * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) { 939 * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL); 940 * } 941 */ 942 while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) { 943 ASR_ccbRemove (sc, (union asr_ccb *)ccb); 944 945 ccb->status &= ~CAM_STATUS_MASK; 946 ccb->status |= CAM_REQUEUE_REQ; 947 /* Nothing Transfered */ 948 ((struct ccb_scsiio *)ccb)->resid 949 = ((struct ccb_scsiio *)ccb)->dxfer_len; 950 951 if (ccb->path) { 952 xpt_done ((union ccb *)ccb); 953 } else { 954 wakeup ((caddr_t)ccb); 955 } 956 } 957 crit_exit(); 958 } /* ASR_failActiveCommands */ 959 960 /* 961 * The following command causes the HBA to reset the specific bus 962 */ 963 STATIC INLINE void 964 ASR_resetBus( 965 IN Asr_softc_t * sc, 966 IN int bus) 967 { 968 defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message); 969 I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr; 970 PI2O_LCT_ENTRY Device; 971 972 Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message, 973 sizeof(I2O_HBA_BUS_RESET_MESSAGE)); 974 I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame, 975 I2O_HBA_BUS_RESET); 976 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) 977 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); 978 ++Device) { 979 if (((Device->le_type & I2O_PORT) != 0) 980 && (Device->le_bus == bus)) { 981 I2O_MESSAGE_FRAME_setTargetAddress( 982 &Message_Ptr->StdMessageFrame, 983 I2O_LCT_ENTRY_getLocalTID(Device)); 984 /* Asynchronous command, with no expectations */ 985 (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 986 break; 987 } 988 } 989 } /* ASR_resetBus */ 990 991 STATIC INLINE int 992 ASR_getBlinkLedCode ( 993 IN Asr_softc_t * sc) 994 { 995 if ((sc != (Asr_softc_t *)NULL) 996 && (sc->ha_blinkLED != (u_int8_t *)NULL) 997 && (sc->ha_blinkLED[1] == 0xBC)) { 998 return (sc->ha_blinkLED[0]); 999 } 1000 return (0); 1001 } /* ASR_getBlinkCode */ 1002 1003 /* 1004 * Determine the address of an TID lookup. Must be done at high priority 1005 * since the address can be changed by other threads of execution. 1006 * 1007 * Returns NULL pointer if not indexible (but will attempt to generate 1008 * an index if `new_entry' flag is set to TRUE). 1009 * 1010 * All addressible entries are to be guaranteed zero if never initialized. 1011 */ 1012 STATIC INLINE tid_t * 1013 ASR_getTidAddress( 1014 INOUT Asr_softc_t * sc, 1015 IN int bus, 1016 IN int target, 1017 IN int lun, 1018 IN int new_entry) 1019 { 1020 target2lun_t * bus_ptr; 1021 lun2tid_t * target_ptr; 1022 unsigned new_size; 1023 1024 /* 1025 * Validity checking of incoming parameters. More of a bound 1026 * expansion limit than an issue with the code dealing with the 1027 * values. 1028 * 1029 * sc must be valid before it gets here, so that check could be 1030 * dropped if speed a critical issue. 1031 */ 1032 if ((sc == (Asr_softc_t *)NULL) 1033 || (bus > MAX_CHANNEL) 1034 || (target > sc->ha_MaxId) 1035 || (lun > sc->ha_MaxLun)) { 1036 debug_asr_printf("(%lx,%d,%d,%d) target out of range\n", 1037 (u_long)sc, bus, target, lun); 1038 return ((tid_t *)NULL); 1039 } 1040 /* 1041 * See if there is an associated bus list. 1042 * 1043 * for performance, allocate in size of BUS_CHUNK chunks. 1044 * BUS_CHUNK must be a power of two. This is to reduce 1045 * fragmentation effects on the allocations. 1046 */ 1047 # define BUS_CHUNK 8 1048 new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1)); 1049 if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) { 1050 /* 1051 * Allocate a new structure? 1052 * Since one element in structure, the +1 1053 * needed for size has been abstracted. 1054 */ 1055 if ((new_entry == FALSE) 1056 || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)kmalloc ( 1057 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), 1058 M_TEMP, M_WAITOK)) 1059 == (target2lun_t *)NULL)) { 1060 debug_asr_printf("failed to allocate bus list\n"); 1061 return ((tid_t *)NULL); 1062 } 1063 bzero (bus_ptr, sizeof(*bus_ptr) 1064 + (sizeof(bus_ptr->LUN) * new_size)); 1065 bus_ptr->size = new_size + 1; 1066 } else if (bus_ptr->size <= new_size) { 1067 target2lun_t * new_bus_ptr; 1068 1069 /* 1070 * Reallocate a new structure? 1071 * Since one element in structure, the +1 1072 * needed for size has been abstracted. 1073 */ 1074 if ((new_entry == FALSE) 1075 || ((new_bus_ptr = (target2lun_t *)kmalloc ( 1076 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size), 1077 M_TEMP, M_WAITOK)) 1078 == (target2lun_t *)NULL)) { 1079 debug_asr_printf("failed to reallocate bus list\n"); 1080 return ((tid_t *)NULL); 1081 } 1082 /* 1083 * Zero and copy the whole thing, safer, simpler coding 1084 * and not really performance critical at this point. 1085 */ 1086 bzero (new_bus_ptr, sizeof(*bus_ptr) 1087 + (sizeof(bus_ptr->LUN) * new_size)); 1088 bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr) 1089 + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1))); 1090 sc->ha_targets[bus] = new_bus_ptr; 1091 kfree (bus_ptr, M_TEMP); 1092 bus_ptr = new_bus_ptr; 1093 bus_ptr->size = new_size + 1; 1094 } 1095 /* 1096 * We now have the bus list, lets get to the target list. 1097 * Since most systems have only *one* lun, we do not allocate 1098 * in chunks as above, here we allow one, then in chunk sizes. 1099 * TARGET_CHUNK must be a power of two. This is to reduce 1100 * fragmentation effects on the allocations. 1101 */ 1102 # define TARGET_CHUNK 8 1103 if ((new_size = lun) != 0) { 1104 new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1)); 1105 } 1106 if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) { 1107 /* 1108 * Allocate a new structure? 1109 * Since one element in structure, the +1 1110 * needed for size has been abstracted. 1111 */ 1112 if ((new_entry == FALSE) 1113 || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)kmalloc ( 1114 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), 1115 M_TEMP, M_WAITOK)) 1116 == (lun2tid_t *)NULL)) { 1117 debug_asr_printf("failed to allocate target list\n"); 1118 return ((tid_t *)NULL); 1119 } 1120 bzero (target_ptr, sizeof(*target_ptr) 1121 + (sizeof(target_ptr->TID) * new_size)); 1122 target_ptr->size = new_size + 1; 1123 } else if (target_ptr->size <= new_size) { 1124 lun2tid_t * new_target_ptr; 1125 1126 /* 1127 * Reallocate a new structure? 1128 * Since one element in structure, the +1 1129 * needed for size has been abstracted. 1130 */ 1131 if ((new_entry == FALSE) 1132 || ((new_target_ptr = (lun2tid_t *)kmalloc ( 1133 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size), 1134 M_TEMP, M_WAITOK)) 1135 == (lun2tid_t *)NULL)) { 1136 debug_asr_printf("failed to reallocate target list\n"); 1137 return ((tid_t *)NULL); 1138 } 1139 /* 1140 * Zero and copy the whole thing, safer, simpler coding 1141 * and not really performance critical at this point. 1142 */ 1143 bzero (new_target_ptr, sizeof(*target_ptr) 1144 + (sizeof(target_ptr->TID) * new_size)); 1145 bcopy (target_ptr, new_target_ptr, 1146 sizeof(*target_ptr) 1147 + (sizeof(target_ptr->TID) * (target_ptr->size - 1))); 1148 bus_ptr->LUN[target] = new_target_ptr; 1149 kfree (target_ptr, M_TEMP); 1150 target_ptr = new_target_ptr; 1151 target_ptr->size = new_size + 1; 1152 } 1153 /* 1154 * Now, acquire the TID address from the LUN indexed list. 1155 */ 1156 return (&(target_ptr->TID[lun])); 1157 } /* ASR_getTidAddress */ 1158 1159 /* 1160 * Get a pre-existing TID relationship. 1161 * 1162 * If the TID was never set, return (tid_t)-1. 1163 * 1164 * should use mutex rather than spl. 1165 */ 1166 STATIC INLINE tid_t 1167 ASR_getTid ( 1168 IN Asr_softc_t * sc, 1169 IN int bus, 1170 IN int target, 1171 IN int lun) 1172 { 1173 tid_t * tid_ptr; 1174 OUT tid_t retval; 1175 1176 crit_enter(); 1177 if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE)) 1178 == (tid_t *)NULL) 1179 /* (tid_t)0 or (tid_t)-1 indicate no TID */ 1180 || (*tid_ptr == (tid_t)0)) { 1181 crit_exit(); 1182 return ((tid_t)-1); 1183 } 1184 retval = *tid_ptr; 1185 crit_exit(); 1186 return (retval); 1187 } /* ASR_getTid */ 1188 1189 /* 1190 * Set a TID relationship. 1191 * 1192 * If the TID was not set, return (tid_t)-1. 1193 * 1194 * should use mutex rather than spl. 1195 */ 1196 STATIC INLINE tid_t 1197 ASR_setTid ( 1198 INOUT Asr_softc_t * sc, 1199 IN int bus, 1200 IN int target, 1201 IN int lun, 1202 INOUT tid_t TID) 1203 { 1204 tid_t * tid_ptr; 1205 1206 if (TID != (tid_t)-1) { 1207 if (TID == 0) { 1208 return ((tid_t)-1); 1209 } 1210 crit_enter(); 1211 if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE)) 1212 == (tid_t *)NULL) { 1213 crit_exit(); 1214 return ((tid_t)-1); 1215 } 1216 *tid_ptr = TID; 1217 crit_exit(); 1218 } 1219 return (TID); 1220 } /* ASR_setTid */ 1221 1222 /*-------------------------------------------------------------------------*/ 1223 /* Function ASR_rescan */ 1224 /*-------------------------------------------------------------------------*/ 1225 /* The Parameters Passed To This Function Are : */ 1226 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */ 1227 /* */ 1228 /* This Function Will rescan the adapter and resynchronize any data */ 1229 /* */ 1230 /* Return : 0 For OK, Error Code Otherwise */ 1231 /*-------------------------------------------------------------------------*/ 1232 1233 STATIC INLINE int 1234 ASR_rescan( 1235 IN Asr_softc_t * sc) 1236 { 1237 int bus; 1238 OUT int error; 1239 1240 /* 1241 * Re-acquire the LCT table and synchronize us to the adapter. 1242 */ 1243 if ((error = ASR_acquireLct(sc)) == 0) { 1244 error = ASR_acquireHrt(sc); 1245 } 1246 1247 if (error != 0) { 1248 return error; 1249 } 1250 1251 bus = sc->ha_MaxBus; 1252 /* Reset all existing cached TID lookups */ 1253 do { 1254 int target, event = 0; 1255 1256 /* 1257 * Scan for all targets on this bus to see if they 1258 * got affected by the rescan. 1259 */ 1260 for (target = 0; target <= sc->ha_MaxId; ++target) { 1261 int lun; 1262 1263 /* Stay away from the controller ID */ 1264 if (target == sc->ha_adapter_target[bus]) { 1265 continue; 1266 } 1267 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { 1268 PI2O_LCT_ENTRY Device; 1269 tid_t TID = (tid_t)-1; 1270 tid_t LastTID; 1271 1272 /* 1273 * See if the cached TID changed. Search for 1274 * the device in our new LCT. 1275 */ 1276 for (Device = sc->ha_LCT->LCTEntry; 1277 Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT) 1278 + I2O_LCT_getTableSize(sc->ha_LCT)); 1279 ++Device) { 1280 if ((Device->le_type != I2O_UNKNOWN) 1281 && (Device->le_bus == bus) 1282 && (Device->le_target == target) 1283 && (Device->le_lun == lun) 1284 && (I2O_LCT_ENTRY_getUserTID(Device) 1285 == 0xFFF)) { 1286 TID = I2O_LCT_ENTRY_getLocalTID( 1287 Device); 1288 break; 1289 } 1290 } 1291 /* 1292 * Indicate to the OS that the label needs 1293 * to be recalculated, or that the specific 1294 * open device is no longer valid (Merde) 1295 * because the cached TID changed. 1296 */ 1297 LastTID = ASR_getTid (sc, bus, target, lun); 1298 if (LastTID != TID) { 1299 struct cam_path * path; 1300 1301 if (xpt_create_path(&path, 1302 /*periph*/NULL, 1303 cam_sim_path(sc->ha_sim[bus]), 1304 target, lun) != CAM_REQ_CMP) { 1305 if (TID == (tid_t)-1) { 1306 event |= AC_LOST_DEVICE; 1307 } else { 1308 event |= AC_INQ_CHANGED 1309 | AC_GETDEV_CHANGED; 1310 } 1311 } else { 1312 if (TID == (tid_t)-1) { 1313 xpt_async( 1314 AC_LOST_DEVICE, 1315 path, NULL); 1316 } else if (LastTID == (tid_t)-1) { 1317 struct ccb_getdev ccb; 1318 1319 xpt_setup_ccb( 1320 &(ccb.ccb_h), 1321 path, /*priority*/5); 1322 xpt_async( 1323 AC_FOUND_DEVICE, 1324 path, 1325 &ccb); 1326 } else { 1327 xpt_async( 1328 AC_INQ_CHANGED, 1329 path, NULL); 1330 xpt_async( 1331 AC_GETDEV_CHANGED, 1332 path, NULL); 1333 } 1334 } 1335 } 1336 /* 1337 * We have the option of clearing the 1338 * cached TID for it to be rescanned, or to 1339 * set it now even if the device never got 1340 * accessed. We chose the later since we 1341 * currently do not use the condition that 1342 * the TID ever got cached. 1343 */ 1344 ASR_setTid (sc, bus, target, lun, TID); 1345 } 1346 } 1347 /* 1348 * The xpt layer can not handle multiple events at the 1349 * same call. 1350 */ 1351 if (event & AC_LOST_DEVICE) { 1352 xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL); 1353 } 1354 if (event & AC_INQ_CHANGED) { 1355 xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL); 1356 } 1357 if (event & AC_GETDEV_CHANGED) { 1358 xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL); 1359 } 1360 } while (--bus >= 0); 1361 return (error); 1362 } /* ASR_rescan */ 1363 1364 /*-------------------------------------------------------------------------*/ 1365 /* Function ASR_reset */ 1366 /*-------------------------------------------------------------------------*/ 1367 /* The Parameters Passed To This Function Are : */ 1368 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */ 1369 /* */ 1370 /* This Function Will reset the adapter and resynchronize any data */ 1371 /* */ 1372 /* Return : None */ 1373 /*-------------------------------------------------------------------------*/ 1374 1375 STATIC INLINE int 1376 ASR_reset( 1377 IN Asr_softc_t * sc) 1378 { 1379 int retVal; 1380 1381 crit_enter(); 1382 if ((sc->ha_in_reset == HA_IN_RESET) 1383 || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) { 1384 crit_exit(); 1385 return (EBUSY); 1386 } 1387 /* 1388 * Promotes HA_OPERATIONAL to HA_IN_RESET, 1389 * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY. 1390 */ 1391 ++(sc->ha_in_reset); 1392 if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) { 1393 debug_asr_printf ("ASR_resetIOP failed\n"); 1394 /* 1395 * We really need to take this card off-line, easier said 1396 * than make sense. Better to keep retrying for now since if a 1397 * UART cable is connected the blinkLEDs the adapter is now in 1398 * a hard state requiring action from the monitor commands to 1399 * the HBA to continue. For debugging waiting forever is a 1400 * good thing. In a production system, however, one may wish 1401 * to instead take the card off-line ... 1402 */ 1403 # if 0 && (defined(HA_OFF_LINE)) 1404 /* 1405 * Take adapter off-line. 1406 */ 1407 kprintf ("asr%d: Taking adapter off-line\n", 1408 sc->ha_path[0] 1409 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) 1410 : 0); 1411 sc->ha_in_reset = HA_OFF_LINE; 1412 crit_exit(); 1413 return (ENXIO); 1414 # else 1415 /* Wait Forever */ 1416 while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0); 1417 # endif 1418 } 1419 retVal = ASR_init (sc); 1420 crit_exit(); 1421 if (retVal != 0) { 1422 debug_asr_printf ("ASR_init failed\n"); 1423 sc->ha_in_reset = HA_OFF_LINE; 1424 return (ENXIO); 1425 } 1426 if (ASR_rescan (sc) != 0) { 1427 debug_asr_printf ("ASR_rescan failed\n"); 1428 } 1429 ASR_failActiveCommands (sc); 1430 if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) { 1431 kprintf ("asr%d: Brining adapter back on-line\n", 1432 sc->ha_path[0] 1433 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0])) 1434 : 0); 1435 } 1436 sc->ha_in_reset = HA_OPERATIONAL; 1437 return (0); 1438 } /* ASR_reset */ 1439 1440 /* 1441 * Device timeout handler. 1442 */ 1443 STATIC void 1444 asr_timeout( 1445 INOUT void * arg) 1446 { 1447 union asr_ccb * ccb = (union asr_ccb *)arg; 1448 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); 1449 int s; 1450 1451 debug_asr_print_path(ccb); 1452 debug_asr_printf("timed out"); 1453 1454 /* 1455 * Check if the adapter has locked up? 1456 */ 1457 if ((s = ASR_getBlinkLedCode(sc)) != 0) { 1458 /* Reset Adapter */ 1459 kprintf ("asr%d: Blink LED 0x%x resetting adapter\n", 1460 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s); 1461 if (ASR_reset (sc) == ENXIO) { 1462 /* Try again later */ 1463 callout_reset(&ccb->ccb_h.timeout_ch, 1464 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb); 1465 } 1466 return; 1467 } 1468 /* 1469 * Abort does not function on the ASR card!!! Walking away from 1470 * the SCSI command is also *very* dangerous. A SCSI BUS reset is 1471 * our best bet, followed by a complete adapter reset if that fails. 1472 */ 1473 crit_enter(); 1474 /* Check if we already timed out once to raise the issue */ 1475 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) { 1476 debug_asr_printf (" AGAIN\nreinitializing adapter\n"); 1477 if (ASR_reset (sc) == ENXIO) { 1478 callout_reset(&ccb->ccb_h.timeout_ch, 1479 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb); 1480 } 1481 crit_exit(); 1482 return; 1483 } 1484 debug_asr_printf ("\nresetting bus\n"); 1485 /* If the BUS reset does not take, then an adapter reset is next! */ 1486 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1487 ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 1488 callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000, 1489 asr_timeout, ccb); 1490 ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path))); 1491 xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL); 1492 crit_exit(); 1493 } /* asr_timeout */ 1494 1495 /* 1496 * send a message asynchronously 1497 */ 1498 STATIC INLINE int 1499 ASR_queue( 1500 IN Asr_softc_t * sc, 1501 IN PI2O_MESSAGE_FRAME Message) 1502 { 1503 OUT U32 MessageOffset; 1504 union asr_ccb * ccb; 1505 1506 debug_asr_printf ("Host Command Dump:\n"); 1507 debug_asr_dump_message (Message); 1508 1509 ccb = (union asr_ccb *)(long) 1510 I2O_MESSAGE_FRAME_getInitiatorContext64(Message); 1511 1512 if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) { 1513 bcopy (Message, sc->ha_Fvirt + MessageOffset, 1514 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2); 1515 if (ccb) { 1516 ASR_ccbAdd (sc, ccb); 1517 } 1518 /* Post the command */ 1519 sc->ha_Virt->ToFIFO = MessageOffset; 1520 } else { 1521 if (ASR_getBlinkLedCode(sc)) { 1522 /* 1523 * Unlikely we can do anything if we can't grab a 1524 * message frame :-(, but lets give it a try. 1525 */ 1526 (void)ASR_reset (sc); 1527 } 1528 } 1529 return (MessageOffset); 1530 } /* ASR_queue */ 1531 1532 1533 /* Simple Scatter Gather elements */ 1534 #define SG(SGL,Index,Flags,Buffer,Size) \ 1535 I2O_FLAGS_COUNT_setCount( \ 1536 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ 1537 Size); \ 1538 I2O_FLAGS_COUNT_setFlags( \ 1539 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \ 1540 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \ 1541 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \ 1542 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \ 1543 (Buffer == NULL) ? 0 : KVTOPHYS(Buffer)) 1544 1545 /* 1546 * Retrieve Parameter Group. 1547 * Buffer must be allocated using defAlignLong macro. 1548 */ 1549 STATIC void * 1550 ASR_getParams( 1551 IN Asr_softc_t * sc, 1552 IN tid_t TID, 1553 IN int Group, 1554 OUT void * Buffer, 1555 IN unsigned BufferSize) 1556 { 1557 struct paramGetMessage { 1558 I2O_UTIL_PARAMS_GET_MESSAGE M; 1559 char F[ 1560 sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)]; 1561 struct Operations { 1562 I2O_PARAM_OPERATIONS_LIST_HEADER Header; 1563 I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1]; 1564 } O; 1565 }; 1566 defAlignLong(struct paramGetMessage, Message); 1567 struct Operations * Operations_Ptr; 1568 I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr; 1569 struct ParamBuffer { 1570 I2O_PARAM_RESULTS_LIST_HEADER Header; 1571 I2O_PARAM_READ_OPERATION_RESULT Read; 1572 char Info[1]; 1573 } * Buffer_Ptr; 1574 1575 Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message, 1576 sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) 1577 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); 1578 Operations_Ptr = (struct Operations *)((char *)Message_Ptr 1579 + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) 1580 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)); 1581 bzero ((void *)Operations_Ptr, sizeof(struct Operations)); 1582 I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount( 1583 &(Operations_Ptr->Header), 1); 1584 I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation( 1585 &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET); 1586 I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount( 1587 &(Operations_Ptr->Template[0]), 0xFFFF); 1588 I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber( 1589 &(Operations_Ptr->Template[0]), Group); 1590 bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)), 1591 BufferSize); 1592 1593 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), 1594 I2O_VERSION_11 1595 + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) 1596 / sizeof(U32)) << 4)); 1597 I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame), 1598 TID); 1599 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), 1600 I2O_UTIL_PARAMS_GET); 1601 /* 1602 * Set up the buffers as scatter gather elements. 1603 */ 1604 SG(&(Message_Ptr->SGL), 0, 1605 I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, 1606 Operations_Ptr, sizeof(struct Operations)); 1607 SG(&(Message_Ptr->SGL), 1, 1608 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, 1609 Buffer_Ptr, BufferSize); 1610 1611 if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP) 1612 && (Buffer_Ptr->Header.ResultCount)) { 1613 return ((void *)(Buffer_Ptr->Info)); 1614 } 1615 return (NULL); 1616 } /* ASR_getParams */ 1617 1618 /* 1619 * Acquire the LCT information. 1620 */ 1621 STATIC INLINE int 1622 ASR_acquireLct ( 1623 INOUT Asr_softc_t * sc) 1624 { 1625 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr; 1626 PI2O_SGE_SIMPLE_ELEMENT sg; 1627 int MessageSizeInBytes; 1628 caddr_t v; 1629 int len; 1630 I2O_LCT Table; 1631 PI2O_LCT_ENTRY Entry; 1632 1633 /* 1634 * sc value assumed valid 1635 */ 1636 MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) 1637 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT); 1638 Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)kmalloc ( 1639 MessageSizeInBytes, M_TEMP, M_WAITOK); 1640 (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes); 1641 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), 1642 (I2O_VERSION_11 + 1643 (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT)) 1644 / sizeof(U32)) << 4))); 1645 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), 1646 I2O_EXEC_LCT_NOTIFY); 1647 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr, 1648 I2O_CLASS_MATCH_ANYCLASS); 1649 /* 1650 * Call the LCT table to determine the number of device entries 1651 * to reserve space for. 1652 */ 1653 SG(&(Message_Ptr->SGL), 0, 1654 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table, 1655 sizeof(I2O_LCT)); 1656 /* 1657 * since this code is reused in several systems, code efficiency 1658 * is greater by using a shift operation rather than a divide by 1659 * sizeof(u_int32_t). 1660 */ 1661 I2O_LCT_setTableSize(&Table, 1662 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); 1663 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 1664 /* 1665 * Determine the size of the LCT table. 1666 */ 1667 if (sc->ha_LCT) { 1668 kfree (sc->ha_LCT, M_TEMP); 1669 } 1670 /* 1671 * kmalloc only generates contiguous memory when less than a 1672 * page is expected. We must break the request up into an SG list ... 1673 */ 1674 if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <= 1675 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY))) 1676 || (len > (128 * 1024))) { /* Arbitrary */ 1677 kfree (Message_Ptr, M_TEMP); 1678 return (EINVAL); 1679 } 1680 sc->ha_LCT = (PI2O_LCT)kmalloc (len, M_TEMP, M_WAITOK); 1681 /* 1682 * since this code is reused in several systems, code efficiency 1683 * is greater by using a shift operation rather than a divide by 1684 * sizeof(u_int32_t). 1685 */ 1686 I2O_LCT_setTableSize(sc->ha_LCT, 1687 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2); 1688 /* 1689 * Convert the access to the LCT table into a SG list. 1690 */ 1691 sg = Message_Ptr->SGL.u.Simple; 1692 v = (caddr_t)(sc->ha_LCT); 1693 for (;;) { 1694 int next, base, span; 1695 1696 span = 0; 1697 next = base = KVTOPHYS(v); 1698 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); 1699 1700 /* How far can we go contiguously */ 1701 while ((len > 0) && (base == next)) { 1702 int size; 1703 1704 next = trunc_page(base) + PAGE_SIZE; 1705 size = next - base; 1706 if (size > len) { 1707 size = len; 1708 } 1709 span += size; 1710 v += size; 1711 len -= size; 1712 base = KVTOPHYS(v); 1713 } 1714 1715 /* Construct the Flags */ 1716 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); 1717 { 1718 int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT; 1719 if (len <= 0) { 1720 rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 1721 | I2O_SGL_FLAGS_LAST_ELEMENT 1722 | I2O_SGL_FLAGS_END_OF_BUFFER); 1723 } 1724 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw); 1725 } 1726 1727 if (len <= 0) { 1728 break; 1729 } 1730 1731 /* 1732 * Incrementing requires resizing of the packet. 1733 */ 1734 ++sg; 1735 MessageSizeInBytes += sizeof(*sg); 1736 I2O_MESSAGE_FRAME_setMessageSize( 1737 &(Message_Ptr->StdMessageFrame), 1738 I2O_MESSAGE_FRAME_getMessageSize( 1739 &(Message_Ptr->StdMessageFrame)) 1740 + (sizeof(*sg) / sizeof(U32))); 1741 { 1742 PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr; 1743 1744 NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE) 1745 kmalloc (MessageSizeInBytes, M_TEMP, M_WAITOK); 1746 span = ((caddr_t)sg) - (caddr_t)Message_Ptr; 1747 bcopy ((caddr_t)Message_Ptr, 1748 (caddr_t)NewMessage_Ptr, span); 1749 kfree (Message_Ptr, M_TEMP); 1750 sg = (PI2O_SGE_SIMPLE_ELEMENT) 1751 (((caddr_t)NewMessage_Ptr) + span); 1752 Message_Ptr = NewMessage_Ptr; 1753 } 1754 } 1755 { int retval; 1756 1757 retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 1758 kfree (Message_Ptr, M_TEMP); 1759 if (retval != CAM_REQ_CMP) { 1760 return (ENODEV); 1761 } 1762 } 1763 /* If the LCT table grew, lets truncate accesses */ 1764 if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) { 1765 I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table)); 1766 } 1767 for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY) 1768 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); 1769 ++Entry) { 1770 Entry->le_type = I2O_UNKNOWN; 1771 switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) { 1772 1773 case I2O_CLASS_RANDOM_BLOCK_STORAGE: 1774 Entry->le_type = I2O_BSA; 1775 break; 1776 1777 case I2O_CLASS_SCSI_PERIPHERAL: 1778 Entry->le_type = I2O_SCSI; 1779 break; 1780 1781 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: 1782 Entry->le_type = I2O_FCA; 1783 break; 1784 1785 case I2O_CLASS_BUS_ADAPTER_PORT: 1786 Entry->le_type = I2O_PORT | I2O_SCSI; 1787 /* FALLTHRU */ 1788 case I2O_CLASS_FIBRE_CHANNEL_PORT: 1789 if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) == 1790 I2O_CLASS_FIBRE_CHANNEL_PORT) { 1791 Entry->le_type = I2O_PORT | I2O_FCA; 1792 } 1793 { struct ControllerInfo { 1794 I2O_PARAM_RESULTS_LIST_HEADER Header; 1795 I2O_PARAM_READ_OPERATION_RESULT Read; 1796 I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; 1797 }; 1798 defAlignLong(struct ControllerInfo, Buffer); 1799 PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info; 1800 1801 Entry->le_bus = 0xff; 1802 Entry->le_target = 0xff; 1803 Entry->le_lun = 0xff; 1804 1805 if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR) 1806 ASR_getParams(sc, 1807 I2O_LCT_ENTRY_getLocalTID(Entry), 1808 I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, 1809 Buffer, sizeof(struct ControllerInfo))) 1810 == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) { 1811 continue; 1812 } 1813 Entry->le_target 1814 = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID( 1815 Info); 1816 Entry->le_lun = 0; 1817 } /* FALLTHRU */ 1818 default: 1819 continue; 1820 } 1821 { struct DeviceInfo { 1822 I2O_PARAM_RESULTS_LIST_HEADER Header; 1823 I2O_PARAM_READ_OPERATION_RESULT Read; 1824 I2O_DPT_DEVICE_INFO_SCALAR Info; 1825 }; 1826 defAlignLong (struct DeviceInfo, Buffer); 1827 PI2O_DPT_DEVICE_INFO_SCALAR Info; 1828 1829 Entry->le_bus = 0xff; 1830 Entry->le_target = 0xff; 1831 Entry->le_lun = 0xff; 1832 1833 if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR) 1834 ASR_getParams(sc, 1835 I2O_LCT_ENTRY_getLocalTID(Entry), 1836 I2O_DPT_DEVICE_INFO_GROUP_NO, 1837 Buffer, sizeof(struct DeviceInfo))) 1838 == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) { 1839 continue; 1840 } 1841 Entry->le_type 1842 |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info); 1843 Entry->le_bus 1844 = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info); 1845 if ((Entry->le_bus > sc->ha_MaxBus) 1846 && (Entry->le_bus <= MAX_CHANNEL)) { 1847 sc->ha_MaxBus = Entry->le_bus; 1848 } 1849 Entry->le_target 1850 = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info); 1851 Entry->le_lun 1852 = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info); 1853 } 1854 } 1855 /* 1856 * A zero return value indicates success. 1857 */ 1858 return (0); 1859 } /* ASR_acquireLct */ 1860 1861 /* 1862 * Initialize a message frame. 1863 * We assume that the CDB has already been set up, so all we do here is 1864 * generate the Scatter Gather list. 1865 */ 1866 STATIC INLINE PI2O_MESSAGE_FRAME 1867 ASR_init_message( 1868 IN union asr_ccb * ccb, 1869 OUT PI2O_MESSAGE_FRAME Message) 1870 { 1871 int next, span, base, rw; 1872 OUT PI2O_MESSAGE_FRAME Message_Ptr; 1873 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0); 1874 PI2O_SGE_SIMPLE_ELEMENT sg; 1875 caddr_t v; 1876 vm_size_t size, len; 1877 U32 MessageSize; 1878 1879 /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */ 1880 bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message), 1881 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))); 1882 1883 { 1884 int target = ccb->ccb_h.target_id; 1885 int lun = ccb->ccb_h.target_lun; 1886 int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)); 1887 tid_t TID; 1888 1889 if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) { 1890 PI2O_LCT_ENTRY Device; 1891 1892 TID = (tid_t)0; 1893 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) 1894 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); 1895 ++Device) { 1896 if ((Device->le_type != I2O_UNKNOWN) 1897 && (Device->le_bus == bus) 1898 && (Device->le_target == target) 1899 && (Device->le_lun == lun) 1900 && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) { 1901 TID = I2O_LCT_ENTRY_getLocalTID(Device); 1902 ASR_setTid (sc, Device->le_bus, 1903 Device->le_target, Device->le_lun, 1904 TID); 1905 break; 1906 } 1907 } 1908 } 1909 if (TID == (tid_t)0) { 1910 return ((PI2O_MESSAGE_FRAME)NULL); 1911 } 1912 I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID); 1913 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID( 1914 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID); 1915 } 1916 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 | 1917 (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)) 1918 / sizeof(U32)) << 4)); 1919 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, 1920 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 1921 - sizeof(I2O_SG_ELEMENT)) / sizeof(U32)); 1922 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1); 1923 I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE); 1924 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( 1925 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC); 1926 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( 1927 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, 1928 I2O_SCB_FLAG_ENABLE_DISCONNECT 1929 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 1930 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); 1931 /* 1932 * We do not need any (optional byteswapping) method access to 1933 * the Initiator & Transaction context field. 1934 */ 1935 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb); 1936 1937 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( 1938 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID); 1939 /* 1940 * copy the cdb over 1941 */ 1942 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength( 1943 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len); 1944 bcopy (&(ccb->csio.cdb_io), 1945 ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len); 1946 1947 /* 1948 * Given a buffer describing a transfer, set up a scatter/gather map 1949 * in a ccb to map that SCSI transfer. 1950 */ 1951 1952 rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR; 1953 1954 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags ( 1955 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, 1956 (ccb->csio.dxfer_len) 1957 ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE 1958 | I2O_SCB_FLAG_ENABLE_DISCONNECT 1959 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 1960 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER) 1961 : (I2O_SCB_FLAG_XFER_FROM_DEVICE 1962 | I2O_SCB_FLAG_ENABLE_DISCONNECT 1963 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 1964 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)) 1965 : (I2O_SCB_FLAG_ENABLE_DISCONNECT 1966 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 1967 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); 1968 1969 /* 1970 * Given a transfer described by a `data', fill in the SG list. 1971 */ 1972 sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0]; 1973 1974 len = ccb->csio.dxfer_len; 1975 v = ccb->csio.data_ptr; 1976 ASSERT (ccb->csio.dxfer_len >= 0); 1977 MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr); 1978 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( 1979 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len); 1980 while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 1981 Message_Ptr)->SGL.u.Simple[SG_SIZE])) { 1982 span = 0; 1983 next = base = KVTOPHYS(v); 1984 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base); 1985 1986 /* How far can we go contiguously */ 1987 while ((len > 0) && (base == next)) { 1988 next = trunc_page(base) + PAGE_SIZE; 1989 size = next - base; 1990 if (size > len) { 1991 size = len; 1992 } 1993 span += size; 1994 v += size; 1995 len -= size; 1996 base = KVTOPHYS(v); 1997 } 1998 1999 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span); 2000 if (len == 0) { 2001 rw |= I2O_SGL_FLAGS_LAST_ELEMENT; 2002 } 2003 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), 2004 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw); 2005 ++sg; 2006 MessageSize += sizeof(*sg) / sizeof(U32); 2007 } 2008 /* We always do the request sense ... */ 2009 if ((span = ccb->csio.sense_len) == 0) { 2010 span = sizeof(ccb->csio.sense_data); 2011 } 2012 SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, 2013 &(ccb->csio.sense_data), span); 2014 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, 2015 MessageSize + (sizeof(*sg) / sizeof(U32))); 2016 return (Message_Ptr); 2017 } /* ASR_init_message */ 2018 2019 /* 2020 * Reset the adapter. 2021 */ 2022 STATIC INLINE U32 2023 ASR_initOutBound ( 2024 INOUT Asr_softc_t * sc) 2025 { 2026 struct initOutBoundMessage { 2027 I2O_EXEC_OUTBOUND_INIT_MESSAGE M; 2028 U32 R; 2029 }; 2030 defAlignLong(struct initOutBoundMessage,Message); 2031 PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr; 2032 OUT U32 * volatile Reply_Ptr; 2033 U32 Old; 2034 2035 /* 2036 * Build up our copy of the Message. 2037 */ 2038 Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message, 2039 sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)); 2040 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), 2041 I2O_EXEC_OUTBOUND_INIT); 2042 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE); 2043 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr, 2044 sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)); 2045 /* 2046 * Reset the Reply Status 2047 */ 2048 *(Reply_Ptr = (U32 *)((char *)Message_Ptr 2049 + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0; 2050 SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr, 2051 sizeof(U32)); 2052 /* 2053 * Send the Message out 2054 */ 2055 if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) { 2056 u_long size, addr; 2057 2058 /* 2059 * Wait for a response (Poll). 2060 */ 2061 while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED); 2062 /* 2063 * Re-enable the interrupts. 2064 */ 2065 sc->ha_Virt->Mask = Old; 2066 /* 2067 * Populate the outbound table. 2068 */ 2069 if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { 2070 2071 /* Allocate the reply frames */ 2072 size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) 2073 * sc->ha_Msgs_Count; 2074 2075 /* 2076 * contigmalloc only works reliably at 2077 * initialization time. 2078 */ 2079 if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) 2080 contigmalloc (size, M_DEVBUF, M_WAITOK | M_ZERO, 0ul, 2081 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul)) 2082 != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) { 2083 sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs); 2084 } 2085 } 2086 2087 /* Initialize the outbound FIFO */ 2088 if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) 2089 for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys; 2090 size; --size) { 2091 sc->ha_Virt->FromFIFO = addr; 2092 addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME); 2093 } 2094 return (*Reply_Ptr); 2095 } 2096 return (0); 2097 } /* ASR_initOutBound */ 2098 2099 /* 2100 * Set the system table 2101 */ 2102 STATIC INLINE int 2103 ASR_setSysTab( 2104 IN Asr_softc_t * sc) 2105 { 2106 PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr; 2107 PI2O_SET_SYSTAB_HEADER SystemTable; 2108 Asr_softc_t * ha; 2109 PI2O_SGE_SIMPLE_ELEMENT sg; 2110 int retVal; 2111 2112 SystemTable = (PI2O_SET_SYSTAB_HEADER)kmalloc ( 2113 sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK | M_ZERO); 2114 for (ha = Asr_softc; ha; ha = ha->ha_next) { 2115 ++SystemTable->NumberEntries; 2116 } 2117 Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)kmalloc ( 2118 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) 2119 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)), 2120 M_TEMP, M_WAITOK); 2121 (void)ASR_fillMessage((char *)Message_Ptr, 2122 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT) 2123 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT))); 2124 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), 2125 (I2O_VERSION_11 + 2126 (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) 2127 / sizeof(U32)) << 4))); 2128 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), 2129 I2O_EXEC_SYS_TAB_SET); 2130 /* 2131 * Call the LCT table to determine the number of device entries 2132 * to reserve space for. 2133 * since this code is reused in several systems, code efficiency 2134 * is greater by using a shift operation rather than a divide by 2135 * sizeof(u_int32_t). 2136 */ 2137 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr 2138 + ((I2O_MESSAGE_FRAME_getVersionOffset( 2139 &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2)); 2140 SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER)); 2141 ++sg; 2142 for (ha = Asr_softc; ha; ha = ha->ha_next) { 2143 SG(sg, 0, 2144 ((ha->ha_next) 2145 ? (I2O_SGL_FLAGS_DIR) 2146 : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)), 2147 &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable)); 2148 ++sg; 2149 } 2150 SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); 2151 SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT 2152 | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0); 2153 retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 2154 kfree (Message_Ptr, M_TEMP); 2155 kfree (SystemTable, M_TEMP); 2156 return (retVal); 2157 } /* ASR_setSysTab */ 2158 2159 STATIC INLINE int 2160 ASR_acquireHrt ( 2161 INOUT Asr_softc_t * sc) 2162 { 2163 defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message); 2164 I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr; 2165 struct { 2166 I2O_HRT Header; 2167 I2O_HRT_ENTRY Entry[MAX_CHANNEL]; 2168 } Hrt; 2169 u_int8_t NumberOfEntries; 2170 PI2O_HRT_ENTRY Entry; 2171 2172 bzero ((void *)&Hrt, sizeof (Hrt)); 2173 Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message, 2174 sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT) 2175 + sizeof(I2O_SGE_SIMPLE_ELEMENT)); 2176 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame), 2177 (I2O_VERSION_11 2178 + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)) 2179 / sizeof(U32)) << 4))); 2180 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame), 2181 I2O_EXEC_HRT_GET); 2182 2183 /* 2184 * Set up the buffers as scatter gather elements. 2185 */ 2186 SG(&(Message_Ptr->SGL), 0, 2187 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, 2188 &Hrt, sizeof(Hrt)); 2189 if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) { 2190 return (ENODEV); 2191 } 2192 if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header)) 2193 > (MAX_CHANNEL + 1)) { 2194 NumberOfEntries = MAX_CHANNEL + 1; 2195 } 2196 for (Entry = Hrt.Header.HRTEntry; 2197 NumberOfEntries != 0; 2198 ++Entry, --NumberOfEntries) { 2199 PI2O_LCT_ENTRY Device; 2200 2201 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) 2202 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); 2203 ++Device) { 2204 if (I2O_LCT_ENTRY_getLocalTID(Device) 2205 == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) { 2206 Device->le_bus = I2O_HRT_ENTRY_getAdapterID( 2207 Entry) >> 16; 2208 if ((Device->le_bus > sc->ha_MaxBus) 2209 && (Device->le_bus <= MAX_CHANNEL)) { 2210 sc->ha_MaxBus = Device->le_bus; 2211 } 2212 } 2213 } 2214 } 2215 return (0); 2216 } /* ASR_acquireHrt */ 2217 2218 /* 2219 * Enable the adapter. 2220 */ 2221 STATIC INLINE int 2222 ASR_enableSys ( 2223 IN Asr_softc_t * sc) 2224 { 2225 defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message); 2226 PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr; 2227 2228 Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message, 2229 sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE)); 2230 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame), 2231 I2O_EXEC_SYS_ENABLE); 2232 return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0); 2233 } /* ASR_enableSys */ 2234 2235 /* 2236 * Perform the stages necessary to initialize the adapter 2237 */ 2238 STATIC int 2239 ASR_init( 2240 IN Asr_softc_t * sc) 2241 { 2242 return ((ASR_initOutBound(sc) == 0) 2243 || (ASR_setSysTab(sc) != CAM_REQ_CMP) 2244 || (ASR_enableSys(sc) != CAM_REQ_CMP)); 2245 } /* ASR_init */ 2246 2247 /* 2248 * Send a Synchronize Cache command to the target device. 2249 */ 2250 STATIC INLINE void 2251 ASR_sync ( 2252 IN Asr_softc_t * sc, 2253 IN int bus, 2254 IN int target, 2255 IN int lun) 2256 { 2257 tid_t TID; 2258 2259 /* 2260 * We will not synchronize the device when there are outstanding 2261 * commands issued by the OS (this is due to a locked up device, 2262 * as the OS normally would flush all outstanding commands before 2263 * issuing a shutdown or an adapter reset). 2264 */ 2265 if ((sc != (Asr_softc_t *)NULL) 2266 && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL) 2267 && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1) 2268 && (TID != (tid_t)0)) { 2269 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); 2270 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; 2271 2272 bzero (Message_Ptr 2273 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), 2274 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2275 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); 2276 2277 I2O_MESSAGE_FRAME_setVersionOffset( 2278 (PI2O_MESSAGE_FRAME)Message_Ptr, 2279 I2O_VERSION_11 2280 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2281 - sizeof(I2O_SG_ELEMENT)) 2282 / sizeof(U32)) << 4)); 2283 I2O_MESSAGE_FRAME_setMessageSize( 2284 (PI2O_MESSAGE_FRAME)Message_Ptr, 2285 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2286 - sizeof(I2O_SG_ELEMENT)) 2287 / sizeof(U32)); 2288 I2O_MESSAGE_FRAME_setInitiatorAddress ( 2289 (PI2O_MESSAGE_FRAME)Message_Ptr, 1); 2290 I2O_MESSAGE_FRAME_setFunction( 2291 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); 2292 I2O_MESSAGE_FRAME_setTargetAddress( 2293 (PI2O_MESSAGE_FRAME)Message_Ptr, TID); 2294 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( 2295 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, 2296 I2O_SCSI_SCB_EXEC); 2297 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID); 2298 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, 2299 I2O_SCB_FLAG_ENABLE_DISCONNECT 2300 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 2301 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); 2302 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( 2303 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, 2304 DPT_ORGANIZATION_ID); 2305 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); 2306 Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE; 2307 Message_Ptr->CDB[1] = (lun << 5); 2308 2309 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, 2310 (I2O_SCB_FLAG_XFER_FROM_DEVICE 2311 | I2O_SCB_FLAG_ENABLE_DISCONNECT 2312 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 2313 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); 2314 2315 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 2316 2317 } 2318 } 2319 2320 STATIC INLINE void 2321 ASR_synchronize ( 2322 IN Asr_softc_t * sc) 2323 { 2324 int bus, target, lun; 2325 2326 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { 2327 for (target = 0; target <= sc->ha_MaxId; ++target) { 2328 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) { 2329 ASR_sync(sc,bus,target,lun); 2330 } 2331 } 2332 } 2333 } 2334 2335 /* 2336 * Reset the HBA, targets and BUS. 2337 * Currently this resets *all* the SCSI busses. 2338 */ 2339 STATIC INLINE void 2340 asr_hbareset( 2341 IN Asr_softc_t * sc) 2342 { 2343 ASR_synchronize (sc); 2344 (void)ASR_reset (sc); 2345 } /* asr_hbareset */ 2346 2347 /* 2348 * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP 2349 * limit and a reduction in error checking (in the pre 4.0 case). 2350 */ 2351 STATIC int 2352 asr_pci_map_mem ( 2353 IN device_t tag, 2354 IN Asr_softc_t * sc) 2355 { 2356 int rid; 2357 u_int32_t p, l, s; 2358 2359 /* 2360 * I2O specification says we must find first *memory* mapped BAR 2361 */ 2362 for (rid = PCIR_MAPS; 2363 rid < (PCIR_MAPS + 4 * sizeof(u_int32_t)); 2364 rid += sizeof(u_int32_t)) { 2365 p = pci_read_config(tag, rid, sizeof(p)); 2366 if ((p & 1) == 0) { 2367 break; 2368 } 2369 } 2370 /* 2371 * Give up? 2372 */ 2373 if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { 2374 rid = PCIR_MAPS; 2375 } 2376 p = pci_read_config(tag, rid, sizeof(p)); 2377 pci_write_config(tag, rid, -1, sizeof(p)); 2378 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); 2379 pci_write_config(tag, rid, p, sizeof(p)); 2380 if (l > MAX_MAP) { 2381 l = MAX_MAP; 2382 } 2383 /* 2384 * The 2005S Zero Channel RAID solution is not a perfect PCI 2385 * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once 2386 * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to 2387 * BAR0+2MB and sets it's size to 2MB. The IOP registers are 2388 * accessible via BAR0, the messaging registers are accessible 2389 * via BAR1. If the subdevice code is 50 to 59 decimal. 2390 */ 2391 s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s)); 2392 if (s != 0xA5111044) { 2393 s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s)); 2394 if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0) 2395 && (ADPTDOMINATOR_SUB_ID_START <= s) 2396 && (s <= ADPTDOMINATOR_SUB_ID_END)) { 2397 l = MAX_MAP; /* Conjoined BAR Raptor Daptor */ 2398 } 2399 } 2400 p &= ~15; 2401 sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, 2402 p, p + l, l, RF_ACTIVE); 2403 if (sc->ha_mem_res == (struct resource *)NULL) { 2404 return (0); 2405 } 2406 sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res); 2407 if (sc->ha_Base == NULL) { 2408 return (0); 2409 } 2410 sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res); 2411 if (s == 0xA5111044) { /* Split BAR Raptor Daptor */ 2412 if ((rid += sizeof(u_int32_t)) 2413 >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) { 2414 return (0); 2415 } 2416 p = pci_read_config(tag, rid, sizeof(p)); 2417 pci_write_config(tag, rid, -1, sizeof(p)); 2418 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15); 2419 pci_write_config(tag, rid, p, sizeof(p)); 2420 if (l > MAX_MAP) { 2421 l = MAX_MAP; 2422 } 2423 p &= ~15; 2424 sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid, 2425 p, p + l, l, RF_ACTIVE); 2426 if (sc->ha_mes_res == (struct resource *)NULL) { 2427 return (0); 2428 } 2429 if ((void *)rman_get_start(sc->ha_mes_res) == NULL) { 2430 return (0); 2431 } 2432 sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res); 2433 } else { 2434 sc->ha_Fvirt = (U8 *)(sc->ha_Virt); 2435 } 2436 return (1); 2437 } /* asr_pci_map_mem */ 2438 2439 /* 2440 * A simplified copy of the real pci_map_int with additional 2441 * registration requirements. 2442 */ 2443 STATIC int 2444 asr_pci_map_int ( 2445 IN device_t tag, 2446 IN Asr_softc_t * sc) 2447 { 2448 int rid = 0; 2449 int error; 2450 2451 sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid, 2452 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 2453 if (sc->ha_irq_res == (struct resource *)NULL) { 2454 return (0); 2455 } 2456 error = bus_setup_intr(tag, sc->ha_irq_res, 0, 2457 (driver_intr_t *)asr_intr, (void *)sc, 2458 &(sc->ha_intr), NULL); 2459 if (error) { 2460 return (0); 2461 } 2462 sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char)); 2463 return (1); 2464 } /* asr_pci_map_int */ 2465 2466 /* 2467 * Attach the devices, and virtual devices to the driver list. 2468 */ 2469 STATIC ATTACH_RET 2470 asr_attach (ATTACH_ARGS) 2471 { 2472 Asr_softc_t * sc; 2473 struct scsi_inquiry_data * iq; 2474 ATTACH_SET(); 2475 2476 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_INTWAIT | M_ZERO); 2477 if (Asr_softc == (Asr_softc_t *)NULL) { 2478 /* 2479 * Fixup the OS revision as saved in the dptsig for the 2480 * engine (dptioctl.h) to pick up. 2481 */ 2482 bcopy (osrelease, &ASR_sig.dsDescription[16], 5); 2483 kprintf ("asr%d: major=%d\n", unit, asr_ops.head.maj); 2484 } 2485 /* 2486 * Initialize the software structure 2487 */ 2488 LIST_INIT(&(sc->ha_ccb)); 2489 /* Link us into the HA list */ 2490 { 2491 Asr_softc_t **ha; 2492 2493 for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next)); 2494 *(ha) = sc; 2495 } 2496 { 2497 PI2O_EXEC_STATUS_GET_REPLY status; 2498 int size; 2499 2500 /* 2501 * This is the real McCoy! 2502 */ 2503 if (!asr_pci_map_mem(tag, sc)) { 2504 kprintf ("asr%d: could not map memory\n", unit); 2505 ATTACH_RETURN(ENXIO); 2506 } 2507 /* Enable if not formerly enabled */ 2508 pci_write_config (tag, PCIR_COMMAND, 2509 pci_read_config (tag, PCIR_COMMAND, sizeof(char)) 2510 | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char)); 2511 /* Knowledge is power, responsibility is direct */ 2512 { 2513 struct pci_devinfo { 2514 STAILQ_ENTRY(pci_devinfo) pci_links; 2515 struct resource_list resources; 2516 pcicfgregs cfg; 2517 } * dinfo = device_get_ivars(tag); 2518 sc->ha_pciBusNum = dinfo->cfg.bus; 2519 sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3) 2520 | dinfo->cfg.func; 2521 } 2522 /* Check if the device is there? */ 2523 if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0) 2524 || ((status = (PI2O_EXEC_STATUS_GET_REPLY)kmalloc ( 2525 sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK)) 2526 == (PI2O_EXEC_STATUS_GET_REPLY)NULL) 2527 || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) { 2528 kprintf ("asr%d: could not initialize hardware\n", unit); 2529 ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */ 2530 } 2531 sc->ha_SystemTable.OrganizationID = status->OrganizationID; 2532 sc->ha_SystemTable.IOP_ID = status->IOP_ID; 2533 sc->ha_SystemTable.I2oVersion = status->I2oVersion; 2534 sc->ha_SystemTable.IopState = status->IopState; 2535 sc->ha_SystemTable.MessengerType = status->MessengerType; 2536 sc->ha_SystemTable.InboundMessageFrameSize 2537 = status->InboundMFrameSize; 2538 sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow 2539 = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO)); 2540 2541 if (!asr_pci_map_int(tag, (void *)sc)) { 2542 kprintf ("asr%d: could not map interrupt\n", unit); 2543 ATTACH_RETURN(ENXIO); 2544 } 2545 2546 /* Adjust the maximim inbound count */ 2547 if (((sc->ha_QueueSize 2548 = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status)) 2549 > MAX_INBOUND) 2550 || (sc->ha_QueueSize == 0)) { 2551 sc->ha_QueueSize = MAX_INBOUND; 2552 } 2553 2554 /* Adjust the maximum outbound count */ 2555 if (((sc->ha_Msgs_Count 2556 = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status)) 2557 > MAX_OUTBOUND) 2558 || (sc->ha_Msgs_Count == 0)) { 2559 sc->ha_Msgs_Count = MAX_OUTBOUND; 2560 } 2561 if (sc->ha_Msgs_Count > sc->ha_QueueSize) { 2562 sc->ha_Msgs_Count = sc->ha_QueueSize; 2563 } 2564 2565 /* Adjust the maximum SG size to adapter */ 2566 if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize( 2567 status) << 2)) > MAX_INBOUND_SIZE) { 2568 size = MAX_INBOUND_SIZE; 2569 } 2570 kfree (status, M_TEMP); 2571 sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2572 + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT); 2573 } 2574 2575 /* 2576 * Only do a bus/HBA reset on the first time through. On this 2577 * first time through, we do not send a flush to the devices. 2578 */ 2579 if (ASR_init(sc) == 0) { 2580 struct BufferInfo { 2581 I2O_PARAM_RESULTS_LIST_HEADER Header; 2582 I2O_PARAM_READ_OPERATION_RESULT Read; 2583 I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; 2584 }; 2585 defAlignLong (struct BufferInfo, Buffer); 2586 PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info; 2587 # define FW_DEBUG_BLED_OFFSET 8 2588 2589 if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR) 2590 ASR_getParams(sc, 0, 2591 I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO, 2592 Buffer, sizeof(struct BufferInfo))) 2593 != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) { 2594 sc->ha_blinkLED = sc->ha_Fvirt 2595 + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info) 2596 + FW_DEBUG_BLED_OFFSET; 2597 } 2598 if (ASR_acquireLct(sc) == 0) { 2599 (void)ASR_acquireHrt(sc); 2600 } 2601 } else { 2602 kprintf ("asr%d: failed to initialize\n", unit); 2603 ATTACH_RETURN(ENXIO); 2604 } 2605 /* 2606 * Add in additional probe responses for more channels. We 2607 * are reusing the variable `target' for a channel loop counter. 2608 * Done here because of we need both the acquireLct and 2609 * acquireHrt data. 2610 */ 2611 { PI2O_LCT_ENTRY Device; 2612 2613 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY) 2614 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT)); 2615 ++Device) { 2616 if (Device->le_type == I2O_UNKNOWN) { 2617 continue; 2618 } 2619 if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) { 2620 if (Device->le_target > sc->ha_MaxId) { 2621 sc->ha_MaxId = Device->le_target; 2622 } 2623 if (Device->le_lun > sc->ha_MaxLun) { 2624 sc->ha_MaxLun = Device->le_lun; 2625 } 2626 } 2627 if (((Device->le_type & I2O_PORT) != 0) 2628 && (Device->le_bus <= MAX_CHANNEL)) { 2629 /* Do not increase MaxId for efficiency */ 2630 sc->ha_adapter_target[Device->le_bus] 2631 = Device->le_target; 2632 } 2633 } 2634 } 2635 2636 2637 /* 2638 * Print the HBA model number as inquired from the card. 2639 */ 2640 2641 kprintf ("asr%d:", unit); 2642 2643 iq = (struct scsi_inquiry_data *)kmalloc ( 2644 sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK | M_ZERO); 2645 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message); 2646 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr; 2647 int posted = 0; 2648 2649 bzero (Message_Ptr 2650 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message), 2651 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2652 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)); 2653 2654 I2O_MESSAGE_FRAME_setVersionOffset( 2655 (PI2O_MESSAGE_FRAME)Message_Ptr, 2656 I2O_VERSION_11 2657 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2658 - sizeof(I2O_SG_ELEMENT)) 2659 / sizeof(U32)) << 4)); 2660 I2O_MESSAGE_FRAME_setMessageSize( 2661 (PI2O_MESSAGE_FRAME)Message_Ptr, 2662 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) 2663 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT)) 2664 / sizeof(U32)); 2665 I2O_MESSAGE_FRAME_setInitiatorAddress ( 2666 (PI2O_MESSAGE_FRAME)Message_Ptr, 1); 2667 I2O_MESSAGE_FRAME_setFunction( 2668 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE); 2669 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode ( 2670 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, 2671 I2O_SCSI_SCB_EXEC); 2672 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, 2673 I2O_SCB_FLAG_ENABLE_DISCONNECT 2674 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 2675 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER); 2676 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1); 2677 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID( 2678 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, 2679 DPT_ORGANIZATION_ID); 2680 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6); 2681 Message_Ptr->CDB[0] = INQUIRY; 2682 Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data); 2683 if (Message_Ptr->CDB[4] == 0) { 2684 Message_Ptr->CDB[4] = 255; 2685 } 2686 2687 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr, 2688 (I2O_SCB_FLAG_XFER_FROM_DEVICE 2689 | I2O_SCB_FLAG_ENABLE_DISCONNECT 2690 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 2691 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)); 2692 2693 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount( 2694 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, 2695 sizeof(struct scsi_inquiry_data)); 2696 SG(&(Message_Ptr->SGL), 0, 2697 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, 2698 iq, sizeof(struct scsi_inquiry_data)); 2699 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 2700 2701 if (iq->vendor[0] && (iq->vendor[0] != ' ')) { 2702 kprintf (" "); 2703 ASR_prstring (iq->vendor, 8); 2704 ++posted; 2705 } 2706 if (iq->product[0] && (iq->product[0] != ' ')) { 2707 kprintf (" "); 2708 ASR_prstring (iq->product, 16); 2709 ++posted; 2710 } 2711 if (iq->revision[0] && (iq->revision[0] != ' ')) { 2712 kprintf (" FW Rev. "); 2713 ASR_prstring (iq->revision, 4); 2714 ++posted; 2715 } 2716 kfree ((caddr_t)iq, M_TEMP); 2717 if (posted) { 2718 kprintf (","); 2719 } 2720 kprintf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1, 2721 (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize); 2722 2723 /* 2724 * fill in the prototype cam_path. 2725 */ 2726 { 2727 int bus; 2728 union asr_ccb * ccb; 2729 2730 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { 2731 kprintf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit); 2732 ATTACH_RETURN(ENOMEM); 2733 } 2734 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) { 2735 int QueueSize = sc->ha_QueueSize; 2736 2737 if (QueueSize > MAX_INBOUND) { 2738 QueueSize = MAX_INBOUND; 2739 } 2740 2741 /* 2742 * Construct our first channel SIM entry 2743 */ 2744 sc->ha_sim[bus] = cam_sim_alloc( 2745 asr_action, asr_poll, "asr", sc, 2746 unit, &sim_mplock, 1, QueueSize, NULL); 2747 if (sc->ha_sim[bus] == NULL) 2748 continue; 2749 2750 if (xpt_bus_register(sc->ha_sim[bus], bus) 2751 != CAM_SUCCESS) { 2752 cam_sim_free(sc->ha_sim[bus]); 2753 sc->ha_sim[bus] = NULL; 2754 continue; 2755 } 2756 2757 if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL, 2758 cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD, 2759 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2760 xpt_bus_deregister( 2761 cam_sim_path(sc->ha_sim[bus])); 2762 cam_sim_free(sc->ha_sim[bus]); 2763 sc->ha_sim[bus] = NULL; 2764 continue; 2765 } 2766 } 2767 asr_free_ccb (ccb); 2768 } 2769 /* 2770 * Generate the device node information 2771 */ 2772 make_dev(&asr_ops, unit, 0, 0, S_IRWXU, "rasr%d", unit); 2773 ATTACH_RETURN(0); 2774 } /* asr_attach */ 2775 2776 STATIC void 2777 asr_poll( 2778 IN struct cam_sim *sim) 2779 { 2780 asr_intr(cam_sim_softc(sim)); 2781 } /* asr_poll */ 2782 2783 STATIC void 2784 asr_action( 2785 IN struct cam_sim * sim, 2786 IN union ccb * ccb) 2787 { 2788 struct Asr_softc * sc; 2789 2790 debug_asr_printf ("asr_action(%lx,%lx{%x})\n", 2791 (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code); 2792 2793 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n")); 2794 2795 ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim); 2796 2797 switch (ccb->ccb_h.func_code) { 2798 2799 /* Common cases first */ 2800 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 2801 { 2802 struct Message { 2803 char M[MAX_INBOUND_SIZE]; 2804 }; 2805 defAlignLong(struct Message,Message); 2806 PI2O_MESSAGE_FRAME Message_Ptr; 2807 2808 /* Reject incoming commands while we are resetting the card */ 2809 if (sc->ha_in_reset != HA_OPERATIONAL) { 2810 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 2811 if (sc->ha_in_reset >= HA_OFF_LINE) { 2812 /* HBA is now off-line */ 2813 ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR; 2814 } else { 2815 /* HBA currently resetting, try again later. */ 2816 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 2817 } 2818 debug_asr_cmd_printf (" e\n"); 2819 xpt_done(ccb); 2820 debug_asr_cmd_printf (" q\n"); 2821 break; 2822 } 2823 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2824 kprintf( 2825 "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n", 2826 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), 2827 ccb->csio.cdb_io.cdb_bytes[0], 2828 cam_sim_bus(sim), 2829 ccb->ccb_h.target_id, 2830 ccb->ccb_h.target_lun); 2831 } 2832 debug_asr_cmd_printf ("(%d,%d,%d,%d)", 2833 cam_sim_unit(sim), 2834 cam_sim_bus(sim), 2835 ccb->ccb_h.target_id, 2836 ccb->ccb_h.target_lun); 2837 debug_asr_cmd_dump_ccb(ccb); 2838 2839 if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb, 2840 (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) { 2841 debug_asr_cmd2_printf ("TID=%x:\n", 2842 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID( 2843 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)); 2844 debug_asr_cmd2_dump_message(Message_Ptr); 2845 debug_asr_cmd1_printf (" q"); 2846 2847 if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) { 2848 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 2849 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 2850 debug_asr_cmd_printf (" E\n"); 2851 xpt_done(ccb); 2852 } 2853 debug_asr_cmd_printf (" Q\n"); 2854 break; 2855 } 2856 /* 2857 * We will get here if there is no valid TID for the device 2858 * referenced in the scsi command packet. 2859 */ 2860 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 2861 ccb->ccb_h.status |= CAM_SEL_TIMEOUT; 2862 debug_asr_cmd_printf (" B\n"); 2863 xpt_done(ccb); 2864 break; 2865 } 2866 2867 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2868 /* Rese HBA device ... */ 2869 asr_hbareset (sc); 2870 ccb->ccb_h.status = CAM_REQ_CMP; 2871 xpt_done(ccb); 2872 break; 2873 2874 # if (defined(REPORT_LUNS)) 2875 case REPORT_LUNS: 2876 # endif 2877 case XPT_ABORT: /* Abort the specified CCB */ 2878 /* XXX Implement */ 2879 ccb->ccb_h.status = CAM_REQ_INVALID; 2880 xpt_done(ccb); 2881 break; 2882 2883 case XPT_SET_TRAN_SETTINGS: 2884 /* XXX Implement */ 2885 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2886 xpt_done(ccb); 2887 break; 2888 2889 case XPT_GET_TRAN_SETTINGS: 2890 /* Get default/user set transfer settings for the target */ 2891 { 2892 struct ccb_trans_settings *cts = &(ccb->cts); 2893 struct ccb_trans_settings_scsi *scsi = 2894 &cts->proto_specific.scsi; 2895 struct ccb_trans_settings_spi *spi = 2896 &cts->xport_specific.spi; 2897 2898 if (cts->type == CTS_TYPE_USER_SETTINGS) { 2899 cts->protocol = PROTO_SCSI; 2900 cts->protocol_version = SCSI_REV_2; 2901 cts->transport = XPORT_SPI; 2902 cts->transport_version = 2; 2903 2904 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2905 spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2906 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 2907 spi->sync_period = 6; /* 40MHz */ 2908 spi->sync_offset = 15; 2909 spi->valid = CTS_SPI_VALID_SYNC_RATE 2910 | CTS_SPI_VALID_SYNC_OFFSET 2911 | CTS_SPI_VALID_BUS_WIDTH 2912 | CTS_SPI_VALID_DISC; 2913 scsi->valid = CTS_SCSI_VALID_TQ; 2914 2915 ccb->ccb_h.status = CAM_REQ_CMP; 2916 } else { 2917 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2918 } 2919 xpt_done(ccb); 2920 break; 2921 } 2922 2923 case XPT_CALC_GEOMETRY: 2924 { 2925 struct ccb_calc_geometry *ccg; 2926 u_int32_t size_mb; 2927 u_int32_t secs_per_cylinder; 2928 2929 ccg = &(ccb->ccg); 2930 size_mb = ccg->volume_size 2931 / ((1024L * 1024L) / ccg->block_size); 2932 2933 if (size_mb > 4096) { 2934 ccg->heads = 255; 2935 ccg->secs_per_track = 63; 2936 } else if (size_mb > 2048) { 2937 ccg->heads = 128; 2938 ccg->secs_per_track = 63; 2939 } else if (size_mb > 1024) { 2940 ccg->heads = 65; 2941 ccg->secs_per_track = 63; 2942 } else { 2943 ccg->heads = 64; 2944 ccg->secs_per_track = 32; 2945 } 2946 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2947 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2948 ccb->ccb_h.status = CAM_REQ_CMP; 2949 xpt_done(ccb); 2950 break; 2951 } 2952 2953 case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2954 ASR_resetBus (sc, cam_sim_bus(sim)); 2955 ccb->ccb_h.status = CAM_REQ_CMP; 2956 xpt_done(ccb); 2957 break; 2958 2959 case XPT_TERM_IO: /* Terminate the I/O process */ 2960 /* XXX Implement */ 2961 ccb->ccb_h.status = CAM_REQ_INVALID; 2962 xpt_done(ccb); 2963 break; 2964 2965 case XPT_PATH_INQ: /* Path routing inquiry */ 2966 { 2967 struct ccb_pathinq *cpi = &(ccb->cpi); 2968 2969 cpi->version_num = 1; /* XXX??? */ 2970 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 2971 cpi->target_sprt = 0; 2972 /* Not necessary to reset bus, done by HDM initialization */ 2973 cpi->hba_misc = PIM_NOBUSRESET; 2974 cpi->hba_eng_cnt = 0; 2975 cpi->max_target = sc->ha_MaxId; 2976 cpi->max_lun = sc->ha_MaxLun; 2977 cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)]; 2978 cpi->bus_id = cam_sim_bus(sim); 2979 cpi->base_transfer_speed = 3300; 2980 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2981 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 2982 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2983 cpi->unit_number = cam_sim_unit(sim); 2984 cpi->ccb_h.status = CAM_REQ_CMP; 2985 cpi->transport = XPORT_SPI; 2986 cpi->transport_version = 2; 2987 cpi->protocol = PROTO_SCSI; 2988 cpi->protocol_version = SCSI_REV_2; 2989 xpt_done(ccb); 2990 break; 2991 } 2992 default: 2993 ccb->ccb_h.status = CAM_REQ_INVALID; 2994 xpt_done(ccb); 2995 break; 2996 } 2997 } /* asr_action */ 2998 2999 3000 /* 3001 * Handle processing of current CCB as pointed to by the Status. 3002 */ 3003 STATIC int 3004 asr_intr ( 3005 IN Asr_softc_t * sc) 3006 { 3007 OUT int processed; 3008 3009 for (processed = 0; 3010 sc->ha_Virt->Status & Mask_InterruptsDisabled; 3011 processed = 1) { 3012 union asr_ccb * ccb; 3013 U32 ReplyOffset; 3014 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; 3015 3016 if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE) 3017 && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) { 3018 break; 3019 } 3020 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset 3021 - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs)); 3022 /* 3023 * We do not need any (optional byteswapping) method access to 3024 * the Initiator context field. 3025 */ 3026 ccb = (union asr_ccb *)(long) 3027 I2O_MESSAGE_FRAME_getInitiatorContext64( 3028 &(Reply->StdReplyFrame.StdMessageFrame)); 3029 if (I2O_MESSAGE_FRAME_getMsgFlags( 3030 &(Reply->StdReplyFrame.StdMessageFrame)) 3031 & I2O_MESSAGE_FLAGS_FAIL) { 3032 defAlignLong(I2O_UTIL_NOP_MESSAGE,Message); 3033 PI2O_UTIL_NOP_MESSAGE Message_Ptr; 3034 U32 MessageOffset; 3035 3036 MessageOffset = (u_long) 3037 I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA( 3038 (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply); 3039 /* 3040 * Get the Original Message Frame's address, and get 3041 * it's Transaction Context into our space. (Currently 3042 * unused at original authorship, but better to be 3043 * safe than sorry). Straight copy means that we 3044 * need not concern ourselves with the (optional 3045 * byteswapping) method access. 3046 */ 3047 Reply->StdReplyFrame.TransactionContext 3048 = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME) 3049 (sc->ha_Fvirt + MessageOffset))->TransactionContext; 3050 /* 3051 * For 64 bit machines, we need to reconstruct the 3052 * 64 bit context. 3053 */ 3054 ccb = (union asr_ccb *)(long) 3055 I2O_MESSAGE_FRAME_getInitiatorContext64( 3056 &(Reply->StdReplyFrame.StdMessageFrame)); 3057 /* 3058 * Unique error code for command failure. 3059 */ 3060 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( 3061 &(Reply->StdReplyFrame), (u_int16_t)-2); 3062 /* 3063 * Modify the message frame to contain a NOP and 3064 * re-issue it to the controller. 3065 */ 3066 Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage( 3067 Message, sizeof(I2O_UTIL_NOP_MESSAGE)); 3068 # if (I2O_UTIL_NOP != 0) 3069 I2O_MESSAGE_FRAME_setFunction ( 3070 &(Message_Ptr->StdMessageFrame), 3071 I2O_UTIL_NOP); 3072 # endif 3073 /* 3074 * Copy the packet out to the Original Message 3075 */ 3076 bcopy ((caddr_t)Message_Ptr, 3077 sc->ha_Fvirt + MessageOffset, 3078 sizeof(I2O_UTIL_NOP_MESSAGE)); 3079 /* 3080 * Issue the NOP 3081 */ 3082 sc->ha_Virt->ToFIFO = MessageOffset; 3083 } 3084 3085 /* 3086 * Asynchronous command with no return requirements, 3087 * and a generic handler for immunity against odd error 3088 * returns from the adapter. 3089 */ 3090 if (ccb == (union asr_ccb *)NULL) { 3091 /* 3092 * Return Reply so that it can be used for the 3093 * next command 3094 */ 3095 sc->ha_Virt->FromFIFO = ReplyOffset; 3096 continue; 3097 } 3098 3099 /* Welease Wadjah! (and stop timeouts) */ 3100 ASR_ccbRemove (sc, ccb); 3101 3102 switch ( 3103 I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode( 3104 &(Reply->StdReplyFrame))) { 3105 3106 case I2O_SCSI_DSC_SUCCESS: 3107 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3108 ccb->ccb_h.status |= CAM_REQ_CMP; 3109 break; 3110 3111 case I2O_SCSI_DSC_CHECK_CONDITION: 3112 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3113 ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID; 3114 break; 3115 3116 case I2O_SCSI_DSC_BUSY: 3117 /* FALLTHRU */ 3118 case I2O_SCSI_HBA_DSC_ADAPTER_BUSY: 3119 /* FALLTHRU */ 3120 case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET: 3121 /* FALLTHRU */ 3122 case I2O_SCSI_HBA_DSC_BUS_BUSY: 3123 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3124 ccb->ccb_h.status |= CAM_SCSI_BUSY; 3125 break; 3126 3127 case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT: 3128 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3129 ccb->ccb_h.status |= CAM_SEL_TIMEOUT; 3130 break; 3131 3132 case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT: 3133 /* FALLTHRU */ 3134 case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT: 3135 /* FALLTHRU */ 3136 case I2O_SCSI_HBA_DSC_LUN_INVALID: 3137 /* FALLTHRU */ 3138 case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID: 3139 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3140 ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 3141 break; 3142 3143 case I2O_SCSI_HBA_DSC_DATA_OVERRUN: 3144 /* FALLTHRU */ 3145 case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR: 3146 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3147 ccb->ccb_h.status |= CAM_DATA_RUN_ERR; 3148 break; 3149 3150 default: 3151 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 3152 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 3153 break; 3154 } 3155 if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) { 3156 ccb->csio.resid -= 3157 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount( 3158 Reply); 3159 } 3160 3161 /* Sense data in reply packet */ 3162 if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) { 3163 u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply); 3164 3165 if (size) { 3166 if (size > sizeof(ccb->csio.sense_data)) { 3167 size = sizeof(ccb->csio.sense_data); 3168 } 3169 if (size > I2O_SCSI_SENSE_DATA_SZ) { 3170 size = I2O_SCSI_SENSE_DATA_SZ; 3171 } 3172 if ((ccb->csio.sense_len) 3173 && (size > ccb->csio.sense_len)) { 3174 size = ccb->csio.sense_len; 3175 } 3176 bcopy ((caddr_t)Reply->SenseData, 3177 (caddr_t)&(ccb->csio.sense_data), size); 3178 } 3179 } 3180 3181 /* 3182 * Return Reply so that it can be used for the next command 3183 * since we have no more need for it now 3184 */ 3185 sc->ha_Virt->FromFIFO = ReplyOffset; 3186 3187 if (ccb->ccb_h.path) { 3188 xpt_done ((union ccb *)ccb); 3189 } else { 3190 wakeup ((caddr_t)ccb); 3191 } 3192 } 3193 return (processed); 3194 } /* asr_intr */ 3195 3196 #undef QueueSize /* Grrrr */ 3197 #undef SG_Size /* Grrrr */ 3198 3199 /* 3200 * Meant to be included at the bottom of asr.c !!! 3201 */ 3202 3203 /* 3204 * Included here as hard coded. Done because other necessary include 3205 * files utilize C++ comment structures which make them a nuisance to 3206 * included here just to pick up these three typedefs. 3207 */ 3208 typedef U32 DPT_TAG_T; 3209 typedef U32 DPT_MSG_T; 3210 typedef U32 DPT_RTN_T; 3211 3212 #undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */ 3213 #include "osd_unix.h" 3214 3215 #define asr_unit(dev) minor(dev) 3216 3217 STATIC INLINE Asr_softc_t * 3218 ASR_get_sc ( 3219 IN cdev_t dev) 3220 { 3221 int unit = asr_unit(dev); 3222 OUT Asr_softc_t * sc = Asr_softc; 3223 3224 while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) { 3225 sc = sc->ha_next; 3226 } 3227 return (sc); 3228 } /* ASR_get_sc */ 3229 3230 STATIC u_int8_t ASR_ctlr_held; 3231 #if (!defined(UNREFERENCED_PARAMETER)) 3232 # define UNREFERENCED_PARAMETER(x) (void)(x) 3233 #endif 3234 3235 STATIC int 3236 asr_open(struct dev_open_args *ap) 3237 { 3238 cdev_t dev = ap->a_head.a_dev; 3239 OUT int error; 3240 3241 if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) { 3242 return (ENODEV); 3243 } 3244 crit_enter(); 3245 if (ASR_ctlr_held) { 3246 error = EBUSY; 3247 } else if ((error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) == 0) { 3248 ++ASR_ctlr_held; 3249 } 3250 crit_exit(); 3251 return (error); 3252 } /* asr_open */ 3253 3254 STATIC int 3255 asr_close(struct dev_close_args *ap) 3256 { 3257 ASR_ctlr_held = 0; 3258 return (0); 3259 } /* asr_close */ 3260 3261 3262 /*-------------------------------------------------------------------------*/ 3263 /* Function ASR_queue_i */ 3264 /*-------------------------------------------------------------------------*/ 3265 /* The Parameters Passed To This Function Are : */ 3266 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */ 3267 /* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */ 3268 /* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */ 3269 /* */ 3270 /* This Function Will Take The User Request Packet And Convert It To An */ 3271 /* I2O MSG And Send It Off To The Adapter. */ 3272 /* */ 3273 /* Return : 0 For OK, Error Code Otherwise */ 3274 /*-------------------------------------------------------------------------*/ 3275 STATIC INLINE int 3276 ASR_queue_i( 3277 IN Asr_softc_t * sc, 3278 INOUT PI2O_MESSAGE_FRAME Packet) 3279 { 3280 union asr_ccb * ccb; 3281 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply; 3282 PI2O_MESSAGE_FRAME Message_Ptr; 3283 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr; 3284 int MessageSizeInBytes; 3285 int ReplySizeInBytes; 3286 int error; 3287 int s; 3288 /* Scatter Gather buffer list */ 3289 struct ioctlSgList_S { 3290 SLIST_ENTRY(ioctlSgList_S) link; 3291 caddr_t UserSpace; 3292 I2O_FLAGS_COUNT FlagsCount; 3293 char KernelSpace[sizeof(long)]; 3294 } * elm; 3295 /* Generates a `first' entry */ 3296 SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList; 3297 3298 if (ASR_getBlinkLedCode(sc)) { 3299 debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n", 3300 ASR_getBlinkLedCode(sc)); 3301 return (EIO); 3302 } 3303 /* Copy in the message into a local allocation */ 3304 Message_Ptr = (PI2O_MESSAGE_FRAME)kmalloc ( 3305 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK); 3306 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, 3307 sizeof(I2O_MESSAGE_FRAME))) != 0) { 3308 kfree (Message_Ptr, M_TEMP); 3309 debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error); 3310 return (error); 3311 } 3312 /* Acquire information to determine type of packet */ 3313 MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2); 3314 /* The offset of the reply information within the user packet */ 3315 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet 3316 + MessageSizeInBytes); 3317 3318 /* Check if the message is a synchronous initialization command */ 3319 s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr); 3320 kfree (Message_Ptr, M_TEMP); 3321 switch (s) { 3322 3323 case I2O_EXEC_IOP_RESET: 3324 { U32 status; 3325 3326 status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt); 3327 ReplySizeInBytes = sizeof(status); 3328 debug_usr_cmd_printf ("resetIOP done\n"); 3329 return (copyout ((caddr_t)&status, (caddr_t)Reply, 3330 ReplySizeInBytes)); 3331 } 3332 3333 case I2O_EXEC_STATUS_GET: 3334 { I2O_EXEC_STATUS_GET_REPLY status; 3335 3336 if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status) 3337 == (PI2O_EXEC_STATUS_GET_REPLY)NULL) { 3338 debug_usr_cmd_printf ("getStatus failed\n"); 3339 return (ENXIO); 3340 } 3341 ReplySizeInBytes = sizeof(status); 3342 debug_usr_cmd_printf ("getStatus done\n"); 3343 return (copyout ((caddr_t)&status, (caddr_t)Reply, 3344 ReplySizeInBytes)); 3345 } 3346 3347 case I2O_EXEC_OUTBOUND_INIT: 3348 { U32 status; 3349 3350 status = ASR_initOutBound(sc); 3351 ReplySizeInBytes = sizeof(status); 3352 debug_usr_cmd_printf ("intOutBound done\n"); 3353 return (copyout ((caddr_t)&status, (caddr_t)Reply, 3354 ReplySizeInBytes)); 3355 } 3356 } 3357 3358 /* Determine if the message size is valid */ 3359 if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME)) 3360 || (MAX_INBOUND_SIZE < MessageSizeInBytes)) { 3361 debug_usr_cmd_printf ("Packet size %d incorrect\n", 3362 MessageSizeInBytes); 3363 return (EINVAL); 3364 } 3365 3366 Message_Ptr = (PI2O_MESSAGE_FRAME)kmalloc (MessageSizeInBytes, 3367 M_TEMP, M_WAITOK); 3368 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr, 3369 MessageSizeInBytes)) != 0) { 3370 kfree (Message_Ptr, M_TEMP); 3371 debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n", 3372 MessageSizeInBytes, error); 3373 return (error); 3374 } 3375 3376 /* Check the size of the reply frame, and start constructing */ 3377 3378 Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)kmalloc ( 3379 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK); 3380 if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr, 3381 sizeof(I2O_MESSAGE_FRAME))) != 0) { 3382 kfree (Reply_Ptr, M_TEMP); 3383 kfree (Message_Ptr, M_TEMP); 3384 debug_usr_cmd_printf ( 3385 "Failed to copy in reply frame, errno=%d\n", 3386 error); 3387 return (error); 3388 } 3389 ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize( 3390 &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2); 3391 kfree (Reply_Ptr, M_TEMP); 3392 if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) { 3393 kfree (Message_Ptr, M_TEMP); 3394 debug_usr_cmd_printf ( 3395 "Failed to copy in reply frame[%d], errno=%d\n", 3396 ReplySizeInBytes, error); 3397 return (EINVAL); 3398 } 3399 3400 Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)kmalloc ( 3401 ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)) 3402 ? ReplySizeInBytes 3403 : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)), 3404 M_TEMP, M_WAITOK); 3405 (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes); 3406 Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext 3407 = Message_Ptr->InitiatorContext; 3408 Reply_Ptr->StdReplyFrame.TransactionContext 3409 = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext; 3410 I2O_MESSAGE_FRAME_setMsgFlags( 3411 &(Reply_Ptr->StdReplyFrame.StdMessageFrame), 3412 I2O_MESSAGE_FRAME_getMsgFlags( 3413 &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) 3414 | I2O_MESSAGE_FLAGS_REPLY); 3415 3416 /* Check if the message is a special case command */ 3417 switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) { 3418 case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */ 3419 if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset( 3420 Message_Ptr) & 0xF0) >> 2)) { 3421 kfree (Message_Ptr, M_TEMP); 3422 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( 3423 &(Reply_Ptr->StdReplyFrame), 3424 (ASR_setSysTab(sc) != CAM_REQ_CMP)); 3425 I2O_MESSAGE_FRAME_setMessageSize( 3426 &(Reply_Ptr->StdReplyFrame.StdMessageFrame), 3427 sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)); 3428 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, 3429 ReplySizeInBytes); 3430 kfree (Reply_Ptr, M_TEMP); 3431 return (error); 3432 } 3433 } 3434 3435 /* Deal in the general case */ 3436 /* First allocate and optionally copy in each scatter gather element */ 3437 SLIST_INIT(&sgList); 3438 if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) { 3439 PI2O_SGE_SIMPLE_ELEMENT sg; 3440 3441 /* 3442 * since this code is reused in several systems, code 3443 * efficiency is greater by using a shift operation rather 3444 * than a divide by sizeof(u_int32_t). 3445 */ 3446 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr 3447 + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) 3448 >> 2)); 3449 while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr) 3450 + MessageSizeInBytes)) { 3451 caddr_t v; 3452 int len; 3453 3454 if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) 3455 & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) { 3456 error = EINVAL; 3457 break; 3458 } 3459 len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount)); 3460 debug_usr_cmd_printf ("SG[%d] = %x[%d]\n", 3461 sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr 3462 + ((I2O_MESSAGE_FRAME_getVersionOffset( 3463 Message_Ptr) & 0xF0) >> 2)), 3464 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len); 3465 3466 elm = (struct ioctlSgList_S *)kmalloc ( 3467 sizeof(*elm) - sizeof(elm->KernelSpace) + len, 3468 M_TEMP, M_WAITOK); 3469 SLIST_INSERT_HEAD(&sgList, elm, link); 3470 elm->FlagsCount = sg->FlagsCount; 3471 elm->UserSpace = (caddr_t) 3472 (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg)); 3473 v = elm->KernelSpace; 3474 /* Copy in outgoing data (DIR bit could be invalid) */ 3475 if ((error = copyin (elm->UserSpace, (caddr_t)v, len)) 3476 != 0) { 3477 break; 3478 } 3479 /* 3480 * If the buffer is not contiguous, lets 3481 * break up the scatter/gather entries. 3482 */ 3483 while ((len > 0) 3484 && (sg < (PI2O_SGE_SIMPLE_ELEMENT) 3485 (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) { 3486 int next, base, span; 3487 3488 span = 0; 3489 next = base = KVTOPHYS(v); 3490 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, 3491 base); 3492 3493 /* How far can we go physically contiguously */ 3494 while ((len > 0) && (base == next)) { 3495 int size; 3496 3497 next = trunc_page(base) + PAGE_SIZE; 3498 size = next - base; 3499 if (size > len) { 3500 size = len; 3501 } 3502 span += size; 3503 v += size; 3504 len -= size; 3505 base = KVTOPHYS(v); 3506 } 3507 3508 /* Construct the Flags */ 3509 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), 3510 span); 3511 { 3512 int flags = I2O_FLAGS_COUNT_getFlags( 3513 &(elm->FlagsCount)); 3514 /* Any remaining length? */ 3515 if (len > 0) { 3516 flags &= 3517 ~(I2O_SGL_FLAGS_END_OF_BUFFER 3518 | I2O_SGL_FLAGS_LAST_ELEMENT); 3519 } 3520 I2O_FLAGS_COUNT_setFlags( 3521 &(sg->FlagsCount), flags); 3522 } 3523 3524 debug_usr_cmd_printf ("sg[%d] = %x[%d]\n", 3525 sg - (PI2O_SGE_SIMPLE_ELEMENT) 3526 ((char *)Message_Ptr 3527 + ((I2O_MESSAGE_FRAME_getVersionOffset( 3528 Message_Ptr) & 0xF0) >> 2)), 3529 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), 3530 span); 3531 if (len <= 0) { 3532 break; 3533 } 3534 3535 /* 3536 * Incrementing requires resizing of the 3537 * packet, and moving up the existing SG 3538 * elements. 3539 */ 3540 ++sg; 3541 MessageSizeInBytes += sizeof(*sg); 3542 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr, 3543 I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr) 3544 + (sizeof(*sg) / sizeof(U32))); 3545 { 3546 PI2O_MESSAGE_FRAME NewMessage_Ptr; 3547 3548 NewMessage_Ptr 3549 = (PI2O_MESSAGE_FRAME) 3550 kmalloc (MessageSizeInBytes, 3551 M_TEMP, M_WAITOK); 3552 span = ((caddr_t)sg) 3553 - (caddr_t)Message_Ptr; 3554 bcopy ((caddr_t)Message_Ptr, 3555 (caddr_t)NewMessage_Ptr, span); 3556 bcopy ((caddr_t)(sg-1), 3557 ((caddr_t)NewMessage_Ptr) + span, 3558 MessageSizeInBytes - span); 3559 kfree (Message_Ptr, M_TEMP); 3560 sg = (PI2O_SGE_SIMPLE_ELEMENT) 3561 (((caddr_t)NewMessage_Ptr) + span); 3562 Message_Ptr = NewMessage_Ptr; 3563 } 3564 } 3565 if ((error) 3566 || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount)) 3567 & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) { 3568 break; 3569 } 3570 ++sg; 3571 } 3572 if (error) { 3573 while ((elm = SLIST_FIRST(&sgList)) 3574 != (struct ioctlSgList_S *)NULL) { 3575 SLIST_REMOVE_HEAD(&sgList, link); 3576 kfree (elm, M_TEMP); 3577 } 3578 kfree (Reply_Ptr, M_TEMP); 3579 kfree (Message_Ptr, M_TEMP); 3580 return (error); 3581 } 3582 } 3583 3584 debug_usr_cmd_printf ("Inbound: "); 3585 debug_usr_cmd_dump_message(Message_Ptr); 3586 3587 /* Send the command */ 3588 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) { 3589 /* Free up in-kernel buffers */ 3590 while ((elm = SLIST_FIRST(&sgList)) 3591 != (struct ioctlSgList_S *)NULL) { 3592 SLIST_REMOVE_HEAD(&sgList, link); 3593 kfree (elm, M_TEMP); 3594 } 3595 kfree (Reply_Ptr, M_TEMP); 3596 kfree (Message_Ptr, M_TEMP); 3597 return (ENOMEM); 3598 } 3599 3600 /* 3601 * We do not need any (optional byteswapping) method access to 3602 * the Initiator context field. 3603 */ 3604 I2O_MESSAGE_FRAME_setInitiatorContext64( 3605 (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb); 3606 3607 (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr); 3608 3609 kfree (Message_Ptr, M_TEMP); 3610 3611 /* 3612 * Wait for the board to report a finished instruction. 3613 */ 3614 crit_enter(); 3615 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 3616 if (ASR_getBlinkLedCode(sc)) { 3617 /* Reset Adapter */ 3618 kprintf ("asr%d: Blink LED 0x%x resetting adapter\n", 3619 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), 3620 ASR_getBlinkLedCode(sc)); 3621 if (ASR_reset (sc) == ENXIO) { 3622 /* Command Cleanup */ 3623 ASR_ccbRemove(sc, ccb); 3624 } 3625 crit_exit(); 3626 /* Free up in-kernel buffers */ 3627 while ((elm = SLIST_FIRST(&sgList)) 3628 != (struct ioctlSgList_S *)NULL) { 3629 SLIST_REMOVE_HEAD(&sgList, link); 3630 kfree (elm, M_TEMP); 3631 } 3632 kfree (Reply_Ptr, M_TEMP); 3633 asr_free_ccb(ccb); 3634 return (EIO); 3635 } 3636 /* Check every second for BlinkLed */ 3637 tsleep((caddr_t)ccb, 0, "asr", hz); 3638 } 3639 crit_exit(); 3640 3641 debug_usr_cmd_printf ("Outbound: "); 3642 debug_usr_cmd_dump_message(Reply_Ptr); 3643 3644 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode( 3645 &(Reply_Ptr->StdReplyFrame), 3646 (ccb->ccb_h.status != CAM_REQ_CMP)); 3647 3648 if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) 3649 - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) { 3650 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr, 3651 ccb->csio.dxfer_len - ccb->csio.resid); 3652 } 3653 if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes 3654 > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) 3655 - I2O_SCSI_SENSE_DATA_SZ))) { 3656 int size = ReplySizeInBytes 3657 - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME) 3658 - I2O_SCSI_SENSE_DATA_SZ; 3659 3660 if (size > sizeof(ccb->csio.sense_data)) { 3661 size = sizeof(ccb->csio.sense_data); 3662 } 3663 bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData, 3664 size); 3665 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount( 3666 Reply_Ptr, size); 3667 } 3668 3669 /* Free up in-kernel buffers */ 3670 while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) { 3671 /* Copy out as necessary */ 3672 if ((error == 0) 3673 /* DIR bit considered `valid', error due to ignorance works */ 3674 && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount)) 3675 & I2O_SGL_FLAGS_DIR) == 0)) { 3676 error = copyout ((caddr_t)(elm->KernelSpace), 3677 elm->UserSpace, 3678 I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount))); 3679 } 3680 SLIST_REMOVE_HEAD(&sgList, link); 3681 kfree (elm, M_TEMP); 3682 } 3683 if (error == 0) { 3684 /* Copy reply frame to user space */ 3685 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply, 3686 ReplySizeInBytes); 3687 } 3688 kfree (Reply_Ptr, M_TEMP); 3689 asr_free_ccb(ccb); 3690 3691 return (error); 3692 } /* ASR_queue_i */ 3693 3694 /*----------------------------------------------------------------------*/ 3695 /* Function asr_ioctl */ 3696 /*----------------------------------------------------------------------*/ 3697 /* The parameters passed to this function are : */ 3698 /* dev : Device number. */ 3699 /* cmd : Ioctl Command */ 3700 /* data : User Argument Passed In. */ 3701 /* flag : Mode Parameter */ 3702 /* proc : Process Parameter */ 3703 /* */ 3704 /* This function is the user interface into this adapter driver */ 3705 /* */ 3706 /* Return : zero if OK, error code if not */ 3707 /*----------------------------------------------------------------------*/ 3708 3709 STATIC int 3710 asr_ioctl(struct dev_ioctl_args *ap) 3711 { 3712 cdev_t dev = ap->a_head.a_dev; 3713 caddr_t data = ap->a_data; 3714 int i, j; 3715 OUT int error = 0; 3716 Asr_softc_t * sc = ASR_get_sc (dev); 3717 3718 if (sc != (Asr_softc_t *)NULL) 3719 switch(ap->a_cmd) { 3720 3721 case DPT_SIGNATURE: 3722 # if (dsDescription_size != 50) 3723 case DPT_SIGNATURE + ((50 - dsDescription_size) << 16): 3724 # endif 3725 if (ap->a_cmd & 0xFFFF0000) { 3726 (void)bcopy ((caddr_t)(&ASR_sig), data, 3727 sizeof(dpt_sig_S)); 3728 return (0); 3729 } 3730 /* Traditional version of the ioctl interface */ 3731 case DPT_SIGNATURE & 0x0000FFFF: 3732 return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data), 3733 sizeof(dpt_sig_S))); 3734 3735 /* Traditional version of the ioctl interface */ 3736 case DPT_CTRLINFO & 0x0000FFFF: 3737 case DPT_CTRLINFO: { 3738 struct { 3739 u_int16_t length; 3740 u_int16_t drvrHBAnum; 3741 u_int32_t baseAddr; 3742 u_int16_t blinkState; 3743 u_int8_t pciBusNum; 3744 u_int8_t pciDeviceNum; 3745 u_int16_t hbaFlags; 3746 u_int16_t Interrupt; 3747 u_int32_t reserved1; 3748 u_int32_t reserved2; 3749 u_int32_t reserved3; 3750 } CtlrInfo; 3751 3752 bzero (&CtlrInfo, sizeof(CtlrInfo)); 3753 CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t); 3754 CtlrInfo.drvrHBAnum = asr_unit(dev); 3755 CtlrInfo.baseAddr = (u_long)sc->ha_Base; 3756 i = ASR_getBlinkLedCode (sc); 3757 if (i == -1) { 3758 i = 0; 3759 } 3760 CtlrInfo.blinkState = i; 3761 CtlrInfo.pciBusNum = sc->ha_pciBusNum; 3762 CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum; 3763 #define FLG_OSD_PCI_VALID 0x0001 3764 #define FLG_OSD_DMA 0x0002 3765 #define FLG_OSD_I2O 0x0004 3766 CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O; 3767 CtlrInfo.Interrupt = sc->ha_irq; 3768 if (ap->a_cmd & 0xFFFF0000) { 3769 bcopy (&CtlrInfo, data, sizeof(CtlrInfo)); 3770 } else { 3771 error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo)); 3772 } 3773 } return (error); 3774 3775 /* Traditional version of the ioctl interface */ 3776 case DPT_SYSINFO & 0x0000FFFF: 3777 case DPT_SYSINFO: { 3778 sysInfo_S Info; 3779 char * cp; 3780 /* Kernel Specific ptok `hack' */ 3781 # define ptok(a) ((char *)(a) + KERNBASE) 3782 3783 bzero (&Info, sizeof(Info)); 3784 3785 /* Appears I am the only person in the Kernel doing this */ 3786 outb (0x70, 0x12); 3787 i = inb(0x71); 3788 j = i >> 4; 3789 if (i == 0x0f) { 3790 outb (0x70, 0x19); 3791 j = inb (0x71); 3792 } 3793 Info.drive0CMOS = j; 3794 3795 j = i & 0x0f; 3796 if (i == 0x0f) { 3797 outb (0x70, 0x1a); 3798 j = inb (0x71); 3799 } 3800 Info.drive1CMOS = j; 3801 3802 Info.numDrives = *((char *)ptok(0x475)); 3803 3804 Info.processorFamily = ASR_sig.dsProcessorFamily; 3805 switch (cpu) { 3806 case CPU_386SX: case CPU_386: 3807 Info.processorType = PROC_386; break; 3808 case CPU_486SX: case CPU_486: 3809 Info.processorType = PROC_486; break; 3810 case CPU_586: 3811 Info.processorType = PROC_PENTIUM; break; 3812 case CPU_686: 3813 Info.processorType = PROC_SEXIUM; break; 3814 } 3815 Info.osType = OS_BSDI_UNIX; 3816 Info.osMajorVersion = osrelease[0] - '0'; 3817 Info.osMinorVersion = osrelease[2] - '0'; 3818 /* Info.osRevision = 0; */ 3819 /* Info.osSubRevision = 0; */ 3820 Info.busType = SI_PCI_BUS; 3821 Info.flags = SI_CMOS_Valid | SI_NumDrivesValid 3822 | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM; 3823 3824 /* Go Out And Look For I2O SmartROM */ 3825 for(j = 0xC8000; j < 0xE0000; j += 2048) { 3826 int k; 3827 3828 cp = ptok(j); 3829 if (*((unsigned short *)cp) != 0xAA55) { 3830 continue; 3831 } 3832 j += (cp[2] * 512) - 2048; 3833 if ((*((u_long *)(cp + 6)) 3834 != ('S' + (' ' * 256) + (' ' * 65536L))) 3835 || (*((u_long *)(cp + 10)) 3836 != ('I' + ('2' * 256) + ('0' * 65536L)))) { 3837 continue; 3838 } 3839 cp += 0x24; 3840 for (k = 0; k < 64; ++k) { 3841 if (*((unsigned short *)cp) 3842 == (' ' + ('v' * 256))) { 3843 break; 3844 } 3845 } 3846 if (k < 64) { 3847 Info.smartROMMajorVersion 3848 = *((unsigned char *)(cp += 4)) - '0'; 3849 Info.smartROMMinorVersion 3850 = *((unsigned char *)(cp += 2)); 3851 Info.smartROMRevision 3852 = *((unsigned char *)(++cp)); 3853 Info.flags |= SI_SmartROMverValid; 3854 Info.flags &= ~SI_NO_SmartROM; 3855 break; 3856 } 3857 } 3858 /* Get The Conventional Memory Size From CMOS */ 3859 outb (0x70, 0x16); 3860 j = inb (0x71); 3861 j <<= 8; 3862 outb (0x70, 0x15); 3863 j |= inb(0x71); 3864 Info.conventionalMemSize = j; 3865 3866 /* Get The Extended Memory Found At Power On From CMOS */ 3867 outb (0x70, 0x31); 3868 j = inb (0x71); 3869 j <<= 8; 3870 outb (0x70, 0x30); 3871 j |= inb(0x71); 3872 Info.extendedMemSize = j; 3873 Info.flags |= SI_MemorySizeValid; 3874 3875 # if (defined(THIS_IS_BROKEN)) 3876 /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */ 3877 if (Info.numDrives > 0) { 3878 /* 3879 * Get The Pointer From Int 41 For The First 3880 * Drive Parameters 3881 */ 3882 j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4) 3883 + (unsigned)(*((unsigned short *)ptok(0x104+0))); 3884 /* 3885 * It appears that SmartROM's Int41/Int46 pointers 3886 * use memory that gets stepped on by the kernel 3887 * loading. We no longer have access to this 3888 * geometry information but try anyways (!?) 3889 */ 3890 Info.drives[0].cylinders = *((unsigned char *)ptok(j)); 3891 ++j; 3892 Info.drives[0].cylinders += ((int)*((unsigned char *) 3893 ptok(j))) << 8; 3894 ++j; 3895 Info.drives[0].heads = *((unsigned char *)ptok(j)); 3896 j += 12; 3897 Info.drives[0].sectors = *((unsigned char *)ptok(j)); 3898 Info.flags |= SI_DriveParamsValid; 3899 if ((Info.drives[0].cylinders == 0) 3900 || (Info.drives[0].heads == 0) 3901 || (Info.drives[0].sectors == 0)) { 3902 Info.flags &= ~SI_DriveParamsValid; 3903 } 3904 if (Info.numDrives > 1) { 3905 /* 3906 * Get The Pointer From Int 46 For The 3907 * Second Drive Parameters 3908 */ 3909 j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4) 3910 + (unsigned)(*((unsigned short *)ptok(0x118+0))); 3911 Info.drives[1].cylinders = *((unsigned char *) 3912 ptok(j)); 3913 ++j; 3914 Info.drives[1].cylinders += ((int) 3915 *((unsigned char *)ptok(j))) << 8; 3916 ++j; 3917 Info.drives[1].heads = *((unsigned char *) 3918 ptok(j)); 3919 j += 12; 3920 Info.drives[1].sectors = *((unsigned char *) 3921 ptok(j)); 3922 if ((Info.drives[1].cylinders == 0) 3923 || (Info.drives[1].heads == 0) 3924 || (Info.drives[1].sectors == 0)) { 3925 Info.flags &= ~SI_DriveParamsValid; 3926 } 3927 } 3928 } 3929 # endif 3930 /* Copy Out The Info Structure To The User */ 3931 if (ap->a_cmd & 0xFFFF0000) { 3932 bcopy (&Info, data, sizeof(Info)); 3933 } else { 3934 error = copyout (&Info, *(caddr_t *)data, sizeof(Info)); 3935 } 3936 return (error); } 3937 3938 /* Get The BlinkLED State */ 3939 case DPT_BLINKLED: 3940 i = ASR_getBlinkLedCode (sc); 3941 if (i == -1) { 3942 i = 0; 3943 } 3944 if (ap->a_cmd & 0xFFFF0000) { 3945 bcopy ((caddr_t)(&i), data, sizeof(i)); 3946 } else { 3947 error = copyout (&i, *(caddr_t *)data, sizeof(i)); 3948 } 3949 break; 3950 3951 /* Send an I2O command */ 3952 case I2OUSRCMD: 3953 return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data))); 3954 3955 /* Reset and re-initialize the adapter */ 3956 case I2ORESETCMD: 3957 return (ASR_reset (sc)); 3958 3959 /* Rescan the LCT table and resynchronize the information */ 3960 case I2ORESCANCMD: 3961 return (ASR_rescan (sc)); 3962 } 3963 return (EINVAL); 3964 } /* asr_ioctl */ 3965