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.14 2004/05/19 22:52:46 dillon 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 cam_imask instead of bio_imask.
85 * - use u_int8_t instead of u_char.
86 * - use u_int16_t instead of u_short.
87 * - use u_int32_t instead of u_long where appropriate.
88 * - use 64 bit context handler instead of 32 bit.
89 * - create_ccb should only allocate the worst case
90 * requirements for the driver since CAM may evolve
91 * making union ccb much larger than needed here.
92 * renamed create_ccb to asr_alloc_ccb.
93 * - go nutz justifying all debug prints as macros
94 * defined at the top and remove unsightly ifdefs.
95 * - INLINE STATIC viewed as confusing. Historically
96 * utilized to affect code performance and debug
97 * issues in OS, Compiler or OEM specific situations.
98 * V1.00 2000/05/31 Mark_Salyzyn@adaptec.com
99 * - Ported from FreeBSD 2.2.X DPT I2O driver.
100 * changed struct scsi_xfer to union ccb/struct ccb_hdr
101 * changed variable name xs to ccb
102 * changed struct scsi_link to struct cam_path
103 * changed struct scsibus_data to struct cam_sim
104 * stopped using fordriver for holding on to the TID
105 * use proprietary packet creation instead of scsi_inquire
106 * CAM layer sends synchronize commands.
109 #define ASR_VERSION 1
110 #define ASR_REVISION '0'
111 #define ASR_SUBREVISION '8'
114 #define ASR_YEAR 2001 - 1980
117 * Debug macros to reduce the unsightly ifdefs
119 #if (defined(DEBUG_ASR) || defined(DEBUG_ASR_USR_CMD) || defined(DEBUG_ASR_CMD))
120 # define debug_asr_message(message) \
122 u_int32_t * pointer = (u_int32_t *)message; \
123 u_int32_t length = I2O_MESSAGE_FRAME_getMessageSize(message);\
124 u_int32_t counter = 0; \
127 printf ("%08lx%c", (u_long)*(pointer++), \
128 (((++counter & 7) == 0) || (length == 0)) \
133 #endif /* DEBUG_ASR || DEBUG_ASR_USR_CMD || DEBUG_ASR_CMD */
135 #if (defined(DEBUG_ASR))
136 /* Breaks on none STDC based compilers :-( */
137 # define debug_asr_printf(fmt,args...) printf(fmt, ##args)
138 # define debug_asr_dump_message(message) debug_asr_message(message)
139 # define debug_asr_print_path(ccb) xpt_print_path(ccb->ccb_h.path);
140 /* None fatal version of the ASSERT macro */
141 # if (defined(__STDC__))
142 # define ASSERT(phrase) if(!(phrase))printf(#phrase " at line %d file %s\n",__LINE__,__FILE__)
144 # define ASSERT(phrase) if(!(phrase))printf("phrase" " at line %d file %s\n",__LINE__,__FILE__)
146 #else /* DEBUG_ASR */
147 # define debug_asr_printf(fmt,args...)
148 # define debug_asr_dump_message(message)
149 # define debug_asr_print_path(ccb)
151 #endif /* DEBUG_ASR */
154 * If DEBUG_ASR_CMD is defined:
155 * 0 - Display incoming SCSI commands
156 * 1 - add in a quick character before queueing.
157 * 2 - add in outgoing message frames.
159 #if (defined(DEBUG_ASR_CMD))
160 # define debug_asr_cmd_printf(fmt,args...) printf(fmt,##args)
161 # define debug_asr_dump_ccb(ccb) \
163 u_int8_t * cp = (unsigned char *)&(ccb->csio.cdb_io); \
164 int len = ccb->csio.cdb_len; \
167 debug_asr_cmd_printf (" %02x", *(cp++)); \
171 # if (DEBUG_ASR_CMD > 0)
172 # define debug_asr_cmd1_printf debug_asr_cmd_printf
174 # define debug_asr_cmd1_printf(fmt,args...)
176 # if (DEBUG_ASR_CMD > 1)
177 # define debug_asr_cmd2_printf debug_asr_cmd_printf
178 # define debug_asr_cmd2_dump_message(message) debug_asr_message(message)
180 # define debug_asr_cmd2_printf(fmt,args...)
181 # define debug_asr_cmd2_dump_message(message)
183 #else /* DEBUG_ASR_CMD */
184 # define debug_asr_cmd_printf(fmt,args...)
185 # define debug_asr_cmd_dump_ccb(ccb)
186 # define debug_asr_cmd1_printf(fmt,args...)
187 # define debug_asr_cmd2_printf(fmt,args...)
188 # define debug_asr_cmd2_dump_message(message)
189 #endif /* DEBUG_ASR_CMD */
191 #if (defined(DEBUG_ASR_USR_CMD))
192 # define debug_usr_cmd_printf(fmt,args...) printf(fmt,##args)
193 # define debug_usr_cmd_dump_message(message) debug_usr_message(message)
194 #else /* DEBUG_ASR_USR_CMD */
195 # define debug_usr_cmd_printf(fmt,args...)
196 # define debug_usr_cmd_dump_message(message)
197 #endif /* DEBUG_ASR_USR_CMD */
199 #define dsDescription_size 46 /* Snug as a bug in a rug */
202 static dpt_sig_S ASR_sig = {
203 { 'd', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, PROC_INTEL,
204 PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, FT_HBADRVR, 0,
205 OEM_DPT, OS_FREE_BSD, CAP_ABOVE16MB, DEV_ALL,
207 0, 0, ASR_VERSION, ASR_REVISION, ASR_SUBREVISION,
208 ASR_MONTH, ASR_DAY, ASR_YEAR,
209 /* 01234567890123456789012345678901234567890123456789 < 50 chars */
210 "Adaptec FreeBSD 4.0.0 Unix SCSI I2O HBA Driver"
211 /* ^^^^^ asr_attach alters these to match OS */
214 #include <sys/param.h> /* TRUE=1 and FALSE=0 defined here */
215 #include <sys/kernel.h>
216 #include <sys/systm.h>
217 #include <sys/malloc.h>
218 #include <sys/proc.h>
219 #include <sys/conf.h>
220 #include <sys/disklabel.h>
222 #include <machine/resource.h>
223 #include <machine/bus.h>
224 #include <sys/rman.h>
225 #include <sys/stat.h>
226 #include <sys/device.h>
228 #include <bus/cam/cam.h>
229 #include <bus/cam/cam_ccb.h>
230 #include <bus/cam/cam_sim.h>
231 #include <bus/cam/cam_xpt_sim.h>
232 #include <bus/cam/cam_xpt_periph.h>
234 #include <bus/cam/scsi/scsi_all.h>
235 #include <bus/cam/scsi/scsi_message.h>
239 #include <machine/cputypes.h>
240 #include <machine/clock.h>
241 #include <i386/include/vmparam.h>
243 #include <bus/pci/pcivar.h>
244 #include <bus/pci/pcireg.h>
246 #define STATIC static
249 #if (defined(DEBUG_ASR) && (DEBUG_ASR > 0))
259 #define osdSwap4(x) ((u_long)ntohl((u_long)(x)))
260 #define KVTOPHYS(x) vtophys(x)
261 #include "dptalign.h"
263 #include "i2obscsi.h"
265 #include "i2oadptr.h"
268 #include "sys_info.h"
270 /* Configuration Definitions */
272 #define SG_SIZE 58 /* Scatter Gather list Size */
273 #define MAX_TARGET_ID 126 /* Maximum Target ID supported */
274 #define MAX_LUN 255 /* Maximum LUN Supported */
275 #define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */
276 #define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */
277 #define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */
278 #define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */
279 #define MAX_MAP 4194304L /* Maximum mapping size of IOP */
280 /* Also serves as the minimum map for */
281 /* the 2005S zero channel RAID product */
283 /**************************************************************************
284 ** ASR Host Adapter structure - One Structure For Each Host Adapter That **
285 ** Is Configured Into The System. The Structure Supplies Configuration **
286 ** Information, Status Info, Queue Info And An Active CCB List Pointer. **
287 ***************************************************************************/
289 /* I2O register set */
294 # define Mask_InterruptsDisabled 0x08
296 volatile U32 ToFIFO; /* In Bound FIFO */
297 volatile U32 FromFIFO; /* Out Bound FIFO */
301 * A MIX of performance and space considerations for TID lookups
303 typedef u_int16_t tid_t;
306 u_int32_t size; /* up to MAX_LUN */
311 u_int32_t size; /* up to MAX_TARGET */
316 * To ensure that we only allocate and use the worst case ccb here, lets
317 * make our own local ccb union. If asr_alloc_ccb is utilized for another
318 * ccb type, ensure that you add the additional structures into our local
319 * ccb union. To ensure strict type checking, we will utilize the local
320 * ccb definition wherever possible.
323 struct ccb_hdr ccb_h; /* For convenience */
324 struct ccb_scsiio csio;
325 struct ccb_setasync csa;
328 typedef struct Asr_softc {
330 void * ha_Base; /* base port for each board */
331 u_int8_t * volatile ha_blinkLED;
332 i2oRegs_t * ha_Virt; /* Base address of IOP */
333 U8 * ha_Fvirt; /* Base address of Frames */
334 I2O_IOP_ENTRY ha_SystemTable;
335 LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */
336 struct cam_path * ha_path[MAX_CHANNEL+1];
337 struct cam_sim * ha_sim[MAX_CHANNEL+1];
338 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
339 struct resource * ha_mem_res;
340 struct resource * ha_mes_res;
341 struct resource * ha_irq_res;
344 PI2O_LCT ha_LCT; /* Complete list of devices */
345 # define le_type IdentityTag[0]
346 # define I2O_BSA 0x20
347 # define I2O_FCA 0x40
348 # define I2O_SCSI 0x00
349 # define I2O_PORT 0x80
350 # define I2O_UNKNOWN 0x7F
351 # define le_bus IdentityTag[1]
352 # define le_target IdentityTag[2]
353 # define le_lun IdentityTag[3]
354 target2lun_t * ha_targets[MAX_CHANNEL+1];
355 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs;
358 u_int8_t ha_in_reset;
359 # define HA_OPERATIONAL 0
360 # define HA_IN_RESET 1
361 # define HA_OFF_LINE 2
362 # define HA_OFF_LINE_RECOVERY 3
363 /* Configuration information */
364 /* The target id maximums we take */
365 u_int8_t ha_MaxBus; /* Maximum bus */
366 u_int8_t ha_MaxId; /* Maximum target ID */
367 u_int8_t ha_MaxLun; /* Maximum target LUN */
368 u_int8_t ha_SgSize; /* Max SG elements */
369 u_int8_t ha_pciBusNum;
370 u_int8_t ha_pciDeviceNum;
371 u_int8_t ha_adapter_target[MAX_CHANNEL+1];
372 u_int16_t ha_QueueSize; /* Max outstanding commands */
373 u_int16_t ha_Msgs_Count;
375 /* Links into other parents and HBAs */
376 struct Asr_softc * ha_next; /* HBA list */
378 #ifdef ASR_MEASURE_PERFORMANCE
379 #define MAX_TIMEQ_SIZE 256 // assumes MAX 256 scsi commands sent
380 asr_perf_t ha_performance;
381 u_int32_t ha_submitted_ccbs_count;
383 // Queueing macros for a circular queue
384 #define TIMEQ_FREE_LIST_EMPTY(head, tail) (-1 == (head) && -1 == (tail))
385 #define TIMEQ_FREE_LIST_FULL(head, tail) ((((tail) + 1) % MAX_TIMEQ_SIZE) == (head))
386 #define ENQ_TIMEQ_FREE_LIST(item, Q, head, tail) \
387 if (!TIMEQ_FREE_LIST_FULL((head), (tail))) { \
388 if TIMEQ_FREE_LIST_EMPTY((head),(tail)) { \
389 (head) = (tail) = 0; \
391 else (tail) = ((tail) + 1) % MAX_TIMEQ_SIZE; \
392 Q[(tail)] = (item); \
395 debug_asr_printf("asr: Enqueueing when TimeQ Free List is full... This should not happen!\n"); \
397 #define DEQ_TIMEQ_FREE_LIST(item, Q, head, tail) \
398 if (!TIMEQ_FREE_LIST_EMPTY((head), (tail))) { \
400 if ((head) == (tail)) { (head) = (tail) = -1; } \
401 else (head) = ((head) + 1) % MAX_TIMEQ_SIZE; \
405 debug_asr_printf("asr: Dequeueing when TimeQ Free List is empty... This should not happen!\n"); \
408 // Circular queue of time stamps
409 struct timeval ha_timeQ[MAX_TIMEQ_SIZE];
410 u_int32_t ha_timeQFreeList[MAX_TIMEQ_SIZE];
411 int ha_timeQFreeHead;
412 int ha_timeQFreeTail;
416 STATIC Asr_softc_t * Asr_softc;
419 * Prototypes of the routines we have in this object.
422 /* Externally callable routines */
423 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
424 #define PROBE_ARGS IN device_t tag
425 #define PROBE_RET int
426 #define PROBE_SET() u_long id = (pci_get_device(tag)<<16)|pci_get_vendor(tag)
427 #define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);}
428 #define ATTACH_ARGS IN device_t tag
429 #define ATTACH_RET int
430 #define ATTACH_SET() int unit = device_get_unit(tag)
431 #define ATTACH_RETURN(retval) return(retval)
433 #define PROBE_ARGS IN pcici_t tag, IN pcidi_t id
434 #define PROBE_RET const char *
436 #define PROBE_RETURN(retval) return(retval)
437 #define ATTACH_ARGS IN pcici_t tag, IN int unit
438 #define ATTACH_RET void
440 #define ATTACH_RETURN(retval) return
442 /* I2O HDM interface */
443 STATIC PROBE_RET asr_probe (PROBE_ARGS);
444 STATIC ATTACH_RET asr_attach (ATTACH_ARGS);
445 /* DOMINO placeholder */
446 STATIC PROBE_RET domino_probe (PROBE_ARGS);
447 STATIC ATTACH_RET domino_attach (ATTACH_ARGS);
448 /* MODE0 adapter placeholder */
449 STATIC PROBE_RET mode0_probe (PROBE_ARGS);
450 STATIC ATTACH_RET mode0_attach (ATTACH_ARGS);
452 STATIC Asr_softc_t * ASR_get_sc (
454 STATIC int asr_ioctl (
460 STATIC int asr_open (
465 STATIC int asr_close (
470 STATIC int asr_intr (
471 IN Asr_softc_t * sc);
472 STATIC void asr_timeout (
474 STATIC int ASR_init (
475 IN Asr_softc_t * sc);
476 STATIC INLINE int ASR_acquireLct (
477 INOUT Asr_softc_t * sc);
478 STATIC INLINE int ASR_acquireHrt (
479 INOUT Asr_softc_t * sc);
480 STATIC void asr_action (
481 IN struct cam_sim * sim,
483 STATIC void asr_poll (
484 IN struct cam_sim * sim);
487 * Here is the auto-probe structure used to nest our tests appropriately
488 * during the startup phase of the operating system.
490 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
491 STATIC device_method_t asr_methods[] = {
492 DEVMETHOD(device_probe, asr_probe),
493 DEVMETHOD(device_attach, asr_attach),
497 STATIC driver_t asr_driver = {
503 STATIC devclass_t asr_devclass;
505 DECLARE_DUMMY_MODULE(asr);
506 DRIVER_MODULE(asr, pci, asr_driver, asr_devclass, 0, 0);
508 STATIC device_method_t domino_methods[] = {
509 DEVMETHOD(device_probe, domino_probe),
510 DEVMETHOD(device_attach, domino_attach),
514 STATIC driver_t domino_driver = {
520 STATIC devclass_t domino_devclass;
522 DRIVER_MODULE(domino, pci, domino_driver, domino_devclass, 0, 0);
524 STATIC device_method_t mode0_methods[] = {
525 DEVMETHOD(device_probe, mode0_probe),
526 DEVMETHOD(device_attach, mode0_attach),
530 STATIC driver_t mode0_driver = {
536 STATIC devclass_t mode0_devclass;
538 DRIVER_MODULE(mode0, pci, mode0_driver, mode0_devclass, 0, 0);
540 STATIC u_long asr_pcicount = 0;
541 STATIC struct pci_device asr_pcidev = {
548 DATA_SET (asr_pciset, asr_pcidev);
550 STATIC u_long domino_pcicount = 0;
551 STATIC struct pci_device domino_pcidev = {
558 DATA_SET (domino_pciset, domino_pcidev);
560 STATIC u_long mode0_pcicount = 0;
561 STATIC struct pci_device mode0_pcidev = {
568 DATA_SET (mode0_pciset, mode0_pcidev);
572 * devsw for asr hba driver
574 * only ioctl is used. the sd driver provides all other access.
576 #define CDEV_MAJOR 154 /* prefered default character major */
577 STATIC struct cdevsw asr_cdevsw = {
579 CDEV_MAJOR, /* maj */
585 asr_close, /* close */
588 asr_ioctl, /* ioctl */
591 nostrategy, /* strategy */
596 #ifdef ASR_MEASURE_PERFORMANCE
597 STATIC u_int32_t asr_time_delta (IN struct timeval start,
598 IN struct timeval end);
602 * Initialize the dynamic cdevsw hooks.
605 asr_drvinit (void * unused)
607 static int asr_devsw_installed = 0;
609 if (asr_devsw_installed) {
612 asr_devsw_installed++;
614 * Find a free spot (the report during driver load used by
615 * osd layer in engine to generate the controlling nodes).
617 * XXX this is garbage code, store a unit number in asr_cdevsw
618 * and iterate through that instead?
620 while (asr_cdevsw.d_maj < NUMCDEVSW &&
621 cdevsw_get(asr_cdevsw.d_maj, -1) != NULL
625 if (asr_cdevsw.d_maj >= NUMCDEVSW) {
626 asr_cdevsw.d_maj = 0;
627 while (asr_cdevsw.d_maj < CDEV_MAJOR &&
628 cdevsw_get(asr_cdevsw.d_maj, -1) != NULL
637 cdevsw_add(&asr_cdevsw, 0, 0);
640 /* Must initialize before CAM layer picks up our HBA driver */
641 SYSINIT(asrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,asr_drvinit,NULL)
643 /* I2O support routines */
644 #define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)]
645 #define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME))
648 * Fill message with default.
650 STATIC PI2O_MESSAGE_FRAME
655 OUT PI2O_MESSAGE_FRAME Message_Ptr;
657 Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message);
658 bzero ((void *)Message_Ptr, size);
659 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11);
660 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
661 (size + sizeof(U32) - 1) >> 2);
662 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
663 return (Message_Ptr);
664 } /* ASR_fillMessage */
666 #define EMPTY_QUEUE ((U32)-1L)
672 OUT U32 MessageOffset;
674 if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) {
675 MessageOffset = virt->ToFIFO;
677 return (MessageOffset);
678 } /* ASR_getMessage */
680 /* Issue a polled command */
683 INOUT i2oRegs_t * virt,
685 IN PI2O_MESSAGE_FRAME Message)
692 * ASR_initiateCp is only used for synchronous commands and will
693 * be made more resiliant to adapter delays since commands like
694 * resetIOP can cause the adapter to be deaf for a little time.
696 while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE)
700 if (MessageOffset != EMPTY_QUEUE) {
701 bcopy (Message, fvirt + MessageOffset,
702 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
704 * Disable the Interrupts
706 virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled;
707 virt->ToFIFO = MessageOffset;
710 } /* ASR_initiateCp */
717 INOUT i2oRegs_t * virt,
720 struct resetMessage {
721 I2O_EXEC_IOP_RESET_MESSAGE M;
724 defAlignLong(struct resetMessage,Message);
725 PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr;
726 OUT U32 * volatile Reply_Ptr;
730 * Build up our copy of the Message.
732 Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message,
733 sizeof(I2O_EXEC_IOP_RESET_MESSAGE));
734 I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET);
736 * Reset the Reply Status
738 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
739 + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0;
740 I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr,
741 KVTOPHYS((void *)Reply_Ptr));
743 * Send the Message out
745 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
747 * Wait for a response (Poll), timeouts are dangerous if
748 * the card is truly responsive. We assume response in 2s.
750 u_int8_t Delay = 200;
752 while ((*Reply_Ptr == 0) && (--Delay != 0)) {
756 * Re-enable the interrupts.
762 ASSERT (Old != (U32)-1L);
767 * Get the curent state of the adapter
769 STATIC INLINE PI2O_EXEC_STATUS_GET_REPLY
771 INOUT i2oRegs_t * virt,
773 OUT PI2O_EXEC_STATUS_GET_REPLY buffer)
775 defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message);
776 PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr;
780 * Build up our copy of the Message.
782 Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message,
783 sizeof(I2O_EXEC_STATUS_GET_MESSAGE));
784 I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr,
785 I2O_EXEC_STATUS_GET);
786 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr,
787 KVTOPHYS((void *)buffer));
788 /* This one is a Byte Count */
789 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr,
790 sizeof(I2O_EXEC_STATUS_GET_REPLY));
792 * Reset the Reply Status
794 bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY));
796 * Send the Message out
798 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
800 * Wait for a response (Poll), timeouts are dangerous if
801 * the card is truly responsive. We assume response in 50ms.
803 u_int8_t Delay = 255;
805 while (*((U8 * volatile)&(buffer->SyncByte)) == 0) {
807 buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL;
813 * Re-enable the interrupts.
818 return ((PI2O_EXEC_STATUS_GET_REPLY)NULL);
819 } /* ASR_getStatus */
822 * Check if the device is a SCSI I2O HBA, and add it to the list.
826 * Probe for ASR controller. If we find it, we will use it.
830 asr_probe(PROBE_ARGS)
833 if ((id == 0xA5011044) || (id == 0xA5111044)) {
834 PROBE_RETURN ("Adaptec Caching SCSI RAID");
840 * Probe/Attach for DOMINO chipset.
843 domino_probe(PROBE_ARGS)
846 if (id == 0x10121044) {
847 PROBE_RETURN ("Adaptec Caching Memory Controller");
853 domino_attach (ATTACH_ARGS)
856 } /* domino_attach */
859 * Probe/Attach for MODE0 adapters.
862 mode0_probe(PROBE_ARGS)
867 * If/When we can get a business case to commit to a
868 * Mode0 driver here, we can make all these tests more
869 * specific and robust. Mode0 adapters have their processors
870 * turned off, this the chips are in a raw state.
873 /* This is a PLX9054 */
874 if (id == 0x905410B5) {
875 PROBE_RETURN ("Adaptec Mode0 PM3757");
877 /* This is a PLX9080 */
878 if (id == 0x908010B5) {
879 PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755");
881 /* This is a ZION 80303 */
882 if (id == 0x53098086) {
883 PROBE_RETURN ("Adaptec Mode0 3010S");
885 /* This is an i960RS */
886 if (id == 0x39628086) {
887 PROBE_RETURN ("Adaptec Mode0 2100S");
889 /* This is an i960RN */
890 if (id == 0x19648086) {
891 PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S");
893 #if 0 /* this would match any generic i960 -- mjs */
894 /* This is an i960RP (typically also on Motherboards) */
895 if (id == 0x19608086) {
896 PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654");
903 mode0_attach (ATTACH_ARGS)
908 STATIC INLINE union asr_ccb *
912 OUT union asr_ccb * new_ccb;
914 if ((new_ccb = (union asr_ccb *)malloc(sizeof(*new_ccb),
915 M_DEVBUF, M_WAITOK)) != (union asr_ccb *)NULL) {
916 bzero (new_ccb, sizeof(*new_ccb));
917 new_ccb->ccb_h.pinfo.priority = 1;
918 new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
919 new_ccb->ccb_h.spriv_ptr0 = sc;
922 } /* asr_alloc_ccb */
926 IN union asr_ccb * free_ccb)
928 free(free_ccb, M_DEVBUF);
932 * Print inquiry data `carefully'
939 while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) {
940 printf ("%c", *(s++));
947 STATIC INLINE int ASR_queue (
949 IN PI2O_MESSAGE_FRAME Message);
951 * Send a message synchronously and without Interrupt to a ccb.
955 INOUT union asr_ccb * ccb,
956 IN PI2O_MESSAGE_FRAME Message)
960 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
963 * We do not need any (optional byteswapping) method access to
964 * the Initiator context field.
966 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
968 /* Prevent interrupt service */
970 sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask)
971 | Mask_InterruptsDisabled;
973 if (ASR_queue (sc, Message) == EMPTY_QUEUE) {
974 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
975 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
979 * Wait for this board to report a finished instruction.
981 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
985 /* Re-enable Interrupts */
986 sc->ha_Virt->Mask = Mask;
989 return (ccb->ccb_h.status);
993 * Send a message synchronously to a Asr_softc_t
998 IN PI2O_MESSAGE_FRAME Message)
1000 union asr_ccb * ccb;
1003 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
1004 return (CAM_REQUEUE_REQ);
1007 status = ASR_queue_s (ccb, Message);
1015 * Add the specified ccb to the active queue
1019 IN Asr_softc_t * sc,
1020 INOUT union asr_ccb * ccb)
1025 LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le);
1026 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
1027 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
1029 * RAID systems can take considerable time to
1030 * complete some commands given the large cache
1031 * flashes switching from write back to write thru.
1033 ccb->ccb_h.timeout = 6 * 60 * 1000;
1035 ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb,
1036 (ccb->ccb_h.timeout * hz) / 1000);
1042 * Remove the specified ccb from the active queue.
1046 IN Asr_softc_t * sc,
1047 INOUT union asr_ccb * ccb)
1052 untimeout(asr_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch);
1053 LIST_REMOVE(&(ccb->ccb_h), sim_links.le);
1055 } /* ASR_ccbRemove */
1058 * Fail all the active commands, so they get re-issued by the operating
1062 ASR_failActiveCommands (
1063 IN Asr_softc_t * sc)
1065 struct ccb_hdr * ccb;
1068 #if 0 /* Currently handled by callers, unnecessary paranoia currently */
1069 /* Left in for historical perspective. */
1070 defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message);
1071 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
1073 /* Send a blind LCT command to wait for the enableSys to complete */
1074 Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message,
1075 sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT));
1076 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
1077 I2O_EXEC_LCT_NOTIFY);
1078 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
1079 I2O_CLASS_MATCH_ANYCLASS);
1080 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1085 * We do not need to inform the CAM layer that we had a bus
1086 * reset since we manage it on our own, this also prevents the
1087 * SCSI_DELAY settling that would be required on other systems.
1088 * The `SCSI_DELAY' has already been handled by the card via the
1089 * acquisition of the LCT table while we are at CAM priority level.
1090 * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) {
1091 * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL);
1094 while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) {
1095 ASR_ccbRemove (sc, (union asr_ccb *)ccb);
1097 ccb->status &= ~CAM_STATUS_MASK;
1098 ccb->status |= CAM_REQUEUE_REQ;
1099 /* Nothing Transfered */
1100 ((struct ccb_scsiio *)ccb)->resid
1101 = ((struct ccb_scsiio *)ccb)->dxfer_len;
1104 xpt_done ((union ccb *)ccb);
1106 wakeup ((caddr_t)ccb);
1110 } /* ASR_failActiveCommands */
1113 * The following command causes the HBA to reset the specific bus
1117 IN Asr_softc_t * sc,
1120 defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message);
1121 I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr;
1122 PI2O_LCT_ENTRY Device;
1124 Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message,
1125 sizeof(I2O_HBA_BUS_RESET_MESSAGE));
1126 I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame,
1128 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
1129 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1131 if (((Device->le_type & I2O_PORT) != 0)
1132 && (Device->le_bus == bus)) {
1133 I2O_MESSAGE_FRAME_setTargetAddress(
1134 &Message_Ptr->StdMessageFrame,
1135 I2O_LCT_ENTRY_getLocalTID(Device));
1136 /* Asynchronous command, with no expectations */
1137 (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1141 } /* ASR_resetBus */
1144 ASR_getBlinkLedCode (
1145 IN Asr_softc_t * sc)
1147 if ((sc != (Asr_softc_t *)NULL)
1148 && (sc->ha_blinkLED != (u_int8_t *)NULL)
1149 && (sc->ha_blinkLED[1] == 0xBC)) {
1150 return (sc->ha_blinkLED[0]);
1153 } /* ASR_getBlinkCode */
1156 * Determine the address of an TID lookup. Must be done at high priority
1157 * since the address can be changed by other threads of execution.
1159 * Returns NULL pointer if not indexible (but will attempt to generate
1160 * an index if `new_entry' flag is set to TRUE).
1162 * All addressible entries are to be guaranteed zero if never initialized.
1164 STATIC INLINE tid_t *
1166 INOUT Asr_softc_t * sc,
1172 target2lun_t * bus_ptr;
1173 lun2tid_t * target_ptr;
1177 * Validity checking of incoming parameters. More of a bound
1178 * expansion limit than an issue with the code dealing with the
1181 * sc must be valid before it gets here, so that check could be
1182 * dropped if speed a critical issue.
1184 if ((sc == (Asr_softc_t *)NULL)
1185 || (bus > MAX_CHANNEL)
1186 || (target > sc->ha_MaxId)
1187 || (lun > sc->ha_MaxLun)) {
1188 debug_asr_printf("(%lx,%d,%d,%d) target out of range\n",
1189 (u_long)sc, bus, target, lun);
1190 return ((tid_t *)NULL);
1193 * See if there is an associated bus list.
1195 * for performance, allocate in size of BUS_CHUNK chunks.
1196 * BUS_CHUNK must be a power of two. This is to reduce
1197 * fragmentation effects on the allocations.
1199 # define BUS_CHUNK 8
1200 new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1));
1201 if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) {
1203 * Allocate a new structure?
1204 * Since one element in structure, the +1
1205 * needed for size has been abstracted.
1207 if ((new_entry == FALSE)
1208 || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)malloc (
1209 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1211 == (target2lun_t *)NULL)) {
1212 debug_asr_printf("failed to allocate bus list\n");
1213 return ((tid_t *)NULL);
1215 bzero (bus_ptr, sizeof(*bus_ptr)
1216 + (sizeof(bus_ptr->LUN) * new_size));
1217 bus_ptr->size = new_size + 1;
1218 } else if (bus_ptr->size <= new_size) {
1219 target2lun_t * new_bus_ptr;
1222 * Reallocate a new structure?
1223 * Since one element in structure, the +1
1224 * needed for size has been abstracted.
1226 if ((new_entry == FALSE)
1227 || ((new_bus_ptr = (target2lun_t *)malloc (
1228 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1230 == (target2lun_t *)NULL)) {
1231 debug_asr_printf("failed to reallocate bus list\n");
1232 return ((tid_t *)NULL);
1235 * Zero and copy the whole thing, safer, simpler coding
1236 * and not really performance critical at this point.
1238 bzero (new_bus_ptr, sizeof(*bus_ptr)
1239 + (sizeof(bus_ptr->LUN) * new_size));
1240 bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr)
1241 + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1)));
1242 sc->ha_targets[bus] = new_bus_ptr;
1243 free (bus_ptr, M_TEMP);
1244 bus_ptr = new_bus_ptr;
1245 bus_ptr->size = new_size + 1;
1248 * We now have the bus list, lets get to the target list.
1249 * Since most systems have only *one* lun, we do not allocate
1250 * in chunks as above, here we allow one, then in chunk sizes.
1251 * TARGET_CHUNK must be a power of two. This is to reduce
1252 * fragmentation effects on the allocations.
1254 # define TARGET_CHUNK 8
1255 if ((new_size = lun) != 0) {
1256 new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1));
1258 if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) {
1260 * Allocate a new structure?
1261 * Since one element in structure, the +1
1262 * needed for size has been abstracted.
1264 if ((new_entry == FALSE)
1265 || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)malloc (
1266 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1268 == (lun2tid_t *)NULL)) {
1269 debug_asr_printf("failed to allocate target list\n");
1270 return ((tid_t *)NULL);
1272 bzero (target_ptr, sizeof(*target_ptr)
1273 + (sizeof(target_ptr->TID) * new_size));
1274 target_ptr->size = new_size + 1;
1275 } else if (target_ptr->size <= new_size) {
1276 lun2tid_t * new_target_ptr;
1279 * Reallocate a new structure?
1280 * Since one element in structure, the +1
1281 * needed for size has been abstracted.
1283 if ((new_entry == FALSE)
1284 || ((new_target_ptr = (lun2tid_t *)malloc (
1285 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1287 == (lun2tid_t *)NULL)) {
1288 debug_asr_printf("failed to reallocate target list\n");
1289 return ((tid_t *)NULL);
1292 * Zero and copy the whole thing, safer, simpler coding
1293 * and not really performance critical at this point.
1295 bzero (new_target_ptr, sizeof(*target_ptr)
1296 + (sizeof(target_ptr->TID) * new_size));
1297 bcopy (target_ptr, new_target_ptr,
1299 + (sizeof(target_ptr->TID) * (target_ptr->size - 1)));
1300 bus_ptr->LUN[target] = new_target_ptr;
1301 free (target_ptr, M_TEMP);
1302 target_ptr = new_target_ptr;
1303 target_ptr->size = new_size + 1;
1306 * Now, acquire the TID address from the LUN indexed list.
1308 return (&(target_ptr->TID[lun]));
1309 } /* ASR_getTidAddress */
1312 * Get a pre-existing TID relationship.
1314 * If the TID was never set, return (tid_t)-1.
1316 * should use mutex rather than spl.
1320 IN Asr_softc_t * sc,
1330 if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE))
1332 /* (tid_t)0 or (tid_t)-1 indicate no TID */
1333 || (*tid_ptr == (tid_t)0)) {
1343 * Set a TID relationship.
1345 * If the TID was not set, return (tid_t)-1.
1347 * should use mutex rather than spl.
1351 INOUT Asr_softc_t * sc,
1360 if (TID != (tid_t)-1) {
1365 if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE))
1376 /*-------------------------------------------------------------------------*/
1377 /* Function ASR_rescan */
1378 /*-------------------------------------------------------------------------*/
1379 /* The Parameters Passed To This Function Are : */
1380 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1382 /* This Function Will rescan the adapter and resynchronize any data */
1384 /* Return : 0 For OK, Error Code Otherwise */
1385 /*-------------------------------------------------------------------------*/
1389 IN Asr_softc_t * sc)
1395 * Re-acquire the LCT table and synchronize us to the adapter.
1397 if ((error = ASR_acquireLct(sc)) == 0) {
1398 error = ASR_acquireHrt(sc);
1405 bus = sc->ha_MaxBus;
1406 /* Reset all existing cached TID lookups */
1408 int target, event = 0;
1411 * Scan for all targets on this bus to see if they
1412 * got affected by the rescan.
1414 for (target = 0; target <= sc->ha_MaxId; ++target) {
1417 /* Stay away from the controller ID */
1418 if (target == sc->ha_adapter_target[bus]) {
1421 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
1422 PI2O_LCT_ENTRY Device;
1423 tid_t TID = (tid_t)-1;
1427 * See if the cached TID changed. Search for
1428 * the device in our new LCT.
1430 for (Device = sc->ha_LCT->LCTEntry;
1431 Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT)
1432 + I2O_LCT_getTableSize(sc->ha_LCT));
1434 if ((Device->le_type != I2O_UNKNOWN)
1435 && (Device->le_bus == bus)
1436 && (Device->le_target == target)
1437 && (Device->le_lun == lun)
1438 && (I2O_LCT_ENTRY_getUserTID(Device)
1440 TID = I2O_LCT_ENTRY_getLocalTID(
1446 * Indicate to the OS that the label needs
1447 * to be recalculated, or that the specific
1448 * open device is no longer valid (Merde)
1449 * because the cached TID changed.
1451 LastTID = ASR_getTid (sc, bus, target, lun);
1452 if (LastTID != TID) {
1453 struct cam_path * path;
1455 if (xpt_create_path(&path,
1457 cam_sim_path(sc->ha_sim[bus]),
1458 target, lun) != CAM_REQ_CMP) {
1459 if (TID == (tid_t)-1) {
1460 event |= AC_LOST_DEVICE;
1462 event |= AC_INQ_CHANGED
1463 | AC_GETDEV_CHANGED;
1466 if (TID == (tid_t)-1) {
1470 } else if (LastTID == (tid_t)-1) {
1471 struct ccb_getdev ccb;
1475 path, /*priority*/5);
1491 * We have the option of clearing the
1492 * cached TID for it to be rescanned, or to
1493 * set it now even if the device never got
1494 * accessed. We chose the later since we
1495 * currently do not use the condition that
1496 * the TID ever got cached.
1498 ASR_setTid (sc, bus, target, lun, TID);
1502 * The xpt layer can not handle multiple events at the
1505 if (event & AC_LOST_DEVICE) {
1506 xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL);
1508 if (event & AC_INQ_CHANGED) {
1509 xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL);
1511 if (event & AC_GETDEV_CHANGED) {
1512 xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL);
1514 } while (--bus >= 0);
1518 /*-------------------------------------------------------------------------*/
1519 /* Function ASR_reset */
1520 /*-------------------------------------------------------------------------*/
1521 /* The Parameters Passed To This Function Are : */
1522 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1524 /* This Function Will reset the adapter and resynchronize any data */
1527 /*-------------------------------------------------------------------------*/
1531 IN Asr_softc_t * sc)
1536 if ((sc->ha_in_reset == HA_IN_RESET)
1537 || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) {
1542 * Promotes HA_OPERATIONAL to HA_IN_RESET,
1543 * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY.
1545 ++(sc->ha_in_reset);
1546 if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) {
1547 debug_asr_printf ("ASR_resetIOP failed\n");
1549 * We really need to take this card off-line, easier said
1550 * than make sense. Better to keep retrying for now since if a
1551 * UART cable is connected the blinkLEDs the adapter is now in
1552 * a hard state requiring action from the monitor commands to
1553 * the HBA to continue. For debugging waiting forever is a
1554 * good thing. In a production system, however, one may wish
1555 * to instead take the card off-line ...
1557 # if 0 && (defined(HA_OFF_LINE))
1559 * Take adapter off-line.
1561 printf ("asr%d: Taking adapter off-line\n",
1563 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1565 sc->ha_in_reset = HA_OFF_LINE;
1570 while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0);
1573 retVal = ASR_init (sc);
1576 debug_asr_printf ("ASR_init failed\n");
1577 sc->ha_in_reset = HA_OFF_LINE;
1580 if (ASR_rescan (sc) != 0) {
1581 debug_asr_printf ("ASR_rescan failed\n");
1583 ASR_failActiveCommands (sc);
1584 if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) {
1585 printf ("asr%d: Brining adapter back on-line\n",
1587 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1590 sc->ha_in_reset = HA_OPERATIONAL;
1595 * Device timeout handler.
1601 union asr_ccb * ccb = (union asr_ccb *)arg;
1602 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
1605 debug_asr_print_path(ccb);
1606 debug_asr_printf("timed out");
1609 * Check if the adapter has locked up?
1611 if ((s = ASR_getBlinkLedCode(sc)) != 0) {
1613 printf ("asr%d: Blink LED 0x%x resetting adapter\n",
1614 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s);
1615 if (ASR_reset (sc) == ENXIO) {
1616 /* Try again later */
1617 ccb->ccb_h.timeout_ch = timeout(asr_timeout,
1619 (ccb->ccb_h.timeout * hz) / 1000);
1624 * Abort does not function on the ASR card!!! Walking away from
1625 * the SCSI command is also *very* dangerous. A SCSI BUS reset is
1626 * our best bet, followed by a complete adapter reset if that fails.
1629 /* Check if we already timed out once to raise the issue */
1630 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) {
1631 debug_asr_printf (" AGAIN\nreinitializing adapter\n");
1632 if (ASR_reset (sc) == ENXIO) {
1633 ccb->ccb_h.timeout_ch = timeout(asr_timeout,
1635 (ccb->ccb_h.timeout * hz) / 1000);
1640 debug_asr_printf ("\nresetting bus\n");
1641 /* If the BUS reset does not take, then an adapter reset is next! */
1642 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1643 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1644 ccb->ccb_h.timeout_ch = timeout(asr_timeout, (caddr_t)ccb,
1645 (ccb->ccb_h.timeout * hz) / 1000);
1646 ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)));
1647 xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL);
1652 * send a message asynchronously
1656 IN Asr_softc_t * sc,
1657 IN PI2O_MESSAGE_FRAME Message)
1659 OUT U32 MessageOffset;
1660 union asr_ccb * ccb;
1662 debug_asr_printf ("Host Command Dump:\n");
1663 debug_asr_dump_message (Message);
1665 ccb = (union asr_ccb *)(long)
1666 I2O_MESSAGE_FRAME_getInitiatorContext64(Message);
1668 if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) {
1669 #ifdef ASR_MEASURE_PERFORMANCE
1673 ++sc->ha_performance.command_count[
1674 (int) ccb->csio.cdb_io.cdb_bytes[0]];
1675 DEQ_TIMEQ_FREE_LIST(startTimeIndex,
1676 sc->ha_timeQFreeList,
1677 sc->ha_timeQFreeHead,
1678 sc->ha_timeQFreeTail);
1679 if (-1 != startTimeIndex) {
1680 microtime(&(sc->ha_timeQ[startTimeIndex]));
1682 /* Time stamp the command before we send it out */
1683 ((PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *) Message)->
1684 PrivateMessageFrame.TransactionContext
1685 = (I2O_TRANSACTION_CONTEXT) startTimeIndex;
1687 ++sc->ha_submitted_ccbs_count;
1688 if (sc->ha_performance.max_submit_count
1689 < sc->ha_submitted_ccbs_count) {
1690 sc->ha_performance.max_submit_count
1691 = sc->ha_submitted_ccbs_count;
1695 bcopy (Message, sc->ha_Fvirt + MessageOffset,
1696 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
1698 ASR_ccbAdd (sc, ccb);
1700 /* Post the command */
1701 sc->ha_Virt->ToFIFO = MessageOffset;
1703 if (ASR_getBlinkLedCode(sc)) {
1705 * Unlikely we can do anything if we can't grab a
1706 * message frame :-(, but lets give it a try.
1708 (void)ASR_reset (sc);
1711 return (MessageOffset);
1715 /* Simple Scatter Gather elements */
1716 #define SG(SGL,Index,Flags,Buffer,Size) \
1717 I2O_FLAGS_COUNT_setCount( \
1718 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1720 I2O_FLAGS_COUNT_setFlags( \
1721 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1722 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \
1723 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \
1724 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \
1725 (Buffer == NULL) ? NULL : KVTOPHYS(Buffer))
1728 * Retrieve Parameter Group.
1729 * Buffer must be allocated using defAlignLong macro.
1733 IN Asr_softc_t * sc,
1737 IN unsigned BufferSize)
1739 struct paramGetMessage {
1740 I2O_UTIL_PARAMS_GET_MESSAGE M;
1742 sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)];
1744 I2O_PARAM_OPERATIONS_LIST_HEADER Header;
1745 I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1];
1748 defAlignLong(struct paramGetMessage, Message);
1749 struct Operations * Operations_Ptr;
1750 I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr;
1751 struct ParamBuffer {
1752 I2O_PARAM_RESULTS_LIST_HEADER Header;
1753 I2O_PARAM_READ_OPERATION_RESULT Read;
1757 Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message,
1758 sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1759 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1760 Operations_Ptr = (struct Operations *)((char *)Message_Ptr
1761 + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1762 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1763 bzero ((void *)Operations_Ptr, sizeof(struct Operations));
1764 I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount(
1765 &(Operations_Ptr->Header), 1);
1766 I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation(
1767 &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET);
1768 I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount(
1769 &(Operations_Ptr->Template[0]), 0xFFFF);
1770 I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber(
1771 &(Operations_Ptr->Template[0]), Group);
1772 bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)),
1775 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1777 + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1778 / sizeof(U32)) << 4));
1779 I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame),
1781 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
1782 I2O_UTIL_PARAMS_GET);
1784 * Set up the buffers as scatter gather elements.
1786 SG(&(Message_Ptr->SGL), 0,
1787 I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER,
1788 Operations_Ptr, sizeof(struct Operations));
1789 SG(&(Message_Ptr->SGL), 1,
1790 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
1791 Buffer_Ptr, BufferSize);
1793 if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP)
1794 && (Buffer_Ptr->Header.ResultCount)) {
1795 return ((void *)(Buffer_Ptr->Info));
1797 return ((void *)NULL);
1798 } /* ASR_getParams */
1801 * Acquire the LCT information.
1805 INOUT Asr_softc_t * sc)
1807 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
1808 PI2O_SGE_SIMPLE_ELEMENT sg;
1809 int MessageSizeInBytes;
1813 PI2O_LCT_ENTRY Entry;
1816 * sc value assumed valid
1818 MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)
1819 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT);
1820 if ((Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)malloc (
1821 MessageSizeInBytes, M_TEMP, M_WAITOK))
1822 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1825 (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes);
1826 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1828 (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1829 / sizeof(U32)) << 4)));
1830 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
1831 I2O_EXEC_LCT_NOTIFY);
1832 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
1833 I2O_CLASS_MATCH_ANYCLASS);
1835 * Call the LCT table to determine the number of device entries
1836 * to reserve space for.
1838 SG(&(Message_Ptr->SGL), 0,
1839 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table,
1842 * since this code is reused in several systems, code efficiency
1843 * is greater by using a shift operation rather than a divide by
1844 * sizeof(u_int32_t).
1846 I2O_LCT_setTableSize(&Table,
1847 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1848 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1850 * Determine the size of the LCT table.
1853 free (sc->ha_LCT, M_TEMP);
1856 * malloc only generates contiguous memory when less than a
1857 * page is expected. We must break the request up into an SG list ...
1859 if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <=
1860 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)))
1861 || (len > (128 * 1024))) { /* Arbitrary */
1862 free (Message_Ptr, M_TEMP);
1865 if ((sc->ha_LCT = (PI2O_LCT)malloc (len, M_TEMP, M_WAITOK))
1866 == (PI2O_LCT)NULL) {
1867 free (Message_Ptr, M_TEMP);
1871 * since this code is reused in several systems, code efficiency
1872 * is greater by using a shift operation rather than a divide by
1873 * sizeof(u_int32_t).
1875 I2O_LCT_setTableSize(sc->ha_LCT,
1876 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1878 * Convert the access to the LCT table into a SG list.
1880 sg = Message_Ptr->SGL.u.Simple;
1881 v = (caddr_t)(sc->ha_LCT);
1883 int next, base, span;
1886 next = base = KVTOPHYS(v);
1887 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
1889 /* How far can we go contiguously */
1890 while ((len > 0) && (base == next)) {
1893 next = trunc_page(base) + PAGE_SIZE;
1904 /* Construct the Flags */
1905 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
1907 int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT;
1909 rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT
1910 | I2O_SGL_FLAGS_LAST_ELEMENT
1911 | I2O_SGL_FLAGS_END_OF_BUFFER);
1913 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw);
1921 * Incrementing requires resizing of the packet.
1924 MessageSizeInBytes += sizeof(*sg);
1925 I2O_MESSAGE_FRAME_setMessageSize(
1926 &(Message_Ptr->StdMessageFrame),
1927 I2O_MESSAGE_FRAME_getMessageSize(
1928 &(Message_Ptr->StdMessageFrame))
1929 + (sizeof(*sg) / sizeof(U32)));
1931 PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr;
1933 if ((NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)
1934 malloc (MessageSizeInBytes, M_TEMP, M_WAITOK))
1935 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1936 free (sc->ha_LCT, M_TEMP);
1937 sc->ha_LCT = (PI2O_LCT)NULL;
1938 free (Message_Ptr, M_TEMP);
1941 span = ((caddr_t)sg) - (caddr_t)Message_Ptr;
1942 bcopy ((caddr_t)Message_Ptr,
1943 (caddr_t)NewMessage_Ptr, span);
1944 free (Message_Ptr, M_TEMP);
1945 sg = (PI2O_SGE_SIMPLE_ELEMENT)
1946 (((caddr_t)NewMessage_Ptr) + span);
1947 Message_Ptr = NewMessage_Ptr;
1952 retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1953 free (Message_Ptr, M_TEMP);
1954 if (retval != CAM_REQ_CMP) {
1958 /* If the LCT table grew, lets truncate accesses */
1959 if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) {
1960 I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table));
1962 for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY)
1963 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1965 Entry->le_type = I2O_UNKNOWN;
1966 switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) {
1968 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
1969 Entry->le_type = I2O_BSA;
1972 case I2O_CLASS_SCSI_PERIPHERAL:
1973 Entry->le_type = I2O_SCSI;
1976 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
1977 Entry->le_type = I2O_FCA;
1980 case I2O_CLASS_BUS_ADAPTER_PORT:
1981 Entry->le_type = I2O_PORT | I2O_SCSI;
1983 case I2O_CLASS_FIBRE_CHANNEL_PORT:
1984 if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) ==
1985 I2O_CLASS_FIBRE_CHANNEL_PORT) {
1986 Entry->le_type = I2O_PORT | I2O_FCA;
1988 { struct ControllerInfo {
1989 I2O_PARAM_RESULTS_LIST_HEADER Header;
1990 I2O_PARAM_READ_OPERATION_RESULT Read;
1991 I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1993 defAlignLong(struct ControllerInfo, Buffer);
1994 PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1996 Entry->le_bus = 0xff;
1997 Entry->le_target = 0xff;
1998 Entry->le_lun = 0xff;
2000 if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)
2002 I2O_LCT_ENTRY_getLocalTID(Entry),
2003 I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO,
2004 Buffer, sizeof(struct ControllerInfo)))
2005 == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) {
2009 = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID(
2016 { struct DeviceInfo {
2017 I2O_PARAM_RESULTS_LIST_HEADER Header;
2018 I2O_PARAM_READ_OPERATION_RESULT Read;
2019 I2O_DPT_DEVICE_INFO_SCALAR Info;
2021 defAlignLong (struct DeviceInfo, Buffer);
2022 PI2O_DPT_DEVICE_INFO_SCALAR Info;
2024 Entry->le_bus = 0xff;
2025 Entry->le_target = 0xff;
2026 Entry->le_lun = 0xff;
2028 if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR)
2030 I2O_LCT_ENTRY_getLocalTID(Entry),
2031 I2O_DPT_DEVICE_INFO_GROUP_NO,
2032 Buffer, sizeof(struct DeviceInfo)))
2033 == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) {
2037 |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info);
2039 = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info);
2040 if ((Entry->le_bus > sc->ha_MaxBus)
2041 && (Entry->le_bus <= MAX_CHANNEL)) {
2042 sc->ha_MaxBus = Entry->le_bus;
2045 = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info);
2047 = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info);
2051 * A zero return value indicates success.
2054 } /* ASR_acquireLct */
2057 * Initialize a message frame.
2058 * We assume that the CDB has already been set up, so all we do here is
2059 * generate the Scatter Gather list.
2061 STATIC INLINE PI2O_MESSAGE_FRAME
2063 IN union asr_ccb * ccb,
2064 OUT PI2O_MESSAGE_FRAME Message)
2066 int next, span, base, rw;
2067 OUT PI2O_MESSAGE_FRAME Message_Ptr;
2068 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
2069 PI2O_SGE_SIMPLE_ELEMENT sg;
2071 vm_size_t size, len;
2074 /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */
2075 bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message),
2076 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)));
2079 int target = ccb->ccb_h.target_id;
2080 int lun = ccb->ccb_h.target_lun;
2081 int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
2084 if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) {
2085 PI2O_LCT_ENTRY Device;
2088 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2089 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2091 if ((Device->le_type != I2O_UNKNOWN)
2092 && (Device->le_bus == bus)
2093 && (Device->le_target == target)
2094 && (Device->le_lun == lun)
2095 && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) {
2096 TID = I2O_LCT_ENTRY_getLocalTID(Device);
2097 ASR_setTid (sc, Device->le_bus,
2098 Device->le_target, Device->le_lun,
2104 if (TID == (tid_t)0) {
2105 return ((PI2O_MESSAGE_FRAME)NULL);
2107 I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID);
2108 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(
2109 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID);
2111 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 |
2112 (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2113 / sizeof(U32)) << 4));
2114 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
2115 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2116 - sizeof(I2O_SG_ELEMENT)) / sizeof(U32));
2117 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
2118 I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE);
2119 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2120 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC);
2121 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
2122 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2123 I2O_SCB_FLAG_ENABLE_DISCONNECT
2124 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2125 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2127 * We do not need any (optional byteswapping) method access to
2128 * the Initiator & Transaction context field.
2130 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
2132 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2133 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID);
2137 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(
2138 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len);
2139 bcopy (&(ccb->csio.cdb_io),
2140 ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len);
2143 * Given a buffer describing a transfer, set up a scatter/gather map
2144 * in a ccb to map that SCSI transfer.
2147 rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR;
2149 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
2150 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2151 (ccb->csio.dxfer_len)
2152 ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE
2153 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2154 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2155 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)
2156 : (I2O_SCB_FLAG_XFER_FROM_DEVICE
2157 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2158 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2159 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER))
2160 : (I2O_SCB_FLAG_ENABLE_DISCONNECT
2161 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2162 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2165 * Given a transfer described by a `data', fill in the SG list.
2167 sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0];
2169 len = ccb->csio.dxfer_len;
2170 v = ccb->csio.data_ptr;
2171 ASSERT (ccb->csio.dxfer_len >= 0);
2172 MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr);
2173 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
2174 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len);
2175 while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2176 Message_Ptr)->SGL.u.Simple[SG_SIZE])) {
2178 next = base = KVTOPHYS(v);
2179 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
2181 /* How far can we go contiguously */
2182 while ((len > 0) && (base == next)) {
2183 next = trunc_page(base) + PAGE_SIZE;
2194 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
2196 rw |= I2O_SGL_FLAGS_LAST_ELEMENT;
2198 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount),
2199 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw);
2201 MessageSize += sizeof(*sg) / sizeof(U32);
2203 /* We always do the request sense ... */
2204 if ((span = ccb->csio.sense_len) == 0) {
2205 span = sizeof(ccb->csio.sense_data);
2207 SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2208 &(ccb->csio.sense_data), span);
2209 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
2210 MessageSize + (sizeof(*sg) / sizeof(U32)));
2211 return (Message_Ptr);
2212 } /* ASR_init_message */
2215 * Reset the adapter.
2219 INOUT Asr_softc_t * sc)
2221 struct initOutBoundMessage {
2222 I2O_EXEC_OUTBOUND_INIT_MESSAGE M;
2225 defAlignLong(struct initOutBoundMessage,Message);
2226 PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr;
2227 OUT U32 * volatile Reply_Ptr;
2231 * Build up our copy of the Message.
2233 Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message,
2234 sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE));
2235 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2236 I2O_EXEC_OUTBOUND_INIT);
2237 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE);
2238 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr,
2239 sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME));
2241 * Reset the Reply Status
2243 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
2244 + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0;
2245 SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr,
2248 * Send the Message out
2250 if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
2254 * Wait for a response (Poll).
2256 while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED);
2258 * Re-enable the interrupts.
2260 sc->ha_Virt->Mask = Old;
2262 * Populate the outbound table.
2264 if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2266 /* Allocate the reply frames */
2267 size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2268 * sc->ha_Msgs_Count;
2271 * contigmalloc only works reliably at
2272 * initialization time.
2274 if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2275 contigmalloc (size, M_DEVBUF, M_WAITOK, 0ul,
2276 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul))
2277 != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2278 (void)bzero ((char *)sc->ha_Msgs, size);
2279 sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs);
2283 /* Initialize the outbound FIFO */
2284 if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL)
2285 for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys;
2287 sc->ha_Virt->FromFIFO = addr;
2288 addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME);
2290 return (*Reply_Ptr);
2293 } /* ASR_initOutBound */
2296 * Set the system table
2300 IN Asr_softc_t * sc)
2302 PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr;
2303 PI2O_SET_SYSTAB_HEADER SystemTable;
2305 PI2O_SGE_SIMPLE_ELEMENT sg;
2308 if ((SystemTable = (PI2O_SET_SYSTAB_HEADER)malloc (
2309 sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK))
2310 == (PI2O_SET_SYSTAB_HEADER)NULL) {
2313 bzero (SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2314 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2315 ++SystemTable->NumberEntries;
2317 if ((Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)malloc (
2318 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2319 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)),
2320 M_TEMP, M_WAITOK)) == (PI2O_EXEC_SYS_TAB_SET_MESSAGE)NULL) {
2321 free (SystemTable, M_TEMP);
2324 (void)ASR_fillMessage((char *)Message_Ptr,
2325 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2326 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)));
2327 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2329 (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2330 / sizeof(U32)) << 4)));
2331 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2332 I2O_EXEC_SYS_TAB_SET);
2334 * Call the LCT table to determine the number of device entries
2335 * to reserve space for.
2336 * since this code is reused in several systems, code efficiency
2337 * is greater by using a shift operation rather than a divide by
2338 * sizeof(u_int32_t).
2340 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
2341 + ((I2O_MESSAGE_FRAME_getVersionOffset(
2342 &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2));
2343 SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2345 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2348 ? (I2O_SGL_FLAGS_DIR)
2349 : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)),
2350 &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable));
2353 SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2354 SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT
2355 | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2356 retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2357 free (Message_Ptr, M_TEMP);
2358 free (SystemTable, M_TEMP);
2360 } /* ASR_setSysTab */
2364 INOUT Asr_softc_t * sc)
2366 defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message);
2367 I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr;
2370 I2O_HRT_ENTRY Entry[MAX_CHANNEL];
2372 u_int8_t NumberOfEntries;
2373 PI2O_HRT_ENTRY Entry;
2375 bzero ((void *)&Hrt, sizeof (Hrt));
2376 Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message,
2377 sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2378 + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2379 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2381 + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2382 / sizeof(U32)) << 4)));
2383 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
2387 * Set up the buffers as scatter gather elements.
2389 SG(&(Message_Ptr->SGL), 0,
2390 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2392 if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) {
2395 if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header))
2396 > (MAX_CHANNEL + 1)) {
2397 NumberOfEntries = MAX_CHANNEL + 1;
2399 for (Entry = Hrt.Header.HRTEntry;
2400 NumberOfEntries != 0;
2401 ++Entry, --NumberOfEntries) {
2402 PI2O_LCT_ENTRY Device;
2404 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2405 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2407 if (I2O_LCT_ENTRY_getLocalTID(Device)
2408 == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) {
2409 Device->le_bus = I2O_HRT_ENTRY_getAdapterID(
2411 if ((Device->le_bus > sc->ha_MaxBus)
2412 && (Device->le_bus <= MAX_CHANNEL)) {
2413 sc->ha_MaxBus = Device->le_bus;
2419 } /* ASR_acquireHrt */
2422 * Enable the adapter.
2426 IN Asr_softc_t * sc)
2428 defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message);
2429 PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr;
2431 Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message,
2432 sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE));
2433 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2434 I2O_EXEC_SYS_ENABLE);
2435 return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0);
2436 } /* ASR_enableSys */
2439 * Perform the stages necessary to initialize the adapter
2443 IN Asr_softc_t * sc)
2445 return ((ASR_initOutBound(sc) == 0)
2446 || (ASR_setSysTab(sc) != CAM_REQ_CMP)
2447 || (ASR_enableSys(sc) != CAM_REQ_CMP));
2451 * Send a Synchronize Cache command to the target device.
2455 IN Asr_softc_t * sc,
2463 * We will not synchronize the device when there are outstanding
2464 * commands issued by the OS (this is due to a locked up device,
2465 * as the OS normally would flush all outstanding commands before
2466 * issuing a shutdown or an adapter reset).
2468 if ((sc != (Asr_softc_t *)NULL)
2469 && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL)
2470 && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1)
2471 && (TID != (tid_t)0)) {
2472 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
2473 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
2476 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
2477 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2478 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2480 I2O_MESSAGE_FRAME_setVersionOffset(
2481 (PI2O_MESSAGE_FRAME)Message_Ptr,
2483 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2484 - sizeof(I2O_SG_ELEMENT))
2485 / sizeof(U32)) << 4));
2486 I2O_MESSAGE_FRAME_setMessageSize(
2487 (PI2O_MESSAGE_FRAME)Message_Ptr,
2488 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2489 - sizeof(I2O_SG_ELEMENT))
2491 I2O_MESSAGE_FRAME_setInitiatorAddress (
2492 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
2493 I2O_MESSAGE_FRAME_setFunction(
2494 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
2495 I2O_MESSAGE_FRAME_setTargetAddress(
2496 (PI2O_MESSAGE_FRAME)Message_Ptr, TID);
2497 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2498 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2500 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID);
2501 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2502 I2O_SCB_FLAG_ENABLE_DISCONNECT
2503 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2504 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2505 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2506 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2507 DPT_ORGANIZATION_ID);
2508 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
2509 Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE;
2510 Message_Ptr->CDB[1] = (lun << 5);
2512 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2513 (I2O_SCB_FLAG_XFER_FROM_DEVICE
2514 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2515 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2516 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2518 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2525 IN Asr_softc_t * sc)
2527 int bus, target, lun;
2529 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
2530 for (target = 0; target <= sc->ha_MaxId; ++target) {
2531 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
2532 ASR_sync(sc,bus,target,lun);
2539 * Reset the HBA, targets and BUS.
2540 * Currently this resets *all* the SCSI busses.
2544 IN Asr_softc_t * sc)
2546 ASR_synchronize (sc);
2547 (void)ASR_reset (sc);
2548 } /* asr_hbareset */
2551 * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP
2552 * limit and a reduction in error checking (in the pre 4.0 case).
2556 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
2561 IN Asr_softc_t * sc)
2566 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
2568 * I2O specification says we must find first *memory* mapped BAR
2570 for (rid = PCIR_MAPS;
2571 rid < (PCIR_MAPS + 4 * sizeof(u_int32_t));
2572 rid += sizeof(u_int32_t)) {
2573 p = pci_read_config(tag, rid, sizeof(p));
2581 if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2584 p = pci_read_config(tag, rid, sizeof(p));
2585 pci_write_config(tag, rid, -1, sizeof(p));
2586 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2587 pci_write_config(tag, rid, p, sizeof(p));
2592 * The 2005S Zero Channel RAID solution is not a perfect PCI
2593 * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once
2594 * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to
2595 * BAR0+2MB and sets it's size to 2MB. The IOP registers are
2596 * accessible via BAR0, the messaging registers are accessible
2597 * via BAR1. If the subdevice code is 50 to 59 decimal.
2599 s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s));
2600 if (s != 0xA5111044) {
2601 s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s));
2602 if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0)
2603 && (ADPTDOMINATOR_SUB_ID_START <= s)
2604 && (s <= ADPTDOMINATOR_SUB_ID_END)) {
2605 l = MAX_MAP; /* Conjoined BAR Raptor Daptor */
2609 sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2610 p, p + l, l, RF_ACTIVE);
2611 if (sc->ha_mem_res == (struct resource *)NULL) {
2614 sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res);
2615 if (sc->ha_Base == (void *)NULL) {
2618 sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res);
2619 if (s == 0xA5111044) { /* Split BAR Raptor Daptor */
2620 if ((rid += sizeof(u_int32_t))
2621 >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2624 p = pci_read_config(tag, rid, sizeof(p));
2625 pci_write_config(tag, rid, -1, sizeof(p));
2626 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2627 pci_write_config(tag, rid, p, sizeof(p));
2632 sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2633 p, p + l, l, RF_ACTIVE);
2634 if (sc->ha_mes_res == (struct resource *)NULL) {
2637 if ((void *)rman_get_start(sc->ha_mes_res) == (void *)NULL) {
2640 sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res);
2642 sc->ha_Fvirt = (U8 *)(sc->ha_Virt);
2645 vm_size_t psize, poffs;
2648 * I2O specification says we must find first *memory* mapped BAR
2650 for (rid = PCI_MAP_REG_START;
2651 rid < (PCI_MAP_REG_START + 4 * sizeof(u_int32_t));
2652 rid += sizeof(u_int32_t)) {
2653 p = pci_conf_read (tag, rid);
2658 if (rid >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) {
2659 rid = PCI_MAP_REG_START;
2662 ** save old mapping, get size and type of memory
2664 ** type is in the lowest four bits.
2665 ** If device requires 2^n bytes, the next
2666 ** n-4 bits are read as 0.
2669 sc->ha_Base = (void *)((p = pci_conf_read (tag, rid))
2670 & PCI_MAP_MEMORY_ADDRESS_MASK);
2671 pci_conf_write (tag, rid, 0xfffffffful);
2672 l = pci_conf_read (tag, rid);
2673 pci_conf_write (tag, rid, p);
2679 if (!((l & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M
2680 && ((u_long)sc->ha_Base & ~0xfffff) == 0)
2681 && ((l & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT)) {
2683 "asr_pci_map_mem failed: bad memory type=0x%x\n",
2692 psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK);
2693 if (psize > MAX_MAP) {
2697 * The 2005S Zero Channel RAID solution is not a perfect PCI
2698 * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once
2699 * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to
2700 * BAR0+2MB and sets it's size to 2MB. The IOP registers are
2701 * accessible via BAR0, the messaging registers are accessible
2702 * via BAR1. If the subdevice code is 50 to 59 decimal.
2704 s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s));
2705 if (s != 0xA5111044) {
2706 s = pci_conf_read (tag, PCIR_SUBVEND_0)
2707 if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0)
2708 && (ADPTDOMINATOR_SUB_ID_START <= s)
2709 && (s <= ADPTDOMINATOR_SUB_ID_END)) {
2714 if ((sc->ha_Base == (void *)NULL)
2715 || (sc->ha_Base == (void *)PCI_MAP_MEMORY_ADDRESS_MASK)) {
2716 debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n");
2721 ** Truncate sc->ha_Base to page boundary.
2722 ** (Or does pmap_mapdev the job?)
2725 poffs = (u_long)sc->ha_Base - trunc_page ((u_long)sc->ha_Base);
2726 sc->ha_Virt = (i2oRegs_t *)pmap_mapdev ((u_long)sc->ha_Base - poffs,
2729 if (sc->ha_Virt == (i2oRegs_t *)NULL) {
2733 sc->ha_Virt = (i2oRegs_t *)((u_long)sc->ha_Virt + poffs);
2734 if (s == 0xA5111044) {
2735 if ((rid += sizeof(u_int32_t))
2736 >= (PCI_MAP_REG_START + 4 * sizeof(u_int32_t))) {
2741 ** save old mapping, get size and type of memory
2743 ** type is in the lowest four bits.
2744 ** If device requires 2^n bytes, the next
2745 ** n-4 bits are read as 0.
2748 if ((((p = pci_conf_read (tag, rid))
2749 & PCI_MAP_MEMORY_ADDRESS_MASK) == 0L)
2750 || ((p & PCI_MAP_MEMORY_ADDRESS_MASK)
2751 == PCI_MAP_MEMORY_ADDRESS_MASK)) {
2752 debug_asr_printf ("asr_pci_map_mem: not configured by bios.\n");
2754 pci_conf_write (tag, rid, 0xfffffffful);
2755 l = pci_conf_read (tag, rid);
2756 pci_conf_write (tag, rid, p);
2757 p &= PCI_MAP_MEMORY_TYPE_MASK;
2763 if (!((l & PCI_MAP_MEMORY_TYPE_MASK)
2764 == PCI_MAP_MEMORY_TYPE_32BIT_1M
2765 && (p & ~0xfffff) == 0)
2766 && ((l & PCI_MAP_MEMORY_TYPE_MASK)
2767 != PCI_MAP_MEMORY_TYPE_32BIT)) {
2769 "asr_pci_map_mem failed: bad memory type=0x%x\n",
2778 psize = -(l & PCI_MAP_MEMORY_ADDRESS_MASK);
2779 if (psize > MAX_MAP) {
2784 ** Truncate p to page boundary.
2785 ** (Or does pmap_mapdev the job?)
2788 poffs = p - trunc_page (p);
2789 sc->ha_Fvirt = (U8 *)pmap_mapdev (p - poffs, psize + poffs);
2791 if (sc->ha_Fvirt == (U8 *)NULL) {
2795 sc->ha_Fvirt = (U8 *)((u_long)sc->ha_Fvirt + poffs);
2797 sc->ha_Fvirt = (U8 *)(sc->ha_Virt);
2801 } /* asr_pci_map_mem */
2804 * A simplified copy of the real pci_map_int with additional
2805 * registration requirements.
2809 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
2814 IN Asr_softc_t * sc)
2816 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
2819 sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid,
2820 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2821 if (sc->ha_irq_res == (struct resource *)NULL) {
2824 if (bus_setup_intr(tag, sc->ha_irq_res, INTR_TYPE_CAM,
2825 (driver_intr_t *)asr_intr, (void *)sc, &(sc->ha_intr))) {
2828 sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char));
2830 if (!pci_map_int(tag, (pci_inthand_t *)asr_intr,
2831 (void *)sc, &cam_imask)) {
2834 sc->ha_irq = pci_conf_read(tag, PCIR_INTLINE);
2837 } /* asr_pci_map_int */
2840 * Attach the devices, and virtual devices to the driver list.
2843 asr_attach (ATTACH_ARGS)
2846 struct scsi_inquiry_data * iq;
2849 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == (Asr_softc_t *)NULL) {
2850 ATTACH_RETURN(ENOMEM);
2852 if (Asr_softc == (Asr_softc_t *)NULL) {
2854 * Fixup the OS revision as saved in the dptsig for the
2855 * engine (dptioctl.h) to pick up.
2857 bcopy (osrelease, &ASR_sig.dsDescription[16], 5);
2858 printf ("asr%d: major=%d\n", unit, asr_cdevsw.d_maj);
2861 * Initialize the software structure
2863 bzero (sc, sizeof(*sc));
2864 LIST_INIT(&(sc->ha_ccb));
2865 # ifdef ASR_MEASURE_PERFORMANCE
2869 // initialize free list for timeQ
2870 sc->ha_timeQFreeHead = 0;
2871 sc->ha_timeQFreeTail = MAX_TIMEQ_SIZE - 1;
2872 for (i = 0; i < MAX_TIMEQ_SIZE; i++) {
2873 sc->ha_timeQFreeList[i] = i;
2877 /* Link us into the HA list */
2881 for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next));
2885 PI2O_EXEC_STATUS_GET_REPLY status;
2889 * This is the real McCoy!
2891 if (!asr_pci_map_mem(tag, sc)) {
2892 printf ("asr%d: could not map memory\n", unit);
2893 ATTACH_RETURN(ENXIO);
2895 /* Enable if not formerly enabled */
2896 #if defined(__DragonFly__) || __FreeBSD_version >= 400000
2897 pci_write_config (tag, PCIR_COMMAND,
2898 pci_read_config (tag, PCIR_COMMAND, sizeof(char))
2899 | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char));
2900 /* Knowledge is power, responsibility is direct */
2902 struct pci_devinfo {
2903 STAILQ_ENTRY(pci_devinfo) pci_links;
2904 struct resource_list resources;
2906 } * dinfo = device_get_ivars(tag);
2907 sc->ha_pciBusNum = dinfo->cfg.bus;
2908 sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3)
2912 pci_conf_write (tag, PCIR_COMMAND,
2913 pci_conf_read (tag, PCIR_COMMAND)
2914 | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
2915 /* Knowledge is power, responsibility is direct */
2916 switch (pci_mechanism) {
2919 sc->ha_pciBusNum = tag.cfg1 >> 16;
2920 sc->ha_pciDeviceNum = tag.cfg1 >> 8;
2923 sc->ha_pciBusNum = tag.cfg2.forward;
2924 sc->ha_pciDeviceNum = ((tag.cfg2.enable >> 1) & 7)
2925 | (tag.cfg2.port >> 5);
2928 /* Check if the device is there? */
2929 if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0)
2930 || ((status = (PI2O_EXEC_STATUS_GET_REPLY)malloc (
2931 sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK))
2932 == (PI2O_EXEC_STATUS_GET_REPLY)NULL)
2933 || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) {
2934 printf ("asr%d: could not initialize hardware\n", unit);
2935 ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */
2937 sc->ha_SystemTable.OrganizationID = status->OrganizationID;
2938 sc->ha_SystemTable.IOP_ID = status->IOP_ID;
2939 sc->ha_SystemTable.I2oVersion = status->I2oVersion;
2940 sc->ha_SystemTable.IopState = status->IopState;
2941 sc->ha_SystemTable.MessengerType = status->MessengerType;
2942 sc->ha_SystemTable.InboundMessageFrameSize
2943 = status->InboundMFrameSize;
2944 sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow
2945 = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO));
2947 if (!asr_pci_map_int(tag, (void *)sc)) {
2948 printf ("asr%d: could not map interrupt\n", unit);
2949 ATTACH_RETURN(ENXIO);
2952 /* Adjust the maximim inbound count */
2953 if (((sc->ha_QueueSize
2954 = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status))
2956 || (sc->ha_QueueSize == 0)) {
2957 sc->ha_QueueSize = MAX_INBOUND;
2960 /* Adjust the maximum outbound count */
2961 if (((sc->ha_Msgs_Count
2962 = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status))
2964 || (sc->ha_Msgs_Count == 0)) {
2965 sc->ha_Msgs_Count = MAX_OUTBOUND;
2967 if (sc->ha_Msgs_Count > sc->ha_QueueSize) {
2968 sc->ha_Msgs_Count = sc->ha_QueueSize;
2971 /* Adjust the maximum SG size to adapter */
2972 if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize(
2973 status) << 2)) > MAX_INBOUND_SIZE) {
2974 size = MAX_INBOUND_SIZE;
2976 free (status, M_TEMP);
2977 sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2978 + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT);
2982 * Only do a bus/HBA reset on the first time through. On this
2983 * first time through, we do not send a flush to the devices.
2985 if (ASR_init(sc) == 0) {
2987 I2O_PARAM_RESULTS_LIST_HEADER Header;
2988 I2O_PARAM_READ_OPERATION_RESULT Read;
2989 I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2991 defAlignLong (struct BufferInfo, Buffer);
2992 PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2993 # define FW_DEBUG_BLED_OFFSET 8
2995 if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)
2996 ASR_getParams(sc, 0,
2997 I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO,
2998 Buffer, sizeof(struct BufferInfo)))
2999 != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) {
3000 sc->ha_blinkLED = sc->ha_Fvirt
3001 + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info)
3002 + FW_DEBUG_BLED_OFFSET;
3004 if (ASR_acquireLct(sc) == 0) {
3005 (void)ASR_acquireHrt(sc);
3008 printf ("asr%d: failed to initialize\n", unit);
3009 ATTACH_RETURN(ENXIO);
3012 * Add in additional probe responses for more channels. We
3013 * are reusing the variable `target' for a channel loop counter.
3014 * Done here because of we need both the acquireLct and
3017 { PI2O_LCT_ENTRY Device;
3019 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
3020 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
3022 if (Device->le_type == I2O_UNKNOWN) {
3025 if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) {
3026 if (Device->le_target > sc->ha_MaxId) {
3027 sc->ha_MaxId = Device->le_target;
3029 if (Device->le_lun > sc->ha_MaxLun) {
3030 sc->ha_MaxLun = Device->le_lun;
3033 if (((Device->le_type & I2O_PORT) != 0)
3034 && (Device->le_bus <= MAX_CHANNEL)) {
3035 /* Do not increase MaxId for efficiency */
3036 sc->ha_adapter_target[Device->le_bus]
3037 = Device->le_target;
3044 * Print the HBA model number as inquired from the card.
3047 printf ("asr%d:", unit);
3049 if ((iq = (struct scsi_inquiry_data *)malloc (
3050 sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK))
3051 != (struct scsi_inquiry_data *)NULL) {
3052 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
3053 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
3056 bzero (iq, sizeof(struct scsi_inquiry_data));
3058 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
3059 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
3060 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
3062 I2O_MESSAGE_FRAME_setVersionOffset(
3063 (PI2O_MESSAGE_FRAME)Message_Ptr,
3065 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
3066 - sizeof(I2O_SG_ELEMENT))
3067 / sizeof(U32)) << 4));
3068 I2O_MESSAGE_FRAME_setMessageSize(
3069 (PI2O_MESSAGE_FRAME)Message_Ptr,
3070 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
3071 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT))
3073 I2O_MESSAGE_FRAME_setInitiatorAddress (
3074 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
3075 I2O_MESSAGE_FRAME_setFunction(
3076 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
3077 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
3078 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
3080 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
3081 I2O_SCB_FLAG_ENABLE_DISCONNECT
3082 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
3083 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
3084 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1);
3085 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
3086 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
3087 DPT_ORGANIZATION_ID);
3088 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
3089 Message_Ptr->CDB[0] = INQUIRY;
3090 Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data);
3091 if (Message_Ptr->CDB[4] == 0) {
3092 Message_Ptr->CDB[4] = 255;
3095 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
3096 (I2O_SCB_FLAG_XFER_FROM_DEVICE
3097 | I2O_SCB_FLAG_ENABLE_DISCONNECT
3098 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
3099 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
3101 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
3102 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
3103 sizeof(struct scsi_inquiry_data));
3104 SG(&(Message_Ptr->SGL), 0,
3105 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
3106 iq, sizeof(struct scsi_inquiry_data));
3107 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
3109 if (iq->vendor[0] && (iq->vendor[0] != ' ')) {
3111 ASR_prstring (iq->vendor, 8);
3114 if (iq->product[0] && (iq->product[0] != ' ')) {
3116 ASR_prstring (iq->product, 16);
3119 if (iq->revision[0] && (iq->revision[0] != ' ')) {
3120 printf (" FW Rev. ");
3121 ASR_prstring (iq->revision, 4);
3124 free ((caddr_t)iq, M_TEMP);
3129 printf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1,
3130 (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize);
3133 * fill in the prototype cam_path.
3137 union asr_ccb * ccb;
3139 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
3140 printf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit);
3141 ATTACH_RETURN(ENOMEM);
3143 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
3144 int QueueSize = sc->ha_QueueSize;
3146 if (QueueSize > MAX_INBOUND) {
3147 QueueSize = MAX_INBOUND;
3151 * Construct our first channel SIM entry
3153 sc->ha_sim[bus] = cam_sim_alloc(
3154 asr_action, asr_poll, "asr", sc,
3155 unit, 1, QueueSize, NULL);
3156 if (sc->ha_sim[bus] == NULL)
3159 if (xpt_bus_register(sc->ha_sim[bus], bus)
3161 cam_sim_free(sc->ha_sim[bus]);
3162 sc->ha_sim[bus] = NULL;
3166 if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL,
3167 cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD,
3168 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3170 cam_sim_path(sc->ha_sim[bus]));
3171 cam_sim_free(sc->ha_sim[bus]);
3172 sc->ha_sim[bus] = NULL;
3179 * Generate the device node information
3181 make_dev(&asr_cdevsw, unit, 0, 0, S_IRWXU, "rasr%d", unit);
3187 IN struct cam_sim *sim)
3189 asr_intr(cam_sim_softc(sim));
3194 IN struct cam_sim * sim,
3197 struct Asr_softc * sc;
3199 debug_asr_printf ("asr_action(%lx,%lx{%x})\n",
3200 (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code);
3202 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n"));
3204 ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim);
3206 switch (ccb->ccb_h.func_code) {
3208 /* Common cases first */
3209 case XPT_SCSI_IO: /* Execute the requested I/O operation */
3212 char M[MAX_INBOUND_SIZE];
3214 defAlignLong(struct Message,Message);
3215 PI2O_MESSAGE_FRAME Message_Ptr;
3217 /* Reject incoming commands while we are resetting the card */
3218 if (sc->ha_in_reset != HA_OPERATIONAL) {
3219 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3220 if (sc->ha_in_reset >= HA_OFF_LINE) {
3221 /* HBA is now off-line */
3222 ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
3224 /* HBA currently resetting, try again later. */
3225 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
3227 debug_asr_cmd_printf (" e\n");
3229 debug_asr_cmd_printf (" q\n");
3232 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
3234 "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n",
3235 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
3236 ccb->csio.cdb_io.cdb_bytes[0],
3238 ccb->ccb_h.target_id,
3239 ccb->ccb_h.target_lun);
3241 debug_asr_cmd_printf ("(%d,%d,%d,%d)",
3244 ccb->ccb_h.target_id,
3245 ccb->ccb_h.target_lun);
3246 debug_asr_cmd_dump_ccb(ccb);
3248 if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb,
3249 (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) {
3250 debug_asr_cmd2_printf ("TID=%x:\n",
3251 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID(
3252 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr));
3253 debug_asr_cmd2_dump_message(Message_Ptr);
3254 debug_asr_cmd1_printf (" q");
3256 if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) {
3257 #ifdef ASR_MEASURE_PERFORMANCE
3258 ++sc->ha_performance.command_too_busy;
3260 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3261 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
3262 debug_asr_cmd_printf (" E\n");
3265 debug_asr_cmd_printf (" Q\n");
3269 * We will get here if there is no valid TID for the device
3270 * referenced in the scsi command packet.
3272 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3273 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
3274 debug_asr_cmd_printf (" B\n");
3279 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
3280 /* Rese HBA device ... */
3282 ccb->ccb_h.status = CAM_REQ_CMP;
3286 # if (defined(REPORT_LUNS))
3289 case XPT_ABORT: /* Abort the specified CCB */
3291 ccb->ccb_h.status = CAM_REQ_INVALID;
3295 case XPT_SET_TRAN_SETTINGS:
3297 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3301 case XPT_GET_TRAN_SETTINGS:
3302 /* Get default/user set transfer settings for the target */
3304 struct ccb_trans_settings *cts;
3308 target_mask = 0x01 << ccb->ccb_h.target_id;
3309 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
3310 cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
3311 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
3312 cts->sync_period = 6; /* 40MHz */
3313 cts->sync_offset = 15;
3315 cts->valid = CCB_TRANS_SYNC_RATE_VALID
3316 | CCB_TRANS_SYNC_OFFSET_VALID
3317 | CCB_TRANS_BUS_WIDTH_VALID
3318 | CCB_TRANS_DISC_VALID
3319 | CCB_TRANS_TQ_VALID;
3320 ccb->ccb_h.status = CAM_REQ_CMP;
3322 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3328 case XPT_CALC_GEOMETRY:
3330 struct ccb_calc_geometry *ccg;
3332 u_int32_t secs_per_cylinder;
3335 size_mb = ccg->volume_size
3336 / ((1024L * 1024L) / ccg->block_size);
3338 if (size_mb > 4096) {
3340 ccg->secs_per_track = 63;
3341 } else if (size_mb > 2048) {
3343 ccg->secs_per_track = 63;
3344 } else if (size_mb > 1024) {
3346 ccg->secs_per_track = 63;
3349 ccg->secs_per_track = 32;
3351 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
3352 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
3353 ccb->ccb_h.status = CAM_REQ_CMP;
3358 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
3359 ASR_resetBus (sc, cam_sim_bus(sim));
3360 ccb->ccb_h.status = CAM_REQ_CMP;
3364 case XPT_TERM_IO: /* Terminate the I/O process */
3366 ccb->ccb_h.status = CAM_REQ_INVALID;
3370 case XPT_PATH_INQ: /* Path routing inquiry */
3372 struct ccb_pathinq *cpi = &(ccb->cpi);
3374 cpi->version_num = 1; /* XXX??? */
3375 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
3376 cpi->target_sprt = 0;
3377 /* Not necessary to reset bus, done by HDM initialization */
3378 cpi->hba_misc = PIM_NOBUSRESET;
3379 cpi->hba_eng_cnt = 0;
3380 cpi->max_target = sc->ha_MaxId;
3381 cpi->max_lun = sc->ha_MaxLun;
3382 cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)];
3383 cpi->bus_id = cam_sim_bus(sim);
3384 cpi->base_transfer_speed = 3300;
3385 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
3386 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
3387 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
3388 cpi->unit_number = cam_sim_unit(sim);
3389 cpi->ccb_h.status = CAM_REQ_CMP;
3394 ccb->ccb_h.status = CAM_REQ_INVALID;
3400 #ifdef ASR_MEASURE_PERFORMANCE
3403 #define min_submitR sc->ha_performance.read_by_size_min_time[index]
3404 #define max_submitR sc->ha_performance.read_by_size_max_time[index]
3405 #define min_submitW sc->ha_performance.write_by_size_min_time[index]
3406 #define max_submitW sc->ha_performance.write_by_size_max_time[index]
3410 IN Asr_softc_t * sc,
3411 IN u_int32_t submitted_time,
3415 struct timeval submitted_timeval;
3417 submitted_timeval.tv_sec = 0;
3418 submitted_timeval.tv_usec = submitted_time;
3420 if ( op == READ_OP ) {
3421 ++sc->ha_performance.read_by_size_count[index];
3423 if ( submitted_time != 0xffffffff ) {
3425 &(sc->ha_performance.read_by_size_total_time[index]),
3426 &submitted_timeval);
3427 if ( (min_submitR == 0)
3428 || (submitted_time < min_submitR) ) {
3429 min_submitR = submitted_time;
3432 if ( submitted_time > max_submitR ) {
3433 max_submitR = submitted_time;
3437 ++sc->ha_performance.write_by_size_count[index];
3438 if ( submitted_time != 0xffffffff ) {
3440 &(sc->ha_performance.write_by_size_total_time[index]),
3441 &submitted_timeval);
3442 if ( (submitted_time < min_submitW)
3443 || (min_submitW == 0) ) {
3444 min_submitW = submitted_time;
3447 if ( submitted_time > max_submitW ) {
3448 max_submitW = submitted_time;
3452 } /* asr_IObySize */
3456 * Handle processing of current CCB as pointed to by the Status.
3460 IN Asr_softc_t * sc)
3464 #ifdef ASR_MEASURE_PERFORMANCE
3465 struct timeval junk;
3468 sc->ha_performance.intr_started = junk;
3472 sc->ha_Virt->Status & Mask_InterruptsDisabled;
3474 union asr_ccb * ccb;
3476 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3478 if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)
3479 && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) {
3482 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset
3483 - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs));
3485 * We do not need any (optional byteswapping) method access to
3486 * the Initiator context field.
3488 ccb = (union asr_ccb *)(long)
3489 I2O_MESSAGE_FRAME_getInitiatorContext64(
3490 &(Reply->StdReplyFrame.StdMessageFrame));
3491 if (I2O_MESSAGE_FRAME_getMsgFlags(
3492 &(Reply->StdReplyFrame.StdMessageFrame))
3493 & I2O_MESSAGE_FLAGS_FAIL) {
3494 defAlignLong(I2O_UTIL_NOP_MESSAGE,Message);
3495 PI2O_UTIL_NOP_MESSAGE Message_Ptr;
3498 MessageOffset = (u_long)
3499 I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA(
3500 (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply);
3502 * Get the Original Message Frame's address, and get
3503 * it's Transaction Context into our space. (Currently
3504 * unused at original authorship, but better to be
3505 * safe than sorry). Straight copy means that we
3506 * need not concern ourselves with the (optional
3507 * byteswapping) method access.
3509 Reply->StdReplyFrame.TransactionContext
3510 = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME)
3511 (sc->ha_Fvirt + MessageOffset))->TransactionContext;
3513 * For 64 bit machines, we need to reconstruct the
3516 ccb = (union asr_ccb *)(long)
3517 I2O_MESSAGE_FRAME_getInitiatorContext64(
3518 &(Reply->StdReplyFrame.StdMessageFrame));
3520 * Unique error code for command failure.
3522 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3523 &(Reply->StdReplyFrame), (u_int16_t)-2);
3525 * Modify the message frame to contain a NOP and
3526 * re-issue it to the controller.
3528 Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage(
3529 Message, sizeof(I2O_UTIL_NOP_MESSAGE));
3530 # if (I2O_UTIL_NOP != 0)
3531 I2O_MESSAGE_FRAME_setFunction (
3532 &(Message_Ptr->StdMessageFrame),
3536 * Copy the packet out to the Original Message
3538 bcopy ((caddr_t)Message_Ptr,
3539 sc->ha_Fvirt + MessageOffset,
3540 sizeof(I2O_UTIL_NOP_MESSAGE));
3544 sc->ha_Virt->ToFIFO = MessageOffset;
3548 * Asynchronous command with no return requirements,
3549 * and a generic handler for immunity against odd error
3550 * returns from the adapter.
3552 if (ccb == (union asr_ccb *)NULL) {
3554 * Return Reply so that it can be used for the
3557 sc->ha_Virt->FromFIFO = ReplyOffset;
3561 /* Welease Wadjah! (and stop timeouts) */
3562 ASR_ccbRemove (sc, ccb);
3565 I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode(
3566 &(Reply->StdReplyFrame))) {
3568 case I2O_SCSI_DSC_SUCCESS:
3569 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3570 ccb->ccb_h.status |= CAM_REQ_CMP;
3573 case I2O_SCSI_DSC_CHECK_CONDITION:
3574 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3575 ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID;
3578 case I2O_SCSI_DSC_BUSY:
3580 case I2O_SCSI_HBA_DSC_ADAPTER_BUSY:
3582 case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET:
3584 case I2O_SCSI_HBA_DSC_BUS_BUSY:
3585 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3586 ccb->ccb_h.status |= CAM_SCSI_BUSY;
3589 case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT:
3590 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3591 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
3594 case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT:
3596 case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT:
3598 case I2O_SCSI_HBA_DSC_LUN_INVALID:
3600 case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID:
3601 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3602 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
3605 case I2O_SCSI_HBA_DSC_DATA_OVERRUN:
3607 case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR:
3608 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3609 ccb->ccb_h.status |= CAM_DATA_RUN_ERR;
3613 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3614 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
3617 if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) {
3619 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount(
3623 #ifdef ASR_MEASURE_PERFORMANCE
3625 struct timeval endTime;
3626 u_int32_t submitted_time;
3631 --sc->ha_submitted_ccbs_count;
3633 = (int)Reply->StdReplyFrame.TransactionContext;
3634 if (-1 != startTimeIndex) {
3635 /* Compute the time spent in device/adapter */
3636 microtime(&endTime);
3637 submitted_time = asr_time_delta(sc->ha_timeQ[
3638 startTimeIndex], endTime);
3639 /* put the startTimeIndex back on free list */
3640 ENQ_TIMEQ_FREE_LIST(startTimeIndex,
3641 sc->ha_timeQFreeList,
3642 sc->ha_timeQFreeHead,
3643 sc->ha_timeQFreeTail);
3645 submitted_time = 0xffffffff;
3648 #define maxctime sc->ha_performance.max_command_time[ccb->csio.cdb_io.cdb_bytes[0]]
3649 #define minctime sc->ha_performance.min_command_time[ccb->csio.cdb_io.cdb_bytes[0]]
3650 if (submitted_time != 0xffffffff) {
3651 if ( maxctime < submitted_time ) {
3652 maxctime = submitted_time;
3654 if ( (minctime == 0)
3655 || (minctime > submitted_time) ) {
3656 minctime = submitted_time;
3659 if ( sc->ha_performance.max_submit_time
3660 < submitted_time ) {
3661 sc->ha_performance.max_submit_time
3664 if ( sc->ha_performance.min_submit_time == 0
3665 || sc->ha_performance.min_submit_time
3667 sc->ha_performance.min_submit_time
3671 switch ( ccb->csio.cdb_io.cdb_bytes[0] ) {
3673 case 0xa8: /* 12-byte READ */
3675 case 0x08: /* 6-byte READ */
3677 case 0x28: /* 10-byte READ */
3681 case 0x0a: /* 6-byte WRITE */
3683 case 0xaa: /* 12-byte WRITE */
3685 case 0x2a: /* 10-byte WRITE */
3694 if ( op_type != 0 ) {
3695 struct scsi_rw_big * cmd;
3697 cmd = (struct scsi_rw_big *)
3698 &(ccb->csio.cdb_io);
3700 size = (((u_int32_t) cmd->length2 << 8)
3701 | ((u_int32_t) cmd->length1)) << 9;
3707 submitted_time, op_type,
3713 submitted_time, op_type,
3719 submitted_time, op_type,
3725 submitted_time, op_type,
3731 submitted_time, op_type,
3737 submitted_time, op_type,
3743 submitted_time, op_type,
3749 submitted_time, op_type,
3754 if ( size > (1 << 16) ) {
3771 /* Sense data in reply packet */
3772 if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
3773 u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply);
3776 if (size > sizeof(ccb->csio.sense_data)) {
3777 size = sizeof(ccb->csio.sense_data);
3779 if (size > I2O_SCSI_SENSE_DATA_SZ) {
3780 size = I2O_SCSI_SENSE_DATA_SZ;
3782 if ((ccb->csio.sense_len)
3783 && (size > ccb->csio.sense_len)) {
3784 size = ccb->csio.sense_len;
3786 bcopy ((caddr_t)Reply->SenseData,
3787 (caddr_t)&(ccb->csio.sense_data), size);
3792 * Return Reply so that it can be used for the next command
3793 * since we have no more need for it now
3795 sc->ha_Virt->FromFIFO = ReplyOffset;
3797 if (ccb->ccb_h.path) {
3798 xpt_done ((union ccb *)ccb);
3800 wakeup ((caddr_t)ccb);
3803 #ifdef ASR_MEASURE_PERFORMANCE
3808 result = asr_time_delta(sc->ha_performance.intr_started, junk);
3810 if (result != 0xffffffff) {
3811 if ( sc->ha_performance.max_intr_time < result ) {
3812 sc->ha_performance.max_intr_time = result;
3815 if ( (sc->ha_performance.min_intr_time == 0)
3816 || (sc->ha_performance.min_intr_time > result) ) {
3817 sc->ha_performance.min_intr_time = result;
3825 #undef QueueSize /* Grrrr */
3826 #undef SG_Size /* Grrrr */
3829 * Meant to be included at the bottom of asr.c !!!
3833 * Included here as hard coded. Done because other necessary include
3834 * files utilize C++ comment structures which make them a nuisance to
3835 * included here just to pick up these three typedefs.
3837 typedef U32 DPT_TAG_T;
3838 typedef U32 DPT_MSG_T;
3839 typedef U32 DPT_RTN_T;
3841 #undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */
3842 #include "osd_unix.h"
3844 #define asr_unit(dev) minor(dev)
3846 STATIC INLINE Asr_softc_t *
3850 int unit = asr_unit(dev);
3851 OUT Asr_softc_t * sc = Asr_softc;
3853 while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) {
3859 STATIC u_int8_t ASR_ctlr_held;
3860 #if (!defined(UNREFERENCED_PARAMETER))
3861 # define UNREFERENCED_PARAMETER(x) (void)(x)
3873 UNREFERENCED_PARAMETER(flags);
3874 UNREFERENCED_PARAMETER(ifmt);
3876 if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) {
3879 KKASSERT(td->td_proc);
3881 if (ASR_ctlr_held) {
3883 } else if ((error = suser_cred(td->td_proc->p_ucred, 0)) == 0) {
3897 UNREFERENCED_PARAMETER(dev);
3898 UNREFERENCED_PARAMETER(flags);
3899 UNREFERENCED_PARAMETER(ifmt);
3900 UNREFERENCED_PARAMETER(td);
3907 /*-------------------------------------------------------------------------*/
3908 /* Function ASR_queue_i */
3909 /*-------------------------------------------------------------------------*/
3910 /* The Parameters Passed To This Function Are : */
3911 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
3912 /* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */
3913 /* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */
3915 /* This Function Will Take The User Request Packet And Convert It To An */
3916 /* I2O MSG And Send It Off To The Adapter. */
3918 /* Return : 0 For OK, Error Code Otherwise */
3919 /*-------------------------------------------------------------------------*/
3922 IN Asr_softc_t * sc,
3923 INOUT PI2O_MESSAGE_FRAME Packet)
3925 union asr_ccb * ccb;
3926 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3927 PI2O_MESSAGE_FRAME Message_Ptr;
3928 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr;
3929 int MessageSizeInBytes;
3930 int ReplySizeInBytes;
3933 /* Scatter Gather buffer list */
3934 struct ioctlSgList_S {
3935 SLIST_ENTRY(ioctlSgList_S) link;
3937 I2O_FLAGS_COUNT FlagsCount;
3938 char KernelSpace[sizeof(long)];
3940 /* Generates a `first' entry */
3941 SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList;
3943 if (ASR_getBlinkLedCode(sc)) {
3944 debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n",
3945 ASR_getBlinkLedCode(sc));
3948 /* Copy in the message into a local allocation */
3949 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (
3950 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
3951 == (PI2O_MESSAGE_FRAME)NULL) {
3952 debug_usr_cmd_printf (
3953 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
3956 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
3957 sizeof(I2O_MESSAGE_FRAME))) != 0) {
3958 free (Message_Ptr, M_TEMP);
3959 debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error);
3962 /* Acquire information to determine type of packet */
3963 MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2);
3964 /* The offset of the reply information within the user packet */
3965 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet
3966 + MessageSizeInBytes);
3968 /* Check if the message is a synchronous initialization command */
3969 s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr);
3970 free (Message_Ptr, M_TEMP);
3973 case I2O_EXEC_IOP_RESET:
3976 status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt);
3977 ReplySizeInBytes = sizeof(status);
3978 debug_usr_cmd_printf ("resetIOP done\n");
3979 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3983 case I2O_EXEC_STATUS_GET:
3984 { I2O_EXEC_STATUS_GET_REPLY status;
3986 if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status)
3987 == (PI2O_EXEC_STATUS_GET_REPLY)NULL) {
3988 debug_usr_cmd_printf ("getStatus failed\n");
3991 ReplySizeInBytes = sizeof(status);
3992 debug_usr_cmd_printf ("getStatus done\n");
3993 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3997 case I2O_EXEC_OUTBOUND_INIT:
4000 status = ASR_initOutBound(sc);
4001 ReplySizeInBytes = sizeof(status);
4002 debug_usr_cmd_printf ("intOutBound done\n");
4003 return (copyout ((caddr_t)&status, (caddr_t)Reply,
4008 /* Determine if the message size is valid */
4009 if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME))
4010 || (MAX_INBOUND_SIZE < MessageSizeInBytes)) {
4011 debug_usr_cmd_printf ("Packet size %d incorrect\n",
4012 MessageSizeInBytes);
4016 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (MessageSizeInBytes,
4017 M_TEMP, M_WAITOK)) == (PI2O_MESSAGE_FRAME)NULL) {
4018 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
4019 MessageSizeInBytes);
4022 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
4023 MessageSizeInBytes)) != 0) {
4024 free (Message_Ptr, M_TEMP);
4025 debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n",
4026 MessageSizeInBytes, error);
4030 /* Check the size of the reply frame, and start constructing */
4032 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc (
4033 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
4034 == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
4035 free (Message_Ptr, M_TEMP);
4036 debug_usr_cmd_printf (
4037 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
4040 if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr,
4041 sizeof(I2O_MESSAGE_FRAME))) != 0) {
4042 free (Reply_Ptr, M_TEMP);
4043 free (Message_Ptr, M_TEMP);
4044 debug_usr_cmd_printf (
4045 "Failed to copy in reply frame, errno=%d\n",
4049 ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(
4050 &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2);
4051 free (Reply_Ptr, M_TEMP);
4052 if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) {
4053 free (Message_Ptr, M_TEMP);
4054 debug_usr_cmd_printf (
4055 "Failed to copy in reply frame[%d], errno=%d\n",
4056 ReplySizeInBytes, error);
4060 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc (
4061 ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME))
4063 : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)),
4064 M_TEMP, M_WAITOK)) == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
4065 free (Message_Ptr, M_TEMP);
4066 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
4070 (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes);
4071 Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext
4072 = Message_Ptr->InitiatorContext;
4073 Reply_Ptr->StdReplyFrame.TransactionContext
4074 = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext;
4075 I2O_MESSAGE_FRAME_setMsgFlags(
4076 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
4077 I2O_MESSAGE_FRAME_getMsgFlags(
4078 &(Reply_Ptr->StdReplyFrame.StdMessageFrame))
4079 | I2O_MESSAGE_FLAGS_REPLY);
4081 /* Check if the message is a special case command */
4082 switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) {
4083 case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */
4084 if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset(
4085 Message_Ptr) & 0xF0) >> 2)) {
4086 free (Message_Ptr, M_TEMP);
4087 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
4088 &(Reply_Ptr->StdReplyFrame),
4089 (ASR_setSysTab(sc) != CAM_REQ_CMP));
4090 I2O_MESSAGE_FRAME_setMessageSize(
4091 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
4092 sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME));
4093 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
4095 free (Reply_Ptr, M_TEMP);
4100 /* Deal in the general case */
4101 /* First allocate and optionally copy in each scatter gather element */
4102 SLIST_INIT(&sgList);
4103 if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) {
4104 PI2O_SGE_SIMPLE_ELEMENT sg;
4107 * since this code is reused in several systems, code
4108 * efficiency is greater by using a shift operation rather
4109 * than a divide by sizeof(u_int32_t).
4111 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
4112 + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0)
4114 while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr)
4115 + MessageSizeInBytes)) {
4119 if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
4120 & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) {
4124 len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount));
4125 debug_usr_cmd_printf ("SG[%d] = %x[%d]\n",
4126 sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
4127 + ((I2O_MESSAGE_FRAME_getVersionOffset(
4128 Message_Ptr) & 0xF0) >> 2)),
4129 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len);
4131 if ((elm = (struct ioctlSgList_S *)malloc (
4132 sizeof(*elm) - sizeof(elm->KernelSpace) + len,
4134 == (struct ioctlSgList_S *)NULL) {
4135 debug_usr_cmd_printf (
4136 "Failed to allocate SG[%d]\n", len);
4140 SLIST_INSERT_HEAD(&sgList, elm, link);
4141 elm->FlagsCount = sg->FlagsCount;
4142 elm->UserSpace = (caddr_t)
4143 (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg));
4144 v = elm->KernelSpace;
4145 /* Copy in outgoing data (DIR bit could be invalid) */
4146 if ((error = copyin (elm->UserSpace, (caddr_t)v, len))
4151 * If the buffer is not contiguous, lets
4152 * break up the scatter/gather entries.
4155 && (sg < (PI2O_SGE_SIMPLE_ELEMENT)
4156 (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) {
4157 int next, base, span;
4160 next = base = KVTOPHYS(v);
4161 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg,
4164 /* How far can we go physically contiguously */
4165 while ((len > 0) && (base == next)) {
4168 next = trunc_page(base) + PAGE_SIZE;
4179 /* Construct the Flags */
4180 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount),
4183 int flags = I2O_FLAGS_COUNT_getFlags(
4184 &(elm->FlagsCount));
4185 /* Any remaining length? */
4188 ~(I2O_SGL_FLAGS_END_OF_BUFFER
4189 | I2O_SGL_FLAGS_LAST_ELEMENT);
4191 I2O_FLAGS_COUNT_setFlags(
4192 &(sg->FlagsCount), flags);
4195 debug_usr_cmd_printf ("sg[%d] = %x[%d]\n",
4196 sg - (PI2O_SGE_SIMPLE_ELEMENT)
4197 ((char *)Message_Ptr
4198 + ((I2O_MESSAGE_FRAME_getVersionOffset(
4199 Message_Ptr) & 0xF0) >> 2)),
4200 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg),
4207 * Incrementing requires resizing of the
4208 * packet, and moving up the existing SG
4212 MessageSizeInBytes += sizeof(*sg);
4213 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
4214 I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)
4215 + (sizeof(*sg) / sizeof(U32)));
4217 PI2O_MESSAGE_FRAME NewMessage_Ptr;
4220 = (PI2O_MESSAGE_FRAME)
4221 malloc (MessageSizeInBytes,
4223 == (PI2O_MESSAGE_FRAME)NULL) {
4224 debug_usr_cmd_printf (
4225 "Failed to acquire frame[%d] memory\n",
4226 MessageSizeInBytes);
4230 span = ((caddr_t)sg)
4231 - (caddr_t)Message_Ptr;
4232 bcopy ((caddr_t)Message_Ptr,
4233 (caddr_t)NewMessage_Ptr, span);
4234 bcopy ((caddr_t)(sg-1),
4235 ((caddr_t)NewMessage_Ptr) + span,
4236 MessageSizeInBytes - span);
4237 free (Message_Ptr, M_TEMP);
4238 sg = (PI2O_SGE_SIMPLE_ELEMENT)
4239 (((caddr_t)NewMessage_Ptr) + span);
4240 Message_Ptr = NewMessage_Ptr;
4244 || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
4245 & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) {
4251 while ((elm = SLIST_FIRST(&sgList))
4252 != (struct ioctlSgList_S *)NULL) {
4253 SLIST_REMOVE_HEAD(&sgList, link);
4256 free (Reply_Ptr, M_TEMP);
4257 free (Message_Ptr, M_TEMP);
4262 debug_usr_cmd_printf ("Inbound: ");
4263 debug_usr_cmd_dump_message(Message_Ptr);
4265 /* Send the command */
4266 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
4267 /* Free up in-kernel buffers */
4268 while ((elm = SLIST_FIRST(&sgList))
4269 != (struct ioctlSgList_S *)NULL) {
4270 SLIST_REMOVE_HEAD(&sgList, link);
4273 free (Reply_Ptr, M_TEMP);
4274 free (Message_Ptr, M_TEMP);
4279 * We do not need any (optional byteswapping) method access to
4280 * the Initiator context field.
4282 I2O_MESSAGE_FRAME_setInitiatorContext64(
4283 (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb);
4285 (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
4287 free (Message_Ptr, M_TEMP);
4290 * Wait for the board to report a finished instruction.
4293 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
4294 if (ASR_getBlinkLedCode(sc)) {
4296 printf ("asr%d: Blink LED 0x%x resetting adapter\n",
4297 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
4298 ASR_getBlinkLedCode(sc));
4299 if (ASR_reset (sc) == ENXIO) {
4300 /* Command Cleanup */
4301 ASR_ccbRemove(sc, ccb);
4304 /* Free up in-kernel buffers */
4305 while ((elm = SLIST_FIRST(&sgList))
4306 != (struct ioctlSgList_S *)NULL) {
4307 SLIST_REMOVE_HEAD(&sgList, link);
4310 free (Reply_Ptr, M_TEMP);
4314 /* Check every second for BlinkLed */
4315 tsleep((caddr_t)ccb, 0, "asr", hz);
4319 debug_usr_cmd_printf ("Outbound: ");
4320 debug_usr_cmd_dump_message(Reply_Ptr);
4322 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
4323 &(Reply_Ptr->StdReplyFrame),
4324 (ccb->ccb_h.status != CAM_REQ_CMP));
4326 if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
4327 - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) {
4328 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr,
4329 ccb->csio.dxfer_len - ccb->csio.resid);
4331 if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes
4332 > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
4333 - I2O_SCSI_SENSE_DATA_SZ))) {
4334 int size = ReplySizeInBytes
4335 - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
4336 - I2O_SCSI_SENSE_DATA_SZ;
4338 if (size > sizeof(ccb->csio.sense_data)) {
4339 size = sizeof(ccb->csio.sense_data);
4341 bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData,
4343 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount(
4347 /* Free up in-kernel buffers */
4348 while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) {
4349 /* Copy out as necessary */
4351 /* DIR bit considered `valid', error due to ignorance works */
4352 && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount))
4353 & I2O_SGL_FLAGS_DIR) == 0)) {
4354 error = copyout ((caddr_t)(elm->KernelSpace),
4356 I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount)));
4358 SLIST_REMOVE_HEAD(&sgList, link);
4362 /* Copy reply frame to user space */
4363 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
4366 free (Reply_Ptr, M_TEMP);
4372 /*----------------------------------------------------------------------*/
4373 /* Function asr_ioctl */
4374 /*----------------------------------------------------------------------*/
4375 /* The parameters passed to this function are : */
4376 /* dev : Device number. */
4377 /* cmd : Ioctl Command */
4378 /* data : User Argument Passed In. */
4379 /* flag : Mode Parameter */
4380 /* proc : Process Parameter */
4382 /* This function is the user interface into this adapter driver */
4384 /* Return : zero if OK, error code if not */
4385 /*----------------------------------------------------------------------*/
4397 Asr_softc_t * sc = ASR_get_sc (dev);
4398 UNREFERENCED_PARAMETER(flag);
4399 UNREFERENCED_PARAMETER(td);
4401 if (sc != (Asr_softc_t *)NULL)
4405 # if (dsDescription_size != 50)
4406 case DPT_SIGNATURE + ((50 - dsDescription_size) << 16):
4408 if (cmd & 0xFFFF0000) {
4409 (void)bcopy ((caddr_t)(&ASR_sig), data,
4413 /* Traditional version of the ioctl interface */
4414 case DPT_SIGNATURE & 0x0000FFFF:
4415 return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data),
4416 sizeof(dpt_sig_S)));
4418 /* Traditional version of the ioctl interface */
4419 case DPT_CTRLINFO & 0x0000FFFF:
4420 case DPT_CTRLINFO: {
4423 u_int16_t drvrHBAnum;
4425 u_int16_t blinkState;
4427 u_int8_t pciDeviceNum;
4429 u_int16_t Interrupt;
4430 u_int32_t reserved1;
4431 u_int32_t reserved2;
4432 u_int32_t reserved3;
4435 bzero (&CtlrInfo, sizeof(CtlrInfo));
4436 CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t);
4437 CtlrInfo.drvrHBAnum = asr_unit(dev);
4438 CtlrInfo.baseAddr = (u_long)sc->ha_Base;
4439 i = ASR_getBlinkLedCode (sc);
4443 CtlrInfo.blinkState = i;
4444 CtlrInfo.pciBusNum = sc->ha_pciBusNum;
4445 CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum;
4446 #define FLG_OSD_PCI_VALID 0x0001
4447 #define FLG_OSD_DMA 0x0002
4448 #define FLG_OSD_I2O 0x0004
4449 CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
4450 CtlrInfo.Interrupt = sc->ha_irq;
4451 if (cmd & 0xFFFF0000) {
4452 bcopy (&CtlrInfo, data, sizeof(CtlrInfo));
4454 error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo));
4458 /* Traditional version of the ioctl interface */
4459 case DPT_SYSINFO & 0x0000FFFF:
4463 /* Kernel Specific ptok `hack' */
4464 # define ptok(a) ((char *)(a) + KERNBASE)
4466 bzero (&Info, sizeof(Info));
4468 /* Appears I am the only person in the Kernel doing this */
4476 Info.drive0CMOS = j;
4483 Info.drive1CMOS = j;
4485 Info.numDrives = *((char *)ptok(0x475));
4487 Info.processorFamily = ASR_sig.dsProcessorFamily;
4489 case CPU_386SX: case CPU_386:
4490 Info.processorType = PROC_386; break;
4491 case CPU_486SX: case CPU_486:
4492 Info.processorType = PROC_486; break;
4494 Info.processorType = PROC_PENTIUM; break;
4496 Info.processorType = PROC_SEXIUM; break;
4498 Info.osType = OS_BSDI_UNIX;
4499 Info.osMajorVersion = osrelease[0] - '0';
4500 Info.osMinorVersion = osrelease[2] - '0';
4501 /* Info.osRevision = 0; */
4502 /* Info.osSubRevision = 0; */
4503 Info.busType = SI_PCI_BUS;
4504 Info.flags = SI_CMOS_Valid | SI_NumDrivesValid
4505 | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM;
4507 /* Go Out And Look For I2O SmartROM */
4508 for(j = 0xC8000; j < 0xE0000; j += 2048) {
4512 if (*((unsigned short *)cp) != 0xAA55) {
4515 j += (cp[2] * 512) - 2048;
4516 if ((*((u_long *)(cp + 6))
4517 != ('S' + (' ' * 256) + (' ' * 65536L)))
4518 || (*((u_long *)(cp + 10))
4519 != ('I' + ('2' * 256) + ('0' * 65536L)))) {
4523 for (k = 0; k < 64; ++k) {
4524 if (*((unsigned short *)cp)
4525 == (' ' + ('v' * 256))) {
4530 Info.smartROMMajorVersion
4531 = *((unsigned char *)(cp += 4)) - '0';
4532 Info.smartROMMinorVersion
4533 = *((unsigned char *)(cp += 2));
4534 Info.smartROMRevision
4535 = *((unsigned char *)(++cp));
4536 Info.flags |= SI_SmartROMverValid;
4537 Info.flags &= ~SI_NO_SmartROM;
4541 /* Get The Conventional Memory Size From CMOS */
4547 Info.conventionalMemSize = j;
4549 /* Get The Extended Memory Found At Power On From CMOS */
4555 Info.extendedMemSize = j;
4556 Info.flags |= SI_MemorySizeValid;
4558 # if (defined(THIS_IS_BROKEN))
4559 /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */
4560 if (Info.numDrives > 0) {
4562 * Get The Pointer From Int 41 For The First
4565 j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4)
4566 + (unsigned)(*((unsigned short *)ptok(0x104+0)));
4568 * It appears that SmartROM's Int41/Int46 pointers
4569 * use memory that gets stepped on by the kernel
4570 * loading. We no longer have access to this
4571 * geometry information but try anyways (!?)
4573 Info.drives[0].cylinders = *((unsigned char *)ptok(j));
4575 Info.drives[0].cylinders += ((int)*((unsigned char *)
4578 Info.drives[0].heads = *((unsigned char *)ptok(j));
4580 Info.drives[0].sectors = *((unsigned char *)ptok(j));
4581 Info.flags |= SI_DriveParamsValid;
4582 if ((Info.drives[0].cylinders == 0)
4583 || (Info.drives[0].heads == 0)
4584 || (Info.drives[0].sectors == 0)) {
4585 Info.flags &= ~SI_DriveParamsValid;
4587 if (Info.numDrives > 1) {
4589 * Get The Pointer From Int 46 For The
4590 * Second Drive Parameters
4592 j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4)
4593 + (unsigned)(*((unsigned short *)ptok(0x118+0)));
4594 Info.drives[1].cylinders = *((unsigned char *)
4597 Info.drives[1].cylinders += ((int)
4598 *((unsigned char *)ptok(j))) << 8;
4600 Info.drives[1].heads = *((unsigned char *)
4603 Info.drives[1].sectors = *((unsigned char *)
4605 if ((Info.drives[1].cylinders == 0)
4606 || (Info.drives[1].heads == 0)
4607 || (Info.drives[1].sectors == 0)) {
4608 Info.flags &= ~SI_DriveParamsValid;
4613 /* Copy Out The Info Structure To The User */
4614 if (cmd & 0xFFFF0000) {
4615 bcopy (&Info, data, sizeof(Info));
4617 error = copyout (&Info, *(caddr_t *)data, sizeof(Info));
4621 /* Get The BlinkLED State */
4623 i = ASR_getBlinkLedCode (sc);
4627 if (cmd & 0xFFFF0000) {
4628 bcopy ((caddr_t)(&i), data, sizeof(i));
4630 error = copyout (&i, *(caddr_t *)data, sizeof(i));
4634 /* Get performance metrics */
4635 #ifdef ASR_MEASURE_PERFORMANCE
4637 bcopy((caddr_t) &(sc->ha_performance), data,
4638 sizeof(sc->ha_performance));
4642 /* Send an I2O command */
4644 return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data)));
4646 /* Reset and re-initialize the adapter */
4648 return (ASR_reset (sc));
4650 /* Rescan the LCT table and resynchronize the information */
4652 return (ASR_rescan (sc));
4657 #ifdef ASR_MEASURE_PERFORMANCE
4659 * This function subtracts one timeval structure from another,
4660 * Returning the result in usec.
4661 * It assumes that less than 4 billion usecs passed form start to end.
4662 * If times are sensless, 0xffffffff is returned.
4667 IN struct timeval start,
4668 IN struct timeval end)
4670 OUT u_int32_t result;
4672 if (start.tv_sec > end.tv_sec) {
4673 result = 0xffffffff;
4676 if (start.tv_sec == end.tv_sec) {
4677 if (start.tv_usec > end.tv_usec) {
4678 result = 0xffffffff;
4680 return (end.tv_usec - start.tv_usec);
4683 return (end.tv_sec - start.tv_sec) * 1000000 +
4684 end.tv_usec + (1000000 - start.tv_usec);
4688 } /* asr_time_delta */