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.19 2005/05/24 20:59:03 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"
266 #include "sys_info.h"
268 /* Configuration Definitions */
270 #define SG_SIZE 58 /* Scatter Gather list Size */
271 #define MAX_TARGET_ID 126 /* Maximum Target ID supported */
272 #define MAX_LUN 255 /* Maximum LUN Supported */
273 #define MAX_CHANNEL 7 /* Maximum Channel # Supported by driver */
274 #define MAX_INBOUND 2000 /* Max CCBs, Also Max Queue Size */
275 #define MAX_OUTBOUND 256 /* Maximum outbound frames/adapter */
276 #define MAX_INBOUND_SIZE 512 /* Maximum inbound frame size */
277 #define MAX_MAP 4194304L /* Maximum mapping size of IOP */
278 /* Also serves as the minimum map for */
279 /* the 2005S zero channel RAID product */
281 /**************************************************************************
282 ** ASR Host Adapter structure - One Structure For Each Host Adapter That **
283 ** Is Configured Into The System. The Structure Supplies Configuration **
284 ** Information, Status Info, Queue Info And An Active CCB List Pointer. **
285 ***************************************************************************/
287 /* I2O register set */
292 # define Mask_InterruptsDisabled 0x08
294 volatile U32 ToFIFO; /* In Bound FIFO */
295 volatile U32 FromFIFO; /* Out Bound FIFO */
299 * A MIX of performance and space considerations for TID lookups
301 typedef u_int16_t tid_t;
304 u_int32_t size; /* up to MAX_LUN */
309 u_int32_t size; /* up to MAX_TARGET */
314 * To ensure that we only allocate and use the worst case ccb here, lets
315 * make our own local ccb union. If asr_alloc_ccb is utilized for another
316 * ccb type, ensure that you add the additional structures into our local
317 * ccb union. To ensure strict type checking, we will utilize the local
318 * ccb definition wherever possible.
321 struct ccb_hdr ccb_h; /* For convenience */
322 struct ccb_scsiio csio;
323 struct ccb_setasync csa;
326 typedef struct Asr_softc {
328 void * ha_Base; /* base port for each board */
329 u_int8_t * volatile ha_blinkLED;
330 i2oRegs_t * ha_Virt; /* Base address of IOP */
331 U8 * ha_Fvirt; /* Base address of Frames */
332 I2O_IOP_ENTRY ha_SystemTable;
333 LIST_HEAD(,ccb_hdr) ha_ccb; /* ccbs in use */
334 struct cam_path * ha_path[MAX_CHANNEL+1];
335 struct cam_sim * ha_sim[MAX_CHANNEL+1];
336 struct resource * ha_mem_res;
337 struct resource * ha_mes_res;
338 struct resource * ha_irq_res;
340 PI2O_LCT ha_LCT; /* Complete list of devices */
341 # define le_type IdentityTag[0]
342 # define I2O_BSA 0x20
343 # define I2O_FCA 0x40
344 # define I2O_SCSI 0x00
345 # define I2O_PORT 0x80
346 # define I2O_UNKNOWN 0x7F
347 # define le_bus IdentityTag[1]
348 # define le_target IdentityTag[2]
349 # define le_lun IdentityTag[3]
350 target2lun_t * ha_targets[MAX_CHANNEL+1];
351 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME ha_Msgs;
354 u_int8_t ha_in_reset;
355 # define HA_OPERATIONAL 0
356 # define HA_IN_RESET 1
357 # define HA_OFF_LINE 2
358 # define HA_OFF_LINE_RECOVERY 3
359 /* Configuration information */
360 /* The target id maximums we take */
361 u_int8_t ha_MaxBus; /* Maximum bus */
362 u_int8_t ha_MaxId; /* Maximum target ID */
363 u_int8_t ha_MaxLun; /* Maximum target LUN */
364 u_int8_t ha_SgSize; /* Max SG elements */
365 u_int8_t ha_pciBusNum;
366 u_int8_t ha_pciDeviceNum;
367 u_int8_t ha_adapter_target[MAX_CHANNEL+1];
368 u_int16_t ha_QueueSize; /* Max outstanding commands */
369 u_int16_t ha_Msgs_Count;
371 /* Links into other parents and HBAs */
372 struct Asr_softc * ha_next; /* HBA list */
375 STATIC Asr_softc_t * Asr_softc;
378 * Prototypes of the routines we have in this object.
381 /* Externally callable routines */
382 #define PROBE_ARGS IN device_t tag
383 #define PROBE_RET int
384 #define PROBE_SET() u_long id = (pci_get_device(tag)<<16)|pci_get_vendor(tag)
385 #define PROBE_RETURN(retval) if(retval){device_set_desc(tag,retval);return(0);}else{return(ENXIO);}
386 #define ATTACH_ARGS IN device_t tag
387 #define ATTACH_RET int
388 #define ATTACH_SET() int unit = device_get_unit(tag)
389 #define ATTACH_RETURN(retval) return(retval)
390 /* I2O HDM interface */
391 STATIC PROBE_RET asr_probe (PROBE_ARGS);
392 STATIC ATTACH_RET asr_attach (ATTACH_ARGS);
393 /* DOMINO placeholder */
394 STATIC PROBE_RET domino_probe (PROBE_ARGS);
395 STATIC ATTACH_RET domino_attach (ATTACH_ARGS);
396 /* MODE0 adapter placeholder */
397 STATIC PROBE_RET mode0_probe (PROBE_ARGS);
398 STATIC ATTACH_RET mode0_attach (ATTACH_ARGS);
400 STATIC Asr_softc_t * ASR_get_sc (
402 STATIC int asr_ioctl (
408 STATIC int asr_open (
413 STATIC int asr_close (
418 STATIC int asr_intr (
419 IN Asr_softc_t * sc);
420 STATIC void asr_timeout (
422 STATIC int ASR_init (
423 IN Asr_softc_t * sc);
424 STATIC INLINE int ASR_acquireLct (
425 INOUT Asr_softc_t * sc);
426 STATIC INLINE int ASR_acquireHrt (
427 INOUT Asr_softc_t * sc);
428 STATIC void asr_action (
429 IN struct cam_sim * sim,
431 STATIC void asr_poll (
432 IN struct cam_sim * sim);
435 * Here is the auto-probe structure used to nest our tests appropriately
436 * during the startup phase of the operating system.
438 STATIC device_method_t asr_methods[] = {
439 DEVMETHOD(device_probe, asr_probe),
440 DEVMETHOD(device_attach, asr_attach),
444 STATIC driver_t asr_driver = {
450 STATIC devclass_t asr_devclass;
452 DECLARE_DUMMY_MODULE(asr);
453 DRIVER_MODULE(asr, pci, asr_driver, asr_devclass, 0, 0);
455 STATIC device_method_t domino_methods[] = {
456 DEVMETHOD(device_probe, domino_probe),
457 DEVMETHOD(device_attach, domino_attach),
461 STATIC driver_t domino_driver = {
467 STATIC devclass_t domino_devclass;
469 DRIVER_MODULE(domino, pci, domino_driver, domino_devclass, 0, 0);
471 STATIC device_method_t mode0_methods[] = {
472 DEVMETHOD(device_probe, mode0_probe),
473 DEVMETHOD(device_attach, mode0_attach),
477 STATIC driver_t mode0_driver = {
483 STATIC devclass_t mode0_devclass;
485 DRIVER_MODULE(mode0, pci, mode0_driver, mode0_devclass, 0, 0);
488 * devsw for asr hba driver
490 * only ioctl is used. the sd driver provides all other access.
492 #define CDEV_MAJOR 154 /* prefered default character major */
493 STATIC struct cdevsw asr_cdevsw = {
495 CDEV_MAJOR, /* maj */
501 asr_close, /* close */
504 asr_ioctl, /* ioctl */
507 nostrategy, /* strategy */
513 * Initialize the dynamic cdevsw hooks.
516 asr_drvinit (void * unused)
518 static int asr_devsw_installed = 0;
520 if (asr_devsw_installed) {
523 asr_devsw_installed++;
525 * Find a free spot (the report during driver load used by
526 * osd layer in engine to generate the controlling nodes).
528 * XXX this is garbage code, store a unit number in asr_cdevsw
529 * and iterate through that instead?
531 while (asr_cdevsw.d_maj < NUMCDEVSW &&
532 cdevsw_get(asr_cdevsw.d_maj, -1) != NULL
536 if (asr_cdevsw.d_maj >= NUMCDEVSW) {
537 asr_cdevsw.d_maj = 0;
538 while (asr_cdevsw.d_maj < CDEV_MAJOR &&
539 cdevsw_get(asr_cdevsw.d_maj, -1) != NULL
548 cdevsw_add(&asr_cdevsw, 0, 0);
551 /* Must initialize before CAM layer picks up our HBA driver */
552 SYSINIT(asrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,asr_drvinit,NULL)
554 /* I2O support routines */
555 #define defAlignLong(STRUCT,NAME) char NAME[sizeof(STRUCT)]
556 #define getAlignLong(STRUCT,NAME) ((STRUCT *)(NAME))
559 * Fill message with default.
561 STATIC PI2O_MESSAGE_FRAME
566 OUT PI2O_MESSAGE_FRAME Message_Ptr;
568 Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message);
569 bzero ((void *)Message_Ptr, size);
570 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11);
571 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
572 (size + sizeof(U32) - 1) >> 2);
573 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
574 return (Message_Ptr);
575 } /* ASR_fillMessage */
577 #define EMPTY_QUEUE ((U32)-1L)
583 OUT U32 MessageOffset;
585 if ((MessageOffset = virt->ToFIFO) == EMPTY_QUEUE) {
586 MessageOffset = virt->ToFIFO;
588 return (MessageOffset);
589 } /* ASR_getMessage */
591 /* Issue a polled command */
594 INOUT i2oRegs_t * virt,
596 IN PI2O_MESSAGE_FRAME Message)
603 * ASR_initiateCp is only used for synchronous commands and will
604 * be made more resiliant to adapter delays since commands like
605 * resetIOP can cause the adapter to be deaf for a little time.
607 while (((MessageOffset = ASR_getMessage(virt)) == EMPTY_QUEUE)
611 if (MessageOffset != EMPTY_QUEUE) {
612 bcopy (Message, fvirt + MessageOffset,
613 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
615 * Disable the Interrupts
617 virt->Mask = (Mask = virt->Mask) | Mask_InterruptsDisabled;
618 virt->ToFIFO = MessageOffset;
621 } /* ASR_initiateCp */
628 INOUT i2oRegs_t * virt,
631 struct resetMessage {
632 I2O_EXEC_IOP_RESET_MESSAGE M;
635 defAlignLong(struct resetMessage,Message);
636 PI2O_EXEC_IOP_RESET_MESSAGE Message_Ptr;
637 OUT U32 * volatile Reply_Ptr;
641 * Build up our copy of the Message.
643 Message_Ptr = (PI2O_EXEC_IOP_RESET_MESSAGE)ASR_fillMessage(Message,
644 sizeof(I2O_EXEC_IOP_RESET_MESSAGE));
645 I2O_EXEC_IOP_RESET_MESSAGE_setFunction(Message_Ptr, I2O_EXEC_IOP_RESET);
647 * Reset the Reply Status
649 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
650 + sizeof(I2O_EXEC_IOP_RESET_MESSAGE))) = 0;
651 I2O_EXEC_IOP_RESET_MESSAGE_setStatusWordLowAddress(Message_Ptr,
652 KVTOPHYS((void *)Reply_Ptr));
654 * Send the Message out
656 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
658 * Wait for a response (Poll), timeouts are dangerous if
659 * the card is truly responsive. We assume response in 2s.
661 u_int8_t Delay = 200;
663 while ((*Reply_Ptr == 0) && (--Delay != 0)) {
667 * Re-enable the interrupts.
673 ASSERT (Old != (U32)-1L);
678 * Get the curent state of the adapter
680 STATIC INLINE PI2O_EXEC_STATUS_GET_REPLY
682 INOUT i2oRegs_t * virt,
684 OUT PI2O_EXEC_STATUS_GET_REPLY buffer)
686 defAlignLong(I2O_EXEC_STATUS_GET_MESSAGE,Message);
687 PI2O_EXEC_STATUS_GET_MESSAGE Message_Ptr;
691 * Build up our copy of the Message.
693 Message_Ptr = (PI2O_EXEC_STATUS_GET_MESSAGE)ASR_fillMessage(Message,
694 sizeof(I2O_EXEC_STATUS_GET_MESSAGE));
695 I2O_EXEC_STATUS_GET_MESSAGE_setFunction(Message_Ptr,
696 I2O_EXEC_STATUS_GET);
697 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferAddressLow(Message_Ptr,
698 KVTOPHYS((void *)buffer));
699 /* This one is a Byte Count */
700 I2O_EXEC_STATUS_GET_MESSAGE_setReplyBufferLength(Message_Ptr,
701 sizeof(I2O_EXEC_STATUS_GET_REPLY));
703 * Reset the Reply Status
705 bzero ((void *)buffer, sizeof(I2O_EXEC_STATUS_GET_REPLY));
707 * Send the Message out
709 if ((Old = ASR_initiateCp (virt, fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
711 * Wait for a response (Poll), timeouts are dangerous if
712 * the card is truly responsive. We assume response in 50ms.
714 u_int8_t Delay = 255;
716 while (*((U8 * volatile)&(buffer->SyncByte)) == 0) {
718 buffer = (PI2O_EXEC_STATUS_GET_REPLY)NULL;
724 * Re-enable the interrupts.
729 return ((PI2O_EXEC_STATUS_GET_REPLY)NULL);
730 } /* ASR_getStatus */
733 * Check if the device is a SCSI I2O HBA, and add it to the list.
737 * Probe for ASR controller. If we find it, we will use it.
741 asr_probe(PROBE_ARGS)
744 if ((id == 0xA5011044) || (id == 0xA5111044)) {
745 PROBE_RETURN ("Adaptec Caching SCSI RAID");
751 * Probe/Attach for DOMINO chipset.
754 domino_probe(PROBE_ARGS)
757 if (id == 0x10121044) {
758 PROBE_RETURN ("Adaptec Caching Memory Controller");
764 domino_attach (ATTACH_ARGS)
767 } /* domino_attach */
770 * Probe/Attach for MODE0 adapters.
773 mode0_probe(PROBE_ARGS)
778 * If/When we can get a business case to commit to a
779 * Mode0 driver here, we can make all these tests more
780 * specific and robust. Mode0 adapters have their processors
781 * turned off, this the chips are in a raw state.
784 /* This is a PLX9054 */
785 if (id == 0x905410B5) {
786 PROBE_RETURN ("Adaptec Mode0 PM3757");
788 /* This is a PLX9080 */
789 if (id == 0x908010B5) {
790 PROBE_RETURN ("Adaptec Mode0 PM3754/PM3755");
792 /* This is a ZION 80303 */
793 if (id == 0x53098086) {
794 PROBE_RETURN ("Adaptec Mode0 3010S");
796 /* This is an i960RS */
797 if (id == 0x39628086) {
798 PROBE_RETURN ("Adaptec Mode0 2100S");
800 /* This is an i960RN */
801 if (id == 0x19648086) {
802 PROBE_RETURN ("Adaptec Mode0 PM2865/2400A/3200S/3400S");
804 #if 0 /* this would match any generic i960 -- mjs */
805 /* This is an i960RP (typically also on Motherboards) */
806 if (id == 0x19608086) {
807 PROBE_RETURN ("Adaptec Mode0 PM2554/PM1554/PM2654");
814 mode0_attach (ATTACH_ARGS)
819 STATIC INLINE union asr_ccb *
823 OUT union asr_ccb * new_ccb;
825 if ((new_ccb = (union asr_ccb *)malloc(sizeof(*new_ccb),
826 M_DEVBUF, M_WAITOK)) != (union asr_ccb *)NULL) {
827 bzero (new_ccb, sizeof(*new_ccb));
828 new_ccb->ccb_h.pinfo.priority = 1;
829 new_ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
830 new_ccb->ccb_h.spriv_ptr0 = sc;
833 } /* asr_alloc_ccb */
837 IN union asr_ccb * free_ccb)
839 free(free_ccb, M_DEVBUF);
843 * Print inquiry data `carefully'
850 while ((--len >= 0) && (*s) && (*s != ' ') && (*s != '-')) {
851 printf ("%c", *(s++));
858 STATIC INLINE int ASR_queue (
860 IN PI2O_MESSAGE_FRAME Message);
862 * Send a message synchronously and without Interrupt to a ccb.
866 INOUT union asr_ccb * ccb,
867 IN PI2O_MESSAGE_FRAME Message)
871 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
874 * We do not need any (optional byteswapping) method access to
875 * the Initiator context field.
877 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
879 /* Prevent interrupt service */
881 sc->ha_Virt->Mask = (Mask = sc->ha_Virt->Mask)
882 | Mask_InterruptsDisabled;
884 if (ASR_queue (sc, Message) == EMPTY_QUEUE) {
885 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
886 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
890 * Wait for this board to report a finished instruction.
892 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
896 /* Re-enable Interrupts */
897 sc->ha_Virt->Mask = Mask;
900 return (ccb->ccb_h.status);
904 * Send a message synchronously to a Asr_softc_t
909 IN PI2O_MESSAGE_FRAME Message)
914 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
915 return (CAM_REQUEUE_REQ);
918 status = ASR_queue_s (ccb, Message);
926 * Add the specified ccb to the active queue
931 INOUT union asr_ccb * ccb)
936 LIST_INSERT_HEAD(&(sc->ha_ccb), &(ccb->ccb_h), sim_links.le);
937 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
938 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
940 * RAID systems can take considerable time to
941 * complete some commands given the large cache
942 * flashes switching from write back to write thru.
944 ccb->ccb_h.timeout = 6 * 60 * 1000;
946 callout_reset(&ccb->ccb_h.timeout_ch,
947 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
953 * Remove the specified ccb from the active queue.
958 INOUT union asr_ccb * ccb)
963 callout_stop(&ccb->ccb_h.timeout_ch);
964 LIST_REMOVE(&(ccb->ccb_h), sim_links.le);
966 } /* ASR_ccbRemove */
969 * Fail all the active commands, so they get re-issued by the operating
973 ASR_failActiveCommands (
976 struct ccb_hdr * ccb;
979 #if 0 /* Currently handled by callers, unnecessary paranoia currently */
980 /* Left in for historical perspective. */
981 defAlignLong(I2O_EXEC_LCT_NOTIFY_MESSAGE,Message);
982 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
984 /* Send a blind LCT command to wait for the enableSys to complete */
985 Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)ASR_fillMessage(Message,
986 sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT));
987 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
988 I2O_EXEC_LCT_NOTIFY);
989 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
990 I2O_CLASS_MATCH_ANYCLASS);
991 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
996 * We do not need to inform the CAM layer that we had a bus
997 * reset since we manage it on our own, this also prevents the
998 * SCSI_DELAY settling that would be required on other systems.
999 * The `SCSI_DELAY' has already been handled by the card via the
1000 * acquisition of the LCT table while we are at CAM priority level.
1001 * for (int bus = 0; bus <= sc->ha_MaxBus; ++bus) {
1002 * xpt_async (AC_BUS_RESET, sc->ha_path[bus], NULL);
1005 while ((ccb = LIST_FIRST(&(sc->ha_ccb))) != (struct ccb_hdr *)NULL) {
1006 ASR_ccbRemove (sc, (union asr_ccb *)ccb);
1008 ccb->status &= ~CAM_STATUS_MASK;
1009 ccb->status |= CAM_REQUEUE_REQ;
1010 /* Nothing Transfered */
1011 ((struct ccb_scsiio *)ccb)->resid
1012 = ((struct ccb_scsiio *)ccb)->dxfer_len;
1015 xpt_done ((union ccb *)ccb);
1017 wakeup ((caddr_t)ccb);
1021 } /* ASR_failActiveCommands */
1024 * The following command causes the HBA to reset the specific bus
1028 IN Asr_softc_t * sc,
1031 defAlignLong(I2O_HBA_BUS_RESET_MESSAGE,Message);
1032 I2O_HBA_BUS_RESET_MESSAGE * Message_Ptr;
1033 PI2O_LCT_ENTRY Device;
1035 Message_Ptr = (I2O_HBA_BUS_RESET_MESSAGE *)ASR_fillMessage(Message,
1036 sizeof(I2O_HBA_BUS_RESET_MESSAGE));
1037 I2O_MESSAGE_FRAME_setFunction(&Message_Ptr->StdMessageFrame,
1039 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
1040 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1042 if (((Device->le_type & I2O_PORT) != 0)
1043 && (Device->le_bus == bus)) {
1044 I2O_MESSAGE_FRAME_setTargetAddress(
1045 &Message_Ptr->StdMessageFrame,
1046 I2O_LCT_ENTRY_getLocalTID(Device));
1047 /* Asynchronous command, with no expectations */
1048 (void)ASR_queue(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1052 } /* ASR_resetBus */
1055 ASR_getBlinkLedCode (
1056 IN Asr_softc_t * sc)
1058 if ((sc != (Asr_softc_t *)NULL)
1059 && (sc->ha_blinkLED != (u_int8_t *)NULL)
1060 && (sc->ha_blinkLED[1] == 0xBC)) {
1061 return (sc->ha_blinkLED[0]);
1064 } /* ASR_getBlinkCode */
1067 * Determine the address of an TID lookup. Must be done at high priority
1068 * since the address can be changed by other threads of execution.
1070 * Returns NULL pointer if not indexible (but will attempt to generate
1071 * an index if `new_entry' flag is set to TRUE).
1073 * All addressible entries are to be guaranteed zero if never initialized.
1075 STATIC INLINE tid_t *
1077 INOUT Asr_softc_t * sc,
1083 target2lun_t * bus_ptr;
1084 lun2tid_t * target_ptr;
1088 * Validity checking of incoming parameters. More of a bound
1089 * expansion limit than an issue with the code dealing with the
1092 * sc must be valid before it gets here, so that check could be
1093 * dropped if speed a critical issue.
1095 if ((sc == (Asr_softc_t *)NULL)
1096 || (bus > MAX_CHANNEL)
1097 || (target > sc->ha_MaxId)
1098 || (lun > sc->ha_MaxLun)) {
1099 debug_asr_printf("(%lx,%d,%d,%d) target out of range\n",
1100 (u_long)sc, bus, target, lun);
1101 return ((tid_t *)NULL);
1104 * See if there is an associated bus list.
1106 * for performance, allocate in size of BUS_CHUNK chunks.
1107 * BUS_CHUNK must be a power of two. This is to reduce
1108 * fragmentation effects on the allocations.
1110 # define BUS_CHUNK 8
1111 new_size = ((target + BUS_CHUNK - 1) & ~(BUS_CHUNK - 1));
1112 if ((bus_ptr = sc->ha_targets[bus]) == (target2lun_t *)NULL) {
1114 * Allocate a new structure?
1115 * Since one element in structure, the +1
1116 * needed for size has been abstracted.
1118 if ((new_entry == FALSE)
1119 || ((sc->ha_targets[bus] = bus_ptr = (target2lun_t *)malloc (
1120 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1122 == (target2lun_t *)NULL)) {
1123 debug_asr_printf("failed to allocate bus list\n");
1124 return ((tid_t *)NULL);
1126 bzero (bus_ptr, sizeof(*bus_ptr)
1127 + (sizeof(bus_ptr->LUN) * new_size));
1128 bus_ptr->size = new_size + 1;
1129 } else if (bus_ptr->size <= new_size) {
1130 target2lun_t * new_bus_ptr;
1133 * Reallocate a new structure?
1134 * Since one element in structure, the +1
1135 * needed for size has been abstracted.
1137 if ((new_entry == FALSE)
1138 || ((new_bus_ptr = (target2lun_t *)malloc (
1139 sizeof(*bus_ptr) + (sizeof(bus_ptr->LUN) * new_size),
1141 == (target2lun_t *)NULL)) {
1142 debug_asr_printf("failed to reallocate bus list\n");
1143 return ((tid_t *)NULL);
1146 * Zero and copy the whole thing, safer, simpler coding
1147 * and not really performance critical at this point.
1149 bzero (new_bus_ptr, sizeof(*bus_ptr)
1150 + (sizeof(bus_ptr->LUN) * new_size));
1151 bcopy (bus_ptr, new_bus_ptr, sizeof(*bus_ptr)
1152 + (sizeof(bus_ptr->LUN) * (bus_ptr->size - 1)));
1153 sc->ha_targets[bus] = new_bus_ptr;
1154 free (bus_ptr, M_TEMP);
1155 bus_ptr = new_bus_ptr;
1156 bus_ptr->size = new_size + 1;
1159 * We now have the bus list, lets get to the target list.
1160 * Since most systems have only *one* lun, we do not allocate
1161 * in chunks as above, here we allow one, then in chunk sizes.
1162 * TARGET_CHUNK must be a power of two. This is to reduce
1163 * fragmentation effects on the allocations.
1165 # define TARGET_CHUNK 8
1166 if ((new_size = lun) != 0) {
1167 new_size = ((lun + TARGET_CHUNK - 1) & ~(TARGET_CHUNK - 1));
1169 if ((target_ptr = bus_ptr->LUN[target]) == (lun2tid_t *)NULL) {
1171 * Allocate a new structure?
1172 * Since one element in structure, the +1
1173 * needed for size has been abstracted.
1175 if ((new_entry == FALSE)
1176 || ((bus_ptr->LUN[target] = target_ptr = (lun2tid_t *)malloc (
1177 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1179 == (lun2tid_t *)NULL)) {
1180 debug_asr_printf("failed to allocate target list\n");
1181 return ((tid_t *)NULL);
1183 bzero (target_ptr, sizeof(*target_ptr)
1184 + (sizeof(target_ptr->TID) * new_size));
1185 target_ptr->size = new_size + 1;
1186 } else if (target_ptr->size <= new_size) {
1187 lun2tid_t * new_target_ptr;
1190 * Reallocate a new structure?
1191 * Since one element in structure, the +1
1192 * needed for size has been abstracted.
1194 if ((new_entry == FALSE)
1195 || ((new_target_ptr = (lun2tid_t *)malloc (
1196 sizeof(*target_ptr) + (sizeof(target_ptr->TID) * new_size),
1198 == (lun2tid_t *)NULL)) {
1199 debug_asr_printf("failed to reallocate target list\n");
1200 return ((tid_t *)NULL);
1203 * Zero and copy the whole thing, safer, simpler coding
1204 * and not really performance critical at this point.
1206 bzero (new_target_ptr, sizeof(*target_ptr)
1207 + (sizeof(target_ptr->TID) * new_size));
1208 bcopy (target_ptr, new_target_ptr,
1210 + (sizeof(target_ptr->TID) * (target_ptr->size - 1)));
1211 bus_ptr->LUN[target] = new_target_ptr;
1212 free (target_ptr, M_TEMP);
1213 target_ptr = new_target_ptr;
1214 target_ptr->size = new_size + 1;
1217 * Now, acquire the TID address from the LUN indexed list.
1219 return (&(target_ptr->TID[lun]));
1220 } /* ASR_getTidAddress */
1223 * Get a pre-existing TID relationship.
1225 * If the TID was never set, return (tid_t)-1.
1227 * should use mutex rather than spl.
1231 IN Asr_softc_t * sc,
1241 if (((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, FALSE))
1243 /* (tid_t)0 or (tid_t)-1 indicate no TID */
1244 || (*tid_ptr == (tid_t)0)) {
1254 * Set a TID relationship.
1256 * If the TID was not set, return (tid_t)-1.
1258 * should use mutex rather than spl.
1262 INOUT Asr_softc_t * sc,
1271 if (TID != (tid_t)-1) {
1276 if ((tid_ptr = ASR_getTidAddress (sc, bus, target, lun, TRUE))
1287 /*-------------------------------------------------------------------------*/
1288 /* Function ASR_rescan */
1289 /*-------------------------------------------------------------------------*/
1290 /* The Parameters Passed To This Function Are : */
1291 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1293 /* This Function Will rescan the adapter and resynchronize any data */
1295 /* Return : 0 For OK, Error Code Otherwise */
1296 /*-------------------------------------------------------------------------*/
1300 IN Asr_softc_t * sc)
1306 * Re-acquire the LCT table and synchronize us to the adapter.
1308 if ((error = ASR_acquireLct(sc)) == 0) {
1309 error = ASR_acquireHrt(sc);
1316 bus = sc->ha_MaxBus;
1317 /* Reset all existing cached TID lookups */
1319 int target, event = 0;
1322 * Scan for all targets on this bus to see if they
1323 * got affected by the rescan.
1325 for (target = 0; target <= sc->ha_MaxId; ++target) {
1328 /* Stay away from the controller ID */
1329 if (target == sc->ha_adapter_target[bus]) {
1332 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
1333 PI2O_LCT_ENTRY Device;
1334 tid_t TID = (tid_t)-1;
1338 * See if the cached TID changed. Search for
1339 * the device in our new LCT.
1341 for (Device = sc->ha_LCT->LCTEntry;
1342 Device < (PI2O_LCT_ENTRY)(((U32 *)sc->ha_LCT)
1343 + I2O_LCT_getTableSize(sc->ha_LCT));
1345 if ((Device->le_type != I2O_UNKNOWN)
1346 && (Device->le_bus == bus)
1347 && (Device->le_target == target)
1348 && (Device->le_lun == lun)
1349 && (I2O_LCT_ENTRY_getUserTID(Device)
1351 TID = I2O_LCT_ENTRY_getLocalTID(
1357 * Indicate to the OS that the label needs
1358 * to be recalculated, or that the specific
1359 * open device is no longer valid (Merde)
1360 * because the cached TID changed.
1362 LastTID = ASR_getTid (sc, bus, target, lun);
1363 if (LastTID != TID) {
1364 struct cam_path * path;
1366 if (xpt_create_path(&path,
1368 cam_sim_path(sc->ha_sim[bus]),
1369 target, lun) != CAM_REQ_CMP) {
1370 if (TID == (tid_t)-1) {
1371 event |= AC_LOST_DEVICE;
1373 event |= AC_INQ_CHANGED
1374 | AC_GETDEV_CHANGED;
1377 if (TID == (tid_t)-1) {
1381 } else if (LastTID == (tid_t)-1) {
1382 struct ccb_getdev ccb;
1386 path, /*priority*/5);
1402 * We have the option of clearing the
1403 * cached TID for it to be rescanned, or to
1404 * set it now even if the device never got
1405 * accessed. We chose the later since we
1406 * currently do not use the condition that
1407 * the TID ever got cached.
1409 ASR_setTid (sc, bus, target, lun, TID);
1413 * The xpt layer can not handle multiple events at the
1416 if (event & AC_LOST_DEVICE) {
1417 xpt_async(AC_LOST_DEVICE, sc->ha_path[bus], NULL);
1419 if (event & AC_INQ_CHANGED) {
1420 xpt_async(AC_INQ_CHANGED, sc->ha_path[bus], NULL);
1422 if (event & AC_GETDEV_CHANGED) {
1423 xpt_async(AC_GETDEV_CHANGED, sc->ha_path[bus], NULL);
1425 } while (--bus >= 0);
1429 /*-------------------------------------------------------------------------*/
1430 /* Function ASR_reset */
1431 /*-------------------------------------------------------------------------*/
1432 /* The Parameters Passed To This Function Are : */
1433 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
1435 /* This Function Will reset the adapter and resynchronize any data */
1438 /*-------------------------------------------------------------------------*/
1442 IN Asr_softc_t * sc)
1447 if ((sc->ha_in_reset == HA_IN_RESET)
1448 || (sc->ha_in_reset == HA_OFF_LINE_RECOVERY)) {
1453 * Promotes HA_OPERATIONAL to HA_IN_RESET,
1454 * or HA_OFF_LINE to HA_OFF_LINE_RECOVERY.
1456 ++(sc->ha_in_reset);
1457 if (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0) {
1458 debug_asr_printf ("ASR_resetIOP failed\n");
1460 * We really need to take this card off-line, easier said
1461 * than make sense. Better to keep retrying for now since if a
1462 * UART cable is connected the blinkLEDs the adapter is now in
1463 * a hard state requiring action from the monitor commands to
1464 * the HBA to continue. For debugging waiting forever is a
1465 * good thing. In a production system, however, one may wish
1466 * to instead take the card off-line ...
1468 # if 0 && (defined(HA_OFF_LINE))
1470 * Take adapter off-line.
1472 printf ("asr%d: Taking adapter off-line\n",
1474 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1476 sc->ha_in_reset = HA_OFF_LINE;
1481 while (ASR_resetIOP (sc->ha_Virt, sc->ha_Fvirt) == 0);
1484 retVal = ASR_init (sc);
1487 debug_asr_printf ("ASR_init failed\n");
1488 sc->ha_in_reset = HA_OFF_LINE;
1491 if (ASR_rescan (sc) != 0) {
1492 debug_asr_printf ("ASR_rescan failed\n");
1494 ASR_failActiveCommands (sc);
1495 if (sc->ha_in_reset == HA_OFF_LINE_RECOVERY) {
1496 printf ("asr%d: Brining adapter back on-line\n",
1498 ? cam_sim_unit(xpt_path_sim(sc->ha_path[0]))
1501 sc->ha_in_reset = HA_OPERATIONAL;
1506 * Device timeout handler.
1512 union asr_ccb * ccb = (union asr_ccb *)arg;
1513 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
1516 debug_asr_print_path(ccb);
1517 debug_asr_printf("timed out");
1520 * Check if the adapter has locked up?
1522 if ((s = ASR_getBlinkLedCode(sc)) != 0) {
1524 printf ("asr%d: Blink LED 0x%x resetting adapter\n",
1525 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)), s);
1526 if (ASR_reset (sc) == ENXIO) {
1527 /* Try again later */
1528 callout_reset(&ccb->ccb_h.timeout_ch,
1529 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
1534 * Abort does not function on the ASR card!!! Walking away from
1535 * the SCSI command is also *very* dangerous. A SCSI BUS reset is
1536 * our best bet, followed by a complete adapter reset if that fails.
1539 /* Check if we already timed out once to raise the issue */
1540 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_CMD_TIMEOUT) {
1541 debug_asr_printf (" AGAIN\nreinitializing adapter\n");
1542 if (ASR_reset (sc) == ENXIO) {
1543 callout_reset(&ccb->ccb_h.timeout_ch,
1544 (ccb->ccb_h.timeout * hz) / 1000, asr_timeout, ccb);
1549 debug_asr_printf ("\nresetting bus\n");
1550 /* If the BUS reset does not take, then an adapter reset is next! */
1551 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1552 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1553 callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
1555 ASR_resetBus (sc, cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)));
1556 xpt_async (AC_BUS_RESET, ccb->ccb_h.path, NULL);
1561 * send a message asynchronously
1565 IN Asr_softc_t * sc,
1566 IN PI2O_MESSAGE_FRAME Message)
1568 OUT U32 MessageOffset;
1569 union asr_ccb * ccb;
1571 debug_asr_printf ("Host Command Dump:\n");
1572 debug_asr_dump_message (Message);
1574 ccb = (union asr_ccb *)(long)
1575 I2O_MESSAGE_FRAME_getInitiatorContext64(Message);
1577 if ((MessageOffset = ASR_getMessage(sc->ha_Virt)) != EMPTY_QUEUE) {
1578 bcopy (Message, sc->ha_Fvirt + MessageOffset,
1579 I2O_MESSAGE_FRAME_getMessageSize(Message) << 2);
1581 ASR_ccbAdd (sc, ccb);
1583 /* Post the command */
1584 sc->ha_Virt->ToFIFO = MessageOffset;
1586 if (ASR_getBlinkLedCode(sc)) {
1588 * Unlikely we can do anything if we can't grab a
1589 * message frame :-(, but lets give it a try.
1591 (void)ASR_reset (sc);
1594 return (MessageOffset);
1598 /* Simple Scatter Gather elements */
1599 #define SG(SGL,Index,Flags,Buffer,Size) \
1600 I2O_FLAGS_COUNT_setCount( \
1601 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1603 I2O_FLAGS_COUNT_setFlags( \
1604 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index].FlagsCount), \
1605 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | (Flags)); \
1606 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress( \
1607 &(((PI2O_SG_ELEMENT)(SGL))->u.Simple[Index]), \
1608 (Buffer == NULL) ? NULL : KVTOPHYS(Buffer))
1611 * Retrieve Parameter Group.
1612 * Buffer must be allocated using defAlignLong macro.
1616 IN Asr_softc_t * sc,
1620 IN unsigned BufferSize)
1622 struct paramGetMessage {
1623 I2O_UTIL_PARAMS_GET_MESSAGE M;
1625 sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT)];
1627 I2O_PARAM_OPERATIONS_LIST_HEADER Header;
1628 I2O_PARAM_OPERATION_ALL_TEMPLATE Template[1];
1631 defAlignLong(struct paramGetMessage, Message);
1632 struct Operations * Operations_Ptr;
1633 I2O_UTIL_PARAMS_GET_MESSAGE * Message_Ptr;
1634 struct ParamBuffer {
1635 I2O_PARAM_RESULTS_LIST_HEADER Header;
1636 I2O_PARAM_READ_OPERATION_RESULT Read;
1640 Message_Ptr = (I2O_UTIL_PARAMS_GET_MESSAGE *)ASR_fillMessage(Message,
1641 sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1642 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1643 Operations_Ptr = (struct Operations *)((char *)Message_Ptr
1644 + sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)
1645 + sizeof(I2O_SGE_SIMPLE_ELEMENT)*2 - sizeof(I2O_SG_ELEMENT));
1646 bzero ((void *)Operations_Ptr, sizeof(struct Operations));
1647 I2O_PARAM_OPERATIONS_LIST_HEADER_setOperationCount(
1648 &(Operations_Ptr->Header), 1);
1649 I2O_PARAM_OPERATION_ALL_TEMPLATE_setOperation(
1650 &(Operations_Ptr->Template[0]), I2O_PARAMS_OPERATION_FIELD_GET);
1651 I2O_PARAM_OPERATION_ALL_TEMPLATE_setFieldCount(
1652 &(Operations_Ptr->Template[0]), 0xFFFF);
1653 I2O_PARAM_OPERATION_ALL_TEMPLATE_setGroupNumber(
1654 &(Operations_Ptr->Template[0]), Group);
1655 bzero ((void *)(Buffer_Ptr = getAlignLong(struct ParamBuffer, Buffer)),
1658 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1660 + (((sizeof(I2O_UTIL_PARAMS_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1661 / sizeof(U32)) << 4));
1662 I2O_MESSAGE_FRAME_setTargetAddress (&(Message_Ptr->StdMessageFrame),
1664 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
1665 I2O_UTIL_PARAMS_GET);
1667 * Set up the buffers as scatter gather elements.
1669 SG(&(Message_Ptr->SGL), 0,
1670 I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER,
1671 Operations_Ptr, sizeof(struct Operations));
1672 SG(&(Message_Ptr->SGL), 1,
1673 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
1674 Buffer_Ptr, BufferSize);
1676 if ((ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) == CAM_REQ_CMP)
1677 && (Buffer_Ptr->Header.ResultCount)) {
1678 return ((void *)(Buffer_Ptr->Info));
1680 return ((void *)NULL);
1681 } /* ASR_getParams */
1684 * Acquire the LCT information.
1688 INOUT Asr_softc_t * sc)
1690 PI2O_EXEC_LCT_NOTIFY_MESSAGE Message_Ptr;
1691 PI2O_SGE_SIMPLE_ELEMENT sg;
1692 int MessageSizeInBytes;
1696 PI2O_LCT_ENTRY Entry;
1699 * sc value assumed valid
1701 MessageSizeInBytes = sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)
1702 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT);
1703 if ((Message_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)malloc (
1704 MessageSizeInBytes, M_TEMP, M_WAITOK))
1705 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1708 (void)ASR_fillMessage((char *)Message_Ptr, MessageSizeInBytes);
1709 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
1711 (((sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1712 / sizeof(U32)) << 4)));
1713 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
1714 I2O_EXEC_LCT_NOTIFY);
1715 I2O_EXEC_LCT_NOTIFY_MESSAGE_setClassIdentifier(Message_Ptr,
1716 I2O_CLASS_MATCH_ANYCLASS);
1718 * Call the LCT table to determine the number of device entries
1719 * to reserve space for.
1721 SG(&(Message_Ptr->SGL), 0,
1722 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, &Table,
1725 * since this code is reused in several systems, code efficiency
1726 * is greater by using a shift operation rather than a divide by
1727 * sizeof(u_int32_t).
1729 I2O_LCT_setTableSize(&Table,
1730 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1731 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1733 * Determine the size of the LCT table.
1736 free (sc->ha_LCT, M_TEMP);
1739 * malloc only generates contiguous memory when less than a
1740 * page is expected. We must break the request up into an SG list ...
1742 if (((len = (I2O_LCT_getTableSize(&Table) << 2)) <=
1743 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)))
1744 || (len > (128 * 1024))) { /* Arbitrary */
1745 free (Message_Ptr, M_TEMP);
1748 if ((sc->ha_LCT = (PI2O_LCT)malloc (len, M_TEMP, M_WAITOK))
1749 == (PI2O_LCT)NULL) {
1750 free (Message_Ptr, M_TEMP);
1754 * since this code is reused in several systems, code efficiency
1755 * is greater by using a shift operation rather than a divide by
1756 * sizeof(u_int32_t).
1758 I2O_LCT_setTableSize(sc->ha_LCT,
1759 (sizeof(I2O_LCT) - sizeof(I2O_LCT_ENTRY)) >> 2);
1761 * Convert the access to the LCT table into a SG list.
1763 sg = Message_Ptr->SGL.u.Simple;
1764 v = (caddr_t)(sc->ha_LCT);
1766 int next, base, span;
1769 next = base = KVTOPHYS(v);
1770 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
1772 /* How far can we go contiguously */
1773 while ((len > 0) && (base == next)) {
1776 next = trunc_page(base) + PAGE_SIZE;
1787 /* Construct the Flags */
1788 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
1790 int rw = I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT;
1792 rw = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT
1793 | I2O_SGL_FLAGS_LAST_ELEMENT
1794 | I2O_SGL_FLAGS_END_OF_BUFFER);
1796 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount), rw);
1804 * Incrementing requires resizing of the packet.
1807 MessageSizeInBytes += sizeof(*sg);
1808 I2O_MESSAGE_FRAME_setMessageSize(
1809 &(Message_Ptr->StdMessageFrame),
1810 I2O_MESSAGE_FRAME_getMessageSize(
1811 &(Message_Ptr->StdMessageFrame))
1812 + (sizeof(*sg) / sizeof(U32)));
1814 PI2O_EXEC_LCT_NOTIFY_MESSAGE NewMessage_Ptr;
1816 if ((NewMessage_Ptr = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)
1817 malloc (MessageSizeInBytes, M_TEMP, M_WAITOK))
1818 == (PI2O_EXEC_LCT_NOTIFY_MESSAGE)NULL) {
1819 free (sc->ha_LCT, M_TEMP);
1820 sc->ha_LCT = (PI2O_LCT)NULL;
1821 free (Message_Ptr, M_TEMP);
1824 span = ((caddr_t)sg) - (caddr_t)Message_Ptr;
1825 bcopy ((caddr_t)Message_Ptr,
1826 (caddr_t)NewMessage_Ptr, span);
1827 free (Message_Ptr, M_TEMP);
1828 sg = (PI2O_SGE_SIMPLE_ELEMENT)
1829 (((caddr_t)NewMessage_Ptr) + span);
1830 Message_Ptr = NewMessage_Ptr;
1835 retval = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
1836 free (Message_Ptr, M_TEMP);
1837 if (retval != CAM_REQ_CMP) {
1841 /* If the LCT table grew, lets truncate accesses */
1842 if (I2O_LCT_getTableSize(&Table) < I2O_LCT_getTableSize(sc->ha_LCT)) {
1843 I2O_LCT_setTableSize(sc->ha_LCT, I2O_LCT_getTableSize(&Table));
1845 for (Entry = sc->ha_LCT->LCTEntry; Entry < (PI2O_LCT_ENTRY)
1846 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1848 Entry->le_type = I2O_UNKNOWN;
1849 switch (I2O_CLASS_ID_getClass(&(Entry->ClassID))) {
1851 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
1852 Entry->le_type = I2O_BSA;
1855 case I2O_CLASS_SCSI_PERIPHERAL:
1856 Entry->le_type = I2O_SCSI;
1859 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
1860 Entry->le_type = I2O_FCA;
1863 case I2O_CLASS_BUS_ADAPTER_PORT:
1864 Entry->le_type = I2O_PORT | I2O_SCSI;
1866 case I2O_CLASS_FIBRE_CHANNEL_PORT:
1867 if (I2O_CLASS_ID_getClass(&(Entry->ClassID)) ==
1868 I2O_CLASS_FIBRE_CHANNEL_PORT) {
1869 Entry->le_type = I2O_PORT | I2O_FCA;
1871 { struct ControllerInfo {
1872 I2O_PARAM_RESULTS_LIST_HEADER Header;
1873 I2O_PARAM_READ_OPERATION_RESULT Read;
1874 I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1876 defAlignLong(struct ControllerInfo, Buffer);
1877 PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR Info;
1879 Entry->le_bus = 0xff;
1880 Entry->le_target = 0xff;
1881 Entry->le_lun = 0xff;
1883 if ((Info = (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)
1885 I2O_LCT_ENTRY_getLocalTID(Entry),
1886 I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO,
1887 Buffer, sizeof(struct ControllerInfo)))
1888 == (PI2O_HBA_SCSI_CONTROLLER_INFO_SCALAR)NULL) {
1892 = I2O_HBA_SCSI_CONTROLLER_INFO_SCALAR_getInitiatorID(
1899 { struct DeviceInfo {
1900 I2O_PARAM_RESULTS_LIST_HEADER Header;
1901 I2O_PARAM_READ_OPERATION_RESULT Read;
1902 I2O_DPT_DEVICE_INFO_SCALAR Info;
1904 defAlignLong (struct DeviceInfo, Buffer);
1905 PI2O_DPT_DEVICE_INFO_SCALAR Info;
1907 Entry->le_bus = 0xff;
1908 Entry->le_target = 0xff;
1909 Entry->le_lun = 0xff;
1911 if ((Info = (PI2O_DPT_DEVICE_INFO_SCALAR)
1913 I2O_LCT_ENTRY_getLocalTID(Entry),
1914 I2O_DPT_DEVICE_INFO_GROUP_NO,
1915 Buffer, sizeof(struct DeviceInfo)))
1916 == (PI2O_DPT_DEVICE_INFO_SCALAR)NULL) {
1920 |= I2O_DPT_DEVICE_INFO_SCALAR_getDeviceType(Info);
1922 = I2O_DPT_DEVICE_INFO_SCALAR_getBus(Info);
1923 if ((Entry->le_bus > sc->ha_MaxBus)
1924 && (Entry->le_bus <= MAX_CHANNEL)) {
1925 sc->ha_MaxBus = Entry->le_bus;
1928 = I2O_DPT_DEVICE_INFO_SCALAR_getIdentifier(Info);
1930 = I2O_DPT_DEVICE_INFO_SCALAR_getLunInfo(Info);
1934 * A zero return value indicates success.
1937 } /* ASR_acquireLct */
1940 * Initialize a message frame.
1941 * We assume that the CDB has already been set up, so all we do here is
1942 * generate the Scatter Gather list.
1944 STATIC INLINE PI2O_MESSAGE_FRAME
1946 IN union asr_ccb * ccb,
1947 OUT PI2O_MESSAGE_FRAME Message)
1949 int next, span, base, rw;
1950 OUT PI2O_MESSAGE_FRAME Message_Ptr;
1951 Asr_softc_t * sc = (Asr_softc_t *)(ccb->ccb_h.spriv_ptr0);
1952 PI2O_SGE_SIMPLE_ELEMENT sg;
1954 vm_size_t size, len;
1957 /* We only need to zero out the PRIVATE_SCSI_SCB_EXECUTE_MESSAGE */
1958 bzero (Message_Ptr = getAlignLong(I2O_MESSAGE_FRAME, Message),
1959 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT)));
1962 int target = ccb->ccb_h.target_id;
1963 int lun = ccb->ccb_h.target_lun;
1964 int bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
1967 if ((TID = ASR_getTid (sc, bus, target, lun)) == (tid_t)-1) {
1968 PI2O_LCT_ENTRY Device;
1971 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
1972 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
1974 if ((Device->le_type != I2O_UNKNOWN)
1975 && (Device->le_bus == bus)
1976 && (Device->le_target == target)
1977 && (Device->le_lun == lun)
1978 && (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF)) {
1979 TID = I2O_LCT_ENTRY_getLocalTID(Device);
1980 ASR_setTid (sc, Device->le_bus,
1981 Device->le_target, Device->le_lun,
1987 if (TID == (tid_t)0) {
1988 return ((PI2O_MESSAGE_FRAME)NULL);
1990 I2O_MESSAGE_FRAME_setTargetAddress(Message_Ptr, TID);
1991 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(
1992 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, TID);
1994 I2O_MESSAGE_FRAME_setVersionOffset(Message_Ptr, I2O_VERSION_11 |
1995 (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT))
1996 / sizeof(U32)) << 4));
1997 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
1998 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
1999 - sizeof(I2O_SG_ELEMENT)) / sizeof(U32));
2000 I2O_MESSAGE_FRAME_setInitiatorAddress (Message_Ptr, 1);
2001 I2O_MESSAGE_FRAME_setFunction(Message_Ptr, I2O_PRIVATE_MESSAGE);
2002 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2003 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, I2O_SCSI_SCB_EXEC);
2004 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
2005 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2006 I2O_SCB_FLAG_ENABLE_DISCONNECT
2007 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2008 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2010 * We do not need any (optional byteswapping) method access to
2011 * the Initiator & Transaction context field.
2013 I2O_MESSAGE_FRAME_setInitiatorContext64(Message, (long)ccb);
2015 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2016 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr, DPT_ORGANIZATION_ID);
2020 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(
2021 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, ccb->csio.cdb_len);
2022 bcopy (&(ccb->csio.cdb_io),
2023 ((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->CDB, ccb->csio.cdb_len);
2026 * Given a buffer describing a transfer, set up a scatter/gather map
2027 * in a ccb to map that SCSI transfer.
2030 rw = (ccb->ccb_h.flags & CAM_DIR_IN) ? 0 : I2O_SGL_FLAGS_DIR;
2032 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (
2033 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2034 (ccb->csio.dxfer_len)
2035 ? ((rw) ? (I2O_SCB_FLAG_XFER_TO_DEVICE
2036 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2037 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2038 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER)
2039 : (I2O_SCB_FLAG_XFER_FROM_DEVICE
2040 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2041 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2042 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER))
2043 : (I2O_SCB_FLAG_ENABLE_DISCONNECT
2044 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2045 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2048 * Given a transfer described by a `data', fill in the SG list.
2050 sg = &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr)->SGL.u.Simple[0];
2052 len = ccb->csio.dxfer_len;
2053 v = ccb->csio.data_ptr;
2054 ASSERT (ccb->csio.dxfer_len >= 0);
2055 MessageSize = I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr);
2056 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
2057 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr, len);
2058 while ((len > 0) && (sg < &((PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2059 Message_Ptr)->SGL.u.Simple[SG_SIZE])) {
2061 next = base = KVTOPHYS(v);
2062 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg, base);
2064 /* How far can we go contiguously */
2065 while ((len > 0) && (base == next)) {
2066 next = trunc_page(base) + PAGE_SIZE;
2077 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount), span);
2079 rw |= I2O_SGL_FLAGS_LAST_ELEMENT;
2081 I2O_FLAGS_COUNT_setFlags(&(sg->FlagsCount),
2082 I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | rw);
2084 MessageSize += sizeof(*sg) / sizeof(U32);
2086 /* We always do the request sense ... */
2087 if ((span = ccb->csio.sense_len) == 0) {
2088 span = sizeof(ccb->csio.sense_data);
2090 SG(sg, 0, I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2091 &(ccb->csio.sense_data), span);
2092 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
2093 MessageSize + (sizeof(*sg) / sizeof(U32)));
2094 return (Message_Ptr);
2095 } /* ASR_init_message */
2098 * Reset the adapter.
2102 INOUT Asr_softc_t * sc)
2104 struct initOutBoundMessage {
2105 I2O_EXEC_OUTBOUND_INIT_MESSAGE M;
2108 defAlignLong(struct initOutBoundMessage,Message);
2109 PI2O_EXEC_OUTBOUND_INIT_MESSAGE Message_Ptr;
2110 OUT U32 * volatile Reply_Ptr;
2114 * Build up our copy of the Message.
2116 Message_Ptr = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)ASR_fillMessage(Message,
2117 sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE));
2118 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2119 I2O_EXEC_OUTBOUND_INIT);
2120 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setHostPageFrameSize(Message_Ptr, PAGE_SIZE);
2121 I2O_EXEC_OUTBOUND_INIT_MESSAGE_setOutboundMFrameSize(Message_Ptr,
2122 sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME));
2124 * Reset the Reply Status
2126 *(Reply_Ptr = (U32 *)((char *)Message_Ptr
2127 + sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE))) = 0;
2128 SG (&(Message_Ptr->SGL), 0, I2O_SGL_FLAGS_LAST_ELEMENT, Reply_Ptr,
2131 * Send the Message out
2133 if ((Old = ASR_initiateCp (sc->ha_Virt, sc->ha_Fvirt, (PI2O_MESSAGE_FRAME)Message_Ptr)) != (U32)-1L) {
2137 * Wait for a response (Poll).
2139 while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED);
2141 * Re-enable the interrupts.
2143 sc->ha_Virt->Mask = Old;
2145 * Populate the outbound table.
2147 if (sc->ha_Msgs == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2149 /* Allocate the reply frames */
2150 size = sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2151 * sc->ha_Msgs_Count;
2154 * contigmalloc only works reliably at
2155 * initialization time.
2157 if ((sc->ha_Msgs = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
2158 contigmalloc (size, M_DEVBUF, M_WAITOK, 0ul,
2159 0xFFFFFFFFul, (u_long)sizeof(U32), 0ul))
2160 != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
2161 (void)bzero ((char *)sc->ha_Msgs, size);
2162 sc->ha_Msgs_Phys = KVTOPHYS(sc->ha_Msgs);
2166 /* Initialize the outbound FIFO */
2167 if (sc->ha_Msgs != (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL)
2168 for (size = sc->ha_Msgs_Count, addr = sc->ha_Msgs_Phys;
2170 sc->ha_Virt->FromFIFO = addr;
2171 addr += sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME);
2173 return (*Reply_Ptr);
2176 } /* ASR_initOutBound */
2179 * Set the system table
2183 IN Asr_softc_t * sc)
2185 PI2O_EXEC_SYS_TAB_SET_MESSAGE Message_Ptr;
2186 PI2O_SET_SYSTAB_HEADER SystemTable;
2188 PI2O_SGE_SIMPLE_ELEMENT sg;
2191 if ((SystemTable = (PI2O_SET_SYSTAB_HEADER)malloc (
2192 sizeof(I2O_SET_SYSTAB_HEADER), M_TEMP, M_WAITOK))
2193 == (PI2O_SET_SYSTAB_HEADER)NULL) {
2196 bzero (SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2197 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2198 ++SystemTable->NumberEntries;
2200 if ((Message_Ptr = (PI2O_EXEC_SYS_TAB_SET_MESSAGE)malloc (
2201 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2202 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)),
2203 M_TEMP, M_WAITOK)) == (PI2O_EXEC_SYS_TAB_SET_MESSAGE)NULL) {
2204 free (SystemTable, M_TEMP);
2207 (void)ASR_fillMessage((char *)Message_Ptr,
2208 sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2209 + ((3+SystemTable->NumberEntries) * sizeof(I2O_SGE_SIMPLE_ELEMENT)));
2210 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2212 (((sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2213 / sizeof(U32)) << 4)));
2214 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2215 I2O_EXEC_SYS_TAB_SET);
2217 * Call the LCT table to determine the number of device entries
2218 * to reserve space for.
2219 * since this code is reused in several systems, code efficiency
2220 * is greater by using a shift operation rather than a divide by
2221 * sizeof(u_int32_t).
2223 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
2224 + ((I2O_MESSAGE_FRAME_getVersionOffset(
2225 &(Message_Ptr->StdMessageFrame)) & 0xF0) >> 2));
2226 SG(sg, 0, I2O_SGL_FLAGS_DIR, SystemTable, sizeof(I2O_SET_SYSTAB_HEADER));
2228 for (ha = Asr_softc; ha; ha = ha->ha_next) {
2231 ? (I2O_SGL_FLAGS_DIR)
2232 : (I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER)),
2233 &(ha->ha_SystemTable), sizeof(ha->ha_SystemTable));
2236 SG(sg, 0, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2237 SG(sg, 1, I2O_SGL_FLAGS_DIR | I2O_SGL_FLAGS_LAST_ELEMENT
2238 | I2O_SGL_FLAGS_END_OF_BUFFER, NULL, 0);
2239 retVal = ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2240 free (Message_Ptr, M_TEMP);
2241 free (SystemTable, M_TEMP);
2243 } /* ASR_setSysTab */
2247 INOUT Asr_softc_t * sc)
2249 defAlignLong(I2O_EXEC_HRT_GET_MESSAGE,Message);
2250 I2O_EXEC_HRT_GET_MESSAGE * Message_Ptr;
2253 I2O_HRT_ENTRY Entry[MAX_CHANNEL];
2255 u_int8_t NumberOfEntries;
2256 PI2O_HRT_ENTRY Entry;
2258 bzero ((void *)&Hrt, sizeof (Hrt));
2259 Message_Ptr = (I2O_EXEC_HRT_GET_MESSAGE *)ASR_fillMessage(Message,
2260 sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT)
2261 + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2262 I2O_MESSAGE_FRAME_setVersionOffset(&(Message_Ptr->StdMessageFrame),
2264 + (((sizeof(I2O_EXEC_HRT_GET_MESSAGE) - sizeof(I2O_SG_ELEMENT))
2265 / sizeof(U32)) << 4)));
2266 I2O_MESSAGE_FRAME_setFunction (&(Message_Ptr->StdMessageFrame),
2270 * Set up the buffers as scatter gather elements.
2272 SG(&(Message_Ptr->SGL), 0,
2273 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2275 if (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != CAM_REQ_CMP) {
2278 if ((NumberOfEntries = I2O_HRT_getNumberEntries(&Hrt.Header))
2279 > (MAX_CHANNEL + 1)) {
2280 NumberOfEntries = MAX_CHANNEL + 1;
2282 for (Entry = Hrt.Header.HRTEntry;
2283 NumberOfEntries != 0;
2284 ++Entry, --NumberOfEntries) {
2285 PI2O_LCT_ENTRY Device;
2287 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2288 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2290 if (I2O_LCT_ENTRY_getLocalTID(Device)
2291 == (I2O_HRT_ENTRY_getAdapterID(Entry) & 0xFFF)) {
2292 Device->le_bus = I2O_HRT_ENTRY_getAdapterID(
2294 if ((Device->le_bus > sc->ha_MaxBus)
2295 && (Device->le_bus <= MAX_CHANNEL)) {
2296 sc->ha_MaxBus = Device->le_bus;
2302 } /* ASR_acquireHrt */
2305 * Enable the adapter.
2309 IN Asr_softc_t * sc)
2311 defAlignLong(I2O_EXEC_SYS_ENABLE_MESSAGE,Message);
2312 PI2O_EXEC_SYS_ENABLE_MESSAGE Message_Ptr;
2314 Message_Ptr = (PI2O_EXEC_SYS_ENABLE_MESSAGE)ASR_fillMessage(Message,
2315 sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE));
2316 I2O_MESSAGE_FRAME_setFunction(&(Message_Ptr->StdMessageFrame),
2317 I2O_EXEC_SYS_ENABLE);
2318 return (ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr) != 0);
2319 } /* ASR_enableSys */
2322 * Perform the stages necessary to initialize the adapter
2326 IN Asr_softc_t * sc)
2328 return ((ASR_initOutBound(sc) == 0)
2329 || (ASR_setSysTab(sc) != CAM_REQ_CMP)
2330 || (ASR_enableSys(sc) != CAM_REQ_CMP));
2334 * Send a Synchronize Cache command to the target device.
2338 IN Asr_softc_t * sc,
2346 * We will not synchronize the device when there are outstanding
2347 * commands issued by the OS (this is due to a locked up device,
2348 * as the OS normally would flush all outstanding commands before
2349 * issuing a shutdown or an adapter reset).
2351 if ((sc != (Asr_softc_t *)NULL)
2352 && (LIST_FIRST(&(sc->ha_ccb)) != (struct ccb_hdr *)NULL)
2353 && ((TID = ASR_getTid (sc, bus, target, lun)) != (tid_t)-1)
2354 && (TID != (tid_t)0)) {
2355 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
2356 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
2359 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
2360 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2361 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2363 I2O_MESSAGE_FRAME_setVersionOffset(
2364 (PI2O_MESSAGE_FRAME)Message_Ptr,
2366 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2367 - sizeof(I2O_SG_ELEMENT))
2368 / sizeof(U32)) << 4));
2369 I2O_MESSAGE_FRAME_setMessageSize(
2370 (PI2O_MESSAGE_FRAME)Message_Ptr,
2371 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2372 - sizeof(I2O_SG_ELEMENT))
2374 I2O_MESSAGE_FRAME_setInitiatorAddress (
2375 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
2376 I2O_MESSAGE_FRAME_setFunction(
2377 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
2378 I2O_MESSAGE_FRAME_setTargetAddress(
2379 (PI2O_MESSAGE_FRAME)Message_Ptr, TID);
2380 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2381 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2383 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setTID(Message_Ptr, TID);
2384 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2385 I2O_SCB_FLAG_ENABLE_DISCONNECT
2386 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2387 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2388 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2389 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2390 DPT_ORGANIZATION_ID);
2391 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
2392 Message_Ptr->CDB[0] = SYNCHRONIZE_CACHE;
2393 Message_Ptr->CDB[1] = (lun << 5);
2395 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2396 (I2O_SCB_FLAG_XFER_FROM_DEVICE
2397 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2398 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2399 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2401 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2408 IN Asr_softc_t * sc)
2410 int bus, target, lun;
2412 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
2413 for (target = 0; target <= sc->ha_MaxId; ++target) {
2414 for (lun = 0; lun <= sc->ha_MaxLun; ++lun) {
2415 ASR_sync(sc,bus,target,lun);
2422 * Reset the HBA, targets and BUS.
2423 * Currently this resets *all* the SCSI busses.
2427 IN Asr_softc_t * sc)
2429 ASR_synchronize (sc);
2430 (void)ASR_reset (sc);
2431 } /* asr_hbareset */
2434 * A reduced copy of the real pci_map_mem, incorporating the MAX_MAP
2435 * limit and a reduction in error checking (in the pre 4.0 case).
2440 IN Asr_softc_t * sc)
2446 * I2O specification says we must find first *memory* mapped BAR
2448 for (rid = PCIR_MAPS;
2449 rid < (PCIR_MAPS + 4 * sizeof(u_int32_t));
2450 rid += sizeof(u_int32_t)) {
2451 p = pci_read_config(tag, rid, sizeof(p));
2459 if (rid >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2462 p = pci_read_config(tag, rid, sizeof(p));
2463 pci_write_config(tag, rid, -1, sizeof(p));
2464 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2465 pci_write_config(tag, rid, p, sizeof(p));
2470 * The 2005S Zero Channel RAID solution is not a perfect PCI
2471 * citizen. It asks for 4MB on BAR0, and 0MB on BAR1, once
2472 * enabled it rewrites the size of BAR0 to 2MB, sets BAR1 to
2473 * BAR0+2MB and sets it's size to 2MB. The IOP registers are
2474 * accessible via BAR0, the messaging registers are accessible
2475 * via BAR1. If the subdevice code is 50 to 59 decimal.
2477 s = pci_read_config(tag, PCIR_DEVVENDOR, sizeof(s));
2478 if (s != 0xA5111044) {
2479 s = pci_read_config(tag, PCIR_SUBVEND_0, sizeof(s));
2480 if ((((ADPTDOMINATOR_SUB_ID_START ^ s) & 0xF000FFFF) == 0)
2481 && (ADPTDOMINATOR_SUB_ID_START <= s)
2482 && (s <= ADPTDOMINATOR_SUB_ID_END)) {
2483 l = MAX_MAP; /* Conjoined BAR Raptor Daptor */
2487 sc->ha_mem_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2488 p, p + l, l, RF_ACTIVE);
2489 if (sc->ha_mem_res == (struct resource *)NULL) {
2492 sc->ha_Base = (void *)rman_get_start(sc->ha_mem_res);
2493 if (sc->ha_Base == (void *)NULL) {
2496 sc->ha_Virt = (i2oRegs_t *) rman_get_virtual(sc->ha_mem_res);
2497 if (s == 0xA5111044) { /* Split BAR Raptor Daptor */
2498 if ((rid += sizeof(u_int32_t))
2499 >= (PCIR_MAPS + 4 * sizeof(u_int32_t))) {
2502 p = pci_read_config(tag, rid, sizeof(p));
2503 pci_write_config(tag, rid, -1, sizeof(p));
2504 l = 0 - (pci_read_config(tag, rid, sizeof(l)) & ~15);
2505 pci_write_config(tag, rid, p, sizeof(p));
2510 sc->ha_mes_res = bus_alloc_resource(tag, SYS_RES_MEMORY, &rid,
2511 p, p + l, l, RF_ACTIVE);
2512 if (sc->ha_mes_res == (struct resource *)NULL) {
2515 if ((void *)rman_get_start(sc->ha_mes_res) == (void *)NULL) {
2518 sc->ha_Fvirt = (U8 *) rman_get_virtual(sc->ha_mes_res);
2520 sc->ha_Fvirt = (U8 *)(sc->ha_Virt);
2523 } /* asr_pci_map_mem */
2526 * A simplified copy of the real pci_map_int with additional
2527 * registration requirements.
2532 IN Asr_softc_t * sc)
2537 sc->ha_irq_res = bus_alloc_resource(tag, SYS_RES_IRQ, &rid,
2538 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
2539 if (sc->ha_irq_res == (struct resource *)NULL) {
2542 error = bus_setup_intr(tag, sc->ha_irq_res, INTR_TYPE_CAM,
2543 (driver_intr_t *)asr_intr, (void *)sc,
2544 &(sc->ha_intr), NULL);
2548 sc->ha_irq = pci_read_config(tag, PCIR_INTLINE, sizeof(char));
2550 } /* asr_pci_map_int */
2553 * Attach the devices, and virtual devices to the driver list.
2556 asr_attach (ATTACH_ARGS)
2559 struct scsi_inquiry_data * iq;
2562 sc = malloc(sizeof(*sc), M_DEVBUF, M_INTWAIT);
2563 if (Asr_softc == (Asr_softc_t *)NULL) {
2565 * Fixup the OS revision as saved in the dptsig for the
2566 * engine (dptioctl.h) to pick up.
2568 bcopy (osrelease, &ASR_sig.dsDescription[16], 5);
2569 printf ("asr%d: major=%d\n", unit, asr_cdevsw.d_maj);
2572 * Initialize the software structure
2574 bzero (sc, sizeof(*sc));
2575 LIST_INIT(&(sc->ha_ccb));
2576 /* Link us into the HA list */
2580 for (ha = &Asr_softc; *ha; ha = &((*ha)->ha_next));
2584 PI2O_EXEC_STATUS_GET_REPLY status;
2588 * This is the real McCoy!
2590 if (!asr_pci_map_mem(tag, sc)) {
2591 printf ("asr%d: could not map memory\n", unit);
2592 ATTACH_RETURN(ENXIO);
2594 /* Enable if not formerly enabled */
2595 pci_write_config (tag, PCIR_COMMAND,
2596 pci_read_config (tag, PCIR_COMMAND, sizeof(char))
2597 | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN, sizeof(char));
2598 /* Knowledge is power, responsibility is direct */
2600 struct pci_devinfo {
2601 STAILQ_ENTRY(pci_devinfo) pci_links;
2602 struct resource_list resources;
2604 } * dinfo = device_get_ivars(tag);
2605 sc->ha_pciBusNum = dinfo->cfg.bus;
2606 sc->ha_pciDeviceNum = (dinfo->cfg.slot << 3)
2609 /* Check if the device is there? */
2610 if ((ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt) == 0)
2611 || ((status = (PI2O_EXEC_STATUS_GET_REPLY)malloc (
2612 sizeof(I2O_EXEC_STATUS_GET_REPLY), M_TEMP, M_WAITOK))
2613 == (PI2O_EXEC_STATUS_GET_REPLY)NULL)
2614 || (ASR_getStatus(sc->ha_Virt, sc->ha_Fvirt, status) == NULL)) {
2615 printf ("asr%d: could not initialize hardware\n", unit);
2616 ATTACH_RETURN(ENODEV); /* Get next, maybe better luck */
2618 sc->ha_SystemTable.OrganizationID = status->OrganizationID;
2619 sc->ha_SystemTable.IOP_ID = status->IOP_ID;
2620 sc->ha_SystemTable.I2oVersion = status->I2oVersion;
2621 sc->ha_SystemTable.IopState = status->IopState;
2622 sc->ha_SystemTable.MessengerType = status->MessengerType;
2623 sc->ha_SystemTable.InboundMessageFrameSize
2624 = status->InboundMFrameSize;
2625 sc->ha_SystemTable.MessengerInfo.InboundMessagePortAddressLow
2626 = (U32)(sc->ha_Base) + (U32)(&(((i2oRegs_t *)NULL)->ToFIFO));
2628 if (!asr_pci_map_int(tag, (void *)sc)) {
2629 printf ("asr%d: could not map interrupt\n", unit);
2630 ATTACH_RETURN(ENXIO);
2633 /* Adjust the maximim inbound count */
2634 if (((sc->ha_QueueSize
2635 = I2O_EXEC_STATUS_GET_REPLY_getMaxInboundMFrames(status))
2637 || (sc->ha_QueueSize == 0)) {
2638 sc->ha_QueueSize = MAX_INBOUND;
2641 /* Adjust the maximum outbound count */
2642 if (((sc->ha_Msgs_Count
2643 = I2O_EXEC_STATUS_GET_REPLY_getMaxOutboundMFrames(status))
2645 || (sc->ha_Msgs_Count == 0)) {
2646 sc->ha_Msgs_Count = MAX_OUTBOUND;
2648 if (sc->ha_Msgs_Count > sc->ha_QueueSize) {
2649 sc->ha_Msgs_Count = sc->ha_QueueSize;
2652 /* Adjust the maximum SG size to adapter */
2653 if ((size = (I2O_EXEC_STATUS_GET_REPLY_getInboundMFrameSize(
2654 status) << 2)) > MAX_INBOUND_SIZE) {
2655 size = MAX_INBOUND_SIZE;
2657 free (status, M_TEMP);
2658 sc->ha_SgSize = (size - sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2659 + sizeof(I2O_SG_ELEMENT)) / sizeof(I2O_SGE_SIMPLE_ELEMENT);
2663 * Only do a bus/HBA reset on the first time through. On this
2664 * first time through, we do not send a flush to the devices.
2666 if (ASR_init(sc) == 0) {
2668 I2O_PARAM_RESULTS_LIST_HEADER Header;
2669 I2O_PARAM_READ_OPERATION_RESULT Read;
2670 I2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2672 defAlignLong (struct BufferInfo, Buffer);
2673 PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR Info;
2674 # define FW_DEBUG_BLED_OFFSET 8
2676 if ((Info = (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)
2677 ASR_getParams(sc, 0,
2678 I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO,
2679 Buffer, sizeof(struct BufferInfo)))
2680 != (PI2O_DPT_EXEC_IOP_BUFFERS_SCALAR)NULL) {
2681 sc->ha_blinkLED = sc->ha_Fvirt
2682 + I2O_DPT_EXEC_IOP_BUFFERS_SCALAR_getSerialOutputOffset(Info)
2683 + FW_DEBUG_BLED_OFFSET;
2685 if (ASR_acquireLct(sc) == 0) {
2686 (void)ASR_acquireHrt(sc);
2689 printf ("asr%d: failed to initialize\n", unit);
2690 ATTACH_RETURN(ENXIO);
2693 * Add in additional probe responses for more channels. We
2694 * are reusing the variable `target' for a channel loop counter.
2695 * Done here because of we need both the acquireLct and
2698 { PI2O_LCT_ENTRY Device;
2700 for (Device = sc->ha_LCT->LCTEntry; Device < (PI2O_LCT_ENTRY)
2701 (((U32 *)sc->ha_LCT)+I2O_LCT_getTableSize(sc->ha_LCT));
2703 if (Device->le_type == I2O_UNKNOWN) {
2706 if (I2O_LCT_ENTRY_getUserTID(Device) == 0xFFF) {
2707 if (Device->le_target > sc->ha_MaxId) {
2708 sc->ha_MaxId = Device->le_target;
2710 if (Device->le_lun > sc->ha_MaxLun) {
2711 sc->ha_MaxLun = Device->le_lun;
2714 if (((Device->le_type & I2O_PORT) != 0)
2715 && (Device->le_bus <= MAX_CHANNEL)) {
2716 /* Do not increase MaxId for efficiency */
2717 sc->ha_adapter_target[Device->le_bus]
2718 = Device->le_target;
2725 * Print the HBA model number as inquired from the card.
2728 printf ("asr%d:", unit);
2730 if ((iq = (struct scsi_inquiry_data *)malloc (
2731 sizeof(struct scsi_inquiry_data), M_TEMP, M_WAITOK))
2732 != (struct scsi_inquiry_data *)NULL) {
2733 defAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE,Message);
2734 PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE Message_Ptr;
2737 bzero (iq, sizeof(struct scsi_inquiry_data));
2739 = getAlignLong(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE, Message),
2740 sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2741 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT));
2743 I2O_MESSAGE_FRAME_setVersionOffset(
2744 (PI2O_MESSAGE_FRAME)Message_Ptr,
2746 | (((sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2747 - sizeof(I2O_SG_ELEMENT))
2748 / sizeof(U32)) << 4));
2749 I2O_MESSAGE_FRAME_setMessageSize(
2750 (PI2O_MESSAGE_FRAME)Message_Ptr,
2751 (sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE)
2752 - sizeof(I2O_SG_ELEMENT) + sizeof(I2O_SGE_SIMPLE_ELEMENT))
2754 I2O_MESSAGE_FRAME_setInitiatorAddress (
2755 (PI2O_MESSAGE_FRAME)Message_Ptr, 1);
2756 I2O_MESSAGE_FRAME_setFunction(
2757 (PI2O_MESSAGE_FRAME)Message_Ptr, I2O_PRIVATE_MESSAGE);
2758 I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode (
2759 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2761 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2762 I2O_SCB_FLAG_ENABLE_DISCONNECT
2763 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2764 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER);
2765 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(Message_Ptr, 1);
2766 I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(
2767 (PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr,
2768 DPT_ORGANIZATION_ID);
2769 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setCDBLength(Message_Ptr, 6);
2770 Message_Ptr->CDB[0] = INQUIRY;
2771 Message_Ptr->CDB[4] = (unsigned char)sizeof(struct scsi_inquiry_data);
2772 if (Message_Ptr->CDB[4] == 0) {
2773 Message_Ptr->CDB[4] = 255;
2776 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags (Message_Ptr,
2777 (I2O_SCB_FLAG_XFER_FROM_DEVICE
2778 | I2O_SCB_FLAG_ENABLE_DISCONNECT
2779 | I2O_SCB_FLAG_SIMPLE_QUEUE_TAG
2780 | I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER));
2782 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(
2783 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr,
2784 sizeof(struct scsi_inquiry_data));
2785 SG(&(Message_Ptr->SGL), 0,
2786 I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER,
2787 iq, sizeof(struct scsi_inquiry_data));
2788 (void)ASR_queue_c(sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
2790 if (iq->vendor[0] && (iq->vendor[0] != ' ')) {
2792 ASR_prstring (iq->vendor, 8);
2795 if (iq->product[0] && (iq->product[0] != ' ')) {
2797 ASR_prstring (iq->product, 16);
2800 if (iq->revision[0] && (iq->revision[0] != ' ')) {
2801 printf (" FW Rev. ");
2802 ASR_prstring (iq->revision, 4);
2805 free ((caddr_t)iq, M_TEMP);
2810 printf (" %d channel, %d CCBs, Protocol I2O\n", sc->ha_MaxBus + 1,
2811 (sc->ha_QueueSize > MAX_INBOUND) ? MAX_INBOUND : sc->ha_QueueSize);
2814 * fill in the prototype cam_path.
2818 union asr_ccb * ccb;
2820 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
2821 printf ("asr%d: CAM could not be notified of asynchronous callback parameters\n", unit);
2822 ATTACH_RETURN(ENOMEM);
2824 for (bus = 0; bus <= sc->ha_MaxBus; ++bus) {
2825 int QueueSize = sc->ha_QueueSize;
2827 if (QueueSize > MAX_INBOUND) {
2828 QueueSize = MAX_INBOUND;
2832 * Construct our first channel SIM entry
2834 sc->ha_sim[bus] = cam_sim_alloc(
2835 asr_action, asr_poll, "asr", sc,
2836 unit, 1, QueueSize, NULL);
2837 if (sc->ha_sim[bus] == NULL)
2840 if (xpt_bus_register(sc->ha_sim[bus], bus)
2842 cam_sim_free(sc->ha_sim[bus]);
2843 sc->ha_sim[bus] = NULL;
2847 if (xpt_create_path(&(sc->ha_path[bus]), /*periph*/NULL,
2848 cam_sim_path(sc->ha_sim[bus]), CAM_TARGET_WILDCARD,
2849 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2851 cam_sim_path(sc->ha_sim[bus]));
2852 cam_sim_free(sc->ha_sim[bus]);
2853 sc->ha_sim[bus] = NULL;
2860 * Generate the device node information
2862 make_dev(&asr_cdevsw, unit, 0, 0, S_IRWXU, "rasr%d", unit);
2868 IN struct cam_sim *sim)
2870 asr_intr(cam_sim_softc(sim));
2875 IN struct cam_sim * sim,
2878 struct Asr_softc * sc;
2880 debug_asr_printf ("asr_action(%lx,%lx{%x})\n",
2881 (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code);
2883 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("asr_action\n"));
2885 ccb->ccb_h.spriv_ptr0 = sc = (struct Asr_softc *)cam_sim_softc(sim);
2887 switch (ccb->ccb_h.func_code) {
2889 /* Common cases first */
2890 case XPT_SCSI_IO: /* Execute the requested I/O operation */
2893 char M[MAX_INBOUND_SIZE];
2895 defAlignLong(struct Message,Message);
2896 PI2O_MESSAGE_FRAME Message_Ptr;
2898 /* Reject incoming commands while we are resetting the card */
2899 if (sc->ha_in_reset != HA_OPERATIONAL) {
2900 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2901 if (sc->ha_in_reset >= HA_OFF_LINE) {
2902 /* HBA is now off-line */
2903 ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
2905 /* HBA currently resetting, try again later. */
2906 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2908 debug_asr_cmd_printf (" e\n");
2910 debug_asr_cmd_printf (" q\n");
2913 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
2915 "asr%d WARNING: scsi_cmd(%x) already done on b%dt%du%d\n",
2916 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
2917 ccb->csio.cdb_io.cdb_bytes[0],
2919 ccb->ccb_h.target_id,
2920 ccb->ccb_h.target_lun);
2922 debug_asr_cmd_printf ("(%d,%d,%d,%d)",
2925 ccb->ccb_h.target_id,
2926 ccb->ccb_h.target_lun);
2927 debug_asr_cmd_dump_ccb(ccb);
2929 if ((Message_Ptr = ASR_init_message ((union asr_ccb *)ccb,
2930 (PI2O_MESSAGE_FRAME)Message)) != (PI2O_MESSAGE_FRAME)NULL) {
2931 debug_asr_cmd2_printf ("TID=%x:\n",
2932 PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getTID(
2933 (PPRIVATE_SCSI_SCB_EXECUTE_MESSAGE)Message_Ptr));
2934 debug_asr_cmd2_dump_message(Message_Ptr);
2935 debug_asr_cmd1_printf (" q");
2937 if (ASR_queue (sc, Message_Ptr) == EMPTY_QUEUE) {
2938 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2939 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2940 debug_asr_cmd_printf (" E\n");
2943 debug_asr_cmd_printf (" Q\n");
2947 * We will get here if there is no valid TID for the device
2948 * referenced in the scsi command packet.
2950 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2951 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
2952 debug_asr_cmd_printf (" B\n");
2957 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
2958 /* Rese HBA device ... */
2960 ccb->ccb_h.status = CAM_REQ_CMP;
2964 # if (defined(REPORT_LUNS))
2967 case XPT_ABORT: /* Abort the specified CCB */
2969 ccb->ccb_h.status = CAM_REQ_INVALID;
2973 case XPT_SET_TRAN_SETTINGS:
2975 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2979 case XPT_GET_TRAN_SETTINGS:
2980 /* Get default/user set transfer settings for the target */
2982 struct ccb_trans_settings *cts;
2986 target_mask = 0x01 << ccb->ccb_h.target_id;
2987 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
2988 cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
2989 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2990 cts->sync_period = 6; /* 40MHz */
2991 cts->sync_offset = 15;
2993 cts->valid = CCB_TRANS_SYNC_RATE_VALID
2994 | CCB_TRANS_SYNC_OFFSET_VALID
2995 | CCB_TRANS_BUS_WIDTH_VALID
2996 | CCB_TRANS_DISC_VALID
2997 | CCB_TRANS_TQ_VALID;
2998 ccb->ccb_h.status = CAM_REQ_CMP;
3000 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3006 case XPT_CALC_GEOMETRY:
3008 struct ccb_calc_geometry *ccg;
3010 u_int32_t secs_per_cylinder;
3013 size_mb = ccg->volume_size
3014 / ((1024L * 1024L) / ccg->block_size);
3016 if (size_mb > 4096) {
3018 ccg->secs_per_track = 63;
3019 } else if (size_mb > 2048) {
3021 ccg->secs_per_track = 63;
3022 } else if (size_mb > 1024) {
3024 ccg->secs_per_track = 63;
3027 ccg->secs_per_track = 32;
3029 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
3030 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
3031 ccb->ccb_h.status = CAM_REQ_CMP;
3036 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
3037 ASR_resetBus (sc, cam_sim_bus(sim));
3038 ccb->ccb_h.status = CAM_REQ_CMP;
3042 case XPT_TERM_IO: /* Terminate the I/O process */
3044 ccb->ccb_h.status = CAM_REQ_INVALID;
3048 case XPT_PATH_INQ: /* Path routing inquiry */
3050 struct ccb_pathinq *cpi = &(ccb->cpi);
3052 cpi->version_num = 1; /* XXX??? */
3053 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
3054 cpi->target_sprt = 0;
3055 /* Not necessary to reset bus, done by HDM initialization */
3056 cpi->hba_misc = PIM_NOBUSRESET;
3057 cpi->hba_eng_cnt = 0;
3058 cpi->max_target = sc->ha_MaxId;
3059 cpi->max_lun = sc->ha_MaxLun;
3060 cpi->initiator_id = sc->ha_adapter_target[cam_sim_bus(sim)];
3061 cpi->bus_id = cam_sim_bus(sim);
3062 cpi->base_transfer_speed = 3300;
3063 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
3064 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
3065 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
3066 cpi->unit_number = cam_sim_unit(sim);
3067 cpi->ccb_h.status = CAM_REQ_CMP;
3072 ccb->ccb_h.status = CAM_REQ_INVALID;
3080 * Handle processing of current CCB as pointed to by the Status.
3084 IN Asr_softc_t * sc)
3089 sc->ha_Virt->Status & Mask_InterruptsDisabled;
3091 union asr_ccb * ccb;
3093 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3095 if (((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)
3096 && ((ReplyOffset = sc->ha_Virt->FromFIFO) == EMPTY_QUEUE)) {
3099 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)(ReplyOffset
3100 - sc->ha_Msgs_Phys + (char *)(sc->ha_Msgs));
3102 * We do not need any (optional byteswapping) method access to
3103 * the Initiator context field.
3105 ccb = (union asr_ccb *)(long)
3106 I2O_MESSAGE_FRAME_getInitiatorContext64(
3107 &(Reply->StdReplyFrame.StdMessageFrame));
3108 if (I2O_MESSAGE_FRAME_getMsgFlags(
3109 &(Reply->StdReplyFrame.StdMessageFrame))
3110 & I2O_MESSAGE_FLAGS_FAIL) {
3111 defAlignLong(I2O_UTIL_NOP_MESSAGE,Message);
3112 PI2O_UTIL_NOP_MESSAGE Message_Ptr;
3115 MessageOffset = (u_long)
3116 I2O_FAILURE_REPLY_MESSAGE_FRAME_getPreservedMFA(
3117 (PI2O_FAILURE_REPLY_MESSAGE_FRAME)Reply);
3119 * Get the Original Message Frame's address, and get
3120 * it's Transaction Context into our space. (Currently
3121 * unused at original authorship, but better to be
3122 * safe than sorry). Straight copy means that we
3123 * need not concern ourselves with the (optional
3124 * byteswapping) method access.
3126 Reply->StdReplyFrame.TransactionContext
3127 = ((PI2O_SINGLE_REPLY_MESSAGE_FRAME)
3128 (sc->ha_Fvirt + MessageOffset))->TransactionContext;
3130 * For 64 bit machines, we need to reconstruct the
3133 ccb = (union asr_ccb *)(long)
3134 I2O_MESSAGE_FRAME_getInitiatorContext64(
3135 &(Reply->StdReplyFrame.StdMessageFrame));
3137 * Unique error code for command failure.
3139 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3140 &(Reply->StdReplyFrame), (u_int16_t)-2);
3142 * Modify the message frame to contain a NOP and
3143 * re-issue it to the controller.
3145 Message_Ptr = (PI2O_UTIL_NOP_MESSAGE)ASR_fillMessage(
3146 Message, sizeof(I2O_UTIL_NOP_MESSAGE));
3147 # if (I2O_UTIL_NOP != 0)
3148 I2O_MESSAGE_FRAME_setFunction (
3149 &(Message_Ptr->StdMessageFrame),
3153 * Copy the packet out to the Original Message
3155 bcopy ((caddr_t)Message_Ptr,
3156 sc->ha_Fvirt + MessageOffset,
3157 sizeof(I2O_UTIL_NOP_MESSAGE));
3161 sc->ha_Virt->ToFIFO = MessageOffset;
3165 * Asynchronous command with no return requirements,
3166 * and a generic handler for immunity against odd error
3167 * returns from the adapter.
3169 if (ccb == (union asr_ccb *)NULL) {
3171 * Return Reply so that it can be used for the
3174 sc->ha_Virt->FromFIFO = ReplyOffset;
3178 /* Welease Wadjah! (and stop timeouts) */
3179 ASR_ccbRemove (sc, ccb);
3182 I2O_SINGLE_REPLY_MESSAGE_FRAME_getDetailedStatusCode(
3183 &(Reply->StdReplyFrame))) {
3185 case I2O_SCSI_DSC_SUCCESS:
3186 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3187 ccb->ccb_h.status |= CAM_REQ_CMP;
3190 case I2O_SCSI_DSC_CHECK_CONDITION:
3191 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3192 ccb->ccb_h.status |= CAM_REQ_CMP|CAM_AUTOSNS_VALID;
3195 case I2O_SCSI_DSC_BUSY:
3197 case I2O_SCSI_HBA_DSC_ADAPTER_BUSY:
3199 case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET:
3201 case I2O_SCSI_HBA_DSC_BUS_BUSY:
3202 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3203 ccb->ccb_h.status |= CAM_SCSI_BUSY;
3206 case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT:
3207 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3208 ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
3211 case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT:
3213 case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT:
3215 case I2O_SCSI_HBA_DSC_LUN_INVALID:
3217 case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID:
3218 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3219 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
3222 case I2O_SCSI_HBA_DSC_DATA_OVERRUN:
3224 case I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR:
3225 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3226 ccb->ccb_h.status |= CAM_DATA_RUN_ERR;
3230 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
3231 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
3234 if ((ccb->csio.resid = ccb->csio.dxfer_len) != 0) {
3236 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getTransferCount(
3240 /* Sense data in reply packet */
3241 if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
3242 u_int16_t size = I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_getAutoSenseTransferCount(Reply);
3245 if (size > sizeof(ccb->csio.sense_data)) {
3246 size = sizeof(ccb->csio.sense_data);
3248 if (size > I2O_SCSI_SENSE_DATA_SZ) {
3249 size = I2O_SCSI_SENSE_DATA_SZ;
3251 if ((ccb->csio.sense_len)
3252 && (size > ccb->csio.sense_len)) {
3253 size = ccb->csio.sense_len;
3255 bcopy ((caddr_t)Reply->SenseData,
3256 (caddr_t)&(ccb->csio.sense_data), size);
3261 * Return Reply so that it can be used for the next command
3262 * since we have no more need for it now
3264 sc->ha_Virt->FromFIFO = ReplyOffset;
3266 if (ccb->ccb_h.path) {
3267 xpt_done ((union ccb *)ccb);
3269 wakeup ((caddr_t)ccb);
3275 #undef QueueSize /* Grrrr */
3276 #undef SG_Size /* Grrrr */
3279 * Meant to be included at the bottom of asr.c !!!
3283 * Included here as hard coded. Done because other necessary include
3284 * files utilize C++ comment structures which make them a nuisance to
3285 * included here just to pick up these three typedefs.
3287 typedef U32 DPT_TAG_T;
3288 typedef U32 DPT_MSG_T;
3289 typedef U32 DPT_RTN_T;
3291 #undef SCSI_RESET /* Conflicts with "scsi/scsiconf.h" defintion */
3292 #include "osd_unix.h"
3294 #define asr_unit(dev) minor(dev)
3296 STATIC INLINE Asr_softc_t *
3300 int unit = asr_unit(dev);
3301 OUT Asr_softc_t * sc = Asr_softc;
3303 while (sc && sc->ha_sim[0] && (cam_sim_unit(sc->ha_sim[0]) != unit)) {
3309 STATIC u_int8_t ASR_ctlr_held;
3310 #if (!defined(UNREFERENCED_PARAMETER))
3311 # define UNREFERENCED_PARAMETER(x) (void)(x)
3323 UNREFERENCED_PARAMETER(flags);
3324 UNREFERENCED_PARAMETER(ifmt);
3326 if (ASR_get_sc (dev) == (Asr_softc_t *)NULL) {
3329 KKASSERT(td->td_proc);
3331 if (ASR_ctlr_held) {
3333 } else if ((error = suser_cred(td->td_proc->p_ucred, 0)) == 0) {
3347 UNREFERENCED_PARAMETER(dev);
3348 UNREFERENCED_PARAMETER(flags);
3349 UNREFERENCED_PARAMETER(ifmt);
3350 UNREFERENCED_PARAMETER(td);
3357 /*-------------------------------------------------------------------------*/
3358 /* Function ASR_queue_i */
3359 /*-------------------------------------------------------------------------*/
3360 /* The Parameters Passed To This Function Are : */
3361 /* Asr_softc_t * : HBA miniport driver's adapter data storage. */
3362 /* PI2O_MESSAGE_FRAME : Msg Structure Pointer For This Command */
3363 /* I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME following the Msg Structure */
3365 /* This Function Will Take The User Request Packet And Convert It To An */
3366 /* I2O MSG And Send It Off To The Adapter. */
3368 /* Return : 0 For OK, Error Code Otherwise */
3369 /*-------------------------------------------------------------------------*/
3372 IN Asr_softc_t * sc,
3373 INOUT PI2O_MESSAGE_FRAME Packet)
3375 union asr_ccb * ccb;
3376 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply;
3377 PI2O_MESSAGE_FRAME Message_Ptr;
3378 PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME Reply_Ptr;
3379 int MessageSizeInBytes;
3380 int ReplySizeInBytes;
3383 /* Scatter Gather buffer list */
3384 struct ioctlSgList_S {
3385 SLIST_ENTRY(ioctlSgList_S) link;
3387 I2O_FLAGS_COUNT FlagsCount;
3388 char KernelSpace[sizeof(long)];
3390 /* Generates a `first' entry */
3391 SLIST_HEAD(ioctlSgListHead_S, ioctlSgList_S) sgList;
3393 if (ASR_getBlinkLedCode(sc)) {
3394 debug_usr_cmd_printf ("Adapter currently in BlinkLed %x\n",
3395 ASR_getBlinkLedCode(sc));
3398 /* Copy in the message into a local allocation */
3399 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (
3400 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
3401 == (PI2O_MESSAGE_FRAME)NULL) {
3402 debug_usr_cmd_printf (
3403 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
3406 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
3407 sizeof(I2O_MESSAGE_FRAME))) != 0) {
3408 free (Message_Ptr, M_TEMP);
3409 debug_usr_cmd_printf ("Can't copy in packet errno=%d\n", error);
3412 /* Acquire information to determine type of packet */
3413 MessageSizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)<<2);
3414 /* The offset of the reply information within the user packet */
3415 Reply = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)((char *)Packet
3416 + MessageSizeInBytes);
3418 /* Check if the message is a synchronous initialization command */
3419 s = I2O_MESSAGE_FRAME_getFunction(Message_Ptr);
3420 free (Message_Ptr, M_TEMP);
3423 case I2O_EXEC_IOP_RESET:
3426 status = ASR_resetIOP(sc->ha_Virt, sc->ha_Fvirt);
3427 ReplySizeInBytes = sizeof(status);
3428 debug_usr_cmd_printf ("resetIOP done\n");
3429 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3433 case I2O_EXEC_STATUS_GET:
3434 { I2O_EXEC_STATUS_GET_REPLY status;
3436 if (ASR_getStatus (sc->ha_Virt, sc->ha_Fvirt, &status)
3437 == (PI2O_EXEC_STATUS_GET_REPLY)NULL) {
3438 debug_usr_cmd_printf ("getStatus failed\n");
3441 ReplySizeInBytes = sizeof(status);
3442 debug_usr_cmd_printf ("getStatus done\n");
3443 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3447 case I2O_EXEC_OUTBOUND_INIT:
3450 status = ASR_initOutBound(sc);
3451 ReplySizeInBytes = sizeof(status);
3452 debug_usr_cmd_printf ("intOutBound done\n");
3453 return (copyout ((caddr_t)&status, (caddr_t)Reply,
3458 /* Determine if the message size is valid */
3459 if ((MessageSizeInBytes < sizeof(I2O_MESSAGE_FRAME))
3460 || (MAX_INBOUND_SIZE < MessageSizeInBytes)) {
3461 debug_usr_cmd_printf ("Packet size %d incorrect\n",
3462 MessageSizeInBytes);
3466 if ((Message_Ptr = (PI2O_MESSAGE_FRAME)malloc (MessageSizeInBytes,
3467 M_TEMP, M_WAITOK)) == (PI2O_MESSAGE_FRAME)NULL) {
3468 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
3469 MessageSizeInBytes);
3472 if ((error = copyin ((caddr_t)Packet, (caddr_t)Message_Ptr,
3473 MessageSizeInBytes)) != 0) {
3474 free (Message_Ptr, M_TEMP);
3475 debug_usr_cmd_printf ("Can't copy in packet[%d] errno=%d\n",
3476 MessageSizeInBytes, error);
3480 /* Check the size of the reply frame, and start constructing */
3482 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc (
3483 sizeof(I2O_MESSAGE_FRAME), M_TEMP, M_WAITOK))
3484 == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
3485 free (Message_Ptr, M_TEMP);
3486 debug_usr_cmd_printf (
3487 "Failed to acquire I2O_MESSAGE_FRAME memory\n");
3490 if ((error = copyin ((caddr_t)Reply, (caddr_t)Reply_Ptr,
3491 sizeof(I2O_MESSAGE_FRAME))) != 0) {
3492 free (Reply_Ptr, M_TEMP);
3493 free (Message_Ptr, M_TEMP);
3494 debug_usr_cmd_printf (
3495 "Failed to copy in reply frame, errno=%d\n",
3499 ReplySizeInBytes = (I2O_MESSAGE_FRAME_getMessageSize(
3500 &(Reply_Ptr->StdReplyFrame.StdMessageFrame)) << 2);
3501 free (Reply_Ptr, M_TEMP);
3502 if (ReplySizeInBytes < sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME)) {
3503 free (Message_Ptr, M_TEMP);
3504 debug_usr_cmd_printf (
3505 "Failed to copy in reply frame[%d], errno=%d\n",
3506 ReplySizeInBytes, error);
3510 if ((Reply_Ptr = (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)malloc (
3511 ((ReplySizeInBytes > sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME))
3513 : sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)),
3514 M_TEMP, M_WAITOK)) == (PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)NULL) {
3515 free (Message_Ptr, M_TEMP);
3516 debug_usr_cmd_printf ("Failed to acquire frame[%d] memory\n",
3520 (void)ASR_fillMessage ((char *)Reply_Ptr, ReplySizeInBytes);
3521 Reply_Ptr->StdReplyFrame.StdMessageFrame.InitiatorContext
3522 = Message_Ptr->InitiatorContext;
3523 Reply_Ptr->StdReplyFrame.TransactionContext
3524 = ((PI2O_PRIVATE_MESSAGE_FRAME)Message_Ptr)->TransactionContext;
3525 I2O_MESSAGE_FRAME_setMsgFlags(
3526 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
3527 I2O_MESSAGE_FRAME_getMsgFlags(
3528 &(Reply_Ptr->StdReplyFrame.StdMessageFrame))
3529 | I2O_MESSAGE_FLAGS_REPLY);
3531 /* Check if the message is a special case command */
3532 switch (I2O_MESSAGE_FRAME_getFunction(Message_Ptr)) {
3533 case I2O_EXEC_SYS_TAB_SET: /* Special Case of empty Scatter Gather */
3534 if (MessageSizeInBytes == ((I2O_MESSAGE_FRAME_getVersionOffset(
3535 Message_Ptr) & 0xF0) >> 2)) {
3536 free (Message_Ptr, M_TEMP);
3537 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3538 &(Reply_Ptr->StdReplyFrame),
3539 (ASR_setSysTab(sc) != CAM_REQ_CMP));
3540 I2O_MESSAGE_FRAME_setMessageSize(
3541 &(Reply_Ptr->StdReplyFrame.StdMessageFrame),
3542 sizeof(I2O_SINGLE_REPLY_MESSAGE_FRAME));
3543 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
3545 free (Reply_Ptr, M_TEMP);
3550 /* Deal in the general case */
3551 /* First allocate and optionally copy in each scatter gather element */
3552 SLIST_INIT(&sgList);
3553 if ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0) != 0) {
3554 PI2O_SGE_SIMPLE_ELEMENT sg;
3557 * since this code is reused in several systems, code
3558 * efficiency is greater by using a shift operation rather
3559 * than a divide by sizeof(u_int32_t).
3561 sg = (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
3562 + ((I2O_MESSAGE_FRAME_getVersionOffset(Message_Ptr) & 0xF0)
3564 while (sg < (PI2O_SGE_SIMPLE_ELEMENT)(((caddr_t)Message_Ptr)
3565 + MessageSizeInBytes)) {
3569 if ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
3570 & I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT) == 0) {
3574 len = I2O_FLAGS_COUNT_getCount(&(sg->FlagsCount));
3575 debug_usr_cmd_printf ("SG[%d] = %x[%d]\n",
3576 sg - (PI2O_SGE_SIMPLE_ELEMENT)((char *)Message_Ptr
3577 + ((I2O_MESSAGE_FRAME_getVersionOffset(
3578 Message_Ptr) & 0xF0) >> 2)),
3579 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg), len);
3581 if ((elm = (struct ioctlSgList_S *)malloc (
3582 sizeof(*elm) - sizeof(elm->KernelSpace) + len,
3584 == (struct ioctlSgList_S *)NULL) {
3585 debug_usr_cmd_printf (
3586 "Failed to allocate SG[%d]\n", len);
3590 SLIST_INSERT_HEAD(&sgList, elm, link);
3591 elm->FlagsCount = sg->FlagsCount;
3592 elm->UserSpace = (caddr_t)
3593 (I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg));
3594 v = elm->KernelSpace;
3595 /* Copy in outgoing data (DIR bit could be invalid) */
3596 if ((error = copyin (elm->UserSpace, (caddr_t)v, len))
3601 * If the buffer is not contiguous, lets
3602 * break up the scatter/gather entries.
3605 && (sg < (PI2O_SGE_SIMPLE_ELEMENT)
3606 (((caddr_t)Message_Ptr) + MAX_INBOUND_SIZE))) {
3607 int next, base, span;
3610 next = base = KVTOPHYS(v);
3611 I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg,
3614 /* How far can we go physically contiguously */
3615 while ((len > 0) && (base == next)) {
3618 next = trunc_page(base) + PAGE_SIZE;
3629 /* Construct the Flags */
3630 I2O_FLAGS_COUNT_setCount(&(sg->FlagsCount),
3633 int flags = I2O_FLAGS_COUNT_getFlags(
3634 &(elm->FlagsCount));
3635 /* Any remaining length? */
3638 ~(I2O_SGL_FLAGS_END_OF_BUFFER
3639 | I2O_SGL_FLAGS_LAST_ELEMENT);
3641 I2O_FLAGS_COUNT_setFlags(
3642 &(sg->FlagsCount), flags);
3645 debug_usr_cmd_printf ("sg[%d] = %x[%d]\n",
3646 sg - (PI2O_SGE_SIMPLE_ELEMENT)
3647 ((char *)Message_Ptr
3648 + ((I2O_MESSAGE_FRAME_getVersionOffset(
3649 Message_Ptr) & 0xF0) >> 2)),
3650 I2O_SGE_SIMPLE_ELEMENT_getPhysicalAddress(sg),
3657 * Incrementing requires resizing of the
3658 * packet, and moving up the existing SG
3662 MessageSizeInBytes += sizeof(*sg);
3663 I2O_MESSAGE_FRAME_setMessageSize(Message_Ptr,
3664 I2O_MESSAGE_FRAME_getMessageSize(Message_Ptr)
3665 + (sizeof(*sg) / sizeof(U32)));
3667 PI2O_MESSAGE_FRAME NewMessage_Ptr;
3670 = (PI2O_MESSAGE_FRAME)
3671 malloc (MessageSizeInBytes,
3673 == (PI2O_MESSAGE_FRAME)NULL) {
3674 debug_usr_cmd_printf (
3675 "Failed to acquire frame[%d] memory\n",
3676 MessageSizeInBytes);
3680 span = ((caddr_t)sg)
3681 - (caddr_t)Message_Ptr;
3682 bcopy ((caddr_t)Message_Ptr,
3683 (caddr_t)NewMessage_Ptr, span);
3684 bcopy ((caddr_t)(sg-1),
3685 ((caddr_t)NewMessage_Ptr) + span,
3686 MessageSizeInBytes - span);
3687 free (Message_Ptr, M_TEMP);
3688 sg = (PI2O_SGE_SIMPLE_ELEMENT)
3689 (((caddr_t)NewMessage_Ptr) + span);
3690 Message_Ptr = NewMessage_Ptr;
3694 || ((I2O_FLAGS_COUNT_getFlags(&(sg->FlagsCount))
3695 & I2O_SGL_FLAGS_LAST_ELEMENT) != 0)) {
3701 while ((elm = SLIST_FIRST(&sgList))
3702 != (struct ioctlSgList_S *)NULL) {
3703 SLIST_REMOVE_HEAD(&sgList, link);
3706 free (Reply_Ptr, M_TEMP);
3707 free (Message_Ptr, M_TEMP);
3712 debug_usr_cmd_printf ("Inbound: ");
3713 debug_usr_cmd_dump_message(Message_Ptr);
3715 /* Send the command */
3716 if ((ccb = asr_alloc_ccb (sc)) == (union asr_ccb *)NULL) {
3717 /* Free up in-kernel buffers */
3718 while ((elm = SLIST_FIRST(&sgList))
3719 != (struct ioctlSgList_S *)NULL) {
3720 SLIST_REMOVE_HEAD(&sgList, link);
3723 free (Reply_Ptr, M_TEMP);
3724 free (Message_Ptr, M_TEMP);
3729 * We do not need any (optional byteswapping) method access to
3730 * the Initiator context field.
3732 I2O_MESSAGE_FRAME_setInitiatorContext64(
3733 (PI2O_MESSAGE_FRAME)Message_Ptr, (long)ccb);
3735 (void)ASR_queue (sc, (PI2O_MESSAGE_FRAME)Message_Ptr);
3737 free (Message_Ptr, M_TEMP);
3740 * Wait for the board to report a finished instruction.
3743 while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
3744 if (ASR_getBlinkLedCode(sc)) {
3746 printf ("asr%d: Blink LED 0x%x resetting adapter\n",
3747 cam_sim_unit(xpt_path_sim(ccb->ccb_h.path)),
3748 ASR_getBlinkLedCode(sc));
3749 if (ASR_reset (sc) == ENXIO) {
3750 /* Command Cleanup */
3751 ASR_ccbRemove(sc, ccb);
3754 /* Free up in-kernel buffers */
3755 while ((elm = SLIST_FIRST(&sgList))
3756 != (struct ioctlSgList_S *)NULL) {
3757 SLIST_REMOVE_HEAD(&sgList, link);
3760 free (Reply_Ptr, M_TEMP);
3764 /* Check every second for BlinkLed */
3765 tsleep((caddr_t)ccb, 0, "asr", hz);
3769 debug_usr_cmd_printf ("Outbound: ");
3770 debug_usr_cmd_dump_message(Reply_Ptr);
3772 I2O_SINGLE_REPLY_MESSAGE_FRAME_setDetailedStatusCode(
3773 &(Reply_Ptr->StdReplyFrame),
3774 (ccb->ccb_h.status != CAM_REQ_CMP));
3776 if (ReplySizeInBytes >= (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3777 - I2O_SCSI_SENSE_DATA_SZ - sizeof(U32))) {
3778 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setTransferCount(Reply_Ptr,
3779 ccb->csio.dxfer_len - ccb->csio.resid);
3781 if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) && (ReplySizeInBytes
3782 > (sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3783 - I2O_SCSI_SENSE_DATA_SZ))) {
3784 int size = ReplySizeInBytes
3785 - sizeof(I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME)
3786 - I2O_SCSI_SENSE_DATA_SZ;
3788 if (size > sizeof(ccb->csio.sense_data)) {
3789 size = sizeof(ccb->csio.sense_data);
3791 bcopy ((caddr_t)&(ccb->csio.sense_data), (caddr_t)Reply_Ptr->SenseData,
3793 I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME_setAutoSenseTransferCount(
3797 /* Free up in-kernel buffers */
3798 while ((elm = SLIST_FIRST(&sgList)) != (struct ioctlSgList_S *)NULL) {
3799 /* Copy out as necessary */
3801 /* DIR bit considered `valid', error due to ignorance works */
3802 && ((I2O_FLAGS_COUNT_getFlags(&(elm->FlagsCount))
3803 & I2O_SGL_FLAGS_DIR) == 0)) {
3804 error = copyout ((caddr_t)(elm->KernelSpace),
3806 I2O_FLAGS_COUNT_getCount(&(elm->FlagsCount)));
3808 SLIST_REMOVE_HEAD(&sgList, link);
3812 /* Copy reply frame to user space */
3813 error = copyout ((caddr_t)Reply_Ptr, (caddr_t)Reply,
3816 free (Reply_Ptr, M_TEMP);
3822 /*----------------------------------------------------------------------*/
3823 /* Function asr_ioctl */
3824 /*----------------------------------------------------------------------*/
3825 /* The parameters passed to this function are : */
3826 /* dev : Device number. */
3827 /* cmd : Ioctl Command */
3828 /* data : User Argument Passed In. */
3829 /* flag : Mode Parameter */
3830 /* proc : Process Parameter */
3832 /* This function is the user interface into this adapter driver */
3834 /* Return : zero if OK, error code if not */
3835 /*----------------------------------------------------------------------*/
3847 Asr_softc_t * sc = ASR_get_sc (dev);
3848 UNREFERENCED_PARAMETER(flag);
3849 UNREFERENCED_PARAMETER(td);
3851 if (sc != (Asr_softc_t *)NULL)
3855 # if (dsDescription_size != 50)
3856 case DPT_SIGNATURE + ((50 - dsDescription_size) << 16):
3858 if (cmd & 0xFFFF0000) {
3859 (void)bcopy ((caddr_t)(&ASR_sig), data,
3863 /* Traditional version of the ioctl interface */
3864 case DPT_SIGNATURE & 0x0000FFFF:
3865 return (copyout ((caddr_t)(&ASR_sig), *((caddr_t *)data),
3866 sizeof(dpt_sig_S)));
3868 /* Traditional version of the ioctl interface */
3869 case DPT_CTRLINFO & 0x0000FFFF:
3870 case DPT_CTRLINFO: {
3873 u_int16_t drvrHBAnum;
3875 u_int16_t blinkState;
3877 u_int8_t pciDeviceNum;
3879 u_int16_t Interrupt;
3880 u_int32_t reserved1;
3881 u_int32_t reserved2;
3882 u_int32_t reserved3;
3885 bzero (&CtlrInfo, sizeof(CtlrInfo));
3886 CtlrInfo.length = sizeof(CtlrInfo) - sizeof(u_int16_t);
3887 CtlrInfo.drvrHBAnum = asr_unit(dev);
3888 CtlrInfo.baseAddr = (u_long)sc->ha_Base;
3889 i = ASR_getBlinkLedCode (sc);
3893 CtlrInfo.blinkState = i;
3894 CtlrInfo.pciBusNum = sc->ha_pciBusNum;
3895 CtlrInfo.pciDeviceNum = sc->ha_pciDeviceNum;
3896 #define FLG_OSD_PCI_VALID 0x0001
3897 #define FLG_OSD_DMA 0x0002
3898 #define FLG_OSD_I2O 0x0004
3899 CtlrInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
3900 CtlrInfo.Interrupt = sc->ha_irq;
3901 if (cmd & 0xFFFF0000) {
3902 bcopy (&CtlrInfo, data, sizeof(CtlrInfo));
3904 error = copyout (&CtlrInfo, *(caddr_t *)data, sizeof(CtlrInfo));
3908 /* Traditional version of the ioctl interface */
3909 case DPT_SYSINFO & 0x0000FFFF:
3913 /* Kernel Specific ptok `hack' */
3914 # define ptok(a) ((char *)(a) + KERNBASE)
3916 bzero (&Info, sizeof(Info));
3918 /* Appears I am the only person in the Kernel doing this */
3926 Info.drive0CMOS = j;
3933 Info.drive1CMOS = j;
3935 Info.numDrives = *((char *)ptok(0x475));
3937 Info.processorFamily = ASR_sig.dsProcessorFamily;
3939 case CPU_386SX: case CPU_386:
3940 Info.processorType = PROC_386; break;
3941 case CPU_486SX: case CPU_486:
3942 Info.processorType = PROC_486; break;
3944 Info.processorType = PROC_PENTIUM; break;
3946 Info.processorType = PROC_SEXIUM; break;
3948 Info.osType = OS_BSDI_UNIX;
3949 Info.osMajorVersion = osrelease[0] - '0';
3950 Info.osMinorVersion = osrelease[2] - '0';
3951 /* Info.osRevision = 0; */
3952 /* Info.osSubRevision = 0; */
3953 Info.busType = SI_PCI_BUS;
3954 Info.flags = SI_CMOS_Valid | SI_NumDrivesValid
3955 | SI_OSversionValid | SI_BusTypeValid | SI_NO_SmartROM;
3957 /* Go Out And Look For I2O SmartROM */
3958 for(j = 0xC8000; j < 0xE0000; j += 2048) {
3962 if (*((unsigned short *)cp) != 0xAA55) {
3965 j += (cp[2] * 512) - 2048;
3966 if ((*((u_long *)(cp + 6))
3967 != ('S' + (' ' * 256) + (' ' * 65536L)))
3968 || (*((u_long *)(cp + 10))
3969 != ('I' + ('2' * 256) + ('0' * 65536L)))) {
3973 for (k = 0; k < 64; ++k) {
3974 if (*((unsigned short *)cp)
3975 == (' ' + ('v' * 256))) {
3980 Info.smartROMMajorVersion
3981 = *((unsigned char *)(cp += 4)) - '0';
3982 Info.smartROMMinorVersion
3983 = *((unsigned char *)(cp += 2));
3984 Info.smartROMRevision
3985 = *((unsigned char *)(++cp));
3986 Info.flags |= SI_SmartROMverValid;
3987 Info.flags &= ~SI_NO_SmartROM;
3991 /* Get The Conventional Memory Size From CMOS */
3997 Info.conventionalMemSize = j;
3999 /* Get The Extended Memory Found At Power On From CMOS */
4005 Info.extendedMemSize = j;
4006 Info.flags |= SI_MemorySizeValid;
4008 # if (defined(THIS_IS_BROKEN))
4009 /* If There Is 1 or 2 Drives Found, Set Up Drive Parameters */
4010 if (Info.numDrives > 0) {
4012 * Get The Pointer From Int 41 For The First
4015 j = ((unsigned)(*((unsigned short *)ptok(0x104+2))) << 4)
4016 + (unsigned)(*((unsigned short *)ptok(0x104+0)));
4018 * It appears that SmartROM's Int41/Int46 pointers
4019 * use memory that gets stepped on by the kernel
4020 * loading. We no longer have access to this
4021 * geometry information but try anyways (!?)
4023 Info.drives[0].cylinders = *((unsigned char *)ptok(j));
4025 Info.drives[0].cylinders += ((int)*((unsigned char *)
4028 Info.drives[0].heads = *((unsigned char *)ptok(j));
4030 Info.drives[0].sectors = *((unsigned char *)ptok(j));
4031 Info.flags |= SI_DriveParamsValid;
4032 if ((Info.drives[0].cylinders == 0)
4033 || (Info.drives[0].heads == 0)
4034 || (Info.drives[0].sectors == 0)) {
4035 Info.flags &= ~SI_DriveParamsValid;
4037 if (Info.numDrives > 1) {
4039 * Get The Pointer From Int 46 For The
4040 * Second Drive Parameters
4042 j = ((unsigned)(*((unsigned short *)ptok(0x118+2))) << 4)
4043 + (unsigned)(*((unsigned short *)ptok(0x118+0)));
4044 Info.drives[1].cylinders = *((unsigned char *)
4047 Info.drives[1].cylinders += ((int)
4048 *((unsigned char *)ptok(j))) << 8;
4050 Info.drives[1].heads = *((unsigned char *)
4053 Info.drives[1].sectors = *((unsigned char *)
4055 if ((Info.drives[1].cylinders == 0)
4056 || (Info.drives[1].heads == 0)
4057 || (Info.drives[1].sectors == 0)) {
4058 Info.flags &= ~SI_DriveParamsValid;
4063 /* Copy Out The Info Structure To The User */
4064 if (cmd & 0xFFFF0000) {
4065 bcopy (&Info, data, sizeof(Info));
4067 error = copyout (&Info, *(caddr_t *)data, sizeof(Info));
4071 /* Get The BlinkLED State */
4073 i = ASR_getBlinkLedCode (sc);
4077 if (cmd & 0xFFFF0000) {
4078 bcopy ((caddr_t)(&i), data, sizeof(i));
4080 error = copyout (&i, *(caddr_t *)data, sizeof(i));
4084 /* Send an I2O command */
4086 return (ASR_queue_i (sc, *((PI2O_MESSAGE_FRAME *)data)));
4088 /* Reset and re-initialize the adapter */
4090 return (ASR_reset (sc));
4092 /* Rescan the LCT table and resynchronize the information */
4094 return (ASR_rescan (sc));