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