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