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