1285809Sscottl/*******************************************************************************
2285809Sscottl**
3285809Sscottl*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
4285809Sscottl *
5285809Sscottl*Redistribution and use in source and binary forms, with or without modification, are permitted provided
6285809Sscottl*that the following conditions are met:
7285809Sscottl*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8285809Sscottl*2. Redistributions in binary form must reproduce the above copyright notice,
9285809Sscottl*this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10285809Sscottl*
11285809Sscottl*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
12285809Sscottl*
13285809Sscottl*INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14285809Sscottl*ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
15285809Sscottl*SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16285809Sscottl*OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
17285809Sscottl*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
18285809Sscottl*THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
19285809Sscottl**
20285809Sscottl*******************************************************************************/
21285809Sscottl
22285809Sscottl#include <sys/cdefs.h>
23285809Sscottl__FBSDID("$FreeBSD$");
24285809Sscottl#include <dev/pms/config.h>
25285809Sscottl
26285809Sscottl#define MAJOR_REVISION	    1
27285809Sscottl#define MINOR_REVISION	    3
28285809Sscottl#define BUILD_REVISION	    10800
29285809Sscottl
30285809Sscottl#include <sys/param.h>      // defines used in kernel.h
31285809Sscottl#include <sys/ioccom.h>
32285809Sscottl#include <sys/module.h>
33285809Sscottl#include <sys/systm.h>
34285809Sscottl#include <sys/errno.h>
35285809Sscottl#include <sys/kernel.h>     // types used in module initialization
36285809Sscottl#include <sys/conf.h>       // cdevsw struct
37285809Sscottl#include <sys/uio.h>        // uio struct
38285809Sscottl#include <sys/types.h>
39285809Sscottl#include <sys/malloc.h>
40285809Sscottl#include <sys/bus.h>        // structs, prototypes for pci bus stuff
41285809Sscottl#include <machine/bus.h>
42285809Sscottl#include <sys/rman.h>
43285809Sscottl#include <machine/resource.h>
44285809Sscottl#include <vm/vm.h>          // 1. for vtophys
45285809Sscottl#include <vm/pmap.h>        // 2. for vtophys
46285809Sscottl#include <machine/pmap.h>   // 3. for vtophys (yes, three)
47285809Sscottl#include <dev/pci/pcivar.h> // For pci_get macros
48285809Sscottl#include <dev/pci/pcireg.h>
49285809Sscottl#include <sys/endian.h>
50285809Sscottl#include <sys/lock.h>
51285809Sscottl#include <sys/mutex.h>
52285809Sscottl#include <sys/sema.h>
53285809Sscottl#include <sys/queue.h>
54285809Sscottl#include <sys/taskqueue.h>
55285809Sscottl#include <machine/atomic.h>
56285809Sscottl#include <sys/libkern.h>
57285809Sscottl#include <cam/cam.h>
58285809Sscottl#include <cam/cam_ccb.h>
59285809Sscottl#include <cam/cam_debug.h>
60285809Sscottl#include <cam/cam_periph.h> //
61285809Sscottl#include <cam/cam_sim.h>
62285809Sscottl#include <cam/cam_xpt_sim.h>
63285809Sscottl#include <cam/scsi/scsi_all.h>
64285809Sscottl#include <cam/scsi/scsi_message.h>
65285809Sscottl#include <sys/systm.h>
66285809Sscottl#include <sys/types.h>
67285809Sscottl#include <dev/pms/RefTisa/tisa/api/tiapi.h>
68285809Sscottl#include <dev/pms/freebsd/driver/ini/src/agtiapi.h>
69285809Sscottl#include <dev/pms/freebsd/driver/ini/src/agtiproto.h>
70285809Sscottl#include <dev/pms/RefTisa/tisa/api/ostiapi.h>
71285809Sscottl#include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
72285809Sscottl#include <dev/pms/freebsd/driver/common/lxencrypt.h>
73285809Sscottl
74285809SscottlMALLOC_DEFINE( M_PMC_MCCB, "CCB List", "CCB List for PMCS driver" );
75285809Sscottl
76285809SscottlMALLOC_DEFINE( M_PMC_MSTL, "STLock malloc",
77285809Sscottl               "allocated in agtiapi_attach as memory for lock use" );
78285809SscottlMALLOC_DEFINE( M_PMC_MDVT, "ag_device_t malloc",
79285809Sscottl               "allocated in agtiapi_attach as mem for ag_device_t pDevList" );
80285809SscottlMALLOC_DEFINE( M_PMC_MPRT, "ag_portal_data_t malloc",
81285809Sscottl               "allocated in agtiapi_attach as mem for *pPortalData" );
82285809SscottlMALLOC_DEFINE( M_PMC_MDEV, "tiDeviceHandle_t * malloc",
83285809Sscottl               "allocated in agtiapi_GetDevHandle as local mem for **agDev" );
84285809SscottlMALLOC_DEFINE( M_PMC_MFLG, "lDevFlags * malloc",
85285809Sscottl               "allocated in agtiapi_GetDevHandle as local mem for * flags" );
86285809Sscottl#ifdef LINUX_PERBI_SUPPORT
87285809SscottlMALLOC_DEFINE( M_PMC_MSLR, "ag_slr_map_t malloc",
88285809Sscottl               "mem allocated in agtiapi_attach for pSLRList" );
89285809SscottlMALLOC_DEFINE( M_PMC_MTGT, "ag_tgt_map_t malloc",
90285809Sscottl               "mem allocated in agtiapi_attach for pWWNList" );
91285809Sscottl#endif
92285809SscottlMALLOC_DEFINE(TEMP,"tempbuff","buffer for payload");
93285809SscottlMALLOC_DEFINE(TEMP2, "tempbuff", "buffer for agtiapi_getdevlist");
94285809SscottlSTATIC U32  agtiapi_intx_mode    = 0;
95285809SscottlSTATIC U08  ag_Perbi             = 0;
96285809SscottlSTATIC U32  agtiapi_polling_mode = 0;
97285809SscottlSTATIC U32  ag_card_good         = 0;   // * total card initialized
98285809SscottlSTATIC U32  ag_option_flag       = 0;   // * adjustable parameter flag
99285809SscottlSTATIC U32  agtiapi_1st_time     = 1;
100285809SscottlSTATIC U32  ag_timeout_secs      = 10;  //Made timeout equivalent to linux
101285809Sscottl
102285809SscottlU32         gTiDebugLevel        = 1;
103285809SscottlS32	        ag_encryption_enable = 0;
104285809Sscottlatomic_t    outstanding_encrypted_io_count;
105285809Sscottl
106285809Sscottl#define cache_line_size() CACHE_LINE_SIZE
107285809Sscottl
108285809Sscottl#define PMCoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
109285809Sscottl
110285809Sscottl#define CPU_TO_LE32(dst, src)                  \
111285809Sscottl    dst.lower = htole32(LOW_32_BITS(src)); \
112285809Sscottl    dst.upper = htole32(HIGH_32_BITS(src))
113285809Sscottl
114285809Sscottl#define CMND_TO_CHANNEL( ccb )     ( ccb->ccb_h.path_id )
115285809Sscottl#define CMND_TO_TARGET(  ccb )     ( ccb->ccb_h.target_id )
116285809Sscottl#define CMND_TO_LUN(     ccb )     ( ccb->ccb_h.target_lun )
117285809Sscottl
118285809SscottlSTATIC U08 agtiapi_AddrModes[AGTIAPI_MAX_CHANNEL_NUM + 1] =
119285809Sscottl      { AGTIAPI_PERIPHERAL };
120285809Sscottl
121285809Sscottl#ifdef LINUX_PERBI_SUPPORT
122285809Sscottl// Holding area for target-WWN mapping assignments on the boot line
123285809Sscottlstatic ag_mapping_t *agMappingList = NULL;  // modified by agtiapi_Setup()
124285809Sscottl#endif
125285809Sscottl
126285809Sscottl// * For Debugging Purpose
127285809Sscottl#ifdef AGTIAPI_DEBUG
128285809Sscottl#define AGTIAPI_WWN(name, len)   wwnprintk(name, len)
129285809Sscottl#else
130285809Sscottl#define AGTIAPI_WWN(name, len)
131285809Sscottl#endif
132285809Sscottl
133285809Sscottl
134285809Sscottl#define AGTIAPI_WWNPRINTK(name, len, format, a...)     \
135285809Sscottl          AGTIAPI_PRINTK(format "name ", a);           \
136285809Sscottl          AGTIAPI_WWN((unsigned char*)name, len);
137285809Sscottl
138285809Sscottl#define AGTIAPI_ERR_WWNPRINTK(name, len, format, a...) \
139285809Sscottl          printk(KERN_DEBUG format "name ", ## a);     \
140285809Sscottl          wwnprintk((unsigned char*)name, len);
141285809Sscottl#define AGTIAPI_CPY_DEV_INFO(root, dev, pDev)            \
142285809Sscottl          tiINIGetDeviceInfo(root, dev, &pDev->devInfo); \
143285809Sscottl          wwncpy(pDev);
144285809Sscottl
145285809Sscottl#ifdef AGTIAPI_LOCAL_LOCK
146285809Sscottl
147285809Sscottl#define AG_CARD_LOCAL_LOCK(lock)     ,(lock)
148285809Sscottl#define AG_SPIN_LOCK_IRQ(lock, flags)
149285809Sscottl#define AG_SPIN_UNLOCK_IRQ(lock, flags)
150285809Sscottl#define AG_SPIN_LOCK(lock)
151285809Sscottl#define AG_SPIN_UNLOCK(lock)
152285809Sscottl#define AG_GLOBAL_ARG(arg)
153285809Sscottl#define AG_PERF_SPINLOCK(lock)
154285809Sscottl#define AG_PERF_SPINLOCK_IRQ(lock, flags)
155285809Sscottl
156285809Sscottl
157285809Sscottl#define AG_LOCAL_LOCK(lock)     if (lock) \
158285809Sscottl                                         mtx_lock(lock)
159285809Sscottl#define AG_LOCAL_UNLOCK(lock)   if (lock) \
160285809Sscottl                                         mtx_unlock(lock)
161285809Sscottl#define AG_LOCAL_FLAGS(_flags)         unsigned long _flags = 0
162285809Sscottl#endif
163285809Sscottl
164285809Sscottl
165285809Sscottl#define AG_GET_DONE_PCCB(pccb, pmcsc)            \
166285809Sscottl  {                                              \
167285809Sscottl    AG_LOCAL_LOCK(&pmcsc->doneLock);             \
168285809Sscottl    pccb = pmcsc->ccbDoneHead;                   \
169285809Sscottl    if (pccb != NULL)                            \
170285809Sscottl    {                                            \
171285809Sscottl      pmcsc->ccbDoneHead = NULL;                 \
172285809Sscottl      pmcsc->ccbDoneTail = NULL;                 \
173285809Sscottl      AG_LOCAL_UNLOCK(&pmcsc->doneLock);         \
174285809Sscottl      agtiapi_Done(pmcsc, pccb);                 \
175285809Sscottl    }                                            \
176285809Sscottl    else                                         \
177285809Sscottl      AG_LOCAL_UNLOCK(&pmcsc->doneLock);         \
178285809Sscottl  }
179285809Sscottl
180285809Sscottl#define AG_GET_DONE_SMP_PCCB(pccb, pmcsc)	\
181285809Sscottl  {                                              \
182285809Sscottl    AG_LOCAL_LOCK(&pmcsc->doneSMPLock);          \
183285809Sscottl    pccb = pmcsc->smpDoneHead;                   \
184285809Sscottl    if (pccb != NULL)                            \
185285809Sscottl    {                                            \
186285809Sscottl      pmcsc->smpDoneHead = NULL;                 \
187285809Sscottl      pmcsc->smpDoneTail = NULL;                 \
188285809Sscottl      AG_LOCAL_UNLOCK(&pmcsc->doneSMPLock);      \
189285809Sscottl      agtiapi_SMPDone(pmcsc, pccb);              \
190285809Sscottl    }                                            \
191285809Sscottl    else                                         \
192285809Sscottl      AG_LOCAL_UNLOCK(&pmcsc->doneSMPLock);      \
193285809Sscottl  }
194285809Sscottl
195285809Sscottl#ifdef AGTIAPI_DUMP_IO_DEBUG
196285809Sscottl#define AG_IO_DUMPCCB(pccb)    agtiapi_DumpCCB(pccb)
197285809Sscottl#else
198285809Sscottl#define AG_IO_DUMPCCB(pccb)
199285809Sscottl#endif
200285809Sscottl
201285809Sscottl#define SCHED_DELAY_JIFFIES 4 /* in seconds */
202285809Sscottl
203285809Sscottl#ifdef HOTPLUG_SUPPORT
204285809Sscottl#define AG_HOTPLUG_LOCK_INIT(lock)   mxt_init(lock)
205285809Sscottl#define AG_LIST_LOCK(lock)           mtx_lock(lock)
206285809Sscottl#define AG_LIST_UNLOCK(lock)         mtx_unlock(lock)
207285809Sscottl#else
208285809Sscottl#define AG_HOTPLUG_LOCK_INIT(lock)
209285809Sscottl#define AG_LIST_LOCK(lock)
210285809Sscottl#define AG_LIST_UNLOCK(lock)
211285809Sscottl#endif
212285809Sscottl
213285809SscottlSTATIC void agtiapi_CheckIOTimeout(void *data);
214285809Sscottl
215285809Sscottl
216285809Sscottl
217285809Sscottlstatic ag_card_info_t agCardInfoList[ AGTIAPI_MAX_CARDS ]; // card info list
218285809Sscottlstatic void agtiapi_cam_action( struct cam_sim *, union ccb * );
219285809Sscottlstatic void agtiapi_cam_poll( struct cam_sim * );
220285809Sscottl
221285809Sscottl// Function prototypes
222285809Sscottlstatic d_open_t  agtiapi_open;
223285809Sscottlstatic d_close_t agtiapi_close;
224285809Sscottlstatic d_read_t  agtiapi_read;
225285809Sscottlstatic d_write_t agtiapi_write;
226285809Sscottlstatic d_ioctl_t agtiapi_CharIoctl;
227285809Sscottlstatic void agtiapi_async(void *callback_arg, u_int32_t code,
228285809Sscottl              struct cam_path *path, void *arg);
229285809Sscottlvoid agtiapi_adjust_queue_depth(struct cam_path *path, bit32 QueueDepth);
230285809Sscottl
231285809Sscottl// Character device entry points
232285809Sscottlstatic struct cdevsw agtiapi_cdevsw = {
233285809Sscottl  .d_version = D_VERSION,
234285809Sscottl  .d_open    = agtiapi_open,
235285809Sscottl  .d_close   = agtiapi_close,
236285809Sscottl  .d_read    = agtiapi_read,
237285809Sscottl  .d_write   = agtiapi_write,
238285809Sscottl  .d_ioctl   = agtiapi_CharIoctl,
239285809Sscottl  .d_name    = "pmspcv",
240285809Sscottl};
241285809Sscottl
242285809SscottlU32 maxTargets = 0;
243285809SscottlU32 ag_portal_count = 0;
244285809Sscottl
245285809Sscottl// In the cdevsw routines, we find our softc by using the si_drv1 member
246285809Sscottl// of struct cdev. We set this variable to point to our softc in our
247285809Sscottl// attach routine when we create the /dev entry.
248285809Sscottl
249285809Sscottlint agtiapi_open( struct cdev *dev, int oflags, int devtype, struct thread *td )
250285809Sscottl{
251285809Sscottl  struct agtiapi_softc *sc;
252285809Sscottl  /* Look up our softc. */
253285809Sscottl  sc = dev->si_drv1;
254285809Sscottl  AGTIAPI_PRINTK("agtiapi_open\n");
255285809Sscottl  AGTIAPI_PRINTK("Opened successfully. sc->my_dev %p\n", sc->my_dev);
256285809Sscottl  return( 0 );
257285809Sscottl}
258285809Sscottl
259285809Sscottlint agtiapi_close( struct cdev *dev, int fflag, int devtype, struct thread *td )
260285809Sscottl{
261285809Sscottl  struct agtiapi_softc *sc;
262285809Sscottl  // Look up our softc
263285809Sscottl  sc = dev->si_drv1;
264285809Sscottl  AGTIAPI_PRINTK("agtiapi_close\n");
265285809Sscottl  AGTIAPI_PRINTK("Closed. sc->my_dev %p\n", sc->my_dev);
266285809Sscottl  return( 0 );
267285809Sscottl}
268285809Sscottl
269285809Sscottlint agtiapi_read( struct cdev *dev, struct uio *uio, int ioflag )
270285809Sscottl{
271285809Sscottl  struct agtiapi_softc *sc;
272285809Sscottl  // Look up our softc
273285809Sscottl  sc = dev->si_drv1;
274285809Sscottl  AGTIAPI_PRINTK( "agtiapi_read\n" );
275285809Sscottl  AGTIAPI_PRINTK( "Asked to read %lu bytes. sc->my_dev %p\n",
276285809Sscottl                  uio->uio_resid, sc->my_dev );
277285809Sscottl  return( 0 );
278285809Sscottl}
279285809Sscottl
280285809Sscottlint agtiapi_write( struct cdev *dev, struct uio *uio, int ioflag )
281285809Sscottl{
282285809Sscottl  struct agtiapi_softc *sc;
283285809Sscottl  // Look up our softc
284285809Sscottl  sc = dev->si_drv1;
285285809Sscottl  AGTIAPI_PRINTK( "agtiapi_write\n" );
286285809Sscottl  AGTIAPI_PRINTK( "Asked to write %lu bytes. sc->my_dev %p\n",
287285809Sscottl                  uio->uio_resid, sc->my_dev );
288285809Sscottl  return( 0 );
289285809Sscottl}
290285809Sscottl
291285809Sscottlint agtiapi_getdevlist( struct agtiapi_softc *pCard,
292285809Sscottl                        tiIOCTLPayload_t *agIOCTLPayload )
293285809Sscottl{
294285809Sscottl  tdDeviceListPayload_t *pIoctlPayload =
295285809Sscottl    (tdDeviceListPayload_t *) agIOCTLPayload->FunctionSpecificArea;
296285809Sscottl  tdDeviceInfoIOCTL_t *pDeviceInfo = NULL;
297285809Sscottl  bit8		   *pDeviceInfoOrg;
298285809Sscottl  tdsaDeviceData_t *pDeviceData = NULL;
299285809Sscottl  tiDeviceHandle_t **devList = NULL;
300285809Sscottl  tiDeviceHandle_t **devHandleArray = NULL;
301285809Sscottl  tiDeviceHandle_t *pDeviceHandle = NULL;
302285809Sscottl  bit32 x, memNeeded1;
303285809Sscottl  bit32 count, total;
304285809Sscottl  bit32 MaxDeviceCount;
305285809Sscottl  bit32 ret_val=IOCTL_CALL_INVALID_CODE;
306285809Sscottl  ag_portal_data_t *pPortalData;
307285809Sscottl  bit8 *pDeviceHandleList = NULL;
308285809Sscottl  AGTIAPI_PRINTK( "agtiapi_getdevlist: Enter\n" );
309285809Sscottl
310285809Sscottl  pDeviceInfoOrg = pIoctlPayload -> pDeviceInfo;
311285809Sscottl  MaxDeviceCount = pCard->devDiscover;
312285809Sscottl  if (MaxDeviceCount > pIoctlPayload->deviceLength )
313285809Sscottl  {
314285809Sscottl    AGTIAPI_PRINTK( "agtiapi_getdevlist: MaxDeviceCount: %d > Requested device length: %d\n", MaxDeviceCount, pIoctlPayload->deviceLength );
315285809Sscottl    MaxDeviceCount = pIoctlPayload->deviceLength;
316285809Sscottl    ret_val = IOCTL_CALL_FAIL;
317285809Sscottl  }
318285809Sscottl  AGTIAPI_PRINTK( "agtiapi_getdevlist: MaxDeviceCount: %d > Requested device length: %d\n", MaxDeviceCount, pIoctlPayload->deviceLength );
319285809Sscottl  memNeeded1 = AG_ALIGNSIZE( MaxDeviceCount * sizeof(tiDeviceHandle_t *),
320285809Sscottl                             sizeof(void *) );
321285809Sscottl  AGTIAPI_PRINTK("agtiapi_getdevlist: portCount %d\n", pCard->portCount);
322285809Sscottl  devList = malloc(memNeeded1, TEMP2, M_WAITOK);
323285809Sscottl  if (devList == NULL)
324285809Sscottl  {
325285809Sscottl    AGTIAPI_PRINTK("agtiapi_getdevlist: failed to allocate memory\n");
326285809Sscottl    ret_val = IOCTL_CALL_FAIL;
327285809Sscottl    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
328285809Sscottl    return ret_val;
329285809Sscottl  }
330285809Sscottl  osti_memset(devList, 0,  memNeeded1);
331285809Sscottl  pPortalData = &pCard->pPortalData[0];
332285809Sscottl  pDeviceHandleList = (bit8*)devList;
333285809Sscottl  for (total = x = 0; x < pCard->portCount; x++, pPortalData++)
334285809Sscottl  {
335285809Sscottl    count = tiINIGetDeviceHandlesForWinIOCTL(&pCard->tiRoot,
336285809Sscottl                    &pPortalData->portalInfo.tiPortalContext,
337285809Sscottl		    ( tiDeviceHandle_t **)pDeviceHandleList ,MaxDeviceCount );
338285809Sscottl    if (count == DISCOVERY_IN_PROGRESS)
339285809Sscottl    {
340285809Sscottl      AGTIAPI_PRINTK( "agtiapi_getdevlist: DISCOVERY_IN_PROGRESS on "
341285809Sscottl                      "portal %d\n", x );
342285809Sscottl      free(devList, TEMP2);
343285809Sscottl      ret_val = IOCTL_CALL_FAIL;
344285809Sscottl      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
345285809Sscottl      return ret_val;
346285809Sscottl    }
347285809Sscottl    total += count;
348285809Sscottl    pDeviceHandleList+= count*sizeof(tiDeviceHandle_t *);
349285809Sscottl    MaxDeviceCount-= count;
350285809Sscottl  }
351285809Sscottl  if (total > pIoctlPayload->deviceLength)
352285809Sscottl  {
353285809Sscottl    total = pIoctlPayload->deviceLength;
354285809Sscottl  }
355285809Sscottl  // dump device information from device handle list
356285809Sscottl  count = 0;
357285809Sscottl
358285809Sscottl  devHandleArray = devList;
359285809Sscottl  for (x = 0; x < pCard->devDiscover; x++)
360285809Sscottl  {
361285809Sscottl     pDeviceHandle = (tiDeviceHandle_t*)devHandleArray[x];
362285809Sscottl    if (devList[x] != agNULL)
363285809Sscottl    {
364285809Sscottl      pDeviceData = devList [x]->tdData;
365285809Sscottl
366285809Sscottl	pDeviceInfo = (tdDeviceInfoIOCTL_t*)(pDeviceInfoOrg + sizeof(tdDeviceInfoIOCTL_t) * count);
367285809Sscottl      if (pDeviceData != agNULL && pDeviceInfo != agNULL)
368285809Sscottl      {
369285809Sscottl        osti_memcpy( &pDeviceInfo->sasAddressHi,
370285809Sscottl                     pDeviceData->agDeviceInfo.sasAddressHi,
371285809Sscottl                     sizeof(bit32) );
372285809Sscottl        osti_memcpy( &pDeviceInfo->sasAddressLo,
373285809Sscottl                     pDeviceData->agDeviceInfo.sasAddressLo,
374285809Sscottl                     sizeof(bit32) );
375285809Sscottl#if 0
376285809Sscottl        pDeviceInfo->sasAddressHi =
377285809Sscottl          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressHi );
378285809Sscottl        pDeviceInfo->sasAddressLo =
379285809Sscottl          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressLo );
380285809Sscottl#endif
381285809Sscottl
382285809Sscottl        pDeviceInfo->deviceType =
383285809Sscottl          ( pDeviceData->agDeviceInfo.devType_S_Rate & 0x30 ) >> 4;
384285809Sscottl        pDeviceInfo->linkRate   =
385285809Sscottl          pDeviceData->agDeviceInfo.devType_S_Rate & 0x0F;
386285809Sscottl        pDeviceInfo->phyId      =  pDeviceData->phyID;
387285809Sscottl 	pDeviceInfo->ishost	=  pDeviceData->target_ssp_stp_smp;
388285809Sscottl	pDeviceInfo->DeviceHandle= (unsigned long)pDeviceHandle;
389285809Sscottl	if(pDeviceInfo->deviceType == 0x02)
390285809Sscottl	{
391285809Sscottl	   bit8 *sasAddressHi;
392285809Sscottl	   bit8 *sasAddressLo;
393285809Sscottl	   tiIniGetDirectSataSasAddr(&pCard->tiRoot, pDeviceData->phyID, &sasAddressHi, &sasAddressLo);
394285809Sscottl	   pDeviceInfo->sasAddressHi = DMA_BEBIT32_TO_BIT32(*(bit32*)sasAddressHi);
395285809Sscottl	   pDeviceInfo->sasAddressLo = DMA_BEBIT32_TO_BIT32(*(bit32*)sasAddressLo) + pDeviceData->phyID + 16;
396285809Sscottl	}
397285809Sscottl	else
398285809Sscottl	{
399285809Sscottl        pDeviceInfo->sasAddressHi =
400285809Sscottl          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressHi );
401285809Sscottl        pDeviceInfo->sasAddressLo =
402285809Sscottl          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressLo );
403285809Sscottl 	}
404285809Sscottl
405285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: devicetype %x\n",
406285809Sscottl                        pDeviceInfo->deviceType );
407285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: linkrate %x\n",
408285809Sscottl                        pDeviceInfo->linkRate );
409285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: phyID %x\n",
410285809Sscottl                        pDeviceInfo->phyId );
411285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: addresshi %x\n",
412285809Sscottl                        pDeviceInfo->sasAddressHi );
413285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: addresslo %x\n",
414285809Sscottl                        pDeviceInfo->sasAddressHi );
415285809Sscottl      }
416285809Sscottl      else
417285809Sscottl      {
418285809Sscottl        AGTIAPI_PRINTK( "agtiapi_getdevlist: pDeviceData %p or pDeviceInfo "
419285809Sscottl                        "%p is NULL %d\n", pDeviceData, pDeviceInfo, x );
420285809Sscottl      }
421285809Sscottl      count++;
422285809Sscottl    }
423285809Sscottl  }
424285809Sscottl  pIoctlPayload->realDeviceCount = count;
425285809Sscottl  AGTIAPI_PRINTK( "agtiapi_getdevlist: Exit RealDeviceCount = %d\n", count );
426285809Sscottl  if (devList)
427285809Sscottl  {
428285809Sscottl    free(devList, TEMP2);
429285809Sscottl  }
430285809Sscottl  if(ret_val != IOCTL_CALL_FAIL)
431285809Sscottl  {
432285809Sscottl    ret_val = IOCTL_CALL_SUCCESS;
433285809Sscottl  }
434285809Sscottl  agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
435285809Sscottl  return  ret_val;
436285809Sscottl}
437285809Sscottl
438285809Sscottl/******************************************************************************
439285809Sscottlagtiapi_getCardInfo()
440285809Sscottl
441285809SscottlPurpose:
442285809Sscottl  This function retrives the Card information
443285809SscottlParameters:
444285809Sscottl
445285809SscottlReturn:
446285809Sscottl  A number - error
447285809Sscottl  0        - HBA has been detected
448285809SscottlNote:
449285809Sscottl******************************************************************************/
450285809Sscottlint agtiapi_getCardInfo ( struct agtiapi_softc *pCard,
451285809Sscottl                          U32_64                size,
452285809Sscottl                          void                 *buffer )
453285809Sscottl{
454285809Sscottl  CardInfo_t       *pCardInfo;
455285809Sscottl
456285809Sscottl  pCardInfo = (CardInfo_t *)buffer;
457285809Sscottl
458285809Sscottl  pCardInfo->deviceId = pci_get_device(pCard->my_dev);
459285809Sscottl  pCardInfo->vendorId =pci_get_vendor(pCard->my_dev) ;
460285809Sscottl  memcpy( pCardInfo->pciMemBaseSpc,
461285809Sscottl          pCard->pCardInfo->pciMemBaseSpc,
462285809Sscottl          ((sizeof(U32_64))*PCI_NUMBER_BARS) );
463285809Sscottl  pCardInfo->deviceNum = pci_get_slot(pCard->my_dev);
464285809Sscottl  pCardInfo->pciMemBase = pCard->pCardInfo->pciMemBase;
465285809Sscottl  pCardInfo->pciIOAddrLow = pCard->pCardInfo->pciIOAddrLow;
466285809Sscottl  pCardInfo->pciIOAddrUp = pCard->pCardInfo->pciIOAddrUp;
467285809Sscottl  pCardInfo->busNum =pci_get_bus(pCard->my_dev);
468285809Sscottl  return 0;
469285809Sscottl}
470285809Sscottl
471285809Sscottlvoid agtiapi_adjust_queue_depth(struct cam_path *path, bit32 QueueDepth)
472285809Sscottl{
473285809Sscottl  struct ccb_relsim crs;
474285809Sscottl  xpt_setup_ccb(&crs.ccb_h, path, 5);
475285809Sscottl  crs.ccb_h.func_code = XPT_REL_SIMQ;
476285809Sscottl  crs.ccb_h.flags = CAM_DEV_QFREEZE;
477285809Sscottl  crs.release_flags = RELSIM_ADJUST_OPENINGS;
478285809Sscottl  crs.openings = QueueDepth;
479285809Sscottl  xpt_action((union ccb *)&crs);
480285809Sscottl  if(crs.ccb_h.status != CAM_REQ_CMP) {
481285809Sscottl                 printf("XPT_REL_SIMQ failed\n");
482285809Sscottl  }
483285809Sscottl}
484285809Sscottlstatic void
485285809Sscottlagtiapi_async(void *callback_arg, u_int32_t code,
486285809Sscottl	       struct cam_path *path, void *arg)
487285809Sscottl{
488285809Sscottl	struct agtiapi_softc *pmsc;
489285809Sscottl	U32        TID;
490285809Sscottl	ag_device_t *targ;
491285809Sscottl	pmsc = (struct agtiapi_softc*)callback_arg;
492285809Sscottl	switch (code) {
493285809Sscottl	case AC_FOUND_DEVICE:
494285809Sscottl	{
495285809Sscottl	    struct ccb_getdev *cgd;
496285809Sscottl	    cgd = (struct ccb_getdev *)arg;
497285809Sscottl	    if (cgd == NULL) {
498285809Sscottl		break;
499285809Sscottl	    }
500285809Sscottl	    TID = cgd->ccb_h.target_id;
501285809Sscottl	    if (TID >= 0 && TID < maxTargets){
502285809Sscottl                if (pmsc != NULL){
503285809Sscottl                    TID = INDEX(pmsc, TID);
504285809Sscottl                    targ   = &pmsc->pDevList[TID];
505285809Sscottl	            agtiapi_adjust_queue_depth(path, targ->qdepth);
506285809Sscottl                }
507285809Sscottl	    }
508285809Sscottl	    break;
509285809Sscottl        }
510285809Sscottl	default:
511285809Sscottl		break;
512285809Sscottl	}
513285809Sscottl}
514285809Sscottl/******************************************************************************
515285809Sscottlagtiapi_CharIoctl()
516285809Sscottl
517285809SscottlPurpose:
518285809Sscottl  This function handles the ioctl from application layer
519285809SscottlParameters:
520285809Sscottl
521285809SscottlReturn:
522285809Sscottl  A number - error
523285809Sscottl  0        - HBA has been detected
524285809SscottlNote:
525285809Sscottl******************************************************************************/
526285809Sscottlstatic int agtiapi_CharIoctl( struct cdev   *dev,
527285809Sscottl                              u_long         cmd,
528285809Sscottl                              caddr_t        data,
529285809Sscottl                              int            fflag,
530285809Sscottl                              struct thread *td )
531285809Sscottl{
532285809Sscottl  struct sema           mx;
533285809Sscottl  datatosend           *load; // structure defined in lxcommon.h
534285809Sscottl  tiIOCTLPayload_t     *pIoctlPayload;
535285809Sscottl  struct agtiapi_softc *pCard;
536285809Sscottl  pCard=dev->si_drv1;
537285809Sscottl  void *param1 = NULL;
538285809Sscottl  void *param2 = NULL;
539285809Sscottl  void *param3 = NULL;
540285809Sscottl  U32   status = 0;
541285809Sscottl  U32   retValue;
542285809Sscottl  int   err    = 0;
543285809Sscottl  int   error  = 0;
544285809Sscottl  tdDeviceListPayload_t *pDeviceList = NULL;
545285809Sscottl  unsigned long flags;
546285809Sscottl
547285809Sscottl  switch (cmd)
548285809Sscottl  {
549285809Sscottl  case AGTIAPI_IOCTL:
550285809Sscottl    load=(datatosend*)data;
551285809Sscottl    pIoctlPayload = malloc(load->datasize,TEMP,M_WAITOK);
552285809Sscottl    AGTIAPI_PRINTK( "agtiapi_CharIoctl: old load->datasize = %d\n", load->datasize );
553285809Sscottl    //Copy payload to kernel buffer, on success it returns 0
554285809Sscottl    err = copyin(load->data,pIoctlPayload,load->datasize);
555285809Sscottl    if (err)
556285809Sscottl    {
557285809Sscottl      status = IOCTL_CALL_FAIL;
558285809Sscottl      return status;
559285809Sscottl    }
560285809Sscottl    sema_init(&mx,0,"sem");
561285809Sscottl    pCard->pIoctlSem  =&mx;
562285809Sscottl    pCard->up_count = pCard->down_count = 0;
563285809Sscottl    if ( pIoctlPayload->MajorFunction == IOCTL_MJ_GET_DEVICE_LIST )
564285809Sscottl    {
565285809Sscottl      retValue = agtiapi_getdevlist(pCard, pIoctlPayload);
566285809Sscottl      if (retValue == 0)
567285809Sscottl      {
568285809Sscottl        pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
569285809Sscottl        status = IOCTL_CALL_SUCCESS;
570285809Sscottl      }
571285809Sscottl      else
572285809Sscottl      {
573285809Sscottl        pIoctlPayload->Status = IOCTL_CALL_FAIL;
574285809Sscottl        status = IOCTL_CALL_FAIL;
575285809Sscottl      }
576285809Sscottl      //update new device length
577285809Sscottl      pDeviceList = (tdDeviceListPayload_t*)pIoctlPayload->FunctionSpecificArea;
578285809Sscottl      load->datasize =load->datasize - sizeof(tdDeviceInfoIOCTL_t) * (pDeviceList->deviceLength - pDeviceList->realDeviceCount);
579285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CharIoctl: new load->datasize = %d\n", load->datasize );
580285809Sscottl
581285809Sscottl    }
582285809Sscottl    else if (pIoctlPayload->MajorFunction == IOCTL_MN_GET_CARD_INFO)
583285809Sscottl    {
584285809Sscottl      retValue = agtiapi_getCardInfo( pCard,
585285809Sscottl                                      pIoctlPayload->Length,
586285809Sscottl                                      (pIoctlPayload->FunctionSpecificArea) );
587285809Sscottl      if (retValue == 0)
588285809Sscottl      {
589285809Sscottl        pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
590285809Sscottl        status = IOCTL_CALL_SUCCESS;
591285809Sscottl      }
592285809Sscottl      else
593285809Sscottl      {
594285809Sscottl        pIoctlPayload->Status = IOCTL_CALL_FAIL;
595285809Sscottl        status = IOCTL_CALL_FAIL;
596285809Sscottl      }
597285809Sscottl    }
598285809Sscottl    else if ( pIoctlPayload->MajorFunction == IOCTL_MJ_CHECK_DPMC_EVENT )
599285809Sscottl    {
600285809Sscottl      if ( pCard->flags & AGTIAPI_PORT_PANIC )
601285809Sscottl      {
602285809Sscottl        strcpy ( pIoctlPayload->FunctionSpecificArea, "DPMC LEAN\n" );
603285809Sscottl      }
604285809Sscottl      else
605285809Sscottl      {
606285809Sscottl        strcpy ( pIoctlPayload->FunctionSpecificArea, "do not dpmc lean\n" );
607285809Sscottl      }
608285809Sscottl      pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
609285809Sscottl      status = IOCTL_CALL_SUCCESS;
610285809Sscottl    }
611285809Sscottl    else if (pIoctlPayload->MajorFunction == IOCTL_MJ_CHECK_FATAL_ERROR )
612285809Sscottl    {
613285809Sscottl      AGTIAPI_PRINTK("agtiapi_CharIoctl: IOCTL_MJ_CHECK_FATAL_ERROR call received for card %d\n", pCard->cardNo);
614285809Sscottl      //read port status to see if there is a fatal event
615285809Sscottl      if(pCard->flags & AGTIAPI_PORT_PANIC)
616285809Sscottl      {
617285809Sscottl        printf("agtiapi_CharIoctl: Port Panic Status For Card %d is True\n",pCard->cardNo);
618285809Sscottl        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERR_CHK_SEND_TRUE;
619285809Sscottl      }
620285809Sscottl      else
621285809Sscottl      {
622285809Sscottl        AGTIAPI_PRINTK("agtiapi_CharIoctl: Port Panic Status For Card %d is False\n",pCard->cardNo);
623285809Sscottl        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERR_CHK_SEND_FALSE;
624285809Sscottl      }
625285809Sscottl      status = IOCTL_CALL_SUCCESS;
626285809Sscottl    }
627285809Sscottl    else if (pIoctlPayload->MajorFunction == IOCTL_MJ_FATAL_ERROR_DUMP_COMPLETE)
628285809Sscottl    {
629285809Sscottl      AGTIAPI_PRINTK("agtiapi_CharIoctl: IOCTL_MJ_FATAL_ERROR_DUMP_COMPLETE call received for card %d\n", pCard->cardNo);
630285809Sscottl      //set flags bit status to be a soft reset
631285809Sscottl      pCard->flags |= AGTIAPI_SOFT_RESET;
632285809Sscottl      //trigger soft reset for the card
633285809Sscottl      retValue = agtiapi_ResetCard (pCard, &flags);
634285809Sscottl
635285809Sscottl      if(retValue == AGTIAPI_SUCCESS)
636285809Sscottl      {
637285809Sscottl        //clear port panic status
638285809Sscottl        pCard->flags &= ~AGTIAPI_PORT_PANIC;
639285809Sscottl        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERROR_SOFT_RESET_TRIG;
640285809Sscottl        status = IOCTL_CALL_SUCCESS;
641285809Sscottl      }
642285809Sscottl      else
643285809Sscottl      {
644285809Sscottl        pIoctlPayload->Status = IOCTL_CALL_FAIL;
645285809Sscottl        status = IOCTL_CALL_FAIL;
646285809Sscottl      }
647285809Sscottl    }
648285809Sscottl    else
649285809Sscottl    {
650285809Sscottl      status = tiCOMMgntIOCTL( &pCard->tiRoot,
651285809Sscottl                               pIoctlPayload,
652285809Sscottl                               pCard,
653285809Sscottl                               param2,
654285809Sscottl                               param3 );
655285809Sscottl      if (status == IOCTL_CALL_PENDING)
656285809Sscottl      {
657285809Sscottl        ostiIOCTLWaitForSignal(&pCard->tiRoot,NULL, NULL, NULL);
658285809Sscottl        status = IOCTL_CALL_SUCCESS;
659285809Sscottl      }
660285809Sscottl    }
661285809Sscottl    pCard->pIoctlSem = NULL;
662285809Sscottl    err = 0;
663285809Sscottl
664285809Sscottl    //copy kernel buffer to userland buffer
665285809Sscottl    err=copyout(pIoctlPayload,load->data,load->datasize);
666285809Sscottl    if (err)
667285809Sscottl    {
668285809Sscottl      status = IOCTL_CALL_FAIL;
669285809Sscottl      return status;
670285809Sscottl    }
671285809Sscottl    free(pIoctlPayload,TEMP);
672285809Sscottl    pIoctlPayload=NULL;
673285809Sscottl    break;
674285809Sscottl  default:
675285809Sscottl    error = ENOTTY;
676285809Sscottl    break;
677285809Sscottl  }
678285809Sscottl  return(status);
679285809Sscottl}
680285809Sscottl
681285809Sscottl/******************************************************************************
682285809Sscottlagtiapi_probe()
683285809Sscottl
684285809SscottlPurpose:
685285809Sscottl  This function initialize and registere all detected HBAs.
686285809Sscottl  The first function being called in driver after agtiapi_probe()
687285809SscottlParameters:
688285809Sscottl  device_t dev (IN)  - device pointer
689285809SscottlReturn:
690285809Sscottl  A number - error
691285809Sscottl  0        - HBA has been detected
692285809SscottlNote:
693285809Sscottl******************************************************************************/
694285809Sscottlstatic int agtiapi_probe( device_t dev )
695285809Sscottl{
696285809Sscottl  int retVal;
697286263Simp  int thisCard;
698286263Simp  ag_card_info_t *thisCardInst;
699286263Simp
700286263Simp  thisCard = device_get_unit( dev );
701286263Simp  if ( thisCard >= AGTIAPI_MAX_CARDS )
702285809Sscottl  {
703286263Simp    device_printf( dev, "Too many PMC-Sierra cards detected ERROR!\n" );
704286263Simp    return (ENXIO); // maybe change to different return value?
705285809Sscottl  }
706286263Simp  thisCardInst = &agCardInfoList[ thisCard ];
707286263Simp  retVal = agtiapi_ProbeCard( dev, thisCardInst, thisCard );
708286263Simp  if ( retVal )
709286263Simp    return (ENXIO); // maybe change to different return value?
710286263Simp  return( BUS_PROBE_DEFAULT );  // successful probe
711285809Sscottl}
712285809Sscottl
713285809Sscottl
714285809Sscottl/******************************************************************************
715285809Sscottlagtiapi_attach()
716285809Sscottl
717285809SscottlPurpose:
718285809Sscottl  This function initialize and registere all detected HBAs.
719285809Sscottl  The first function being called in driver after agtiapi_probe()
720285809SscottlParameters:
721285809Sscottl  device_t dev (IN)  - device pointer
722285809SscottlReturn:
723285809Sscottl  A number - error
724285809Sscottl  0        - HBA has been detected
725285809SscottlNote:
726285809Sscottl******************************************************************************/
727285809Sscottlstatic int agtiapi_attach( device_t devx )
728285809Sscottl{
729285809Sscottl  // keeping get_unit call to once
730285809Sscottl  int                   thisCard = device_get_unit( devx );
731285809Sscottl  struct agtiapi_softc *pmsc;
732285809Sscottl  ag_card_info_t       *thisCardInst = &agCardInfoList[ thisCard ];
733285809Sscottl  ag_resource_info_t   *pRscInfo;
734285809Sscottl  int                   idx;
735285809Sscottl  int			        lenRecv;
736285809Sscottl  char			        buffer [256], *pLastUsedChar;
737285809Sscottl  union ccb *ccb;
738285809Sscottl  int bus, tid, lun;
739285809Sscottl  struct ccb_setasync csa;
740285809Sscottl
741285809Sscottl  AGTIAPI_PRINTK("agtiapi_attach: start dev %p thisCard %d\n", devx, thisCard);
742285809Sscottl  // AGTIAPI_PRINTK( "agtiapi_attach: entry pointer values  A %p / %p\n",
743285809Sscottl  //        thisCardInst->pPCIDev, thisCardInst );
744285809Sscottl  AGTIAPI_PRINTK( "agtiapi_attach: deviceID: 0x%x\n", pci_get_devid( devx ) );
745285809Sscottl
746285809Sscottl  TUNABLE_INT_FETCH( "DPMC_TIMEOUT_SECS",  &ag_timeout_secs );
747285809Sscottl  TUNABLE_INT_FETCH( "DPMC_TIDEBUG_LEVEL", &gTiDebugLevel   );
748285809Sscottl  // printf( "agtiapi_attach: debugLevel %d, timeout %d\n",
749285809Sscottl  //         gTiDebugLevel, ag_timeout_secs );
750285809Sscottl  if ( ag_timeout_secs < 1 )
751285809Sscottl  {
752285809Sscottl    ag_timeout_secs = 1; // set minimum timeout value of 1 second
753285809Sscottl  }
754285809Sscottl  ag_timeout_secs = (ag_timeout_secs * 1000); // convert to millisecond notation
755285809Sscottl
756285809Sscottl  // Look up our softc and initialize its fields.
757285809Sscottl  pmsc = device_get_softc( devx );
758285809Sscottl  pmsc->my_dev = devx;
759285809Sscottl
760285809Sscottl  /* Get NumberOfPortals */
761285809Sscottl  if ((ostiGetTransportParam(
762285809Sscottl                             &pmsc->tiRoot,
763285809Sscottl                             "Global",
764285809Sscottl                             "CardDefault",
765285809Sscottl                             agNULL,
766285809Sscottl                             agNULL,
767285809Sscottl                             agNULL,
768285809Sscottl                             agNULL,
769285809Sscottl                             "NumberOfPortals",
770285809Sscottl                             buffer,
771285809Sscottl                             255,
772285809Sscottl                             &lenRecv
773285809Sscottl                             ) == tiSuccess) && (lenRecv != 0))
774285809Sscottl  {
775285809Sscottl    if (osti_strncmp(buffer, "0x", 2) == 0)
776285809Sscottl    {
777285809Sscottl      ag_portal_count = osti_strtoul (buffer, &pLastUsedChar, 0);
778285809Sscottl    }
779285809Sscottl    else
780285809Sscottl    {
781285809Sscottl      ag_portal_count = osti_strtoul (buffer, &pLastUsedChar, 10);
782285809Sscottl    }
783285809Sscottl    if (ag_portal_count > AGTIAPI_MAX_PORTALS)
784285809Sscottl      ag_portal_count = AGTIAPI_MAX_PORTALS;
785285809Sscottl  }
786285809Sscottl  else
787285809Sscottl  {
788285809Sscottl    ag_portal_count = AGTIAPI_MAX_PORTALS;
789285809Sscottl  }
790285809Sscottl  AGTIAPI_PRINTK( "agtiapi_attach: ag_portal_count=%d\n", ag_portal_count );
791285809Sscottl  // initialize hostdata structure
792285809Sscottl  pmsc->flags    |= AGTIAPI_INIT_TIME | AGTIAPI_SCSI_REGISTERED |
793285809Sscottl      AGTIAPI_INITIATOR;
794285809Sscottl  pmsc->cardNo    = thisCard;
795285809Sscottl  pmsc->ccbTotal  = 0;
796285809Sscottl  pmsc->portCount = ag_portal_count;
797285809Sscottl  pmsc->pCardInfo = thisCardInst;
798285809Sscottl  pmsc->tiRoot.osData = pmsc;
799285809Sscottl  pmsc->pCardInfo->pCard  = (void *)pmsc;
800285809Sscottl  pmsc->VidDid    = ( pci_get_vendor(devx) << 16 ) | pci_get_device( devx );
801285809Sscottl  pmsc->SimQFrozen = agFALSE;
802285809Sscottl  pmsc->devq_flag  = agFALSE;
803285809Sscottl  pRscInfo = &thisCardInst->tiRscInfo;
804285809Sscottl
805285809Sscottl  osti_memset(buffer, 0, 256);
806285809Sscottl  lenRecv = 0;
807285809Sscottl
808285809Sscottl  /* Get MaxTargets */
809285809Sscottl  if ((ostiGetTransportParam(
810285809Sscottl                             &pmsc->tiRoot,
811285809Sscottl                             "Global",
812285809Sscottl                             "InitiatorParms",
813285809Sscottl                             agNULL,
814285809Sscottl                             agNULL,
815285809Sscottl                             agNULL,
816285809Sscottl                             agNULL,
817285809Sscottl                             "MaxTargets",
818285809Sscottl                             buffer,
819285809Sscottl                             sizeof(buffer),
820285809Sscottl                             &lenRecv
821285809Sscottl                             ) == tiSuccess) && (lenRecv != 0))
822285809Sscottl  {
823285809Sscottl    if (osti_strncmp(buffer, "0x", 2) == 0)
824285809Sscottl    {
825285809Sscottl      maxTargets = osti_strtoul (buffer, &pLastUsedChar, 0);
826285809Sscottl      AGTIAPI_PRINTK( "agtiapi_attach:  maxTargets = osti_strtoul  0 \n" );
827285809Sscottl    }
828285809Sscottl    else
829285809Sscottl    {
830285809Sscottl      maxTargets = osti_strtoul (buffer, &pLastUsedChar, 10);
831285809Sscottl      AGTIAPI_PRINTK( "agtiapi_attach:  maxTargets = osti_strtoul 10\n"   );
832285809Sscottl    }
833285809Sscottl  }
834285809Sscottl  else
835285809Sscottl
836285809Sscottl  {
837285809Sscottl    if(Is_ADP8H(pmsc))
838285809Sscottl       maxTargets = AGTIAPI_MAX_DEVICE_8H;
839285809Sscottl    else if(Is_ADP7H(pmsc))
840285809Sscottl       maxTargets = AGTIAPI_MAX_DEVICE_7H;
841285809Sscottl    else
842285809Sscottl       maxTargets = AGTIAPI_MAX_DEVICE;
843285809Sscottl  }
844285809Sscottl
845285809Sscottl  if (maxTargets > AGTIAPI_HW_LIMIT_DEVICE)
846285809Sscottl  {
847285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: maxTargets: %d > AGTIAPI_HW_LIMIT_DEVICE: %d\n",  maxTargets, AGTIAPI_HW_LIMIT_DEVICE );
848285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: change maxTargets = AGTIAPI_HW_LIMIT_DEVICE\n" );
849285809Sscottl    maxTargets = AGTIAPI_HW_LIMIT_DEVICE;
850285809Sscottl  }
851285809Sscottl  pmsc->devDiscover    = maxTargets ;
852285809Sscottl
853285809Sscottl #ifdef HIALEAH_ENCRYPTION
854285809Sscottl   ag_encryption_enable   =  1;
855285809Sscottl   if(ag_encryption_enable && pci_get_device(pmsc->pCardInfo->pPCIDev) ==
856285809Sscottl                                  PCI_DEVICE_ID_HIALEAH_HBA_SPCVE)
857285809Sscottl   {
858285809Sscottl	pmsc->encrypt = 1;
859285809Sscottl	pRscInfo->tiLoLevelResource.loLevelOption.encryption = agTRUE;
860285809Sscottl	printf("agtiapi_attach: Encryption Enabled\n" );
861285809Sscottl   }
862285809Sscottl#endif
863285809Sscottl  // ## for now, skip calls to ostiGetTransportParam(...)
864285809Sscottl  // ## for now, skip references to DIF & EDC
865285809Sscottl
866285809Sscottl  // Create a /dev entry for this device. The kernel will assign us
867285809Sscottl  // a major number automatically. We use the unit number of this
868285809Sscottl  // device as the minor number and name the character device
869285809Sscottl  // "agtiapi<unit>".
870285809Sscottl  pmsc->my_cdev = make_dev( &agtiapi_cdevsw, thisCard, UID_ROOT, GID_WHEEL,
871285809Sscottl			    0600, "spcv%u", thisCard );
872285809Sscottl  pmsc->my_cdev->si_drv1 = pmsc;
873285809Sscottl
874285809Sscottl  mtx_init( &thisCardInst->pmIOLock, "pmc SAS I/O lock",
875285809Sscottl	    NULL, MTX_DEF|MTX_RECURSE );
876285809Sscottl
877285809Sscottl  struct cam_devq *devq;
878285809Sscottl
879285809Sscottl  /* set the maximum number of pending IOs */
880285809Sscottl  devq = cam_simq_alloc( AGTIAPI_MAX_CAM_Q_DEPTH );
881285809Sscottl  if (devq == NULL)
882285809Sscottl  {
883285809Sscottl    AGTIAPI_PRINTK("agtiapi_attach: cam_simq_alloc is NULL\n" );
884285809Sscottl    return( EIO );
885285809Sscottl  }
886285809Sscottl
887285809Sscottl  struct cam_sim *lsim;
888285809Sscottl  lsim = cam_sim_alloc( agtiapi_cam_action,
889285809Sscottl                        agtiapi_cam_poll,
890285809Sscottl                        "pmspcbsd",
891285809Sscottl                        pmsc,
892285809Sscottl                        thisCard,
893285809Sscottl                        &thisCardInst->pmIOLock,
894285809Sscottl                        1,                       // queued per target
895285809Sscottl                        AGTIAPI_MAX_CAM_Q_DEPTH, // max tag depth
896285809Sscottl                        devq );
897285809Sscottl  if ( lsim == NULL ) {
898285809Sscottl    cam_simq_free( devq );
899285809Sscottl    AGTIAPI_PRINTK("agtiapi_attach: cam_sim_alloc is NULL\n" );
900285809Sscottl    return( EIO );
901285809Sscottl  }
902285809Sscottl
903285809Sscottl  pmsc->dev_scan = agFALSE;
904285809Sscottl  //one cam sim per scsi bus
905285809Sscottl  mtx_lock( &thisCardInst->pmIOLock );
906285809Sscottl  if ( xpt_bus_register( lsim, devx, 0 ) != CAM_SUCCESS )
907285809Sscottl  { // bus 0
908285809Sscottl    cam_sim_free( lsim, TRUE );
909285809Sscottl    mtx_unlock( &thisCardInst->pmIOLock );
910285809Sscottl    AGTIAPI_PRINTK("agtiapi_attach: xpt_bus_register fails\n" );
911285809Sscottl    return( EIO );
912285809Sscottl  }
913285809Sscottl
914285809Sscottl  pmsc->sim  = lsim;
915285809Sscottl  bus = cam_sim_path(pmsc->sim);
916285809Sscottl  tid = CAM_TARGET_WILDCARD;
917285809Sscottl  lun = CAM_LUN_WILDCARD;
918285809Sscottl  ccb = xpt_alloc_ccb_nowait();
919285809Sscottl  if (ccb == agNULL)
920285809Sscottl  {
921285809Sscottl	mtx_unlock( &thisCardInst->pmIOLock );
922285809Sscottl    cam_sim_free( lsim, TRUE );
923285809Sscottl    cam_simq_free( devq );
924285809Sscottl    return ( EIO );
925285809Sscottl  }
926285809Sscottl  if (xpt_create_path(&ccb->ccb_h.path, agNULL, bus, tid,
927285809Sscottl		      CAM_LUN_WILDCARD) != CAM_REQ_CMP)
928285809Sscottl  {
929285809Sscottl	mtx_unlock( &thisCardInst->pmIOLock );
930285809Sscottl	cam_sim_free( lsim, TRUE );
931285809Sscottl    cam_simq_free( devq );
932285809Sscottl    xpt_free_ccb(ccb);
933285809Sscottl    return( EIO );
934285809Sscottl  }
935285809Sscottl  pmsc->path = ccb->ccb_h.path;
936285809Sscottl  xpt_setup_ccb(&csa.ccb_h, pmsc->path, 5);
937285809Sscottl  csa.ccb_h.func_code = XPT_SASYNC_CB;
938285809Sscottl  csa.event_enable = AC_FOUND_DEVICE;
939285809Sscottl  csa.callback = agtiapi_async;
940285809Sscottl  csa.callback_arg = pmsc;
941285809Sscottl  xpt_action((union ccb *)&csa);
942285809Sscottl  if (csa.ccb_h.status != CAM_REQ_CMP) {
943285809Sscottl	  AGTIAPI_PRINTK("agtiapi_attach: Unable to register AC_FOUND_DEVICE\n" );
944285809Sscottl  }
945285809Sscottl  lsim->devq = devq;
946285809Sscottl  mtx_unlock( &thisCardInst->pmIOLock );
947285809Sscottl
948285809Sscottl
949285809Sscottl
950285809Sscottl
951285809Sscottl  // get TD and lower layer memory requirements
952285809Sscottl  tiCOMGetResource( &pmsc->tiRoot,
953285809Sscottl                    &pRscInfo->tiLoLevelResource,
954285809Sscottl                    &pRscInfo->tiInitiatorResource,
955285809Sscottl                    NULL,
956285809Sscottl                    &pRscInfo->tiSharedMem );
957285809Sscottl
958285809Sscottl  agtiapi_ScopeDMARes( thisCardInst );
959285809Sscottl  AGTIAPI_PRINTK( "agtiapi_attach: size from the call agtiapi_ScopeDMARes"
960285809Sscottl                  " 0x%x \n", pmsc->typhn );
961285809Sscottl
962285809Sscottl  // initialize card information and get resource ready
963285809Sscottl  if( agtiapi_InitResource( thisCardInst ) == AGTIAPI_FAIL ) {
964285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: Card %d initialize resource ERROR\n",
965285809Sscottl            thisCard );
966285809Sscottl  }
967285809Sscottl
968285809Sscottl  // begin: allocate and initialize card portal info resource
969285809Sscottl  ag_portal_data_t   *pPortalData;
970285809Sscottl  if (pmsc->portCount == 0)
971285809Sscottl  {
972285809Sscottl    pmsc->pPortalData = NULL;
973285809Sscottl  }
974285809Sscottl  else
975285809Sscottl  {
976285809Sscottl    pmsc->pPortalData = (ag_portal_data_t *)
977285809Sscottl                        malloc( sizeof(ag_portal_data_t) * pmsc->portCount,
978285809Sscottl                                M_PMC_MPRT, M_ZERO | M_WAITOK );
979285809Sscottl    if (pmsc->pPortalData == NULL)
980285809Sscottl    {
981285809Sscottl      AGTIAPI_PRINTK( "agtiapi_attach: Portal memory allocation ERROR\n" );
982285809Sscottl    }
983285809Sscottl  }
984285809Sscottl
985285809Sscottl  pPortalData = pmsc->pPortalData;
986285809Sscottl  for( idx = 0; idx < pmsc->portCount; idx++ ) {
987285809Sscottl    pPortalData->pCard = pmsc;
988285809Sscottl    pPortalData->portalInfo.portID = idx;
989285809Sscottl    pPortalData->portalInfo.tiPortalContext.osData = (void *)pPortalData;
990285809Sscottl    pPortalData++;
991285809Sscottl  }
992285809Sscottl  // end: allocate and initialize card portal info resource
993285809Sscottl
994285809Sscottl  // begin: enable msix
995285809Sscottl
996285809Sscottl  // setup msix
997285809Sscottl  // map to interrupt handler
998285809Sscottl  int error = 0;
999285809Sscottl  int mesgs = MAX_MSIX_NUM_VECTOR;
1000285809Sscottl  int i, cnt;
1001285809Sscottl
1002285809Sscottl  void (*intrHandler[MAX_MSIX_NUM_ISR])(void *arg) =
1003285809Sscottl    {
1004285809Sscottl      agtiapi_IntrHandler0,
1005285809Sscottl      agtiapi_IntrHandler1,
1006285809Sscottl      agtiapi_IntrHandler2,
1007285809Sscottl      agtiapi_IntrHandler3,
1008285809Sscottl      agtiapi_IntrHandler4,
1009285809Sscottl      agtiapi_IntrHandler5,
1010285809Sscottl      agtiapi_IntrHandler6,
1011285809Sscottl      agtiapi_IntrHandler7,
1012285809Sscottl      agtiapi_IntrHandler8,
1013285809Sscottl      agtiapi_IntrHandler9,
1014285809Sscottl      agtiapi_IntrHandler10,
1015285809Sscottl      agtiapi_IntrHandler11,
1016285809Sscottl      agtiapi_IntrHandler12,
1017285809Sscottl      agtiapi_IntrHandler13,
1018285809Sscottl      agtiapi_IntrHandler14,
1019285809Sscottl      agtiapi_IntrHandler15
1020285809Sscottl
1021285809Sscottl    };
1022285809Sscottl
1023285809Sscottl  cnt = pci_msix_count(devx);
1024285809Sscottl  AGTIAPI_PRINTK("supported MSIX %d\n", cnt); //this should be 64
1025285809Sscottl  mesgs = MIN(mesgs, cnt);
1026285809Sscottl  error = pci_alloc_msix(devx, &mesgs);
1027285809Sscottl  if (error != 0) {
1028285809Sscottl    printf( "pci_alloc_msix error %d\n", error );
1029285809Sscottl    AGTIAPI_PRINTK("error %d\n", error);
1030285809Sscottl    return( EIO );
1031285809Sscottl  }
1032285809Sscottl
1033285809Sscottl  for(i=0; i < mesgs; i++) {
1034285809Sscottl    pmsc->rscID[i] = i + 1;
1035285809Sscottl    pmsc->irq[i] = bus_alloc_resource_any( devx,
1036285809Sscottl                                           SYS_RES_IRQ,
1037285809Sscottl                                           &pmsc->rscID[i],
1038285809Sscottl                                           RF_ACTIVE );
1039285809Sscottl    if( pmsc->irq[i] == NULL ) {
1040285809Sscottl      printf( "RES_IRQ went terribly bad at %d\n", i );
1041285809Sscottl      return( EIO );
1042285809Sscottl    }
1043285809Sscottl
1044285809Sscottl    if ( (error = bus_setup_intr( devx, pmsc->irq[i],
1045285809Sscottl                                  INTR_TYPE_CAM | INTR_MPSAFE,
1046285809Sscottl                                  NULL,
1047285809Sscottl                                  intrHandler[i],
1048285809Sscottl                                  pmsc,
1049285809Sscottl                                  &pmsc->intrcookie[i] )
1050285809Sscottl           ) != 0 ) {
1051285809Sscottl      device_printf( devx, "Failed to register handler" );
1052285809Sscottl      return( EIO );
1053285809Sscottl    }
1054285809Sscottl  }
1055285809Sscottl  pmsc->flags |= AGTIAPI_IRQ_REQUESTED;
1056285809Sscottl  pmsc->pCardInfo->maxInterruptVectors = MAX_MSIX_NUM_VECTOR;
1057285809Sscottl  // end: enable msix
1058285809Sscottl
1059285809Sscottl  int ret = 0;
1060285809Sscottl  ret = agtiapi_InitCardSW(pmsc);
1061285809Sscottl  if (ret == AGTIAPI_FAIL || ret == AGTIAPI_UNKNOWN)
1062285809Sscottl  {
1063285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_InitCardSW failure %d\n",
1064285809Sscottl                    ret );
1065285809Sscottl    return( EIO );
1066285809Sscottl  }
1067285809Sscottl
1068285809Sscottl  pmsc->ccbFreeList = NULL;
1069285809Sscottl  pmsc->ccbChainList = NULL;
1070285809Sscottl  pmsc->ccbAllocList = NULL;
1071285809Sscottl
1072285809Sscottl  pmsc->flags |= ( AGTIAPI_INSTALLED );
1073285809Sscottl
1074285809Sscottl  ret = agtiapi_alloc_requests( pmsc );
1075285809Sscottl  if( ret != 0 ) {
1076285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_alloc_requests failure %d\n",
1077285809Sscottl                    ret );
1078285809Sscottl    return( EIO );
1079285809Sscottl  }
1080285809Sscottl
1081285809Sscottl  ret = agtiapi_alloc_ostimem( pmsc );
1082285809Sscottl  if (ret != AGTIAPI_SUCCESS)
1083285809Sscottl  {
1084285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_alloc_ostimem failure %d\n",
1085285809Sscottl                    ret );
1086285809Sscottl    return( EIO );
1087285809Sscottl  }
1088285809Sscottl
1089285809Sscottl  ret = agtiapi_InitCardHW( pmsc );
1090285809Sscottl  if (ret != 0)
1091285809Sscottl  {
1092285809Sscottl    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_InitCardHW failure %d\n",
1093285809Sscottl                    ret );
1094285809Sscottl    return( EIO );
1095285809Sscottl  }
1096285809Sscottl
1097285809Sscottl#ifdef HIALEAH_ENCRYPTION
1098285809Sscottl  if(pmsc->encrypt)
1099285809Sscottl  {
1100285809Sscottl	if((agtiapi_SetupEncryption(pmsc)) < 0)
1101285809Sscottl		AGTIAPI_PRINTK("SetupEncryption returned less than 0\n");
1102285809Sscottl  }
1103285809Sscottl#endif
1104285809Sscottl
1105285809Sscottl  pmsc->flags &= ~AGTIAPI_INIT_TIME;
1106285809Sscottl  return( 0 );
1107285809Sscottl}
1108285809Sscottl
1109285809Sscottl/******************************************************************************
1110285809Sscottlagtiapi_InitCardSW()
1111285809Sscottl
1112285809SscottlPurpose:
1113285809Sscottl  Host Bus Adapter Initialization
1114285809SscottlParameters:
1115285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1116285809SscottlReturn:
1117285809Sscottl  AGTIAPI_SUCCESS - success
1118285809Sscottl  AGTIAPI_FAIL    - fail
1119285809SscottlNote:
1120285809Sscottl  TBD, need chip register information
1121285809Sscottl******************************************************************************/
1122285809SscottlSTATIC agBOOLEAN agtiapi_InitCardSW( struct agtiapi_softc *pmsc )
1123285809Sscottl{
1124285809Sscottl  ag_card_info_t *thisCardInst = pmsc->pCardInfo;
1125285809Sscottl  ag_resource_info_t *pRscInfo = &thisCardInst->tiRscInfo;
1126285809Sscottl  int initSWIdx;
1127285809Sscottl
1128285809Sscottl  // begin: agtiapi_InitCardSW()
1129285809Sscottl  // now init some essential locks  n agtiapi_InitCardSW
1130285809Sscottl  mtx_init( &pmsc->sendLock,     "local q send lock",   NULL, MTX_DEF );
1131285809Sscottl  mtx_init( &pmsc->doneLock,     "local q done lock",   NULL, MTX_DEF );
1132285809Sscottl  mtx_init( &pmsc->sendSMPLock,  "local q send lock",   NULL, MTX_DEF );
1133285809Sscottl  mtx_init( &pmsc->doneSMPLock,  "local q done lock",   NULL, MTX_DEF );
1134285809Sscottl  mtx_init( &pmsc->ccbLock,      "ccb list lock",       NULL, MTX_DEF );
1135285809Sscottl  mtx_init( &pmsc->devListLock,  "hotP devListLock",    NULL, MTX_DEF );
1136285809Sscottl  mtx_init( &pmsc->memLock,      "dynamic memory lock", NULL, MTX_DEF );
1137285809Sscottl  mtx_init( &pmsc->freezeLock,   "sim freeze lock",     NULL, MTX_DEF | MTX_RECURSE);
1138285809Sscottl
1139285809Sscottl  // initialize lower layer resources
1140285809Sscottl  //## if (pCard->flags & AGTIAPI_INIT_TIME) {
1141285809Sscottl#ifdef HIALEAH_ENCRYPTION
1142285809Sscottl    /* Enable encryption if chip supports it */
1143285809Sscottl    if (pci_get_device(pmsc->pCardInfo->pPCIDev) ==
1144285809Sscottl                     PCI_DEVICE_ID_HIALEAH_HBA_SPCVE)
1145285809Sscottl        pmsc->encrypt = 1;
1146285809Sscottl
1147285809Sscottl    if (pmsc->encrypt)
1148285809Sscottl        pRscInfo->tiLoLevelResource.loLevelOption.encryption = agTRUE;
1149285809Sscottl#endif
1150285809Sscottl  pmsc->flags &= ~(AGTIAPI_PORT_INITIALIZED | AGTIAPI_SYS_INTR_ON);
1151285809Sscottl
1152285809Sscottl
1153285809Sscottl  // For now, up to 16 MSIX vectors are supported
1154285809Sscottl  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.
1155285809Sscottl    maxInterruptVectors = pmsc->pCardInfo->maxInterruptVectors;
1156285809Sscottl  AGTIAPI_PRINTK( "agtiapi_InitCardSW: maxInterruptVectors set to %d",
1157285809Sscottl                  pmsc->pCardInfo->maxInterruptVectors );
1158285809Sscottl  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.max_MSI_InterruptVectors = 0;
1159285809Sscottl  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.flag = 0;
1160285809Sscottl  pRscInfo->tiLoLevelResource.loLevelOption.maxNumOSLocks = 0;
1161285809Sscottl
1162285809Sscottl  AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMInit root %p, dev %p, pmsc %p\n",
1163285809Sscottl                  &pmsc->tiRoot, pmsc->my_dev, pmsc );
1164285809Sscottl  if( tiCOMInit( &pmsc->tiRoot,
1165285809Sscottl                 &thisCardInst->tiRscInfo.tiLoLevelResource,
1166285809Sscottl                 &thisCardInst->tiRscInfo.tiInitiatorResource,
1167285809Sscottl                 NULL,
1168285809Sscottl                 &thisCardInst->tiRscInfo.tiSharedMem ) != tiSuccess ) {
1169285809Sscottl    AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMInit ERROR\n" );
1170285809Sscottl    return AGTIAPI_FAIL;
1171285809Sscottl  }
1172285809Sscottl  int maxLocks;
1173285809Sscottl  maxLocks = pRscInfo->tiLoLevelResource.loLevelOption.numOfQueuesPerPort;
1174285809Sscottl  pmsc->STLock = malloc( ( maxLocks * sizeof(struct mtx) ), M_PMC_MSTL,
1175285809Sscottl			              M_ZERO | M_WAITOK );
1176285809Sscottl
1177285809Sscottl  for( initSWIdx = 0; initSWIdx < maxLocks; initSWIdx++ )
1178285809Sscottl  {
1179285809Sscottl    // init all indexes
1180285809Sscottl    mtx_init( &pmsc->STLock[initSWIdx], "LL & TD lock", NULL, MTX_DEF );
1181285809Sscottl  }
1182285809Sscottl
1183285809Sscottl  if( tiCOMPortInit( &pmsc->tiRoot, agFALSE ) != tiSuccess ) {
1184285809Sscottl    printf( "agtiapi_InitCardSW: tiCOMPortInit ERROR -- AGTIAPI_FAIL\n" );
1185285809Sscottl    return AGTIAPI_FAIL;
1186285809Sscottl  }
1187285809Sscottl  AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMPortInit"
1188285809Sscottl                  " root %p, dev %p, pmsc %p\n",
1189285809Sscottl                  &pmsc->tiRoot, pmsc->my_dev, pmsc );
1190285809Sscottl
1191285809Sscottl  pmsc->flags |= AGTIAPI_PORT_INITIALIZED;
1192285809Sscottl  pmsc->freezeSim = agFALSE;
1193285809Sscottl
1194285809Sscottl#ifdef HIALEAH_ENCRYPTION
1195285809Sscottl  atomic_set(&outstanding_encrypted_io_count, 0);
1196285809Sscottl  /*fix below*/
1197285809Sscottl  /*if(pmsc->encrypt && (pmsc->flags & AGTIAPI_INIT_TIME))
1198285809Sscottl	   if((agtiapi_SetupEncryptionPools(pmsc)) != 0)
1199285809Sscottl	     printf("SetupEncryptionPools failed\n"); */
1200285809Sscottl#endif
1201285809Sscottl  return AGTIAPI_SUCCESS;
1202285809Sscottl  // end: agtiapi_InitCardSW()
1203285809Sscottl}
1204285809Sscottl
1205285809Sscottl/******************************************************************************
1206285809Sscottlagtiapi_InitCardHW()
1207285809Sscottl
1208285809SscottlPurpose:
1209285809Sscottl  Host Bus Adapter Initialization
1210285809SscottlParameters:
1211285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1212285809SscottlReturn:
1213285809Sscottl  AGTIAPI_SUCCESS - success
1214285809Sscottl  AGTIAPI_FAIL    - fail
1215285809SscottlNote:
1216285809Sscottl  TBD, need chip register information
1217285809Sscottl******************************************************************************/
1218285809SscottlSTATIC agBOOLEAN agtiapi_InitCardHW( struct agtiapi_softc *pmsc )
1219285809Sscottl{
1220285809Sscottl  U32 numVal;
1221285809Sscottl  U32 count;
1222285809Sscottl  U32 loop;
1223285809Sscottl  // begin: agtiapi_InitCardHW()
1224285809Sscottl
1225285809Sscottl  ag_portal_info_t *pPortalInfo = NULL;
1226285809Sscottl  ag_portal_data_t *pPortalData;
1227285809Sscottl
1228285809Sscottl  // ISR is registered, enable chip interrupt.
1229285809Sscottl  tiCOMSystemInterruptsActive( &pmsc->tiRoot, agTRUE );
1230285809Sscottl  pmsc->flags |= AGTIAPI_SYS_INTR_ON;
1231285809Sscottl
1232285809Sscottl  numVal = sizeof(ag_device_t) * pmsc->devDiscover;
1233285809Sscottl  pmsc->pDevList =
1234285809Sscottl    (ag_device_t *)malloc( numVal, M_PMC_MDVT, M_ZERO | M_WAITOK );
1235285809Sscottl  if( !pmsc->pDevList ) {
1236285809Sscottl    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d DevList ERROR\n", numVal );
1237285809Sscottl    panic( "agtiapi_InitCardHW\n" );
1238285809Sscottl    return AGTIAPI_FAIL;
1239285809Sscottl  }
1240285809Sscottl
1241285809Sscottl#ifdef LINUX_PERBI_SUPPORT
1242285809Sscottl  numVal = sizeof(ag_slr_map_t) * pmsc->devDiscover;
1243285809Sscottl  pmsc->pSLRList =
1244285809Sscottl    (ag_slr_map_t *)malloc( numVal, M_PMC_MSLR, M_ZERO | M_WAITOK );
1245285809Sscottl  if( !pmsc->pSLRList ) {
1246285809Sscottl    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d SLRList ERROR\n", numVal );
1247285809Sscottl    panic( "agtiapi_InitCardHW SLRL\n" );
1248285809Sscottl    return AGTIAPI_FAIL;
1249285809Sscottl  }
1250285809Sscottl
1251285809Sscottl  numVal = sizeof(ag_tgt_map_t) * pmsc->devDiscover;
1252285809Sscottl  pmsc->pWWNList =
1253285809Sscottl    (ag_tgt_map_t *)malloc( numVal, M_PMC_MTGT, M_ZERO | M_WAITOK );
1254285809Sscottl  if( !pmsc->pWWNList ) {
1255285809Sscottl    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d WWNList ERROR\n", numVal );
1256285809Sscottl    panic( "agtiapi_InitCardHW WWNL\n" );
1257285809Sscottl    return AGTIAPI_FAIL;
1258285809Sscottl  }
1259285809Sscottl
1260285809Sscottl  // Get the WWN_to_target_ID mappings from the
1261285809Sscottl  // holding area which contains the input of the
1262285809Sscottl  // system configuration file.
1263285809Sscottl  if( ag_Perbi )
1264285809Sscottl    agtiapi_GetWWNMappings( pmsc, agMappingList );
1265285809Sscottl  else {
1266285809Sscottl    agtiapi_GetWWNMappings( pmsc, 0 );
1267285809Sscottl    if( agMappingList )
1268285809Sscottl      printf( "agtiapi_InitCardHW: WWN PERBI disabled WARN\n" );
1269285809Sscottl  }
1270285809Sscottl#endif
1271285809Sscottl
1272285809Sscottl  //agtiapi_DelaySec(5);
1273285809Sscottl  DELAY( 500000 );
1274285809Sscottl
1275285809Sscottl  pmsc->tgtCount = 0;
1276285809Sscottl
1277285809Sscottl  pmsc->flags &= ~AGTIAPI_CB_DONE;
1278285809Sscottl  pPortalData = pmsc->pPortalData;
1279285809Sscottl
1280285809Sscottl  //start port
1281285809Sscottl
1282285809Sscottl  for (count = 0; count < pmsc->portCount; count++)
1283285809Sscottl  {
1284285809Sscottl    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
1285285809Sscottl
1286285809Sscottl    pPortalInfo = &pPortalData->portalInfo;
1287285809Sscottl    pPortalInfo->portStatus &= ~( AGTIAPI_PORT_START      |
1288285809Sscottl                                  AGTIAPI_PORT_DISC_READY |
1289285809Sscottl                                  AGTIAPI_DISC_DONE       |
1290285809Sscottl                                  AGTIAPI_DISC_COMPLETE );
1291285809Sscottl
1292285809Sscottl    for (loop = 0; loop < AGTIAPI_LOOP_MAX; loop++)
1293285809Sscottl    {
1294285809Sscottl      AGTIAPI_PRINTK( "tiCOMPortStart entry data %p / %d / %p\n",
1295285809Sscottl                      &pmsc->tiRoot,
1296285809Sscottl                      pPortalInfo->portID,
1297285809Sscottl                      &pPortalInfo->tiPortalContext );
1298285809Sscottl
1299285809Sscottl      if( tiCOMPortStart( &pmsc->tiRoot,
1300285809Sscottl                          pPortalInfo->portID,
1301285809Sscottl                          &pPortalInfo->tiPortalContext,
1302285809Sscottl                          0 )
1303285809Sscottl          != tiSuccess ) {
1304285809Sscottl        AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
1305285809Sscottl        agtiapi_DelayMSec( AGTIAPI_EXTRA_DELAY );
1306285809Sscottl        AG_SPIN_LOCK_IRQ(agtiapi_host_lock, flags);
1307285809Sscottl        AGTIAPI_PRINTK( "tiCOMPortStart failed -- no loop, portalData %p\n",
1308285809Sscottl                        pPortalData );
1309285809Sscottl      }
1310285809Sscottl      else {
1311285809Sscottl        AGTIAPI_PRINTK( "tiCOMPortStart success no loop, portalData %p\n",
1312285809Sscottl                        pPortalData );
1313285809Sscottl        break;
1314285809Sscottl      }
1315285809Sscottl    } // end of for loop
1316285809Sscottl    /* release lock */
1317285809Sscottl    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
1318285809Sscottl
1319285809Sscottl    if( loop >= AGTIAPI_LOOP_MAX ) {
1320285809Sscottl      return AGTIAPI_FAIL;
1321285809Sscottl    }
1322285809Sscottl    tiCOMGetPortInfo( &pmsc->tiRoot,
1323285809Sscottl                      &pPortalInfo->tiPortalContext,
1324285809Sscottl                      &pPortalInfo->tiPortInfo );
1325285809Sscottl    pPortalData++;
1326285809Sscottl  }
1327285809Sscottl
1328285809Sscottl  /* discover target device */
1329285809Sscottl#ifndef HOTPLUG_SUPPORT
1330285809Sscottl  agtiapi_DiscoverTgt( pCard );
1331285809Sscottl#endif
1332285809Sscottl
1333285809Sscottl
1334285809Sscottl  pmsc->flags |= AGTIAPI_INSTALLED;
1335285809Sscottl
1336285809Sscottl  if( pmsc->flags & AGTIAPI_INIT_TIME ) {
1337285809Sscottl    agtiapi_TITimer( (void *)pmsc );
1338285809Sscottl    pmsc->flags |= AGTIAPI_TIMER_ON;
1339285809Sscottl  }
1340285809Sscottl
1341285809Sscottl  return 0;
1342285809Sscottl}
1343285809Sscottl
1344285809Sscottl
1345285809Sscottl
1346285809Sscottl/******************************************************************************
1347285809Sscottlagtiapi_IntrHandlerx_()
1348285809Sscottl
1349285809SscottlPurpose:
1350285809Sscottl  Interrupt service routine.
1351285809SscottlParameters:
1352285809Sscottl  void arg (IN)              Pointer to the HBA data structure
1353285809Sscottl  bit32 idx (IN)             Vector index
1354285809Sscottl******************************************************************************/
1355285809Sscottlvoid  agtiapi_IntrHandlerx_( void *arg, int index )
1356285809Sscottl{
1357285809Sscottl
1358285809Sscottl  struct agtiapi_softc *pCard;
1359285809Sscottl  int rv;
1360285809Sscottl
1361285809Sscottl  pCard = (struct agtiapi_softc *)arg;
1362285809Sscottl
1363285809Sscottl#ifndef AGTIAPI_DPC
1364285809Sscottl  ccb_t     *pccb;
1365285809Sscottl#endif
1366285809Sscottl
1367285809Sscottl  AG_LOCAL_LOCK(&(pCard->pCardInfo->pmIOLock));
1368285809Sscottl  AG_PERF_SPINLOCK(agtiapi_host_lock);
1369285809Sscottl  if (pCard->flags & AGTIAPI_SHUT_DOWN)
1370285809Sscottl    goto ext;
1371285809Sscottl
1372285809Sscottl  rv = tiCOMInterruptHandler(&pCard->tiRoot, index);
1373285809Sscottl  if (rv == agFALSE)
1374285809Sscottl  {
1375285809Sscottl    /* not our irq */
1376285809Sscottl    AG_SPIN_UNLOCK(agtiapi_host_lock);
1377285809Sscottl    AG_LOCAL_UNLOCK(&(pCard->pCardInfo->pmIOLock));
1378285809Sscottl    return;
1379285809Sscottl  }
1380285809Sscottl
1381285809Sscottl
1382285809Sscottl#ifdef AGTIAPI_DPC
1383285809Sscottl  tasklet_hi_schedule(&pCard->tasklet_dpc[idx]);
1384285809Sscottl#else
1385285809Sscottl  /* consume all completed entries, 100 is random number to be big enough */
1386285809Sscottl  tiCOMDelayedInterruptHandler(&pCard->tiRoot, index, 100, tiInterruptContext);
1387285809Sscottl  AG_GET_DONE_PCCB(pccb, pCard);
1388285809Sscottl  AG_GET_DONE_SMP_PCCB(pccb, pCard);
1389285809Sscottl#endif
1390285809Sscottl
1391285809Sscottlext:
1392285809Sscottl  AG_SPIN_UNLOCK(agtiapi_host_lock);
1393285809Sscottl  AG_LOCAL_UNLOCK(&(pCard->pCardInfo->pmIOLock));
1394285809Sscottl  return;
1395285809Sscottl
1396285809Sscottl}
1397285809Sscottl
1398285809Sscottl/******************************************************************************
1399285809Sscottlagtiapi_IntrHandler0()
1400285809SscottlPurpose:     Interrupt service routine for interrupt vector index 0.
1401285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1402285809Sscottl******************************************************************************/
1403285809Sscottlvoid agtiapi_IntrHandler0( void *arg )
1404285809Sscottl{
1405285809Sscottl  agtiapi_IntrHandlerx_( arg, 0 );
1406285809Sscottl  return;
1407285809Sscottl}
1408285809Sscottl
1409285809Sscottl/******************************************************************************
1410285809Sscottlagtiapi_IntrHandler1()
1411285809SscottlPurpose:     Interrupt service routine for interrupt vector index 1.
1412285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1413285809Sscottl******************************************************************************/
1414285809Sscottlvoid agtiapi_IntrHandler1( void *arg )
1415285809Sscottl{
1416285809Sscottl  agtiapi_IntrHandlerx_( arg, 1 );
1417285809Sscottl  return;
1418285809Sscottl}
1419285809Sscottl
1420285809Sscottl/******************************************************************************
1421285809Sscottlagtiapi_IntrHandler2()
1422285809SscottlPurpose:     Interrupt service routine for interrupt vector index 2.
1423285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1424285809Sscottl******************************************************************************/
1425285809Sscottlvoid agtiapi_IntrHandler2( void *arg )
1426285809Sscottl{
1427285809Sscottl  agtiapi_IntrHandlerx_( arg, 2 );
1428285809Sscottl  return;
1429285809Sscottl}
1430285809Sscottl
1431285809Sscottl/******************************************************************************
1432285809Sscottlagtiapi_IntrHandler3()
1433285809SscottlPurpose:     Interrupt service routine for interrupt vector index 3.
1434285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1435285809Sscottl******************************************************************************/
1436285809Sscottlvoid agtiapi_IntrHandler3( void *arg )
1437285809Sscottl{
1438285809Sscottl  agtiapi_IntrHandlerx_( arg, 3 );
1439285809Sscottl  return;
1440285809Sscottl}
1441285809Sscottl
1442285809Sscottl/******************************************************************************
1443285809Sscottlagtiapi_IntrHandler4()
1444285809SscottlPurpose:     Interrupt service routine for interrupt vector index 4.
1445285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1446285809Sscottl******************************************************************************/
1447285809Sscottlvoid agtiapi_IntrHandler4( void *arg )
1448285809Sscottl{
1449285809Sscottl  agtiapi_IntrHandlerx_( arg, 4 );
1450285809Sscottl  return;
1451285809Sscottl}
1452285809Sscottl
1453285809Sscottl/******************************************************************************
1454285809Sscottlagtiapi_IntrHandler5()
1455285809SscottlPurpose:     Interrupt service routine for interrupt vector index 5.
1456285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1457285809Sscottl******************************************************************************/
1458285809Sscottlvoid agtiapi_IntrHandler5( void *arg )
1459285809Sscottl{
1460285809Sscottl  agtiapi_IntrHandlerx_( arg, 5 );
1461285809Sscottl  return;
1462285809Sscottl}
1463285809Sscottl
1464285809Sscottl/******************************************************************************
1465285809Sscottlagtiapi_IntrHandler6()
1466285809SscottlPurpose:     Interrupt service routine for interrupt vector index 6.
1467285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1468285809Sscottl******************************************************************************/
1469285809Sscottlvoid agtiapi_IntrHandler6( void *arg )
1470285809Sscottl{
1471285809Sscottl  agtiapi_IntrHandlerx_( arg, 6 );
1472285809Sscottl  return;
1473285809Sscottl}
1474285809Sscottl
1475285809Sscottl/******************************************************************************
1476285809Sscottlagtiapi_IntrHandler7()
1477285809SscottlPurpose:     Interrupt service routine for interrupt vector index 7.
1478285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1479285809Sscottl******************************************************************************/
1480285809Sscottlvoid agtiapi_IntrHandler7( void *arg )
1481285809Sscottl{
1482285809Sscottl  agtiapi_IntrHandlerx_( arg, 7 );
1483285809Sscottl  return;
1484285809Sscottl}
1485285809Sscottl
1486285809Sscottl/******************************************************************************
1487285809Sscottlagtiapi_IntrHandler8()
1488285809SscottlPurpose:     Interrupt service routine for interrupt vector index 8.
1489285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1490285809Sscottl******************************************************************************/
1491285809Sscottlvoid agtiapi_IntrHandler8( void *arg )
1492285809Sscottl{
1493285809Sscottl  agtiapi_IntrHandlerx_( arg, 8 );
1494285809Sscottl  return;
1495285809Sscottl}
1496285809Sscottl
1497285809Sscottl/******************************************************************************
1498285809Sscottlagtiapi_IntrHandler9()
1499285809SscottlPurpose:     Interrupt service routine for interrupt vector index 9.
1500285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1501285809Sscottl******************************************************************************/
1502285809Sscottlvoid agtiapi_IntrHandler9( void *arg )
1503285809Sscottl{
1504285809Sscottl  agtiapi_IntrHandlerx_( arg, 9 );
1505285809Sscottl  return;
1506285809Sscottl}
1507285809Sscottl
1508285809Sscottl/******************************************************************************
1509285809Sscottlagtiapi_IntrHandler10()
1510285809SscottlPurpose:     Interrupt service routine for interrupt vector index 10.
1511285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1512285809Sscottl******************************************************************************/
1513285809Sscottlvoid agtiapi_IntrHandler10( void *arg )
1514285809Sscottl{
1515285809Sscottl  agtiapi_IntrHandlerx_( arg, 10 );
1516285809Sscottl  return;
1517285809Sscottl}
1518285809Sscottl
1519285809Sscottl/******************************************************************************
1520285809Sscottlagtiapi_IntrHandler11()
1521285809SscottlPurpose:     Interrupt service routine for interrupt vector index 11.
1522285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1523285809Sscottl******************************************************************************/
1524285809Sscottlvoid agtiapi_IntrHandler11( void *arg )
1525285809Sscottl{
1526285809Sscottl  agtiapi_IntrHandlerx_( arg, 11 );
1527285809Sscottl  return;
1528285809Sscottl}
1529285809Sscottl
1530285809Sscottl/******************************************************************************
1531285809Sscottlagtiapi_IntrHandler12()
1532285809SscottlPurpose:     Interrupt service routine for interrupt vector index 12.
1533285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1534285809Sscottl******************************************************************************/
1535285809Sscottlvoid agtiapi_IntrHandler12( void *arg )
1536285809Sscottl{
1537285809Sscottl  agtiapi_IntrHandlerx_( arg, 12 );
1538285809Sscottl  return;
1539285809Sscottl}
1540285809Sscottl
1541285809Sscottl/******************************************************************************
1542285809Sscottlagtiapi_IntrHandler13()
1543285809SscottlPurpose:     Interrupt service routine for interrupt vector index 13.
1544285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1545285809Sscottl******************************************************************************/
1546285809Sscottlvoid agtiapi_IntrHandler13( void *arg )
1547285809Sscottl{
1548285809Sscottl  agtiapi_IntrHandlerx_( arg, 13 );
1549285809Sscottl  return;
1550285809Sscottl}
1551285809Sscottl
1552285809Sscottl/******************************************************************************
1553285809Sscottlagtiapi_IntrHandler14()
1554285809SscottlPurpose:     Interrupt service routine for interrupt vector index 14.
1555285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1556285809Sscottl******************************************************************************/
1557285809Sscottlvoid agtiapi_IntrHandler14( void *arg )
1558285809Sscottl{
1559285809Sscottl  agtiapi_IntrHandlerx_( arg, 14 );
1560285809Sscottl  return;
1561285809Sscottl}
1562285809Sscottl
1563285809Sscottl/******************************************************************************
1564285809Sscottlagtiapi_IntrHandler15()
1565285809SscottlPurpose:     Interrupt service routine for interrupt vector index 15.
1566285809SscottlParameters:  void arg (IN)       Pointer to the HBA data structure
1567285809Sscottl******************************************************************************/
1568285809Sscottlvoid agtiapi_IntrHandler15( void *arg )
1569285809Sscottl{
1570285809Sscottl  agtiapi_IntrHandlerx_( arg, 15 );
1571285809Sscottl  return;
1572285809Sscottl}
1573285809Sscottl
1574285809Sscottlstatic void agtiapi_SglMemoryCB( void *arg,
1575285809Sscottl                                 bus_dma_segment_t *dm_segs,
1576285809Sscottl                                 int nseg,
1577285809Sscottl                                 int error )
1578285809Sscottl{
1579285809Sscottl  bus_addr_t *addr;
1580285809Sscottl  AGTIAPI_PRINTK("agtiapi_SglMemoryCB: start\n");
1581285809Sscottl  if (error != 0)
1582285809Sscottl  {
1583285809Sscottl    AGTIAPI_PRINTK("agtiapi_SglMemoryCB: error %d\n", error);
1584285809Sscottl    panic("agtiapi_SglMemoryCB: error %d\n", error);
1585285809Sscottl    return;
1586285809Sscottl  }
1587285809Sscottl  addr = arg;
1588285809Sscottl  *addr = dm_segs[0].ds_addr;
1589285809Sscottl  return;
1590285809Sscottl}
1591285809Sscottl
1592285809Sscottlstatic void agtiapi_MemoryCB( void *arg,
1593285809Sscottl                              bus_dma_segment_t *dm_segs,
1594285809Sscottl                              int nseg,
1595285809Sscottl                              int error )
1596285809Sscottl{
1597285809Sscottl  bus_addr_t *addr;
1598285809Sscottl  AGTIAPI_PRINTK("agtiapi_MemoryCB: start\n");
1599285809Sscottl  if (error != 0)
1600285809Sscottl  {
1601285809Sscottl    AGTIAPI_PRINTK("agtiapi_MemoryCB: error %d\n", error);
1602285809Sscottl    panic("agtiapi_MemoryCB: error %d\n", error);
1603285809Sscottl    return;
1604285809Sscottl  }
1605285809Sscottl  addr = arg;
1606285809Sscottl  *addr = dm_segs[0].ds_addr;
1607285809Sscottl  return;
1608285809Sscottl}
1609285809Sscottl
1610285809Sscottl/******************************************************************************
1611285809Sscottlagtiapi_alloc_requests()
1612285809Sscottl
1613285809SscottlPurpose:
1614285809Sscottl  Allocates resources such as dma tag and timer
1615285809SscottlParameters:
1616285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1617285809SscottlReturn:
1618285809Sscottl  AGTIAPI_SUCCESS - success
1619285809Sscottl  AGTIAPI_FAIL    - fail
1620285809SscottlNote:
1621285809Sscottl******************************************************************************/
1622285809Sscottlint agtiapi_alloc_requests( struct agtiapi_softc *pmcsc )
1623285809Sscottl{
1624285809Sscottl
1625285809Sscottl  int rsize, nsegs;
1626285809Sscottl  U32 next_tick;
1627285809Sscottl
1628285809Sscottl  nsegs = AGTIAPI_NSEGS;
1629285809Sscottl  rsize = AGTIAPI_MAX_DMA_SEGS;   // 128
1630285809Sscottl  AGTIAPI_PRINTK( "agtiapi_alloc_requests: MAXPHYS 0x%x PAGE_SIZE 0x%x \n",
1631285809Sscottl                  MAXPHYS, PAGE_SIZE );
1632285809Sscottl  AGTIAPI_PRINTK( "agtiapi_alloc_requests: nsegs %d rsize %d \n",
1633285809Sscottl                  nsegs, rsize ); // 32, 128
1634285809Sscottl  // This is for csio->data_ptr
1635285809Sscottl  if( bus_dma_tag_create( agNULL,                      // parent
1636285809Sscottl                          1,                           // alignment
1637285809Sscottl                          0,                           // boundary
1638285809Sscottl                          BUS_SPACE_MAXADDR,           // lowaddr
1639285809Sscottl                          BUS_SPACE_MAXADDR,           // highaddr
1640285809Sscottl                          NULL,                        // filter
1641285809Sscottl                          NULL,                        // filterarg
1642285809Sscottl                          BUS_SPACE_MAXSIZE_32BIT,     // maxsize
1643285809Sscottl                          nsegs,                       // nsegments
1644285809Sscottl                          BUS_SPACE_MAXSIZE_32BIT,     // maxsegsize
1645285809Sscottl                          BUS_DMA_ALLOCNOW,            // flags
1646285809Sscottl                          busdma_lock_mutex,           // lockfunc
1647285809Sscottl                          &pmcsc->pCardInfo->pmIOLock, // lockarg
1648285809Sscottl                          &pmcsc->buffer_dmat ) ) {
1649285809Sscottl    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot alloc request DMA tag\n" );
1650285809Sscottl    return( ENOMEM );
1651285809Sscottl  }
1652285809Sscottl
1653285809Sscottl  // This is for tiSgl_t of pccb in agtiapi_PrepCCBs()
1654285809Sscottl  rsize =
1655285809Sscottl    (sizeof(tiSgl_t) * AGTIAPI_NSEGS) *
1656285809Sscottl    AGTIAPI_CCB_PER_DEVICE * maxTargets;
1657285809Sscottl  AGTIAPI_PRINTK( "agtiapi_alloc_requests: rsize %d \n", rsize ); // 32, 128
1658285809Sscottl  if( bus_dma_tag_create( agNULL,                  // parent
1659285809Sscottl                          32,                      // alignment
1660285809Sscottl                          0,	                     // boundary
1661285809Sscottl                          BUS_SPACE_MAXADDR_32BIT, // lowaddr
1662285809Sscottl                          BUS_SPACE_MAXADDR,	     // highaddr
1663285809Sscottl                          NULL,                    // filter
1664285809Sscottl                          NULL,	                   // filterarg
1665285809Sscottl                          rsize,                   // maxsize
1666285809Sscottl                          1,                       // nsegments
1667285809Sscottl                          rsize,                   // maxsegsize
1668285809Sscottl                          BUS_DMA_ALLOCNOW,        // flags
1669285809Sscottl                          NULL,                    // lockfunc
1670285809Sscottl                          NULL,                    // lockarg
1671285809Sscottl                          &pmcsc->tisgl_dmat ) ) {
1672285809Sscottl    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot alloc request DMA tag\n" );
1673285809Sscottl    return( ENOMEM );
1674285809Sscottl  }
1675285809Sscottl
1676285809Sscottl  if( bus_dmamem_alloc( pmcsc->tisgl_dmat,
1677285809Sscottl                        (void **)&pmcsc->tisgl_mem,
1678285809Sscottl                        BUS_DMA_NOWAIT,
1679285809Sscottl                        &pmcsc->tisgl_map ) ) {
1680285809Sscottl    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot allocate SGL memory\n" );
1681285809Sscottl    return( ENOMEM );
1682285809Sscottl  }
1683285809Sscottl
1684285809Sscottl  bzero( pmcsc->tisgl_mem, rsize );
1685285809Sscottl  bus_dmamap_load( pmcsc->tisgl_dmat,
1686285809Sscottl                   pmcsc->tisgl_map,
1687285809Sscottl                   pmcsc->tisgl_mem,
1688285809Sscottl                   rsize,
1689285809Sscottl                   agtiapi_SglMemoryCB,
1690285809Sscottl                   &pmcsc->tisgl_busaddr,
1691285809Sscottl                   BUS_DMA_NOWAIT /* 0 */ );
1692285809Sscottl
1693285809Sscottl  mtx_init( &pmcsc->OS_timer_lock,  "OS timer lock",      NULL, MTX_DEF );
1694285809Sscottl  mtx_init( &pmcsc->IO_timer_lock,  "IO timer lock",      NULL, MTX_DEF );
1695285809Sscottl  mtx_init( &pmcsc->devRmTimerLock, "targ rm timer lock", NULL, MTX_DEF );
1696285809Sscottl  callout_init_mtx( &pmcsc->OS_timer, &pmcsc->OS_timer_lock, 0 );
1697285809Sscottl  callout_init_mtx( &pmcsc->IO_timer, &pmcsc->IO_timer_lock, 0 );
1698285809Sscottl  callout_init_mtx( &pmcsc->devRmTimer,
1699285809Sscottl		    &pmcsc->devRmTimerLock, 0);
1700285809Sscottl
1701285809Sscottl  next_tick = pmcsc->pCardInfo->tiRscInfo.tiLoLevelResource.
1702285809Sscottl              loLevelOption.usecsPerTick / USEC_PER_TICK;
1703285809Sscottl  AGTIAPI_PRINTK( "agtiapi_alloc_requests: before callout_reset, "
1704285809Sscottl                  "next_tick 0x%x\n", next_tick );
1705285809Sscottl  callout_reset( &pmcsc->OS_timer, next_tick, agtiapi_TITimer, pmcsc );
1706285809Sscottl  return 0;
1707285809Sscottl}
1708285809Sscottl
1709285809Sscottl/******************************************************************************
1710285809Sscottlagtiapi_alloc_ostimem()
1711285809Sscottl
1712285809SscottlPurpose:
1713285809Sscottl  Allocates memory used later in ostiAllocMemory
1714285809SscottlParameters:
1715285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to the HBA data structure
1716285809SscottlReturn:
1717285809Sscottl  AGTIAPI_SUCCESS - success
1718285809Sscottl  AGTIAPI_FAIL    - fail
1719285809SscottlNote:
1720285809Sscottl  This is a pre-allocation for ostiAllocMemory() "non-cacheable" function calls
1721285809Sscottl******************************************************************************/
1722285809Sscottlint  agtiapi_alloc_ostimem( struct agtiapi_softc *pmcsc ) {
1723285809Sscottl  int rsize, nomsize;
1724285809Sscottl
1725285809Sscottl  nomsize = 4096;
1726285809Sscottl  rsize = AGTIAPI_DYNAMIC_MAX * nomsize; // 8M
1727285809Sscottl  AGTIAPI_PRINTK("agtiapi_alloc_ostimem: rsize %d \n", rsize);
1728285809Sscottl
1729285809Sscottl  if( bus_dma_tag_create( agNULL,                      // parent
1730285809Sscottl                          32,                          // alignment
1731285809Sscottl                          0,                           // boundary
1732285809Sscottl                          BUS_SPACE_MAXADDR,           // lowaddr
1733285809Sscottl                          BUS_SPACE_MAXADDR,           // highaddr
1734285809Sscottl                          NULL,                        // filter
1735285809Sscottl                          NULL,                        // filterarg
1736285809Sscottl                          rsize,                       // maxsize (size)
1737285809Sscottl                          1,                           // number of segments
1738285809Sscottl                          rsize,                       // maxsegsize
1739285809Sscottl                          0,                           // flags
1740285809Sscottl                          NULL,                        // lockfunc
1741285809Sscottl                          NULL,                        // lockarg
1742285809Sscottl                          &pmcsc->osti_dmat ) ) {
1743285809Sscottl    AGTIAPI_PRINTK( "agtiapi_alloc_ostimem: Can't create no-cache mem tag\n" );
1744285809Sscottl    return AGTIAPI_FAIL;
1745285809Sscottl  }
1746285809Sscottl
1747285809Sscottl
1748285809Sscottl  if( bus_dmamem_alloc( pmcsc->osti_dmat,
1749285809Sscottl                        &pmcsc->osti_mem,
1750285809Sscottl                        BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE,
1751285809Sscottl                        &pmcsc->osti_mapp ) ) {
1752285809Sscottl    AGTIAPI_PRINTK( "agtiapi_alloc_ostimem: Cannot allocate cache mem %d\n",
1753285809Sscottl                    rsize );
1754285809Sscottl    return AGTIAPI_FAIL;
1755285809Sscottl  }
1756285809Sscottl
1757285809Sscottl
1758285809Sscottl  bus_dmamap_load( pmcsc->osti_dmat,
1759285809Sscottl                   pmcsc->osti_mapp,
1760285809Sscottl                   pmcsc->osti_mem,
1761285809Sscottl                   rsize,
1762285809Sscottl                   agtiapi_MemoryCB, // try reuse of CB for same goal
1763285809Sscottl                   &pmcsc->osti_busaddr,
1764285809Sscottl                   BUS_DMA_NOWAIT );
1765285809Sscottl
1766285809Sscottl  // populate all the ag_dma_addr_t osti_busaddr/mem fields with addresses for
1767285809Sscottl  //  handy reference when driver is in motion
1768285809Sscottl  int idx;
1769285809Sscottl  ag_card_info_t *pCardInfo = pmcsc->pCardInfo;
1770285809Sscottl  ag_dma_addr_t  *pMem;
1771285809Sscottl
1772285809Sscottl  for( idx = 0; idx < AGTIAPI_DYNAMIC_MAX; idx++ ) {
1773285809Sscottl    pMem = &pCardInfo->dynamicMem[idx];
1774285809Sscottl    pMem->nocache_busaddr = pmcsc->osti_busaddr + ( idx * nomsize );
1775285809Sscottl    pMem->nocache_mem     = (void*)((U64)pmcsc->osti_mem + ( idx * nomsize ));
1776285809Sscottl    pCardInfo->freeDynamicMem[idx] = &pCardInfo->dynamicMem[idx];
1777285809Sscottl  }
1778285809Sscottl
1779285809Sscottl  pCardInfo->topOfFreeDynamicMem = AGTIAPI_DYNAMIC_MAX;
1780285809Sscottl
1781285809Sscottl  return AGTIAPI_SUCCESS;
1782285809Sscottl}
1783285809Sscottl
1784285809Sscottl
1785285809Sscottl/******************************************************************************
1786285809Sscottlagtiapi_cam_action()
1787285809Sscottl
1788285809SscottlPurpose:
1789285809Sscottl  Parses CAM frames and triggers a corresponding action
1790285809SscottlParameters:
1791285809Sscottl  struct cam_sim *sim (IN)  Pointer to SIM data structure
1792285809Sscottl  union ccb * ccb (IN)      Pointer to CAM ccb data structure
1793285809SscottlReturn:
1794285809SscottlNote:
1795285809Sscottl******************************************************************************/
1796285809Sscottlstatic void agtiapi_cam_action( struct cam_sim *sim, union ccb * ccb )
1797285809Sscottl{
1798285809Sscottl  struct agtiapi_softc *pmcsc;
1799285809Sscottl  tiDeviceHandle_t *pDevHandle = NULL;	// acts as flag as well
1800285809Sscottl  tiDeviceInfo_t devInfo;
1801285809Sscottl  int pathID, targetID, lunID;
1802285809Sscottl  int lRetVal;
1803285809Sscottl  U32 TID;
1804285809Sscottl  U32 speed = 150000;
1805285809Sscottl
1806285809Sscottl  pmcsc = cam_sim_softc( sim );
1807285809Sscottl  AGTIAPI_IO( "agtiapi_cam_action: start pmcs %p\n", pmcsc );
1808285809Sscottl
1809285809Sscottl  if (pmcsc == agNULL)
1810285809Sscottl  {
1811285809Sscottl    AGTIAPI_PRINTK( "agtiapi_cam_action: start pmcs is NULL\n" );
1812285809Sscottl    return;
1813285809Sscottl  }
1814285809Sscottl  mtx_assert( &(pmcsc->pCardInfo->pmIOLock), MA_OWNED );
1815285809Sscottl
1816285809Sscottl  AGTIAPI_IO( "agtiapi_cam_action: cardNO %d func_code 0x%x\n", pmcsc->cardNo, ccb->ccb_h.func_code );
1817285809Sscottl
1818285809Sscottl  pathID   = xpt_path_path_id( ccb->ccb_h.path );
1819285809Sscottl  targetID = xpt_path_target_id( ccb->ccb_h.path );
1820285809Sscottl  lunID    = xpt_path_lun_id( ccb->ccb_h.path );
1821285809Sscottl
1822285809Sscottl  AGTIAPI_IO( "agtiapi_cam_action: P 0x%x T 0x%x L 0x%x\n",
1823285809Sscottl              pathID, targetID, lunID );
1824285809Sscottl
1825285809Sscottl  switch (ccb->ccb_h.func_code)
1826285809Sscottl  {
1827285809Sscottl  case XPT_PATH_INQ:
1828285809Sscottl  {
1829285809Sscottl    struct ccb_pathinq *cpi;
1830285809Sscottl
1831285809Sscottl    /* See architecure book p180*/
1832285809Sscottl    cpi = &ccb->cpi;
1833285809Sscottl    cpi->version_num = 1;
1834285809Sscottl    cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_16;
1835285809Sscottl    cpi->target_sprt = 0;
1836285809Sscottl    cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
1837285809Sscottl    cpi->hba_eng_cnt = 0;
1838285809Sscottl    cpi->max_target = maxTargets - 1;
1839285809Sscottl    cpi->max_lun = AGTIAPI_MAX_LUN;
1840285809Sscottl    cpi->maxio = 1024 *1024; /* Max supported I/O size, in bytes. */
1841285809Sscottl    cpi->initiator_id = 255;
1842285809Sscottl    strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1843285809Sscottl    strncpy(cpi->hba_vid, "PMC", HBA_IDLEN);
1844285809Sscottl    strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1845285809Sscottl    cpi->unit_number = cam_sim_unit(sim);
1846285809Sscottl    cpi->bus_id = cam_sim_bus(sim);
1847285809Sscottl    // rate is set when XPT_GET_TRAN_SETTINGS is processed
1848285809Sscottl    cpi->base_transfer_speed = 150000;
1849285809Sscottl    cpi->transport = XPORT_SAS;
1850285809Sscottl    cpi->transport_version = 0;
1851285809Sscottl    cpi->protocol = PROTO_SCSI;
1852285809Sscottl    cpi->protocol_version = SCSI_REV_SPC3;
1853285809Sscottl    cpi->ccb_h.status = CAM_REQ_CMP;
1854285809Sscottl    break;
1855285809Sscottl  }
1856285809Sscottl  case XPT_GET_TRAN_SETTINGS:
1857285809Sscottl  {
1858285809Sscottl    struct ccb_trans_settings	*cts;
1859285809Sscottl    struct ccb_trans_settings_sas *sas;
1860285809Sscottl    struct ccb_trans_settings_scsi	*scsi;
1861285809Sscottl
1862285809Sscottl    if ( pmcsc->flags & AGTIAPI_SHUT_DOWN )
1863285809Sscottl    {
1864285809Sscottl      return;
1865285809Sscottl    }
1866285809Sscottl
1867285809Sscottl    cts = &ccb->cts;
1868285809Sscottl    sas = &ccb->cts.xport_specific.sas;
1869285809Sscottl    scsi = &cts->proto_specific.scsi;
1870285809Sscottl
1871285809Sscottl    cts->protocol = PROTO_SCSI;
1872285809Sscottl    cts->protocol_version = SCSI_REV_SPC3;
1873285809Sscottl    cts->transport = XPORT_SAS;
1874285809Sscottl    cts->transport_version = 0;
1875285809Sscottl
1876285809Sscottl    sas->valid = CTS_SAS_VALID_SPEED;
1877285809Sscottl
1878285809Sscottl    /* this sets the "MB/s transfers" */
1879285809Sscottl    if (pmcsc != NULL && targetID >= 0 && targetID < maxTargets)
1880285809Sscottl    {
1881285809Sscottl      if (pmcsc->pWWNList != NULL)
1882285809Sscottl      {
1883285809Sscottl        TID = INDEX(pmcsc, targetID);
1884285809Sscottl        if (TID < maxTargets)
1885285809Sscottl        {
1886285809Sscottl          pDevHandle = pmcsc->pDevList[TID].pDevHandle;
1887285809Sscottl        }
1888285809Sscottl      }
1889285809Sscottl    }
1890285809Sscottl    if (pDevHandle)
1891285809Sscottl    {
1892285809Sscottl      tiINIGetDeviceInfo( &pmcsc->tiRoot, pDevHandle, &devInfo );
1893285809Sscottl      switch (devInfo.info.devType_S_Rate & 0xF)
1894285809Sscottl      {
1895285809Sscottl        case 0x8: speed = 150000;
1896285809Sscottl          break;
1897285809Sscottl        case 0x9: speed = 300000;
1898285809Sscottl          break;
1899285809Sscottl        case 0xA: speed = 600000;
1900285809Sscottl          break;
1901285809Sscottl        case 0xB: speed = 1200000;
1902285809Sscottl          break;
1903285809Sscottl        default:  speed = 150000;
1904285809Sscottl          break;
1905285809Sscottl      }
1906285809Sscottl    }
1907285809Sscottl    sas->bitrate      = speed;
1908285809Sscottl    scsi->valid       = CTS_SCSI_VALID_TQ;
1909285809Sscottl    scsi->flags       = CTS_SCSI_FLAGS_TAG_ENB;
1910285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
1911285809Sscottl    break;
1912285809Sscottl  }
1913285809Sscottl  case XPT_RESET_BUS:
1914285809Sscottl  {
1915285809Sscottl    lRetVal = agtiapi_eh_HostReset( pmcsc, ccb ); // usually works first time
1916285809Sscottl    if ( SUCCESS == lRetVal )
1917285809Sscottl    {
1918285809Sscottl      AGTIAPI_PRINTK( "agtiapi_cam_action: bus reset success.\n" );
1919285809Sscottl    }
1920285809Sscottl    else
1921285809Sscottl    {
1922285809Sscottl      AGTIAPI_PRINTK( "agtiapi_cam_action: bus reset failed.\n" );
1923285809Sscottl    }
1924285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
1925285809Sscottl    break;
1926285809Sscottl  }
1927285809Sscottl  case XPT_RESET_DEV:
1928285809Sscottl  {
1929285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
1930285809Sscottl    break;
1931285809Sscottl  }
1932285809Sscottl  case XPT_ABORT:
1933285809Sscottl  {
1934285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
1935285809Sscottl    break;
1936285809Sscottl  }
1937285809Sscottl#if __FreeBSD_version >= 900026
1938285809Sscottl  case XPT_SMP_IO:
1939285809Sscottl  {
1940285809Sscottl    agtiapi_QueueSMP( pmcsc, ccb );
1941285809Sscottl    return;
1942285809Sscottl  }
1943285809Sscottl#endif /* __FreeBSD_version >= 900026 */
1944285809Sscottl  case XPT_SCSI_IO:
1945285809Sscottl  {
1946285809Sscottl    if(pmcsc->dev_scan == agFALSE)
1947285809Sscottl    {
1948285809Sscottl       ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1949285809Sscottl       break;
1950285809Sscottl    }
1951285809Sscottl    if (pmcsc->flags & AGTIAPI_SHUT_DOWN)
1952285809Sscottl    {
1953285809Sscottl      AGTIAPI_PRINTK( "agtiapi_cam_action: shutdown, XPT_SCSI_IO 0x%x\n",
1954285809Sscottl                      XPT_SCSI_IO );
1955285809Sscottl      ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1956285809Sscottl      break;
1957285809Sscottl    }
1958285809Sscottl    else
1959285809Sscottl    {
1960285809Sscottl      AGTIAPI_IO( "agtiapi_cam_action: Zero XPT_SCSI_IO 0x%x, doing IOs\n",
1961285809Sscottl                  XPT_SCSI_IO );
1962285809Sscottl      agtiapi_QueueCmnd_( pmcsc, ccb );
1963285809Sscottl      return;
1964285809Sscottl    }
1965285809Sscottl  }
1966285809Sscottl
1967285809Sscottl  case XPT_CALC_GEOMETRY:
1968285809Sscottl  {
1969285809Sscottl	  cam_calc_geometry(&ccb->ccg, 1);
1970285809Sscottl	  ccb->ccb_h.status = CAM_REQ_CMP;
1971285809Sscottl	  break;
1972285809Sscottl  }
1973285809Sscottl  default:
1974285809Sscottl  {
1975285809Sscottl    /*
1976285809Sscottl      XPT_SET_TRAN_SETTINGS
1977285809Sscottl    */
1978285809Sscottl    AGTIAPI_IO( "agtiapi_cam_action: default function code 0x%x\n",
1979285809Sscottl                ccb->ccb_h.func_code );
1980285809Sscottl    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1981285809Sscottl    break;
1982285809Sscottl  }
1983285809Sscottl  } /* switch */
1984285809Sscottl  xpt_done(ccb);
1985285809Sscottl}
1986285809Sscottl
1987285809Sscottl
1988285809Sscottl/******************************************************************************
1989285809Sscottlagtiapi_GetCCB()
1990285809Sscottl
1991285809SscottlPurpose:
1992285809Sscottl  Get a ccb from free list or allocate a new one
1993285809SscottlParameters:
1994285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA structure
1995285809SscottlReturn:
1996285809Sscottl  Pointer to a ccb structure, or NULL if not available
1997285809SscottlNote:
1998285809Sscottl******************************************************************************/
1999285809SscottlSTATIC pccb_t agtiapi_GetCCB( struct agtiapi_softc *pmcsc )
2000285809Sscottl{
2001285809Sscottl  pccb_t pccb;
2002285809Sscottl
2003285809Sscottl  AGTIAPI_IO( "agtiapi_GetCCB: start\n" );
2004285809Sscottl
2005285809Sscottl  AG_LOCAL_LOCK( &pmcsc->ccbLock );
2006285809Sscottl
2007285809Sscottl  /* get the ccb from the head of the free list */
2008285809Sscottl  if ((pccb = (pccb_t)pmcsc->ccbFreeList) != NULL)
2009285809Sscottl  {
2010285809Sscottl    pmcsc->ccbFreeList = (caddr_t *)pccb->pccbNext;
2011285809Sscottl    pccb->pccbNext = NULL;
2012285809Sscottl    pccb->flags = ACTIVE;
2013285809Sscottl    pccb->startTime = 0;
2014285809Sscottl    pmcsc->activeCCB++;
2015285809Sscottl    AGTIAPI_IO( "agtiapi_GetCCB: re-allocated ccb %p\n", pccb );
2016285809Sscottl  }
2017285809Sscottl  else
2018285809Sscottl  {
2019285809Sscottl    AGTIAPI_PRINTK( "agtiapi_GetCCB: kmalloc ERROR - no ccb allocated\n" );
2020285809Sscottl  }
2021285809Sscottl
2022285809Sscottl  AG_LOCAL_UNLOCK( &pmcsc->ccbLock );
2023285809Sscottl  return pccb;
2024285809Sscottl}
2025285809Sscottl
2026285809Sscottl/******************************************************************************
2027285809Sscottlagtiapi_QueueCmnd_()
2028285809Sscottl
2029285809SscottlPurpose:
2030285809Sscottl  Calls for sending CCB and excuting on HBA.
2031285809SscottlParameters:
2032285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2033285809Sscottl  union ccb * ccb (IN)      Pointer to CAM ccb data structure
2034285809SscottlReturn:
2035285809Sscottl  0 - Command is pending to execute
2036285809Sscottl  1 - Command returned without further process
2037285809SscottlNote:
2038285809Sscottl******************************************************************************/
2039285809Sscottlint agtiapi_QueueCmnd_(struct agtiapi_softc *pmcsc, union ccb * ccb)
2040285809Sscottl{
2041285809Sscottl  struct ccb_scsiio *csio = &ccb->csio;
2042285809Sscottl  pccb_t     pccb = agNULL; // call dequeue
2043285809Sscottl  int        status = tiSuccess;
2044285809Sscottl  U32        Channel = CMND_TO_CHANNEL(ccb);
2045285809Sscottl  U32        TID     = CMND_TO_TARGET(ccb);
2046285809Sscottl  U32        LUN     = CMND_TO_LUN(ccb);
2047285809Sscottl
2048285809Sscottl  AGTIAPI_IO( "agtiapi_QueueCmnd_: start\n" );
2049285809Sscottl
2050285809Sscottl  /* no support for CBD > 16 */
2051285809Sscottl  if (csio->cdb_len > 16)
2052285809Sscottl  {
2053285809Sscottl    AGTIAPI_PRINTK( "agtiapi_QueueCmnd_: unsupported CDB length %d\n",
2054285809Sscottl                    csio->cdb_len );
2055285809Sscottl    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2056285809Sscottl    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2057285809Sscottl    ccb->ccb_h.status |= CAM_REQ_INVALID;//CAM_REQ_CMP;
2058285809Sscottl    xpt_done(ccb);
2059285809Sscottl    return tiError;
2060285809Sscottl  }
2061285809Sscottl  if (TID < 0 || TID >= maxTargets)
2062285809Sscottl  {
2063285809Sscottl    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: INVALID TID ERROR\n");
2064285809Sscottl    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2065285809Sscottl    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2066285809Sscottl    ccb->ccb_h.status |= CAM_DEV_NOT_THERE;//CAM_REQ_CMP;
2067285809Sscottl    xpt_done(ccb);
2068285809Sscottl    return tiError;
2069285809Sscottl  }
2070285809Sscottl  /* get a ccb */
2071285809Sscottl  if ((pccb = agtiapi_GetCCB(pmcsc)) == NULL)
2072285809Sscottl  {
2073285809Sscottl    ag_device_t *targ;
2074285809Sscottl    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: GetCCB ERROR\n");
2075285809Sscottl    if (pmcsc != NULL)
2076285809Sscottl    {
2077285809Sscottl      TID = INDEX(pmcsc, TID);
2078285809Sscottl      targ   = &pmcsc->pDevList[TID];
2079285809Sscottl    }
2080285809Sscottl    if (targ != NULL)
2081285809Sscottl	{
2082285809Sscottl      agtiapi_adjust_queue_depth(ccb->ccb_h.path,targ->qdepth);
2083285809Sscottl	}
2084285809Sscottl    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2085285809Sscottl    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2086285809Sscottl    ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2087285809Sscottl    xpt_done(ccb);
2088285809Sscottl    return tiBusy;
2089285809Sscottl  }
2090285809Sscottl  pccb->pmcsc = pmcsc;
2091285809Sscottl  /* initialize Command Control Block (CCB) */
2092285809Sscottl  pccb->targetId   = TID;
2093285809Sscottl  pccb->lun        = LUN;
2094285809Sscottl  pccb->channel    = Channel;
2095285809Sscottl  pccb->ccb        = ccb; /* for struct scsi_cmnd */
2096285809Sscottl  pccb->senseLen   = csio->sense_len;
2097285809Sscottl  pccb->startTime  = ticks;
2098285809Sscottl  pccb->pSenseData = (caddr_t) &csio->sense_data;
2099285809Sscottl  pccb->tiSuperScsiRequest.flags = 0;
2100285809Sscottl
2101285809Sscottl  /* each channel is reserved for different addr modes */
2102285809Sscottl  pccb->addrMode = agtiapi_AddrModes[Channel];
2103285809Sscottl
2104285809Sscottl  status = agtiapi_PrepareSGList(pmcsc, pccb);
2105285809Sscottl  if (status != tiSuccess)
2106285809Sscottl  {
2107285809Sscottl    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: agtiapi_PrepareSGList failure\n");
2108285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
2109285809Sscottl    if (status == tiReject)
2110285809Sscottl    {
2111285809Sscottl      ccb->ccb_h.status = CAM_REQ_INVALID;
2112285809Sscottl    }
2113285809Sscottl    else
2114285809Sscottl    {
2115285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP;
2116285809Sscottl    }
2117285809Sscottl    xpt_done( ccb );
2118285809Sscottl    return tiError;
2119285809Sscottl  }
2120285809Sscottl  return status;
2121285809Sscottl}
2122285809Sscottl
2123285809Sscottl/******************************************************************************
2124285809Sscottlagtiapi_DumpCDB()
2125285809Sscottl
2126285809SscottlPurpose:
2127285809Sscottl  Prints out CDB
2128285809SscottlParameters:
2129285809Sscottl  const char *ptitle (IN)  A string to be printed
2130285809Sscottl  ccb_t *pccb (IN)         A pointer to the driver's own CCB, not CAM's CCB
2131285809SscottlReturn:
2132285809SscottlNote:
2133285809Sscottl******************************************************************************/
2134285809SscottlSTATIC void agtiapi_DumpCDB(const char *ptitle, ccb_t *pccb)
2135285809Sscottl{
2136285809Sscottl  union ccb *ccb;
2137285809Sscottl  struct ccb_scsiio *csio;
2138285809Sscottl  bit8  cdb[64];
2139285809Sscottl  int len;
2140285809Sscottl
2141285809Sscottl  if (pccb == NULL)
2142285809Sscottl  {
2143285809Sscottl    printf( "agtiapi_DumpCDB: no pccb here \n" );
2144285809Sscottl    panic("agtiapi_DumpCDB: pccb is NULL. called from %s\n", ptitle);
2145285809Sscottl    return;
2146285809Sscottl  }
2147285809Sscottl  ccb = pccb->ccb;
2148285809Sscottl  if (ccb == NULL)
2149285809Sscottl  {
2150285809Sscottl    printf( "agtiapi_DumpCDB: no ccb here \n" );
2151285809Sscottl    panic( "agtiapi_DumpCDB: pccb %p ccb %p flags %d ccb NULL! "
2152285809Sscottl           "called from %s\n",
2153285809Sscottl           pccb, pccb->ccb, pccb->flags, ptitle );
2154285809Sscottl    return;
2155285809Sscottl  }
2156285809Sscottl  csio = &ccb->csio;
2157285809Sscottl  if (csio == NULL)
2158285809Sscottl  {
2159285809Sscottl    printf( "agtiapi_DumpCDB: no csio here \n" );
2160285809Sscottl    panic( "agtiapi_DumpCDB: pccb%p ccb%p flags%d csio NULL! called from %s\n",
2161285809Sscottl           pccb, pccb->ccb, pccb->flags, ptitle );
2162285809Sscottl    return;
2163285809Sscottl  }
2164285809Sscottl  len = MIN(64, csio->cdb_len);
2165285809Sscottl  if (csio->ccb_h.flags & CAM_CDB_POINTER)
2166285809Sscottl  {
2167285809Sscottl    bcopy(csio->cdb_io.cdb_ptr, &cdb[0], len);
2168285809Sscottl  }
2169285809Sscottl  else
2170285809Sscottl  {
2171285809Sscottl    bcopy(csio->cdb_io.cdb_bytes, &cdb[0], len);
2172285809Sscottl  }
2173285809Sscottl
2174285809Sscottl  AGTIAPI_IO( "agtiapi_DumpCDB: pccb%p CDB0x%x csio->cdb_len %d"
2175285809Sscottl              " len %d from %s\n",
2176285809Sscottl              pccb, cdb[0],
2177285809Sscottl              csio->cdb_len,
2178285809Sscottl              len,
2179285809Sscottl              ptitle );
2180285809Sscottl  return;
2181285809Sscottl}
2182285809Sscottl
2183285809Sscottl/******************************************************************************
2184285809Sscottlagtiapi_DoSoftReset()
2185285809Sscottl
2186285809SscottlPurpose:
2187285809Sscottl  Do card reset
2188285809SscottlParameters:
2189285809Sscottl  *data (IN)               point to pmcsc (struct agtiapi_softc *)
2190285809SscottlReturn:
2191285809SscottlNote:
2192285809Sscottl******************************************************************************/
2193285809Sscottlint agtiapi_DoSoftReset (struct agtiapi_softc *pmcsc)
2194285809Sscottl{
2195285809Sscottl  int  ret;
2196285809Sscottl  unsigned long flags;
2197285809Sscottl
2198285809Sscottl  pmcsc->flags |=  AGTIAPI_SOFT_RESET;
2199285809Sscottl  AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
2200285809Sscottl  ret = agtiapi_ResetCard( pmcsc, &flags );
2201285809Sscottl  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
2202285809Sscottl
2203285809Sscottl  if( ret != AGTIAPI_SUCCESS )
2204285809Sscottl    return tiError;
2205285809Sscottl
2206285809Sscottl  return SUCCESS;
2207285809Sscottl}
2208285809Sscottl
2209285809Sscottl/******************************************************************************
2210285809Sscottlagtiapi_CheckIOTimeout()
2211285809Sscottl
2212285809SscottlPurpose:
2213285809Sscottl  Timeout function for SCSI IO or TM
2214285809SscottlParameters:
2215285809Sscottl  *data (IN)               point to pCard (ag_card_t *)
2216285809SscottlReturn:
2217285809SscottlNote:
2218285809Sscottl******************************************************************************/
2219285809SscottlSTATIC void agtiapi_CheckIOTimeout(void *data)
2220285809Sscottl{
2221285809Sscottl  U32       status = AGTIAPI_SUCCESS;
2222285809Sscottl  ccb_t *pccb;
2223285809Sscottl  struct agtiapi_softc *pmcsc;
2224285809Sscottl  pccb_t pccb_curr;
2225285809Sscottl  pccb_t pccb_next;
2226285809Sscottl  pmcsc = (struct agtiapi_softc *)data;
2227285809Sscottl
2228285809Sscottl  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Enter\n");
2229285809Sscottl
2230285809Sscottl  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Active CCB %d\n", pmcsc->activeCCB);
2231285809Sscottl
2232285809Sscottl  pccb = (pccb_t)pmcsc->ccbChainList;
2233285809Sscottl
2234285809Sscottl  /* if link is down, do nothing */
2235285809Sscottl  if ((pccb == NULL) || (pmcsc->activeCCB == 0))
2236285809Sscottl  {
2237285809Sscottl  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: goto restart_timer\n");
2238285809Sscottl    goto restart_timer;
2239285809Sscottl  }
2240285809Sscottl
2241285809Sscottl  AG_SPIN_LOCK_IRQ(agtiapi_host_lock, flags);
2242285809Sscottl  if (pmcsc->flags & AGTIAPI_SHUT_DOWN)
2243285809Sscottl    goto ext;
2244285809Sscottl
2245285809Sscottl  pccb_curr = pccb;
2246285809Sscottl
2247285809Sscottl  /* Walk thorugh the IO Chain linked list to find the pending io */
2248285809Sscottl  /* Set the TM flag based on the pccb type, i.e SCSI IO or TM cmd */
2249285809Sscottl  while (pccb_curr != NULL)
2250285809Sscottl  {
2251285809Sscottl    /* start from 1st ccb in the chain */
2252285809Sscottl    pccb_next = pccb_curr->pccbChainNext;
2253285809Sscottl    if( (pccb_curr->flags == 0) || (pccb_curr->tiIORequest.tdData == NULL) ||
2254285809Sscottl        (pccb_curr->startTime == 0) /* && (pccb->startTime == 0) */)
2255285809Sscottl    {
2256285809Sscottl      //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: move to next element\n");
2257285809Sscottl    }
2258285809Sscottl    else if ( ( (ticks-pccb_curr->startTime) >= ag_timeout_secs ) &&
2259285809Sscottl              !(pccb_curr->flags & TIMEDOUT) )
2260285809Sscottl    {
2261285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout: pccb %p timed out, call TM "
2262285809Sscottl		      "function -- flags=%x startTime=%ld tdData = %p\n",
2263285809Sscottl		      pccb_curr, pccb_curr->flags, pccb->startTime,
2264285809Sscottl		      pccb_curr->tiIORequest.tdData );
2265285809Sscottl      pccb_curr->flags |= TIMEDOUT;
2266285809Sscottl      status = agtiapi_StartTM(pmcsc, pccb_curr);
2267285809Sscottl      if (status == AGTIAPI_SUCCESS)
2268285809Sscottl      {
2269285809Sscottl        AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout: TM Request sent with "
2270285809Sscottl                        "success\n" );
2271285809Sscottl        goto restart_timer;
2272285809Sscottl      }
2273285809Sscottl      else
2274285809Sscottl      {
2275285809Sscottl#ifdef AGTIAPI_LOCAL_RESET
2276285809Sscottl        /* abort request did not go through */
2277285809Sscottl        AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Abort request failed\n");
2278285809Sscottl        /* TODO: call Soft reset here */
2279285809Sscottl        AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout:in agtiapi_CheckIOTimeout() "
2280285809Sscottl                        "abort request did not go thru ==> soft reset#7, then "
2281285809Sscottl                        "restart timer\n" );
2282285809Sscottl        agtiapi_DoSoftReset (pmcsc);
2283285809Sscottl        goto restart_timer;
2284285809Sscottl#endif
2285285809Sscottl      }
2286285809Sscottl    }
2287285809Sscottl    pccb_curr = pccb_next;
2288285809Sscottl  }
2289285809Sscottlrestart_timer:
2290285809Sscottl  callout_reset(&pmcsc->IO_timer, 1*hz, agtiapi_CheckIOTimeout, pmcsc);
2291285809Sscottl
2292285809Sscottlext:
2293285809Sscottl  AG_SPIN_UNLOCK_IRQ(agtiapi_host_lock, flags);
2294285809Sscottl  return;
2295285809Sscottl}
2296285809Sscottl
2297285809Sscottl/******************************************************************************
2298285809Sscottlagtiapi_StartTM()
2299285809Sscottl
2300285809SscottlPurpose:
2301285809Sscottl  DDI calls for aborting outstanding IO command
2302285809SscottlParameters:
2303285809Sscottl  struct scsi_cmnd *pccb (IN) Pointer to the command to be aborted
2304285809Sscottl  unsigned long flags (IN/out) spinlock flags used in locking from
2305285809Sscottl                              calling layers
2306285809SscottlReturn:
2307285809Sscottl  AGTIAPI_SUCCESS  - success
2308285809Sscottl  AGTIAPI_FAIL     - fail
2309285809Sscottl******************************************************************************/
2310285809Sscottlint
2311285809Sscottlagtiapi_StartTM(struct agtiapi_softc *pCard, ccb_t *pccb)
2312285809Sscottl{
2313285809Sscottl  ccb_t     *pTMccb = NULL;
2314285809Sscottl  U32       status = AGTIAPI_SUCCESS;
2315285809Sscottl  ag_device_t      *pDevice = NULL;
2316285809Sscottl  U32       TMstatus = tiSuccess;
2317285809Sscottl  AGTIAPI_PRINTK( "agtiapi_StartTM: pccb %p, pccb->flags %x\n",
2318285809Sscottl                  pccb, pccb->flags );
2319285809Sscottl  if (pccb == NULL)
2320285809Sscottl  {
2321285809Sscottl    AGTIAPI_PRINTK("agtiapi_StartTM: %p not found\n",pccb);
2322285809Sscottl    status = AGTIAPI_SUCCESS;
2323285809Sscottl    goto ext;
2324285809Sscottl  }
2325285809Sscottl  if (!pccb->tiIORequest.tdData)
2326285809Sscottl  {
2327285809Sscottl    /* should not be the case */
2328285809Sscottl    AGTIAPI_PRINTK("agtiapi_StartTM: ccb %p flag 0x%x tid %d no tdData "
2329285809Sscottl                   "ERROR\n", pccb, pccb->flags, pccb->targetId);
2330285809Sscottl    status = AGTIAPI_FAIL;
2331285809Sscottl  }
2332285809Sscottl  else
2333285809Sscottl  {
2334285809Sscottl    /* If timedout CCB is TM_ABORT_TASK command, issue LocalAbort first to
2335285809Sscottl       clear pending TM_ABORT_TASK */
2336285809Sscottl    /* Else Device State will not be put back to Operational, (refer FW) */
2337285809Sscottl    if (pccb->flags & TASK_MANAGEMENT)
2338285809Sscottl    {
2339285809Sscottl      if (tiINIIOAbort(&pCard->tiRoot, &pccb->tiIORequest) != tiSuccess)
2340285809Sscottl      {
2341285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: LocalAbort Request for Abort_TASK "
2342285809Sscottl                        "TM failed\n" );
2343285809Sscottl        /* TODO: call Soft reset here */
2344285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: in agtiapi_StartTM() abort "
2345285809Sscottl			"tiINIIOAbort() failed ==> soft reset#8\n" );
2346285809Sscottl        agtiapi_DoSoftReset( pCard );
2347285809Sscottl      }
2348285809Sscottl      else
2349285809Sscottl      {
2350285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: LocalAbort for Abort_TASK TM "
2351285809Sscottl                        "Request sent\n" );
2352285809Sscottl        status = AGTIAPI_SUCCESS;
2353285809Sscottl      }
2354285809Sscottl    }
2355285809Sscottl    else
2356285809Sscottl    {
2357285809Sscottl      /* get a ccb */
2358285809Sscottl      if ((pTMccb = agtiapi_GetCCB(pCard)) == NULL)
2359285809Sscottl      {
2360285809Sscottl        AGTIAPI_PRINTK("agtiapi_StartTM: TM resource unavailable!\n");
2361285809Sscottl        status = AGTIAPI_FAIL;
2362285809Sscottl        goto ext;
2363285809Sscottl      }
2364285809Sscottl      pTMccb->pmcsc = pCard;
2365285809Sscottl      pTMccb->targetId = pccb->targetId;
2366285809Sscottl      pTMccb->devHandle = pccb->devHandle;
2367285809Sscottl      if (pTMccb->targetId >= pCard->devDiscover)
2368285809Sscottl      {
2369285809Sscottl        AGTIAPI_PRINTK("agtiapi_StartTM: Incorrect dev Id in TM!\n");
2370285809Sscottl        status = AGTIAPI_FAIL;
2371285809Sscottl        goto ext;
2372285809Sscottl      }
2373285809Sscottl      if (pTMccb->targetId < 0 || pTMccb->targetId >= maxTargets)
2374285809Sscottl      {
2375285809Sscottl        return AGTIAPI_FAIL;
2376285809Sscottl      }
2377285809Sscottl      if (INDEX(pCard, pTMccb->targetId) >= maxTargets)
2378285809Sscottl      {
2379285809Sscottl        return AGTIAPI_FAIL;
2380285809Sscottl      }
2381285809Sscottl      pDevice = &pCard->pDevList[INDEX(pCard, pTMccb->targetId)];
2382285809Sscottl      if ((pDevice == NULL) || !(pDevice->flags & ACTIVE))
2383285809Sscottl      {
2384285809Sscottl        return AGTIAPI_FAIL;
2385285809Sscottl      }
2386285809Sscottl
2387285809Sscottl      /* save pending io to issue local abort at Task mgmt CB */
2388285809Sscottl      pTMccb->pccbIO = pccb;
2389285809Sscottl      AGTIAPI_PRINTK( "agtiapi_StartTM: pTMccb %p flag %x tid %d via TM "
2390285809Sscottl                      "request !\n",
2391285809Sscottl                      pTMccb, pTMccb->flags, pTMccb->targetId );
2392285809Sscottl      pTMccb->flags &= ~(TASK_SUCCESS | ACTIVE);
2393285809Sscottl      pTMccb->flags |= TASK_MANAGEMENT;
2394285809Sscottl      TMstatus = tiINITaskManagement(&pCard->tiRoot,
2395285809Sscottl                              pccb->devHandle,
2396285809Sscottl                              AG_ABORT_TASK,
2397285809Sscottl                              &pccb->tiSuperScsiRequest.scsiCmnd.lun,
2398285809Sscottl                              &pccb->tiIORequest,
2399285809Sscottl                              &pTMccb->tiIORequest);
2400285809Sscottl      if (TMstatus == tiSuccess)
2401285809Sscottl      {
2402285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request success ccb "
2403285809Sscottl                        "%p, pTMccb %p\n",
2404285809Sscottl                        pccb, pTMccb );
2405285809Sscottl        pTMccb->startTime = ticks;
2406285809Sscottl        status = AGTIAPI_SUCCESS;
2407285809Sscottl      }
2408285809Sscottl      else if (TMstatus == tiIONoDevice)
2409285809Sscottl      {
2410285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request tiIONoDevice ccb "
2411285809Sscottl                        "%p, pTMccb %p\n",
2412285809Sscottl                        pccb, pTMccb );
2413285809Sscottl        status = AGTIAPI_SUCCESS;
2414285809Sscottl      }
2415285809Sscottl      else
2416285809Sscottl      {
2417285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request failed ccb %p, "
2418285809Sscottl                        "pTMccb %p\n",
2419285809Sscottl                        pccb, pTMccb );
2420285809Sscottl        status = AGTIAPI_FAIL;
2421285809Sscottl        agtiapi_FreeTMCCB(pCard, pTMccb);
2422285809Sscottl        /* TODO */
2423285809Sscottl        /* call TM_TARGET_RESET */
2424285809Sscottl      }
2425285809Sscottl    }
2426285809Sscottl  }
2427285809Sscottl  ext:
2428285809Sscottl  AGTIAPI_PRINTK("agtiapi_StartTM: return %d flgs %x\n", status,
2429285809Sscottl                 (pccb) ? pccb->flags : -1);
2430285809Sscottl  return status;
2431285809Sscottl} /* agtiapi_StartTM */
2432285809Sscottl
2433285809Sscottl#if __FreeBSD_version > 901000
2434285809Sscottl/******************************************************************************
2435285809Sscottlagtiapi_PrepareSGList()
2436285809Sscottl
2437285809SscottlPurpose:
2438285809Sscottl  This function prepares scatter-gather list for the given ccb
2439285809SscottlParameters:
2440285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2441285809Sscottl  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
2442285809SscottlReturn:
2443285809Sscottl  0 - success
2444285809Sscottl  1 - failure
2445285809Sscottl
2446285809SscottlNote:
2447285809Sscottl******************************************************************************/
2448285809Sscottlstatic int agtiapi_PrepareSGList(struct agtiapi_softc *pmcsc, ccb_t *pccb)
2449285809Sscottl{
2450285809Sscottl  union ccb *ccb = pccb->ccb;
2451285809Sscottl  struct ccb_scsiio *csio = &ccb->csio;
2452285809Sscottl  struct ccb_hdr *ccbh = &ccb->ccb_h;
2453285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGList: start\n" );
2454285809Sscottl
2455285809Sscottl//  agtiapi_DumpCDB("agtiapi_PrepareSGList", pccb);
2456285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGList: dxfer_len %d\n", csio->dxfer_len );
2457285809Sscottl
2458285809Sscottl  if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE)
2459285809Sscottl  {
2460285809Sscottl	switch((ccbh->flags & CAM_DATA_MASK))
2461285809Sscottl    	{
2462285809Sscottl          int error;
2463285809Sscottl          struct bus_dma_segment seg;
2464285809Sscottl	  case CAM_DATA_VADDR:
2465285809Sscottl        /* Virtual address that needs to translated into one or more physical address ranges. */
2466285809Sscottl          //  int error;
2467285809Sscottl            //  AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
2468285809Sscottl            AGTIAPI_IO( "agtiapi_PrepareSGList: virtual address\n" );
2469285809Sscottl            error = bus_dmamap_load( pmcsc->buffer_dmat,
2470285809Sscottl                                 pccb->CCB_dmamap,
2471285809Sscottl                                 csio->data_ptr,
2472285809Sscottl                                 csio->dxfer_len,
2473285809Sscottl                                 agtiapi_PrepareSGListCB,
2474285809Sscottl                                 pccb,
2475285809Sscottl                                 BUS_DMA_NOWAIT/* 0 */ );
2476285809Sscottl            //  AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
2477285809Sscottl
2478285809Sscottl	    if (error == EINPROGRESS)
2479285809Sscottl	    {
2480285809Sscottl          /* So as to maintain ordering, freeze the controller queue until our mapping is returned. */
2481285809Sscottl          AGTIAPI_PRINTK("agtiapi_PrepareSGList: EINPROGRESS\n");
2482285809Sscottl          xpt_freeze_simq(pmcsc->sim, 1);
2483285809Sscottl          pmcsc->SimQFrozen = agTRUE;
2484285809Sscottl          ccbh->status |= CAM_RELEASE_SIMQ;
2485285809Sscottl        }
2486285809Sscottl	break;
2487285809Sscottl	case CAM_DATA_PADDR:
2488285809Sscottl	    /* We have been given a pointer to single physical buffer. */
2489285809Sscottl	    /* pccb->tiSuperScsiRequest.sglVirtualAddr = seg.ds_addr; */
2490285809Sscottl          //struct bus_dma_segment seg;
2491285809Sscottl          AGTIAPI_PRINTK("agtiapi_PrepareSGList: physical address\n");
2492285809Sscottl          seg.ds_addr =
2493285809Sscottl            (bus_addr_t)(vm_offset_t)csio->data_ptr;
2494285809Sscottl             seg.ds_len = csio->dxfer_len;
2495285809Sscottl             // * 0xFF to be defined
2496285809Sscottl             agtiapi_PrepareSGListCB(pccb, &seg, 1, 0xAABBCCDD);
2497285809Sscottl	     break;
2498285809Sscottl	default:
2499285809Sscottl           AGTIAPI_PRINTK("agtiapi_PrepareSGList: unexpected case\n");
2500285809Sscottl           return tiReject;
2501285809Sscottl    }
2502285809Sscottl  }
2503285809Sscottl  else
2504285809Sscottl  {
2505285809Sscottl    agtiapi_PrepareSGListCB(pccb, NULL, 0, 0xAAAAAAAA);
2506285809Sscottl  }
2507285809Sscottl  return tiSuccess;
2508285809Sscottl}
2509285809Sscottl#else
2510285809Sscottl/******************************************************************************
2511285809Sscottlagtiapi_PrepareSGList()
2512285809Sscottl
2513285809SscottlPurpose:
2514285809Sscottl  This function prepares scatter-gather list for the given ccb
2515285809SscottlParameters:
2516285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2517285809Sscottl  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
2518285809SscottlReturn:
2519285809Sscottl  0 - success
2520285809Sscottl  1 - failure
2521285809Sscottl
2522285809SscottlNote:
2523285809Sscottl******************************************************************************/
2524285809Sscottlstatic int agtiapi_PrepareSGList(struct agtiapi_softc *pmcsc, ccb_t *pccb)
2525285809Sscottl{
2526285809Sscottl  union ccb *ccb = pccb->ccb;
2527285809Sscottl  struct ccb_scsiio *csio = &ccb->csio;
2528285809Sscottl  struct ccb_hdr *ccbh = &ccb->ccb_h;
2529285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGList: start\n" );
2530285809Sscottl//  agtiapi_DumpCDB("agtiapi_PrepareSGList", pccb);
2531285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGList: dxfer_len %d\n", csio->dxfer_len );
2532285809Sscottl
2533285809Sscottl  if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE)
2534285809Sscottl  {
2535285809Sscottl    if ((ccbh->flags & CAM_SCATTER_VALID) == 0)
2536285809Sscottl    {
2537285809Sscottl      /* We've been given a pointer to a single buffer. */
2538285809Sscottl      if ((ccbh->flags & CAM_DATA_PHYS) == 0)
2539285809Sscottl      {
2540285809Sscottl        /* Virtual address that needs to translated into one or more physical address ranges. */
2541285809Sscottl        int error;
2542285809Sscottl      //  AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
2543285809Sscottl        AGTIAPI_IO( "agtiapi_PrepareSGList: virtual address\n" );
2544285809Sscottl        error = bus_dmamap_load( pmcsc->buffer_dmat,
2545285809Sscottl                                 pccb->CCB_dmamap,
2546285809Sscottl                                 csio->data_ptr,
2547285809Sscottl                                 csio->dxfer_len,
2548285809Sscottl                                 agtiapi_PrepareSGListCB,
2549285809Sscottl                                 pccb,
2550285809Sscottl                                 BUS_DMA_NOWAIT/* 0 */ );
2551285809Sscottl      //  AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
2552285809Sscottl
2553285809Sscottl	    if (error == EINPROGRESS)
2554285809Sscottl	    {
2555285809Sscottl          /* So as to maintain ordering, freeze the controller queue until our mapping is returned. */
2556285809Sscottl          AGTIAPI_PRINTK("agtiapi_PrepareSGList: EINPROGRESS\n");
2557285809Sscottl          xpt_freeze_simq(pmcsc->sim, 1);
2558285809Sscottl          pmcsc->SimQFrozen = agTRUE;
2559285809Sscottl          ccbh->status |= CAM_RELEASE_SIMQ;
2560285809Sscottl        }
2561285809Sscottl      }
2562285809Sscottl      else
2563285809Sscottl      {
2564285809Sscottl	    /* We have been given a pointer to single physical buffer. */
2565285809Sscottl	    /* pccb->tiSuperScsiRequest.sglVirtualAddr = seg.ds_addr; */
2566285809Sscottl        struct bus_dma_segment seg;
2567285809Sscottl        AGTIAPI_PRINTK("agtiapi_PrepareSGList: physical address\n");
2568285809Sscottl        seg.ds_addr =
2569285809Sscottl          (bus_addr_t)(vm_offset_t)csio->data_ptr;
2570285809Sscottl        seg.ds_len = csio->dxfer_len;
2571285809Sscottl        // * 0xFF to be defined
2572285809Sscottl        agtiapi_PrepareSGListCB(pccb, &seg, 1, 0xAABBCCDD);
2573285809Sscottl      }
2574285809Sscottl    }
2575285809Sscottl    else
2576285809Sscottl    {
2577285809Sscottl
2578285809Sscottl      AGTIAPI_PRINTK("agtiapi_PrepareSGList: unexpected case\n");
2579285809Sscottl      return tiReject;
2580285809Sscottl    }
2581285809Sscottl  }
2582285809Sscottl  else
2583285809Sscottl  {
2584285809Sscottl    agtiapi_PrepareSGListCB(pccb, NULL, 0, 0xAAAAAAAA);
2585285809Sscottl  }
2586285809Sscottl  return tiSuccess;
2587285809Sscottl}
2588285809Sscottl
2589285809Sscottl#endif
2590285809Sscottl/******************************************************************************
2591285809Sscottlagtiapi_PrepareSGListCB()
2592285809Sscottl
2593285809SscottlPurpose:
2594285809Sscottl  Callback function for bus_dmamap_load()
2595285809Sscottl  This fuctions sends IO to LL layer.
2596285809SscottlParameters:
2597285809Sscottl  void *arg (IN)                Pointer to the HBA data structure
2598285809Sscottl  bus_dma_segment_t *segs (IN)  Pointer to dma segment
2599285809Sscottl  int nsegs (IN)                number of dma segment
2600285809Sscottl  int error (IN)                error
2601285809SscottlReturn:
2602285809SscottlNote:
2603285809Sscottl******************************************************************************/
2604285809Sscottlstatic void agtiapi_PrepareSGListCB( void *arg,
2605285809Sscottl                                     bus_dma_segment_t *segs,
2606285809Sscottl                                     int nsegs,
2607285809Sscottl                                     int error )
2608285809Sscottl{
2609285809Sscottl  pccb_t     pccb = arg;
2610285809Sscottl  union ccb *ccb = pccb->ccb;
2611285809Sscottl  struct ccb_scsiio *csio = &ccb->csio;
2612285809Sscottl
2613285809Sscottl  struct agtiapi_softc *pmcsc;
2614285809Sscottl  tiIniScsiCmnd_t *pScsiCmnd;
2615285809Sscottl  bit32 i;
2616285809Sscottl  bus_dmasync_op_t op;
2617285809Sscottl  U32_64     phys_addr;
2618285809Sscottl  U08        *CDB;
2619285809Sscottl  int        io_is_encryptable = 0;
2620285809Sscottl  unsigned long long start_lba = 0;
2621285809Sscottl  ag_device_t *pDev;
2622285809Sscottl  U32        TID     = CMND_TO_TARGET(ccb);
2623285809Sscottl
2624285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGListCB: start, nsegs %d error 0x%x\n",
2625285809Sscottl              nsegs, error );
2626285809Sscottl  pmcsc = pccb->pmcsc;
2627285809Sscottl
2628285809Sscottl  if (error != tiSuccess)
2629285809Sscottl  {
2630285809Sscottl    if (error == 0xAABBCCDD || error == 0xAAAAAAAA)
2631285809Sscottl    {
2632285809Sscottl      // do nothing
2633285809Sscottl    }
2634285809Sscottl    else
2635285809Sscottl    {
2636285809Sscottl      AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: error status 0x%x\n", error);
2637285809Sscottl      bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2638285809Sscottl      bus_dmamap_destroy(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2639285809Sscottl      agtiapi_FreeCCB(pmcsc, pccb);
2640285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP;
2641285809Sscottl      xpt_done(ccb);
2642285809Sscottl      return;
2643285809Sscottl    }
2644285809Sscottl  }
2645285809Sscottl
2646285809Sscottl  if (nsegs > AGTIAPI_MAX_DMA_SEGS)
2647285809Sscottl  {
2648285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSGListCB: over the limit. nsegs %d"
2649285809Sscottl                    " AGTIAPI_MAX_DMA_SEGS %d\n",
2650285809Sscottl                    nsegs, AGTIAPI_MAX_DMA_SEGS );
2651285809Sscottl    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2652285809Sscottl    bus_dmamap_destroy(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2653285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
2654285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
2655285809Sscottl    xpt_done(ccb);
2656285809Sscottl    return;
2657285809Sscottl  }
2658285809Sscottl
2659285809Sscottl
2660285809Sscottl  /* fill in IO information */
2661285809Sscottl  pccb->dataLen = csio->dxfer_len;
2662285809Sscottl
2663285809Sscottl  /* start fill in sgl structure */
2664285809Sscottl  if (nsegs == 1 && error == 0xAABBCCDD)
2665285809Sscottl  {
2666285809Sscottl    /* to be tested */
2667285809Sscottl    /* A single physical buffer */
2668285809Sscottl    AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: nsegs is 1\n");
2669285809Sscottl    CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, segs[0].ds_addr);
2670285809Sscottl    pccb->tiSuperScsiRequest.agSgl1.len   = htole32(pccb->dataLen);
2671285809Sscottl    pccb->tiSuperScsiRequest.agSgl1.type  = htole32(tiSgl);
2672285809Sscottl    pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)segs->ds_addr;
2673285809Sscottl    pccb->numSgElements = 1;
2674285809Sscottl  }
2675285809Sscottl  else if (nsegs == 0 && error == 0xAAAAAAAA)
2676285809Sscottl  {
2677285809Sscottl    /* no data transfer */
2678285809Sscottl    AGTIAPI_IO( "agtiapi_PrepareSGListCB: no data transfer\n" );
2679285809Sscottl    pccb->tiSuperScsiRequest.agSgl1.len = 0;
2680285809Sscottl    pccb->dataLen = 0;
2681285809Sscottl    pccb->numSgElements = 0;
2682285809Sscottl  }
2683285809Sscottl  else
2684285809Sscottl  {
2685285809Sscottl    /* virtual/logical buffer */
2686285809Sscottl    if (nsegs == 1)
2687285809Sscottl    {
2688285809Sscottl      pccb->dataLen = segs[0].ds_len;
2689285809Sscottl
2690285809Sscottl      CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, segs[0].ds_addr);
2691285809Sscottl      pccb->tiSuperScsiRequest.agSgl1.type = htole32(tiSgl);
2692285809Sscottl      pccb->tiSuperScsiRequest.agSgl1.len = htole32(segs[0].ds_len);
2693285809Sscottl      pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)csio->data_ptr;
2694285809Sscottl      pccb->numSgElements = nsegs;
2695285809Sscottl
2696285809Sscottl    }
2697285809Sscottl    else
2698285809Sscottl    {
2699285809Sscottl      pccb->dataLen = 0;
2700285809Sscottl      /* loop */
2701285809Sscottl      for (i = 0; i < nsegs; i++)
2702285809Sscottl      {
2703285809Sscottl        pccb->sgList[i].len = htole32(segs[i].ds_len);
2704285809Sscottl        CPU_TO_LE32(pccb->sgList[i], segs[i].ds_addr);
2705285809Sscottl        pccb->sgList[i].type = htole32(tiSgl);
2706285809Sscottl        pccb->dataLen += segs[i].ds_len;
2707285809Sscottl
2708285809Sscottl      } /* for */
2709285809Sscottl      pccb->numSgElements = nsegs;
2710285809Sscottl      /* set up sgl buffer address */
2711285809Sscottl      CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1,  pccb->tisgl_busaddr);
2712285809Sscottl      pccb->tiSuperScsiRequest.agSgl1.type = htole32(tiSglList);
2713285809Sscottl      pccb->tiSuperScsiRequest.agSgl1.len = htole32(pccb->dataLen);
2714285809Sscottl      pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)csio->data_ptr;
2715285809Sscottl      pccb->numSgElements = nsegs;
2716285809Sscottl    } /* else */
2717285809Sscottl  }
2718285809Sscottl
2719285809Sscottl  /* set data transfer direction */
2720285809Sscottl  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2721285809Sscottl  {
2722285809Sscottl    op = BUS_DMASYNC_PREWRITE;
2723285809Sscottl    pccb->tiSuperScsiRequest.dataDirection = tiDirectionOut;
2724285809Sscottl  }
2725285809Sscottl  else
2726285809Sscottl  {
2727285809Sscottl    op = BUS_DMASYNC_PREREAD;
2728285809Sscottl    pccb->tiSuperScsiRequest.dataDirection = tiDirectionIn;
2729285809Sscottl  }
2730285809Sscottl
2731285809Sscottl  pScsiCmnd = &pccb->tiSuperScsiRequest.scsiCmnd;
2732285809Sscottl
2733285809Sscottl  pScsiCmnd->expDataLength = pccb->dataLen;
2734285809Sscottl
2735285809Sscottl  if (csio->ccb_h.flags & CAM_CDB_POINTER)
2736285809Sscottl  {
2737285809Sscottl    bcopy(csio->cdb_io.cdb_ptr, &pScsiCmnd->cdb[0], csio->cdb_len);
2738285809Sscottl  }
2739285809Sscottl  else
2740285809Sscottl  {
2741285809Sscottl    bcopy(csio->cdb_io.cdb_bytes, &pScsiCmnd->cdb[0],csio->cdb_len);
2742285809Sscottl  }
2743285809Sscottl
2744285809Sscottl  CDB = &pScsiCmnd->cdb[0];
2745285809Sscottl
2746285809Sscottl  switch (CDB[0])
2747285809Sscottl  {
2748285809Sscottl  case REQUEST_SENSE:  /* requires different buffer */
2749285809Sscottl    /* This code should not be excercised because SAS support auto sense
2750285809Sscottl       For the completeness, vtophys() is still used here.
2751285809Sscottl     */
2752285809Sscottl    AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: QueueCmnd - REQUEST SENSE new\n");
2753285809Sscottl    pccb->tiSuperScsiRequest.agSgl1.len = htole32(pccb->senseLen);
2754285809Sscottl    phys_addr = vtophys(&csio->sense_data);
2755285809Sscottl    CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, phys_addr);
2756285809Sscottl    pccb->tiSuperScsiRequest.agSgl1.type  = htole32(tiSgl);
2757285809Sscottl    pccb->dataLen = pccb->senseLen;
2758285809Sscottl    pccb->numSgElements = 1;
2759285809Sscottl    break;
2760285809Sscottl  case INQUIRY:
2761285809Sscottl    /* only using lun 0 for device type detection */
2762285809Sscottl    pccb->flags |= AGTIAPI_INQUIRY;
2763285809Sscottl    break;
2764285809Sscottl  case TEST_UNIT_READY:
2765285809Sscottl  case RESERVE:
2766285809Sscottl  case RELEASE:
2767285809Sscottl  case START_STOP:
2768285809Sscottl  	pccb->tiSuperScsiRequest.agSgl1.len = 0;
2769285809Sscottl    pccb->dataLen = 0;
2770285809Sscottl    break;
2771285809Sscottl  case READ_6:
2772285809Sscottl  case WRITE_6:
2773285809Sscottl    /* Extract LBA */
2774285809Sscottl    start_lba = ((CDB[1] & 0x1f) << 16) |
2775285809Sscottl                 (CDB[2] << 8)          |
2776285809Sscottl                 (CDB[3]);
2777285809Sscottl#ifdef HIALEAH_ENCRYPTION
2778285809Sscottl    io_is_encryptable = 1;
2779285809Sscottl#endif
2780285809Sscottl    break;
2781285809Sscottl  case READ_10:
2782285809Sscottl  case WRITE_10:
2783285809Sscottl  case READ_12:
2784285809Sscottl  case WRITE_12:
2785285809Sscottl    /* Extract LBA */
2786285809Sscottl    start_lba = (CDB[2] << 24) |
2787285809Sscottl                (CDB[3] << 16) |
2788285809Sscottl                (CDB[4] << 8)  |
2789285809Sscottl                (CDB[5]);
2790285809Sscottl#ifdef HIALEAH_ENCRYPTION
2791285809Sscottl    io_is_encryptable = 1;
2792285809Sscottl#endif
2793285809Sscottl    break;
2794285809Sscottl  case READ_16:
2795285809Sscottl  case WRITE_16:
2796285809Sscottl    /* Extract LBA */
2797285809Sscottl    start_lba = (CDB[2] << 24) |
2798285809Sscottl                (CDB[3] << 16) |
2799285809Sscottl                (CDB[4] << 8)  |
2800285809Sscottl                (CDB[5]);
2801285809Sscottl    start_lba <<= 32;
2802285809Sscottl    start_lba |= ((CDB[6] << 24) |
2803285809Sscottl                  (CDB[7] << 16) |
2804285809Sscottl                  (CDB[8] << 8)  |
2805285809Sscottl                  (CDB[9]));
2806285809Sscottl#ifdef HIALEAH_ENCRYPTION
2807285809Sscottl    io_is_encryptable = 1;
2808285809Sscottl#endif
2809285809Sscottl    break;
2810285809Sscottl  default:
2811285809Sscottl    break;
2812285809Sscottl  }
2813285809Sscottl
2814285809Sscottl  /* fill device lun based one address mode */
2815285809Sscottl  agtiapi_SetLunField(pccb);
2816285809Sscottl
2817285809Sscottl  if (pccb->targetId < 0 || pccb->targetId >= maxTargets)
2818285809Sscottl  {
2819285809Sscottl    pccb->ccbStatus   = tiIOFailed;
2820285809Sscottl    pccb->scsiStatus  = tiDetailNoLogin;
2821285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
2822285809Sscottl    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
2823285809Sscottl    xpt_done(ccb);
2824285809Sscottl    pccb->ccb         = NULL;
2825285809Sscottl    return;
2826285809Sscottl  }
2827285809Sscottl  if (INDEX(pmcsc, pccb->targetId) >= maxTargets)
2828285809Sscottl  {
2829285809Sscottl    pccb->ccbStatus   = tiIOFailed;
2830285809Sscottl    pccb->scsiStatus  = tiDetailNoLogin;
2831285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
2832285809Sscottl    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
2833285809Sscottl    xpt_done(ccb);
2834285809Sscottl    pccb->ccb         = NULL;
2835285809Sscottl    return;
2836285809Sscottl  }
2837285809Sscottl  pDev = &pmcsc->pDevList[INDEX(pmcsc, pccb->targetId)];
2838285809Sscottl
2839285809Sscottl#if 1
2840285809Sscottl  if ((pmcsc->flags & EDC_DATA) &&
2841285809Sscottl      (pDev->flags & EDC_DATA))
2842285809Sscottl  {
2843285809Sscottl    /*
2844285809Sscottl     * EDC support:
2845285809Sscottl     *
2846285809Sscottl     * Possible command supported -
2847285809Sscottl     * READ_6, READ_10, READ_12, READ_16, READ_LONG, READ_BUFFER,
2848285809Sscottl     * READ_DEFECT_DATA, etc.
2849285809Sscottl     * WRITE_6, WRITE_10, WRITE_12, WRITE_16, WRITE_LONG, WRITE_LONG2,
2850285809Sscottl     * WRITE_BUFFER, WRITE_VERIFY, WRITE_VERIFY_12, etc.
2851285809Sscottl     *
2852285809Sscottl     * Do some data length adjustment and set chip operation instruction.
2853285809Sscottl     */
2854285809Sscottl    switch (CDB[0])
2855285809Sscottl    {
2856285809Sscottl      case READ_6:
2857285809Sscottl      case READ_10:
2858285809Sscottl      case READ_12:
2859285809Sscottl      case READ_16:
2860285809Sscottl        //  BUG_ON(pccb->tiSuperScsiRequest.flags & TI_SCSI_INITIATOR_ENCRYPT);
2861285809Sscottl#ifdef AGTIAPI_TEST_DIF
2862285809Sscottl        pccb->tiSuperScsiRequest.flags |= TI_SCSI_INITIATOR_DIF;
2863285809Sscottl#endif
2864285809Sscottl        pccb->flags |= EDC_DATA;
2865285809Sscottl
2866285809Sscottl#ifdef TEST_VERIFY_AND_FORWARD
2867285809Sscottl        pccb->tiSuperScsiRequest.Dif.flags =
2868285809Sscottl          DIF_VERIFY_FORWARD | DIF_UDT_REF_BLOCK_COUNT;
2869285809Sscottl        if(pDev->sector_size == 520) {
2870285809Sscottl            pScsiCmnd->expDataLength += (pccb->dataLen / 512) * 8;
2871285809Sscottl        } else if(pDev->sector_size == 4104) {
2872285809Sscottl            pScsiCmnd->expDataLength += (pccb->dataLen / 4096) * 8;
2873285809Sscottl        }
2874285809Sscottl#else
2875285809Sscottl#ifdef AGTIAPI_TEST_DIF
2876285809Sscottl        pccb->tiSuperScsiRequest.Dif.flags =
2877285809Sscottl          DIF_VERIFY_DELETE | DIF_UDT_REF_BLOCK_COUNT;
2878285809Sscottl#endif
2879285809Sscottl#endif
2880285809Sscottl#ifdef AGTIAPI_TEST_DIF
2881285809Sscottl        switch(pDev->sector_size) {
2882285809Sscottl            case 528:
2883285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2884285809Sscottl                  ( DIF_BLOCK_SIZE_520 << 16 );
2885285809Sscottl                break;
2886285809Sscottl            case 4104:
2887285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2888285809Sscottl                  ( DIF_BLOCK_SIZE_4096 << 16 );
2889285809Sscottl                break;
2890285809Sscottl            case 4168:
2891285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2892285809Sscottl                  ( DIF_BLOCK_SIZE_4160 << 16 );
2893285809Sscottl                break;
2894285809Sscottl        }
2895285809Sscottl
2896285809Sscottl        if(pCard->flags & EDC_DATA_CRC)
2897285809Sscottl            pccb->tiSuperScsiRequest.Dif.flags |= DIF_CRC_VERIFICATION;
2898285809Sscottl
2899285809Sscottl        /* Turn on upper 4 bits of UVM */
2900285809Sscottl        pccb->tiSuperScsiRequest.Dif.flags |= 0x03c00000;
2901285809Sscottl
2902285809Sscottl#endif
2903285809Sscottl#ifdef AGTIAPI_TEST_DPL
2904285809Sscottl        if(agtiapi_SetupDifPerLA(pCard, pccb, start_lba) < 0) {
2905285809Sscottl            printk(KERN_ERR "SetupDifPerLA Failed.\n");
2906285809Sscottl            cmnd->result = SCSI_HOST(DID_ERROR);
2907285809Sscottl            goto err;
2908285809Sscottl        }
2909285809Sscottl        pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = TRUE;
2910285809Sscottl#endif
2911285809Sscottl#ifdef AGTIAPI_TEST_DIF
2912285809Sscottl        /* Set App Tag */
2913285809Sscottl        pccb->tiSuperScsiRequest.Dif.udtArray[0] = 0xaa;
2914285809Sscottl        pccb->tiSuperScsiRequest.Dif.udtArray[1] = 0xbb;
2915285809Sscottl
2916285809Sscottl        /* Set LBA in UDT array */
2917285809Sscottl        if(CDB[0] == READ_6) {
2918285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[3];
2919285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[2];
2920285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[1] & 0x1f;
2921285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[5] = 0;
2922285809Sscottl        } else if(CDB[0] == READ_10 || CDB[0] == READ_12) {
2923285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2924285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2925285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2926285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2927285809Sscottl        } else if(CDB[0] == READ_16) {
2928285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[9];
2929285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[8];
2930285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[7];
2931285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[6];
2932285809Sscottl            /* Note: 32 bits lost */
2933285809Sscottl        }
2934285809Sscottl#endif
2935285809Sscottl
2936285809Sscottl        break;
2937285809Sscottl      case WRITE_6:
2938285809Sscottl      case WRITE_10:
2939285809Sscottl      case WRITE_12:
2940285809Sscottl      case WRITE_16:
2941285809Sscottl        //   BUG_ON(pccb->tiSuperScsiRequest.flags & TI_SCSI_INITIATOR_ENCRYPT);
2942285809Sscottl        pccb->flags |= EDC_DATA;
2943285809Sscottl#ifdef AGTIAPI_TEST_DIF
2944285809Sscottl        pccb->tiSuperScsiRequest.flags |= TI_SCSI_INITIATOR_DIF;
2945285809Sscottl        pccb->tiSuperScsiRequest.Dif.flags =
2946285809Sscottl          DIF_INSERT | DIF_UDT_REF_BLOCK_COUNT;
2947285809Sscottl        switch(pDev->sector_size) {
2948285809Sscottl            case 528:
2949285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2950285809Sscottl                  (DIF_BLOCK_SIZE_520 << 16);
2951285809Sscottl                break;
2952285809Sscottl            case 4104:
2953285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2954285809Sscottl                  ( DIF_BLOCK_SIZE_4096 << 16 );
2955285809Sscottl                break;
2956285809Sscottl            case 4168:
2957285809Sscottl                pccb->tiSuperScsiRequest.Dif.flags |=
2958285809Sscottl                  ( DIF_BLOCK_SIZE_4160 << 16 );
2959285809Sscottl                break;
2960285809Sscottl        }
2961285809Sscottl
2962285809Sscottl        /* Turn on upper 4 bits of UUM */
2963285809Sscottl        pccb->tiSuperScsiRequest.Dif.flags |= 0xf0000000;
2964285809Sscottl#endif
2965285809Sscottl#ifdef AGTIAPI_TEST_DPL
2966285809Sscottl        if(agtiapi_SetupDifPerLA(pCard, pccb, start_lba) < 0) {
2967285809Sscottl            printk(KERN_ERR "SetupDifPerLA Failed.\n");
2968285809Sscottl            cmnd->result = SCSI_HOST(DID_ERROR);
2969285809Sscottl            goto err;
2970285809Sscottl        }
2971285809Sscottl        pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = TRUE;
2972285809Sscottl#endif
2973285809Sscottl#ifdef AGTIAPI_TEST_DIF
2974285809Sscottl        /* Set App Tag */
2975285809Sscottl        pccb->tiSuperScsiRequest.Dif.udtArray[0] = 0xaa;
2976285809Sscottl        pccb->tiSuperScsiRequest.Dif.udtArray[1] = 0xbb;
2977285809Sscottl
2978285809Sscottl        /* Set LBA in UDT array */
2979285809Sscottl        if(CDB[0] == WRITE_6) {
2980285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[3];
2981285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[2];
2982285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[1] & 0x1f;
2983285809Sscottl        } else if(CDB[0] == WRITE_10 || CDB[0] == WRITE_12) {
2984285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2985285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2986285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2987285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2988285809Sscottl        } else if(CDB[0] == WRITE_16) {
2989285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2990285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2991285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2992285809Sscottl            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2993285809Sscottl            /* Note: 32 bits lost */
2994285809Sscottl        }
2995285809Sscottl#endif
2996285809Sscottl        break;
2997285809Sscottl    }
2998285809Sscottl  }
2999285809Sscottl#endif /* end of DIF */
3000285809Sscottl
3001285809Sscottl  if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
3002285809Sscottl  {
3003285809Sscottl    switch(csio->tag_action)
3004285809Sscottl    {
3005285809Sscottl    case MSG_HEAD_OF_Q_TAG:
3006285809Sscottl      pScsiCmnd->taskAttribute = TASK_HEAD_OF_QUEUE;
3007285809Sscottl      break;
3008285809Sscottl    case MSG_ACA_TASK:
3009285809Sscottl      pScsiCmnd->taskAttribute = TASK_ACA;
3010285809Sscottl      break;
3011285809Sscottl    case MSG_ORDERED_Q_TAG:
3012285809Sscottl      pScsiCmnd->taskAttribute = TASK_ORDERED;
3013285809Sscottl      break;
3014285809Sscottl    case MSG_SIMPLE_Q_TAG: /* fall through */
3015285809Sscottl    default:
3016285809Sscottl      pScsiCmnd->taskAttribute = TASK_SIMPLE;
3017285809Sscottl      break;
3018285809Sscottl    }
3019285809Sscottl  }
3020285809Sscottl
3021285809Sscottl  if (pccb->tiSuperScsiRequest.agSgl1.len != 0 && pccb->dataLen != 0)
3022285809Sscottl  {
3023285809Sscottl    /* should be just before start IO */
3024285809Sscottl    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
3025285809Sscottl  }
3026285809Sscottl
3027285809Sscottl  /*
3028285809Sscottl   * If assigned pDevHandle is not available
3029285809Sscottl   * then there is no need to send it to StartIO()
3030285809Sscottl   */
3031285809Sscottl  if (pccb->targetId < 0 || pccb->targetId >= maxTargets)
3032285809Sscottl  {
3033285809Sscottl    pccb->ccbStatus   = tiIOFailed;
3034285809Sscottl    pccb->scsiStatus  = tiDetailNoLogin;
3035285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
3036285809Sscottl    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
3037285809Sscottl    xpt_done(ccb);
3038285809Sscottl    pccb->ccb         = NULL;
3039285809Sscottl    return;
3040285809Sscottl  }
3041285809Sscottl  TID = INDEX(pmcsc, pccb->targetId);
3042285809Sscottl  if ((TID >= pmcsc->devDiscover) ||
3043285809Sscottl      !(pccb->devHandle = pmcsc->pDevList[TID].pDevHandle))
3044285809Sscottl  {
3045285809Sscottl    /*
3046285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSGListCB: not sending ccb devH %p,"
3047285809Sscottl                    " target %d tid %d/%d card %p ERROR pccb %p\n",
3048285809Sscottl                    pccb->devHandle, pccb->targetId, TID,
3049285809Sscottl                    pmcsc->devDiscover, pmcsc, pccb );
3050285809Sscottl    */
3051285809Sscottl    pccb->ccbStatus   = tiIOFailed;
3052285809Sscottl    pccb->scsiStatus  = tiDetailNoLogin;
3053285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
3054285809Sscottl    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
3055285809Sscottl    xpt_done(ccb);
3056285809Sscottl    pccb->ccb         = NULL;
3057285809Sscottl    return;
3058285809Sscottl  }
3059285809Sscottl  AGTIAPI_IO( "agtiapi_PrepareSGListCB: send ccb pccb->devHandle %p, "
3060285809Sscottl                  "pccb->targetId %d TID %d pmcsc->devDiscover %d card %p\n",
3061285809Sscottl                  pccb->devHandle, pccb->targetId, TID, pmcsc->devDiscover,
3062285809Sscottl                  pmcsc );
3063285809Sscottl#ifdef HIALEAH_ENCRYPTION
3064285809Sscottl  if(pmcsc->encrypt && io_is_encryptable) {
3065285809Sscottl    agtiapi_SetupEncryptedIO(pmcsc, pccb, start_lba);
3066285809Sscottl  } else{
3067285809Sscottl	io_is_encryptable = 0;
3068285809Sscottl	pccb->tiSuperScsiRequest.flags = 0;
3069285809Sscottl  }
3070285809Sscottl#endif
3071285809Sscottl  // put the request in send queue
3072285809Sscottl  agtiapi_QueueCCB( pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
3073285809Sscottl                    AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb );
3074285809Sscottl  agtiapi_StartIO(pmcsc);
3075285809Sscottl  return;
3076285809Sscottl}
3077285809Sscottl
3078285809Sscottl/******************************************************************************
3079285809Sscottlagtiapi_StartIO()
3080285809Sscottl
3081285809SscottlPurpose:
3082285809Sscottl  Send IO request down for processing.
3083285809SscottlParameters:
3084285809Sscottl  (struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
3085285809SscottlReturn:
3086285809SscottlNote:
3087285809Sscottl******************************************************************************/
3088285809SscottlSTATIC void agtiapi_StartIO( struct agtiapi_softc *pmcsc )
3089285809Sscottl{
3090285809Sscottl  ccb_t *pccb;
3091285809Sscottl  int TID;
3092285809Sscottl  ag_device_t *targ;
3093285809Sscottl  struct ccb_relsim crs;
3094285809Sscottl
3095285809Sscottl  AGTIAPI_IO( "agtiapi_StartIO: start\n" );
3096285809Sscottl
3097285809Sscottl  AG_LOCAL_LOCK( &pmcsc->sendLock );
3098285809Sscottl  pccb = pmcsc->ccbSendHead;
3099285809Sscottl
3100285809Sscottl  /* if link is down, do nothing */
3101285809Sscottl  if ((pccb == NULL) || pmcsc->flags & AGTIAPI_RESET)
3102285809Sscottl  {
3103285809Sscottl    AG_LOCAL_UNLOCK( &pmcsc->sendLock );
3104285809Sscottl    AGTIAPI_PRINTK( "agtiapi_StartIO: goto ext\n" );
3105285809Sscottl    goto ext;
3106285809Sscottl  }
3107285809Sscottl
3108285809Sscottl
3109285809Sscottl if (pmcsc != NULL && pccb->targetId >= 0 && pccb->targetId < maxTargets)
3110285809Sscottl  {
3111285809Sscottl      TID = INDEX(pmcsc, pccb->targetId);
3112285809Sscottl      targ   = &pmcsc->pDevList[TID];
3113285809Sscottl  }
3114285809Sscottl
3115285809Sscottl
3116285809Sscottl  /* clear send queue */
3117285809Sscottl  pmcsc->ccbSendHead = NULL;
3118285809Sscottl  pmcsc->ccbSendTail = NULL;
3119285809Sscottl  AG_LOCAL_UNLOCK( &pmcsc->sendLock );
3120285809Sscottl
3121285809Sscottl  /* send all ccbs down */
3122285809Sscottl  while (pccb)
3123285809Sscottl  {
3124285809Sscottl    pccb_t pccb_next;
3125285809Sscottl    U32    status;
3126285809Sscottl
3127285809Sscottl    pccb_next = pccb->pccbNext;
3128285809Sscottl    pccb->pccbNext = NULL;
3129285809Sscottl
3130285809Sscottl    if (!pccb->ccb)
3131285809Sscottl    {
3132285809Sscottl      AGTIAPI_PRINTK( "agtiapi_StartIO: pccb->ccb is NULL ERROR!\n" );
3133285809Sscottl      pccb = pccb_next;
3134285809Sscottl      continue;
3135285809Sscottl    }
3136285809Sscottl    AG_IO_DUMPCCB( pccb );
3137285809Sscottl
3138285809Sscottl    if (!pccb->devHandle)
3139285809Sscottl    {
3140285809Sscottl      agtiapi_DumpCCB( pccb );
3141285809Sscottl      AGTIAPI_PRINTK( "agtiapi_StartIO: ccb NULL device ERROR!\n" );
3142285809Sscottl      pccb = pccb_next;
3143285809Sscottl      continue;
3144285809Sscottl    }
3145285809Sscottl    AGTIAPI_IO( "agtiapi_StartIO: ccb %p retry %d\n", pccb, pccb->retryCount );
3146285809Sscottl
3147285809Sscottl#ifndef ABORT_TEST
3148285809Sscottl    if( !pccb->devHandle || !pccb->devHandle->osData || /* in rmmod case */
3149285809Sscottl        !(((ag_device_t *)(pccb->devHandle->osData))->flags & ACTIVE))
3150285809Sscottl    {
3151285809Sscottl      AGTIAPI_PRINTK( "agtiapi_StartIO: device %p not active! ERROR\n",
3152285809Sscottl                      pccb->devHandle );
3153285809Sscottl      if( pccb->devHandle ) {
3154285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartIO: device not active detail"
3155285809Sscottl                        " -- osData:%p\n",
3156285809Sscottl                        pccb->devHandle->osData );
3157285809Sscottl        if( pccb->devHandle->osData ) {
3158285809Sscottl          AGTIAPI_PRINTK( "agtiapi_StartIO: more device not active detail"
3159285809Sscottl                          " -- active flag:%d\n",
3160285809Sscottl                          ( (ag_device_t *)
3161285809Sscottl                            (pccb->devHandle->osData))->flags & ACTIVE );
3162285809Sscottl        }
3163285809Sscottl      }
3164285809Sscottl      pccb->ccbStatus  = tiIOFailed;
3165285809Sscottl      pccb->scsiStatus = tiDetailNoLogin;
3166285809Sscottl      agtiapi_Done( pmcsc, pccb );
3167285809Sscottl      pccb = pccb_next;
3168285809Sscottl      continue;
3169285809Sscottl    }
3170285809Sscottl#endif
3171285809Sscottl
3172285809Sscottl#ifdef FAST_IO_TEST
3173285809Sscottl    status = agtiapi_FastIOTest( pmcsc, pccb );
3174285809Sscottl#else
3175285809Sscottl    status = tiINISuperIOStart( &pmcsc->tiRoot,
3176285809Sscottl                                &pccb->tiIORequest,
3177285809Sscottl                                pccb->devHandle,
3178285809Sscottl                                &pccb->tiSuperScsiRequest,
3179285809Sscottl                                (void *)&pccb->tdIOReqBody,
3180285809Sscottl                                tiInterruptContext );
3181285809Sscottl#endif
3182285809Sscottl    switch( status )
3183285809Sscottl    {
3184285809Sscottl      case tiSuccess:
3185285809Sscottl        /*
3186285809Sscottl        static int squelchCount = 0;
3187285809Sscottl        if ( 200000 == squelchCount++ ) // squelch prints
3188285809Sscottl        {
3189285809Sscottl          AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart stat tiSuccess %p\n",
3190285809Sscottl                          pccb );
3191285809Sscottl          squelchCount = 0; // reset count
3192285809Sscottl        }
3193285809Sscottl        */
3194285809Sscottl
3195285809Sscottl
3196285809Sscottl        break;
3197285809Sscottl      case tiDeviceBusy:
3198285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiDeviceBusy %p\n",
3199285809Sscottl                        pccb->ccb );
3200285809Sscottl#ifdef LOGEVENT
3201285809Sscottl        agtiapi_LogEvent( pmcsc,
3202285809Sscottl                          IOCTL_EVT_SEV_INFORMATIONAL,
3203285809Sscottl                          0,
3204285809Sscottl                          agNULL,
3205285809Sscottl                          0,
3206285809Sscottl                          "tiINIIOStart tiDeviceBusy " );
3207285809Sscottl#endif
3208285809Sscottl        pccb->ccbStatus = tiIOFailed;
3209285809Sscottl        pccb->scsiStatus = tiDeviceBusy;
3210285809Sscottl        agtiapi_Done(pmcsc, pccb);
3211285809Sscottl        break;
3212285809Sscottl      case tiBusy:
3213285809Sscottl
3214285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiBusy %p\n",
3215285809Sscottl                        pccb->ccb );
3216285809Sscottl#ifdef LOGEVENT
3217285809Sscottl        agtiapi_LogEvent( pmcsc,
3218285809Sscottl                          IOCTL_EVT_SEV_INFORMATIONAL,
3219285809Sscottl                          0,
3220285809Sscottl                          agNULL,
3221285809Sscottl                          0,
3222285809Sscottl                          "tiINIIOStart tiBusy " );
3223285809Sscottl#endif
3224285809Sscottl
3225285809Sscottl        pccb->ccbStatus = tiIOFailed;
3226285809Sscottl        pccb->scsiStatus = tiBusy;
3227285809Sscottl        agtiapi_Done(pmcsc, pccb);
3228285809Sscottl
3229285809Sscottl        break;
3230285809Sscottl      case tiIONoDevice:
3231285809Sscottl        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiNoDevice %p "
3232285809Sscottl                        "ERROR\n", pccb->ccb );
3233285809Sscottl#ifdef LOGEVENT
3234285809Sscottl        agtiapi_LogEvent( pmcsc,
3235285809Sscottl                          IOCTL_EVT_SEV_INFORMATIONAL,
3236285809Sscottl                          0,
3237285809Sscottl                          agNULL,
3238285809Sscottl                          0,
3239285809Sscottl                          "tiINIIOStart invalid device handle " );
3240285809Sscottl#endif
3241285809Sscottl#ifndef ABORT_TEST
3242285809Sscottl        /* return command back to OS due to no device available */
3243285809Sscottl        ((ag_device_t *)(pccb->devHandle->osData))->flags &= ~ACTIVE;
3244285809Sscottl        pccb->ccbStatus  = tiIOFailed;
3245285809Sscottl        pccb->scsiStatus = tiDetailNoLogin;
3246285809Sscottl        agtiapi_Done(pmcsc, pccb);
3247285809Sscottl#else
3248285809Sscottl        /* for short cable pull, we want IO retried - 3-18-2005 */
3249285809Sscottl        agtiapi_QueueCCB(pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
3250285809Sscottl                         AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb);
3251285809Sscottl#endif
3252285809Sscottl        break;
3253285809Sscottl      case tiError:
3254285809Sscottl        AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status tiError %p\n",
3255285809Sscottl                       pccb->ccb);
3256285809Sscottl#ifdef LOGEVENT
3257285809Sscottl        agtiapi_LogEvent(pmcsc,
3258285809Sscottl                         IOCTL_EVT_SEV_INFORMATIONAL,
3259285809Sscottl                         0,
3260285809Sscottl                         agNULL,
3261285809Sscottl                         0,
3262285809Sscottl                         "tiINIIOStart tiError ");
3263285809Sscottl#endif
3264285809Sscottl        pccb->ccbStatus  = tiIOFailed;
3265285809Sscottl        pccb->scsiStatus = tiDetailOtherError;
3266285809Sscottl        agtiapi_Done(pmcsc, pccb);
3267285809Sscottl        break;
3268285809Sscottl      default:
3269285809Sscottl        AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status default %x %p\n",
3270285809Sscottl                       status, pccb->ccb);
3271285809Sscottl#ifdef LOGEVENT
3272285809Sscottl        agtiapi_LogEvent(pmcsc,
3273285809Sscottl                         IOCTL_EVT_SEV_ERROR,
3274285809Sscottl                         0,
3275285809Sscottl                         agNULL,
3276285809Sscottl                         0,
3277285809Sscottl                         "tiINIIOStart unexpected status ");
3278285809Sscottl#endif
3279285809Sscottl        pccb->ccbStatus  = tiIOFailed;
3280285809Sscottl        pccb->scsiStatus = tiDetailOtherError;
3281285809Sscottl        agtiapi_Done(pmcsc, pccb);
3282285809Sscottl    }
3283285809Sscottl
3284285809Sscottl    pccb = pccb_next;
3285285809Sscottl  }
3286285809Sscottlext:
3287285809Sscottl  /* some IO requests might have been completed */
3288285809Sscottl  AG_GET_DONE_PCCB(pccb, pmcsc);
3289285809Sscottl  return;
3290285809Sscottl}
3291285809Sscottl
3292285809Sscottl/******************************************************************************
3293285809Sscottlagtiapi_StartSMP()
3294285809Sscottl
3295285809SscottlPurpose:
3296285809Sscottl  Send SMP request down for processing.
3297285809SscottlParameters:
3298285809Sscottl  (struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
3299285809SscottlReturn:
3300285809SscottlNote:
3301285809Sscottl******************************************************************************/
3302285809SscottlSTATIC void agtiapi_StartSMP(struct agtiapi_softc *pmcsc)
3303285809Sscottl{
3304285809Sscottl  ccb_t *pccb;
3305285809Sscottl
3306285809Sscottl  AGTIAPI_PRINTK("agtiapi_StartSMP: start\n");
3307285809Sscottl
3308285809Sscottl  AG_LOCAL_LOCK(&pmcsc->sendSMPLock);
3309285809Sscottl  pccb = pmcsc->smpSendHead;
3310285809Sscottl
3311285809Sscottl  /* if link is down, do nothing */
3312285809Sscottl  if ((pccb == NULL) || pmcsc->flags & AGTIAPI_RESET)
3313285809Sscottl  {
3314285809Sscottl    AG_LOCAL_UNLOCK(&pmcsc->sendSMPLock);
3315285809Sscottl    AGTIAPI_PRINTK("agtiapi_StartSMP: goto ext\n");
3316285809Sscottl    goto ext;
3317285809Sscottl  }
3318285809Sscottl
3319285809Sscottl  /* clear send queue */
3320285809Sscottl  pmcsc->smpSendHead = NULL;
3321285809Sscottl  pmcsc->smpSendTail = NULL;
3322285809Sscottl  AG_LOCAL_UNLOCK(&pmcsc->sendSMPLock);
3323285809Sscottl
3324285809Sscottl  /* send all ccbs down */
3325285809Sscottl  while (pccb)
3326285809Sscottl  {
3327285809Sscottl    pccb_t pccb_next;
3328285809Sscottl    U32    status;
3329285809Sscottl
3330285809Sscottl    pccb_next = pccb->pccbNext;
3331285809Sscottl    pccb->pccbNext = NULL;
3332285809Sscottl
3333285809Sscottl    if (!pccb->ccb)
3334285809Sscottl    {
3335285809Sscottl      AGTIAPI_PRINTK("agtiapi_StartSMP: pccb->ccb is NULL ERROR!\n");
3336285809Sscottl      pccb = pccb_next;
3337285809Sscottl      continue;
3338285809Sscottl    }
3339285809Sscottl
3340285809Sscottl    if (!pccb->devHandle)
3341285809Sscottl    {
3342285809Sscottl      AGTIAPI_PRINTK("agtiapi_StartSMP: ccb NULL device ERROR!\n");
3343285809Sscottl      pccb = pccb_next;
3344285809Sscottl      continue;
3345285809Sscottl    }
3346285809Sscottl    pccb->flags |= TAG_SMP; // mark as SMP for later tracking
3347285809Sscottl    AGTIAPI_PRINTK( "agtiapi_StartSMP: ccb %p retry %d\n",
3348285809Sscottl                    pccb, pccb->retryCount );
3349285809Sscottl    status = tiINISMPStart( &pmcsc->tiRoot,
3350285809Sscottl                            &pccb->tiIORequest,
3351285809Sscottl                            pccb->devHandle,
3352285809Sscottl                            &pccb->tiSMPFrame,
3353285809Sscottl                            (void *)&pccb->tdIOReqBody,
3354285809Sscottl                            tiInterruptContext);
3355285809Sscottl
3356285809Sscottl    switch (status)
3357285809Sscottl    {
3358285809Sscottl    case tiSuccess:
3359285809Sscottl      break;
3360285809Sscottl    case tiBusy:
3361285809Sscottl      AGTIAPI_PRINTK("agtiapi_StartSMP: tiINISMPStart status tiBusy %p\n",
3362285809Sscottl                     pccb->ccb);
3363285809Sscottl      /* pending ccb back to send queue */
3364285809Sscottl      agtiapi_QueueCCB(pmcsc, &pmcsc->smpSendHead, &pmcsc->smpSendTail
3365285809Sscottl                       AG_CARD_LOCAL_LOCK(&pmcsc->sendSMPLock), pccb);
3366285809Sscottl      break;
3367285809Sscottl    case tiError:
3368285809Sscottl      AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status tiError %p\n",
3369285809Sscottl                     pccb->ccb);
3370285809Sscottl      pccb->ccbStatus = tiSMPFailed;
3371285809Sscottl      agtiapi_SMPDone(pmcsc, pccb);
3372285809Sscottl      break;
3373285809Sscottl    default:
3374285809Sscottl      AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status default %x %p\n",
3375285809Sscottl                     status, pccb->ccb);
3376285809Sscottl      pccb->ccbStatus = tiSMPFailed;
3377285809Sscottl      agtiapi_SMPDone(pmcsc, pccb);
3378285809Sscottl    }
3379285809Sscottl
3380285809Sscottl    pccb = pccb_next;
3381285809Sscottl  }
3382285809Sscottl  ext:
3383285809Sscottl  /* some SMP requests might have been completed */
3384285809Sscottl  AG_GET_DONE_SMP_PCCB(pccb, pmcsc);
3385285809Sscottl
3386285809Sscottl  return;
3387285809Sscottl}
3388285809Sscottl
3389285809Sscottl#if __FreeBSD_version > 901000
3390285809Sscottl/******************************************************************************
3391285809Sscottlagtiapi_PrepareSMPSGList()
3392285809Sscottl
3393285809SscottlPurpose:
3394285809Sscottl  This function prepares scatter-gather list for the given ccb
3395285809SscottlParameters:
3396285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
3397285809Sscottl  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
3398285809SscottlReturn:
3399285809Sscottl  0 - success
3400285809Sscottl  1 - failure
3401285809Sscottl
3402285809SscottlNote:
3403285809Sscottl******************************************************************************/
3404285809Sscottlstatic int agtiapi_PrepareSMPSGList( struct agtiapi_softc *pmcsc, ccb_t *pccb )
3405285809Sscottl{
3406285809Sscottl  /* Pointer to CAM's ccb */
3407285809Sscottl  union ccb *ccb = pccb->ccb;
3408285809Sscottl  struct ccb_smpio *csmpio = &ccb->smpio;
3409285809Sscottl  struct ccb_hdr *ccbh = &ccb->ccb_h;
3410285809Sscottl
3411285809Sscottl  AGTIAPI_PRINTK("agtiapi_PrepareSMPSGList: start\n");
3412285809Sscottl  switch((ccbh->flags & CAM_DATA_MASK))
3413285809Sscottl  {
3414285809Sscottl    case CAM_DATA_PADDR:
3415285809Sscottl    case CAM_DATA_SG_PADDR:
3416285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Physical Address not supported\n");
3417285809Sscottl      ccb->ccb_h.status = CAM_REQ_INVALID;
3418285809Sscottl      xpt_done(ccb);
3419285809Sscottl      return tiReject;
3420285809Sscottl    case CAM_DATA_SG:
3421285809Sscottl
3422285809Sscottl    /*
3423285809Sscottl     * Currently we do not support Multiple SG list
3424285809Sscottl     * return error for now
3425285809Sscottl     */
3426285809Sscottl      if ( (csmpio->smp_request_sglist_cnt > 1)
3427285809Sscottl           || (csmpio->smp_response_sglist_cnt > 1) )
3428285809Sscottl      {
3429285809Sscottl        AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Multiple SG list not supported\n");
3430285809Sscottl        ccb->ccb_h.status = CAM_REQ_INVALID;
3431285809Sscottl        xpt_done(ccb);
3432285809Sscottl        return tiReject;
3433285809Sscottl      }
3434285809Sscottl    }
3435285809Sscottl    if ( csmpio->smp_request_sglist_cnt != 0 )
3436285809Sscottl    {
3437285809Sscottl      /*
3438285809Sscottl       * Virtual address that needs to translated into
3439285809Sscottl       * one or more physical address ranges.
3440285809Sscottl       */
3441285809Sscottl      int error;
3442285809Sscottl      //AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
3443285809Sscottl      AGTIAPI_PRINTK("agtiapi_PrepareSGList: virtual address\n");
3444285809Sscottl      error = bus_dmamap_load( pmcsc->buffer_dmat,
3445285809Sscottl                               pccb->CCB_dmamap,
3446285809Sscottl                               csmpio->smp_request,
3447285809Sscottl                               csmpio->smp_request_len,
3448285809Sscottl                               agtiapi_PrepareSMPSGListCB,
3449285809Sscottl                               pccb,
3450285809Sscottl                               BUS_DMA_NOWAIT /* 0 */ );
3451285809Sscottl
3452285809Sscottl      //AG_LOCAL_UNLOCK(&(pmcsc->pCardInfo->pmIOLock));
3453285809Sscottl
3454285809Sscottl      if (error == EINPROGRESS)
3455285809Sscottl      {
3456285809Sscottl        /*
3457285809Sscottl         * So as to maintain ordering,
3458285809Sscottl         * freeze the controller queue
3459285809Sscottl         * until our mapping is
3460285809Sscottl         * returned.
3461285809Sscottl         */
3462285809Sscottl        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3463285809Sscottl        xpt_freeze_simq( pmcsc->sim, 1 );
3464285809Sscottl        pmcsc->SimQFrozen = agTRUE;
3465285809Sscottl        ccbh->status |= CAM_RELEASE_SIMQ;
3466285809Sscottl      }
3467285809Sscottl    }
3468285809Sscottl    if( csmpio->smp_response_sglist_cnt != 0 )
3469285809Sscottl    {
3470285809Sscottl      /*
3471285809Sscottl       * Virtual address that needs to translated into
3472285809Sscottl       * one or more physical address ranges.
3473285809Sscottl       */
3474285809Sscottl      int error;
3475285809Sscottl      //AG_LOCAL_LOCK( &(pmcsc->pCardInfo->pmIOLock) );
3476285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSGList: virtual address\n" );
3477285809Sscottl      error = bus_dmamap_load( pmcsc->buffer_dmat,
3478285809Sscottl                               pccb->CCB_dmamap,
3479285809Sscottl                               csmpio->smp_response,
3480285809Sscottl                               csmpio->smp_response_len,
3481285809Sscottl                               agtiapi_PrepareSMPSGListCB,
3482285809Sscottl                               pccb,
3483285809Sscottl                               BUS_DMA_NOWAIT /* 0 */ );
3484285809Sscottl
3485285809Sscottl      //AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
3486285809Sscottl
3487285809Sscottl      if ( error == EINPROGRESS )
3488285809Sscottl      {
3489285809Sscottl        /*
3490285809Sscottl         * So as to maintain ordering,
3491285809Sscottl         * freeze the controller queue
3492285809Sscottl         * until our mapping is
3493285809Sscottl         * returned.
3494285809Sscottl         */
3495285809Sscottl        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3496285809Sscottl        xpt_freeze_simq( pmcsc->sim, 1 );
3497285809Sscottl        pmcsc->SimQFrozen = agTRUE;
3498285809Sscottl        ccbh->status |= CAM_RELEASE_SIMQ;
3499285809Sscottl      }
3500285809Sscottl    }
3501285809Sscottl
3502285809Sscottl  else
3503285809Sscottl  {
3504285809Sscottl    if ( (csmpio->smp_request_sglist_cnt == 0) &&
3505285809Sscottl         (csmpio->smp_response_sglist_cnt == 0) )
3506285809Sscottl    {
3507285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: physical address\n" );
3508285809Sscottl      pccb->tiSMPFrame.outFrameBuf = (void *)csmpio->smp_request;
3509285809Sscottl      pccb->tiSMPFrame.outFrameLen = csmpio->smp_request_len;
3510285809Sscottl      pccb->tiSMPFrame.expectedRespLen = csmpio->smp_response_len;
3511285809Sscottl
3512285809Sscottl      // 0xFF to be defined
3513285809Sscottl      agtiapi_PrepareSMPSGListCB( pccb, NULL, 0, 0xAABBCCDD );
3514285809Sscottl    }
3515285809Sscottl    pccb->tiSMPFrame.flag = 0;
3516285809Sscottl  }
3517285809Sscottl
3518285809Sscottl  return tiSuccess;
3519285809Sscottl}
3520285809Sscottl#else
3521285809Sscottl
3522285809Sscottl/******************************************************************************
3523285809Sscottlagtiapi_PrepareSMPSGList()
3524285809Sscottl
3525285809SscottlPurpose:
3526285809Sscottl  This function prepares scatter-gather list for the given ccb
3527285809SscottlParameters:
3528285809Sscottl  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
3529285809Sscottl  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
3530285809SscottlReturn:
3531285809Sscottl  0 - success
3532285809Sscottl  1 - failure
3533285809Sscottl
3534285809SscottlNote:
3535285809Sscottl******************************************************************************/
3536285809Sscottlstatic int agtiapi_PrepareSMPSGList( struct agtiapi_softc *pmcsc, ccb_t *pccb )
3537285809Sscottl{
3538285809Sscottl  /* Pointer to CAM's ccb */
3539285809Sscottl  union ccb *ccb = pccb->ccb;
3540285809Sscottl  struct ccb_smpio *csmpio = &ccb->smpio;
3541285809Sscottl  struct ccb_hdr *ccbh = &ccb->ccb_h;
3542285809Sscottl
3543285809Sscottl  AGTIAPI_PRINTK("agtiapi_PrepareSMPSGList: start\n");
3544285809Sscottl
3545285809Sscottl  if (ccbh->flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS))
3546285809Sscottl  {
3547285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Physical Address "
3548285809Sscottl                    "not supported\n" );
3549285809Sscottl    ccb->ccb_h.status = CAM_REQ_INVALID;
3550285809Sscottl    xpt_done(ccb);
3551285809Sscottl    return tiReject;;
3552285809Sscottl  }
3553285809Sscottl
3554285809Sscottl  if (ccbh->flags & CAM_SCATTER_VALID)
3555285809Sscottl  {
3556285809Sscottl    /*
3557285809Sscottl     * Currently we do not support Multiple SG list
3558285809Sscottl     * return error for now
3559285809Sscottl     */
3560285809Sscottl    if ( (csmpio->smp_request_sglist_cnt > 1)
3561285809Sscottl         || (csmpio->smp_response_sglist_cnt > 1) )
3562285809Sscottl    {
3563285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Multiple SG list "
3564285809Sscottl                      "not supported\n" );
3565285809Sscottl      ccb->ccb_h.status = CAM_REQ_INVALID;
3566285809Sscottl      xpt_done(ccb);
3567285809Sscottl      return tiReject;;
3568285809Sscottl    }
3569285809Sscottl    if ( csmpio->smp_request_sglist_cnt != 0 )
3570285809Sscottl    {
3571285809Sscottl      /*
3572285809Sscottl       * Virtual address that needs to translated into
3573285809Sscottl       * one or more physical address ranges.
3574285809Sscottl       */
3575285809Sscottl      int error;
3576285809Sscottl      //AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
3577285809Sscottl      AGTIAPI_PRINTK("agtiapi_PrepareSGList: virtual address\n");
3578285809Sscottl      error = bus_dmamap_load( pmcsc->buffer_dmat,
3579285809Sscottl                               pccb->CCB_dmamap,
3580285809Sscottl                               csmpio->smp_request,
3581285809Sscottl                               csmpio->smp_request_len,
3582285809Sscottl                               agtiapi_PrepareSMPSGListCB,
3583285809Sscottl                               pccb,
3584285809Sscottl                               BUS_DMA_NOWAIT /* 0 */ );
3585285809Sscottl
3586285809Sscottl      //AG_LOCAL_UNLOCK(&(pmcsc->pCardInfo->pmIOLock));
3587285809Sscottl
3588285809Sscottl      if (error == EINPROGRESS)
3589285809Sscottl      {
3590285809Sscottl        /*
3591285809Sscottl         * So as to maintain ordering,
3592285809Sscottl         * freeze the controller queue
3593285809Sscottl         * until our mapping is
3594285809Sscottl         * returned.
3595285809Sscottl         */
3596285809Sscottl        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3597285809Sscottl        xpt_freeze_simq( pmcsc->sim, 1 );
3598285809Sscottl        pmcsc->SimQFrozen = agTRUE;
3599285809Sscottl        ccbh->status |= CAM_RELEASE_SIMQ;
3600285809Sscottl      }
3601285809Sscottl    }
3602285809Sscottl    if( csmpio->smp_response_sglist_cnt != 0 )
3603285809Sscottl    {
3604285809Sscottl      /*
3605285809Sscottl       * Virtual address that needs to translated into
3606285809Sscottl       * one or more physical address ranges.
3607285809Sscottl       */
3608285809Sscottl      int error;
3609285809Sscottl      //AG_LOCAL_LOCK( &(pmcsc->pCardInfo->pmIOLock) );
3610285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSGList: virtual address\n" );
3611285809Sscottl      error = bus_dmamap_load( pmcsc->buffer_dmat,
3612285809Sscottl                               pccb->CCB_dmamap,
3613285809Sscottl                               csmpio->smp_response,
3614285809Sscottl                               csmpio->smp_response_len,
3615285809Sscottl                               agtiapi_PrepareSMPSGListCB,
3616285809Sscottl                               pccb,
3617285809Sscottl                               BUS_DMA_NOWAIT /* 0 */ );
3618285809Sscottl
3619285809Sscottl      //AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
3620285809Sscottl
3621285809Sscottl      if ( error == EINPROGRESS )
3622285809Sscottl      {
3623285809Sscottl        /*
3624285809Sscottl         * So as to maintain ordering,
3625285809Sscottl         * freeze the controller queue
3626285809Sscottl         * until our mapping is
3627285809Sscottl         * returned.
3628285809Sscottl         */
3629285809Sscottl        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3630285809Sscottl        xpt_freeze_simq( pmcsc->sim, 1 );
3631285809Sscottl        pmcsc->SimQFrozen = agTRUE;
3632285809Sscottl        ccbh->status |= CAM_RELEASE_SIMQ;
3633285809Sscottl      }
3634285809Sscottl    }
3635285809Sscottl  }
3636285809Sscottl  else
3637285809Sscottl  {
3638285809Sscottl    if ( (csmpio->smp_request_sglist_cnt == 0) &&
3639285809Sscottl         (csmpio->smp_response_sglist_cnt == 0) )
3640285809Sscottl    {
3641285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: physical address\n" );
3642285809Sscottl      pccb->tiSMPFrame.outFrameBuf = (void *)csmpio->smp_request;
3643285809Sscottl      pccb->tiSMPFrame.outFrameLen = csmpio->smp_request_len;
3644285809Sscottl      pccb->tiSMPFrame.expectedRespLen = csmpio->smp_response_len;
3645285809Sscottl
3646285809Sscottl      // 0xFF to be defined
3647285809Sscottl      agtiapi_PrepareSMPSGListCB( pccb, NULL, 0, 0xAABBCCDD );
3648285809Sscottl    }
3649285809Sscottl    pccb->tiSMPFrame.flag = 0;
3650285809Sscottl  }
3651285809Sscottl
3652285809Sscottl  return tiSuccess;
3653285809Sscottl}
3654285809Sscottl
3655285809Sscottl#endif
3656285809Sscottl/******************************************************************************
3657285809Sscottlagtiapi_PrepareSMPSGListCB()
3658285809Sscottl
3659285809SscottlPurpose:
3660285809Sscottl  Callback function for bus_dmamap_load()
3661285809Sscottl  This fuctions sends IO to LL layer.
3662285809SscottlParameters:
3663285809Sscottl  void *arg (IN)                Pointer to the HBA data structure
3664285809Sscottl  bus_dma_segment_t *segs (IN)  Pointer to dma segment
3665285809Sscottl  int nsegs (IN)                number of dma segment
3666285809Sscottl  int error (IN)                error
3667285809SscottlReturn:
3668285809SscottlNote:
3669285809Sscottl******************************************************************************/
3670285809Sscottlstatic void agtiapi_PrepareSMPSGListCB( void *arg,
3671285809Sscottl                                        bus_dma_segment_t *segs,
3672285809Sscottl                                        int nsegs,
3673285809Sscottl                                        int error )
3674285809Sscottl{
3675285809Sscottl  pccb_t                pccb = arg;
3676285809Sscottl  union ccb            *ccb  = pccb->ccb;
3677285809Sscottl  struct agtiapi_softc *pmcsc;
3678285809Sscottl  U32        TID     = CMND_TO_TARGET(ccb);
3679285809Sscottl  int status;
3680285809Sscottl  tiDeviceHandle_t     *tiExpDevHandle;
3681285809Sscottl  tiPortalContext_t    *tiExpPortalContext;
3682285809Sscottl  ag_portal_info_t     *tiExpPortalInfo;
3683285809Sscottl
3684285809Sscottl  AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: start, nsegs %d error 0x%x\n",
3685285809Sscottl                  nsegs, error );
3686285809Sscottl  pmcsc = pccb->pmcsc;
3687285809Sscottl
3688285809Sscottl  if ( error != tiSuccess )
3689285809Sscottl  {
3690285809Sscottl    if (error == 0xAABBCCDD)
3691285809Sscottl    {
3692285809Sscottl      // do nothing
3693285809Sscottl    }
3694285809Sscottl    else
3695285809Sscottl    {
3696285809Sscottl      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: error status 0x%x\n",
3697285809Sscottl                      error );
3698285809Sscottl      bus_dmamap_unload( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3699285809Sscottl      bus_dmamap_destroy( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3700285809Sscottl      agtiapi_FreeCCB( pmcsc, pccb );
3701285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP;
3702285809Sscottl      xpt_done( ccb );
3703285809Sscottl      return;
3704285809Sscottl    }
3705285809Sscottl  }
3706285809Sscottl
3707285809Sscottl  if ( nsegs > AGTIAPI_MAX_DMA_SEGS )
3708285809Sscottl  {
3709285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: over the limit. nsegs %d "
3710285809Sscottl                    "AGTIAPI_MAX_DMA_SEGS %d\n",
3711285809Sscottl                    nsegs, AGTIAPI_MAX_DMA_SEGS );
3712285809Sscottl    bus_dmamap_unload( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3713285809Sscottl    bus_dmamap_destroy( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3714285809Sscottl    agtiapi_FreeCCB( pmcsc, pccb );
3715285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
3716285809Sscottl    xpt_done( ccb );
3717285809Sscottl    return;
3718285809Sscottl  }
3719285809Sscottl
3720285809Sscottl  /*
3721285809Sscottl   * If assigned pDevHandle is not available
3722285809Sscottl   * then there is no need to send it to StartIO()
3723285809Sscottl   */
3724285809Sscottl  /* TODO: Add check for deviceType */
3725285809Sscottl  if ( pccb->targetId < 0 || pccb->targetId >= maxTargets )
3726285809Sscottl  {
3727285809Sscottl    agtiapi_FreeCCB( pmcsc, pccb );
3728285809Sscottl    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3729285809Sscottl    xpt_done(ccb);
3730285809Sscottl    pccb->ccb        = NULL;
3731285809Sscottl    return;
3732285809Sscottl  }
3733285809Sscottl  TID = INDEX( pmcsc, pccb->targetId );
3734285809Sscottl  if ( (TID >= pmcsc->devDiscover) ||
3735285809Sscottl       !(pccb->devHandle = pmcsc->pDevList[TID].pDevHandle) )
3736285809Sscottl  {
3737285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: not sending ccb devH %p, "
3738285809Sscottl                    "target %d tid %d/%d "
3739285809Sscottl                    "card %p ERROR pccb %p\n",
3740285809Sscottl                    pccb->devHandle,
3741285809Sscottl                    pccb->targetId,
3742285809Sscottl                    TID,
3743285809Sscottl                    pmcsc->devDiscover,
3744285809Sscottl                    pmcsc,
3745285809Sscottl                    pccb );
3746285809Sscottl    agtiapi_FreeCCB( pmcsc, pccb );
3747285809Sscottl    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3748285809Sscottl    xpt_done( ccb );
3749285809Sscottl    pccb->ccb        = NULL;
3750285809Sscottl    return;
3751285809Sscottl  }
3752285809Sscottl  /* TODO: add indirect handling */
3753285809Sscottl  /* set the flag correctly based on Indiret SMP request and responce */
3754285809Sscottl
3755285809Sscottl  AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: send ccb pccb->devHandle %p, "
3756285809Sscottl                  "pccb->targetId %d TID %d pmcsc->devDiscover %d card %p\n",
3757285809Sscottl                  pccb->devHandle,
3758285809Sscottl                  pccb->targetId, TID,
3759285809Sscottl                  pmcsc->devDiscover,
3760285809Sscottl                  pmcsc );
3761285809Sscottl  tiExpDevHandle = pccb->devHandle;
3762285809Sscottl  tiExpPortalInfo = pmcsc->pDevList[TID].pPortalInfo;
3763285809Sscottl  tiExpPortalContext = &tiExpPortalInfo->tiPortalContext;
3764285809Sscottl  /* Look for the expander associated with the ses device */
3765285809Sscottl  status = tiINIGetExpander( &pmcsc->tiRoot,
3766285809Sscottl                             tiExpPortalContext,
3767285809Sscottl                             pccb->devHandle,
3768285809Sscottl                             &tiExpDevHandle );
3769285809Sscottl
3770285809Sscottl  if ( status != tiSuccess )
3771285809Sscottl  {
3772285809Sscottl    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: Error getting Expander "
3773285809Sscottl                    "device\n" );
3774285809Sscottl    agtiapi_FreeCCB( pmcsc, pccb );
3775285809Sscottl    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3776285809Sscottl    xpt_done( ccb );
3777285809Sscottl    pccb->ccb        = NULL;
3778285809Sscottl    return;
3779285809Sscottl  }
3780285809Sscottl
3781285809Sscottl  /* this is expander device */
3782285809Sscottl  pccb->devHandle = tiExpDevHandle;
3783285809Sscottl  /* put the request in send queue */
3784285809Sscottl  agtiapi_QueueCCB( pmcsc, &pmcsc->smpSendHead, &pmcsc->smpSendTail
3785285809Sscottl                    AG_CARD_LOCAL_LOCK(&pmcsc->sendSMPLock), pccb );
3786285809Sscottl
3787285809Sscottl  agtiapi_StartSMP( pmcsc );
3788285809Sscottl
3789285809Sscottl  return;
3790285809Sscottl}
3791285809Sscottl
3792285809Sscottl
3793285809Sscottl/******************************************************************************
3794285809Sscottlagtiapi_Done()
3795285809Sscottl
3796285809SscottlPurpose:
3797285809Sscottl  Processing completed ccbs
3798285809SscottlParameters:
3799285809Sscottl  struct agtiapi_softc *pmcsc (IN)   Pointer to HBA data structure
3800285809Sscottl  ccb_t *pccb (IN)     A pointer to the driver's own CCB, not CAM's CCB
3801285809SscottlReturn:
3802285809SscottlNote:
3803285809Sscottl******************************************************************************/
3804285809SscottlSTATIC void agtiapi_Done(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3805285809Sscottl{
3806285809Sscottl  pccb_t pccb_curr = pccb;
3807285809Sscottl  pccb_t pccb_next;
3808285809Sscottl
3809285809Sscottl  tiIniScsiCmnd_t *cmnd;
3810285809Sscottl  union ccb * ccb;
3811285809Sscottl
3812285809Sscottl  AGTIAPI_IO("agtiapi_Done: start\n");
3813285809Sscottl  while (pccb_curr)
3814285809Sscottl  {
3815285809Sscottl    /* start from 1st ccb in the chain */
3816285809Sscottl    pccb_next = pccb_curr->pccbNext;
3817285809Sscottl
3818285809Sscottl    if (agtiapi_CheckError(pmcsc, pccb_curr) != 0)
3819285809Sscottl    {
3820285809Sscottl      /* send command back and release the ccb */
3821285809Sscottl      cmnd = &pccb_curr->tiSuperScsiRequest.scsiCmnd;
3822285809Sscottl
3823285809Sscottl      if (cmnd->cdb[0] == RECEIVE_DIAGNOSTIC)
3824285809Sscottl      {
3825285809Sscottl        AGTIAPI_PRINTK("agtiapi_Done: RECEIVE_DIAG pg %d id %d cmnd %p pccb "
3826285809Sscottl                       "%p\n", cmnd->cdb[2], pccb_curr->targetId, cmnd,
3827285809Sscottl                       pccb_curr);
3828285809Sscottl      }
3829285809Sscottl
3830285809Sscottl      CMND_DMA_UNMAP(pmcsc, ccb);
3831285809Sscottl
3832285809Sscottl      /* send the request back to the CAM */
3833285809Sscottl      ccb = pccb_curr->ccb;
3834285809Sscottl      agtiapi_FreeCCB(pmcsc, pccb_curr);
3835285809Sscottl      xpt_done(ccb);
3836285809Sscottl	}
3837285809Sscottl    pccb_curr = pccb_next;
3838285809Sscottl  }
3839285809Sscottl  return;
3840285809Sscottl}
3841285809Sscottl
3842285809Sscottl/******************************************************************************
3843285809Sscottlagtiapi_SMPDone()
3844285809Sscottl
3845285809SscottlPurpose:
3846285809Sscottl  Processing completed ccbs
3847285809SscottlParameters:
3848285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Ponter to HBA data structure
3849285809Sscottl  ccb_t *pccb (IN)                  A pointer to the driver's own CCB, not
3850285809Sscottl                                    CAM's CCB
3851285809SscottlReturn:
3852285809SscottlNote:
3853285809Sscottl******************************************************************************/
3854285809SscottlSTATIC void agtiapi_SMPDone(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3855285809Sscottl{
3856285809Sscottl  pccb_t pccb_curr = pccb;
3857285809Sscottl  pccb_t pccb_next;
3858285809Sscottl
3859285809Sscottl  union ccb * ccb;
3860285809Sscottl
3861285809Sscottl  AGTIAPI_PRINTK("agtiapi_SMPDone: start\n");
3862285809Sscottl
3863285809Sscottl  while (pccb_curr)
3864285809Sscottl  {
3865285809Sscottl    /* start from 1st ccb in the chain */
3866285809Sscottl    pccb_next = pccb_curr->pccbNext;
3867285809Sscottl
3868285809Sscottl    if (agtiapi_CheckSMPError(pmcsc, pccb_curr) != 0)
3869285809Sscottl    {
3870285809Sscottl      CMND_DMA_UNMAP(pmcsc, ccb);
3871285809Sscottl
3872285809Sscottl      /* send the request back to the CAM */
3873285809Sscottl      ccb = pccb_curr->ccb;
3874285809Sscottl      agtiapi_FreeSMPCCB(pmcsc, pccb_curr);
3875285809Sscottl      xpt_done(ccb);
3876285809Sscottl
3877285809Sscottl    }
3878285809Sscottl    pccb_curr = pccb_next;
3879285809Sscottl  }
3880285809Sscottl
3881285809Sscottl  AGTIAPI_PRINTK("agtiapi_SMPDone: Done\n");
3882285809Sscottl  return;
3883285809Sscottl}
3884285809Sscottl
3885285809Sscottl/******************************************************************************
3886285809Sscottlagtiapi_hexdump()
3887285809Sscottl
3888285809SscottlPurpose:
3889285809Sscottl  Utility function for dumping in hex
3890285809SscottlParameters:
3891285809Sscottl  const char *ptitle (IN)  A string to be printed
3892285809Sscottl  bit8 *pbuf (IN)          A pointer to a buffer to be printed.
3893285809Sscottl  int len (IN)             The lengther of the buffer
3894285809SscottlReturn:
3895285809SscottlNote:
3896285809Sscottl******************************************************************************/
3897285809Sscottlvoid agtiapi_hexdump(const char *ptitle, bit8 *pbuf, int len)
3898285809Sscottl{
3899285809Sscottl  int i;
3900285809Sscottl  AGTIAPI_PRINTK("%s - hexdump(len=%d):\n", ptitle, (int)len);
3901285809Sscottl  if (!pbuf)
3902285809Sscottl  {
3903285809Sscottl    AGTIAPI_PRINTK("pbuf is NULL\n");
3904285809Sscottl    return;
3905285809Sscottl  }
3906285809Sscottl  for (i = 0; i < len; )
3907285809Sscottl  {
3908285809Sscottl    if (len - i > 4)
3909285809Sscottl    {
3910285809Sscottl      AGTIAPI_PRINTK( " 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", pbuf[i], pbuf[i+1],
3911285809Sscottl                      pbuf[i+2], pbuf[i+3] );
3912285809Sscottl      i += 4;
3913285809Sscottl    }
3914285809Sscottl    else
3915285809Sscottl    {
3916285809Sscottl      AGTIAPI_PRINTK(" 0x%02x,", pbuf[i]);
3917285809Sscottl      i++;
3918285809Sscottl    }
3919285809Sscottl  }
3920285809Sscottl  AGTIAPI_PRINTK("\n");
3921285809Sscottl}
3922285809Sscottl
3923285809Sscottl
3924285809Sscottl/******************************************************************************
3925285809Sscottlagtiapi_CheckError()
3926285809Sscottl
3927285809SscottlPurpose:
3928285809Sscottl  Processes status pertaining to the ccb -- whether it was
3929285809Sscottl  completed successfully, aborted, or error encountered.
3930285809SscottlParameters:
3931285809Sscottl  ag_card_t *pCard (IN)  Pointer to HBA data structure
3932285809Sscottl  ccb_t *pccd (IN)       A pointer to the driver's own CCB, not CAM's CCB
3933285809SscottlReturn:
3934285809Sscottl  0 - the command retry is required
3935285809Sscottl  1 - the command process is completed
3936285809SscottlNote:
3937285809Sscottl
3938285809Sscottl******************************************************************************/
3939285809SscottlSTATIC U32 agtiapi_CheckError(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3940285809Sscottl{
3941285809Sscottl  ag_device_t      *pDevice;
3942285809Sscottl  // union ccb * ccb = pccb->ccb;
3943285809Sscottl  union ccb * ccb;
3944285809Sscottl  int is_error, TID;
3945285809Sscottl
3946285809Sscottl  if (pccb == NULL) {
3947285809Sscottl    return 0;
3948285809Sscottl  }
3949285809Sscottl  ccb = pccb->ccb;
3950285809Sscottl  AGTIAPI_IO("agtiapi_CheckError: start\n");
3951285809Sscottl  if (ccb == NULL)
3952285809Sscottl  {
3953285809Sscottl    /* shouldn't be here but just in case we do */
3954285809Sscottl    AGTIAPI_PRINTK("agtiapi_CheckError: CCB orphan = %p ERROR\n", pccb);
3955285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
3956285809Sscottl    return 0;
3957285809Sscottl  }
3958285809Sscottl
3959285809Sscottl  is_error = 1;
3960285809Sscottl  pDevice = NULL;
3961285809Sscottl  if (pmcsc != NULL && pccb->targetId >= 0 && pccb->targetId < maxTargets)
3962285809Sscottl  {
3963285809Sscottl    if (pmcsc->pWWNList != NULL)
3964285809Sscottl    {
3965285809Sscottl      TID = INDEX(pmcsc, pccb->targetId);
3966285809Sscottl      if (TID < maxTargets)
3967285809Sscottl      {
3968285809Sscottl        pDevice = &pmcsc->pDevList[TID];
3969285809Sscottl        if (pDevice != NULL)
3970285809Sscottl        {
3971285809Sscottl          is_error = 0;
3972285809Sscottl        }
3973285809Sscottl      }
3974285809Sscottl    }
3975285809Sscottl  }
3976285809Sscottl  if (is_error)
3977285809Sscottl  {
3978285809Sscottl    AGTIAPI_PRINTK("agtiapi_CheckError: pDevice == NULL\n");
3979285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
3980285809Sscottl    return 0;
3981285809Sscottl  }
3982285809Sscottl
3983285809Sscottl  /* SCSI status */
3984285809Sscottl  ccb->csio.scsi_status = pccb->scsiStatus;
3985285809Sscottl
3986285809Sscottl   if(pDevice->CCBCount > 0){
3987285809Sscottl    atomic_subtract_int(&pDevice->CCBCount,1);
3988285809Sscottl}
3989285809Sscottl  AG_LOCAL_LOCK(&pmcsc->freezeLock);
3990285809Sscottl  if(pmcsc->freezeSim == agTRUE)
3991285809Sscottl  {
3992285809Sscottl    pmcsc->freezeSim = agFALSE;
3993285809Sscottl    xpt_release_simq(pmcsc->sim, 1);
3994285809Sscottl  }
3995285809Sscottl  AG_LOCAL_UNLOCK(&pmcsc->freezeLock);
3996285809Sscottl
3997285809Sscottl  switch (pccb->ccbStatus)
3998285809Sscottl  {
3999285809Sscottl  case tiIOSuccess:
4000285809Sscottl    AGTIAPI_IO("agtiapi_CheckError: tiIOSuccess pccb %p\n", pccb);
4001285809Sscottl    /* CAM status */
4002285809Sscottl    if (pccb->scsiStatus == SCSI_STATUS_OK)
4003285809Sscottl    {
4004285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP;
4005285809Sscottl    }
4006285809Sscottl    else
4007285809Sscottl      if (pccb->scsiStatus == SCSI_TASK_ABORTED)
4008285809Sscottl    {
4009285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4010285809Sscottl    }
4011285809Sscottl    else
4012285809Sscottl    {
4013285809Sscottl      ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
4014285809Sscottl    }
4015285809Sscottl    if (ccb->csio.scsi_status == SCSI_CHECK_CONDITION)
4016285809Sscottl    {
4017285809Sscottl      ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
4018285809Sscottl    }
4019285809Sscottl
4020285809Sscottl    break;
4021285809Sscottl
4022285809Sscottl  case tiIOOverRun:
4023285809Sscottl    AGTIAPI_PRINTK("agtiapi_CheckError: tiIOOverRun pccb %p\n", pccb);
4024285809Sscottl    /* resid is ignored for this condition */
4025285809Sscottl    ccb->csio.resid = 0;
4026285809Sscottl    ccb->ccb_h.status = CAM_DATA_RUN_ERR;
4027285809Sscottl    break;
4028285809Sscottl  case tiIOUnderRun:
4029285809Sscottl    AGTIAPI_PRINTK("agtiapi_CheckError: tiIOUnderRun pccb %p\n", pccb);
4030285809Sscottl    ccb->csio.resid = pccb->scsiStatus;
4031285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
4032285809Sscottl    ccb->csio.scsi_status = SCSI_STATUS_OK;
4033285809Sscottl    break;
4034285809Sscottl
4035285809Sscottl  case tiIOFailed:
4036285809Sscottl    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4037285809Sscottl                    pccb, pccb->scsiStatus, pccb->targetId );
4038285809Sscottl    if (pccb->scsiStatus == tiDeviceBusy)
4039285809Sscottl    {
4040285809Sscottl      AGTIAPI_IO( "agtiapi_CheckError: pccb %p tiIOFailed - tiDetailBusy\n",
4041285809Sscottl                  pccb );
4042285809Sscottl      ccb->ccb_h.status &= ~CAM_STATUS_MASK;
4043285809Sscottl      ccb->ccb_h.status |= CAM_REQUEUE_REQ;
4044285809Sscottl      if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0)
4045285809Sscottl      {
4046285809Sscottl        ccb->ccb_h.status |= CAM_DEV_QFRZN;
4047285809Sscottl        xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
4048285809Sscottl      }
4049285809Sscottl    }
4050285809Sscottl    else if(pccb->scsiStatus == tiBusy)
4051285809Sscottl    {
4052285809Sscottl      AG_LOCAL_LOCK(&pmcsc->freezeLock);
4053285809Sscottl      if(pmcsc->freezeSim == agFALSE)
4054285809Sscottl      {
4055285809Sscottl        pmcsc->freezeSim = agTRUE;
4056285809Sscottl        xpt_freeze_simq(pmcsc->sim, 1);
4057285809Sscottl      }
4058285809Sscottl      AG_LOCAL_UNLOCK(&pmcsc->freezeLock);
4059285809Sscottl      ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
4060285809Sscottl      ccb->ccb_h.status |= CAM_REQUEUE_REQ;
4061285809Sscottl    }
4062285809Sscottl    else if (pccb->scsiStatus == tiDetailNoLogin)
4063285809Sscottl    {
4064285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4065285809Sscottl                      "tiDetailNoLogin ERROR\n", pccb );
4066285809Sscottl      ccb->ccb_h.status = CAM_DEV_NOT_THERE;
4067285809Sscottl    }
4068285809Sscottl    else if (pccb->scsiStatus == tiDetailNotValid)
4069285809Sscottl    {
4070285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4071285809Sscottl                      "tiDetailNotValid ERROR\n", pccb );
4072285809Sscottl      ccb->ccb_h.status = CAM_REQ_INVALID;
4073285809Sscottl    }
4074285809Sscottl    else if (pccb->scsiStatus == tiDetailAbortLogin)
4075285809Sscottl    {
4076285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4077285809Sscottl                      "tiDetailAbortLogin ERROR\n", pccb );
4078285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4079285809Sscottl    }
4080285809Sscottl    else if (pccb->scsiStatus == tiDetailAbortReset)
4081285809Sscottl    {
4082285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4083285809Sscottl                      "tiDetailAbortReset ERROR\n", pccb );
4084285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4085285809Sscottl    }
4086285809Sscottl    else if (pccb->scsiStatus == tiDetailAborted)
4087285809Sscottl    {
4088285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4089285809Sscottl                      "tiDetailAborted ERROR\n", pccb );
4090285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4091285809Sscottl    }
4092285809Sscottl    else if (pccb->scsiStatus == tiDetailOtherError)
4093285809Sscottl    {
4094285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4095285809Sscottl                      "tiDetailOtherError ERROR\n", pccb );
4096285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4097285809Sscottl    }
4098285809Sscottl    break;
4099285809Sscottl  case tiIODifError:
4100285809Sscottl    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4101285809Sscottl                    pccb, pccb->scsiStatus, pccb->targetId );
4102285809Sscottl    if (pccb->scsiStatus == tiDetailDifAppTagMismatch)
4103285809Sscottl    {
4104285809Sscottl      AGTIAPI_IO( "agtiapi_CheckError: pccb %p tiIOFailed - "
4105285809Sscottl                  "tiDetailDifAppTagMismatch\n", pccb );
4106285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4107285809Sscottl    }
4108285809Sscottl    else if (pccb->scsiStatus == tiDetailDifRefTagMismatch)
4109285809Sscottl    {
4110285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4111285809Sscottl                      "tiDetailDifRefTagMismatch\n", pccb );
4112285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4113285809Sscottl    }
4114285809Sscottl    else if (pccb->scsiStatus == tiDetailDifCrcMismatch)
4115285809Sscottl    {
4116285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4117285809Sscottl                      "tiDetailDifCrcMismatch\n", pccb );
4118285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4119285809Sscottl    }
4120285809Sscottl    break;
4121285809Sscottl#ifdef HIALEAH_ENCRYPTION
4122285809Sscottl  case tiIOEncryptError:
4123285809Sscottl    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4124285809Sscottl                    pccb, pccb->scsiStatus, pccb->targetId );
4125285809Sscottl    if (pccb->scsiStatus == tiDetailDekKeyCacheMiss)
4126285809Sscottl    {
4127285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: %s: pccb %p tiIOFailed - "
4128285809Sscottl                      "tiDetailDekKeyCacheMiss ERROR\n",
4129285809Sscottl                      __FUNCTION__, pccb );
4130285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4131285809Sscottl      agtiapi_HandleEncryptedIOFailure(pDevice, pccb);
4132285809Sscottl    }
4133285809Sscottl    else if (pccb->scsiStatus == tiDetailDekIVMismatch)
4134285809Sscottl    {
4135285809Sscottl      AGTIAPI_PRINTK( "agtiapi_CheckError: %s: pccb %p tiIOFailed - "
4136285809Sscottl                      "tiDetailDekIVMismatch ERROR\n", __FUNCTION__, pccb );
4137285809Sscottl      ccb->ccb_h.status = CAM_REQ_ABORTED;
4138285809Sscottl      agtiapi_HandleEncryptedIOFailure(pDevice, pccb);
4139285809Sscottl    }
4140285809Sscottl    break;
4141285809Sscottl#endif
4142285809Sscottl  default:
4143285809Sscottl    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOdefault %d id %d ERROR\n",
4144285809Sscottl                    pccb, pccb->ccbStatus, pccb->targetId );
4145285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4146285809Sscottl    break;
4147285809Sscottl  }
4148285809Sscottl
4149285809Sscottl  return 1;
4150285809Sscottl}
4151285809Sscottl
4152285809Sscottl
4153285809Sscottl/******************************************************************************
4154285809Sscottlagtiapi_SMPCheckError()
4155285809Sscottl
4156285809SscottlPurpose:
4157285809Sscottl  Processes status pertaining to the ccb -- whether it was
4158285809Sscottl  completed successfully, aborted, or error encountered.
4159285809SscottlParameters:
4160285809Sscottl  ag_card_t *pCard (IN)  Pointer to HBA data structure
4161285809Sscottl  ccb_t *pccd (IN)       A pointer to the driver's own CCB, not CAM's CCB
4162285809SscottlReturn:
4163285809Sscottl  0 - the command retry is required
4164285809Sscottl  1 - the command process is completed
4165285809SscottlNote:
4166285809Sscottl
4167285809Sscottl******************************************************************************/
4168285809SscottlSTATIC U32 agtiapi_CheckSMPError( struct agtiapi_softc *pmcsc, ccb_t *pccb )
4169285809Sscottl{
4170285809Sscottl	union ccb * ccb = pccb->ccb;
4171285809Sscottl
4172285809Sscottl	AGTIAPI_PRINTK("agtiapi_CheckSMPError: start\n");
4173285809Sscottl
4174285809Sscottl	if (!ccb)
4175285809Sscottl	{
4176285809Sscottl		/* shouldn't be here but just in case we do */
4177285809Sscottl		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: CCB orphan = %p ERROR\n",
4178285809Sscottl                              pccb );
4179285809Sscottl		agtiapi_FreeSMPCCB(pmcsc, pccb);
4180285809Sscottl		return 0;
4181285809Sscottl	}
4182285809Sscottl
4183285809Sscottl	switch (pccb->ccbStatus)
4184285809Sscottl	{
4185285809Sscottl	case tiSMPSuccess:
4186285809Sscottl		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: tiSMPSuccess pccb %p\n",
4187285809Sscottl                              pccb );
4188285809Sscottl		/* CAM status */
4189285809Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
4190285809Sscottl		break;
4191285809Sscottl  case tiSMPFailed:
4192285809Sscottl		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: tiSMPFailed pccb %p\n",
4193285809Sscottl                              pccb );
4194285809Sscottl		/* CAM status */
4195285809Sscottl		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4196285809Sscottl		break;
4197285809Sscottl  default:
4198285809Sscottl		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: pccb %p tiSMPdefault %d "
4199285809Sscottl                              "id %d ERROR\n",
4200285809Sscottl                              pccb,
4201285809Sscottl                              pccb->ccbStatus,
4202285809Sscottl                              pccb->targetId );
4203285809Sscottl		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4204285809Sscottl		break;
4205285809Sscottl	}
4206285809Sscottl
4207285809Sscottl
4208285809Sscottl  return 1;
4209285809Sscottl
4210285809Sscottl}
4211285809Sscottl
4212285809Sscottl/******************************************************************************
4213285809Sscottlagtiapi_HandleEncryptedIOFailure():
4214285809Sscottl
4215285809SscottlPurpose:
4216285809SscottlParameters:
4217285809SscottlReturn:
4218285809SscottlNote:
4219285809Sscottl  Currently not used.
4220285809Sscottl******************************************************************************/
4221285809Sscottlvoid agtiapi_HandleEncryptedIOFailure(ag_device_t *pDev, ccb_t *pccb)
4222285809Sscottl{
4223285809Sscottl
4224285809Sscottl  AGTIAPI_PRINTK("agtiapi_HandleEncryptedIOFailure: start\n");
4225285809Sscottl  return;
4226285809Sscottl}
4227285809Sscottl
4228285809Sscottl/******************************************************************************
4229285809Sscottlagtiapi_Retry()
4230285809Sscottl
4231285809SscottlPurpose:
4232285809Sscottl  Retry a ccb.
4233285809SscottlParameters:
4234285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to the HBA structure
4235285809Sscottl  ccb_t *pccb (IN)            A pointer to the driver's own CCB, not CAM's CCB
4236285809SscottlReturn:
4237285809SscottlNote:
4238285809Sscottl  Currently not used.
4239285809Sscottl******************************************************************************/
4240285809SscottlSTATIC void agtiapi_Retry(struct agtiapi_softc *pmcsc, ccb_t *pccb)
4241285809Sscottl{
4242285809Sscottl  pccb->retryCount++;
4243285809Sscottl  pccb->flags      = ACTIVE | AGTIAPI_RETRY;
4244285809Sscottl  pccb->ccbStatus  = 0;
4245285809Sscottl  pccb->scsiStatus = 0;
4246285809Sscottl  pccb->startTime  = ticks;
4247285809Sscottl
4248285809Sscottl  AGTIAPI_PRINTK( "agtiapi_Retry: start\n" );
4249285809Sscottl  AGTIAPI_PRINTK( "agtiapi_Retry: ccb %p retry %d flgs x%x\n", pccb,
4250285809Sscottl                  pccb->retryCount, pccb->flags );
4251285809Sscottl
4252285809Sscottl  agtiapi_QueueCCB(pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
4253285809Sscottl                   AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb);
4254285809Sscottl  return;
4255285809Sscottl}
4256285809Sscottl
4257285809Sscottl
4258285809Sscottl/******************************************************************************
4259285809Sscottlagtiapi_DumpCCB()
4260285809Sscottl
4261285809SscottlPurpose:
4262285809Sscottl  Dump CCB for debuging
4263285809SscottlParameters:
4264285809Sscottl  ccb_t *pccb (IN)  A pointer to the driver's own CCB, not CAM's CCB
4265285809SscottlReturn:
4266285809SscottlNote:
4267285809Sscottl******************************************************************************/
4268285809SscottlSTATIC void agtiapi_DumpCCB(ccb_t *pccb)
4269285809Sscottl{
4270285809Sscottl  AGTIAPI_PRINTK("agtiapi_DumpCCB: pccb %p, devHandle %p, tid %d, lun %d\n",
4271285809Sscottl         pccb,
4272285809Sscottl         pccb->devHandle,
4273285809Sscottl         pccb->targetId,
4274285809Sscottl         pccb->lun);
4275285809Sscottl  AGTIAPI_PRINTK("flag 0x%x, add_mode 0x%x, ccbStatus 0x%x, scsiStatus 0x%x\n",
4276285809Sscottl         pccb->flags,
4277285809Sscottl         pccb->addrMode,
4278285809Sscottl         pccb->ccbStatus,
4279285809Sscottl         pccb->scsiStatus);
4280285809Sscottl  AGTIAPI_PRINTK("scsi comand = 0x%x, numSgElements = %d\n",
4281285809Sscottl	 pccb->tiSuperScsiRequest.scsiCmnd.cdb[0],
4282285809Sscottl         pccb->numSgElements);
4283285809Sscottl  AGTIAPI_PRINTK("dataLen = 0x%x, sens_len = 0x%x\n",
4284285809Sscottl         pccb->dataLen,
4285285809Sscottl         pccb->senseLen);
4286285809Sscottl  AGTIAPI_PRINTK("tiSuperScsiRequest:\n");
4287285809Sscottl  AGTIAPI_PRINTK("scsiCmnd: expDataLength 0x%x, taskAttribute 0x%x\n",
4288285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.expDataLength,
4289285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.taskAttribute);
4290285809Sscottl  AGTIAPI_PRINTK("cdb[0] = 0x%x, cdb[1] = 0x%x, cdb[2] = 0x%x, cdb[3] = 0x%x\n",
4291285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[0],
4292285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[1],
4293285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[2],
4294285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[3]);
4295285809Sscottl  AGTIAPI_PRINTK("cdb[4] = 0x%x, cdb[5] = 0x%x, cdb[6] = 0x%x, cdb[7] = 0x%x\n",
4296285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[4],
4297285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[5],
4298285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[6],
4299285809Sscottl         pccb->tiSuperScsiRequest.scsiCmnd.cdb[7]);
4300285809Sscottl  AGTIAPI_PRINTK( "cdb[8] = 0x%x, cdb[9] = 0x%x, cdb[10] = 0x%x, "
4301285809Sscottl                  "cdb[11] = 0x%x\n",
4302285809Sscottl                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[8],
4303285809Sscottl                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[9],
4304285809Sscottl                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[10],
4305285809Sscottl                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[11] );
4306285809Sscottl  AGTIAPI_PRINTK("agSgl1: upper 0x%x, lower 0x%x, len 0x%x, type %d\n",
4307285809Sscottl         pccb->tiSuperScsiRequest.agSgl1.upper,
4308285809Sscottl         pccb->tiSuperScsiRequest.agSgl1.lower,
4309285809Sscottl         pccb->tiSuperScsiRequest.agSgl1.len,
4310285809Sscottl         pccb->tiSuperScsiRequest.agSgl1.type);
4311285809Sscottl}
4312285809Sscottl
4313285809Sscottl/******************************************************************************
4314285809Sscottlagtiapi_eh_HostReset()
4315285809Sscottl
4316285809SscottlPurpose:
4317285809Sscottl  A new error handler of Host Reset command.
4318285809SscottlParameters:
4319285809Sscottl  scsi_cmnd *cmnd (IN)  Pointer to a command to the HBA to be reset
4320285809SscottlReturn:
4321285809Sscottl  SUCCESS - success
4322285809Sscottl  FAILED  - fail
4323285809SscottlNote:
4324285809Sscottl******************************************************************************/
4325285809Sscottlint agtiapi_eh_HostReset( struct agtiapi_softc *pmcsc, union ccb *cmnd )
4326285809Sscottl{
4327285809Sscottl  AGTIAPI_PRINTK( "agtiapi_eh_HostReset: ccb pointer %p\n",
4328285809Sscottl                  cmnd );
4329285809Sscottl
4330285809Sscottl  if( cmnd == NULL )
4331285809Sscottl  {
4332285809Sscottl    printf( "agtiapi_eh_HostReset: null command, skipping reset.\n" );
4333285809Sscottl    return tiInvalidHandle;
4334285809Sscottl  }
4335285809Sscottl
4336285809Sscottl#ifdef LOGEVENT
4337285809Sscottl  agtiapi_LogEvent( pmcsc,
4338285809Sscottl                    IOCTL_EVT_SEV_INFORMATIONAL,
4339285809Sscottl                    0,
4340285809Sscottl                    agNULL,
4341285809Sscottl                    0,
4342285809Sscottl                    "agtiapi_eh_HostReset! " );
4343285809Sscottl#endif
4344285809Sscottl
4345285809Sscottl  return agtiapi_DoSoftReset( pmcsc );
4346285809Sscottl}
4347285809Sscottl
4348285809Sscottl
4349285809Sscottlint agtiapi_eh_DeviceReset( struct agtiapi_softc *pmcsc, union ccb *cmnd )
4350285809Sscottl{
4351285809Sscottl  AGTIAPI_PRINTK( "agtiapi_eh_HostReset: ccb pointer %p\n",
4352285809Sscottl                  cmnd );
4353285809Sscottl
4354285809Sscottl  if( cmnd == NULL )
4355285809Sscottl  {
4356285809Sscottl    printf( "agtiapi_eh_HostReset: null command, skipping reset.\n" );
4357285809Sscottl    return tiInvalidHandle;
4358285809Sscottl  }
4359285809Sscottl  return agtiapi_DoSoftReset( pmcsc );
4360285809Sscottl}
4361285809Sscottl/******************************************************************************
4362285809Sscottlagtiapi_QueueCCB()
4363285809Sscottl
4364285809SscottlPurpose:
4365285809Sscottl  Put ccb in ccb queue at the tail
4366285809SscottlParameters:
4367285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4368285809Sscottl  pccb_t *phead (IN)                Double pointer to ccb queue head
4369285809Sscottl  pccb_t *ptail (IN)                Double pointer to ccb queue tail
4370285809Sscottl  ccb_t *pccb (IN)                  Poiner to a ccb to be queued
4371285809SscottlReturn:
4372285809SscottlNote:
4373285809Sscottl  Put the ccb to the tail of queue
4374285809Sscottl******************************************************************************/
4375285809SscottlSTATIC void agtiapi_QueueCCB( struct agtiapi_softc *pmcsc,
4376285809Sscottl                              pccb_t *phead,
4377285809Sscottl                              pccb_t *ptail,
4378285809Sscottl#ifdef AGTIAPI_LOCAL_LOCK
4379285809Sscottl                              struct mtx *mutex,
4380285809Sscottl#endif
4381285809Sscottl                              ccb_t *pccb )
4382285809Sscottl{
4383285809Sscottl  AGTIAPI_IO( "agtiapi_QueueCCB: start\n" );
4384285809Sscottl  AGTIAPI_IO( "agtiapi_QueueCCB: %p to %p\n", pccb, phead );
4385285809Sscottl  if (phead == NULL || ptail == NULL)
4386285809Sscottl  {
4387285809Sscottl    panic( "agtiapi_QueueCCB: phead %p ptail %p", phead, ptail );
4388285809Sscottl  }
4389285809Sscottl  pccb->pccbNext = NULL;
4390285809Sscottl  AG_LOCAL_LOCK( mutex );
4391285809Sscottl  if (*phead == NULL)
4392285809Sscottl  {
4393285809Sscottl    //WARN_ON(*ptail != NULL); /* critical, just get more logs */
4394285809Sscottl    *phead = pccb;
4395285809Sscottl  }
4396285809Sscottl  else
4397285809Sscottl  {
4398285809Sscottl    //WARN_ON(*ptail == NULL); /* critical, just get more logs */
4399285809Sscottl    if (*ptail)
4400285809Sscottl      (*ptail)->pccbNext = pccb;
4401285809Sscottl  }
4402285809Sscottl  *ptail = pccb;
4403285809Sscottl  AG_LOCAL_UNLOCK( mutex );
4404285809Sscottl  return;
4405285809Sscottl}
4406285809Sscottl
4407285809Sscottl
4408285809Sscottl/******************************************************************************
4409285809Sscottlagtiapi_QueueCCB()
4410285809Sscottl
4411285809SscottlPurpose:
4412285809Sscottl
4413285809SscottlParameters:
4414285809Sscottl
4415285809Sscottl
4416285809SscottlReturn:
4417285809SscottlNote:
4418285809Sscottl
4419285809Sscottl******************************************************************************/
4420285809Sscottlstatic int agtiapi_QueueSMP(struct agtiapi_softc *pmcsc, union ccb * ccb)
4421285809Sscottl{
4422285809Sscottl  pccb_t pccb = agNULL; /* call dequeue */
4423285809Sscottl  int        status = tiSuccess;
4424285809Sscottl  int        targetID = xpt_path_target_id(ccb->ccb_h.path);
4425285809Sscottl
4426285809Sscottl  AGTIAPI_PRINTK("agtiapi_QueueSMP: start\n");
4427285809Sscottl
4428285809Sscottl  /* get a ccb */
4429285809Sscottl  if ((pccb = agtiapi_GetCCB(pmcsc)) == NULL)
4430285809Sscottl  {
4431285809Sscottl    AGTIAPI_PRINTK("agtiapi_QueueSMP: GetCCB ERROR\n");
4432285809Sscottl    ccb->ccb_h.status = CAM_REQ_CMP;
4433285809Sscottl    xpt_done(ccb);
4434285809Sscottl    return tiBusy;
4435285809Sscottl  }
4436285809Sscottl  pccb->pmcsc = pmcsc;
4437285809Sscottl
4438285809Sscottl  /* initialize Command Control Block (CCB) */
4439285809Sscottl  pccb->targetId   = targetID;
4440285809Sscottl  pccb->ccb        = ccb;	/* for struct scsi_cmnd */
4441285809Sscottl
4442285809Sscottl  status = agtiapi_PrepareSMPSGList(pmcsc, pccb);
4443285809Sscottl
4444285809Sscottl  if (status != tiSuccess)
4445285809Sscottl  {
4446285809Sscottl    AGTIAPI_PRINTK("agtiapi_QueueSMP: agtiapi_PrepareSMPSGList failure\n");
4447285809Sscottl    agtiapi_FreeCCB(pmcsc, pccb);
4448285809Sscottl    if (status == tiReject)
4449285809Sscottl    {
4450285809Sscottl      ccb->ccb_h.status = CAM_REQ_INVALID;
4451285809Sscottl    }
4452285809Sscottl    else
4453285809Sscottl    {
4454285809Sscottl      ccb->ccb_h.status = CAM_REQ_CMP;
4455285809Sscottl    }
4456285809Sscottl    xpt_done(ccb);
4457285809Sscottl    return tiError;
4458285809Sscottl  }
4459285809Sscottl
4460285809Sscottl  return status;
4461285809Sscottl}
4462285809Sscottl
4463285809Sscottl/******************************************************************************
4464285809Sscottlagtiapi_SetLunField()
4465285809Sscottl
4466285809SscottlPurpose:
4467285809Sscottl  Set LUN field based on different address mode
4468285809SscottlParameters:
4469285809Sscottl  ccb_t *pccb (IN)  A pointer to the driver's own CCB, not CAM's CCB
4470285809SscottlReturn:
4471285809SscottlNote:
4472285809Sscottl******************************************************************************/
4473285809Sscottlvoid agtiapi_SetLunField(ccb_t *pccb)
4474285809Sscottl{
4475285809Sscottl  U08 *pchar;
4476285809Sscottl
4477285809Sscottl  pchar = (U08 *)&pccb->tiSuperScsiRequest.scsiCmnd.lun;
4478285809Sscottl
4479285809Sscottl//  AGTIAPI_PRINTK("agtiapi_SetLunField: start\n");
4480285809Sscottl
4481285809Sscottl  switch (pccb->addrMode)
4482285809Sscottl  {
4483285809Sscottl  case AGTIAPI_PERIPHERAL:
4484285809Sscottl       *pchar++ = 0;
4485285809Sscottl       *pchar   = (U08)pccb->lun;
4486285809Sscottl       break;
4487285809Sscottl  case AGTIAPI_VOLUME_SET:
4488285809Sscottl       *pchar++ = (AGTIAPI_VOLUME_SET << AGTIAPI_ADDRMODE_SHIFT) |
4489285809Sscottl                  (U08)((pccb->lun >> 8) & 0x3F);
4490285809Sscottl       *pchar   = (U08)pccb->lun;
4491285809Sscottl       break;
4492285809Sscottl  case AGTIAPI_LUN_ADDR:
4493285809Sscottl       *pchar++ = (AGTIAPI_LUN_ADDR << AGTIAPI_ADDRMODE_SHIFT) |
4494285809Sscottl                  pccb->targetId;
4495285809Sscottl       *pchar   = (U08)pccb->lun;
4496285809Sscottl       break;
4497285809Sscottl  }
4498285809Sscottl
4499285809Sscottl
4500285809Sscottl}
4501285809Sscottl
4502285809Sscottl
4503285809Sscottl/*****************************************************************************
4504285809Sscottlagtiapi_FreeCCB()
4505285809Sscottl
4506285809SscottlPurpose:
4507285809Sscottl  Free a ccb and put it back to ccbFreeList.
4508285809SscottlParameters:
4509285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4510285809Sscottl  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4511285809Sscottl                                    CAM's CCB
4512285809SscottlReturns:
4513285809SscottlNote:
4514285809Sscottl*****************************************************************************/
4515285809SscottlSTATIC void agtiapi_FreeCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4516285809Sscottl{
4517285809Sscottl  union ccb *ccb = pccb->ccb;
4518285809Sscottl  bus_dmasync_op_t op;
4519285809Sscottl
4520285809Sscottl  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4521285809Sscottl  AGTIAPI_IO( "agtiapi_FreeCCB: start %p\n", pccb );
4522285809Sscottl
4523285809Sscottl#ifdef AGTIAPI_TEST_EPL
4524285809Sscottl  tiEncrypt_t *encrypt;
4525285809Sscottl#endif
4526285809Sscottl
4527285809Sscottl  agtiapi_DumpCDB( "agtiapi_FreeCCB", pccb );
4528285809Sscottl
4529285809Sscottl  if (pccb->sgList != agNULL)
4530285809Sscottl  {
4531285809Sscottl    AGTIAPI_IO( "agtiapi_FreeCCB: pccb->sgList is NOT null\n" );
4532285809Sscottl  }
4533285809Sscottl  else
4534285809Sscottl  {
4535285809Sscottl    AGTIAPI_PRINTK( "agtiapi_FreeCCB: pccb->sgList is null\n" );
4536285809Sscottl  }
4537285809Sscottl
4538285809Sscottl  /* set data transfer direction */
4539285809Sscottl  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
4540285809Sscottl  {
4541285809Sscottl    op = BUS_DMASYNC_POSTWRITE;
4542285809Sscottl  }
4543285809Sscottl  else
4544285809Sscottl  {
4545285809Sscottl    op = BUS_DMASYNC_POSTREAD;
4546285809Sscottl  }
4547285809Sscottl
4548285809Sscottl  if (pccb->numSgElements == 0)
4549285809Sscottl  {
4550285809Sscottl    // do nothing
4551285809Sscottl    AGTIAPI_IO( "agtiapi_FreeCCB: numSgElements zero\n" );
4552285809Sscottl  }
4553285809Sscottl  else if (pccb->numSgElements == 1)
4554285809Sscottl  {
4555285809Sscottl    AGTIAPI_IO( "agtiapi_FreeCCB: numSgElements is one\n" );
4556285809Sscottl    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4557285809Sscottl    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4558285809Sscottl    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4559285809Sscottl  }
4560285809Sscottl  else
4561285809Sscottl  {
4562285809Sscottl    AGTIAPI_PRINTK( "agtiapi_FreeCCB: numSgElements 2 or higher \n" );
4563285809Sscottl    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4564285809Sscottl    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4565285809Sscottl    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4566285809Sscottl  }
4567285809Sscottl
4568285809Sscottl#ifdef AGTIAPI_TEST_DPL
4569285809Sscottl  if (pccb->tiSuperScsiRequest.Dif.enableDIFPerLA == TRUE) {
4570285809Sscottl    if(pccb->dplPtr)
4571285809Sscottl        memset( (char *) pccb->dplPtr,
4572285809Sscottl                0,
4573285809Sscottl                MAX_DPL_REGIONS * sizeof(dplaRegion_t) );
4574285809Sscottl    pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = FALSE;
4575285809Sscottl    pccb->tiSuperScsiRequest.Dif.DIFPerLAAddrLo = 0;
4576285809Sscottl    pccb->tiSuperScsiRequest.Dif.DIFPerLAAddrHi = 0;
4577285809Sscottl  }
4578285809Sscottl#endif
4579285809Sscottl
4580285809Sscottl#ifdef AGTIAPI_TEST_EPL
4581285809Sscottl  encrypt = &pccb->tiSuperScsiRequest.Encrypt;
4582285809Sscottl  if (encrypt->enableEncryptionPerLA == TRUE) {
4583285809Sscottl    encrypt->enableEncryptionPerLA = FALSE;
4584285809Sscottl    encrypt->EncryptionPerLAAddrLo = 0;
4585285809Sscottl    encrypt->EncryptionPerLAAddrHi = 0;
4586285809Sscottl  }
4587285809Sscottl#endif
4588285809Sscottl
4589285809Sscottl#ifdef ENABLE_SATA_DIF
4590285809Sscottl  if (pccb->holePtr && pccb->dmaHandleHole)
4591285809Sscottl    pci_free_consistent( pmcsc->pCardInfo->pPCIDev,
4592285809Sscottl                         512,
4593285809Sscottl                         pccb->holePtr,
4594285809Sscottl                         pccb->dmaHandleHole );
4595285809Sscottl  pccb->holePtr    = 0;
4596285809Sscottl  pccb->dmaHandleHole = 0;
4597285809Sscottl#endif
4598285809Sscottl
4599285809Sscottl  pccb->dataLen    = 0;
4600285809Sscottl  pccb->retryCount = 0;
4601285809Sscottl  pccb->ccbStatus  = 0;
4602285809Sscottl  pccb->scsiStatus = 0;
4603285809Sscottl  pccb->startTime  = 0;
4604285809Sscottl  pccb->dmaHandle  = 0;
4605285809Sscottl  pccb->numSgElements = 0;
4606285809Sscottl  pccb->tiIORequest.tdData = 0;
4607285809Sscottl  memset((void *)&pccb->tiSuperScsiRequest, 0, AGSCSI_INIT_XCHG_LEN);
4608285809Sscottl
4609285809Sscottl#ifdef HIALEAH_ENCRYPTION
4610285809Sscottl  if (pmcsc->encrypt)
4611285809Sscottl    agtiapi_CleanupEncryptedIO(pmcsc, pccb);
4612285809Sscottl#endif
4613285809Sscottl
4614285809Sscottl  pccb->flags      = 0;
4615285809Sscottl  pccb->ccb        = NULL;
4616285809Sscottl  pccb->pccbIO = NULL;
4617285809Sscottl  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4618285809Sscottl  pmcsc->ccbFreeList = (caddr_t *)pccb;
4619285809Sscottl
4620285809Sscottl  pmcsc->activeCCB--;
4621285809Sscottl
4622285809Sscottl  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4623285809Sscottl  return;
4624285809Sscottl}
4625285809Sscottl
4626285809Sscottl
4627285809Sscottl/******************************************************************************
4628285809Sscottlagtiapi_FlushCCBs()
4629285809Sscottl
4630285809SscottlPurpose:
4631285809Sscottl  Flush all in processed ccbs.
4632285809SscottlParameters:
4633285809Sscottl  ag_card_t *pCard (IN)  Pointer to HBA data structure
4634285809Sscottl  U32 flag (IN)            Flag to call back
4635285809SscottlReturn:
4636285809SscottlNote:
4637285809Sscottl******************************************************************************/
4638285809SscottlSTATIC void agtiapi_FlushCCBs( struct agtiapi_softc *pCard, U32 flag )
4639285809Sscottl{
4640285809Sscottl  union ccb *ccb;
4641285809Sscottl  ccb_t     *pccb;
4642285809Sscottl
4643285809Sscottl  AGTIAPI_PRINTK( "agtiapi_FlushCCBs: enter \n" );
4644285809Sscottl  for( pccb = (pccb_t)pCard->ccbChainList;
4645285809Sscottl       pccb != NULL;
4646285809Sscottl       pccb = pccb->pccbChainNext ) {
4647285809Sscottl    if( pccb->flags == 0 )
4648285809Sscottl    {
4649285809Sscottl      // printf( "agtiapi_FlushCCBs: nothing, continue \n" );
4650285809Sscottl      continue;
4651285809Sscottl    }
4652285809Sscottl    ccb = pccb->ccb;
4653285809Sscottl    if ( pccb->flags & ( TASK_MANAGEMENT | DEV_RESET ) )
4654285809Sscottl    {
4655285809Sscottl      AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeTMCCB \n" );
4656285809Sscottl      agtiapi_FreeTMCCB( pCard, pccb );
4657285809Sscottl    }
4658285809Sscottl    else
4659285809Sscottl    {
4660285809Sscottl      if ( pccb->flags & TAG_SMP )
4661285809Sscottl      {
4662285809Sscottl        AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeSMPCCB \n" );
4663285809Sscottl        agtiapi_FreeSMPCCB( pCard, pccb );
4664285809Sscottl      }
4665285809Sscottl      else
4666285809Sscottl      {
4667285809Sscottl        AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeCCB \n" );
4668285809Sscottl        agtiapi_FreeCCB( pCard, pccb );
4669285809Sscottl      }
4670285809Sscottl      if( ccb ) {
4671285809Sscottl        CMND_DMA_UNMAP( pCard, ccb );
4672285809Sscottl        if( flag == AGTIAPI_CALLBACK ) {
4673285809Sscottl          ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
4674285809Sscottl          xpt_done( ccb );
4675285809Sscottl        }
4676285809Sscottl      }
4677285809Sscottl    }
4678285809Sscottl  }
4679285809Sscottl}
4680285809Sscottl
4681285809Sscottl/*****************************************************************************
4682285809Sscottlagtiapi_FreeSMPCCB()
4683285809Sscottl
4684285809SscottlPurpose:
4685285809Sscottl  Free a ccb and put it back to ccbFreeList.
4686285809SscottlParameters:
4687285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4688285809Sscottl  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4689285809Sscottl                                    CAM's CCB
4690285809SscottlReturns:
4691285809SscottlNote:
4692285809Sscottl*****************************************************************************/
4693285809SscottlSTATIC void agtiapi_FreeSMPCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4694285809Sscottl{
4695285809Sscottl  union ccb *ccb = pccb->ccb;
4696285809Sscottl  bus_dmasync_op_t op;
4697285809Sscottl
4698285809Sscottl  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4699285809Sscottl  AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: start %p\n", pccb);
4700285809Sscottl
4701285809Sscottl  /* set data transfer direction */
4702285809Sscottl  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
4703285809Sscottl  {
4704285809Sscottl    op = BUS_DMASYNC_POSTWRITE;
4705285809Sscottl  }
4706285809Sscottl  else
4707285809Sscottl  {
4708285809Sscottl    op = BUS_DMASYNC_POSTREAD;
4709285809Sscottl  }
4710285809Sscottl
4711285809Sscottl  if (pccb->numSgElements == 0)
4712285809Sscottl  {
4713285809Sscottl    // do nothing
4714285809Sscottl    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 0\n");
4715285809Sscottl  }
4716285809Sscottl  else if (pccb->numSgElements == 1)
4717285809Sscottl  {
4718285809Sscottl    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 1\n");
4719285809Sscottl    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4720285809Sscottl    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4721285809Sscottl    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4722285809Sscottl  }
4723285809Sscottl  else
4724285809Sscottl  {
4725285809Sscottl    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 2 or higher \n");
4726285809Sscottl    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4727285809Sscottl    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4728285809Sscottl    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4729285809Sscottl  }
4730285809Sscottl
4731285809Sscottl  /*dma api cleanning*/
4732285809Sscottl  pccb->dataLen    = 0;
4733285809Sscottl  pccb->retryCount = 0;
4734285809Sscottl  pccb->ccbStatus  = 0;
4735285809Sscottl  pccb->startTime  = 0;
4736285809Sscottl  pccb->dmaHandle  = 0;
4737285809Sscottl  pccb->numSgElements = 0;
4738285809Sscottl  pccb->tiIORequest.tdData = 0;
4739285809Sscottl  memset((void *)&pccb->tiSMPFrame, 0, AGSMP_INIT_XCHG_LEN);
4740285809Sscottl
4741285809Sscottl  pccb->flags        = 0;
4742285809Sscottl  pccb->ccb = NULL;
4743285809Sscottl  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4744285809Sscottl  pmcsc->ccbFreeList = (caddr_t *)pccb;
4745285809Sscottl
4746285809Sscottl  pmcsc->activeCCB--;
4747285809Sscottl
4748285809Sscottl  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4749285809Sscottl  return;
4750285809Sscottl
4751285809Sscottl}
4752285809Sscottl
4753285809Sscottl/*****************************************************************************
4754285809Sscottlagtiapi_FreeTMCCB()
4755285809Sscottl
4756285809SscottlPurpose:
4757285809Sscottl  Free a ccb and put it back to ccbFreeList.
4758285809SscottlParameters:
4759285809Sscottl  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4760285809Sscottl  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4761285809Sscottl                                    CAM's CCB
4762285809SscottlReturns:
4763285809SscottlNote:
4764285809Sscottl*****************************************************************************/
4765285809SscottlSTATIC void agtiapi_FreeTMCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4766285809Sscottl{
4767285809Sscottl  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4768285809Sscottl  AGTIAPI_PRINTK("agtiapi_FreeTMCCB: start %p\n", pccb);
4769285809Sscottl  pccb->dataLen    = 0;
4770285809Sscottl  pccb->retryCount = 0;
4771285809Sscottl  pccb->ccbStatus  = 0;
4772285809Sscottl  pccb->scsiStatus = 0;
4773285809Sscottl  pccb->startTime  = 0;
4774285809Sscottl  pccb->dmaHandle  = 0;
4775285809Sscottl  pccb->numSgElements = 0;
4776285809Sscottl  pccb->tiIORequest.tdData = 0;
4777285809Sscottl  memset((void *)&pccb->tiSuperScsiRequest, 0, AGSCSI_INIT_XCHG_LEN);
4778285809Sscottl  pccb->flags        = 0;
4779285809Sscottl  pccb->ccb = NULL;
4780285809Sscottl  pccb->pccbIO = NULL;
4781285809Sscottl  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4782285809Sscottl  pmcsc->ccbFreeList = (caddr_t *)pccb;
4783285809Sscottl  pmcsc->activeCCB--;
4784285809Sscottl  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4785285809Sscottl  return;
4786285809Sscottl}
4787285809Sscottl/******************************************************************************
4788285809Sscottlagtiapi_CheckAllVectors():
4789285809Sscottl
4790285809SscottlPurpose:
4791285809SscottlParameters:
4792285809SscottlReturn:
4793285809SscottlNote:
4794285809Sscottl  Currently, not used.
4795285809Sscottl******************************************************************************/
4796285809Sscottlvoid agtiapi_CheckAllVectors( struct agtiapi_softc *pCard, bit32 context )
4797285809Sscottl{
4798285809Sscottl#ifdef SPC_MSIX_INTR
4799285809Sscottl  if (!agtiapi_intx_mode)
4800285809Sscottl  {
4801285809Sscottl    int i;
4802285809Sscottl
4803285809Sscottl    for (i = 0; i < pCard->pCardInfo->maxInterruptVectors; i++)
4804285809Sscottl      if (tiCOMInterruptHandler(&pCard->tiRoot, i) == agTRUE)
4805285809Sscottl        tiCOMDelayedInterruptHandler(&pCard->tiRoot, i, 100, context);
4806285809Sscottl  }
4807285809Sscottl  else
4808285809Sscottl  if (tiCOMInterruptHandler(&pCard->tiRoot, 0) == agTRUE)
4809285809Sscottl    tiCOMDelayedInterruptHandler(&pCard->tiRoot, 0, 100, context);
4810285809Sscottl#else
4811285809Sscottl  if (tiCOMInterruptHandler(&pCard->tiRoot, 0) == agTRUE)
4812285809Sscottl    tiCOMDelayedInterruptHandler(&pCard->tiRoot, 0, 100, context);
4813285809Sscottl#endif
4814285809Sscottl
4815285809Sscottl}
4816285809Sscottl
4817285809Sscottl
4818285809Sscottl/******************************************************************************
4819285809Sscottlagtiapi_CheckCB()
4820285809Sscottl
4821285809SscottlPurpose:
4822285809Sscottl  Check call back function returned event for process completion
4823285809SscottlParameters:
4824285809Sscottl  struct agtiapi_softc *pCard  Pointer to card data structure
4825285809Sscottl  U32 milisec (IN)       Waiting time for expected event
4826285809Sscottl  U32 flag (IN)          Flag of the event to check
4827285809Sscottl  U32 *pStatus (IN)      Pointer to status of the card or port to check
4828285809SscottlReturn:
4829285809Sscottl  AGTIAPI_SUCCESS - event comes as expected
4830285809Sscottl  AGTIAPI_FAIL    - event not coming
4831285809SscottlNote:
4832285809Sscottl  Currently, not used
4833285809Sscottl******************************************************************************/
4834285809SscottlagBOOLEAN agtiapi_CheckCB( struct agtiapi_softc *pCard,
4835285809Sscottl                           U32 milisec,
4836285809Sscottl                           U32 flag,
4837285809Sscottl                           volatile U32 *pStatus )
4838285809Sscottl{
4839285809Sscottl  U32    msecsPerTick = pCard->pCardInfo->tiRscInfo.tiInitiatorResource.
4840285809Sscottl                        initiatorOption.usecsPerTick / 1000;
4841285809Sscottl  S32    i = milisec/msecsPerTick;
4842285809Sscottl  AG_GLOBAL_ARG( _flags );
4843285809Sscottl
4844285809Sscottl  AGTIAPI_PRINTK( "agtiapi_CheckCB: start\n" );
4845285809Sscottl  AGTIAPI_FLOW(   "agtiapi_CheckCB: start\n" );
4846285809Sscottl
4847285809Sscottl  if( i <= 0 )
4848285809Sscottl    i = 1;
4849285809Sscottl  while (i > 0)
4850285809Sscottl  {
4851285809Sscottl    if (*pStatus & TASK_MANAGEMENT)
4852285809Sscottl    {
4853285809Sscottl      if (*pStatus & AGTIAPI_CB_DONE)
4854285809Sscottl      {
4855285809Sscottl        if( flag == 0 || *pStatus & flag )
4856285809Sscottl          return AGTIAPI_SUCCESS;
4857285809Sscottl        else
4858285809Sscottl          return AGTIAPI_FAIL;
4859285809Sscottl      }
4860285809Sscottl    }
4861285809Sscottl    else if (pCard->flags & AGTIAPI_CB_DONE)
4862285809Sscottl    {
4863285809Sscottl      if( flag == 0 || *pStatus & flag )
4864285809Sscottl        return AGTIAPI_SUCCESS;
4865285809Sscottl      else
4866285809Sscottl        return AGTIAPI_FAIL;
4867285809Sscottl    }
4868285809Sscottl
4869285809Sscottl    agtiapi_DelayMSec( msecsPerTick );
4870285809Sscottl
4871285809Sscottl    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, _flags );
4872285809Sscottl    tiCOMTimerTick( &pCard->tiRoot );
4873285809Sscottl
4874285809Sscottl    agtiapi_CheckAllVectors( pCard, tiNonInterruptContext );
4875285809Sscottl    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, _flags );
4876285809Sscottl
4877285809Sscottl    i--;
4878285809Sscottl  }
4879285809Sscottl
4880285809Sscottl  if( *pStatus & TASK_MANAGEMENT )
4881285809Sscottl    *pStatus |= TASK_TIMEOUT;
4882285809Sscottl
4883285809Sscottl  return AGTIAPI_FAIL;
4884285809Sscottl}
4885285809Sscottl
4886285809Sscottl
4887285809Sscottl/******************************************************************************
4888285809Sscottlagtiapi_DiscoverTgt()
4889285809Sscottl
4890285809SscottlPurpose:
4891285809Sscottl  Discover available devices
4892285809SscottlParameters:
4893285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
4894285809SscottlReturn:
4895285809SscottlNote:
4896285809Sscottl******************************************************************************/
4897285809SscottlSTATIC void agtiapi_DiscoverTgt(struct agtiapi_softc *pCard)
4898285809Sscottl{
4899285809Sscottl
4900285809Sscottl  ag_portal_data_t *pPortalData;
4901285809Sscottl  U32              count;
4902285809Sscottl
4903285809Sscottl  AGTIAPI_PRINTK("agtiapi_DiscoverTgt: start\n");
4904285809Sscottl  AGTIAPI_FLOW("agtiapi_DiscoverTgt\n");
4905285809Sscottl  AGTIAPI_INIT("agtiapi_DiscoverTgt\n");
4906285809Sscottl
4907285809Sscottl  pPortalData = pCard->pPortalData;
4908285809Sscottl  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4909285809Sscottl  {
4910285809Sscottl    pCard->flags &= ~AGTIAPI_CB_DONE;
4911285809Sscottl    if (!(PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY))
4912285809Sscottl    {
4913285809Sscottl      if (pCard->flags & AGTIAPI_INIT_TIME)
4914285809Sscottl      {
4915285809Sscottl        if (agtiapi_CheckCB(pCard, 5000, AGTIAPI_PORT_DISC_READY,
4916285809Sscottl            &PORTAL_STATUS(pPortalData)) == AGTIAPI_FAIL)
4917285809Sscottl        {
4918285809Sscottl          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Port %p / %d not ready for "
4919285809Sscottl                          "discovery\n",
4920285809Sscottl                          pPortalData, count );
4921285809Sscottl          /*
4922285809Sscottl           * There is no need to spend time on discovering device
4923285809Sscottl           * if port is not ready to do so.
4924285809Sscottl           */
4925285809Sscottl          continue;
4926285809Sscottl        }
4927285809Sscottl      }
4928285809Sscottl      else
4929285809Sscottl        continue;
4930285809Sscottl    }
4931285809Sscottl
4932285809Sscottl    AGTIAPI_FLOW( "agtiapi_DiscoverTgt: Portal %p DiscoverTargets starts\n",
4933285809Sscottl                  pPortalData );
4934285809Sscottl    AGTIAPI_INIT_DELAY(1000);
4935285809Sscottl
4936285809Sscottl    pCard->flags &= ~AGTIAPI_CB_DONE;
4937285809Sscottl    if (tiINIDiscoverTargets(&pCard->tiRoot,
4938285809Sscottl                             &pPortalData->portalInfo.tiPortalContext,
4939285809Sscottl                             FORCE_PERSISTENT_ASSIGN_MASK)
4940285809Sscottl        != tiSuccess)
4941285809Sscottl      AGTIAPI_PRINTK("agtiapi_DiscoverTgt: tiINIDiscoverTargets ERROR\n");
4942285809Sscottl
4943285809Sscottl    /*
4944285809Sscottl     * Should wait till discovery completion to start
4945285809Sscottl     * next portal. However, lower layer have issue on
4946285809Sscottl     * multi-portal case under Linux.
4947285809Sscottl     */
4948285809Sscottl  }
4949285809Sscottl
4950285809Sscottl  pPortalData = pCard->pPortalData;
4951285809Sscottl  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4952285809Sscottl  {
4953285809Sscottl    if ((PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY))
4954285809Sscottl    {
4955285809Sscottl      if (agtiapi_CheckCB(pCard, 20000, AGTIAPI_DISC_COMPLETE,
4956285809Sscottl          &PORTAL_STATUS(pPortalData)) == AGTIAPI_FAIL)
4957285809Sscottl      {
4958285809Sscottl        if ((PORTAL_STATUS(pPortalData) & AGTIAPI_DISC_COMPLETE))
4959285809Sscottl          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %p discover complete, "
4960285809Sscottl                          "status 0x%x\n",
4961285809Sscottl                          pPortalData,
4962285809Sscottl                          PORTAL_STATUS(pPortalData) );
4963285809Sscottl        else
4964285809Sscottl          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %p discover is not "
4965285809Sscottl                          "completed, status 0x%x\n",
4966285809Sscottl                          pPortalData, PORTAL_STATUS(pPortalData) );
4967285809Sscottl        continue;
4968285809Sscottl      }
4969285809Sscottl      AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %d discover target "
4970285809Sscottl                      "success\n",
4971285809Sscottl                      count );
4972285809Sscottl    }
4973285809Sscottl  }
4974285809Sscottl
4975285809Sscottl  /*
4976285809Sscottl   * Calling to get device handle should be done per portal based
4977285809Sscottl   * and better right after discovery is done. However, lower iscsi
4978285809Sscottl   * layer may not returns discovery complete in correct sequence or we
4979285809Sscottl   * ran out time. We get device handle for all portals together
4980285809Sscottl   * after discovery is done or timed out.
4981285809Sscottl   */
4982285809Sscottl  pPortalData = pCard->pPortalData;
4983285809Sscottl  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4984285809Sscottl  {
4985285809Sscottl    /*
4986285809Sscottl     * We try to get device handle no matter
4987285809Sscottl     * if discovery is completed or not.
4988285809Sscottl     */
4989285809Sscottl    if (PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY)
4990285809Sscottl    {
4991285809Sscottl      U32 i;
4992285809Sscottl
4993285809Sscottl      for (i = 0; i < AGTIAPI_GET_DEV_MAX; i++)
4994285809Sscottl      {
4995285809Sscottl        if (agtiapi_GetDevHandle(pCard, &pPortalData->portalInfo, 0, 0) != 0)
4996285809Sscottl          break;
4997285809Sscottl        agtiapi_DelayMSec(AGTIAPI_EXTRA_DELAY);
4998285809Sscottl      }
4999285809Sscottl
5000285809Sscottl      if ((PORTAL_STATUS(pPortalData) & AGTIAPI_DISC_COMPLETE) ||
5001285809Sscottl          (pCard->tgtCount > 0))
5002285809Sscottl        PORTAL_STATUS(pPortalData) |= ( AGTIAPI_DISC_DONE |
5003285809Sscottl                                        AGTIAPI_PORT_LINK_UP );
5004285809Sscottl    }
5005285809Sscottl  }
5006285809Sscottl
5007285809Sscottl  return;
5008285809Sscottl
5009285809Sscottl}
5010285809Sscottl
5011285809Sscottl
5012285809Sscottl
5013285809Sscottl/******************************************************************************
5014285809Sscottlagtiapi_PrepCCBs()
5015285809Sscottl
5016285809SscottlPurpose:
5017285809Sscottl  Prepares CCB including DMA map.
5018285809SscottlParameters:
5019285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
5020285809Sscottl  ccb_hdr_t *hdr (IN)               Pointer to the CCB header
5021285809Sscottl  U32 size (IN)                     size
5022285809Sscottl  U32 max_ccb (IN)                  count
5023285809Sscottl
5024285809SscottlReturn:
5025285809SscottlNote:
5026285809Sscottl******************************************************************************/
5027285809SscottlSTATIC void agtiapi_PrepCCBs( struct agtiapi_softc *pCard,
5028285809Sscottl                              ccb_hdr_t *hdr,
5029285809Sscottl                              U32 size,
5030285809Sscottl                              U32 max_ccb,
5031285809Sscottl                              int tid )
5032285809Sscottl{
5033285809Sscottl
5034285809Sscottl  int i;
5035285809Sscottl  U32 hdr_sz, ccb_sz;
5036285809Sscottl  ccb_t *pccb = 0;
5037285809Sscottl  int offset = 0;
5038285809Sscottl  int nsegs = 0;
5039285809Sscottl  int sgl_sz = 0;
5040285809Sscottl
5041285809Sscottl  AGTIAPI_PRINTK("agtiapi_PrepCCBs: start\n");
5042285809Sscottl  offset = tid * AGTIAPI_CCB_PER_DEVICE;
5043285809Sscottl  nsegs = AGTIAPI_NSEGS;
5044285809Sscottl  sgl_sz = sizeof(tiSgl_t) * nsegs;
5045285809Sscottl  AGTIAPI_PRINTK( "agtiapi_PrepCCBs: tid %d offset %d nsegs %d sizeof(tiSgl_t) "
5046285809Sscottl                  "%lu, max_ccb %d\n",
5047285809Sscottl                  tid,
5048285809Sscottl                  offset,
5049285809Sscottl                  nsegs,
5050285809Sscottl                  sizeof(tiSgl_t),
5051285809Sscottl                  max_ccb );
5052285809Sscottl
5053285809Sscottl  ccb_sz = (AGTIAPI_CCB_SIZE + cache_line_size() - 1) & ~(cache_line_size() -1);
5054285809Sscottl  hdr_sz = (sizeof(*hdr) + cache_line_size() - 1) & ~(cache_line_size() - 1);
5055285809Sscottl
5056285809Sscottl  AGTIAPI_PRINTK("agtiapi_PrepCCBs: after cache line\n");
5057285809Sscottl
5058285809Sscottl  memset((void *)hdr, 0, size);
5059285809Sscottl  hdr->next = pCard->ccbAllocList;
5060285809Sscottl  pCard->ccbAllocList = hdr;
5061285809Sscottl
5062285809Sscottl  AGTIAPI_PRINTK("agtiapi_PrepCCBs: after memset\n");
5063285809Sscottl
5064285809Sscottl  pccb = (ccb_t*) ((char*)hdr + hdr_sz);
5065285809Sscottl
5066285809Sscottl  for (i = 0; i < max_ccb; i++, pccb = (ccb_t*)((char*)pccb + ccb_sz))
5067285809Sscottl  {
5068285809Sscottl    pccb->tiIORequest.osData = (void *)pccb;
5069285809Sscottl
5070285809Sscottl    /*
5071285809Sscottl     * Initially put all the ccbs on the free list
5072285809Sscottl     * in addition to chainlist.
5073285809Sscottl     * ccbChainList is a list of all available ccbs
5074285809Sscottl     * (free/active everything)
5075285809Sscottl     */
5076285809Sscottl    pccb->pccbChainNext = (pccb_t)pCard->ccbChainList;
5077285809Sscottl    pccb->pccbNext      = (pccb_t)pCard->ccbFreeList;
5078285809Sscottl
5079285809Sscottl    pCard->ccbChainList = (caddr_t *)pccb;
5080285809Sscottl    pCard->ccbFreeList  = (caddr_t *)pccb;
5081285809Sscottl    pCard->ccbTotal++;
5082285809Sscottl
5083285809Sscottl#ifdef AGTIAPI_ALIGN_CHECK
5084285809Sscottl    if (&pccb & 0x63)
5085285809Sscottl      AGTIAPI_PRINTK("pccb = %p\n", pccb);
5086285809Sscottl    if (pccb->devHandle & 0x63)
5087285809Sscottl      AGTIAPI_PRINTK("devHandle addr = %p\n", &pccb->devHandle);
5088285809Sscottl    if (&pccb->lun & 0x63)
5089285809Sscottl      AGTIAPI_PRINTK("lun addr = %p\n", &pccb->lun);
5090285809Sscottl    if (&pccb->targetId & 0x63)
5091285809Sscottl      AGTIAPI_PRINTK("tig addr = %p\n", &pccb->targetId);
5092285809Sscottl    if (&pccb->ccbStatus & 0x63)
5093285809Sscottl      AGTIAPI_PRINTK("ccbStatus addr = %p\n", &pccb->ccbStatus);
5094285809Sscottl    if (&pccb->scsiStatus & 0x63)
5095285809Sscottl      AGTIAPI_PRINTK("scsiStatus addr = %p\n", &pccb->scsiStatus);
5096285809Sscottl    if (&pccb->dataLen & 0x63)
5097285809Sscottl      AGTIAPI_PRINTK("dataLen addr = %p\n", &pccb->dataLen);
5098285809Sscottl    if (&pccb->senseLen & 0x63)
5099285809Sscottl      AGTIAPI_PRINTK("senseLen addr = %p\n", &pccb->senseLen);
5100285809Sscottl    if (&pccb->numSgElements & 0x63)
5101285809Sscottl      AGTIAPI_PRINTK("numSgElements addr = %p\n", &pccb->numSgElements);
5102285809Sscottl    if (&pccb->retryCount & 0x63)
5103285809Sscottl      AGTIAPI_PRINTK("retry cnt addr = %p\n", &pccb->retryCount);
5104285809Sscottl    if (&pccb->flags & 0x63)
5105285809Sscottl      AGTIAPI_PRINTK("flag addr = %p\n", &pccb->flags);
5106285809Sscottl    if (&pccb->pSenseData & 0x63)
5107285809Sscottl      AGTIAPI_PRINTK("senseData addr = %p\n", &pccb->pSenseData);
5108285809Sscottl    if (&pccb->sgList[0] & 0x63)
5109285809Sscottl      AGTIAPI_PRINTK("SgList 0 = %p\n", &pccb->sgList[0]);
5110285809Sscottl    if (&pccb->pccbNext & 0x63)
5111285809Sscottl      AGTIAPI_PRINTK("ccb next = %p\n", &pccb->pccbNext);
5112285809Sscottl    if (&pccb->pccbChainNext & 0x63)
5113285809Sscottl      AGTIAPI_PRINTK("ccbChainNext = %p\n", &pccb->pccbChainNext);
5114285809Sscottl    if (&pccb->cmd & 0x63)
5115285809Sscottl      AGTIAPI_PRINTK("command = %p\n", &pccb->cmd);
5116285809Sscottl    if( &pccb->startTime & 0x63 )
5117285809Sscottl      AGTIAPI_PRINTK( "startTime = %p\n", &pccb->startTime );
5118285809Sscottl    if (&pccb->tiIORequest & 0x63)
5119285809Sscottl      AGTIAPI_PRINTK("tiIOReq addr = %p\n", &pccb->tiIORequest);
5120285809Sscottl    if (&pccb->tdIOReqBody & 0x63)
5121285809Sscottl      AGTIAPI_PRINTK("tdIORequestBody addr = %p\n", &pccb->tdIOReqBody);
5122285809Sscottl    if (&pccb->tiSuperScsiRequest & 0x63)
5123285809Sscottl      AGTIAPI_PRINTK( "InitiatorExchange addr = %p\n",
5124285809Sscottl                      &pccb->tiSuperScsiRequest );
5125285809Sscottl#endif
5126285809Sscottl    if ( bus_dmamap_create( pCard->buffer_dmat, 0, &pccb->CCB_dmamap ) !=
5127285809Sscottl         tiSuccess)
5128285809Sscottl    {
5129285809Sscottl      AGTIAPI_PRINTK("agtiapi_PrepCCBs: can't create dma\n");
5130285809Sscottl      return;
5131285809Sscottl    }
5132285809Sscottl    /* assigns tiSgl_t memory to pccb */
5133285809Sscottl    pccb->sgList = (void*)((U64)pCard->tisgl_mem + ((i + offset) * sgl_sz));
5134285809Sscottl    pccb->tisgl_busaddr = pCard->tisgl_busaddr + ((i + offset) * sgl_sz);
5135285809Sscottl    pccb->ccb = NULL;
5136285809Sscottl    pccb->pccbIO = NULL;
5137285809Sscottl    pccb->startTime = 0;
5138285809Sscottl  }
5139285809Sscottl
5140285809Sscottl#ifdef AGTIAPI_ALIGN_CHECK
5141285809Sscottl  AGTIAPI_PRINTK("ccb size = %d / %d\n", sizeof(ccb_t), ccb_sz);
5142285809Sscottl#endif
5143285809Sscottl  return;
5144285809Sscottl}
5145285809Sscottl
5146285809Sscottl/******************************************************************************
5147285809Sscottlagtiapi_InitCCBs()
5148285809Sscottl
5149285809SscottlPurpose:
5150285809Sscottl  Create and initialize per card based CCB pool.
5151285809SscottlParameters:
5152285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
5153285809Sscottl  int tgtCount (IN)                 Count
5154285809SscottlReturn:
5155285809Sscottl  Total number of ccb allocated
5156285809SscottlNote:
5157285809Sscottl******************************************************************************/
5158285809SscottlSTATIC U32 agtiapi_InitCCBs(struct agtiapi_softc *pCard, int tgtCount, int tid)
5159285809Sscottl{
5160285809Sscottl
5161285809Sscottl  U32   max_ccb, size, ccb_sz, hdr_sz;
5162285809Sscottl  int   no_allocs = 0, i;
5163285809Sscottl  ccb_hdr_t  *hdr = 0;
5164285809Sscottl
5165285809Sscottl  AGTIAPI_PRINTK("agtiapi_InitCCBs: start\n");
5166285809Sscottl  AGTIAPI_PRINTK("agtiapi_InitCCBs: tgtCount %d tid %d\n", tgtCount, tid);
5167285809Sscottl  AGTIAPI_FLOW("agtiapi_InitCCBs: tgtCount %d tid %d\n", tgtCount, tid);
5168285809Sscottl
5169285809Sscottl#ifndef HOTPLUG_SUPPORT
5170285809Sscottl  if (pCard->tgtCount > AGSA_MAX_INBOUND_Q)
5171285809Sscottl    return 1;
5172285809Sscottl#else
5173285809Sscottl  if (tgtCount > AGSA_MAX_INBOUND_Q)
5174285809Sscottl    tgtCount = AGSA_MAX_INBOUND_Q;
5175285809Sscottl#endif
5176285809Sscottl
5177285809Sscottl  max_ccb = tgtCount * AGTIAPI_CCB_PER_DEVICE;//      / 4; // TBR
5178285809Sscottl  ccb_sz = ( (AGTIAPI_CCB_SIZE + cache_line_size() - 1) &
5179285809Sscottl             ~(cache_line_size() -1) );
5180285809Sscottl  hdr_sz = (sizeof(*hdr) + cache_line_size() - 1) & ~(cache_line_size() - 1);
5181285809Sscottl  size = ccb_sz * max_ccb + hdr_sz;
5182285809Sscottl
5183285809Sscottl  for (i = 0; i < (1 << no_allocs); i++)
5184285809Sscottl  {
5185285809Sscottl    hdr = (ccb_hdr_t*)malloc( size, M_PMC_MCCB, M_NOWAIT );
5186285809Sscottl    if( !hdr )
5187285809Sscottl    {
5188285809Sscottl      panic( "agtiapi_InitCCBs: bug!!!\n" );
5189285809Sscottl    }
5190285809Sscottl    else
5191285809Sscottl    {
5192285809Sscottl      agtiapi_PrepCCBs( pCard, hdr, size, max_ccb, tid );
5193285809Sscottl    }
5194285809Sscottl  }
5195285809Sscottl
5196285809Sscottl  return 1;
5197285809Sscottl
5198285809Sscottl}
5199285809Sscottl
5200285809Sscottl
5201285809Sscottl#ifdef LINUX_PERBI_SUPPORT
5202285809Sscottl/******************************************************************************
5203285809Sscottlagtiapi_GetWWNMappings()
5204285809Sscottl
5205285809SscottlPurpose:
5206285809Sscottl  Get the mappings from target IDs to WWNs, if any.
5207285809Sscottl  Store them in the WWN_list array, indexed by target ID.
5208285809Sscottl  Leave the devListIndex field blank; this will be filled-in later.
5209285809SscottlParameters:
5210285809Sscottl  ag_card_t *pCard (IN)        Pointer to HBA data structure
5211285809Sscottl  ag_mapping_t *pMapList (IN)  Pointer to mapped device list
5212285809SscottlReturn:
5213285809SscottlNote:  The boot command line parameters are used to load the
5214285809Sscottl  mapping information, which is contained in the system
5215285809Sscottl  configuration file.
5216285809Sscottl******************************************************************************/
5217285809SscottlSTATIC void agtiapi_GetWWNMappings( struct agtiapi_softc *pCard,
5218285809Sscottl                                    ag_mapping_t         *pMapList )
5219285809Sscottl{
5220285809Sscottl  int           devDisc;
5221285809Sscottl  int           lIdx = 0;
5222285809Sscottl  ag_tgt_map_t *pWWNList;
5223285809Sscottl  ag_slr_map_t *pSLRList;
5224285809Sscottl  ag_device_t  *pDevList;
5225285809Sscottl
5226285809Sscottl  if( !pCard )
5227285809Sscottl    panic( "agtiapi_GetWWNMappings: no pCard \n" );
5228285809Sscottl
5229285809Sscottl  AGTIAPI_PRINTK( "agtiapi_GetWWNMappings: start\n" );
5230285809Sscottl
5231285809Sscottl  pWWNList = pCard->pWWNList;
5232285809Sscottl  pSLRList = pCard->pSLRList;
5233285809Sscottl  pDevList = pCard->pDevList;
5234285809Sscottl  pCard->numTgtHardMapped = 0;
5235285809Sscottl  devDisc = pCard->devDiscover;
5236285809Sscottl
5237285809Sscottl  pWWNList[devDisc-1].devListIndex  = maxTargets;
5238285809Sscottl  pSLRList[devDisc-1].localeNameLen = -2;
5239285809Sscottl  pSLRList[devDisc-1].remoteNameLen = -2;
5240285809Sscottl  pDevList[devDisc-1].targetId      = maxTargets;
5241285809Sscottl
5242285809Sscottl  /*
5243285809Sscottl   * Get the mappings from holding area which contains
5244285809Sscottl   * the input of the system file and store them
5245285809Sscottl   * in the WWN_list array, indexed by target ID.
5246285809Sscottl   */
5247285809Sscottl  for ( lIdx = 0; lIdx < devDisc - 1; lIdx++) {
5248285809Sscottl    pWWNList[lIdx].flags = 0;
5249285809Sscottl    pWWNList[lIdx].devListIndex  = maxTargets;
5250285809Sscottl    pSLRList[lIdx].localeNameLen = -1;
5251285809Sscottl    pSLRList[lIdx].remoteNameLen = -1;
5252285809Sscottl  }
5253285809Sscottl
5254285809Sscottl  //  this is where we would propagate values fed to pMapList
5255285809Sscottl
5256285809Sscottl} /* agtiapi_GetWWNMappings */
5257285809Sscottl
5258285809Sscottl#endif
5259285809Sscottl
5260285809Sscottl
5261285809Sscottl/******************************************************************************
5262285809Sscottlagtiapi_FindWWNListNext()
5263285809SscottlPurpose:
5264285809Sscottl  finds first available new (unused) wwn list entry
5265285809Sscottl
5266285809SscottlParameters:
5267285809Sscottl  ag_tgt_map_t *pWWNList              Pointer to head of wwn list
5268285809Sscottl  int lstMax                          Number of entries in WWNList
5269285809SscottlReturn:
5270285809Sscottl  index into WWNList indicating available entry space;
5271285809Sscottl  if available entry space is not found, return negative value
5272285809Sscottl******************************************************************************/
5273285809SscottlSTATIC int agtiapi_FindWWNListNext( ag_tgt_map_t *pWWNList, int lstMax )
5274285809Sscottl{
5275285809Sscottl  int  lLstIdx;
5276285809Sscottl
5277285809Sscottl  for ( lLstIdx = 0; lLstIdx < lstMax; lLstIdx++ )
5278285809Sscottl  {
5279285809Sscottl    if ( pWWNList[lLstIdx].devListIndex == lstMax &&
5280285809Sscottl         pWWNList[lLstIdx].targetLen == 0 )
5281285809Sscottl    {
5282285809Sscottl      AGTIAPI_PRINTK( "agtiapi_FindWWNListNext: %d %d %d %d v. %d\n",
5283285809Sscottl                      lLstIdx,
5284285809Sscottl                      pWWNList[lLstIdx].devListIndex,
5285285809Sscottl                      pWWNList[lLstIdx].targetLen,
5286285809Sscottl                      pWWNList[lLstIdx].portId,
5287285809Sscottl                      lstMax );
5288285809Sscottl      return lLstIdx;
5289285809Sscottl    }
5290285809Sscottl  }
5291285809Sscottl  return -1;
5292285809Sscottl}
5293285809Sscottl
5294285809Sscottl
5295285809Sscottl/******************************************************************************
5296285809Sscottlagtiapi_GetDevHandle()
5297285809Sscottl
5298285809SscottlPurpose:
5299285809Sscottl  Get device handle.  Handles will be placed in the
5300285809Sscottl  devlist array with same order as TargetList provided and
5301285809Sscottl  will be mapped to a scsi target id and registered to OS later.
5302285809SscottlParameters:
5303285809Sscottl  struct agtiapi_softc *pCard (IN)    Pointer to the HBA data structure
5304285809Sscottl  ag_portal_info_t *pPortalInfo (IN)  Pointer to the portal data structure
5305285809Sscottl  U32 eType (IN)                      Port event
5306285809Sscottl  U32 eStatus (IN)                    Port event status
5307285809SscottlReturn:
5308285809Sscottl  Number of device handle slot present
5309285809SscottlNote:
5310285809Sscottl  The sequence of device handle will match the sequence of taregt list
5311285809Sscottl******************************************************************************/
5312285809SscottlSTATIC U32 agtiapi_GetDevHandle( struct agtiapi_softc *pCard,
5313285809Sscottl                                 ag_portal_info_t *pPortalInfo,
5314285809Sscottl                                 U32 eType,
5315285809Sscottl                                 U32 eStatus )
5316285809Sscottl{
5317285809Sscottl  ag_device_t       *pDevice;
5318285809Sscottl  // tiDeviceHandle_t *agDev[pCard->devDiscover];
5319285809Sscottl  tiDeviceHandle_t **agDev;
5320285809Sscottl  int                devIdx, szdv, devTotal, cmpsetRtn;
5321285809Sscottl  int                lDevIndex = 0, lRunScanFlag = FALSE;
5322285809Sscottl  int               *lDevFlags;
5323285809Sscottl  tiPortInfo_t       portInfT;
5324285809Sscottl  ag_device_t        lTmpDevice;
5325285809Sscottl  ag_tgt_map_t      *pWWNList;
5326285809Sscottl  ag_slr_map_t      *pSLRList;
5327285809Sscottl  bit32              lReadRm;
5328285809Sscottl  bit16              lReadCt;
5329285809Sscottl
5330285809Sscottl
5331285809Sscottl  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: start\n" );
5332285809Sscottl  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: pCard->devDiscover %d / tgtCt %d\n",
5333285809Sscottl                  pCard->devDiscover, pCard->tgtCount );
5334285809Sscottl  AGTIAPI_FLOW( "agtiapi_GetDevHandle: portalInfo %p\n", pPortalInfo );
5335285809Sscottl  AGTIAPI_INIT_DELAY( 1000 );
5336285809Sscottl
5337285809Sscottl  agDev = (tiDeviceHandle_t **) malloc( sizeof(tiDeviceHandle_t *) * pCard->devDiscover,
5338285809Sscottl                                        M_PMC_MDEV, M_ZERO | M_NOWAIT);
5339285809Sscottl  if (agDev == NULL)
5340285809Sscottl  {
5341285809Sscottl    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: failed to alloc agDev[]\n" );
5342285809Sscottl    return 0;
5343285809Sscottl  }
5344285809Sscottl
5345285809Sscottl  lDevFlags = (int *) malloc( sizeof(int) * pCard->devDiscover,
5346285809Sscottl                              M_PMC_MFLG, M_ZERO | M_NOWAIT );
5347285809Sscottl  if (lDevFlags == NULL)
5348285809Sscottl  {
5349285809Sscottl    free((caddr_t)agDev, M_PMC_MDEV);
5350285809Sscottl    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: failed to alloc lDevFlags[]\n" );
5351285809Sscottl    return 0;
5352285809Sscottl  }
5353285809Sscottl
5354285809Sscottl  pWWNList = pCard->pWWNList;
5355285809Sscottl  pSLRList = pCard->pSLRList;
5356285809Sscottl
5357285809Sscottl  memset( (void *)agDev, 0, sizeof(void *) * pCard->devDiscover );
5358285809Sscottl  memset( lDevFlags,     0, sizeof(int)    * pCard->devDiscover );
5359285809Sscottl
5360285809Sscottl  // get device handles
5361285809Sscottl  devTotal = tiINIGetDeviceHandles( &pCard->tiRoot,
5362285809Sscottl                                    &pPortalInfo->tiPortalContext,
5363285809Sscottl                                    (tiDeviceHandle_t **)agDev,
5364285809Sscottl                                    pCard->devDiscover );
5365285809Sscottl
5366285809Sscottl  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: portalInfo %p port id %d event %u "
5367285809Sscottl                  "status %u card %p pCard->devDiscover %d devTotal %d "
5368285809Sscottl                  "pPortalInfo->devTotal %d pPortalInfo->devPrev %d "
5369285809Sscottl                  "AGTIAPI_INIT_TIME %x\n",
5370285809Sscottl                  pPortalInfo, pPortalInfo->portID, eType, eStatus, pCard,
5371285809Sscottl                  pCard->devDiscover, devTotal, pPortalInfo->devTotal,
5372285809Sscottl                  pPortalInfo->devPrev,
5373285809Sscottl                  pCard->flags & AGTIAPI_INIT_TIME );
5374285809Sscottl
5375285809Sscottl  // reset devTotal from any previous runs of this
5376285809Sscottl  pPortalInfo->devPrev  = devTotal;
5377285809Sscottl  pPortalInfo->devTotal = devTotal;
5378285809Sscottl
5379285809Sscottl  AG_LIST_LOCK( &pCard->devListLock );
5380285809Sscottl
5381285809Sscottl  if ( tiCOMGetPortInfo( &pCard->tiRoot,
5382285809Sscottl                         &pPortalInfo->tiPortalContext,
5383285809Sscottl                         &portInfT )
5384285809Sscottl       != tiSuccess)
5385285809Sscottl  {
5386285809Sscottl    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: tiCOMGetPortInfo did not succeed. \n" );
5387285809Sscottl  }
5388285809Sscottl
5389285809Sscottl
5390285809Sscottl  szdv = sizeof( pPortalInfo->pDevList ) / sizeof( pPortalInfo->pDevList[0] );
5391285809Sscottl  if (szdv > pCard->devDiscover)
5392285809Sscottl  {
5393285809Sscottl    szdv = pCard->devDiscover;
5394285809Sscottl  }
5395285809Sscottl
5396285809Sscottl  // reconstructing dev list via comparison of wwn
5397285809Sscottl
5398285809Sscottl  for ( devIdx = 0; devIdx < pCard->devDiscover; devIdx++ )
5399285809Sscottl  {
5400285809Sscottl    if ( agDev[devIdx] != 0 )
5401285809Sscottl    {
5402285809Sscottl      // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: agDev %d not NULL %p\n",
5403285809Sscottl      //                 devIdx, agDev[devIdx] );
5404285809Sscottl
5405285809Sscottl      // pack temp device structure for tiINIGetDeviceInfo call
5406285809Sscottl      pDevice                  = &lTmpDevice;
5407285809Sscottl      pDevice->devType         = DIRECT_DEVICE;
5408285809Sscottl      pDevice->pCard           = (void *)pCard;
5409285809Sscottl      pDevice->flags           = ACTIVE;
5410285809Sscottl      pDevice->pPortalInfo     = pPortalInfo;
5411285809Sscottl      pDevice->pDevHandle      = agDev[devIdx];
5412285809Sscottl      pDevice->qbusy           = agFALSE;
5413285809Sscottl
5414285809Sscottl      //AGTIAPI_PRINTK( "agtiapi_GetDevHandle: idx %d / %d : %p \n",
5415285809Sscottl      //                devIdx, pCard->devDiscover, agDev[devIdx] );
5416285809Sscottl
5417285809Sscottl      tiINIGetDeviceInfo( &pCard->tiRoot, agDev[devIdx],
5418285809Sscottl                          &pDevice->devInfo );
5419285809Sscottl
5420285809Sscottl      //AGTIAPI_PRINTK( "agtiapi_GetDevHandle: wwn sizes %ld %d/%d ",
5421285809Sscottl      //                sizeof(pDevice->targetName),
5422285809Sscottl      //                pDevice->devInfo.osAddress1,
5423285809Sscottl      //                pDevice->devInfo.osAddress2 );
5424285809Sscottl
5425285809Sscottl      wwncpy( pDevice );
5426285809Sscottl      wwnprintk( (unsigned char*)pDevice->targetName, pDevice->targetLen );
5427285809Sscottl
5428285809Sscottl      for ( lDevIndex = 0; lDevIndex < szdv; lDevIndex++ ) // match w/ wwn list
5429285809Sscottl      {
5430285809Sscottl        if ( (pCard->pDevList[lDevIndex].portalId == pPortalInfo->portID) &&
5431285809Sscottl             pDevice->targetLen     > 0 &&
5432285809Sscottl             portInfT.localNameLen  > 0 &&
5433285809Sscottl             portInfT.remoteNameLen > 0 &&
5434285809Sscottl             pSLRList[pWWNList[lDevIndex].sasLrIdx].localeNameLen > 0 &&
5435285809Sscottl             pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteNameLen > 0 &&
5436285809Sscottl             ( portInfT.localNameLen ==
5437285809Sscottl               pSLRList[pWWNList[lDevIndex].sasLrIdx].localeNameLen ) &&
5438285809Sscottl             ( portInfT.remoteNameLen ==
5439285809Sscottl               pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteNameLen ) &&
5440285809Sscottl             memcmp( pWWNList[lDevIndex].targetName, pDevice->targetName,
5441285809Sscottl                     pDevice->targetLen )   == 0  &&
5442285809Sscottl             memcmp( pSLRList[pWWNList[lDevIndex].sasLrIdx].localeName,
5443285809Sscottl                     portInfT.localName,
5444285809Sscottl                     portInfT.localNameLen )   == 0  &&
5445285809Sscottl             memcmp( pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteName,
5446285809Sscottl                     portInfT.remoteName,
5447285809Sscottl                     portInfT.remoteNameLen )   == 0  )
5448285809Sscottl        {
5449285809Sscottl          AGTIAPI_PRINTK( " pWWNList match @ %d/%d/%d \n",
5450285809Sscottl                          lDevIndex, devIdx, pPortalInfo->portID );
5451285809Sscottl
5452285809Sscottl          if ( (pCard->pDevList[lDevIndex].targetId == lDevIndex) &&
5453285809Sscottl               ( pPortalInfo->pDevList[lDevIndex] ==
5454285809Sscottl                 &pCard->pDevList[lDevIndex] )  ) // active
5455285809Sscottl          {
5456285809Sscottl
5457285809Sscottl            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: dev in use %d of %d/%d\n",
5458285809Sscottl                            lDevIndex, devTotal, pPortalInfo->portID );
5459285809Sscottl            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev handle
5460285809Sscottl            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5461285809Sscottl            lReadRm = atomic_readandclear_32( &pWWNList[lDevIndex].devRemoved );
5462285809Sscottl            if ( lReadRm )   // cleared timeout, now remove count for timer
5463285809Sscottl            {
5464285809Sscottl              AGTIAPI_PRINTK( "agtiapi_GetDevHandle: clear timer count for"
5465285809Sscottl                              " %d of %d\n",
5466285809Sscottl                              lDevIndex, pPortalInfo->portID );
5467285809Sscottl              atomic_subtract_16( &pCard->rmChkCt, 1 );
5468285809Sscottl              lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
5469285809Sscottl              if ( 0 == lReadCt )
5470285809Sscottl              {
5471285809Sscottl                callout_stop( &pCard->devRmTimer );
5472285809Sscottl              }
5473285809Sscottl            }
5474285809Sscottl            break;
5475285809Sscottl          }
5476285809Sscottl
5477285809Sscottl          AGTIAPI_PRINTK( "agtiapi_GetDevHandle: goin fresh on %d of %d/%d\n",
5478285809Sscottl                          lDevIndex,  // reactivate now
5479285809Sscottl                          devTotal, pPortalInfo->portID );
5480285809Sscottl
5481285809Sscottl          // pDevice going fresh
5482285809Sscottl          lRunScanFlag = TRUE; // scan and clear outstanding removals
5483285809Sscottl
5484285809Sscottl          // pCard->tgtCount++; ##
5485285809Sscottl          pDevice->targetId  = lDevIndex;
5486285809Sscottl          pDevice->portalId  = pPortalInfo->portID;
5487285809Sscottl
5488285809Sscottl          memcpy ( &pCard->pDevList[lDevIndex], pDevice, sizeof(lTmpDevice) );
5489285809Sscottl          agDev[devIdx]->osData = (void *)&pCard->pDevList[lDevIndex];
5490285809Sscottl          if ( agtiapi_InitCCBs( pCard, 1, pDevice->targetId ) == 0 )
5491285809Sscottl          {
5492285809Sscottl            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: InitCCB "
5493285809Sscottl                            "tgtCnt %d ERROR!\n", pCard->tgtCount );
5494285809Sscottl            AG_LIST_UNLOCK( &pCard->devListLock );
5495285809Sscottl            free((caddr_t)lDevFlags, M_PMC_MFLG);
5496285809Sscottl            free((caddr_t)agDev, M_PMC_MDEV);
5497285809Sscottl            return 0;
5498285809Sscottl          }
5499285809Sscottl          pPortalInfo->pDevList[lDevIndex] = &pCard->pDevList[lDevIndex];     // (ag_device_t *)
5500285809Sscottl          if ( 0 == lDevFlags[devIdx] )
5501285809Sscottl          {
5502285809Sscottl            pPortalInfo->devTotal++;
5503285809Sscottl            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev used
5504285809Sscottl            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5505285809Sscottl          }
5506285809Sscottl          else
5507285809Sscottl          {
5508285809Sscottl            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: odd dev handle "
5509285809Sscottl                            "status inspect %d %d %d\n",
5510285809Sscottl                            lDevFlags[devIdx], devIdx, lDevIndex );
5511285809Sscottl            pPortalInfo->devTotal++;
5512285809Sscottl            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev used
5513285809Sscottl            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5514285809Sscottl
5515285809Sscottl          }
5516285809Sscottl          break;
5517285809Sscottl        }
5518285809Sscottl      }
5519285809Sscottl      // end: match this wwn with previous wwn list
5520285809Sscottl
5521285809Sscottl      // we have an agDev entry, but no pWWNList target for it
5522285809Sscottl      if ( !(lDevFlags[devIdx] & DPMC_LEANFLAG_AGDEVUSED) )
5523285809Sscottl      { // flag dev handle not accounted for yet
5524285809Sscottl        lDevFlags[devIdx] |= DPMC_LEANFLAG_NOWWNLIST;
5525285809Sscottl        // later, get an empty pDevice and map this agDev.
5526285809Sscottl        // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: devIdx %d flags 0x%x, %d\n",
5527285809Sscottl        //                 devIdx, lDevFlags[devIdx], (lDevFlags[devIdx] & 8) );
5528285809Sscottl      }
5529285809Sscottl    }
5530285809Sscottl    else
5531285809Sscottl    {
5532285809Sscottl      lDevFlags[devIdx] |= DPMC_LEANFLAG_NOAGDEVYT; // known empty agDev handle
5533285809Sscottl    }
5534285809Sscottl  }
5535285809Sscottl
5536285809Sscottl  // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: all WWN all the time, "
5537285809Sscottl  //                 "devLstIdx/flags/(WWNL)portId ... \n" );
5538285809Sscottl  // review device list for further action needed
5539285809Sscottl  for ( devIdx = 0; devIdx < pCard->devDiscover; devIdx++ )
5540285809Sscottl  {
5541285809Sscottl    if ( lDevFlags[devIdx] & DPMC_LEANFLAG_NOWWNLIST ) // new target, register
5542285809Sscottl    {
5543285809Sscottl      int lNextDyad; // find next available dyad entry
5544285809Sscottl
5545285809Sscottl      AGTIAPI_PRINTK( "agtiapi_GetDevHandle: register new target, "
5546285809Sscottl                      "devIdx %d -- %d \n", devIdx, pCard->devDiscover );
5547285809Sscottl      lRunScanFlag = TRUE; // scan and clear outstanding removals
5548285809Sscottl      for ( lNextDyad = 0; lNextDyad < pCard->devDiscover; lNextDyad++ )
5549285809Sscottl      {
5550285809Sscottl        if ( pSLRList[lNextDyad].localeNameLen < 0 &&
5551285809Sscottl             pSLRList[lNextDyad].remoteNameLen < 0    )
5552285809Sscottl          break;
5553285809Sscottl      }
5554285809Sscottl
5555285809Sscottl      if ( lNextDyad == pCard->devDiscover )
5556285809Sscottl      {
5557285809Sscottl        printf( "agtiapi_GetDevHandle: failed to find available SAS LR\n" );
5558285809Sscottl        AG_LIST_UNLOCK( &pCard->devListLock );
5559285809Sscottl        free( (caddr_t)lDevFlags, M_PMC_MFLG );
5560285809Sscottl        free( (caddr_t)agDev, M_PMC_MDEV );
5561285809Sscottl        return 0;
5562285809Sscottl      }
5563285809Sscottl      // index of new entry
5564285809Sscottl      lDevIndex = agtiapi_FindWWNListNext( pWWNList, pCard->devDiscover );
5565285809Sscottl      AGTIAPI_PRINTK( "agtiapi_GetDevHandle: listIdx new target %d of %d/%d\n",
5566285809Sscottl                      lDevIndex, devTotal, pPortalInfo->portID );
5567285809Sscottl      if ( 0 > lDevIndex )
5568285809Sscottl      {
5569285809Sscottl        printf( "agtiapi_GetDevHandle: WARNING -- WWNList exhausted.\n" );
5570285809Sscottl        continue;
5571285809Sscottl      }
5572285809Sscottl
5573285809Sscottl      pDevice = &pCard->pDevList[lDevIndex];
5574285809Sscottl
5575285809Sscottl      tiINIGetDeviceInfo( &pCard->tiRoot, agDev[devIdx], &pDevice->devInfo );
5576285809Sscottl      wwncpy( pDevice );
5577285809Sscottl      agtiapi_InitCCBs( pCard, 1, lDevIndex );
5578285809Sscottl
5579285809Sscottl      pDevice->pCard   = (void *)pCard;
5580285809Sscottl      pDevice->devType = DIRECT_DEVICE;
5581285809Sscottl
5582285809Sscottl      // begin to populate new WWNList entry
5583285809Sscottl      memcpy( pWWNList[lDevIndex].targetName, pDevice->targetName, pDevice->targetLen );
5584285809Sscottl      pWWNList[lDevIndex].targetLen = pDevice->targetLen;
5585285809Sscottl
5586285809Sscottl      pWWNList[lDevIndex].flags         = SOFT_MAPPED;
5587285809Sscottl      pWWNList[lDevIndex].portId        = pPortalInfo->portID;
5588285809Sscottl      pWWNList[lDevIndex].devListIndex  = lDevIndex;
5589285809Sscottl      pWWNList[lDevIndex].sasLrIdx      = lNextDyad;
5590285809Sscottl
5591285809Sscottl      pSLRList[lNextDyad].localeNameLen = portInfT.localNameLen;
5592285809Sscottl      pSLRList[lNextDyad].remoteNameLen = portInfT.remoteNameLen;
5593285809Sscottl      memcpy( pSLRList[lNextDyad].localeName, portInfT.localName, portInfT.localNameLen );
5594285809Sscottl      memcpy( pSLRList[lNextDyad].remoteName, portInfT.remoteName, portInfT.remoteNameLen );
5595285809Sscottl      // end of populating new WWNList entry
5596285809Sscottl
5597285809Sscottl      pDevice->targetId = lDevIndex;
5598285809Sscottl
5599285809Sscottl      pDevice->flags = ACTIVE;
5600285809Sscottl      pDevice->CCBCount = 0;
5601285809Sscottl      pDevice->pDevHandle = agDev[devIdx];
5602285809Sscottl      agDev[devIdx]->osData = (void*)pDevice;
5603285809Sscottl
5604285809Sscottl      pDevice->pPortalInfo = pPortalInfo;
5605285809Sscottl      pDevice->portalId = pPortalInfo->portID;
5606285809Sscottl      pPortalInfo->pDevList[lDevIndex] = (void*)pDevice;
5607285809Sscottl      lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // mark pDevice slot used
5608285809Sscottl    }
5609285809Sscottl
5610285809Sscottl    if ( (pCard->pDevList[devIdx].portalId == pPortalInfo->portID) &&
5611285809Sscottl         !(lDevFlags[devIdx] & DPMC_LEANFLAG_PDEVSUSED) ) // pDevice not used
5612285809Sscottl    {
5613285809Sscottl      pDevice = &pCard->pDevList[devIdx];
5614285809Sscottl      //pDevice->flags &= ~ACTIVE;
5615285809Sscottl      if ( ( pDevice->pDevHandle != NULL ||
5616285809Sscottl             pPortalInfo->pDevList[devIdx] != NULL ) )
5617285809Sscottl      {
5618285809Sscottl        atomic_add_16( &pCard->rmChkCt, 1 );      // show count of lost device
5619285809Sscottl
5620285809Sscottl        if (FALSE == lRunScanFlag)
5621285809Sscottl        {
5622285809Sscottl
5623285809Sscottl          AGTIAPI_PRINTK( "agtiapi_GetDevHandle: targ dropped out %d of %d/%d\n",
5624285809Sscottl                          devIdx, devTotal, pPortalInfo->portID );
5625285809Sscottl          // if ( 0 == pWWNList[devIdx].devRemoved ) '.devRemoved = 5;
5626285809Sscottl          cmpsetRtn = atomic_cmpset_32( &pWWNList[devIdx].devRemoved, 0, 5 );
5627285809Sscottl          if ( 0 == cmpsetRtn )
5628285809Sscottl          {
5629285809Sscottl            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: target %d timer already set\n",
5630285809Sscottl                    devIdx );
5631285809Sscottl          }
5632285809Sscottl          else
5633285809Sscottl          {
5634285809Sscottl            callout_reset( &pCard->devRmTimer, 1 * hz, agtiapi_devRmCheck, pCard );
5635285809Sscottl          }
5636285809Sscottl        }
5637285809Sscottl        // else ... scan coming soon enough anyway, ignore timer for dropout
5638285809Sscottl      }
5639285809Sscottl    }
5640285809Sscottl  } // end of for ( devIdx = 0; ...
5641285809Sscottl
5642285809Sscottl  AG_LIST_UNLOCK( &pCard->devListLock );
5643285809Sscottl
5644285809Sscottl  free((caddr_t)lDevFlags, M_PMC_MFLG);
5645285809Sscottl  free((caddr_t)agDev, M_PMC_MDEV);
5646285809Sscottl
5647285809Sscottl  if ( TRUE == lRunScanFlag )
5648285809Sscottl    agtiapi_clrRmScan( pCard );
5649285809Sscottl
5650285809Sscottl  return devTotal;
5651285809Sscottl} // end  agtiapi_GetDevHandle
5652285809Sscottl
5653285809Sscottl/******************************************************************************
5654285809Sscottlagtiapi_scan()
5655285809Sscottl
5656285809SscottlPurpose:
5657285809Sscottl  Triggers CAM's scan
5658285809SscottlParameters:
5659285809Sscottl  struct agtiapi_softc *pCard (IN)    Pointer to the HBA data structure
5660285809SscottlReturn:
5661285809SscottlNote:
5662285809Sscottl******************************************************************************/
5663285809Sscottlstatic void agtiapi_scan(struct agtiapi_softc *pmcsc)
5664285809Sscottl{
5665285809Sscottl  union ccb *ccb;
5666285809Sscottl  int bus, tid, lun, card_no;
5667285809Sscottl  static int num=0;
5668285809Sscottl
5669285809Sscottl  AGTIAPI_PRINTK("agtiapi_scan: start cardNO %d \n", pmcsc->cardNo);
5670285809Sscottl
5671285809Sscottl  bus = cam_sim_path(pmcsc->sim);
5672285809Sscottl
5673285809Sscottl  tid = CAM_TARGET_WILDCARD;
5674285809Sscottl  lun = CAM_LUN_WILDCARD;
5675285809Sscottl
5676285809Sscottl  mtx_lock(&(pmcsc->pCardInfo->pmIOLock));
5677285809Sscottl  ccb = xpt_alloc_ccb_nowait();
5678285809Sscottl  if (ccb == agNULL)
5679285809Sscottl  {
5680285809Sscottl    mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5681285809Sscottl    return;
5682285809Sscottl  }
5683285809Sscottl  if (xpt_create_path(&ccb->ccb_h.path, agNULL, bus, tid,
5684285809Sscottl		      CAM_LUN_WILDCARD) != CAM_REQ_CMP)
5685285809Sscottl  {
5686285809Sscottl    mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5687285809Sscottl    xpt_free_ccb(ccb);
5688285809Sscottl    return;
5689285809Sscottl  }
5690285809Sscottl
5691285809Sscottl  mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5692285809Sscottl  pmcsc->dev_scan = agTRUE;
5693285809Sscottl  xpt_rescan(ccb);
5694285809Sscottl  return;
5695285809Sscottl}
5696285809Sscottl
5697285809Sscottl/******************************************************************************
5698285809Sscottlagtiapi_DeQueueCCB()
5699285809Sscottl
5700285809SscottlPurpose:
5701285809Sscottl  Remove a ccb from a queue
5702285809SscottlParameters:
5703285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to the card structure
5704285809Sscottl  pccb_t *phead (IN)     Pointer to a head of ccb queue
5705285809Sscottl  ccb_t  *pccd  (IN)     Pointer to the ccb to be processed
5706285809SscottlReturn:
5707285809Sscottl  AGTIAPI_SUCCESS - the ccb is removed from queue
5708285809Sscottl  AGTIAPI_FAIL    - the ccb is not found from queue
5709285809SscottlNote:
5710285809Sscottl******************************************************************************/
5711285809SscottlSTATIC agBOOLEAN
5712285809Sscottlagtiapi_DeQueueCCB(struct agtiapi_softc *pCard, pccb_t *phead, pccb_t *ptail,
5713285809Sscottl#ifdef AGTIAPI_LOCAL_LOCK
5714285809Sscottl                   struct mtx *lock,
5715285809Sscottl#endif
5716285809Sscottl                   ccb_t *pccb)
5717285809Sscottl{
5718285809Sscottl  ccb_t  *pccb_curr;
5719285809Sscottl  U32     status = AGTIAPI_FAIL;
5720285809Sscottl
5721285809Sscottl  AGTIAPI_PRINTK("agtiapi_DeQueueCCB: %p from %p\n", pccb, phead);
5722285809Sscottl
5723285809Sscottl  if (pccb == NULL || *phead == NULL)
5724285809Sscottl  {
5725285809Sscottl    return AGTIAPI_FAIL;
5726285809Sscottl  }
5727285809Sscottl
5728285809Sscottl  AGTIAPI_PRINTK("agtiapi_DeQueueCCB: %p from %p\n", pccb, phead);
5729285809Sscottl  AG_LOCAL_LOCK(lock);
5730285809Sscottl
5731285809Sscottl  if (pccb == *phead)
5732285809Sscottl  {
5733285809Sscottl    *phead = (*phead)->pccbNext;
5734285809Sscottl    if (pccb == *ptail)
5735285809Sscottl    {
5736285809Sscottl      *ptail = NULL;
5737285809Sscottl    }
5738285809Sscottl    else
5739285809Sscottl      pccb->pccbNext = NULL;
5740285809Sscottl    status = AGTIAPI_SUCCESS;
5741285809Sscottl  }
5742285809Sscottl  else
5743285809Sscottl  {
5744285809Sscottl    pccb_curr = *phead;
5745285809Sscottl    while (pccb_curr->pccbNext != NULL)
5746285809Sscottl    {
5747285809Sscottl      if (pccb_curr->pccbNext == pccb)
5748285809Sscottl      {
5749285809Sscottl        pccb_curr->pccbNext = pccb->pccbNext;
5750285809Sscottl        pccb->pccbNext = NULL;
5751285809Sscottl        if (pccb == *ptail)
5752285809Sscottl        {
5753285809Sscottl          *ptail = pccb_curr;
5754285809Sscottl        }
5755285809Sscottl        else
5756285809Sscottl          pccb->pccbNext = NULL;
5757285809Sscottl        status = AGTIAPI_SUCCESS;
5758285809Sscottl        break;
5759285809Sscottl      }
5760285809Sscottl      pccb_curr = pccb_curr->pccbNext;
5761285809Sscottl    }
5762285809Sscottl  }
5763285809Sscottl  AG_LOCAL_UNLOCK(lock);
5764285809Sscottl
5765285809Sscottl  return status;
5766285809Sscottl}
5767285809Sscottl
5768285809Sscottl
5769285809SscottlSTATIC void wwnprintk( unsigned char *name, int len )
5770285809Sscottl{
5771285809Sscottl  int i;
5772285809Sscottl
5773285809Sscottl  for (i = 0; i < len; i++, name++)
5774285809Sscottl    AGTIAPI_PRINTK("%02x", *name);
5775285809Sscottl  AGTIAPI_PRINTK("\n");
5776285809Sscottl}
5777285809Sscottl/*
5778285809Sscottl * SAS and SATA behind expander has 8 byte long unique address.
5779285809Sscottl * However, direct connect SATA device use 512 byte unique device id.
5780285809Sscottl * SPC uses remoteName to indicate length of ID and remoteAddress for the
5781285809Sscottl * address of memory that holding ID.
5782285809Sscottl */
5783285809SscottlSTATIC int wwncpy( ag_device_t      *pDevice )
5784285809Sscottl{
5785285809Sscottl  int rc = 0;
5786285809Sscottl
5787285809Sscottl  if (sizeof(pDevice->targetName) >= pDevice->devInfo.osAddress1 +
5788285809Sscottl                                     pDevice->devInfo.osAddress2)
5789285809Sscottl  {
5790285809Sscottl    memcpy(pDevice->targetName,
5791285809Sscottl             pDevice->devInfo.remoteName,
5792285809Sscottl             pDevice->devInfo.osAddress1);
5793285809Sscottl    memcpy(pDevice->targetName + pDevice->devInfo.osAddress1,
5794285809Sscottl             pDevice->devInfo.remoteAddress,
5795285809Sscottl             pDevice->devInfo.osAddress2);
5796285809Sscottl    pDevice->targetLen = pDevice->devInfo.osAddress1 +
5797285809Sscottl                         pDevice->devInfo.osAddress2;
5798285809Sscottl    rc = pDevice->targetLen;
5799285809Sscottl  }
5800285809Sscottl  else
5801285809Sscottl  {
5802285809Sscottl    AGTIAPI_PRINTK("WWN wrong size: %d + %d ERROR\n",
5803285809Sscottl           pDevice->devInfo.osAddress1, pDevice->devInfo.osAddress2);
5804285809Sscottl    rc = -1;
5805285809Sscottl  }
5806285809Sscottl  return rc;
5807285809Sscottl}
5808285809Sscottl
5809285809Sscottl
5810285809Sscottl/******************************************************************************
5811285809Sscottlagtiapi_ReleaseCCBs()
5812285809Sscottl
5813285809SscottlPurpose:
5814285809Sscottl  Free all allocated CCB memories for the Host Adapter.
5815285809SscottlParameters:
5816285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to HBA data stucture
5817285809SscottlReturn:
5818285809SscottlNote:
5819285809Sscottl******************************************************************************/
5820285809SscottlSTATIC void agtiapi_ReleaseCCBs( struct agtiapi_softc *pCard )
5821285809Sscottl{
5822285809Sscottl
5823285809Sscottl  ccb_hdr_t *hdr;
5824285809Sscottl  U32 hdr_sz;
5825285809Sscottl  ccb_t *pccb = 0;
5826285809Sscottl
5827285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ReleaseCCBs: start\n" );
5828285809Sscottl
5829285809Sscottl#if ( defined AGTIAPI_TEST_DPL || defined AGTIAPI_TEST_EPL )
5830285809Sscottl  ccb_t *pccb;
5831285809Sscottl#endif
5832285809Sscottl
5833285809Sscottl#ifdef AGTIAPI_TEST_DPL
5834285809Sscottl  for (pccb = (pccb_t)pCard->ccbChainList; pccb != NULL;
5835285809Sscottl       pccb = pccb->pccbChainNext)
5836285809Sscottl  {
5837285809Sscottl    if(pccb->dplPtr && pccb->dplDma)
5838285809Sscottl      pci_pool_free(pCard->dpl_ctx_pool,   pccb->dplPtr, pccb->dplDma);
5839285809Sscottl  }
5840285809Sscottl#endif
5841285809Sscottl
5842285809Sscottl#ifdef AGTIAPI_TEST_EPL
5843285809Sscottl  for (pccb = (pccb_t)pCard->ccbChainList; pccb != NULL;
5844285809Sscottl       pccb = pccb->pccbChainNext)
5845285809Sscottl  {
5846285809Sscottl    if(pccb->epl_ptr && pccb->epl_dma_ptr)
5847285809Sscottl        pci_pool_free(
5848285809Sscottl            pCard->epl_ctx_pool,
5849285809Sscottl            pccb->epl_ptr,
5850285809Sscottl            pccb->epl_dma_ptr
5851285809Sscottl        );
5852285809Sscottl  }
5853285809Sscottl#endif
5854285809Sscottl
5855285809Sscottl  while ((hdr = pCard->ccbAllocList) != NULL)
5856285809Sscottl  {
5857285809Sscottl    pCard->ccbAllocList = hdr->next;
5858285809Sscottl    hdr_sz = (sizeof(*hdr) + cache_line_size() - 1) & ~(cache_line_size() - 1);
5859285809Sscottl    pccb = (ccb_t*) ((char*)hdr + hdr_sz);
5860285809Sscottl    if (pCard->buffer_dmat != NULL && pccb->CCB_dmamap != NULL)
5861285809Sscottl    {
5862285809Sscottl      bus_dmamap_destroy(pCard->buffer_dmat, pccb->CCB_dmamap);
5863285809Sscottl    }
5864285809Sscottl    free(hdr, M_PMC_MCCB);
5865285809Sscottl  }
5866285809Sscottl  pCard->ccbAllocList = NULL;
5867285809Sscottl
5868285809Sscottl
5869285809Sscottl  return;
5870285809Sscottl}
5871285809Sscottl
5872285809Sscottl/******************************************************************************
5873285809Sscottlagtiapi_TITimer()
5874285809Sscottl
5875285809SscottlPurpose:
5876285809Sscottl  Timer tick for tisa common layer
5877285809SscottlParameters:
5878285809Sscottl  void *data (IN)  Pointer to the HBA data structure
5879285809SscottlReturn:
5880285809SscottlNote:
5881285809Sscottl******************************************************************************/
5882285809SscottlSTATIC void agtiapi_TITimer( void *data )
5883285809Sscottl{
5884285809Sscottl
5885285809Sscottl  U32                   next_tick;
5886285809Sscottl  struct agtiapi_softc *pCard;
5887285809Sscottl
5888285809Sscottl  pCard = (struct agtiapi_softc *)data;
5889285809Sscottl
5890285809Sscottl//  AGTIAPI_PRINTK("agtiapi_TITimer: start\n");
5891285809Sscottl  AG_GLOBAL_ARG( flags );
5892285809Sscottl
5893285809Sscottl  next_tick = pCard->pCardInfo->tiRscInfo.tiLoLevelResource.
5894285809Sscottl              loLevelOption.usecsPerTick / USEC_PER_TICK;
5895285809Sscottl
5896285809Sscottl  if( next_tick == 0 )               /* no timer required */
5897285809Sscottl    return;
5898285809Sscottl  AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
5899285809Sscottl  if( pCard->flags & AGTIAPI_SHUT_DOWN )
5900285809Sscottl    goto ext;
5901285809Sscottl  tiCOMTimerTick( &pCard->tiRoot );  /* tisa common layer timer tick */
5902285809Sscottl
5903285809Sscottl  //add for polling mode
5904285809Sscottl#ifdef PMC_SPC
5905285809Sscottl  if( agtiapi_polling_mode )
5906285809Sscottl    agtiapi_CheckAllVectors( pCard, tiNonInterruptContext );
5907285809Sscottl#endif
5908285809Sscottl  callout_reset( &pCard->OS_timer, next_tick, agtiapi_TITimer, pCard );
5909285809Sscottlext:
5910285809Sscottl  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
5911285809Sscottl  return;
5912285809Sscottl}
5913285809Sscottl
5914285809Sscottl/******************************************************************************
5915285809Sscottlagtiapi_clrRmScan()
5916285809Sscottl
5917285809SscottlPurpose:
5918285809Sscottl  Clears device list entries scheduled for timeout and calls scan
5919285809SscottlParameters:
5920285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to HBA data structure
5921285809Sscottl******************************************************************************/
5922285809SscottlSTATIC void agtiapi_clrRmScan( struct agtiapi_softc *pCard )
5923285809Sscottl{
5924285809Sscottl  ag_tgt_map_t         *pWWNList;
5925285809Sscottl  ag_portal_info_t     *pPortalInfo;
5926285809Sscottl  ag_portal_data_t     *pPortalData;
5927285809Sscottl  int                   lIdx;
5928285809Sscottl  bit32                 lReadRm;
5929285809Sscottl  bit16                 lReadCt;
5930285809Sscottl
5931285809Sscottl  pWWNList = pCard->pWWNList;
5932285809Sscottl
5933285809Sscottl  AGTIAPI_PRINTK( "agtiapi_clrRmScan: start\n" );
5934285809Sscottl
5935285809Sscottl  AG_LIST_LOCK( &pCard->devListLock );
5936285809Sscottl
5937285809Sscottl  for ( lIdx = 0; lIdx < pCard->devDiscover; lIdx++ )
5938285809Sscottl  {
5939285809Sscottl    lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
5940285809Sscottl    if ( 0 == lReadCt )
5941285809Sscottl    {
5942285809Sscottl      break;  // trim to who cares
5943285809Sscottl    }
5944285809Sscottl
5945285809Sscottl    lReadRm = atomic_readandclear_32( &pWWNList[lIdx].devRemoved );
5946285809Sscottl    if ( lReadRm > 0 )
5947285809Sscottl    {
5948285809Sscottl      pCard->pDevList[lIdx].flags &= ~ACTIVE;
5949285809Sscottl      pCard->pDevList[lIdx].pDevHandle = NULL;
5950285809Sscottl
5951285809Sscottl      pPortalData = &pCard->pPortalData[pWWNList[lIdx].portId];
5952285809Sscottl      pPortalInfo = &pPortalData->portalInfo;
5953285809Sscottl      pPortalInfo->pDevList[lIdx] = NULL;
5954285809Sscottl      AGTIAPI_PRINTK( "agtiapi_clrRmScan: cleared dev %d at port %d\n",
5955285809Sscottl                      lIdx, pWWNList[lIdx].portId );
5956285809Sscottl      atomic_subtract_16( &pCard->rmChkCt, 1 );
5957285809Sscottl    }
5958285809Sscottl  }
5959285809Sscottl  AG_LIST_UNLOCK( &pCard->devListLock );
5960285809Sscottl
5961285809Sscottl  agtiapi_scan( pCard );
5962285809Sscottl}
5963285809Sscottl
5964285809Sscottl
5965285809Sscottl/******************************************************************************
5966285809Sscottlagtiapi_devRmCheck()
5967285809Sscottl
5968285809SscottlPurpose:
5969285809Sscottl  Timer tick to check for timeout on missing targets
5970285809Sscottl  Removes device list entry when timeout is reached
5971285809SscottlParameters:
5972285809Sscottl  void *data (IN)  Pointer to the HBA data structure
5973285809Sscottl******************************************************************************/
5974285809SscottlSTATIC void agtiapi_devRmCheck( void *data )
5975285809Sscottl{
5976285809Sscottl  struct agtiapi_softc *pCard;
5977285809Sscottl  ag_tgt_map_t         *pWWNList;
5978285809Sscottl  int                   lIdx, cmpsetRtn, lRunScanFlag = FALSE;
5979285809Sscottl  bit16                 lReadCt;
5980285809Sscottl  bit32                 lReadRm;
5981285809Sscottl
5982285809Sscottl  pCard = ( struct agtiapi_softc * )data;
5983285809Sscottl
5984285809Sscottl  // routine overhead
5985285809Sscottl  if ( callout_pending( &pCard->devRmTimer ) )  // callout was reset
5986285809Sscottl  {
5987285809Sscottl    return;
5988285809Sscottl  }
5989285809Sscottl  if ( !callout_active( &pCard->devRmTimer ) )  // callout was stopped
5990285809Sscottl  {
5991285809Sscottl    return;
5992285809Sscottl  }
5993285809Sscottl  callout_deactivate( &pCard->devRmTimer );
5994285809Sscottl
5995285809Sscottl  if( pCard->flags & AGTIAPI_SHUT_DOWN )
5996285809Sscottl  {
5997285809Sscottl    return;  // implicit timer clear
5998285809Sscottl  }
5999285809Sscottl
6000285809Sscottl  pWWNList = pCard->pWWNList;
6001285809Sscottl
6002285809Sscottl  AG_LIST_LOCK( &pCard->devListLock );
6003285809Sscottl  lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
6004285809Sscottl  if ( lReadCt )
6005285809Sscottl  {
6006285809Sscottl    if ( callout_pending(&pCard->devRmTimer) == FALSE )
6007285809Sscottl    {
6008285809Sscottl      callout_reset( &pCard->devRmTimer, 1 * hz, agtiapi_devRmCheck, pCard );
6009285809Sscottl    }
6010285809Sscottl    else
6011285809Sscottl    {
6012285809Sscottl      AG_LIST_UNLOCK( &pCard->devListLock );
6013285809Sscottl	  return;
6014285809Sscottl    }
6015285809Sscottl
6016285809Sscottl    for ( lIdx = 0; lIdx < pCard->devDiscover; lIdx++ )
6017285809Sscottl    {
6018285809Sscottl      lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
6019285809Sscottl      if ( 0 == lReadCt )
6020285809Sscottl      {
6021285809Sscottl        break;  // if handled somewhere else, get out
6022285809Sscottl      }
6023285809Sscottl
6024285809Sscottl      lReadRm = atomic_load_acq_32( &pWWNList[lIdx].devRemoved );
6025285809Sscottl      if ( lReadRm > 0 )
6026285809Sscottl      {
6027285809Sscottl        if ( 1 == lReadRm ) // timed out
6028285809Sscottl        { // no decrement of devRemoved as way to leave a clrRmScan marker
6029285809Sscottl          lRunScanFlag = TRUE; // other devRemoved values are about to get wiped
6030285809Sscottl          break; // ... so bail out
6031285809Sscottl        }
6032285809Sscottl        else
6033285809Sscottl        {
6034285809Sscottl          AGTIAPI_PRINTK( "agtiapi_devRmCheck: counting down dev %d @ %d; %d\n",
6035285809Sscottl                          lIdx, lReadRm, lReadCt );
6036285809Sscottl          cmpsetRtn = atomic_cmpset_32( &pWWNList[lIdx].devRemoved,
6037285809Sscottl                                        lReadRm,
6038285809Sscottl                                        lReadRm-1 );
6039285809Sscottl          if ( 0 == cmpsetRtn )
6040285809Sscottl          {
6041285809Sscottl            printf( "agtiapi_devRmCheck: %d decrement already handled\n",
6042285809Sscottl                    lIdx );
6043285809Sscottl          }
6044285809Sscottl        }
6045285809Sscottl      }
6046285809Sscottl    }
6047285809Sscottl    AG_LIST_UNLOCK( &pCard->devListLock );
6048285809Sscottl
6049285809Sscottl    if ( TRUE == lRunScanFlag )
6050285809Sscottl      agtiapi_clrRmScan( pCard );
6051285809Sscottl  }
6052285809Sscottl  else
6053285809Sscottl  {
6054285809Sscottl    AG_LIST_UNLOCK( &pCard->devListLock );
6055285809Sscottl  }
6056285809Sscottl
6057285809Sscottl  return;
6058285809Sscottl}
6059285809Sscottl
6060285809Sscottl
6061285809Sscottlstatic void agtiapi_cam_poll( struct cam_sim *asim )
6062285809Sscottl{
6063285809Sscottl  return;
6064285809Sscottl}
6065285809Sscottl
6066285809Sscottl/*****************************************************************************
6067285809Sscottlagtiapi_ResetCard()
6068285809Sscottl
6069285809SscottlPurpose:
6070285809Sscottl  Hard or soft reset on the controller and resend any
6071285809Sscottl  outstanding requests if needed.
6072285809SscottlParameters:
6073285809Sscottl  struct agtiapi_softc *pCard (IN)  Pointer to HBA data structure
6074285809Sscottl  unsigned lomg flags (IN/OUT) Flags used in locking done from calling layers
6075285809SscottlReturn:
6076285809Sscottl  AGTIAPI_SUCCESS - reset successful
6077285809Sscottl  AGTIAPI_FAIL    - reset failed
6078285809SscottlNote:
6079285809Sscottl*****************************************************************************/
6080285809SscottlU32 agtiapi_ResetCard( struct agtiapi_softc *pCard, unsigned long *flags )
6081285809Sscottl{
6082285809Sscottl  ag_device_t      *pDevice;
6083285809Sscottl  U32               lIdx = 0;
6084285809Sscottl  U32               lFlagVal;
6085285809Sscottl  agBOOLEAN         ret;
6086285809Sscottl  ag_portal_info_t *pPortalInfo;
6087285809Sscottl  ag_portal_data_t *pPortalData;
6088285809Sscottl  U32               count, loop;
6089285809Sscottl  int               szdv;
6090285809Sscottl
6091285809Sscottl  if( pCard->flags & AGTIAPI_RESET ) {
6092285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ResetCard: reset card already in progress!\n" );
6093285809Sscottl    return AGTIAPI_FAIL;
6094285809Sscottl  }
6095285809Sscottl
6096285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ResetCard: Enter cnt %d\n",
6097285809Sscottl                  pCard->resetCount );
6098285809Sscottl#ifdef LOGEVENT
6099285809Sscottl  agtiapi_LogEvent( pCard,
6100285809Sscottl                    IOCTL_EVT_SEV_INFORMATIONAL,
6101285809Sscottl                    0,
6102285809Sscottl                    agNULL,
6103285809Sscottl                    0,
6104285809Sscottl                    "Reset initiator time = %d!",
6105285809Sscottl                    pCard->resetCount + 1 );
6106285809Sscottl#endif
6107285809Sscottl
6108285809Sscottl  pCard->flags |= AGTIAPI_RESET;
6109285809Sscottl  pCard->flags &= ~(AGTIAPI_CB_DONE | AGTIAPI_RESET_SUCCESS);
6110285809Sscottl  tiCOMSystemInterruptsActive( &pCard->tiRoot, FALSE );
6111285809Sscottl  pCard->flags &= ~AGTIAPI_SYS_INTR_ON;
6112285809Sscottl
6113285809Sscottl  agtiapi_FlushCCBs( pCard, AGTIAPI_CALLBACK );
6114285809Sscottl
6115285809Sscottl  for ( lIdx = 1; 3 >= lIdx; lIdx++ ) // we try reset up to 3 times
6116285809Sscottl  {
6117285809Sscottl    if( pCard->flags & AGTIAPI_SOFT_RESET )
6118285809Sscottl    {
6119285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft variant\n" );
6120285809Sscottl      tiCOMReset( &pCard->tiRoot, tiSoftReset );
6121285809Sscottl    }
6122285809Sscottl    else
6123285809Sscottl    {
6124285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: no flag, no reset!\n" );
6125285809Sscottl    }
6126285809Sscottl
6127285809Sscottl    lFlagVal = AGTIAPI_RESET_SUCCESS;
6128285809Sscottl    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, *flags );
6129285809Sscottl    ret = agtiapi_CheckCB( pCard, 50000, lFlagVal, &pCard->flags );
6130285809Sscottl    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, *flags );
6131285809Sscottl
6132285809Sscottl    if( ret == AGTIAPI_FAIL )
6133285809Sscottl    {
6134285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: CheckCB indicates failed reset call, "
6135285809Sscottl              "try again?\n" );
6136285809Sscottl    }
6137285809Sscottl    else
6138285809Sscottl    {
6139285809Sscottl      break;
6140285809Sscottl    }
6141285809Sscottl  }
6142285809Sscottl  if ( 1 < lIdx )
6143285809Sscottl  {
6144285809Sscottl    if ( AGTIAPI_FAIL == ret )
6145285809Sscottl    {
6146285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft reset failed after try %d\n",
6147285809Sscottl                      lIdx );
6148285809Sscottl    }
6149285809Sscottl    else
6150285809Sscottl    {
6151285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft reset success at try %d\n",
6152285809Sscottl                      lIdx );
6153285809Sscottl    }
6154285809Sscottl  }
6155285809Sscottl  if( AGTIAPI_FAIL == ret )
6156285809Sscottl  {
6157285809Sscottl    printf( "agtiapi_ResetCard: reset ERROR\n" );
6158285809Sscottl    pCard->flags &= ~AGTIAPI_INSTALLED;
6159285809Sscottl    return AGTIAPI_FAIL;
6160285809Sscottl  }
6161285809Sscottl
6162285809Sscottl  pCard->flags &= ~AGTIAPI_SOFT_RESET;
6163285809Sscottl
6164285809Sscottl  // disable all devices
6165285809Sscottl  pDevice = pCard->pDevList;
6166285809Sscottl  for( lIdx = 0; lIdx < maxTargets; lIdx++, pDevice++ )
6167285809Sscottl  {
6168285809Sscottl    /* if ( pDevice->flags & ACTIVE )
6169285809Sscottl    {
6170285809Sscottl      printf( "agtiapi_ResetCard: before ... active device %d\n", lIdx );
6171285809Sscottl    } */
6172285809Sscottl    pDevice->flags &= ~ACTIVE;
6173285809Sscottl  }
6174285809Sscottl
6175285809Sscottl  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, *flags );
6176285809Sscottl  if( tiCOMPortInit( &pCard->tiRoot, agFALSE ) != tiSuccess )
6177285809Sscottl    printf( "agtiapi_ResetCard: tiCOMPortInit FAILED \n" );
6178285809Sscottl  else
6179285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortInit success\n" );
6180285809Sscottl
6181285809Sscottl  if( !pCard->pDevList ) {  // try to get a little sanity here
6182285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ResetCard: no pDevList ERROR %p\n",
6183285809Sscottl                    pCard->pDevList );
6184285809Sscottl    return AGTIAPI_FAIL;
6185285809Sscottl  }
6186285809Sscottl
6187285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ResetCard: pre target-count %d port-count %d\n",
6188285809Sscottl                  pCard->tgtCount, pCard->portCount );
6189285809Sscottl  pCard->tgtCount = 0;
6190285809Sscottl
6191285809Sscottl  DELAY( 500000 );
6192285809Sscottl
6193285809Sscottl  pCard->flags &= ~AGTIAPI_CB_DONE;
6194285809Sscottl
6195285809Sscottl  pPortalData = pCard->pPortalData;
6196285809Sscottl
6197285809Sscottl  for( count = 0; count < pCard->portCount; count++ ) {
6198285809Sscottl    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
6199285809Sscottl    pPortalInfo = &pPortalData->portalInfo;
6200285809Sscottl    pPortalInfo->portStatus = 0;
6201285809Sscottl    pPortalInfo->portStatus &= ~( AGTIAPI_PORT_START      |
6202285809Sscottl                                  AGTIAPI_PORT_DISC_READY |
6203285809Sscottl                                  AGTIAPI_DISC_DONE       |
6204285809Sscottl                                  AGTIAPI_DISC_COMPLETE );
6205285809Sscottl
6206285809Sscottl    szdv =
6207285809Sscottl      sizeof( pPortalInfo->pDevList ) / sizeof( pPortalInfo->pDevList[0] );
6208285809Sscottl    if (szdv > pCard->devDiscover)
6209285809Sscottl    {
6210285809Sscottl      szdv = pCard->devDiscover;
6211285809Sscottl    }
6212285809Sscottl
6213285809Sscottl    for( lIdx = 0, loop = 0;
6214285809Sscottl         lIdx < szdv  &&  loop < pPortalInfo->devTotal;
6215285809Sscottl         lIdx++ )
6216285809Sscottl    {
6217285809Sscottl      pDevice = (ag_device_t*)pPortalInfo->pDevList[lIdx];
6218285809Sscottl      if( pDevice )
6219285809Sscottl      {
6220285809Sscottl        loop++;
6221285809Sscottl        pDevice->pDevHandle = 0; // mark for availability in pCard->pDevList[]
6222285809Sscottl        // don't erase more as the device is scheduled for removal on DPC
6223285809Sscottl      }
6224285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: reset pDev %p pDevList %p idx %d\n",
6225285809Sscottl                      pDevice, pPortalInfo->pDevList, lIdx );
6226285809Sscottl      pPortalInfo->devTotal = pPortalInfo->devPrev = 0;
6227285809Sscottl    }
6228285809Sscottl
6229285809Sscottl    for( lIdx = 0; lIdx < maxTargets; lIdx++ )
6230285809Sscottl    { // we reconstruct dev list later in get dev handle
6231285809Sscottl      pPortalInfo->pDevList[lIdx] = NULL;
6232285809Sscottl    }
6233285809Sscottl
6234285809Sscottl    for( loop = 0; loop < AGTIAPI_LOOP_MAX; loop++ )
6235285809Sscottl    {
6236285809Sscottl      AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortStart entry data "
6237285809Sscottl                      "%p / %d / %p\n",
6238285809Sscottl                      &pCard->tiRoot,
6239285809Sscottl                      pPortalInfo->portID,
6240285809Sscottl                      &pPortalInfo->tiPortalContext );
6241285809Sscottl
6242285809Sscottl      if( tiCOMPortStart( &pCard->tiRoot,
6243285809Sscottl                          pPortalInfo->portID,
6244285809Sscottl                          &pPortalInfo->tiPortalContext,
6245285809Sscottl                          0 )
6246285809Sscottl          != tiSuccess )
6247285809Sscottl      {
6248285809Sscottl        printf( "agtiapi_ResetCard: tiCOMPortStart %d FAILED\n",
6249285809Sscottl                pPortalInfo->portID );
6250285809Sscottl      }
6251285809Sscottl      else
6252285809Sscottl      {
6253285809Sscottl        AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortStart %d success\n",
6254285809Sscottl                        pPortalInfo->portID );
6255285809Sscottl        break;
6256285809Sscottl      }
6257285809Sscottl    }
6258285809Sscottl    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
6259285809Sscottl    tiCOMGetPortInfo( &pCard->tiRoot,
6260285809Sscottl                      &pPortalInfo->tiPortalContext,
6261285809Sscottl                      &pPortalInfo->tiPortInfo );
6262285809Sscottl    pPortalData++;
6263285809Sscottl  }
6264285809Sscottl  // ## fail case:  pCard->flags &= ~AGTIAPI_INSTALLED;
6265285809Sscottl
6266285809Sscottl
6267285809Sscottl  AG_SPIN_LOCK_IRQ(agtiapi_host_lock, *flags);
6268285809Sscottl
6269285809Sscottl  if( !(pCard->flags & AGTIAPI_INSTALLED) ) // driver not installed !
6270285809Sscottl  {
6271285809Sscottl    printf( "agtiapi_ResetCard: error, driver not intstalled? "
6272285809Sscottl            "!AGTIAPI_INSTALLED \n" );
6273285809Sscottl    return AGTIAPI_FAIL;
6274285809Sscottl  }
6275285809Sscottl
6276285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ResetCard: total device %d\n", pCard->tgtCount );
6277285809Sscottl
6278285809Sscottl#ifdef LOGEVENT
6279285809Sscottl  agtiapi_LogEvent( pCard,
6280285809Sscottl                    IOCTL_EVT_SEV_INFORMATIONAL,
6281285809Sscottl                    0,
6282285809Sscottl                    agNULL,
6283285809Sscottl                    0,
6284285809Sscottl                    "Reset initiator total device = %d!",
6285285809Sscottl                    pCard->tgtCount );
6286285809Sscottl#endif
6287285809Sscottl  pCard->resetCount++;
6288285809Sscottl
6289285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ResetCard: clear send and done queues\n" );
6290285809Sscottl  // clear send & done queue
6291285809Sscottl  AG_LOCAL_LOCK( &pCard->sendLock );
6292285809Sscottl  pCard->ccbSendHead = NULL;
6293285809Sscottl  pCard->ccbSendTail = NULL;
6294285809Sscottl  AG_LOCAL_UNLOCK( &pCard->sendLock );
6295285809Sscottl
6296285809Sscottl  AG_LOCAL_LOCK( &pCard->doneLock );
6297285809Sscottl  pCard->ccbDoneHead = NULL;
6298285809Sscottl  pCard->ccbDoneTail = NULL;
6299285809Sscottl  AG_LOCAL_UNLOCK( &pCard->doneLock );
6300285809Sscottl
6301285809Sscottl  // clear smp queues also
6302285809Sscottl  AG_LOCAL_LOCK( &pCard->sendSMPLock );
6303285809Sscottl  pCard->smpSendHead = NULL;
6304285809Sscottl  pCard->smpSendTail = NULL;
6305285809Sscottl  AG_LOCAL_UNLOCK( &pCard->sendSMPLock );
6306285809Sscottl
6307285809Sscottl  AG_LOCAL_LOCK( &pCard->doneSMPLock );
6308285809Sscottl  pCard->smpDoneHead = NULL;
6309285809Sscottl  pCard->smpDoneTail = NULL;
6310285809Sscottl  AG_LOCAL_UNLOCK( &pCard->doneSMPLock );
6311285809Sscottl
6312285809Sscottl  // finished with all reset stuff, now start things back up
6313285809Sscottl  tiCOMSystemInterruptsActive( &pCard->tiRoot, TRUE );
6314285809Sscottl  pCard->flags |= AGTIAPI_SYS_INTR_ON;
6315285809Sscottl  pCard->flags |= AGTIAPI_HAD_RESET;
6316285809Sscottl  pCard->flags &= ~AGTIAPI_RESET;  // ##
6317285809Sscottl  agtiapi_StartIO( pCard );
6318285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ResetCard: local return success\n" );
6319285809Sscottl  return AGTIAPI_SUCCESS;
6320285809Sscottl} // agtiapi_ResetCard
6321285809Sscottl
6322285809Sscottl
6323285809Sscottl/******************************************************************************
6324285809Sscottlagtiapi_ReleaseHBA()
6325285809Sscottl
6326285809SscottlPurpose:
6327285809Sscottl  Releases all resources previously acquired to support
6328285809Sscottl  a specific Host Adapter, including the I/O Address range,
6329285809Sscottl  and unregisters the agtiapi Host Adapter.
6330285809SscottlParameters:
6331285809Sscottl  device_t dev (IN)  - device pointer
6332285809SscottlReturn:
6333285809Sscottl  always return 0 - success
6334285809SscottlNote:
6335285809Sscottl******************************************************************************/
6336285809Sscottlint agtiapi_ReleaseHBA( device_t dev )
6337285809Sscottl{
6338285809Sscottl
6339285809Sscottl  int thisCard = device_get_unit( dev ); // keeping get_unit call to once
6340285809Sscottl  int i;
6341285809Sscottl  ag_card_info_t *thisCardInst = &agCardInfoList[ thisCard ];
6342285809Sscottl  struct ccb_setasync csa;
6343285809Sscottl  struct agtiapi_softc *pCard;
6344285809Sscottl  pCard = device_get_softc( dev );
6345285809Sscottl  ag_card_info_t *pCardInfo = pCard->pCardInfo;
6346285809Sscottl  ag_resource_info_t *pRscInfo = &thisCardInst->tiRscInfo;
6347285809Sscottl
6348285809Sscottl  AG_GLOBAL_ARG(flags);
6349285809Sscottl
6350285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: start\n" );
6351285809Sscottl
6352285809Sscottl  if (thisCardInst != pCardInfo)
6353285809Sscottl  {
6354285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: Wrong ag_card_info_t thisCardInst %p "
6355285809Sscottl                    "pCardInfo %p\n",
6356285809Sscottl                    thisCardInst,
6357285809Sscottl                    pCardInfo );
6358285809Sscottl    panic( "agtiapi_ReleaseHBA: Wrong ag_card_info_t thisCardInst %p pCardInfo "
6359285809Sscottl           "%p\n",
6360285809Sscottl           thisCardInst,
6361285809Sscottl           pCardInfo );
6362285809Sscottl    return( EIO );
6363285809Sscottl  }
6364285809Sscottl
6365285809Sscottl
6366285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA card %p\n", pCard );
6367285809Sscottl  pCard->flags |= AGTIAPI_SHUT_DOWN;
6368285809Sscottl
6369285809Sscottl
6370285809Sscottl  // remove timer
6371285809Sscottl  if (pCard->flags & AGTIAPI_TIMER_ON)
6372285809Sscottl  {
6373285809Sscottl    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
6374285809Sscottl    callout_drain( &pCard->OS_timer );
6375285809Sscottl    callout_drain( &pCard->devRmTimer );
6376285809Sscottl    callout_drain(&pCard->IO_timer);
6377285809Sscottl    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
6378285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: timer released\n" );
6379285809Sscottl  }
6380285809Sscottl
6381285809Sscottl#ifdef HIALEAH_ENCRYPTION
6382285809Sscottl//Release encryption table memory - Fix it
6383285809Sscottl   //if(pCard->encrypt && (pCard->flags & AGTIAPI_INSTALLED))
6384285809Sscottl	//agtiapi_CleanupEncryption(pCard);
6385285809Sscottl#endif
6386285809Sscottl
6387285809Sscottl  /*
6388285809Sscottl   * Shutdown the channel so that chip gets frozen
6389285809Sscottl   * and it does not do any more pci-bus accesses.
6390285809Sscottl   */
6391285809Sscottl  if (pCard->flags & AGTIAPI_SYS_INTR_ON)
6392285809Sscottl  {
6393285809Sscottl    tiCOMSystemInterruptsActive( &pCard->tiRoot, FALSE );
6394285809Sscottl    pCard->flags &= ~AGTIAPI_SYS_INTR_ON;
6395285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: card interrupt off\n" );
6396285809Sscottl  }
6397285809Sscottl  if (pCard->flags & AGTIAPI_INSTALLED)
6398285809Sscottl  {
6399285809Sscottl    tiCOMShutDown( &pCard->tiRoot );
6400285809Sscottl    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: low layers shutdown\n" );
6401285809Sscottl  }
6402285809Sscottl
6403285809Sscottl  /*
6404285809Sscottl   * first release IRQ, so that we do not get any more interrupts
6405285809Sscottl   * from this host
6406285809Sscottl   */
6407285809Sscottl  if (pCard->flags & AGTIAPI_IRQ_REQUESTED)
6408285809Sscottl  {
6409285809Sscottl    if (!agtiapi_intx_mode)
6410285809Sscottl    {
6411285809Sscottl      int i;
6412285809Sscottl      for (i = 0; i< MAX_MSIX_NUM_VECTOR; i++)
6413285809Sscottl      {
6414285809Sscottl        if (pCard->irq[i] != agNULL && pCard->rscID[i] != 0)
6415285809Sscottl        {
6416285809Sscottl          bus_teardown_intr(dev, pCard->irq[i], pCard->intrcookie[i]);
6417285809Sscottl          bus_release_resource( dev,
6418285809Sscottl                                SYS_RES_IRQ,
6419285809Sscottl                                pCard->rscID[i],
6420285809Sscottl                                pCard->irq[i] );
6421285809Sscottl        }
6422285809Sscottl      }
6423285809Sscottl      pci_release_msi(dev);
6424285809Sscottl    }
6425285809Sscottl    pCard->flags &= ~AGTIAPI_IRQ_REQUESTED;
6426285809Sscottl
6427285809Sscottl
6428285809Sscottl
6429285809Sscottl#ifdef AGTIAPI_DPC
6430285809Sscottl    for (i = 0; i < MAX_MSIX_NUM_DPC; i++)
6431285809Sscottl      tasklet_kill(&pCard->tasklet_dpc[i]);
6432285809Sscottl#endif
6433285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: IRQ released\n");
6434285809Sscottl  }
6435285809Sscottl
6436285809Sscottl  // release memory vs. alloc in agtiapi_alloc_ostimem; used in ostiAllocMemory
6437285809Sscottl  if( pCard->osti_busaddr != 0 ) {
6438285809Sscottl    bus_dmamap_unload( pCard->osti_dmat, pCard->osti_mapp );
6439285809Sscottl  }
6440285809Sscottl  if( pCard->osti_mem != NULL )  {
6441285809Sscottl    bus_dmamem_free( pCard->osti_dmat, pCard->osti_mem, pCard->osti_mapp );
6442285809Sscottl  }
6443285809Sscottl  if( pCard->osti_dmat != NULL ) {
6444285809Sscottl    bus_dma_tag_destroy( pCard->osti_dmat );
6445285809Sscottl  }
6446285809Sscottl
6447285809Sscottl  /* unmap the mapped PCI memory */
6448285809Sscottl  /* calls bus_release_resource( ,SYS_RES_MEMORY, ..) */
6449285809Sscottl  agtiapi_ReleasePCIMem(thisCardInst);
6450285809Sscottl
6451285809Sscottl  /* release all ccbs */
6452285809Sscottl  if (pCard->ccbTotal)
6453285809Sscottl  {
6454285809Sscottl    //calls bus_dmamap_destroy() for all pccbs
6455285809Sscottl    agtiapi_ReleaseCCBs(pCard);
6456285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: CCB released\n");
6457285809Sscottl  }
6458285809Sscottl
6459285809Sscottl#ifdef HIALEAH_ENCRYPTION
6460285809Sscottl/*release encryption resources - Fix it*/
6461285809Sscottl  if(pCard->encrypt)
6462285809Sscottl  {
6463285809Sscottl    /*Check that all IO's are completed */
6464285809Sscottl    if(atomic_read (&outstanding_encrypted_io_count) > 0)
6465285809Sscottl    {
6466285809Sscottl       printf("%s: WARNING: %d outstanding encrypted IOs !\n", __FUNCTION__, atomic_read(&outstanding_encrypted_io_count));
6467285809Sscottl    }
6468285809Sscottl    //agtiapi_CleanupEncryptionPools(pCard);
6469285809Sscottl  }
6470285809Sscottl#endif
6471285809Sscottl
6472285809Sscottl
6473285809Sscottl  /* release device list */
6474285809Sscottl  if( pCard->pDevList ) {
6475285809Sscottl    free((caddr_t)pCard->pDevList, M_PMC_MDVT);
6476285809Sscottl    pCard->pDevList = NULL;
6477285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: device list released\n");
6478285809Sscottl  }
6479285809Sscottl#ifdef LINUX_PERBI_SUPPORT // ## review use of PERBI
6480285809Sscottl  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: WWN list %p \n", pCard->pWWNList );
6481285809Sscottl  if( pCard->pWWNList ) {
6482285809Sscottl    free( (caddr_t)pCard->pWWNList, M_PMC_MTGT );
6483285809Sscottl    pCard->pWWNList = NULL;
6484285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: WWN list released\n");
6485285809Sscottl  }
6486285809Sscottl  if( pCard->pSLRList ) {
6487285809Sscottl    free( (caddr_t)pCard->pSLRList, M_PMC_MSLR );
6488285809Sscottl    pCard->pSLRList = NULL;
6489285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: SAS Local Remote list released\n");
6490285809Sscottl  }
6491285809Sscottl
6492285809Sscottl#endif
6493285809Sscottl  if (pCard->pPortalData)
6494285809Sscottl  {
6495285809Sscottl    free((caddr_t)pCard->pPortalData, M_PMC_MPRT);
6496285809Sscottl    pCard->pPortalData = NULL;
6497285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: PortalData released\n");
6498285809Sscottl  }
6499285809Sscottl  //calls contigfree() or free()
6500285809Sscottl  agtiapi_MemFree(pCardInfo);
6501285809Sscottl  AGTIAPI_PRINTK("agtiapi_ReleaseHBA: low level resource released\n");
6502285809Sscottl
6503285809Sscottl#ifdef HOTPLUG_SUPPORT
6504285809Sscottl  if (pCard->flags & AGTIAPI_PORT_INITIALIZED)
6505285809Sscottl  {
6506285809Sscottl    //    agtiapi_FreeDevWorkList(pCard);
6507285809Sscottl    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: (HP dev) work resources released\n");
6508285809Sscottl  }
6509285809Sscottl#endif
6510285809Sscottl
6511285809Sscottl  /*
6512285809Sscottl   * TBD, scsi_unregister may release wrong host data structure
6513285809Sscottl   * which cause NULL pointer shows up.
6514285809Sscottl   */
6515285809Sscottl  if (pCard->flags & AGTIAPI_SCSI_REGISTERED)
6516285809Sscottl  {
6517285809Sscottl    pCard->flags &= ~AGTIAPI_SCSI_REGISTERED;
6518285809Sscottl
6519285809Sscottl
6520285809Sscottl#ifdef AGTIAPI_LOCAL_LOCK
6521285809Sscottl    if (pCard->STLock)
6522285809Sscottl    {
6523285809Sscottl      //destroy mtx
6524285809Sscottl      int maxLocks;
6525285809Sscottl      maxLocks = pRscInfo->tiLoLevelResource.loLevelOption.numOfQueuesPerPort;
6526285809Sscottl
6527285809Sscottl      for( i = 0; i < maxLocks; i++ )
6528285809Sscottl      {
6529285809Sscottl        mtx_destroy(&pCard->STLock[i]);
6530285809Sscottl      }
6531285809Sscottl      free(pCard->STLock, M_PMC_MSTL);
6532285809Sscottl      pCard->STLock = NULL;
6533285809Sscottl    }
6534285809Sscottl#endif
6535285809Sscottl
6536285809Sscottl  }
6537285809Sscottl  ag_card_good--;
6538285809Sscottl
6539285809Sscottl  /* reset agtiapi_1st_time if this is the only card */
6540285809Sscottl  if (!ag_card_good && !agtiapi_1st_time)
6541285809Sscottl  {
6542285809Sscottl    agtiapi_1st_time = 1;
6543285809Sscottl  }
6544285809Sscottl
6545285809Sscottl  /* for tiSgl_t memeory */
6546285809Sscottl  if (pCard->tisgl_busaddr != 0)
6547285809Sscottl  {
6548285809Sscottl    bus_dmamap_unload(pCard->tisgl_dmat, pCard->tisgl_map);
6549285809Sscottl  }
6550285809Sscottl  if (pCard->tisgl_mem != NULL)
6551285809Sscottl  {
6552285809Sscottl    bus_dmamem_free(pCard->tisgl_dmat, pCard->tisgl_mem, pCard->tisgl_map);
6553285809Sscottl  }
6554285809Sscottl  if (pCard->tisgl_dmat != NULL)
6555285809Sscottl  {
6556285809Sscottl    bus_dma_tag_destroy(pCard->tisgl_dmat);
6557285809Sscottl  }
6558285809Sscottl
6559285809Sscottl  if (pCard->buffer_dmat != agNULL)
6560285809Sscottl  {
6561285809Sscottl    bus_dma_tag_destroy(pCard->buffer_dmat);
6562285809Sscottl  }
6563285809Sscottl
6564285809Sscottl  if (pCard->sim != NULL)
6565285809Sscottl  {
6566285809Sscottl    mtx_lock(&thisCardInst->pmIOLock);
6567285809Sscottl      xpt_setup_ccb(&csa.ccb_h, pCard->path, 5);
6568285809Sscottl      csa.ccb_h.func_code = XPT_SASYNC_CB;
6569285809Sscottl      csa.event_enable = 0;
6570285809Sscottl      csa.callback = agtiapi_async;
6571285809Sscottl      csa.callback_arg = pCard;
6572285809Sscottl      xpt_action((union ccb *)&csa);
6573285809Sscottl      xpt_free_path(pCard->path);
6574285809Sscottl //   if (pCard->ccbTotal == 0)
6575285809Sscottl    if (pCard->ccbTotal <= thisCard)
6576285809Sscottl    {
6577285809Sscottl      /*
6578285809Sscottl        no link up so that simq has not been released.
6579285809Sscottl        In order to remove cam, we call this.
6580285809Sscottl      */
6581285809Sscottl      xpt_release_simq(pCard->sim, 1);
6582285809Sscottl    }
6583285809Sscottl    xpt_bus_deregister(cam_sim_path(pCard->sim));
6584285809Sscottl    cam_sim_free(pCard->sim, FALSE);
6585285809Sscottl    mtx_unlock(&thisCardInst->pmIOLock);
6586285809Sscottl  }
6587285809Sscottl  if (pCard->devq != NULL)
6588285809Sscottl  {
6589285809Sscottl    cam_simq_free(pCard->devq);
6590285809Sscottl  }
6591285809Sscottl
6592285809Sscottl  //destroy mtx
6593285809Sscottl  mtx_destroy( &thisCardInst->pmIOLock );
6594285809Sscottl  mtx_destroy( &pCard->sendLock );
6595285809Sscottl  mtx_destroy( &pCard->doneLock );
6596285809Sscottl  mtx_destroy( &pCard->sendSMPLock );
6597285809Sscottl  mtx_destroy( &pCard->doneSMPLock );
6598285809Sscottl  mtx_destroy( &pCard->ccbLock );
6599285809Sscottl  mtx_destroy( &pCard->devListLock );
6600285809Sscottl  mtx_destroy( &pCard->OS_timer_lock );
6601285809Sscottl  mtx_destroy( &pCard->devRmTimerLock );
6602285809Sscottl  mtx_destroy( &pCard->memLock );
6603285809Sscottl  mtx_destroy( &pCard->freezeLock );
6604285809Sscottl
6605285809Sscottl  destroy_dev( pCard->my_cdev );
6606285809Sscottl  memset((void *)pCardInfo, 0, sizeof(ag_card_info_t));
6607285809Sscottl  return 0;
6608285809Sscottl}
6609285809Sscottl
6610285809Sscottl
6611285809Sscottl// Called during system shutdown after sync
6612285809Sscottlstatic int agtiapi_shutdown( device_t dev )
6613285809Sscottl{
6614285809Sscottl  AGTIAPI_PRINTK( "agtiapi_shutdown\n" );
6615285809Sscottl  return( 0 );
6616285809Sscottl}
6617285809Sscottl
6618285809Sscottlstatic int agtiapi_suspend( device_t dev )  // Device suspend routine.
6619285809Sscottl{
6620285809Sscottl  AGTIAPI_PRINTK( "agtiapi_suspend\n" );
6621285809Sscottl  return( 0 );
6622285809Sscottl}
6623285809Sscottl
6624285809Sscottlstatic int agtiapi_resume( device_t dev ) // Device resume routine.
6625285809Sscottl{
6626285809Sscottl  AGTIAPI_PRINTK( "agtiapi_resume\n" );
6627285809Sscottl  return( 0 );
6628285809Sscottl}
6629285809Sscottl
6630285809Sscottlstatic device_method_t agtiapi_methods[] = {   // Device interface
6631285809Sscottl  DEVMETHOD( device_probe,    agtiapi_probe      ),
6632285809Sscottl  DEVMETHOD( device_attach,   agtiapi_attach     ),
6633285809Sscottl  DEVMETHOD( device_detach,   agtiapi_ReleaseHBA ),
6634285809Sscottl  DEVMETHOD( device_shutdown, agtiapi_shutdown   ),
6635285809Sscottl  DEVMETHOD( device_suspend,  agtiapi_suspend    ),
6636285809Sscottl  DEVMETHOD( device_resume,   agtiapi_resume     ),
6637285809Sscottl  { 0, 0 }
6638285809Sscottl};
6639285809Sscottl
6640285809Sscottlstatic devclass_t pmspcv_devclass;
6641285809Sscottl
6642285809Sscottlstatic driver_t pmspcv_driver = {
6643285809Sscottl  "pmspcv",
6644285809Sscottl  agtiapi_methods,
6645285809Sscottl  sizeof( struct agtiapi_softc )
6646285809Sscottl};
6647285809Sscottl
6648285809SscottlDRIVER_MODULE( pmspcv, pci, pmspcv_driver, pmspcv_devclass, 0, 0 );
6649285809SscottlMODULE_DEPEND( pmspcv, cam, 1, 1, 1 );
6650285809SscottlMODULE_DEPEND( pmspcv, pci, 1, 1, 1 );
6651285809Sscottl
6652285809Sscottl#include <dev/pms/freebsd/driver/common/lxosapi.c>
6653285809Sscottl#include <dev/pms/freebsd/driver/ini/src/osapi.c>
6654285809Sscottl#include <dev/pms/freebsd/driver/common/lxutil.c>
6655285809Sscottl#include <dev/pms/freebsd/driver/common/lxencrypt.c>
6656285809Sscottl
6657285809Sscottl
6658