1 /* $FreeBSD: src/sys/dev/asr/asr.c,v 1.3.2.2 2001/08/23 05:21:29 scottl Exp $ */
2 /* $DragonFly: src/sys/dev/raid/asr/asr.c,v 1.31 2007/12/23 07:00:56 pavalos Exp $ */
4 * Copyright (c) 1996-2000 Distributed Processing Technology Corporation
5 * Copyright (c) 2000-2001 Adaptec Corporation
8 * TERMS AND CONDITIONS OF USE
10 * Redistribution and use in source form, with or without modification, are
11 * permitted provided that redistributions of source code must retain the
12 * above copyright notice, this list of conditions and the following disclaimer.
14 * This software is provided `as is' by Adaptec and any express or implied
15 * warranties, including, but not limited to, the implied warranties of
16 * merchantability and fitness for a particular purpose, are disclaimed. In no
17 * event shall Adaptec be liable for any direct, indirect, incidental, special,
18 * exemplary or consequential damages (including, but not limited to,
19 * procurement of substitute goods or services; loss of use, data, or profits;
20 * or business interruptions) however caused and on any theory of liability,
21 * whether in contract, strict liability, or tort (including negligence or
22 * otherwise) arising in any way out of the use of this driver software, even
23 * if advised of the possibility of such damage.
25 * SCSI I2O host adapter driver
27 * V1.08 2001/08/21 Mark_Salyzyn@adaptec.com
28 * - The 2000S and 2005S do not initialize on some machines,
29 * increased timeout to 255ms from 50ms for the StatusGet
31 * V1.07 2001/05/22 Mark_Salyzyn@adaptec.com
32 * - I knew this one was too good to be true. The error return
33 * on ioctl commands needs to be compared to CAM_REQ_CMP, not
34 * to the bit masked status.
35 * V1.06 2001/05/08 Mark_Salyzyn@adaptec.com
36 * - The 2005S that was supported is affectionately called the
37 * Conjoined BAR Firmware. In order to support RAID-5 in a
38 * 16MB low-cost configuration, Firmware was forced to go
39 * to a Split BAR Firmware. This requires a separate IOP and
40 * Messaging base address.
41 * V1.05 2001/04/25 Mark_Salyzyn@adaptec.com
42 * - Handle support for 2005S Zero Channel RAID solution.
43 * - System locked up if the Adapter locked up. Do not try
44 * to send other commands if the resetIOP command fails. The
45 * fail outstanding command discovery loop was flawed as the
46 * removal of the command from the list prevented discovering
48 * - Comment changes to clarify driver.
49 * - SysInfo searched for an EATA SmartROM, not an I2O SmartROM.
50 * - We do not use the AC_FOUND_DEV event because of I2O.
52 * V1.04 2000/09/22 Mark_Salyzyn@adaptec.com, msmith@freebsd.org,
53 * lampa@fee.vutbr.cz and Scott_Long@adaptec.com.
54 * - Removed support for PM1554, PM2554 and PM2654 in Mode-0
55 * mode as this is confused with competitor adapters in run
57 * - critical locking needed in ASR_ccbAdd and ASR_ccbRemove
58 * to prevent operating system panic.
59 * - moved default major number to 154 from 97.
60 * V1.03 2000/07/12 Mark_Salyzyn@adaptec.com
61 * - The controller is not actually an ASR (Adaptec SCSI RAID)
62 * series that is visible, it's more of an internal code name.
63 * remove any visible references within reason for now.
64 * - bus_ptr->LUN was not correctly zeroed when initially
65 * allocated causing a possible panic of the operating system
67 * V1.02 2000/06/26 Mark_Salyzyn@adaptec.com
68 * - Code always fails for ASR_getTid affecting performance.
69 * - initiated a set of changes that resulted from a formal
70 * code inspection by Mark_Salyzyn@adaptec.com,
71 * George_Dake@adaptec.com, Jeff_Zeak@adaptec.com,
72 * Martin_Wilson@adaptec.com and Vincent_Trandoan@adaptec.com.
73 * Their findings were focussed on the LCT & TID handler, and
74 * all resulting changes were to improve code readability,
75 * consistency or have a positive effect on performance.
76 * V1.01 2000/06/14 Mark_Salyzyn@adaptec.com
77 * - Passthrough returned an incorrect error.
78 * - Passthrough did not migrate the intrinsic scsi layer wakeup
79 * on command completion.
80 * - generate control device nodes using make_dev and delete_dev.
81 * - Performance affected by TID caching reallocing.
82 * - Made suggested changes by Justin_Gibbs@adaptec.com
83 * - use splcam instead of splbio.
84 * - use u_int8_t instead of u_char.
85 * - use u_int16_t instead of u_short.
86 * - use u_int32_t instead of u_long where appropriate.
87 * - use 64 bit context handler instead of 32 bit.
88 * - create_ccb should only allocate the worst case
89 * requirements for the driver since CAM may evolve
90 * making union ccb much larger than needed here.
91 * renamed create_ccb to asr_alloc_ccb.
92 * - go nutz justifying all debug prints as macros
93 * defined at the top and remove unsightly ifdefs.
94 * - INLINE STATIC viewed as confusing. Historically
95 * utilized to affect code performance and debug
96 * issues in OS, Compiler or OEM specific situations.
97 * V1.00 2000/05/31 Mark_Salyzyn@adaptec.com
98 * - Ported from FreeBSD 2.2.X DPT I2O driver.
99 * changed struct scsi_xfer to union ccb/struct ccb_hdr
100 * changed variable name xs to ccb
101 * changed struct scsi_link to struct cam_path
102 * changed struct scsibus_data to struct cam_sim
103 * stopped using fordriver for holding on to the TID
104 * use proprietary packet creation instead of scsi_inquire
105 * CAM layer sends synchronize commands.
108 #define ASR_VERSION 1
109 #define ASR_REVISION '0'
110 #define ASR_SUBREVISION '8'
113 #define ASR_YEAR 2001 - 1980
116 * Debug macros to reduce the unsightly ifdefs
118 #if (defined(DEBUG_ASR) || defined(DEBUG_ASR_USR_CMD) || defined(DEBUG_ASR_CMD))
119 # define debug_asr_message(message) \
121 u_int32_t * pointer = (u_int32_t *)message; \
122 u_int32_t length = I2O_MESSAGE_FRAME_getMessageSize(message);\
123 u_int32_t counter = 0; \
126 kprintf ("%08lx%c", (u_long)*(pointer++), \
127 (((++counter & 7) == 0) || (length == 0)) \
132 #endif /* DEBUG_ASR || DEBUG_ASR_USR_CMD || DEBUG_ASR_CMD */
134 #if (defined(DEBUG_ASR))
135 /* Breaks on none STDC based compilers :-( */
136 # define debug_asr_printf(fmt,args...) kprintf(fmt, ##args)
137 # define debug_asr_dump_message(message) debug_asr_message(message)
138 # define debug_asr_print_path(ccb) xpt_print_path(ccb->ccb_h.path);
139 /* None fatal version of the ASSERT macro */
140 # if (defined(__STDC__))
141 # define ASSERT(phrase) if(!(phrase))kprintf(#phrase " at line %d file %s\n",__LINE__,__FILE__)
143 # define ASSERT(phrase) if(!(phrase))kprintf("phrase" " at line %d file %s\n",__LINE__,__FILE__)
145 #else /* DEBUG_ASR */
146 # define debug_asr_printf(fmt,args...)
147 # define debug_asr_dump_message(message)
148 # define debug_asr_print_path(ccb)
150 #endif /* DEBUG_ASR */
153 * If DEBUG_ASR_CMD is defined:
154 * 0 - Display incoming SCSI commands
155 * 1 - add in a quick character before queueing.
156 * 2 - add in outgoing message frames.
158 #if (defined(DEBUG_ASR_CMD))
159 # define debug_asr_cmd_printf(fmt,args...) kprintf(fmt,##args)
160 # define debug_asr_dump_ccb(ccb) \
162 u_int8_t * cp = (unsigned char *)&(ccb->csio.cdb_io); \
163 int len = ccb->csio.cdb_len; \
166 debug_asr_cmd_printf (" %02x", *(cp++)); \
170 # if (DEBUG_ASR_CMD > 0)
171 # define debug_asr_cmd1_printf debug_asr_cmd_printf
173 # define debug_asr_cmd1_printf(fmt,args...)
175 # if (DEBUG_ASR_CMD > 1)
176 # define debug_asr_cmd2_printf debug_asr_cmd_printf
177 # define debug_asr_cmd2_dump_message(message) debug_asr_message(message)
179 # define debug_asr_cmd2_printf(fmt,args...)
180 # define debug_asr_cmd2_dump_message(message)
182 #else /* DEBUG_ASR_CMD */
183 # define debug_asr_cmd_printf(fmt,args...)
184 # define debug_asr_cmd_dump_ccb(ccb)
185 # define debug_asr_cmd1_printf(fmt,args...)
186 # define debug_asr_cmd2_printf(fmt,args...)
187 # define debug_asr_cmd2_dump_message(message)
188 #endif /* DEBUG_ASR_CMD */
190 #if (defined(DEBUG_ASR_USR_CMD))
191 # define debug_usr_cmd_printf(fmt,args...) kprintf(fmt,##args)
192 # define debug_usr_cmd_dump_message(message) debug_usr_message(message)
193 #else /* DEBUG_ASR_USR_CMD */
194 # define debug_usr_cmd_printf(fmt,args...)
195 # define debug_usr_cmd_dump_message(message)
196 #endif /* DEBUG_ASR_USR_CMD */
198 #define dsDescription_size 46 /* Snug as a bug in a rug */
201 static dpt_sig_S ASR_sig = {
202 { 'd', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, PROC_INTEL,
203 PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, FT_HBADRVR, 0,
204 OEM_DPT, OS_FREE_BSD, CAP_ABOVE16MB, DEV_ALL,
206 0, 0, ASR_VERSION, ASR_REVISION, ASR_SUBREVISION,
207 ASR_MONTH, ASR_DAY, ASR_YEAR,
208 /* 01234567890123456789012345678901234567890123456789 < 50 chars */
209 "Adaptec FreeBSD 4.0.0 Unix SCSI I2O HBA Driver"
210 /* ^^^^^ asr_attach alters these to match OS */
213 #include <sys/param.h> /* TRUE=1 and FALSE=0 defined here */
214 #include <sys/kernel.h>
215 #include <sys/systm.h>
216 #include <sys/malloc.h>
217 #include <sys/proc.h>
218 #include <sys/conf.h>
220 #include <sys/rman.h>
221 #include <sys/stat.h>
222 #include <sys/device.h>
223 #include <sys/thread2.h>
224 #include <sys/ioccom.h>
226 #include <bus/cam/cam.h>
227 #include <bus/cam/cam_ccb.h>
228 #include <bus/cam/cam_sim.h>
229 #include <bus/cam/cam_xpt_sim.h>
230 #include <bus/cam/cam_xpt_periph.h>
232 #include <bus/cam/scsi/scsi_all.h>
233 #include <bus/cam/scsi/scsi_message.h>
237 #include <machine/cputypes.h>
238 #include <machine/clock.h>
239 #include <machine/vmparam.h>
241 #include <bus/pci/pcivar.h>
242 #include <bus/pci/pcireg.h>
244 #define STATIC static
247 #if (defined(DEBUG_ASR) && (DEBUG_ASR > 0))
257 #define osdSwap4(x) ((u_long)ntohl((u_long)(x)))
258 #define KVTOPHYS(x) vtophys(x)
259 #include "dptalign.h"
261 #include "i2obscsi.h"
263 #include "i2oadptr.h"
264 #include "sys_info.h"
266 /* Configuration Definitions */
268 #define SG_SIZE 58 /* Scatter Gather list Size */
269 #define MAX_TARGET_ID 126 /* Maximum Target ID supported */
270 #define MAX_LUN 255 /* Maximum LUN Supported */
271 #define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */
272 #define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */
273 #define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */
274 #define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */
275 #define MAX_MAP 4194304L /* Maximum mapping size of IOP */
276 /* Also serves as the minimum map for */
277 /* the 2005S zero channel RAID product */
279 /**************************************************************************
280 ** ASR Host Adapter structure - One Structure For Each Host Adapter That **
281 ** Is Configured Into The System. The Structure Supplies Configuration **
282 ** Information, Status Info, Queue Info And An Active CCB List Pointer. **
283 ***************************************************************************/
285 /* I2O register set */
290 # define Mask_InterruptsDisabled 0x08
292 volatile U32 ToFIFO; /* In Bound FIFO */
293 volatile U32 FromFIFO; /* Out Bound FIFO */
297 * A MIX of performance and space considerations for TID lookups
299 typedef u_int16_t tid_t;
302 u_int32_t size; /* up to MAX_LUN */
307 u_int32_t size; /* up to MAX_TARGET */
312 * To ensure that we only allocate and use the worst case ccb here, lets
313 * make our own local ccb union. If asr_alloc_ccb is utilized for another
314 * ccb type, ensure that you add the additional structures into our local
315 * ccb union. To ensure strict type checking, we will utilize the local
316 * ccb definition wherever possible.
319 struct ccb_hdr ccb_h; /* For convenience */
320 struct ccb_scsiio csio;
321 struct ccb_setasync csa;
324 typedef struct Asr_softc {
326 void * ha_Base; /* base port for each board */
327 u_int8_t * volatile ha_blinkLED;
328 i2oRegs_t * ha_Virt; /* Base address of IOP */
329 U8 * ha_Fvirt; /* Base address of Frames */
330 I2O_IOP_ENTRY ha_SystemTable;
331 LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */
332 struct cam_path * ha_path[MAX_CHANNEL+1];
333 struct cam_sim * ha_sim[MAX_CHANNEL+1];
334 struct resource * ha_mem_res;
335 struct resource * ha_mes_res;
336 struct resource * ha_irq_res;
338 PI2O_LCT ha_LCT; /* Complete list of devices */
339 # define le_type IdentityTag[0]
340 # define I2O_BSA 0x20
341 # define I2O_FCA 0x40
342 # define I2O_SCSI 0x00
343 # define I2O_PORT 0x80
344 # define I2O_UNKNOWN 0x7F
345 # define le_bus IdentityTag[1]
346 # define le_target IdentityTag[2]
347 # define le_lun IdentityTag[3]
348 target2lun_t * ha_targets[MAX_CHANNEL+1];
349 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs;
352 u_int8_t ha_in_reset;
353 # define HA_OPERATIONAL 0
354 # define HA_IN_RESET 1
355 # define HA_OFF_LINE 2
356 # define HA_OFF_LINE_RECOVERY 3
357 /* Configuration information */
358 /* The target id maximums we take */
359 u_int8_t ha_MaxBus; /* Maximum bus */
360 u_int8_t ha_MaxId; /* Maximum target ID */
361 u_int8_t ha_MaxLun; /* Maximum target LUN */
362 u_int8_t ha_SgSize; /* Max SG elements */
363 u_int8_t ha_pciBusNum;
364 u_int8_t ha_pciDeviceNum;
365 u_int8_t ha_adapter_target[MAX_CHANNEL+1];
366 u_int16_t ha_QueueSize; /* Max outstanding commands */
367 u_int16_t ha_Msgs_Count;
369 /* Links into other parents and HBAs */
370 struct Asr_softc * ha_next; /* HBA list */
373 STATIC Asr_softc_t * Asr_softc;
376 * Prototypes of the routines we have in this object.
379 /* Externally callable routines */
380 #define PROBE_ARGS IN device_t tag
381 #define PROBE_RET int
382 #define PROBE_SET() u_long id = (pci_get_device(tag)<<16)|pci_get_vendor(tag)
383 #define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);}
384 #define ATTACH_ARGS IN device_t tag
385 #define ATTACH_RET int
386 #define ATTACH_SET() int unit = device_get_unit(tag)
387 #define ATTACH_RETURN(retval) return(retval)
388 /* I2O HDM interface */
389 STATIC PROBE_RET asr_probe (PROBE_ARGS);
390 STATIC ATTACH_RET asr_attach (ATTACH_ARGS);
391 /* DOMINO placeholder */
392 STATIC PROBE_RET domino_probe (PROBE_ARGS);
393 STATIC ATTACH_RET domino_attach (ATTACH_ARGS);
394 /* MODE0 adapter placeholder */
395 STATIC PROBE_RET mode0_probe (PROBE_ARGS);
396 STATIC ATTACH_RET mode0_attach (ATTACH_ARGS);
398 STATIC Asr_softc_t * ASR_get_sc (cdev_t dev);
399 STATIC d_ioctl_t asr_ioctl;
400 STATIC d_open_t asr_open;
401 STATIC d_close_t asr_close;
402 STATIC int asr_intr (IN Asr_softc_t *sc);
403 STATIC void asr_timeout (INOUT void *arg);
404 STATIC int ASR_init (IN Asr_softc_t *sc);
405 STATIC INLINE int ASR_acquireLct (INOUT Asr_softc_t *sc);
406 STATIC INLINE int ASR_acquireHrt (INOUT Asr_softc_t *sc);
407 STATIC void asr_action (IN struct cam_sim *sim,
409 STATIC void asr_poll (IN struct cam_sim * sim);
412 * Here is the auto-probe structure used to nest our tests appropriately
413 * during the startup phase of the operating system.
415 STATIC device_method_t asr_methods[] = {
416 DEVMETHOD(device_probe, asr_probe),
417 DEVMETHOD(device_attach, asr_attach),
421 STATIC driver_t asr_driver = {
427 STATIC devclass_t asr_devclass;
429 DECLARE_DUMMY_MODULE(asr);
430 DRIVER_MODULE(asr, pci, asr_driver, asr_devclass, 0, 0);
432 STATIC device_method_t domino_methods[] = {
433 DEVMETHOD(device_probe, domino_probe),
434 DEVMETHOD(device_attach, domino_attach),
438 STATIC driver_t domino_driver = {
444 STATIC devclass_t domino_devclass;
446 DRIVER_MODULE(domino, pci, domino_driver, domino_devclass, 0, 0);
448 STATIC device_method_t mode0_methods[] = {
449 DEVMETHOD(device_probe, mode0_probe),
450 DEVMETHOD(device_attach, mode0_attach),
454 STATIC driver_t mode0_driver = {
460 STATIC devclass_t mode0_devclass;
462 DRIVER_MODULE(mode0, pci, mode0_driver, mode0_devclass, 0, 0);
465 * devsw for asr hba driver
467 * only ioctl is used. the sd driver provides all other access.
469 STATIC struct dev_ops asr_ops = {
472 .d_close = asr_close,
473 .d_ioctl = asr_ioctl,
477 * Initialize the dynamic dev_ops hooks.
480 asr_drvinit (void * unused)
482 static int asr_devsw_installed = 0;
484 if (asr_devsw_installed) {
487 asr_devsw_installed++;
490 * Adding the ops will dynamically assign a major number.
492 dev_ops_add(&asr_ops, 0, 0);
495 /* XXX Must initialize before CAM layer picks up our HBA driver */
496 SYSINIT(asrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,asr_drvinit,NULL)
498 /* I2O support routines */
499 #define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)]
500 #define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME))
503 * Fill message with default.
505 STATIC PI2O_MESSAGE_FRAME
510 OUT PI2O_MESSAGE_FRAME Message_Ptr;
512 Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message);
513 bzero ((void *)Message_Ptr, size);
514 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11);
515 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
516 (size + sizeof(U32) - 1) >> 2);
517 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
518 return (Message_Ptr);
519 } /* ASR_fillMessage */
521 #define EMPTY_QUEUE ((U32)-1L)
527 OUT U32 MessageOffset;
529 if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) {
530 MessageOffset = virt->ToFIFO;
532 return (MessageOffset);
533 } /* ASR_getMessage */
535 /* Issue a polled command */
538 INOUT i2oRegs_t * virt,
540 IN PI2O_MESSAGE_FRAME Message)
547 * ASR_initiateCp is only used for synchronous commands and will
548 * be made more resiliant to adapter delays since commands like
549 * resetIOP can cause the adapter to be deaf for a little time.
551 while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE)
555 if (MessageOffset != EMPTY_QUEUE) {
556 bcopy (Message, fvirt + MessageOffset,
557 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
559 * Disable the Interrupts
561 virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled;
562 virt->ToFIFO = MessageOffset;
565 } /* ASR_initiateCp */
572 INOUT i2oRegs_t * virt,
575 struct resetMessage {
576 I2O_EXEC_IOP_RESET_MESSAGE M;
579 defAlignLong(struct resetMessage,Message);
580 PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr;
581 OUT U32 * volatile Reply_Ptr;
585 * Build up our copy of the Message.
587 Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message,
588 sizeof(I2O_EXEC_IOP_RESET_MESSAGE));
589 I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET);
591 * Reset the Reply Status
593 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
594 + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0;
595 I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr,
596 KVTOPHYS((void *)Reply_Ptr));
598 * Send the Message out
600 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
602 * Wait for a response (Poll), timeouts are dangerous if
603 * the card is truly responsive. We assume response in 2s.
605 u_int8_t Delay = 200;
607 while ((*Reply_Ptr == 0) && (--Delay != 0)) {
611 * Re-enable the interrupts.
617 ASSERT (Old != (U32)-1L);
622 * Get the curent state of the adapter
624 STATIC INLINE PI2O_EXEC_STATUS_GET_REPLY
626 INOUT i2oRegs_t * virt,
628 OUT PI2O_EXEC_STATUS_GET_REPLY buffer)
630 defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message);
631 PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr;
635 * Build up our copy of the Message.
637 Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message,
638 sizeof(I2O_EXEC_STATUS_GET_MESSAGE));
639 I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr,
640 I2O_EXEC_STATUS_GET);
641 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr,
642 KVTOPHYS((void *)buffer));
643 /* This one is a Byte Count */
644 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr,
645 sizeof(I2O_EXEC_STATUS_GET_REPLY));
647 * Reset the Reply Status
649 bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY));
651 * Send the Message out
653 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
655 * Wait for a response (Poll), timeouts are dangerous if
656 * the card is truly responsive. We assume response in 50ms.
658 u_int8_t Delay = 255;
660 while (*((U8 * volatile)&(buffer->SyncByte)) == 0) {
662 buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL;
668 * Re-enable the interrupts.
673 return ((PI2O_EXEC_STATUS_GET_REPLY)NULL);
674 } /* ASR_getStatus */
677 * Check if the device is a SCSI I2O HBA, and add it to the list.
681 * Probe for ASR controller. If we find it, we will use it.
685 asr_probe(PROBE_ARGS)
688 if ((id == 0xA5011044) || (id == 0xA5111044)) {
689 PROBE_RETURN ("Adaptec Caching SCSI RAID");
695 * Probe/Attach for DOMINO chipset.
698 domino_probe(PROBE_ARGS)
701 if (id == 0x10121044) {
702 PROBE_RETURN ("Adaptec Caching Memory Controller");
708 domino_attach (ATTACH_ARGS)
711 } /* domino_attach */
714 * Probe/Attach for MODE0 adapters.
717 mode0_probe(PROBE_ARGS)
722 * If/When we can get a business case to commit to a
723 * Mode0 driver here, we can make all these tests more
724 * specific and robust. Mode0 adapters have their processors
725 * turned off, this the chips are in a raw state.
728 /* This is a PLX9054 */
729 if (id == 0x905410B5) {
730 PROBE_RETURN ("Adaptec Mode0 PM3757");
732 /* This is a PLX9080 */
733 if (id == 0x908010B5) {
734 PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755");
736 /* This is a ZION 80303 */
737 if (id == 0x53098086) {
738 PROBE_RETURN ("Adaptec Mode0 3010S");
740 /* This is an i960RS */
741 if (id == 0x39628086) {
742 PROBE_RETURN ("Adaptec Mode0 2100S");
744 /* This is an i960RN */
745 if (id == 0x19648086) {
746 PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S");
748 #if 0 /* this would match any generic i960 -- mjs */
749 /* This is an i960RP (typically also on Motherboards) */
750 if (id == 0x19608086) {
751 PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654");
758 mode0_attach (ATTACH_ARGS)
763 STATIC INLINE union asr_ccb *
767 OUT union asr_ccb * new_ccb;
769 if ((new_ccb = (union asr_ccb *)kmalloc(sizeof(*new_ccb),
770 M_DEVBUF, M_WAITOK)) != (union asr_ccb *)NULL) {
771 bzero (new_ccb, sizeof(*new_ccb));
772 new_ccb->ccb_h.pinfo.priority = 1;
773 new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
774 new_ccb->ccb_h.spriv_ptr0 = sc;
777 } /* asr_alloc_ccb */
781 IN union asr_ccb * free_ccb)
783 kfree(free_ccb, M_DEVBUF);
787 * Print inquiry data `carefully'
794 while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) {
795 kprintf ("%c", *(s++));
802 STATIC INLINE int ASR_queue (
804 IN PI2O_MESSAGE_FRAME Message);
806 * Send a message synchronously and without Interrupt to a ccb.
810 INOUT union asr_ccb * ccb,
811 IN PI2O_MESSAGE_FRAME Message)
814 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
817 * We do not need any (optional byteswapping) method access to
818 * the Initiator context field.
820 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
822 /* Prevent interrupt service */
824 sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask)
825 | Mask_InterruptsDisabled;
827 if (ASR_queue (sc, Message) == EMPTY_QUEUE) {
828 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
829 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
833 * Wait for this board to report a finished instruction.
835 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
839 /* Re-enable Interrupts */
840 sc->ha_Virt->Mask = Mask;
843 return (ccb->ccb_h.status);
847 * Send a message synchronously to a Asr_softc_t
852 IN PI2O_MESSAGE_FRAME Message)
857 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
858 return (CAM_REQUEUE_REQ);
861 status = ASR_queue_s (ccb, Message);
869 * Add the specified ccb to the active queue
874 INOUT union asr_ccb * ccb)
877 LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le);
878 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
879 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
881 * RAID systems can take considerable time to
882 * complete some commands given the large cache
883 * flashes switching from write back to write thru.
885 ccb->ccb_h.timeout = 6 * 60 * 1000;
887 callout_reset(&ccb->ccb_h.timeout_ch,
888 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
894 * Remove the specified ccb from the active queue.
899 INOUT union asr_ccb * ccb)
902 callout_stop(&ccb->ccb_h.timeout_ch);
903 LIST_REMOVE(&(ccb->ccb_h), sim_links.le);
905 } /* ASR_ccbRemove */
908 * Fail all the active commands, so they get re-issued by the operating
912 ASR_failActiveCommands (
915 struct ccb_hdr * ccb;
917 #if 0 /* Currently handled by callers, unnecessary paranoia currently */
918 /* Left in for historical perspective. */
919 defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message);
920 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
922 /* Send a blind LCT command to wait for the enableSys to complete */
923 Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message,
924 sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT));
925 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
926 I2O_EXEC_LCT_NOTIFY);
927 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
928 I2O_CLASS_MATCH_ANYCLASS);
929 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
934 * We do not need to inform the CAM layer that we had a bus
935 * reset since we manage it on our own, this also prevents the
936 * SCSI_DELAY settling that would be required on other systems.
937 * The `SCSI_DELAY' has already been handled by the card via the
938 * acquisition of the LCT table while we are at CAM priority level.
939 * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) {
940 * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL);
943 while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) {
944 ASR_ccbRemove (sc, (union asr_ccb *)ccb);
946 ccb->status &= ~CAM_STATUS_MASK;
947 ccb->status |= CAM_REQUEUE_REQ;
948 /* Nothing Transfered */
949 ((struct ccb_scsiio *)ccb)->resid
950 = ((struct ccb_scsiio *)ccb)->dxfer_len;
953 xpt_done ((union ccb *)ccb);
955 wakeup ((caddr_t)ccb);
959 } /* ASR_failActiveCommands */
962 * The following command causes the HBA to reset the specific bus
969 defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message);
970 I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr;
971 PI2O_LCT_ENTRY Device;
973 Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message,
974 sizeof(I2O_HBA_BUS_RESET_MESSAGE));
975 I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame,
977 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
978 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
980 if (((Device->le_type & I2O_PORT) != 0)
981 && (Device->le_bus == bus)) {
982 I2O_MESSAGE_FRAME_setTargetAddress(
983 &Message_Ptr->StdMessageFrame,
984 I2O_LCT_ENTRY_getLocalTID(Device));
985 /* Asynchronous command, with no expectations */
986 (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
993 ASR_getBlinkLedCode (
996 if ((sc != (Asr_softc_t *)NULL)
997 && (sc->ha_blinkLED != (u_int8_t *)NULL)
998 && (sc->ha_blinkLED[1] == 0xBC)) {
999 return (sc->ha_blinkLED[0]);
1002 } /* ASR_getBlinkCode */
1005 * Determine the address of an TID lookup. Must be done at high priority
1006 * since the address can be changed by other threads of execution.
1008 * Returns NULL pointer if not indexible (but will attempt to generate
1009 * an index if `new_entry' flag is set to TRUE).
1011 * All addressible entries are to be guaranteed zero if never initialized.
1013 STATIC INLINE tid_t *
1015 INOUT Asr_softc_t * sc,
1021 target2lun_t * bus_ptr;
1022 lun2tid_t * target_ptr;
1026 * Validity checking of incoming parameters. More of a bound
1027 * expansion limit than an issue with the code dealing with the
1030 * sc must be valid before it gets here, so that check could be
1031 * dropped if speed a critical issue.
1033 if ((sc == (Asr_softc_t *)NULL)
1034 || (bus > MAX_CHANNEL)
1035 || (target > sc->ha_MaxId)
1036 || (lun > sc->ha_MaxLun)) {
1037 debug_asr_printf("(%lx,%d,%d,%d) target out of range\n",
1038 (u_long)sc, bus, target, lun);
1039 return ((tid_t *)NULL);
1042 * See if there is an associated bus list.
1044 * for performance, allocate in size of BUS_CHUNK chunks.
1045 * BUS_CHUNK must be a power of two. This is to reduce
1046 * fragmentation effects on the allocations.
1048 # define BUS_CHUNK 8
1049 new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1));
1050 if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) {
1052 * Allocate a new structure?
1053 * Since one element in structure, the +1
1054 * needed for size has been abstracted.
1056 if ((new_entry == FALSE)
1057 || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)kmalloc (
1058 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1060 == (target2lun_t *)NULL)) {
1061 debug_asr_printf("failed to allocate bus list\n");
1062 return ((tid_t *)NULL);
1064 bzero (bus_ptr, sizeof(*bus_ptr)
1065 + (sizeof(bus_ptr->LUN) * new_size));
1066 bus_ptr->size = new_size + 1;
1067 } else if (bus_ptr->size <= new_size) {
1068 target2lun_t * new_bus_ptr;
1071 * Reallocate a new structure?
1072 * Since one element in structure, the +1
1073 * needed for size has been abstracted.
1075 if ((new_entry == FALSE)
1076 || ((new_bus_ptr = (target2lun_t *)kmalloc (
1077 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1079 == (target2lun_t *)NULL)) {
1080 debug_asr_printf("failed to reallocate bus list\n");
1081 return ((tid_t *)NULL);
1084 * Zero and copy the whole thing, safer, simpler coding
1085 * and not really performance critical at this point.
1087 bzero (new_bus_ptr, sizeof(*bus_ptr)
1088 + (sizeof(bus_ptr->LUN) * new_size));
1089 bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr)
1090 + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1)));
1091 sc->ha_targets[bus] = new_bus_ptr;
1092 kfree (bus_ptr, M_TEMP);
1093 bus_ptr = new_bus_ptr;
1094 bus_ptr->size = new_size + 1;
1097 * We now have the bus list, lets get to the target list.
1098 * Since most systems have only *one* lun, we do not allocate
1099 * in chunks as above, here we allow one, then in chunk sizes.
1100 * TARGET_CHUNK must be a power of two. This is to reduce
1101 * fragmentation effects on the allocations.
1103 # define TARGET_CHUNK 8
1104 if ((new_size = lun) != 0) {
1105 new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1));
1107 if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) {
1109 * Allocate a new structure?
1110 * Since one element in structure, the +1
1111 * needed for size has been abstracted.
1113 if ((new_entry == FALSE)
1114 || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)kmalloc (
1115 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1117 == (lun2tid_t *)NULL)) {
1118 debug_asr_printf("failed to allocate target list\n");
1119 return ((tid_t *)NULL);
1121 bzero (target_ptr, sizeof(*target_ptr)
1122 + (sizeof(target_ptr->TID) * new_size));
1123 target_ptr->size = new_size + 1;
1124 } else if (target_ptr->size <= new_size) {
1125 lun2tid_t * new_target_ptr;
1128 * Reallocate a new structure?
1129 * Since one element in structure, the +1
1130 * needed for size has been abstracted.
1132 if ((new_entry == FALSE)
1133 || ((new_target_ptr = (lun2tid_t *)kmalloc (
1134 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1136 == (lun2tid_t *)NULL)) {
1137 debug_asr_printf("failed to reallocate target list\n");
1138 return ((tid_t *)NULL);
1141 * Zero and copy the whole thing, safer, simpler coding
1142 * and not really performance critical at this point.
1144 bzero (new_target_ptr, sizeof(*target_ptr)
1145 + (sizeof(target_ptr->TID) * new_size));
1146 bcopy (target_ptr, new_target_ptr,
1148 + (sizeof(target_ptr->TID) * (target_ptr->size - 1)));
1149 bus_ptr->LUN[target] = new_target_ptr;
1150 kfree (target_ptr, M_TEMP);
1151 target_ptr = new_target_ptr;
1152 target_ptr->size = new_size + 1;
1155 * Now, acquire the TID address from the LUN indexed list.
1157 return (&(target_ptr->TID[lun]));
1158 } /* ASR_getTidAddress */
1161 * Get a pre-existing TID relationship.
1163 * If the TID was never set, return (tid_t)-1.
1165 * should use mutex rather than spl.
1169 IN Asr_softc_t * sc,
1178 if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE))
1180 /* (tid_t)0 or (tid_t)-1 indicate no TID */
1181 || (*tid_ptr == (tid_t)0)) {
1191 * Set a TID relationship.
1193 * If the TID was not set, return (tid_t)-1.
1195 * should use mutex rather than spl.
1199 INOUT Asr_softc_t * sc,
1207 if (TID != (tid_t)-1) {
1212 if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE))
1223 /*-------------------------------------------------------------------------*/
1224 /* Function ASR_rescan */
1225 /*-------------------------------------------------------------------------*/
1226 /* The Parameters Passed To This Function Are : */
1227 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1229 /* This Function Will rescan the adapter and resynchronize any data */
1231 /* Return : 0 For OK, Error Code Otherwise */
1232 /*-------------------------------------------------------------------------*/
1236 IN Asr_softc_t * sc)
1242 * Re-acquire the LCT table and synchronize us to the adapter.
1244 if ((error = ASR_acquireLct(sc)) == 0) {
1245 error = ASR_acquireHrt(sc);
1252 bus = sc->ha_MaxBus;
1253 /* Reset all existing cached TID lookups */
1255 int target, event = 0;
1258 * Scan for all targets on this bus to see if they
1259 * got affected by the rescan.
1261 for (target = 0; target <= sc->ha_MaxId; ++target) {
1264 /* Stay away from the controller ID */
1265 if (target == sc->ha_adapter_target[bus]) {
1268 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
1269 PI2O_LCT_ENTRY Device;
1270 tid_t TID = (tid_t)-1;
1274 * See if the cached TID changed. Search for
1275 * the device in our new LCT.
1277 for (Device = sc->ha_LCT->LCTEntry;
1278 Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT)
1279 + I2O_LCT_getTableSize(sc->ha_LCT));
1281 if ((Device->le_type != I2O_UNKNOWN)
1282 && (Device->le_bus == bus)
1283 && (Device->le_target == target)
1284 && (Device->le_lun == lun)
1285 && (I2O_LCT_ENTRY_getUserTID(Device)
1287 TID = I2O_LCT_ENTRY_getLocalTID(
1293 * Indicate to the OS that the label needs
1294 * to be recalculated, or that the specific
1295 * open device is no longer valid (Merde)
1296 * because the cached TID changed.
1298 LastTID = ASR_getTid (sc, bus, target, lun);
1299 if (LastTID != TID) {
1300 struct cam_path * path;
1302 if (xpt_create_path(&path,
1304 cam_sim_path(sc->ha_sim[bus]),
1305 target, lun) != CAM_REQ_CMP) {
1306 if (TID == (tid_t)-1) {
1307 event |= AC_LOST_DEVICE;
1309 event |= AC_INQ_CHANGED
1310 | AC_GETDEV_CHANGED;
1313 if (TID == (tid_t)-1) {
1317 } else if (LastTID == (tid_t)-1) {
1318 struct ccb_getdev ccb;
1322 path, /*priority*/5);
1338 * We have the option of clearing the
1339 * cached TID for it to be rescanned, or to
1340 * set it now even if the device never got
1341 * accessed. We chose the later since we
1342 * currently do not use the condition that
1343 * the TID ever got cached.
1345 ASR_setTid (sc, bus, target, lun, TID);
1349 * The xpt layer can not handle multiple events at the
1352 if (event & AC_LOST_DEVICE) {
1353 xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL);
1355 if (event & AC_INQ_CHANGED) {
1356 xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL);
1358 if (event & AC_GETDEV_CHANGED) {
1359 xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL);
1361 } while (--bus >= 0);
1365 /*-------------------------------------------------------------------------*/
1366 /* Function ASR_reset */
1367 /*-------------------------------------------------------------------------*/
1368 /* The Parameters Passed To This Function Are : */
1369 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1371 /* This Function Will reset the adapter and resynchronize any data */
1374 /*-------------------------------------------------------------------------*/
1378 IN Asr_softc_t * sc)
1383 if ((sc->ha_in_reset == HA_IN_RESET)
1384 || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) {
1389 * Promotes HA_OPERATIONAL to HA_IN_RESET,
1390 * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY.
1392 ++(sc->ha_in_reset);
1393 if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) {
1394 debug_asr_printf ("ASR_resetIOP failed\n");
1396 * We really need to take this card off-line, easier said
1397 * than make sense. Better to keep retrying for now since if a
1398 * UART cable is connected the blinkLEDs the adapter is now in
1399 * a hard state requiring action from the monitor commands to
1400 * the HBA to continue. For debugging waiting forever is a
1401 * good thing. In a production system, however, one may wish
1402 * to instead take the card off-line ...
1404 # if 0 && (defined(HA_OFF_LINE))
1406 * Take adapter off-line.
1408 kprintf ("asr%d: Taking adapter off-line\n",
1410 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1412 sc->ha_in_reset = HA_OFF_LINE;
1417 while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0);
1420 retVal = ASR_init (sc);
1423 debug_asr_printf ("ASR_init failed\n");
1424 sc->ha_in_reset = HA_OFF_LINE;
1427 if (ASR_rescan (sc) != 0) {
1428 debug_asr_printf ("ASR_rescan failed\n");
1430 ASR_failActiveCommands (sc);
1431 if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) {
1432 kprintf ("asr%d: Brining adapter back on-line\n",
1434 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1437 sc->ha_in_reset = HA_OPERATIONAL;
1442 * Device timeout handler.
1448 union asr_ccb * ccb = (union asr_ccb *)arg;
1449 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
1452 debug_asr_print_path(ccb);
1453 debug_asr_printf("timed out");
1456 * Check if the adapter has locked up?
1458 if ((s = ASR_getBlinkLedCode(sc)) != 0) {
1460 kprintf ("asr%d: Blink LED 0x%x resetting adapter\n",
1461 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s);
1462 if (ASR_reset (sc) == ENXIO) {
1463 /* Try again later */
1464 callout_reset(&ccb->ccb_h.timeout_ch,
1465 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
1470 * Abort does not function on the ASR card!!! Walking away from
1471 * the SCSI command is also *very* dangerous. A SCSI BUS reset is
1472 * our best bet, followed by a complete adapter reset if that fails.
1475 /* Check if we already timed out once to raise the issue */
1476 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) {
1477 debug_asr_printf (" AGAIN\nreinitializing adapter\n");
1478 if (ASR_reset (sc) == ENXIO) {
1479 callout_reset(&ccb->ccb_h.timeout_ch,
1480 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
1485 debug_asr_printf ("\nresetting bus\n");
1486 /* If the BUS reset does not take, then an adapter reset is next! */
1487 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1488 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1489 callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
1491 ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)));
1492 xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL);
1497 * send a message asynchronously
1501 IN Asr_softc_t * sc,
1502 IN PI2O_MESSAGE_FRAME Message)
1504 OUT U32 MessageOffset;
1505 union asr_ccb * ccb;
1507 debug_asr_printf ("Host Command Dump:\n");
1508 debug_asr_dump_message (Message);
1510 ccb = (union asr_ccb *)(long)
1511 I2O_MESSAGE_FRAME_getInitiatorContext64(Message);
1513 if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) {
1514 bcopy (Message, sc->ha_Fvirt + MessageOffset,
1515 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
1517 ASR_ccbAdd (sc, ccb);
1519 /* Post the command */
1520 sc->ha_Virt->ToFIFO = MessageOffset;
1522 if (ASR_getBlinkLedCode(sc)) {
1524 * Unlikely we can do anything if we can't grab a
1525 * message frame :-(, but lets give it a try.
1527 (void)ASR_reset (sc);
1530 return (MessageOffset);
1534 /* Simple Scatter Gather elements */
1535 #define SG(SGL,Index,Flags,Buffer,Size) \
1536 I2O_FLAGS_COUNT_setCount( \
1537 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1539 I2O_FLAGS_COUNT_setFlags( \
1540 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1541 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \
1542 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \
1543 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \
1544 (Buffer == NULL) ? NULL : KVTOPHYS(Buffer))
1547 * Retrieve Parameter Group.
1548 * Buffer must be allocated using defAlignLong macro.
1552 IN Asr_softc_t * sc,
1556 IN unsigned BufferSize)
1558 struct paramGetMessage {
1559 I2O_UTIL_PARAMS_GET_MESSAGE M;
1561 sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)];
1563 I2O_PARAM_OPERATIONS_LIST_HEADER Header;
1564 I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1];
1567 defAlignLong(struct paramGetMessage, Message);
1568 struct Operations * Operations_Ptr;
1569 I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr;
1570 struct ParamBuffer {
1571 I2O_PARAM_RESULTS_LIST_HEADER Header;
1572 I2O_PARAM_READ_OPERATION_RESULT Read;
1576 Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message,
1577 sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1578 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1579 Operations_Ptr = (struct Operations *)((char *)Message_Ptr
1580 + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1581 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1582 bzero ((void *)Operations_Ptr, sizeof(struct Operations));
1583 I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount(
1584 &(Operations_Ptr->Header), 1);
1585 I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation(
1586 &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET);
1587 I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount(
1588 &(Operations_Ptr->Template[0]), 0xFFFF);
1589 I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber(
1590 &(Operations_Ptr->Template[0]), Group);
1591 bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)),
1594 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1596 + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1597 / sizeof(U32)) << 4));
1598 I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame),
1600 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
1601 I2O_UTIL_PARAMS_GET);
1603 * Set up the buffers as scatter gather elements.
1605 SG(&(Message_Ptr->SGL), 0,
1606 I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER,
1607 Operations_Ptr, sizeof(struct Operations));
1608 SG(&(Message_Ptr->SGL), 1,
1609 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
1610 Buffer_Ptr, BufferSize);
1612 if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP)
1613 && (Buffer_Ptr->Header.ResultCount)) {
1614 return ((void *)(Buffer_Ptr->Info));
1616 return ((void *)NULL);
1617 } /* ASR_getParams */
1620 * Acquire the LCT information.
1624 INOUT Asr_softc_t * sc)
1626 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
1627 PI2O_SGE_SIMPLE_ELEMENT sg;
1628 int MessageSizeInBytes;
1632 PI2O_LCT_ENTRY Entry;
1635 * sc value assumed valid
1637 MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)
1638 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT);
1639 if ((Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)kmalloc (
1640 MessageSizeInBytes, M_TEMP, M_WAITOK))
1641 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1644 (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes);
1645 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1647 (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1648 / sizeof(U32)) << 4)));
1649 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
1650 I2O_EXEC_LCT_NOTIFY);
1651 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
1652 I2O_CLASS_MATCH_ANYCLASS);
1654 * Call the LCT table to determine the number of device entries
1655 * to reserve space for.
1657 SG(&(Message_Ptr->SGL), 0,
1658 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table,
1661 * since this code is reused in several systems, code efficiency
1662 * is greater by using a shift operation rather than a divide by
1663 * sizeof(u_int32_t).
1665 I2O_LCT_setTableSize(&Table,
1666 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1667 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1669 * Determine the size of the LCT table.
1672 kfree (sc->ha_LCT, M_TEMP);
1675 * kmalloc only generates contiguous memory when less than a
1676 * page is expected. We must break the request up into an SG list ...
1678 if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <=
1679 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)))
1680 || (len > (128 * 1024))) { /* Arbitrary */
1681 kfree (Message_Ptr, M_TEMP);
1684 if ((sc->ha_LCT = (PI2O_LCT)kmalloc (len, M_TEMP, M_WAITOK))
1685 == (PI2O_LCT)NULL) {
1686 kfree (Message_Ptr, M_TEMP);
1690 * since this code is reused in several systems, code efficiency
1691 * is greater by using a shift operation rather than a divide by
1692 * sizeof(u_int32_t).
1694 I2O_LCT_setTableSize(sc->ha_LCT,
1695 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1697 * Convert the access to the LCT table into a SG list.
1699 sg = Message_Ptr->SGL.u.Simple;
1700 v = (caddr_t)(sc->ha_LCT);
1702 int next, base, span;
1705 next = base = KVTOPHYS(v);
1706 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
1708 /* How far can we go contiguously */
1709 while ((len > 0) && (base == next)) {
1712 next = trunc_page(base) + PAGE_SIZE;
1723 /* Construct the Flags */
1724 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
1726 int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT;
1728 rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT
1729 | I2O_SGL_FLAGS_LAST_ELEMENT
1730 | I2O_SGL_FLAGS_END_OF_BUFFER);
1732 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw);
1740 * Incrementing requires resizing of the packet.
1743 MessageSizeInBytes += sizeof(*sg);
1744 I2O_MESSAGE_FRAME_setMessageSize(
1745 &(Message_Ptr->StdMessageFrame),
1746 I2O_MESSAGE_FRAME_getMessageSize(
1747 &(Message_Ptr->StdMessageFrame))
1748 + (sizeof(*sg) / sizeof(U32)));
1750 PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr;
1752 if ((NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)
1753 kmalloc (MessageSizeInBytes, M_TEMP, M_WAITOK))
1754 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1755 kfree (sc->ha_LCT, M_TEMP);
1756 sc->ha_LCT = (PI2O_LCT)NULL;
1757 kfree (Message_Ptr, M_TEMP);
1760 span = ((caddr_t)sg) - (caddr_t)Message_Ptr;
1761 bcopy ((caddr_t)Message_Ptr,
1762 (caddr_t)NewMessage_Ptr, span);
1763 kfree (Message_Ptr, M_TEMP);
1764 sg = (PI2O_SGE_SIMPLE_ELEMENT)
1765 (((caddr_t)NewMessage_Ptr) + span);
1766 Message_Ptr = NewMessage_Ptr;
1771 retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1772 kfree (Message_Ptr, M_TEMP);
1773 if (retval != CAM_REQ_CMP) {
1777 /* If the LCT table grew, lets truncate accesses */
1778 if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) {
1779 I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table));
1781 for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY)
1782 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1784 Entry->le_type = I2O_UNKNOWN;
1785 switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) {
1787 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
1788 Entry->le_type = I2O_BSA;
1791 case I2O_CLASS_SCSI_PERIPHERAL:
1792 Entry->le_type = I2O_SCSI;
1795 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
1796 Entry->le_type = I2O_FCA;
1799 case I2O_CLASS_BUS_ADAPTER_PORT:
1800 Entry->le_type = I2O_PORT | I2O_SCSI;
1802 case I2O_CLASS_FIBRE_CHANNEL_PORT:
1803 if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) ==
1804 I2O_CLASS_FIBRE_CHANNEL_PORT) {
1805 Entry->le_type = I2O_PORT | I2O_FCA;
1807 { struct ControllerInfo {
1808 I2O_PARAM_RESULTS_LIST_HEADER Header;
1809 I2O_PARAM_READ_OPERATION_RESULT Read;
1810 I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1812 defAlignLong(struct ControllerInfo, Buffer);
1813 PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1815 Entry->le_bus = 0xff;
1816 Entry->le_target = 0xff;
1817 Entry->le_lun = 0xff;
1819 if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)
1821 I2O_LCT_ENTRY_getLocalTID(Entry),
1822 I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO,
1823 Buffer, sizeof(struct ControllerInfo)))
1824 == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) {
1828 = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID(
1835 { struct DeviceInfo {
1836 I2O_PARAM_RESULTS_LIST_HEADER Header;
1837 I2O_PARAM_READ_OPERATION_RESULT Read;
1838 I2O_DPT_DEVICE_INFO_SCALAR Info;
1840 defAlignLong (struct DeviceInfo, Buffer);
1841 PI2O_DPT_DEVICE_INFO_SCALAR Info;
1843 Entry->le_bus = 0xff;
1844 Entry->le_target = 0xff;
1845 Entry->le_lun = 0xff;
1847 if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR)
1849 I2O_LCT_ENTRY_getLocalTID(Entry),
1850 I2O_DPT_DEVICE_INFO_GROUP_NO,
1851 Buffer, sizeof(struct DeviceInfo)))
1852 == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) {
1856 |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info);
1858 = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info);
1859 if ((Entry->le_bus > sc->ha_MaxBus)
1860 && (Entry->le_bus <= MAX_CHANNEL)) {
1861 sc->ha_MaxBus = Entry->le_bus;
1864 = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info);
1866 = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info);
1870 * A zero return value indicates success.
1873 } /* ASR_acquireLct */
1876 * Initialize a message frame.
1877 * We assume that the CDB has already been set up, so all we do here is
1878 * generate the Scatter Gather list.
1880 STATIC INLINE PI2O_MESSAGE_FRAME
1882 IN union asr_ccb * ccb,
1883 OUT PI2O_MESSAGE_FRAME Message)
1885 int next, span, base, rw;
1886 OUT PI2O_MESSAGE_FRAME Message_Ptr;
1887 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
1888 PI2O_SGE_SIMPLE_ELEMENT sg;
1890 vm_size_t size, len;
1893 /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */
1894 bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message),
1895 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)));
1898 int target = ccb->ccb_h.target_id;
1899 int lun = ccb->ccb_h.target_lun;
1900 int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
1903 if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) {
1904 PI2O_LCT_ENTRY Device;
1907 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
1908 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1910 if ((Device->le_type != I2O_UNKNOWN)
1911 && (Device->le_bus == bus)
1912 && (Device->le_target == target)
1913 && (Device->le_lun == lun)
1914 && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) {
1915 TID = I2O_LCT_ENTRY_getLocalTID(Device);
1916 ASR_setTid (sc, Device->le_bus,
1917 Device->le_target, Device->le_lun,
1923 if (TID == (tid_t)0) {
1924 return ((PI2O_MESSAGE_FRAME)NULL);
1926 I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID);
1927 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(
1928 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID);
1930 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 |
1931 (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1932 / sizeof(U32)) << 4));
1933 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
1934 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
1935 - sizeof(I2O_SG_ELEMENT)) / sizeof(U32));
1936 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
1937 I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE);
1938 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
1939 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC);
1940 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
1941 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
1942 I2O_SCB_FLAG_ENABLE_DISCONNECT
1943 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
1944 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
1946 * We do not need any (optional byteswapping) method access to
1947 * the Initiator & Transaction context field.
1949 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
1951 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
1952 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID);
1956 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(
1957 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len);
1958 bcopy (&(ccb->csio.cdb_io),
1959 ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len);
1962 * Given a buffer describing a transfer, set up a scatter/gather map
1963 * in a ccb to map that SCSI transfer.
1966 rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR;
1968 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
1969 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
1970 (ccb->csio.dxfer_len)
1971 ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE
1972 | I2O_SCB_FLAG_ENABLE_DISCONNECT
1973 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
1974 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)
1975 : (I2O_SCB_FLAG_XFER_FROM_DEVICE
1976 | I2O_SCB_FLAG_ENABLE_DISCONNECT
1977 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
1978 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER))
1979 : (I2O_SCB_FLAG_ENABLE_DISCONNECT
1980 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
1981 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
1984 * Given a transfer described by a `data', fill in the SG list.
1986 sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0];
1988 len = ccb->csio.dxfer_len;
1989 v = ccb->csio.data_ptr;
1990 ASSERT (ccb->csio.dxfer_len >= 0);
1991 MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr);
1992 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
1993 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len);
1994 while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
1995 Message_Ptr)->SGL.u.Simple[SG_SIZE])) {
1997 next = base = KVTOPHYS(v);
1998 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
2000 /* How far can we go contiguously */
2001 while ((len > 0) && (base == next)) {
2002 next = trunc_page(base) + PAGE_SIZE;
2013 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
2015 rw |= I2O_SGL_FLAGS_LAST_ELEMENT;
2017 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount),
2018 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw);
2020 MessageSize += sizeof(*sg) / sizeof(U32);
2022 /* We always do the request sense ... */
2023 if ((span = ccb->csio.sense_len) == 0) {
2024 span = sizeof(ccb->csio.sense_data);
2026 SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2027 &(ccb->csio.sense_data), span);
2028 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
2029 MessageSize + (sizeof(*sg) / sizeof(U32)));
2030 return (Message_Ptr);
2031 } /* ASR_init_message */
2034 * Reset the adapter.
2038 INOUT Asr_softc_t * sc)
2040 struct initOutBoundMessage {
2041 I2O_EXEC_OUTBOUND_INIT_MESSAGE M;
2044 defAlignLong(struct initOutBoundMessage,Message);
2045 PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr;
2046 OUT U32 * volatile Reply_Ptr;
2050 * Build up our copy of the Message.
2052 Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message,
2053 sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE));
2054 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2055 I2O_EXEC_OUTBOUND_INIT);
2056 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE);
2057 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr,
2058 sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME));
2060 * Reset the Reply Status
2062 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
2063 + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0;
2064 SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr,
2067 * Send the Message out
2069 if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
2073 * Wait for a response (Poll).
2075 while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED);
2077 * Re-enable the interrupts.
2079 sc->ha_Virt->Mask = Old;
2081 * Populate the outbound table.
2083 if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2085 /* Allocate the reply frames */
2086 size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2087 * sc->ha_Msgs_Count;
2090 * contigmalloc only works reliably at
2091 * initialization time.
2093 if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2094 contigmalloc (size, M_DEVBUF, M_WAITOK, 0ul,
2095 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul))
2096 != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2097 (void)bzero ((char *)sc->ha_Msgs, size);
2098 sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs);
2102 /* Initialize the outbound FIFO */
2103 if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL)
2104 for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys;
2106 sc->ha_Virt->FromFIFO = addr;
2107 addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME);
2109 return (*Reply_Ptr);
2112 } /* ASR_initOutBound */
2115 * Set the system table
2119 IN Asr_softc_t * sc)
2121 PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr;
2122 PI2O_SET_SYSTAB_HEADER SystemTable;
2124 PI2O_SGE_SIMPLE_ELEMENT sg;
2127 if ((SystemTable = (PI2O_SET_SYSTAB_HEADER)kmalloc (
2128 sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK))
2129 == (PI2O_SET_SYSTAB_HEADER)NULL) {
2132 bzero (SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2133 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2134 ++SystemTable->NumberEntries;
2136 if ((Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)kmalloc (
2137 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2138 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)),
2139 M_TEMP, M_WAITOK)) == (PI2O_EXEC_SYS_TAB_SET_MESSAGE)NULL) {
2140 kfree (SystemTable, M_TEMP);
2143 (void)ASR_fillMessage((char *)Message_Ptr,
2144 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2145 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)));
2146 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2148 (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2149 / sizeof(U32)) << 4)));
2150 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2151 I2O_EXEC_SYS_TAB_SET);
2153 * Call the LCT table to determine the number of device entries
2154 * to reserve space for.
2155 * since this code is reused in several systems, code efficiency
2156 * is greater by using a shift operation rather than a divide by
2157 * sizeof(u_int32_t).
2159 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
2160 + ((I2O_MESSAGE_FRAME_getVersionOffset(
2161 &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2));
2162 SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2164 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2167 ? (I2O_SGL_FLAGS_DIR)
2168 : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)),
2169 &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable));
2172 SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2173 SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT
2174 | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2175 retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2176 kfree (Message_Ptr, M_TEMP);
2177 kfree (SystemTable, M_TEMP);
2179 } /* ASR_setSysTab */
2183 INOUT Asr_softc_t * sc)
2185 defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message);
2186 I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr;
2189 I2O_HRT_ENTRY Entry[MAX_CHANNEL];
2191 u_int8_t NumberOfEntries;
2192 PI2O_HRT_ENTRY Entry;
2194 bzero ((void *)&Hrt, sizeof (Hrt));
2195 Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message,
2196 sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2197 + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2198 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2200 + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2201 / sizeof(U32)) << 4)));
2202 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
2206 * Set up the buffers as scatter gather elements.
2208 SG(&(Message_Ptr->SGL), 0,
2209 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2211 if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) {
2214 if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header))
2215 > (MAX_CHANNEL + 1)) {
2216 NumberOfEntries = MAX_CHANNEL + 1;
2218 for (Entry = Hrt.Header.HRTEntry;
2219 NumberOfEntries != 0;
2220 ++Entry, --NumberOfEntries) {
2221 PI2O_LCT_ENTRY Device;
2223 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2224 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2226 if (I2O_LCT_ENTRY_getLocalTID(Device)
2227 == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) {
2228 Device->le_bus = I2O_HRT_ENTRY_getAdapterID(
2230 if ((Device->le_bus > sc->ha_MaxBus)
2231 && (Device->le_bus <= MAX_CHANNEL)) {
2232 sc->ha_MaxBus = Device->le_bus;
2238 } /* ASR_acquireHrt */
2241 * Enable the adapter.
2245 IN Asr_softc_t * sc)
2247 defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message);
2248 PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr;
2250 Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message,
2251 sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE));
2252 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2253 I2O_EXEC_SYS_ENABLE);
2254 return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0);
2255 } /* ASR_enableSys */
2258 * Perform the stages necessary to initialize the adapter
2262 IN Asr_softc_t * sc)
2264 return ((ASR_initOutBound(sc) == 0)
2265 || (ASR_setSysTab(sc) != CAM_REQ_CMP)
2266 || (ASR_enableSys(sc) != CAM_REQ_CMP));
2270 * Send a Synchronize Cache command to the target device.
2274 IN Asr_softc_t * sc,
2282 * We will not synchronize the device when there are outstanding
2283 * commands issued by the OS (this is due to a locked up device,
2284 * as the OS normally would flush all outstanding commands before
2285 * issuing a shutdown or an adapter reset).
2287 if ((sc != (Asr_softc_t *)NULL)
2288 && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL)
2289 && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1)
2290 && (TID != (tid_t)0)) {
2291 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
2292 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
2295 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
2296 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2297 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2299 I2O_MESSAGE_FRAME_setVersionOffset(
2300 (PI2O_MESSAGE_FRAME)Message_Ptr,
2302 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2303 - sizeof(I2O_SG_ELEMENT))
2304 / sizeof(U32)) << 4));
2305 I2O_MESSAGE_FRAME_setMessageSize(
2306 (PI2O_MESSAGE_FRAME)Message_Ptr,
2307 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2308 - sizeof(I2O_SG_ELEMENT))
2310 I2O_MESSAGE_FRAME_setInitiatorAddress (
2311 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
2312 I2O_MESSAGE_FRAME_setFunction(
2313 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
2314 I2O_MESSAGE_FRAME_setTargetAddress(
2315 (PI2O_MESSAGE_FRAME)Message_Ptr, TID);
2316 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2317 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2319 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID);
2320 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2321 I2O_SCB_FLAG_ENABLE_DISCONNECT
2322 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2323 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2324 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2325 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2326 DPT_ORGANIZATION_ID);
2327 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
2328 Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE;
2329 Message_Ptr->CDB[1] = (lun << 5);
2331 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2332 (I2O_SCB_FLAG_XFER_FROM_DEVICE
2333 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2334 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2335 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2337 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2344 IN Asr_softc_t * sc)
2346 int bus, target, lun;
2348 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
2349 for (target = 0; target <= sc->ha_MaxId; ++target) {
2350 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
2351 ASR_sync(sc,bus,target,lun);
2358 * Reset the HBA, targets and BUS.
2359 * Currently this resets *all* the SCSI busses.
2363 IN Asr_softc_t * sc)
2365 ASR_synchronize (sc);
2366 (void)ASR_reset (sc);
2367 } /* asr_hbareset */
2370 * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP
2371 * limit and a reduction in error checking (in the pre 4.0 case).
2376 IN Asr_softc_t * sc)
2382 * I2O specification says we must find first *memory* mapped BAR
2384 for (rid = PCIR_MAPS;
2385 rid < (PCIR_MAPS + 4 * sizeof(u_int32_t));
2386 rid += sizeof(u_int32_t)) {
2387 p = pci_read_config(tag, rid, sizeof(p));
2395 if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2398 p = pci_read_config(tag, rid, sizeof(p));
2399 pci_write_config(tag, rid, -1, sizeof(p));
2400 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2401 pci_write_config(tag, rid, p, sizeof(p));
2406 * The 2005S Zero Channel RAID solution is not a perfect PCI
2407 * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once
2408 * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to
2409 * BAR0+2MB and sets it's size to 2MB. The IOP registers are
2410 * accessible via BAR0, the messaging registers are accessible
2411 * via BAR1. If the subdevice code is 50 to 59 decimal.
2413 s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s));
2414 if (s != 0xA5111044) {
2415 s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s));
2416 if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0)
2417 && (ADPTDOMINATOR_SUB_ID_START <= s)
2418 && (s <= ADPTDOMINATOR_SUB_ID_END)) {
2419 l = MAX_MAP; /* Conjoined BAR Raptor Daptor */
2423 sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2424 p, p + l, l, RF_ACTIVE);
2425 if (sc->ha_mem_res == (struct resource *)NULL) {
2428 sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res);
2429 if (sc->ha_Base == (void *)NULL) {
2432 sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res);
2433 if (s == 0xA5111044) { /* Split BAR Raptor Daptor */
2434 if ((rid += sizeof(u_int32_t))
2435 >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2438 p = pci_read_config(tag, rid, sizeof(p));
2439 pci_write_config(tag, rid, -1, sizeof(p));
2440 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2441 pci_write_config(tag, rid, p, sizeof(p));
2446 sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2447 p, p + l, l, RF_ACTIVE);
2448 if (sc->ha_mes_res == (struct resource *)NULL) {
2451 if ((void *)rman_get_start(sc->ha_mes_res) == (void *)NULL) {
2454 sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res);
2456 sc->ha_Fvirt = (U8 *)(sc->ha_Virt);
2459 } /* asr_pci_map_mem */
2462 * A simplified copy of the real pci_map_int with additional
2463 * registration requirements.
2468 IN Asr_softc_t * sc)
2473 sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid,
2474 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2475 if (sc->ha_irq_res == (struct resource *)NULL) {
2478 error = bus_setup_intr(tag, sc->ha_irq_res, 0,
2479 (driver_intr_t *)asr_intr, (void *)sc,
2480 &(sc->ha_intr), NULL);
2484 sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char));
2486 } /* asr_pci_map_int */
2489 * Attach the devices, and virtual devices to the driver list.
2492 asr_attach (ATTACH_ARGS)
2495 struct scsi_inquiry_data * iq;
2498 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_INTWAIT);
2499 if (Asr_softc == (Asr_softc_t *)NULL) {
2501 * Fixup the OS revision as saved in the dptsig for the
2502 * engine (dptioctl.h) to pick up.
2504 bcopy (osrelease, &ASR_sig.dsDescription[16], 5);
2505 kprintf ("asr%d: major=%d\n", unit, asr_ops.head.maj);
2508 * Initialize the software structure
2510 bzero (sc, sizeof(*sc));
2511 LIST_INIT(&(sc->ha_ccb));
2512 /* Link us into the HA list */
2516 for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next));
2520 PI2O_EXEC_STATUS_GET_REPLY status;
2524 * This is the real McCoy!
2526 if (!asr_pci_map_mem(tag, sc)) {
2527 kprintf ("asr%d: could not map memory\n", unit);
2528 ATTACH_RETURN(ENXIO);
2530 /* Enable if not formerly enabled */
2531 pci_write_config (tag, PCIR_COMMAND,
2532 pci_read_config (tag, PCIR_COMMAND, sizeof(char))
2533 | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char));
2534 /* Knowledge is power, responsibility is direct */
2536 struct pci_devinfo {
2537 STAILQ_ENTRY(pci_devinfo) pci_links;
2538 struct resource_list resources;
2540 } * dinfo = device_get_ivars(tag);
2541 sc->ha_pciBusNum = dinfo->cfg.bus;
2542 sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3)
2545 /* Check if the device is there? */
2546 if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0)
2547 || ((status = (PI2O_EXEC_STATUS_GET_REPLY)kmalloc (
2548 sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK))
2549 == (PI2O_EXEC_STATUS_GET_REPLY)NULL)
2550 || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) {
2551 kprintf ("asr%d: could not initialize hardware\n", unit);
2552 ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */
2554 sc->ha_SystemTable.OrganizationID = status->OrganizationID;
2555 sc->ha_SystemTable.IOP_ID = status->IOP_ID;
2556 sc->ha_SystemTable.I2oVersion = status->I2oVersion;
2557 sc->ha_SystemTable.IopState = status->IopState;
2558 sc->ha_SystemTable.MessengerType = status->MessengerType;
2559 sc->ha_SystemTable.InboundMessageFrameSize
2560 = status->InboundMFrameSize;
2561 sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow
2562 = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO));
2564 if (!asr_pci_map_int(tag, (void *)sc)) {
2565 kprintf ("asr%d: could not map interrupt\n", unit);
2566 ATTACH_RETURN(ENXIO);
2569 /* Adjust the maximim inbound count */
2570 if (((sc->ha_QueueSize
2571 = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status))
2573 || (sc->ha_QueueSize == 0)) {
2574 sc->ha_QueueSize = MAX_INBOUND;
2577 /* Adjust the maximum outbound count */
2578 if (((sc->ha_Msgs_Count
2579 = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status))
2581 || (sc->ha_Msgs_Count == 0)) {
2582 sc->ha_Msgs_Count = MAX_OUTBOUND;
2584 if (sc->ha_Msgs_Count > sc->ha_QueueSize) {
2585 sc->ha_Msgs_Count = sc->ha_QueueSize;
2588 /* Adjust the maximum SG size to adapter */
2589 if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize(
2590 status) << 2)) > MAX_INBOUND_SIZE) {
2591 size = MAX_INBOUND_SIZE;
2593 kfree (status, M_TEMP);
2594 sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2595 + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT);
2599 * Only do a bus/HBA reset on the first time through. On this
2600 * first time through, we do not send a flush to the devices.
2602 if (ASR_init(sc) == 0) {
2604 I2O_PARAM_RESULTS_LIST_HEADER Header;
2605 I2O_PARAM_READ_OPERATION_RESULT Read;
2606 I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2608 defAlignLong (struct BufferInfo, Buffer);
2609 PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2610 # define FW_DEBUG_BLED_OFFSET 8
2612 if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)
2613 ASR_getParams(sc, 0,
2614 I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO,
2615 Buffer, sizeof(struct BufferInfo)))
2616 != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) {
2617 sc->ha_blinkLED = sc->ha_Fvirt
2618 + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info)
2619 + FW_DEBUG_BLED_OFFSET;
2621 if (ASR_acquireLct(sc) == 0) {
2622 (void)ASR_acquireHrt(sc);
2625 kprintf ("asr%d: failed to initialize\n", unit);
2626 ATTACH_RETURN(ENXIO);
2629 * Add in additional probe responses for more channels. We
2630 * are reusing the variable `target' for a channel loop counter.
2631 * Done here because of we need both the acquireLct and
2634 { PI2O_LCT_ENTRY Device;
2636 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2637 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2639 if (Device->le_type == I2O_UNKNOWN) {
2642 if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) {
2643 if (Device->le_target > sc->ha_MaxId) {
2644 sc->ha_MaxId = Device->le_target;
2646 if (Device->le_lun > sc->ha_MaxLun) {
2647 sc->ha_MaxLun = Device->le_lun;
2650 if (((Device->le_type & I2O_PORT) != 0)
2651 && (Device->le_bus <= MAX_CHANNEL)) {
2652 /* Do not increase MaxId for efficiency */
2653 sc->ha_adapter_target[Device->le_bus]
2654 = Device->le_target;
2661 * Print the HBA model number as inquired from the card.
2664 kprintf ("asr%d:", unit);
2666 if ((iq = (struct scsi_inquiry_data *)kmalloc (
2667 sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK))
2668 != (struct scsi_inquiry_data *)NULL) {
2669 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
2670 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
2673 bzero (iq, sizeof(struct scsi_inquiry_data));
2675 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
2676 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2677 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2679 I2O_MESSAGE_FRAME_setVersionOffset(
2680 (PI2O_MESSAGE_FRAME)Message_Ptr,
2682 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2683 - sizeof(I2O_SG_ELEMENT))
2684 / sizeof(U32)) << 4));
2685 I2O_MESSAGE_FRAME_setMessageSize(
2686 (PI2O_MESSAGE_FRAME)Message_Ptr,
2687 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2688 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT))
2690 I2O_MESSAGE_FRAME_setInitiatorAddress (
2691 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
2692 I2O_MESSAGE_FRAME_setFunction(
2693 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
2694 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2695 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2697 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2698 I2O_SCB_FLAG_ENABLE_DISCONNECT
2699 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2700 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2701 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1);
2702 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2703 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2704 DPT_ORGANIZATION_ID);
2705 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
2706 Message_Ptr->CDB[0] = INQUIRY;
2707 Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data);
2708 if (Message_Ptr->CDB[4] == 0) {
2709 Message_Ptr->CDB[4] = 255;
2712 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2713 (I2O_SCB_FLAG_XFER_FROM_DEVICE
2714 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2715 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2716 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2718 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
2719 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2720 sizeof(struct scsi_inquiry_data));
2721 SG(&(Message_Ptr->SGL), 0,
2722 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2723 iq, sizeof(struct scsi_inquiry_data));
2724 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2726 if (iq->vendor[0] && (iq->vendor[0] != ' ')) {
2728 ASR_prstring (iq->vendor, 8);
2731 if (iq->product[0] && (iq->product[0] != ' ')) {
2733 ASR_prstring (iq->product, 16);
2736 if (iq->revision[0] && (iq->revision[0] != ' ')) {
2737 kprintf (" FW Rev. ");
2738 ASR_prstring (iq->revision, 4);
2741 kfree ((caddr_t)iq, M_TEMP);
2746 kprintf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1,
2747 (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize);
2750 * fill in the prototype cam_path.
2754 union asr_ccb * ccb;
2756 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
2757 kprintf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit);
2758 ATTACH_RETURN(ENOMEM);
2760 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
2761 int QueueSize = sc->ha_QueueSize;
2763 if (QueueSize > MAX_INBOUND) {
2764 QueueSize = MAX_INBOUND;
2768 * Construct our first channel SIM entry
2770 sc->ha_sim[bus] = cam_sim_alloc(
2771 asr_action, asr_poll, "asr", sc,
2772 unit, 1, QueueSize, NULL);
2773 if (sc->ha_sim[bus] == NULL)
2776 if (xpt_bus_register(sc->ha_sim[bus], bus)
2778 cam_sim_free(sc->ha_sim[bus]);
2779 sc->ha_sim[bus] = NULL;
2783 if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL,
2784 cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD,
2785 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2787 cam_sim_path(sc->ha_sim[bus]));
2788 cam_sim_free(sc->ha_sim[bus]);
2789 sc->ha_sim[bus] = NULL;
2796 * Generate the device node information
2798 make_dev(&asr_ops, unit, 0, 0, S_IRWXU, "rasr%d", unit);
2804 IN struct cam_sim *sim)
2806 asr_intr(cam_sim_softc(sim));
2811 IN struct cam_sim * sim,
2814 struct Asr_softc * sc;
2816 debug_asr_printf ("asr_action(%lx,%lx{%x})\n",
2817 (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code);
2819 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n"));
2821 ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim);
2823 switch (ccb->ccb_h.func_code) {
2825 /* Common cases first */
2826 case XPT_SCSI_IO: /* Execute the requested I/O operation */
2829 char M[MAX_INBOUND_SIZE];
2831 defAlignLong(struct Message,Message);
2832 PI2O_MESSAGE_FRAME Message_Ptr;
2834 /* Reject incoming commands while we are resetting the card */
2835 if (sc->ha_in_reset != HA_OPERATIONAL) {
2836 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2837 if (sc->ha_in_reset >= HA_OFF_LINE) {
2838 /* HBA is now off-line */
2839 ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
2841 /* HBA currently resetting, try again later. */
2842 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2844 debug_asr_cmd_printf (" e\n");
2846 debug_asr_cmd_printf (" q\n");
2849 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
2851 "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n",
2852 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
2853 ccb->csio.cdb_io.cdb_bytes[0],
2855 ccb->ccb_h.target_id,
2856 ccb->ccb_h.target_lun);
2858 debug_asr_cmd_printf ("(%d,%d,%d,%d)",
2861 ccb->ccb_h.target_id,
2862 ccb->ccb_h.target_lun);
2863 debug_asr_cmd_dump_ccb(ccb);
2865 if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb,
2866 (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) {
2867 debug_asr_cmd2_printf ("TID=%x:\n",
2868 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID(
2869 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr));
2870 debug_asr_cmd2_dump_message(Message_Ptr);
2871 debug_asr_cmd1_printf (" q");
2873 if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) {
2874 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2875 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2876 debug_asr_cmd_printf (" E\n");
2879 debug_asr_cmd_printf (" Q\n");
2883 * We will get here if there is no valid TID for the device
2884 * referenced in the scsi command packet.
2886 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2887 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
2888 debug_asr_cmd_printf (" B\n");
2893 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
2894 /* Rese HBA device ... */
2896 ccb->ccb_h.status = CAM_REQ_CMP;
2900 # if (defined(REPORT_LUNS))
2903 case XPT_ABORT: /* Abort the specified CCB */
2905 ccb->ccb_h.status = CAM_REQ_INVALID;
2909 case XPT_SET_TRAN_SETTINGS:
2911 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2915 case XPT_GET_TRAN_SETTINGS:
2916 /* Get default/user set transfer settings for the target */
2918 struct ccb_trans_settings *cts = &(ccb->cts);
2919 #ifdef CAM_NEW_TRAN_CODE
2920 struct ccb_trans_settings_scsi *scsi =
2921 &cts->proto_specific.scsi;
2922 struct ccb_trans_settings_spi *spi =
2923 &cts->xport_specific.spi;
2925 if (cts->type == CTS_TYPE_USER_SETTINGS) {
2926 cts->protocol = PROTO_SCSI;
2927 cts->protocol_version = SCSI_REV_2;
2928 cts->transport = XPORT_SPI;
2929 cts->transport_version = 2;
2931 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2932 spi->flags = CTS_SPI_FLAGS_DISC_ENB;
2933 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2934 spi->sync_period = 6; /* 40MHz */
2935 spi->sync_offset = 15;
2936 spi->valid = CTS_SPI_VALID_SYNC_RATE
2937 | CTS_SPI_VALID_SYNC_OFFSET
2938 | CTS_SPI_VALID_BUS_WIDTH
2939 | CTS_SPI_VALID_DISC;
2940 scsi->valid = CTS_SCSI_VALID_TQ;
2942 ccb->ccb_h.status = CAM_REQ_CMP;
2944 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2947 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
2948 cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
2949 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2950 cts->sync_period = 6; /* 40MHz */
2951 cts->sync_offset = 15;
2953 cts->valid = CCB_TRANS_SYNC_RATE_VALID
2954 | CCB_TRANS_SYNC_OFFSET_VALID
2955 | CCB_TRANS_BUS_WIDTH_VALID
2956 | CCB_TRANS_DISC_VALID
2957 | CCB_TRANS_TQ_VALID;
2958 ccb->ccb_h.status = CAM_REQ_CMP;
2960 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2967 case XPT_CALC_GEOMETRY:
2969 struct ccb_calc_geometry *ccg;
2971 u_int32_t secs_per_cylinder;
2974 size_mb = ccg->volume_size
2975 / ((1024L * 1024L) / ccg->block_size);
2977 if (size_mb > 4096) {
2979 ccg->secs_per_track = 63;
2980 } else if (size_mb > 2048) {
2982 ccg->secs_per_track = 63;
2983 } else if (size_mb > 1024) {
2985 ccg->secs_per_track = 63;
2988 ccg->secs_per_track = 32;
2990 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2991 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2992 ccb->ccb_h.status = CAM_REQ_CMP;
2997 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
2998 ASR_resetBus (sc, cam_sim_bus(sim));
2999 ccb->ccb_h.status = CAM_REQ_CMP;
3003 case XPT_TERM_IO: /* Terminate the I/O process */
3005 ccb->ccb_h.status = CAM_REQ_INVALID;
3009 case XPT_PATH_INQ: /* Path routing inquiry */
3011 struct ccb_pathinq *cpi = &(ccb->cpi);
3013 cpi->version_num = 1; /* XXX??? */
3014 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
3015 cpi->target_sprt = 0;
3016 /* Not necessary to reset bus, done by HDM initialization */
3017 cpi->hba_misc = PIM_NOBUSRESET;
3018 cpi->hba_eng_cnt = 0;
3019 cpi->max_target = sc->ha_MaxId;
3020 cpi->max_lun = sc->ha_MaxLun;
3021 cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)];
3022 cpi->bus_id = cam_sim_bus(sim);
3023 cpi->base_transfer_speed = 3300;
3024 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
3025 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
3026 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
3027 cpi->unit_number = cam_sim_unit(sim);
3028 cpi->ccb_h.status = CAM_REQ_CMP;
3029 #ifdef CAM_NEW_TRAN_CODE
3030 cpi->transport = XPORT_SPI;
3031 cpi->transport_version = 2;
3032 cpi->protocol = PROTO_SCSI;
3033 cpi->protocol_version = SCSI_REV_2;
3039 ccb->ccb_h.status = CAM_REQ_INVALID;
3047 * Handle processing of current CCB as pointed to by the Status.
3051 IN Asr_softc_t * sc)
3056 sc->ha_Virt->Status & Mask_InterruptsDisabled;
3058 union asr_ccb * ccb;
3060 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3062 if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)
3063 && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) {
3066 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset
3067 - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs));
3069 * We do not need any (optional byteswapping) method access to
3070 * the Initiator context field.
3072 ccb = (union asr_ccb *)(long)
3073 I2O_MESSAGE_FRAME_getInitiatorContext64(
3074 &(Reply->StdReplyFrame.StdMessageFrame));
3075 if (I2O_MESSAGE_FRAME_getMsgFlags(
3076 &(Reply->StdReplyFrame.StdMessageFrame))
3077 & I2O_MESSAGE_FLAGS_FAIL) {
3078 defAlignLong(I2O_UTIL_NOP_MESSAGE,Message);
3079 PI2O_UTIL_NOP_MESSAGE Message_Ptr;
3082 MessageOffset = (u_long)
3083 I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA(
3084 (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply);
3086 * Get the Original Message Frame's address, and get
3087 * it's Transaction Context into our space. (Currently
3088 * unused at original authorship, but better to be
3089 * safe than sorry). Straight copy means that we
3090 * need not concern ourselves with the (optional
3091 * byteswapping) method access.
3093 Reply->StdReplyFrame.TransactionContext
3094 = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME)
3095 (sc->ha_Fvirt + MessageOffset))->TransactionContext;
3097 * For 64 bit machines, we need to reconstruct the
3100 ccb = (union asr_ccb *)(long)
3101 I2O_MESSAGE_FRAME_getInitiatorContext64(
3102 &(Reply->StdReplyFrame.StdMessageFrame));
3104 * Unique error code for command failure.
3106 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3107 &(Reply->StdReplyFrame), (u_int16_t)-2);
3109 * Modify the message frame to contain a NOP and
3110 * re-issue it to the controller.
3112 Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage(
3113 Message, sizeof(I2O_UTIL_NOP_MESSAGE));
3114 # if (I2O_UTIL_NOP != 0)
3115 I2O_MESSAGE_FRAME_setFunction (
3116 &(Message_Ptr->StdMessageFrame),
3120 * Copy the packet out to the Original Message
3122 bcopy ((caddr_t)Message_Ptr,
3123 sc->ha_Fvirt + MessageOffset,
3124 sizeof(I2O_UTIL_NOP_MESSAGE));
3128 sc->ha_Virt->ToFIFO = MessageOffset;
3132 * Asynchronous command with no return requirements,
3133 * and a generic handler for immunity against odd error
3134 * returns from the adapter.
3136 if (ccb == (union asr_ccb *)NULL) {
3138 * Return Reply so that it can be used for the
3141 sc->ha_Virt->FromFIFO = ReplyOffset;
3145 /* Welease Wadjah! (and stop timeouts) */
3146 ASR_ccbRemove (sc, ccb);
3149 I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode(
3150 &(Reply->StdReplyFrame))) {
3152 case I2O_SCSI_DSC_SUCCESS:
3153 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3154 ccb->ccb_h.status |= CAM_REQ_CMP;
3157 case I2O_SCSI_DSC_CHECK_CONDITION:
3158 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3159 ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID;
3162 case I2O_SCSI_DSC_BUSY:
3164 case I2O_SCSI_HBA_DSC_ADAPTER_BUSY:
3166 case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET:
3168 case I2O_SCSI_HBA_DSC_BUS_BUSY:
3169 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3170 ccb->ccb_h.status |= CAM_SCSI_BUSY;
3173 case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT:
3174 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3175 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
3178 case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT:
3180 case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT:
3182 case I2O_SCSI_HBA_DSC_LUN_INVALID:
3184 case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID:
3185 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3186 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
3189 case I2O_SCSI_HBA_DSC_DATA_OVERRUN:
3191 case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR:
3192 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3193 ccb->ccb_h.status |= CAM_DATA_RUN_ERR;
3197 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3198 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
3201 if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) {
3203 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount(
3207 /* Sense data in reply packet */
3208 if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
3209 u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply);
3212 if (size > sizeof(ccb->csio.sense_data)) {
3213 size = sizeof(ccb->csio.sense_data);
3215 if (size > I2O_SCSI_SENSE_DATA_SZ) {
3216 size = I2O_SCSI_SENSE_DATA_SZ;
3218 if ((ccb->csio.sense_len)
3219 && (size > ccb->csio.sense_len)) {
3220 size = ccb->csio.sense_len;
3222 bcopy ((caddr_t)Reply->SenseData,
3223 (caddr_t)&(ccb->csio.sense_data), size);
3228 * Return Reply so that it can be used for the next command
3229 * since we have no more need for it now
3231 sc->ha_Virt->FromFIFO = ReplyOffset;
3233 if (ccb->ccb_h.path) {
3234 xpt_done ((union ccb *)ccb);
3236 wakeup ((caddr_t)ccb);
3242 #undef QueueSize /* Grrrr */
3243 #undef SG_Size /* Grrrr */
3246 * Meant to be included at the bottom of asr.c !!!
3250 * Included here as hard coded. Done because other necessary include
3251 * files utilize C++ comment structures which make them a nuisance to
3252 * included here just to pick up these three typedefs.
3254 typedef U32 DPT_TAG_T;
3255 typedef U32 DPT_MSG_T;
3256 typedef U32 DPT_RTN_T;
3258 #undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */
3259 #include "osd_unix.h"
3261 #define asr_unit(dev) minor(dev)
3263 STATIC INLINE Asr_softc_t *
3267 int unit = asr_unit(dev);
3268 OUT Asr_softc_t * sc = Asr_softc;
3270 while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) {
3276 STATIC u_int8_t ASR_ctlr_held;
3277 #if (!defined(UNREFERENCED_PARAMETER))
3278 # define UNREFERENCED_PARAMETER(x) (void)(x)
3282 asr_open(struct dev_open_args *ap)
3284 cdev_t dev = ap->a_head.a_dev;
3287 if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) {
3291 if (ASR_ctlr_held) {
3293 } else if ((error = suser_cred(ap->a_cred, 0)) == 0) {
3301 asr_close(struct dev_close_args *ap)
3308 /*-------------------------------------------------------------------------*/
3309 /* Function ASR_queue_i */
3310 /*-------------------------------------------------------------------------*/
3311 /* The Parameters Passed To This Function Are : */
3312 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
3313 /* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */
3314 /* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */
3316 /* This Function Will Take The User Request Packet And Convert It To An */
3317 /* I2O MSG And Send It Off To The Adapter. */
3319 /* Return : 0 For OK, Error Code Otherwise */
3320 /*-------------------------------------------------------------------------*/
3323 IN Asr_softc_t * sc,
3324 INOUT PI2O_MESSAGE_FRAME Packet)
3326 union asr_ccb * ccb;
3327 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3328 PI2O_MESSAGE_FRAME Message_Ptr;
3329 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr;
3330 int MessageSizeInBytes;
3331 int ReplySizeInBytes;
3334 /* Scatter Gather buffer list */
3335 struct ioctlSgList_S {
3336 SLIST_ENTRY(ioctlSgList_S) link;
3338 I2O_FLAGS_COUNT FlagsCount;
3339 char KernelSpace[sizeof(long)];
3341 /* Generates a `first' entry */
3342 SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList;
3344 if (ASR_getBlinkLedCode(sc)) {
3345 debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n",
3346 ASR_getBlinkLedCode(sc));
3349 /* Copy in the message into a local allocation */
3350 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)kmalloc (
3351 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
3352 == (PI2O_MESSAGE_FRAME)NULL) {
3353 debug_usr_cmd_printf (
3354 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
3357 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
3358 sizeof(I2O_MESSAGE_FRAME))) != 0) {
3359 kfree (Message_Ptr, M_TEMP);
3360 debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error);
3363 /* Acquire information to determine type of packet */
3364 MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2);
3365 /* The offset of the reply information within the user packet */
3366 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet
3367 + MessageSizeInBytes);
3369 /* Check if the message is a synchronous initialization command */
3370 s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr);
3371 kfree (Message_Ptr, M_TEMP);
3374 case I2O_EXEC_IOP_RESET:
3377 status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt);
3378 ReplySizeInBytes = sizeof(status);
3379 debug_usr_cmd_printf ("resetIOP done\n");
3380 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3384 case I2O_EXEC_STATUS_GET:
3385 { I2O_EXEC_STATUS_GET_REPLY status;
3387 if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status)
3388 == (PI2O_EXEC_STATUS_GET_REPLY)NULL) {
3389 debug_usr_cmd_printf ("getStatus failed\n");
3392 ReplySizeInBytes = sizeof(status);
3393 debug_usr_cmd_printf ("getStatus done\n");
3394 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3398 case I2O_EXEC_OUTBOUND_INIT:
3401 status = ASR_initOutBound(sc);
3402 ReplySizeInBytes = sizeof(status);
3403 debug_usr_cmd_printf ("intOutBound done\n");
3404 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3409 /* Determine if the message size is valid */
3410 if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME))
3411 || (MAX_INBOUND_SIZE < MessageSizeInBytes)) {
3412 debug_usr_cmd_printf ("Packet size %d incorrect\n",
3413 MessageSizeInBytes);
3417 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)kmalloc (MessageSizeInBytes,
3418 M_TEMP, M_WAITOK)) == (PI2O_MESSAGE_FRAME)NULL) {
3419 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
3420 MessageSizeInBytes);
3423 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
3424 MessageSizeInBytes)) != 0) {
3425 kfree (Message_Ptr, M_TEMP);
3426 debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n",
3427 MessageSizeInBytes, error);
3431 /* Check the size of the reply frame, and start constructing */
3433 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)kmalloc (
3434 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
3435 == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
3436 kfree (Message_Ptr, M_TEMP);
3437 debug_usr_cmd_printf (
3438 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
3441 if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr,
3442 sizeof(I2O_MESSAGE_FRAME))) != 0) {
3443 kfree (Reply_Ptr, M_TEMP);
3444 kfree (Message_Ptr, M_TEMP);
3445 debug_usr_cmd_printf (
3446 "Failed to copy in reply frame, errno=%d\n",
3450 ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(
3451 &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2);
3452 kfree (Reply_Ptr, M_TEMP);
3453 if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) {
3454 kfree (Message_Ptr, M_TEMP);
3455 debug_usr_cmd_printf (
3456 "Failed to copy in reply frame[%d], errno=%d\n",
3457 ReplySizeInBytes, error);
3461 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)kmalloc (
3462 ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME))
3464 : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)),
3465 M_TEMP, M_WAITOK)) == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
3466 kfree (Message_Ptr, M_TEMP);
3467 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
3471 (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes);
3472 Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext
3473 = Message_Ptr->InitiatorContext;
3474 Reply_Ptr->StdReplyFrame.TransactionContext
3475 = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext;
3476 I2O_MESSAGE_FRAME_setMsgFlags(
3477 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
3478 I2O_MESSAGE_FRAME_getMsgFlags(
3479 &(Reply_Ptr->StdReplyFrame.StdMessageFrame))
3480 | I2O_MESSAGE_FLAGS_REPLY);
3482 /* Check if the message is a special case command */
3483 switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) {
3484 case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */
3485 if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset(
3486 Message_Ptr) & 0xF0) >> 2)) {
3487 kfree (Message_Ptr, M_TEMP);
3488 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3489 &(Reply_Ptr->StdReplyFrame),
3490 (ASR_setSysTab(sc) != CAM_REQ_CMP));
3491 I2O_MESSAGE_FRAME_setMessageSize(
3492 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
3493 sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME));
3494 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
3496 kfree (Reply_Ptr, M_TEMP);
3501 /* Deal in the general case */
3502 /* First allocate and optionally copy in each scatter gather element */
3503 SLIST_INIT(&sgList);
3504 if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) {
3505 PI2O_SGE_SIMPLE_ELEMENT sg;
3508 * since this code is reused in several systems, code
3509 * efficiency is greater by using a shift operation rather
3510 * than a divide by sizeof(u_int32_t).
3512 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
3513 + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0)
3515 while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr)
3516 + MessageSizeInBytes)) {
3520 if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
3521 & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) {
3525 len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount));
3526 debug_usr_cmd_printf ("SG[%d] = %x[%d]\n",
3527 sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
3528 + ((I2O_MESSAGE_FRAME_getVersionOffset(
3529 Message_Ptr) & 0xF0) >> 2)),
3530 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len);
3532 if ((elm = (struct ioctlSgList_S *)kmalloc (
3533 sizeof(*elm) - sizeof(elm->KernelSpace) + len,
3535 == (struct ioctlSgList_S *)NULL) {
3536 debug_usr_cmd_printf (
3537 "Failed to allocate SG[%d]\n", len);
3541 SLIST_INSERT_HEAD(&sgList, elm, link);
3542 elm->FlagsCount = sg->FlagsCount;
3543 elm->UserSpace = (caddr_t)
3544 (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg));
3545 v = elm->KernelSpace;
3546 /* Copy in outgoing data (DIR bit could be invalid) */
3547 if ((error = copyin (elm->UserSpace, (caddr_t)v, len))
3552 * If the buffer is not contiguous, lets
3553 * break up the scatter/gather entries.
3556 && (sg < (PI2O_SGE_SIMPLE_ELEMENT)
3557 (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) {
3558 int next, base, span;
3561 next = base = KVTOPHYS(v);
3562 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg,
3565 /* How far can we go physically contiguously */
3566 while ((len > 0) && (base == next)) {
3569 next = trunc_page(base) + PAGE_SIZE;
3580 /* Construct the Flags */
3581 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount),
3584 int flags = I2O_FLAGS_COUNT_getFlags(
3585 &(elm->FlagsCount));
3586 /* Any remaining length? */
3589 ~(I2O_SGL_FLAGS_END_OF_BUFFER
3590 | I2O_SGL_FLAGS_LAST_ELEMENT);
3592 I2O_FLAGS_COUNT_setFlags(
3593 &(sg->FlagsCount), flags);
3596 debug_usr_cmd_printf ("sg[%d] = %x[%d]\n",
3597 sg - (PI2O_SGE_SIMPLE_ELEMENT)
3598 ((char *)Message_Ptr
3599 + ((I2O_MESSAGE_FRAME_getVersionOffset(
3600 Message_Ptr) & 0xF0) >> 2)),
3601 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg),
3608 * Incrementing requires resizing of the
3609 * packet, and moving up the existing SG
3613 MessageSizeInBytes += sizeof(*sg);
3614 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
3615 I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)
3616 + (sizeof(*sg) / sizeof(U32)));
3618 PI2O_MESSAGE_FRAME NewMessage_Ptr;
3621 = (PI2O_MESSAGE_FRAME)
3622 kmalloc (MessageSizeInBytes,
3624 == (PI2O_MESSAGE_FRAME)NULL) {
3625 debug_usr_cmd_printf (
3626 "Failed to acquire frame[%d] memory\n",
3627 MessageSizeInBytes);
3631 span = ((caddr_t)sg)
3632 - (caddr_t)Message_Ptr;
3633 bcopy ((caddr_t)Message_Ptr,
3634 (caddr_t)NewMessage_Ptr, span);
3635 bcopy ((caddr_t)(sg-1),
3636 ((caddr_t)NewMessage_Ptr) + span,
3637 MessageSizeInBytes - span);
3638 kfree (Message_Ptr, M_TEMP);
3639 sg = (PI2O_SGE_SIMPLE_ELEMENT)
3640 (((caddr_t)NewMessage_Ptr) + span);
3641 Message_Ptr = NewMessage_Ptr;
3645 || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
3646 & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) {
3652 while ((elm = SLIST_FIRST(&sgList))
3653 != (struct ioctlSgList_S *)NULL) {
3654 SLIST_REMOVE_HEAD(&sgList, link);
3655 kfree (elm, M_TEMP);
3657 kfree (Reply_Ptr, M_TEMP);
3658 kfree (Message_Ptr, M_TEMP);
3663 debug_usr_cmd_printf ("Inbound: ");
3664 debug_usr_cmd_dump_message(Message_Ptr);
3666 /* Send the command */
3667 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
3668 /* Free up in-kernel buffers */
3669 while ((elm = SLIST_FIRST(&sgList))
3670 != (struct ioctlSgList_S *)NULL) {
3671 SLIST_REMOVE_HEAD(&sgList, link);
3672 kfree (elm, M_TEMP);
3674 kfree (Reply_Ptr, M_TEMP);
3675 kfree (Message_Ptr, M_TEMP);
3680 * We do not need any (optional byteswapping) method access to
3681 * the Initiator context field.
3683 I2O_MESSAGE_FRAME_setInitiatorContext64(
3684 (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb);
3686 (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
3688 kfree (Message_Ptr, M_TEMP);
3691 * Wait for the board to report a finished instruction.
3694 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
3695 if (ASR_getBlinkLedCode(sc)) {
3697 kprintf ("asr%d: Blink LED 0x%x resetting adapter\n",
3698 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
3699 ASR_getBlinkLedCode(sc));
3700 if (ASR_reset (sc) == ENXIO) {
3701 /* Command Cleanup */
3702 ASR_ccbRemove(sc, ccb);
3705 /* Free up in-kernel buffers */
3706 while ((elm = SLIST_FIRST(&sgList))
3707 != (struct ioctlSgList_S *)NULL) {
3708 SLIST_REMOVE_HEAD(&sgList, link);
3709 kfree (elm, M_TEMP);
3711 kfree (Reply_Ptr, M_TEMP);
3715 /* Check every second for BlinkLed */
3716 tsleep((caddr_t)ccb, 0, "asr", hz);
3720 debug_usr_cmd_printf ("Outbound: ");
3721 debug_usr_cmd_dump_message(Reply_Ptr);
3723 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3724 &(Reply_Ptr->StdReplyFrame),
3725 (ccb->ccb_h.status != CAM_REQ_CMP));
3727 if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3728 - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) {
3729 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr,
3730 ccb->csio.dxfer_len - ccb->csio.resid);
3732 if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes
3733 > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3734 - I2O_SCSI_SENSE_DATA_SZ))) {
3735 int size = ReplySizeInBytes
3736 - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3737 - I2O_SCSI_SENSE_DATA_SZ;
3739 if (size > sizeof(ccb->csio.sense_data)) {
3740 size = sizeof(ccb->csio.sense_data);
3742 bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData,
3744 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount(
3748 /* Free up in-kernel buffers */
3749 while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) {
3750 /* Copy out as necessary */
3752 /* DIR bit considered `valid', error due to ignorance works */
3753 && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount))
3754 & I2O_SGL_FLAGS_DIR) == 0)) {
3755 error = copyout ((caddr_t)(elm->KernelSpace),
3757 I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount)));
3759 SLIST_REMOVE_HEAD(&sgList, link);
3760 kfree (elm, M_TEMP);
3763 /* Copy reply frame to user space */
3764 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
3767 kfree (Reply_Ptr, M_TEMP);
3773 /*----------------------------------------------------------------------*/
3774 /* Function asr_ioctl */
3775 /*----------------------------------------------------------------------*/
3776 /* The parameters passed to this function are : */
3777 /* dev : Device number. */
3778 /* cmd : Ioctl Command */
3779 /* data : User Argument Passed In. */
3780 /* flag : Mode Parameter */
3781 /* proc : Process Parameter */
3783 /* This function is the user interface into this adapter driver */
3785 /* Return : zero if OK, error code if not */
3786 /*----------------------------------------------------------------------*/
3789 asr_ioctl(struct dev_ioctl_args *ap)
3791 cdev_t dev = ap->a_head.a_dev;
3792 caddr_t data = ap->a_data;
3795 Asr_softc_t * sc = ASR_get_sc (dev);
3797 if (sc != (Asr_softc_t *)NULL)
3801 # if (dsDescription_size != 50)
3802 case DPT_SIGNATURE + ((50 - dsDescription_size) << 16):
3804 if (ap->a_cmd & 0xFFFF0000) {
3805 (void)bcopy ((caddr_t)(&ASR_sig), data,
3809 /* Traditional version of the ioctl interface */
3810 case DPT_SIGNATURE & 0x0000FFFF:
3811 return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data),
3812 sizeof(dpt_sig_S)));
3814 /* Traditional version of the ioctl interface */
3815 case DPT_CTRLINFO & 0x0000FFFF:
3816 case DPT_CTRLINFO: {
3819 u_int16_t drvrHBAnum;
3821 u_int16_t blinkState;
3823 u_int8_t pciDeviceNum;
3825 u_int16_t Interrupt;
3826 u_int32_t reserved1;
3827 u_int32_t reserved2;
3828 u_int32_t reserved3;
3831 bzero (&CtlrInfo, sizeof(CtlrInfo));
3832 CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t);
3833 CtlrInfo.drvrHBAnum = asr_unit(dev);
3834 CtlrInfo.baseAddr = (u_long)sc->ha_Base;
3835 i = ASR_getBlinkLedCode (sc);
3839 CtlrInfo.blinkState = i;
3840 CtlrInfo.pciBusNum = sc->ha_pciBusNum;
3841 CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum;
3842 #define FLG_OSD_PCI_VALID 0x0001
3843 #define FLG_OSD_DMA 0x0002
3844 #define FLG_OSD_I2O 0x0004
3845 CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
3846 CtlrInfo.Interrupt = sc->ha_irq;
3847 if (ap->a_cmd & 0xFFFF0000) {
3848 bcopy (&CtlrInfo, data, sizeof(CtlrInfo));
3850 error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo));
3854 /* Traditional version of the ioctl interface */
3855 case DPT_SYSINFO & 0x0000FFFF:
3859 /* Kernel Specific ptok `hack' */
3860 # define ptok(a) ((char *)(a) + KERNBASE)
3862 bzero (&Info, sizeof(Info));
3864 /* Appears I am the only person in the Kernel doing this */
3872 Info.drive0CMOS = j;
3879 Info.drive1CMOS = j;
3881 Info.numDrives = *((char *)ptok(0x475));
3883 Info.processorFamily = ASR_sig.dsProcessorFamily;
3885 case CPU_386SX: case CPU_386:
3886 Info.processorType = PROC_386; break;
3887 case CPU_486SX: case CPU_486:
3888 Info.processorType = PROC_486; break;
3890 Info.processorType = PROC_PENTIUM; break;
3892 Info.processorType = PROC_SEXIUM; break;
3894 Info.osType = OS_BSDI_UNIX;
3895 Info.osMajorVersion = osrelease[0] - '0';
3896 Info.osMinorVersion = osrelease[2] - '0';
3897 /* Info.osRevision = 0; */
3898 /* Info.osSubRevision = 0; */
3899 Info.busType = SI_PCI_BUS;
3900 Info.flags = SI_CMOS_Valid | SI_NumDrivesValid
3901 | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM;
3903 /* Go Out And Look For I2O SmartROM */
3904 for(j = 0xC8000; j < 0xE0000; j += 2048) {
3908 if (*((unsigned short *)cp) != 0xAA55) {
3911 j += (cp[2] * 512) - 2048;
3912 if ((*((u_long *)(cp + 6))
3913 != ('S' + (' ' * 256) + (' ' * 65536L)))
3914 || (*((u_long *)(cp + 10))
3915 != ('I' + ('2' * 256) + ('0' * 65536L)))) {
3919 for (k = 0; k < 64; ++k) {
3920 if (*((unsigned short *)cp)
3921 == (' ' + ('v' * 256))) {
3926 Info.smartROMMajorVersion
3927 = *((unsigned char *)(cp += 4)) - '0';
3928 Info.smartROMMinorVersion
3929 = *((unsigned char *)(cp += 2));
3930 Info.smartROMRevision
3931 = *((unsigned char *)(++cp));
3932 Info.flags |= SI_SmartROMverValid;
3933 Info.flags &= ~SI_NO_SmartROM;
3937 /* Get The Conventional Memory Size From CMOS */
3943 Info.conventionalMemSize = j;
3945 /* Get The Extended Memory Found At Power On From CMOS */
3951 Info.extendedMemSize = j;
3952 Info.flags |= SI_MemorySizeValid;
3954 # if (defined(THIS_IS_BROKEN))
3955 /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */
3956 if (Info.numDrives > 0) {
3958 * Get The Pointer From Int 41 For The First
3961 j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4)
3962 + (unsigned)(*((unsigned short *)ptok(0x104+0)));
3964 * It appears that SmartROM's Int41/Int46 pointers
3965 * use memory that gets stepped on by the kernel
3966 * loading. We no longer have access to this
3967 * geometry information but try anyways (!?)
3969 Info.drives[0].cylinders = *((unsigned char *)ptok(j));
3971 Info.drives[0].cylinders += ((int)*((unsigned char *)
3974 Info.drives[0].heads = *((unsigned char *)ptok(j));
3976 Info.drives[0].sectors = *((unsigned char *)ptok(j));
3977 Info.flags |= SI_DriveParamsValid;
3978 if ((Info.drives[0].cylinders == 0)
3979 || (Info.drives[0].heads == 0)
3980 || (Info.drives[0].sectors == 0)) {
3981 Info.flags &= ~SI_DriveParamsValid;
3983 if (Info.numDrives > 1) {
3985 * Get The Pointer From Int 46 For The
3986 * Second Drive Parameters
3988 j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4)
3989 + (unsigned)(*((unsigned short *)ptok(0x118+0)));
3990 Info.drives[1].cylinders = *((unsigned char *)
3993 Info.drives[1].cylinders += ((int)
3994 *((unsigned char *)ptok(j))) << 8;
3996 Info.drives[1].heads = *((unsigned char *)
3999 Info.drives[1].sectors = *((unsigned char *)
4001 if ((Info.drives[1].cylinders == 0)
4002 || (Info.drives[1].heads == 0)
4003 || (Info.drives[1].sectors == 0)) {
4004 Info.flags &= ~SI_DriveParamsValid;
4009 /* Copy Out The Info Structure To The User */
4010 if (ap->a_cmd & 0xFFFF0000) {
4011 bcopy (&Info, data, sizeof(Info));
4013 error = copyout (&Info, *(caddr_t *)data, sizeof(Info));
4017 /* Get The BlinkLED State */
4019 i = ASR_getBlinkLedCode (sc);
4023 if (ap->a_cmd & 0xFFFF0000) {
4024 bcopy ((caddr_t)(&i), data, sizeof(i));
4026 error = copyout (&i, *(caddr_t *)data, sizeof(i));
4030 /* Send an I2O command */
4032 return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data)));
4034 /* Reset and re-initialize the adapter */
4036 return (ASR_reset (sc));
4038 /* Rescan the LCT table and resynchronize the information */
4040 return (ASR_rescan (sc));