1/*******************************************************************************
2**
3*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
4 *
5*Redistribution and use in source and binary forms, with or without modification, are permitted provided
6*that the following conditions are met:
7*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8*2. Redistributions in binary form must reproduce the above copyright notice,
9*this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10*
11*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
12*
13*INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14*ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
15*SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16*OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
17*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
18*THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
19**
20*******************************************************************************/
21
22#include <sys/cdefs.h>
23__FBSDID("$FreeBSD$");
24#include <dev/pms/config.h>
25
26#define MAJOR_REVISION	    1
27#define MINOR_REVISION	    3
28#define BUILD_REVISION	    10800
29
30#include <sys/param.h>      // defines used in kernel.h
31#include <sys/ioccom.h>
32#include <sys/module.h>
33#include <sys/systm.h>
34#include <sys/errno.h>
35#include <sys/kernel.h>     // types used in module initialization
36#include <sys/conf.h>       // cdevsw struct
37#include <sys/uio.h>        // uio struct
38#include <sys/types.h>
39#include <sys/malloc.h>
40#include <sys/bus.h>        // structs, prototypes for pci bus stuff
41#include <machine/bus.h>
42#include <sys/rman.h>
43#include <machine/resource.h>
44#include <vm/vm.h>          // 1. for vtophys
45#include <vm/pmap.h>        // 2. for vtophys
46#include <dev/pci/pcivar.h> // For pci_get macros
47#include <dev/pci/pcireg.h>
48#include <sys/endian.h>
49#include <sys/lock.h>
50#include <sys/mutex.h>
51#include <sys/sema.h>
52#include <sys/queue.h>
53#include <sys/taskqueue.h>
54#include <machine/atomic.h>
55#include <sys/libkern.h>
56#include <cam/cam.h>
57#include <cam/cam_ccb.h>
58#include <cam/cam_debug.h>
59#include <cam/cam_periph.h> //
60#include <cam/cam_sim.h>
61#include <cam/cam_xpt_sim.h>
62#include <cam/scsi/scsi_all.h>
63#include <cam/scsi/scsi_message.h>
64#include <sys/systm.h>
65#include <sys/types.h>
66#include <dev/pms/RefTisa/tisa/api/tiapi.h>
67#include <dev/pms/freebsd/driver/ini/src/agtiapi.h>
68#include <dev/pms/freebsd/driver/ini/src/agtiproto.h>
69#include <dev/pms/RefTisa/tisa/api/ostiapi.h>
70#include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
71#include <dev/pms/freebsd/driver/common/lxencrypt.h>
72
73MALLOC_DEFINE( M_PMC_MCCB, "CCB List", "CCB List for PMCS driver" );
74
75MALLOC_DEFINE( M_PMC_MSTL, "STLock malloc",
76               "allocated in agtiapi_attach as memory for lock use" );
77MALLOC_DEFINE( M_PMC_MDVT, "ag_device_t malloc",
78               "allocated in agtiapi_attach as mem for ag_device_t pDevList" );
79MALLOC_DEFINE( M_PMC_MPRT, "ag_portal_data_t malloc",
80               "allocated in agtiapi_attach as mem for *pPortalData" );
81MALLOC_DEFINE( M_PMC_MDEV, "tiDeviceHandle_t * malloc",
82               "allocated in agtiapi_GetDevHandle as local mem for **agDev" );
83MALLOC_DEFINE( M_PMC_MFLG, "lDevFlags * malloc",
84               "allocated in agtiapi_GetDevHandle as local mem for * flags" );
85#ifdef LINUX_PERBI_SUPPORT
86MALLOC_DEFINE( M_PMC_MSLR, "ag_slr_map_t malloc",
87               "mem allocated in agtiapi_attach for pSLRList" );
88MALLOC_DEFINE( M_PMC_MTGT, "ag_tgt_map_t malloc",
89               "mem allocated in agtiapi_attach for pWWNList" );
90#endif
91MALLOC_DEFINE(TEMP,"tempbuff","buffer for payload");
92MALLOC_DEFINE(TEMP2, "tempbuff", "buffer for agtiapi_getdevlist");
93STATIC U32  agtiapi_intx_mode    = 0;
94STATIC U08  ag_Perbi             = 0;
95STATIC U32  agtiapi_polling_mode = 0;
96STATIC U32  ag_card_good         = 0;   // * total card initialized
97STATIC U32  ag_option_flag       = 0;   // * adjustable parameter flag
98STATIC U32  agtiapi_1st_time     = 1;
99STATIC U32  ag_timeout_secs      = 10;  //Made timeout equivalent to linux
100
101U32         gTiDebugLevel        = 1;
102S32	        ag_encryption_enable = 0;
103atomic_t    outstanding_encrypted_io_count;
104
105#define cache_line_size() CACHE_LINE_SIZE
106
107#define PMCoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
108
109#define CPU_TO_LE32(dst, src)                  \
110    dst.lower = htole32(LOW_32_BITS(src)); \
111    dst.upper = htole32(HIGH_32_BITS(src))
112
113#define CMND_TO_CHANNEL( ccb )     ( ccb->ccb_h.path_id )
114#define CMND_TO_TARGET(  ccb )     ( ccb->ccb_h.target_id )
115#define CMND_TO_LUN(     ccb )     ( ccb->ccb_h.target_lun )
116
117STATIC U08 agtiapi_AddrModes[AGTIAPI_MAX_CHANNEL_NUM + 1] =
118      { AGTIAPI_PERIPHERAL };
119
120#ifdef LINUX_PERBI_SUPPORT
121// Holding area for target-WWN mapping assignments on the boot line
122static ag_mapping_t *agMappingList = NULL;  // modified by agtiapi_Setup()
123#endif
124
125// * For Debugging Purpose
126#ifdef AGTIAPI_DEBUG
127#define AGTIAPI_WWN(name, len)   wwnprintk(name, len)
128#else
129#define AGTIAPI_WWN(name, len)
130#endif
131
132
133#define AGTIAPI_WWNPRINTK(name, len, format, a...)     \
134          AGTIAPI_PRINTK(format "name ", a);           \
135          AGTIAPI_WWN((unsigned char*)name, len);
136
137#define AGTIAPI_ERR_WWNPRINTK(name, len, format, a...) \
138          printk(KERN_DEBUG format "name ", ## a);     \
139          wwnprintk((unsigned char*)name, len);
140#define AGTIAPI_CPY_DEV_INFO(root, dev, pDev)            \
141          tiINIGetDeviceInfo(root, dev, &pDev->devInfo); \
142          wwncpy(pDev);
143
144#ifdef AGTIAPI_LOCAL_LOCK
145
146#define AG_CARD_LOCAL_LOCK(lock)     ,(lock)
147#define AG_SPIN_LOCK_IRQ(lock, flags)
148#define AG_SPIN_UNLOCK_IRQ(lock, flags)
149#define AG_SPIN_LOCK(lock)
150#define AG_SPIN_UNLOCK(lock)
151#define AG_GLOBAL_ARG(arg)
152#define AG_PERF_SPINLOCK(lock)
153#define AG_PERF_SPINLOCK_IRQ(lock, flags)
154
155
156#define AG_LOCAL_LOCK(lock)     if (lock) \
157                                         mtx_lock(lock)
158#define AG_LOCAL_UNLOCK(lock)   if (lock) \
159                                         mtx_unlock(lock)
160#define AG_LOCAL_FLAGS(_flags)         unsigned long _flags = 0
161#endif
162
163
164#define AG_GET_DONE_PCCB(pccb, pmcsc)            \
165  {                                              \
166    AG_LOCAL_LOCK(&pmcsc->doneLock);             \
167    pccb = pmcsc->ccbDoneHead;                   \
168    if (pccb != NULL)                            \
169    {                                            \
170      pmcsc->ccbDoneHead = NULL;                 \
171      pmcsc->ccbDoneTail = NULL;                 \
172      AG_LOCAL_UNLOCK(&pmcsc->doneLock);         \
173      agtiapi_Done(pmcsc, pccb);                 \
174    }                                            \
175    else                                         \
176      AG_LOCAL_UNLOCK(&pmcsc->doneLock);         \
177  }
178
179#define AG_GET_DONE_SMP_PCCB(pccb, pmcsc)	\
180  {                                              \
181    AG_LOCAL_LOCK(&pmcsc->doneSMPLock);          \
182    pccb = pmcsc->smpDoneHead;                   \
183    if (pccb != NULL)                            \
184    {                                            \
185      pmcsc->smpDoneHead = NULL;                 \
186      pmcsc->smpDoneTail = NULL;                 \
187      AG_LOCAL_UNLOCK(&pmcsc->doneSMPLock);      \
188      agtiapi_SMPDone(pmcsc, pccb);              \
189    }                                            \
190    else                                         \
191      AG_LOCAL_UNLOCK(&pmcsc->doneSMPLock);      \
192  }
193
194#ifdef AGTIAPI_DUMP_IO_DEBUG
195#define AG_IO_DUMPCCB(pccb)    agtiapi_DumpCCB(pccb)
196#else
197#define AG_IO_DUMPCCB(pccb)
198#endif
199
200#define SCHED_DELAY_JIFFIES 4 /* in seconds */
201
202#ifdef HOTPLUG_SUPPORT
203#define AG_HOTPLUG_LOCK_INIT(lock)   mxt_init(lock)
204#define AG_LIST_LOCK(lock)           mtx_lock(lock)
205#define AG_LIST_UNLOCK(lock)         mtx_unlock(lock)
206#else
207#define AG_HOTPLUG_LOCK_INIT(lock)
208#define AG_LIST_LOCK(lock)
209#define AG_LIST_UNLOCK(lock)
210#endif
211
212STATIC void agtiapi_CheckIOTimeout(void *data);
213
214
215
216static ag_card_info_t agCardInfoList[ AGTIAPI_MAX_CARDS ]; // card info list
217static void agtiapi_cam_action( struct cam_sim *, union ccb * );
218static void agtiapi_cam_poll( struct cam_sim * );
219
220// Function prototypes
221static d_open_t  agtiapi_open;
222static d_close_t agtiapi_close;
223static d_read_t  agtiapi_read;
224static d_write_t agtiapi_write;
225static d_ioctl_t agtiapi_CharIoctl;
226static void agtiapi_async(void *callback_arg, u_int32_t code,
227              struct cam_path *path, void *arg);
228void agtiapi_adjust_queue_depth(struct cam_path *path, bit32 QueueDepth);
229
230// Character device entry points
231static struct cdevsw agtiapi_cdevsw = {
232  .d_version = D_VERSION,
233  .d_open    = agtiapi_open,
234  .d_close   = agtiapi_close,
235  .d_read    = agtiapi_read,
236  .d_write   = agtiapi_write,
237  .d_ioctl   = agtiapi_CharIoctl,
238  .d_name    = "pmspcv",
239};
240
241U32 maxTargets = 0;
242U32 ag_portal_count = 0;
243
244// In the cdevsw routines, we find our softc by using the si_drv1 member
245// of struct cdev. We set this variable to point to our softc in our
246// attach routine when we create the /dev entry.
247
248int agtiapi_open( struct cdev *dev, int oflags, int devtype, struct thread *td )
249{
250  struct agtiapi_softc *sc;
251  /* Look up our softc. */
252  sc = dev->si_drv1;
253  AGTIAPI_PRINTK("agtiapi_open\n");
254  AGTIAPI_PRINTK("Opened successfully. sc->my_dev %p\n", sc->my_dev);
255  return( 0 );
256}
257
258int agtiapi_close( struct cdev *dev, int fflag, int devtype, struct thread *td )
259{
260  struct agtiapi_softc *sc;
261  // Look up our softc
262  sc = dev->si_drv1;
263  AGTIAPI_PRINTK("agtiapi_close\n");
264  AGTIAPI_PRINTK("Closed. sc->my_dev %p\n", sc->my_dev);
265  return( 0 );
266}
267
268int agtiapi_read( struct cdev *dev, struct uio *uio, int ioflag )
269{
270  struct agtiapi_softc *sc;
271  // Look up our softc
272  sc = dev->si_drv1;
273  AGTIAPI_PRINTK( "agtiapi_read\n" );
274  AGTIAPI_PRINTK( "Asked to read %lu bytes. sc->my_dev %p\n",
275                  uio->uio_resid, sc->my_dev );
276  return( 0 );
277}
278
279int agtiapi_write( struct cdev *dev, struct uio *uio, int ioflag )
280{
281  struct agtiapi_softc *sc;
282  // Look up our softc
283  sc = dev->si_drv1;
284  AGTIAPI_PRINTK( "agtiapi_write\n" );
285  AGTIAPI_PRINTK( "Asked to write %lu bytes. sc->my_dev %p\n",
286                  uio->uio_resid, sc->my_dev );
287  return( 0 );
288}
289
290int agtiapi_getdevlist( struct agtiapi_softc *pCard,
291                        tiIOCTLPayload_t *agIOCTLPayload )
292{
293  tdDeviceListPayload_t *pIoctlPayload =
294    (tdDeviceListPayload_t *) agIOCTLPayload->FunctionSpecificArea;
295  tdDeviceInfoIOCTL_t *pDeviceInfo = NULL;
296  bit8		   *pDeviceInfoOrg;
297  tdsaDeviceData_t *pDeviceData = NULL;
298  tiDeviceHandle_t **devList = NULL;
299  tiDeviceHandle_t **devHandleArray = NULL;
300  tiDeviceHandle_t *pDeviceHandle = NULL;
301  bit32 x, memNeeded1;
302  bit32 count, total;
303  bit32 MaxDeviceCount;
304  bit32 ret_val=IOCTL_CALL_INVALID_CODE;
305  ag_portal_data_t *pPortalData;
306  bit8 *pDeviceHandleList = NULL;
307  AGTIAPI_PRINTK( "agtiapi_getdevlist: Enter\n" );
308
309  pDeviceInfoOrg = pIoctlPayload -> pDeviceInfo;
310  MaxDeviceCount = pCard->devDiscover;
311  if (MaxDeviceCount > pIoctlPayload->deviceLength )
312  {
313    AGTIAPI_PRINTK( "agtiapi_getdevlist: MaxDeviceCount: %d > Requested device length: %d\n", MaxDeviceCount, pIoctlPayload->deviceLength );
314    MaxDeviceCount = pIoctlPayload->deviceLength;
315    ret_val = IOCTL_CALL_FAIL;
316  }
317  AGTIAPI_PRINTK( "agtiapi_getdevlist: MaxDeviceCount: %d > Requested device length: %d\n", MaxDeviceCount, pIoctlPayload->deviceLength );
318  memNeeded1 = AG_ALIGNSIZE( MaxDeviceCount * sizeof(tiDeviceHandle_t *),
319                             sizeof(void *) );
320  AGTIAPI_PRINTK("agtiapi_getdevlist: portCount %d\n", pCard->portCount);
321  devList = malloc(memNeeded1, TEMP2, M_WAITOK);
322  if (devList == NULL)
323  {
324    AGTIAPI_PRINTK("agtiapi_getdevlist: failed to allocate memory\n");
325    ret_val = IOCTL_CALL_FAIL;
326    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
327    return ret_val;
328  }
329  osti_memset(devList, 0,  memNeeded1);
330  pPortalData = &pCard->pPortalData[0];
331  pDeviceHandleList = (bit8*)devList;
332  for (total = x = 0; x < pCard->portCount; x++, pPortalData++)
333  {
334    count = tiINIGetDeviceHandlesForWinIOCTL(&pCard->tiRoot,
335                    &pPortalData->portalInfo.tiPortalContext,
336		    ( tiDeviceHandle_t **)pDeviceHandleList ,MaxDeviceCount );
337    if (count == DISCOVERY_IN_PROGRESS)
338    {
339      AGTIAPI_PRINTK( "agtiapi_getdevlist: DISCOVERY_IN_PROGRESS on "
340                      "portal %d\n", x );
341      free(devList, TEMP2);
342      ret_val = IOCTL_CALL_FAIL;
343      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
344      return ret_val;
345    }
346    total += count;
347    pDeviceHandleList+= count*sizeof(tiDeviceHandle_t *);
348    MaxDeviceCount-= count;
349  }
350  if (total > pIoctlPayload->deviceLength)
351  {
352    total = pIoctlPayload->deviceLength;
353  }
354  // dump device information from device handle list
355  count = 0;
356
357  devHandleArray = devList;
358  for (x = 0; x < pCard->devDiscover; x++)
359  {
360     pDeviceHandle = (tiDeviceHandle_t*)devHandleArray[x];
361    if (devList[x] != agNULL)
362    {
363      pDeviceData = devList [x]->tdData;
364
365	pDeviceInfo = (tdDeviceInfoIOCTL_t*)(pDeviceInfoOrg + sizeof(tdDeviceInfoIOCTL_t) * count);
366      if (pDeviceData != agNULL && pDeviceInfo != agNULL)
367      {
368        osti_memcpy( &pDeviceInfo->sasAddressHi,
369                     pDeviceData->agDeviceInfo.sasAddressHi,
370                     sizeof(bit32) );
371        osti_memcpy( &pDeviceInfo->sasAddressLo,
372                     pDeviceData->agDeviceInfo.sasAddressLo,
373                     sizeof(bit32) );
374#if 0
375        pDeviceInfo->sasAddressHi =
376          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressHi );
377        pDeviceInfo->sasAddressLo =
378          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressLo );
379#endif
380
381        pDeviceInfo->deviceType =
382          ( pDeviceData->agDeviceInfo.devType_S_Rate & 0x30 ) >> 4;
383        pDeviceInfo->linkRate   =
384          pDeviceData->agDeviceInfo.devType_S_Rate & 0x0F;
385        pDeviceInfo->phyId      =  pDeviceData->phyID;
386 	pDeviceInfo->ishost	=  pDeviceData->target_ssp_stp_smp;
387	pDeviceInfo->DeviceHandle= (unsigned long)pDeviceHandle;
388	if(pDeviceInfo->deviceType == 0x02)
389	{
390	   bit8 *sasAddressHi;
391	   bit8 *sasAddressLo;
392	   tiIniGetDirectSataSasAddr(&pCard->tiRoot, pDeviceData->phyID, &sasAddressHi, &sasAddressLo);
393	   pDeviceInfo->sasAddressHi = DMA_BEBIT32_TO_BIT32(*(bit32*)sasAddressHi);
394	   pDeviceInfo->sasAddressLo = DMA_BEBIT32_TO_BIT32(*(bit32*)sasAddressLo) + pDeviceData->phyID + 16;
395	}
396	else
397	{
398        pDeviceInfo->sasAddressHi =
399          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressHi );
400        pDeviceInfo->sasAddressLo =
401          DMA_BEBIT32_TO_BIT32( pDeviceInfo->sasAddressLo );
402 	}
403
404        AGTIAPI_PRINTK( "agtiapi_getdevlist: devicetype %x\n",
405                        pDeviceInfo->deviceType );
406        AGTIAPI_PRINTK( "agtiapi_getdevlist: linkrate %x\n",
407                        pDeviceInfo->linkRate );
408        AGTIAPI_PRINTK( "agtiapi_getdevlist: phyID %x\n",
409                        pDeviceInfo->phyId );
410        AGTIAPI_PRINTK( "agtiapi_getdevlist: addresshi %x\n",
411                        pDeviceInfo->sasAddressHi );
412        AGTIAPI_PRINTK( "agtiapi_getdevlist: addresslo %x\n",
413                        pDeviceInfo->sasAddressHi );
414      }
415      else
416      {
417        AGTIAPI_PRINTK( "agtiapi_getdevlist: pDeviceData %p or pDeviceInfo "
418                        "%p is NULL %d\n", pDeviceData, pDeviceInfo, x );
419      }
420      count++;
421    }
422  }
423  pIoctlPayload->realDeviceCount = count;
424  AGTIAPI_PRINTK( "agtiapi_getdevlist: Exit RealDeviceCount = %d\n", count );
425  if (devList)
426  {
427    free(devList, TEMP2);
428  }
429  if(ret_val != IOCTL_CALL_FAIL)
430  {
431    ret_val = IOCTL_CALL_SUCCESS;
432  }
433  agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
434  return  ret_val;
435}
436
437/******************************************************************************
438agtiapi_getCardInfo()
439
440Purpose:
441  This function retrives the Card information
442Parameters:
443
444Return:
445  A number - error
446  0        - HBA has been detected
447Note:
448******************************************************************************/
449int agtiapi_getCardInfo ( struct agtiapi_softc *pCard,
450                          U32_64                size,
451                          void                 *buffer )
452{
453  CardInfo_t       *pCardInfo;
454
455  pCardInfo = (CardInfo_t *)buffer;
456
457  pCardInfo->deviceId = pci_get_device(pCard->my_dev);
458  pCardInfo->vendorId =pci_get_vendor(pCard->my_dev) ;
459  memcpy( pCardInfo->pciMemBaseSpc,
460          pCard->pCardInfo->pciMemBaseSpc,
461          ((sizeof(U32_64))*PCI_NUMBER_BARS) );
462  pCardInfo->deviceNum = pci_get_slot(pCard->my_dev);
463  pCardInfo->pciMemBase = pCard->pCardInfo->pciMemBase;
464  pCardInfo->pciIOAddrLow = pCard->pCardInfo->pciIOAddrLow;
465  pCardInfo->pciIOAddrUp = pCard->pCardInfo->pciIOAddrUp;
466  pCardInfo->busNum =pci_get_bus(pCard->my_dev);
467  return 0;
468}
469
470void agtiapi_adjust_queue_depth(struct cam_path *path, bit32 QueueDepth)
471{
472  struct ccb_relsim crs;
473  xpt_setup_ccb(&crs.ccb_h, path, 5);
474  crs.ccb_h.func_code = XPT_REL_SIMQ;
475  crs.ccb_h.flags = CAM_DEV_QFREEZE;
476  crs.release_flags = RELSIM_ADJUST_OPENINGS;
477  crs.openings = QueueDepth;
478  xpt_action((union ccb *)&crs);
479  if(crs.ccb_h.status != CAM_REQ_CMP) {
480                 printf("XPT_REL_SIMQ failed\n");
481  }
482}
483static void
484agtiapi_async(void *callback_arg, u_int32_t code,
485	       struct cam_path *path, void *arg)
486{
487	struct agtiapi_softc *pmsc;
488	U32        TID;
489	ag_device_t *targ;
490	pmsc = (struct agtiapi_softc*)callback_arg;
491	switch (code) {
492	case AC_FOUND_DEVICE:
493	{
494	    struct ccb_getdev *cgd;
495	    cgd = (struct ccb_getdev *)arg;
496	    if (cgd == NULL) {
497		break;
498	    }
499	    TID = cgd->ccb_h.target_id;
500	    if (TID >= 0 && TID < maxTargets){
501                if (pmsc != NULL){
502                    TID = INDEX(pmsc, TID);
503                    targ   = &pmsc->pDevList[TID];
504	            agtiapi_adjust_queue_depth(path, targ->qdepth);
505                }
506	    }
507	    break;
508        }
509	default:
510		break;
511	}
512}
513/******************************************************************************
514agtiapi_CharIoctl()
515
516Purpose:
517  This function handles the ioctl from application layer
518Parameters:
519
520Return:
521  A number - error
522  0        - HBA has been detected
523Note:
524******************************************************************************/
525static int agtiapi_CharIoctl( struct cdev   *dev,
526                              u_long         cmd,
527                              caddr_t        data,
528                              int            fflag,
529                              struct thread *td )
530{
531  struct sema           mx;
532  datatosend           *load; // structure defined in lxcommon.h
533  tiIOCTLPayload_t     *pIoctlPayload;
534  struct agtiapi_softc *pCard;
535  pCard=dev->si_drv1;
536  U32   status = 0;
537  U32   retValue;
538  int   err    = 0;
539  int   error  = 0;
540  tdDeviceListPayload_t *pDeviceList = NULL;
541  unsigned long flags;
542
543  switch (cmd)
544  {
545  case AGTIAPI_IOCTL:
546    load=(datatosend*)data;
547    pIoctlPayload = malloc(load->datasize,TEMP,M_WAITOK);
548    AGTIAPI_PRINTK( "agtiapi_CharIoctl: old load->datasize = %d\n", load->datasize );
549    //Copy payload to kernel buffer, on success it returns 0
550    err = copyin(load->data,pIoctlPayload,load->datasize);
551    if (err)
552    {
553      status = IOCTL_CALL_FAIL;
554      return status;
555    }
556    sema_init(&mx,0,"sem");
557    pCard->pIoctlSem  =&mx;
558    pCard->up_count = pCard->down_count = 0;
559    if ( pIoctlPayload->MajorFunction == IOCTL_MJ_GET_DEVICE_LIST )
560    {
561      retValue = agtiapi_getdevlist(pCard, pIoctlPayload);
562      if (retValue == 0)
563      {
564        pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
565        status = IOCTL_CALL_SUCCESS;
566      }
567      else
568      {
569        pIoctlPayload->Status = IOCTL_CALL_FAIL;
570        status = IOCTL_CALL_FAIL;
571      }
572      //update new device length
573      pDeviceList = (tdDeviceListPayload_t*)pIoctlPayload->FunctionSpecificArea;
574      load->datasize =load->datasize - sizeof(tdDeviceInfoIOCTL_t) * (pDeviceList->deviceLength - pDeviceList->realDeviceCount);
575      AGTIAPI_PRINTK( "agtiapi_CharIoctl: new load->datasize = %d\n", load->datasize );
576
577    }
578    else if (pIoctlPayload->MajorFunction == IOCTL_MN_GET_CARD_INFO)
579    {
580      retValue = agtiapi_getCardInfo( pCard,
581                                      pIoctlPayload->Length,
582                                      (pIoctlPayload->FunctionSpecificArea) );
583      if (retValue == 0)
584      {
585        pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
586        status = IOCTL_CALL_SUCCESS;
587      }
588      else
589      {
590        pIoctlPayload->Status = IOCTL_CALL_FAIL;
591        status = IOCTL_CALL_FAIL;
592      }
593    }
594    else if ( pIoctlPayload->MajorFunction == IOCTL_MJ_CHECK_DPMC_EVENT )
595    {
596      if ( pCard->flags & AGTIAPI_PORT_PANIC )
597      {
598        strcpy ( pIoctlPayload->FunctionSpecificArea, "DPMC LEAN\n" );
599      }
600      else
601      {
602        strcpy ( pIoctlPayload->FunctionSpecificArea, "do not dpmc lean\n" );
603      }
604      pIoctlPayload->Status = IOCTL_CALL_SUCCESS;
605      status = IOCTL_CALL_SUCCESS;
606    }
607    else if (pIoctlPayload->MajorFunction == IOCTL_MJ_CHECK_FATAL_ERROR )
608    {
609      AGTIAPI_PRINTK("agtiapi_CharIoctl: IOCTL_MJ_CHECK_FATAL_ERROR call received for card %d\n", pCard->cardNo);
610      //read port status to see if there is a fatal event
611      if(pCard->flags & AGTIAPI_PORT_PANIC)
612      {
613        printf("agtiapi_CharIoctl: Port Panic Status For Card %d is True\n",pCard->cardNo);
614        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERR_CHK_SEND_TRUE;
615      }
616      else
617      {
618        AGTIAPI_PRINTK("agtiapi_CharIoctl: Port Panic Status For Card %d is False\n",pCard->cardNo);
619        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERR_CHK_SEND_FALSE;
620      }
621      status = IOCTL_CALL_SUCCESS;
622    }
623    else if (pIoctlPayload->MajorFunction == IOCTL_MJ_FATAL_ERROR_DUMP_COMPLETE)
624    {
625      AGTIAPI_PRINTK("agtiapi_CharIoctl: IOCTL_MJ_FATAL_ERROR_DUMP_COMPLETE call received for card %d\n", pCard->cardNo);
626      //set flags bit status to be a soft reset
627      pCard->flags |= AGTIAPI_SOFT_RESET;
628      //trigger soft reset for the card
629      retValue = agtiapi_ResetCard (pCard, &flags);
630
631      if(retValue == AGTIAPI_SUCCESS)
632      {
633        //clear port panic status
634        pCard->flags &= ~AGTIAPI_PORT_PANIC;
635        pIoctlPayload->Status = IOCTL_MJ_FATAL_ERROR_SOFT_RESET_TRIG;
636        status = IOCTL_CALL_SUCCESS;
637      }
638      else
639      {
640        pIoctlPayload->Status = IOCTL_CALL_FAIL;
641        status = IOCTL_CALL_FAIL;
642      }
643    }
644    else
645    {
646      status = tiCOMMgntIOCTL( &pCard->tiRoot,
647                               pIoctlPayload,
648                               pCard,
649                               NULL,
650                               NULL );
651      if (status == IOCTL_CALL_PENDING)
652      {
653        ostiIOCTLWaitForSignal(&pCard->tiRoot,NULL, NULL, NULL);
654        status = IOCTL_CALL_SUCCESS;
655      }
656    }
657    pCard->pIoctlSem = NULL;
658    err = 0;
659
660    //copy kernel buffer to userland buffer
661    err=copyout(pIoctlPayload,load->data,load->datasize);
662    if (err)
663    {
664      status = IOCTL_CALL_FAIL;
665      return status;
666    }
667    free(pIoctlPayload,TEMP);
668    pIoctlPayload=NULL;
669    break;
670  default:
671    error = ENOTTY;
672    break;
673  }
674  return(status);
675}
676
677/******************************************************************************
678agtiapi_probe()
679
680Purpose:
681  This function initialize and registere all detected HBAs.
682  The first function being called in driver after agtiapi_probe()
683Parameters:
684  device_t dev (IN)  - device pointer
685Return:
686  A number - error
687  0        - HBA has been detected
688Note:
689******************************************************************************/
690static int agtiapi_probe( device_t dev )
691{
692  int retVal;
693  int thisCard;
694  ag_card_info_t *thisCardInst;
695
696  thisCard = device_get_unit( dev );
697  if ( thisCard >= AGTIAPI_MAX_CARDS )
698  {
699    device_printf( dev, "Too many PMC-Sierra cards detected ERROR!\n" );
700    return (ENXIO); // maybe change to different return value?
701  }
702  thisCardInst = &agCardInfoList[ thisCard ];
703  retVal = agtiapi_ProbeCard( dev, thisCardInst, thisCard );
704  if ( retVal )
705    return (ENXIO); // maybe change to different return value?
706  return( BUS_PROBE_DEFAULT );  // successful probe
707}
708
709
710/******************************************************************************
711agtiapi_attach()
712
713Purpose:
714  This function initialize and registere all detected HBAs.
715  The first function being called in driver after agtiapi_probe()
716Parameters:
717  device_t dev (IN)  - device pointer
718Return:
719  A number - error
720  0        - HBA has been detected
721Note:
722******************************************************************************/
723static int agtiapi_attach( device_t devx )
724{
725  // keeping get_unit call to once
726  int                   thisCard = device_get_unit( devx );
727  struct agtiapi_softc *pmsc;
728  ag_card_info_t       *thisCardInst = &agCardInfoList[ thisCard ];
729  ag_resource_info_t   *pRscInfo;
730  int                   idx;
731  int			        lenRecv;
732  char			        buffer [256], *pLastUsedChar;
733  union ccb *ccb;
734  int bus, tid, lun;
735  struct ccb_setasync csa;
736
737  AGTIAPI_PRINTK("agtiapi_attach: start dev %p thisCard %d\n", devx, thisCard);
738  // AGTIAPI_PRINTK( "agtiapi_attach: entry pointer values  A %p / %p\n",
739  //        thisCardInst->pPCIDev, thisCardInst );
740  AGTIAPI_PRINTK( "agtiapi_attach: deviceID: 0x%x\n", pci_get_devid( devx ) );
741
742  TUNABLE_INT_FETCH( "DPMC_TIMEOUT_SECS",  &ag_timeout_secs );
743  TUNABLE_INT_FETCH( "DPMC_TIDEBUG_LEVEL", &gTiDebugLevel   );
744  // printf( "agtiapi_attach: debugLevel %d, timeout %d\n",
745  //         gTiDebugLevel, ag_timeout_secs );
746  if ( ag_timeout_secs < 1 )
747  {
748    ag_timeout_secs = 1; // set minimum timeout value of 1 second
749  }
750  ag_timeout_secs = (ag_timeout_secs * 1000); // convert to millisecond notation
751
752  // Look up our softc and initialize its fields.
753  pmsc = device_get_softc( devx );
754  pmsc->my_dev = devx;
755
756  /* Get NumberOfPortals */
757  if ((ostiGetTransportParam(
758                             &pmsc->tiRoot,
759                             "Global",
760                             "CardDefault",
761                             agNULL,
762                             agNULL,
763                             agNULL,
764                             agNULL,
765                             "NumberOfPortals",
766                             buffer,
767                             255,
768                             &lenRecv
769                             ) == tiSuccess) && (lenRecv != 0))
770  {
771    if (osti_strncmp(buffer, "0x", 2) == 0)
772    {
773      ag_portal_count = osti_strtoul (buffer, &pLastUsedChar, 0);
774    }
775    else
776    {
777      ag_portal_count = osti_strtoul (buffer, &pLastUsedChar, 10);
778    }
779    if (ag_portal_count > AGTIAPI_MAX_PORTALS)
780      ag_portal_count = AGTIAPI_MAX_PORTALS;
781  }
782  else
783  {
784    ag_portal_count = AGTIAPI_MAX_PORTALS;
785  }
786  AGTIAPI_PRINTK( "agtiapi_attach: ag_portal_count=%d\n", ag_portal_count );
787  // initialize hostdata structure
788  pmsc->flags    |= AGTIAPI_INIT_TIME | AGTIAPI_SCSI_REGISTERED |
789      AGTIAPI_INITIATOR;
790  pmsc->cardNo    = thisCard;
791  pmsc->ccbTotal  = 0;
792  pmsc->portCount = ag_portal_count;
793  pmsc->pCardInfo = thisCardInst;
794  pmsc->tiRoot.osData = pmsc;
795  pmsc->pCardInfo->pCard  = (void *)pmsc;
796  pmsc->VidDid    = ( pci_get_vendor(devx) << 16 ) | pci_get_device( devx );
797  pmsc->SimQFrozen = agFALSE;
798  pmsc->devq_flag  = agFALSE;
799  pRscInfo = &thisCardInst->tiRscInfo;
800
801  osti_memset(buffer, 0, 256);
802  lenRecv = 0;
803
804  /* Get MaxTargets */
805  if ((ostiGetTransportParam(
806                             &pmsc->tiRoot,
807                             "Global",
808                             "InitiatorParms",
809                             agNULL,
810                             agNULL,
811                             agNULL,
812                             agNULL,
813                             "MaxTargets",
814                             buffer,
815                             sizeof(buffer),
816                             &lenRecv
817                             ) == tiSuccess) && (lenRecv != 0))
818  {
819    if (osti_strncmp(buffer, "0x", 2) == 0)
820    {
821      maxTargets = osti_strtoul (buffer, &pLastUsedChar, 0);
822      AGTIAPI_PRINTK( "agtiapi_attach:  maxTargets = osti_strtoul  0 \n" );
823    }
824    else
825    {
826      maxTargets = osti_strtoul (buffer, &pLastUsedChar, 10);
827      AGTIAPI_PRINTK( "agtiapi_attach:  maxTargets = osti_strtoul 10\n"   );
828    }
829  }
830  else
831
832  {
833    if(Is_ADP8H(pmsc))
834       maxTargets = AGTIAPI_MAX_DEVICE_8H;
835    else if(Is_ADP7H(pmsc))
836       maxTargets = AGTIAPI_MAX_DEVICE_7H;
837    else
838       maxTargets = AGTIAPI_MAX_DEVICE;
839  }
840
841  if (maxTargets > AGTIAPI_HW_LIMIT_DEVICE)
842  {
843    AGTIAPI_PRINTK( "agtiapi_attach: maxTargets: %d > AGTIAPI_HW_LIMIT_DEVICE: %d\n",  maxTargets, AGTIAPI_HW_LIMIT_DEVICE );
844    AGTIAPI_PRINTK( "agtiapi_attach: change maxTargets = AGTIAPI_HW_LIMIT_DEVICE\n" );
845    maxTargets = AGTIAPI_HW_LIMIT_DEVICE;
846  }
847  pmsc->devDiscover    = maxTargets ;
848
849 #ifdef HIALEAH_ENCRYPTION
850   ag_encryption_enable   =  1;
851   if(ag_encryption_enable && pci_get_device(pmsc->pCardInfo->pPCIDev) ==
852                                  PCI_DEVICE_ID_HIALEAH_HBA_SPCVE)
853   {
854	pmsc->encrypt = 1;
855	pRscInfo->tiLoLevelResource.loLevelOption.encryption = agTRUE;
856	printf("agtiapi_attach: Encryption Enabled\n" );
857   }
858#endif
859  // ## for now, skip calls to ostiGetTransportParam(...)
860  // ## for now, skip references to DIF & EDC
861
862  // Create a /dev entry for this device. The kernel will assign us
863  // a major number automatically. We use the unit number of this
864  // device as the minor number and name the character device
865  // "agtiapi<unit>".
866  pmsc->my_cdev = make_dev( &agtiapi_cdevsw, thisCard, UID_ROOT, GID_WHEEL,
867			    0600, "spcv%u", thisCard );
868  pmsc->my_cdev->si_drv1 = pmsc;
869
870  mtx_init( &thisCardInst->pmIOLock, "pmc SAS I/O lock",
871	    NULL, MTX_DEF|MTX_RECURSE );
872
873  struct cam_devq *devq;
874
875  /* set the maximum number of pending IOs */
876  devq = cam_simq_alloc( AGTIAPI_MAX_CAM_Q_DEPTH );
877  if (devq == NULL)
878  {
879    AGTIAPI_PRINTK("agtiapi_attach: cam_simq_alloc is NULL\n" );
880    return( EIO );
881  }
882
883  struct cam_sim *lsim;
884  lsim = cam_sim_alloc( agtiapi_cam_action,
885                        agtiapi_cam_poll,
886                        "pmspcbsd",
887                        pmsc,
888                        thisCard,
889                        &thisCardInst->pmIOLock,
890                        1,                       // queued per target
891                        AGTIAPI_MAX_CAM_Q_DEPTH, // max tag depth
892                        devq );
893  if ( lsim == NULL ) {
894    cam_simq_free( devq );
895    AGTIAPI_PRINTK("agtiapi_attach: cam_sim_alloc is NULL\n" );
896    return( EIO );
897  }
898
899  pmsc->dev_scan = agFALSE;
900  //one cam sim per scsi bus
901  mtx_lock( &thisCardInst->pmIOLock );
902  if ( xpt_bus_register( lsim, devx, 0 ) != CAM_SUCCESS )
903  { // bus 0
904    cam_sim_free( lsim, TRUE );
905    mtx_unlock( &thisCardInst->pmIOLock );
906    AGTIAPI_PRINTK("agtiapi_attach: xpt_bus_register fails\n" );
907    return( EIO );
908  }
909
910  pmsc->sim  = lsim;
911  bus = cam_sim_path(pmsc->sim);
912  tid = CAM_TARGET_WILDCARD;
913  lun = CAM_LUN_WILDCARD;
914  ccb = xpt_alloc_ccb_nowait();
915  if (ccb == agNULL)
916  {
917	mtx_unlock( &thisCardInst->pmIOLock );
918    cam_sim_free( lsim, TRUE );
919    cam_simq_free( devq );
920    return ( EIO );
921  }
922  if (xpt_create_path(&ccb->ccb_h.path, agNULL, bus, tid,
923		      CAM_LUN_WILDCARD) != CAM_REQ_CMP)
924  {
925	mtx_unlock( &thisCardInst->pmIOLock );
926	cam_sim_free( lsim, TRUE );
927    cam_simq_free( devq );
928    xpt_free_ccb(ccb);
929    return( EIO );
930  }
931  pmsc->path = ccb->ccb_h.path;
932  xpt_setup_ccb(&csa.ccb_h, pmsc->path, 5);
933  csa.ccb_h.func_code = XPT_SASYNC_CB;
934  csa.event_enable = AC_FOUND_DEVICE;
935  csa.callback = agtiapi_async;
936  csa.callback_arg = pmsc;
937  xpt_action((union ccb *)&csa);
938  if (csa.ccb_h.status != CAM_REQ_CMP) {
939	  AGTIAPI_PRINTK("agtiapi_attach: Unable to register AC_FOUND_DEVICE\n" );
940  }
941  lsim->devq = devq;
942  mtx_unlock( &thisCardInst->pmIOLock );
943
944
945
946
947  // get TD and lower layer memory requirements
948  tiCOMGetResource( &pmsc->tiRoot,
949                    &pRscInfo->tiLoLevelResource,
950                    &pRscInfo->tiInitiatorResource,
951                    NULL,
952                    &pRscInfo->tiSharedMem );
953
954  agtiapi_ScopeDMARes( thisCardInst );
955  AGTIAPI_PRINTK( "agtiapi_attach: size from the call agtiapi_ScopeDMARes"
956                  " 0x%x \n", pmsc->typhn );
957
958  // initialize card information and get resource ready
959  if( agtiapi_InitResource( thisCardInst ) == AGTIAPI_FAIL ) {
960    AGTIAPI_PRINTK( "agtiapi_attach: Card %d initialize resource ERROR\n",
961            thisCard );
962  }
963
964  // begin: allocate and initialize card portal info resource
965  ag_portal_data_t   *pPortalData;
966  if (pmsc->portCount == 0)
967  {
968    pmsc->pPortalData = NULL;
969  }
970  else
971  {
972    pmsc->pPortalData = (ag_portal_data_t *)
973                        malloc( sizeof(ag_portal_data_t) * pmsc->portCount,
974                                M_PMC_MPRT, M_ZERO | M_WAITOK );
975    if (pmsc->pPortalData == NULL)
976    {
977      AGTIAPI_PRINTK( "agtiapi_attach: Portal memory allocation ERROR\n" );
978    }
979  }
980
981  pPortalData = pmsc->pPortalData;
982  for( idx = 0; idx < pmsc->portCount; idx++ ) {
983    pPortalData->pCard = pmsc;
984    pPortalData->portalInfo.portID = idx;
985    pPortalData->portalInfo.tiPortalContext.osData = (void *)pPortalData;
986    pPortalData++;
987  }
988  // end: allocate and initialize card portal info resource
989
990  // begin: enable msix
991
992  // setup msix
993  // map to interrupt handler
994  int error = 0;
995  int mesgs = MAX_MSIX_NUM_VECTOR;
996  int i, cnt;
997
998  void (*intrHandler[MAX_MSIX_NUM_ISR])(void *arg) =
999    {
1000      agtiapi_IntrHandler0,
1001      agtiapi_IntrHandler1,
1002      agtiapi_IntrHandler2,
1003      agtiapi_IntrHandler3,
1004      agtiapi_IntrHandler4,
1005      agtiapi_IntrHandler5,
1006      agtiapi_IntrHandler6,
1007      agtiapi_IntrHandler7,
1008      agtiapi_IntrHandler8,
1009      agtiapi_IntrHandler9,
1010      agtiapi_IntrHandler10,
1011      agtiapi_IntrHandler11,
1012      agtiapi_IntrHandler12,
1013      agtiapi_IntrHandler13,
1014      agtiapi_IntrHandler14,
1015      agtiapi_IntrHandler15
1016
1017    };
1018
1019  cnt = pci_msix_count(devx);
1020  AGTIAPI_PRINTK("supported MSIX %d\n", cnt); //this should be 64
1021  mesgs = MIN(mesgs, cnt);
1022  error = pci_alloc_msix(devx, &mesgs);
1023  if (error != 0) {
1024    printf( "pci_alloc_msix error %d\n", error );
1025    AGTIAPI_PRINTK("error %d\n", error);
1026    return( EIO );
1027  }
1028
1029  for(i=0; i < mesgs; i++) {
1030    pmsc->rscID[i] = i + 1;
1031    pmsc->irq[i] = bus_alloc_resource_any( devx,
1032                                           SYS_RES_IRQ,
1033                                           &pmsc->rscID[i],
1034                                           RF_ACTIVE );
1035    if( pmsc->irq[i] == NULL ) {
1036      printf( "RES_IRQ went terribly bad at %d\n", i );
1037      return( EIO );
1038    }
1039
1040    if ( (error = bus_setup_intr( devx, pmsc->irq[i],
1041                                  INTR_TYPE_CAM | INTR_MPSAFE,
1042                                  NULL,
1043                                  intrHandler[i],
1044                                  pmsc,
1045                                  &pmsc->intrcookie[i] )
1046           ) != 0 ) {
1047      device_printf( devx, "Failed to register handler" );
1048      return( EIO );
1049    }
1050  }
1051  pmsc->flags |= AGTIAPI_IRQ_REQUESTED;
1052  pmsc->pCardInfo->maxInterruptVectors = MAX_MSIX_NUM_VECTOR;
1053  // end: enable msix
1054
1055  int ret = 0;
1056  ret = agtiapi_InitCardSW(pmsc);
1057  if (ret == AGTIAPI_FAIL || ret == AGTIAPI_UNKNOWN)
1058  {
1059    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_InitCardSW failure %d\n",
1060                    ret );
1061    return( EIO );
1062  }
1063
1064  pmsc->ccbFreeList = NULL;
1065  pmsc->ccbChainList = NULL;
1066  pmsc->ccbAllocList = NULL;
1067
1068  pmsc->flags |= ( AGTIAPI_INSTALLED );
1069
1070  ret = agtiapi_alloc_requests( pmsc );
1071  if( ret != 0 ) {
1072    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_alloc_requests failure %d\n",
1073                    ret );
1074    return( EIO );
1075  }
1076
1077  ret = agtiapi_alloc_ostimem( pmsc );
1078  if (ret != AGTIAPI_SUCCESS)
1079  {
1080    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_alloc_ostimem failure %d\n",
1081                    ret );
1082    return( EIO );
1083  }
1084
1085  ret = agtiapi_InitCardHW( pmsc );
1086  if (ret != 0)
1087  {
1088    AGTIAPI_PRINTK( "agtiapi_attach: agtiapi_InitCardHW failure %d\n",
1089                    ret );
1090    return( EIO );
1091  }
1092
1093#ifdef HIALEAH_ENCRYPTION
1094  if(pmsc->encrypt)
1095  {
1096	if((agtiapi_SetupEncryption(pmsc)) < 0)
1097		AGTIAPI_PRINTK("SetupEncryption returned less than 0\n");
1098  }
1099#endif
1100
1101  pmsc->flags &= ~AGTIAPI_INIT_TIME;
1102  return( 0 );
1103}
1104
1105/******************************************************************************
1106agtiapi_InitCardSW()
1107
1108Purpose:
1109  Host Bus Adapter Initialization
1110Parameters:
1111  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1112Return:
1113  AGTIAPI_SUCCESS - success
1114  AGTIAPI_FAIL    - fail
1115Note:
1116  TBD, need chip register information
1117******************************************************************************/
1118STATIC agBOOLEAN agtiapi_InitCardSW( struct agtiapi_softc *pmsc )
1119{
1120  ag_card_info_t *thisCardInst = pmsc->pCardInfo;
1121  ag_resource_info_t *pRscInfo = &thisCardInst->tiRscInfo;
1122  int initSWIdx;
1123
1124  // begin: agtiapi_InitCardSW()
1125  // now init some essential locks  n agtiapi_InitCardSW
1126  mtx_init( &pmsc->sendLock,     "local q send lock",   NULL, MTX_DEF );
1127  mtx_init( &pmsc->doneLock,     "local q done lock",   NULL, MTX_DEF );
1128  mtx_init( &pmsc->sendSMPLock,  "local q send lock",   NULL, MTX_DEF );
1129  mtx_init( &pmsc->doneSMPLock,  "local q done lock",   NULL, MTX_DEF );
1130  mtx_init( &pmsc->ccbLock,      "ccb list lock",       NULL, MTX_DEF );
1131  mtx_init( &pmsc->devListLock,  "hotP devListLock",    NULL, MTX_DEF );
1132  mtx_init( &pmsc->memLock,      "dynamic memory lock", NULL, MTX_DEF );
1133  mtx_init( &pmsc->freezeLock,   "sim freeze lock",     NULL, MTX_DEF | MTX_RECURSE);
1134
1135  // initialize lower layer resources
1136  //## if (pCard->flags & AGTIAPI_INIT_TIME) {
1137#ifdef HIALEAH_ENCRYPTION
1138    /* Enable encryption if chip supports it */
1139    if (pci_get_device(pmsc->pCardInfo->pPCIDev) ==
1140                     PCI_DEVICE_ID_HIALEAH_HBA_SPCVE)
1141        pmsc->encrypt = 1;
1142
1143    if (pmsc->encrypt)
1144        pRscInfo->tiLoLevelResource.loLevelOption.encryption = agTRUE;
1145#endif
1146  pmsc->flags &= ~(AGTIAPI_PORT_INITIALIZED | AGTIAPI_SYS_INTR_ON);
1147
1148
1149  // For now, up to 16 MSIX vectors are supported
1150  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.
1151    maxInterruptVectors = pmsc->pCardInfo->maxInterruptVectors;
1152  AGTIAPI_PRINTK( "agtiapi_InitCardSW: maxInterruptVectors set to %d",
1153                  pmsc->pCardInfo->maxInterruptVectors );
1154  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.max_MSI_InterruptVectors = 0;
1155  thisCardInst->tiRscInfo.tiLoLevelResource.loLevelOption.flag = 0;
1156  pRscInfo->tiLoLevelResource.loLevelOption.maxNumOSLocks = 0;
1157
1158  AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMInit root %p, dev %p, pmsc %p\n",
1159                  &pmsc->tiRoot, pmsc->my_dev, pmsc );
1160  if( tiCOMInit( &pmsc->tiRoot,
1161                 &thisCardInst->tiRscInfo.tiLoLevelResource,
1162                 &thisCardInst->tiRscInfo.tiInitiatorResource,
1163                 NULL,
1164                 &thisCardInst->tiRscInfo.tiSharedMem ) != tiSuccess ) {
1165    AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMInit ERROR\n" );
1166    return AGTIAPI_FAIL;
1167  }
1168  int maxLocks;
1169  maxLocks = pRscInfo->tiLoLevelResource.loLevelOption.numOfQueuesPerPort;
1170  pmsc->STLock = malloc( ( maxLocks * sizeof(struct mtx) ), M_PMC_MSTL,
1171			              M_ZERO | M_WAITOK );
1172
1173  for( initSWIdx = 0; initSWIdx < maxLocks; initSWIdx++ )
1174  {
1175    // init all indexes
1176    mtx_init( &pmsc->STLock[initSWIdx], "LL & TD lock", NULL, MTX_DEF );
1177  }
1178
1179  if( tiCOMPortInit( &pmsc->tiRoot, agFALSE ) != tiSuccess ) {
1180    printf( "agtiapi_InitCardSW: tiCOMPortInit ERROR -- AGTIAPI_FAIL\n" );
1181    return AGTIAPI_FAIL;
1182  }
1183  AGTIAPI_PRINTK( "agtiapi_InitCardSW: tiCOMPortInit"
1184                  " root %p, dev %p, pmsc %p\n",
1185                  &pmsc->tiRoot, pmsc->my_dev, pmsc );
1186
1187  pmsc->flags |= AGTIAPI_PORT_INITIALIZED;
1188  pmsc->freezeSim = agFALSE;
1189
1190#ifdef HIALEAH_ENCRYPTION
1191  atomic_set(&outstanding_encrypted_io_count, 0);
1192  /*fix below*/
1193  /*if(pmsc->encrypt && (pmsc->flags & AGTIAPI_INIT_TIME))
1194	   if((agtiapi_SetupEncryptionPools(pmsc)) != 0)
1195	     printf("SetupEncryptionPools failed\n"); */
1196#endif
1197  return AGTIAPI_SUCCESS;
1198  // end: agtiapi_InitCardSW()
1199}
1200
1201/******************************************************************************
1202agtiapi_InitCardHW()
1203
1204Purpose:
1205  Host Bus Adapter Initialization
1206Parameters:
1207  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1208Return:
1209  AGTIAPI_SUCCESS - success
1210  AGTIAPI_FAIL    - fail
1211Note:
1212  TBD, need chip register information
1213******************************************************************************/
1214STATIC agBOOLEAN agtiapi_InitCardHW( struct agtiapi_softc *pmsc )
1215{
1216  U32 numVal;
1217  U32 count;
1218  U32 loop;
1219  // begin: agtiapi_InitCardHW()
1220
1221  ag_portal_info_t *pPortalInfo = NULL;
1222  ag_portal_data_t *pPortalData;
1223
1224  // ISR is registered, enable chip interrupt.
1225  tiCOMSystemInterruptsActive( &pmsc->tiRoot, agTRUE );
1226  pmsc->flags |= AGTIAPI_SYS_INTR_ON;
1227
1228  numVal = sizeof(ag_device_t) * pmsc->devDiscover;
1229  pmsc->pDevList =
1230    (ag_device_t *)malloc( numVal, M_PMC_MDVT, M_ZERO | M_WAITOK );
1231  if( !pmsc->pDevList ) {
1232    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d DevList ERROR\n", numVal );
1233    panic( "agtiapi_InitCardHW\n" );
1234    return AGTIAPI_FAIL;
1235  }
1236
1237#ifdef LINUX_PERBI_SUPPORT
1238  numVal = sizeof(ag_slr_map_t) * pmsc->devDiscover;
1239  pmsc->pSLRList =
1240    (ag_slr_map_t *)malloc( numVal, M_PMC_MSLR, M_ZERO | M_WAITOK );
1241  if( !pmsc->pSLRList ) {
1242    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d SLRList ERROR\n", numVal );
1243    panic( "agtiapi_InitCardHW SLRL\n" );
1244    return AGTIAPI_FAIL;
1245  }
1246
1247  numVal = sizeof(ag_tgt_map_t) * pmsc->devDiscover;
1248  pmsc->pWWNList =
1249    (ag_tgt_map_t *)malloc( numVal, M_PMC_MTGT, M_ZERO | M_WAITOK );
1250  if( !pmsc->pWWNList ) {
1251    AGTIAPI_PRINTK( "agtiapi_InitCardHW: kmalloc %d WWNList ERROR\n", numVal );
1252    panic( "agtiapi_InitCardHW WWNL\n" );
1253    return AGTIAPI_FAIL;
1254  }
1255
1256  // Get the WWN_to_target_ID mappings from the
1257  // holding area which contains the input of the
1258  // system configuration file.
1259  if( ag_Perbi )
1260    agtiapi_GetWWNMappings( pmsc, agMappingList );
1261  else {
1262    agtiapi_GetWWNMappings( pmsc, 0 );
1263    if( agMappingList )
1264      printf( "agtiapi_InitCardHW: WWN PERBI disabled WARN\n" );
1265  }
1266#endif
1267
1268  //agtiapi_DelaySec(5);
1269  DELAY( 500000 );
1270
1271  pmsc->tgtCount = 0;
1272
1273  pmsc->flags &= ~AGTIAPI_CB_DONE;
1274  pPortalData = pmsc->pPortalData;
1275
1276  //start port
1277
1278  for (count = 0; count < pmsc->portCount; count++)
1279  {
1280    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
1281
1282    pPortalInfo = &pPortalData->portalInfo;
1283    pPortalInfo->portStatus &= ~( AGTIAPI_PORT_START      |
1284                                  AGTIAPI_PORT_DISC_READY |
1285                                  AGTIAPI_DISC_DONE       |
1286                                  AGTIAPI_DISC_COMPLETE );
1287
1288    for (loop = 0; loop < AGTIAPI_LOOP_MAX; loop++)
1289    {
1290      AGTIAPI_PRINTK( "tiCOMPortStart entry data %p / %d / %p\n",
1291                      &pmsc->tiRoot,
1292                      pPortalInfo->portID,
1293                      &pPortalInfo->tiPortalContext );
1294
1295      if( tiCOMPortStart( &pmsc->tiRoot,
1296                          pPortalInfo->portID,
1297                          &pPortalInfo->tiPortalContext,
1298                          0 )
1299          != tiSuccess ) {
1300        AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
1301        agtiapi_DelayMSec( AGTIAPI_EXTRA_DELAY );
1302        AG_SPIN_LOCK_IRQ(agtiapi_host_lock, flags);
1303        AGTIAPI_PRINTK( "tiCOMPortStart failed -- no loop, portalData %p\n",
1304                        pPortalData );
1305      }
1306      else {
1307        AGTIAPI_PRINTK( "tiCOMPortStart success no loop, portalData %p\n",
1308                        pPortalData );
1309        break;
1310      }
1311    } // end of for loop
1312    /* release lock */
1313    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
1314
1315    if( loop >= AGTIAPI_LOOP_MAX ) {
1316      return AGTIAPI_FAIL;
1317    }
1318    tiCOMGetPortInfo( &pmsc->tiRoot,
1319                      &pPortalInfo->tiPortalContext,
1320                      &pPortalInfo->tiPortInfo );
1321    pPortalData++;
1322  }
1323
1324  /* discover target device */
1325#ifndef HOTPLUG_SUPPORT
1326  agtiapi_DiscoverTgt( pCard );
1327#endif
1328
1329
1330  pmsc->flags |= AGTIAPI_INSTALLED;
1331
1332  if( pmsc->flags & AGTIAPI_INIT_TIME ) {
1333    agtiapi_TITimer( (void *)pmsc );
1334    pmsc->flags |= AGTIAPI_TIMER_ON;
1335  }
1336
1337  return 0;
1338}
1339
1340
1341
1342/******************************************************************************
1343agtiapi_IntrHandlerx_()
1344
1345Purpose:
1346  Interrupt service routine.
1347Parameters:
1348  void arg (IN)              Pointer to the HBA data structure
1349  bit32 idx (IN)             Vector index
1350******************************************************************************/
1351void  agtiapi_IntrHandlerx_( void *arg, int index )
1352{
1353
1354  struct agtiapi_softc *pCard;
1355  int rv;
1356
1357  pCard = (struct agtiapi_softc *)arg;
1358
1359#ifndef AGTIAPI_DPC
1360  ccb_t     *pccb;
1361#endif
1362
1363  AG_LOCAL_LOCK(&(pCard->pCardInfo->pmIOLock));
1364  AG_PERF_SPINLOCK(agtiapi_host_lock);
1365  if (pCard->flags & AGTIAPI_SHUT_DOWN)
1366    goto ext;
1367
1368  rv = tiCOMInterruptHandler(&pCard->tiRoot, index);
1369  if (rv == agFALSE)
1370  {
1371    /* not our irq */
1372    AG_SPIN_UNLOCK(agtiapi_host_lock);
1373    AG_LOCAL_UNLOCK(&(pCard->pCardInfo->pmIOLock));
1374    return;
1375  }
1376
1377
1378#ifdef AGTIAPI_DPC
1379  tasklet_hi_schedule(&pCard->tasklet_dpc[idx]);
1380#else
1381  /* consume all completed entries, 100 is random number to be big enough */
1382  tiCOMDelayedInterruptHandler(&pCard->tiRoot, index, 100, tiInterruptContext);
1383  AG_GET_DONE_PCCB(pccb, pCard);
1384  AG_GET_DONE_SMP_PCCB(pccb, pCard);
1385#endif
1386
1387ext:
1388  AG_SPIN_UNLOCK(agtiapi_host_lock);
1389  AG_LOCAL_UNLOCK(&(pCard->pCardInfo->pmIOLock));
1390  return;
1391
1392}
1393
1394/******************************************************************************
1395agtiapi_IntrHandler0()
1396Purpose:     Interrupt service routine for interrupt vector index 0.
1397Parameters:  void arg (IN)       Pointer to the HBA data structure
1398******************************************************************************/
1399void agtiapi_IntrHandler0( void *arg )
1400{
1401  agtiapi_IntrHandlerx_( arg, 0 );
1402  return;
1403}
1404
1405/******************************************************************************
1406agtiapi_IntrHandler1()
1407Purpose:     Interrupt service routine for interrupt vector index 1.
1408Parameters:  void arg (IN)       Pointer to the HBA data structure
1409******************************************************************************/
1410void agtiapi_IntrHandler1( void *arg )
1411{
1412  agtiapi_IntrHandlerx_( arg, 1 );
1413  return;
1414}
1415
1416/******************************************************************************
1417agtiapi_IntrHandler2()
1418Purpose:     Interrupt service routine for interrupt vector index 2.
1419Parameters:  void arg (IN)       Pointer to the HBA data structure
1420******************************************************************************/
1421void agtiapi_IntrHandler2( void *arg )
1422{
1423  agtiapi_IntrHandlerx_( arg, 2 );
1424  return;
1425}
1426
1427/******************************************************************************
1428agtiapi_IntrHandler3()
1429Purpose:     Interrupt service routine for interrupt vector index 3.
1430Parameters:  void arg (IN)       Pointer to the HBA data structure
1431******************************************************************************/
1432void agtiapi_IntrHandler3( void *arg )
1433{
1434  agtiapi_IntrHandlerx_( arg, 3 );
1435  return;
1436}
1437
1438/******************************************************************************
1439agtiapi_IntrHandler4()
1440Purpose:     Interrupt service routine for interrupt vector index 4.
1441Parameters:  void arg (IN)       Pointer to the HBA data structure
1442******************************************************************************/
1443void agtiapi_IntrHandler4( void *arg )
1444{
1445  agtiapi_IntrHandlerx_( arg, 4 );
1446  return;
1447}
1448
1449/******************************************************************************
1450agtiapi_IntrHandler5()
1451Purpose:     Interrupt service routine for interrupt vector index 5.
1452Parameters:  void arg (IN)       Pointer to the HBA data structure
1453******************************************************************************/
1454void agtiapi_IntrHandler5( void *arg )
1455{
1456  agtiapi_IntrHandlerx_( arg, 5 );
1457  return;
1458}
1459
1460/******************************************************************************
1461agtiapi_IntrHandler6()
1462Purpose:     Interrupt service routine for interrupt vector index 6.
1463Parameters:  void arg (IN)       Pointer to the HBA data structure
1464******************************************************************************/
1465void agtiapi_IntrHandler6( void *arg )
1466{
1467  agtiapi_IntrHandlerx_( arg, 6 );
1468  return;
1469}
1470
1471/******************************************************************************
1472agtiapi_IntrHandler7()
1473Purpose:     Interrupt service routine for interrupt vector index 7.
1474Parameters:  void arg (IN)       Pointer to the HBA data structure
1475******************************************************************************/
1476void agtiapi_IntrHandler7( void *arg )
1477{
1478  agtiapi_IntrHandlerx_( arg, 7 );
1479  return;
1480}
1481
1482/******************************************************************************
1483agtiapi_IntrHandler8()
1484Purpose:     Interrupt service routine for interrupt vector index 8.
1485Parameters:  void arg (IN)       Pointer to the HBA data structure
1486******************************************************************************/
1487void agtiapi_IntrHandler8( void *arg )
1488{
1489  agtiapi_IntrHandlerx_( arg, 8 );
1490  return;
1491}
1492
1493/******************************************************************************
1494agtiapi_IntrHandler9()
1495Purpose:     Interrupt service routine for interrupt vector index 9.
1496Parameters:  void arg (IN)       Pointer to the HBA data structure
1497******************************************************************************/
1498void agtiapi_IntrHandler9( void *arg )
1499{
1500  agtiapi_IntrHandlerx_( arg, 9 );
1501  return;
1502}
1503
1504/******************************************************************************
1505agtiapi_IntrHandler10()
1506Purpose:     Interrupt service routine for interrupt vector index 10.
1507Parameters:  void arg (IN)       Pointer to the HBA data structure
1508******************************************************************************/
1509void agtiapi_IntrHandler10( void *arg )
1510{
1511  agtiapi_IntrHandlerx_( arg, 10 );
1512  return;
1513}
1514
1515/******************************************************************************
1516agtiapi_IntrHandler11()
1517Purpose:     Interrupt service routine for interrupt vector index 11.
1518Parameters:  void arg (IN)       Pointer to the HBA data structure
1519******************************************************************************/
1520void agtiapi_IntrHandler11( void *arg )
1521{
1522  agtiapi_IntrHandlerx_( arg, 11 );
1523  return;
1524}
1525
1526/******************************************************************************
1527agtiapi_IntrHandler12()
1528Purpose:     Interrupt service routine for interrupt vector index 12.
1529Parameters:  void arg (IN)       Pointer to the HBA data structure
1530******************************************************************************/
1531void agtiapi_IntrHandler12( void *arg )
1532{
1533  agtiapi_IntrHandlerx_( arg, 12 );
1534  return;
1535}
1536
1537/******************************************************************************
1538agtiapi_IntrHandler13()
1539Purpose:     Interrupt service routine for interrupt vector index 13.
1540Parameters:  void arg (IN)       Pointer to the HBA data structure
1541******************************************************************************/
1542void agtiapi_IntrHandler13( void *arg )
1543{
1544  agtiapi_IntrHandlerx_( arg, 13 );
1545  return;
1546}
1547
1548/******************************************************************************
1549agtiapi_IntrHandler14()
1550Purpose:     Interrupt service routine for interrupt vector index 14.
1551Parameters:  void arg (IN)       Pointer to the HBA data structure
1552******************************************************************************/
1553void agtiapi_IntrHandler14( void *arg )
1554{
1555  agtiapi_IntrHandlerx_( arg, 14 );
1556  return;
1557}
1558
1559/******************************************************************************
1560agtiapi_IntrHandler15()
1561Purpose:     Interrupt service routine for interrupt vector index 15.
1562Parameters:  void arg (IN)       Pointer to the HBA data structure
1563******************************************************************************/
1564void agtiapi_IntrHandler15( void *arg )
1565{
1566  agtiapi_IntrHandlerx_( arg, 15 );
1567  return;
1568}
1569
1570static void agtiapi_SglMemoryCB( void *arg,
1571                                 bus_dma_segment_t *dm_segs,
1572                                 int nseg,
1573                                 int error )
1574{
1575  bus_addr_t *addr;
1576  AGTIAPI_PRINTK("agtiapi_SglMemoryCB: start\n");
1577  if (error != 0)
1578  {
1579    AGTIAPI_PRINTK("agtiapi_SglMemoryCB: error %d\n", error);
1580    panic("agtiapi_SglMemoryCB: error %d\n", error);
1581    return;
1582  }
1583  addr = arg;
1584  *addr = dm_segs[0].ds_addr;
1585  return;
1586}
1587
1588static void agtiapi_MemoryCB( void *arg,
1589                              bus_dma_segment_t *dm_segs,
1590                              int nseg,
1591                              int error )
1592{
1593  bus_addr_t *addr;
1594  AGTIAPI_PRINTK("agtiapi_MemoryCB: start\n");
1595  if (error != 0)
1596  {
1597    AGTIAPI_PRINTK("agtiapi_MemoryCB: error %d\n", error);
1598    panic("agtiapi_MemoryCB: error %d\n", error);
1599    return;
1600  }
1601  addr = arg;
1602  *addr = dm_segs[0].ds_addr;
1603  return;
1604}
1605
1606/******************************************************************************
1607agtiapi_alloc_requests()
1608
1609Purpose:
1610  Allocates resources such as dma tag and timer
1611Parameters:
1612  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
1613Return:
1614  AGTIAPI_SUCCESS - success
1615  AGTIAPI_FAIL    - fail
1616Note:
1617******************************************************************************/
1618int agtiapi_alloc_requests( struct agtiapi_softc *pmcsc )
1619{
1620
1621  int rsize, nsegs;
1622  U32 next_tick;
1623
1624  nsegs = AGTIAPI_NSEGS;
1625  rsize = AGTIAPI_MAX_DMA_SEGS;   // 128
1626  AGTIAPI_PRINTK( "agtiapi_alloc_requests: MAXPHYS 0x%x PAGE_SIZE 0x%x \n",
1627                  MAXPHYS, PAGE_SIZE );
1628  AGTIAPI_PRINTK( "agtiapi_alloc_requests: nsegs %d rsize %d \n",
1629                  nsegs, rsize ); // 32, 128
1630  // This is for csio->data_ptr
1631  if( bus_dma_tag_create( agNULL,                      // parent
1632                          1,                           // alignment
1633                          0,                           // boundary
1634                          BUS_SPACE_MAXADDR,           // lowaddr
1635                          BUS_SPACE_MAXADDR,           // highaddr
1636                          NULL,                        // filter
1637                          NULL,                        // filterarg
1638                          BUS_SPACE_MAXSIZE_32BIT,     // maxsize
1639                          nsegs,                       // nsegments
1640                          BUS_SPACE_MAXSIZE_32BIT,     // maxsegsize
1641                          BUS_DMA_ALLOCNOW,            // flags
1642                          busdma_lock_mutex,           // lockfunc
1643                          &pmcsc->pCardInfo->pmIOLock, // lockarg
1644                          &pmcsc->buffer_dmat ) ) {
1645    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot alloc request DMA tag\n" );
1646    return( ENOMEM );
1647  }
1648
1649  // This is for tiSgl_t of pccb in agtiapi_PrepCCBs()
1650  rsize =
1651    (sizeof(tiSgl_t) * AGTIAPI_NSEGS) *
1652    AGTIAPI_CCB_PER_DEVICE * maxTargets;
1653  AGTIAPI_PRINTK( "agtiapi_alloc_requests: rsize %d \n", rsize ); // 32, 128
1654  if( bus_dma_tag_create( agNULL,                  // parent
1655                          32,                      // alignment
1656                          0,	                     // boundary
1657                          BUS_SPACE_MAXADDR_32BIT, // lowaddr
1658                          BUS_SPACE_MAXADDR,	     // highaddr
1659                          NULL,                    // filter
1660                          NULL,	                   // filterarg
1661                          rsize,                   // maxsize
1662                          1,                       // nsegments
1663                          rsize,                   // maxsegsize
1664                          BUS_DMA_ALLOCNOW,        // flags
1665                          NULL,                    // lockfunc
1666                          NULL,                    // lockarg
1667                          &pmcsc->tisgl_dmat ) ) {
1668    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot alloc request DMA tag\n" );
1669    return( ENOMEM );
1670  }
1671
1672  if( bus_dmamem_alloc( pmcsc->tisgl_dmat,
1673                        (void **)&pmcsc->tisgl_mem,
1674                        BUS_DMA_NOWAIT,
1675                        &pmcsc->tisgl_map ) ) {
1676    AGTIAPI_PRINTK( "agtiapi_alloc_requests: Cannot allocate SGL memory\n" );
1677    return( ENOMEM );
1678  }
1679
1680  bzero( pmcsc->tisgl_mem, rsize );
1681  bus_dmamap_load( pmcsc->tisgl_dmat,
1682                   pmcsc->tisgl_map,
1683                   pmcsc->tisgl_mem,
1684                   rsize,
1685                   agtiapi_SglMemoryCB,
1686                   &pmcsc->tisgl_busaddr,
1687                   BUS_DMA_NOWAIT /* 0 */ );
1688
1689  mtx_init( &pmcsc->OS_timer_lock,  "OS timer lock",      NULL, MTX_DEF );
1690  mtx_init( &pmcsc->IO_timer_lock,  "IO timer lock",      NULL, MTX_DEF );
1691  mtx_init( &pmcsc->devRmTimerLock, "targ rm timer lock", NULL, MTX_DEF );
1692  callout_init_mtx( &pmcsc->OS_timer, &pmcsc->OS_timer_lock, 0 );
1693  callout_init_mtx( &pmcsc->IO_timer, &pmcsc->IO_timer_lock, 0 );
1694  callout_init_mtx( &pmcsc->devRmTimer,
1695		    &pmcsc->devRmTimerLock, 0);
1696
1697  next_tick = pmcsc->pCardInfo->tiRscInfo.tiLoLevelResource.
1698              loLevelOption.usecsPerTick / USEC_PER_TICK;
1699  AGTIAPI_PRINTK( "agtiapi_alloc_requests: before callout_reset, "
1700                  "next_tick 0x%x\n", next_tick );
1701  callout_reset( &pmcsc->OS_timer, next_tick, agtiapi_TITimer, pmcsc );
1702  return 0;
1703}
1704
1705/******************************************************************************
1706agtiapi_alloc_ostimem()
1707
1708Purpose:
1709  Allocates memory used later in ostiAllocMemory
1710Parameters:
1711  struct agtiapi_softc *pmcsc (IN)  Pointer to the HBA data structure
1712Return:
1713  AGTIAPI_SUCCESS - success
1714  AGTIAPI_FAIL    - fail
1715Note:
1716  This is a pre-allocation for ostiAllocMemory() "non-cacheable" function calls
1717******************************************************************************/
1718int  agtiapi_alloc_ostimem( struct agtiapi_softc *pmcsc ) {
1719  int rsize, nomsize;
1720
1721  nomsize = 4096;
1722  rsize = AGTIAPI_DYNAMIC_MAX * nomsize; // 8M
1723  AGTIAPI_PRINTK("agtiapi_alloc_ostimem: rsize %d \n", rsize);
1724
1725  if( bus_dma_tag_create( agNULL,                      // parent
1726                          32,                          // alignment
1727                          0,                           // boundary
1728                          BUS_SPACE_MAXADDR,           // lowaddr
1729                          BUS_SPACE_MAXADDR,           // highaddr
1730                          NULL,                        // filter
1731                          NULL,                        // filterarg
1732                          rsize,                       // maxsize (size)
1733                          1,                           // number of segments
1734                          rsize,                       // maxsegsize
1735                          0,                           // flags
1736                          NULL,                        // lockfunc
1737                          NULL,                        // lockarg
1738                          &pmcsc->osti_dmat ) ) {
1739    AGTIAPI_PRINTK( "agtiapi_alloc_ostimem: Can't create no-cache mem tag\n" );
1740    return AGTIAPI_FAIL;
1741  }
1742
1743
1744  if( bus_dmamem_alloc( pmcsc->osti_dmat,
1745                        &pmcsc->osti_mem,
1746                        BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE,
1747                        &pmcsc->osti_mapp ) ) {
1748    AGTIAPI_PRINTK( "agtiapi_alloc_ostimem: Cannot allocate cache mem %d\n",
1749                    rsize );
1750    return AGTIAPI_FAIL;
1751  }
1752
1753
1754  bus_dmamap_load( pmcsc->osti_dmat,
1755                   pmcsc->osti_mapp,
1756                   pmcsc->osti_mem,
1757                   rsize,
1758                   agtiapi_MemoryCB, // try reuse of CB for same goal
1759                   &pmcsc->osti_busaddr,
1760                   BUS_DMA_NOWAIT );
1761
1762  // populate all the ag_dma_addr_t osti_busaddr/mem fields with addresses for
1763  //  handy reference when driver is in motion
1764  int idx;
1765  ag_card_info_t *pCardInfo = pmcsc->pCardInfo;
1766  ag_dma_addr_t  *pMem;
1767
1768  for( idx = 0; idx < AGTIAPI_DYNAMIC_MAX; idx++ ) {
1769    pMem = &pCardInfo->dynamicMem[idx];
1770    pMem->nocache_busaddr = pmcsc->osti_busaddr + ( idx * nomsize );
1771    pMem->nocache_mem     = (void*)((U64)pmcsc->osti_mem + ( idx * nomsize ));
1772    pCardInfo->freeDynamicMem[idx] = &pCardInfo->dynamicMem[idx];
1773  }
1774
1775  pCardInfo->topOfFreeDynamicMem = AGTIAPI_DYNAMIC_MAX;
1776
1777  return AGTIAPI_SUCCESS;
1778}
1779
1780
1781/******************************************************************************
1782agtiapi_cam_action()
1783
1784Purpose:
1785  Parses CAM frames and triggers a corresponding action
1786Parameters:
1787  struct cam_sim *sim (IN)  Pointer to SIM data structure
1788  union ccb * ccb (IN)      Pointer to CAM ccb data structure
1789Return:
1790Note:
1791******************************************************************************/
1792static void agtiapi_cam_action( struct cam_sim *sim, union ccb * ccb )
1793{
1794  struct agtiapi_softc *pmcsc;
1795  tiDeviceHandle_t *pDevHandle = NULL;	// acts as flag as well
1796  tiDeviceInfo_t devInfo;
1797  int pathID, targetID, lunID;
1798  int lRetVal;
1799  U32 TID;
1800  U32 speed = 150000;
1801
1802  pmcsc = cam_sim_softc( sim );
1803  AGTIAPI_IO( "agtiapi_cam_action: start pmcs %p\n", pmcsc );
1804
1805  if (pmcsc == agNULL)
1806  {
1807    AGTIAPI_PRINTK( "agtiapi_cam_action: start pmcs is NULL\n" );
1808    return;
1809  }
1810  mtx_assert( &(pmcsc->pCardInfo->pmIOLock), MA_OWNED );
1811
1812  AGTIAPI_IO( "agtiapi_cam_action: cardNO %d func_code 0x%x\n", pmcsc->cardNo, ccb->ccb_h.func_code );
1813
1814  pathID   = xpt_path_path_id( ccb->ccb_h.path );
1815  targetID = xpt_path_target_id( ccb->ccb_h.path );
1816  lunID    = xpt_path_lun_id( ccb->ccb_h.path );
1817
1818  AGTIAPI_IO( "agtiapi_cam_action: P 0x%x T 0x%x L 0x%x\n",
1819              pathID, targetID, lunID );
1820
1821  switch (ccb->ccb_h.func_code)
1822  {
1823  case XPT_PATH_INQ:
1824  {
1825    struct ccb_pathinq *cpi;
1826
1827    /* See architecure book p180*/
1828    cpi = &ccb->cpi;
1829    cpi->version_num = 1;
1830    cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_16;
1831    cpi->target_sprt = 0;
1832    cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
1833    cpi->hba_eng_cnt = 0;
1834    cpi->max_target = maxTargets - 1;
1835    cpi->max_lun = AGTIAPI_MAX_LUN;
1836    /* Max supported I/O size, in bytes. */
1837    cpi->maxio = ctob(AGTIAPI_NSEGS - 1);
1838    cpi->initiator_id = 255;
1839    strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1840    strlcpy(cpi->hba_vid, "PMC", HBA_IDLEN);
1841    strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1842    cpi->unit_number = cam_sim_unit(sim);
1843    cpi->bus_id = cam_sim_bus(sim);
1844    // rate is set when XPT_GET_TRAN_SETTINGS is processed
1845    cpi->base_transfer_speed = 150000;
1846    cpi->transport = XPORT_SAS;
1847    cpi->transport_version = 0;
1848    cpi->protocol = PROTO_SCSI;
1849    cpi->protocol_version = SCSI_REV_SPC3;
1850    cpi->ccb_h.status = CAM_REQ_CMP;
1851    break;
1852  }
1853  case XPT_GET_TRAN_SETTINGS:
1854  {
1855    struct ccb_trans_settings	*cts;
1856    struct ccb_trans_settings_sas *sas;
1857    struct ccb_trans_settings_scsi	*scsi;
1858
1859    if ( pmcsc->flags & AGTIAPI_SHUT_DOWN )
1860    {
1861      return;
1862    }
1863
1864    cts = &ccb->cts;
1865    sas = &ccb->cts.xport_specific.sas;
1866    scsi = &cts->proto_specific.scsi;
1867
1868    cts->protocol = PROTO_SCSI;
1869    cts->protocol_version = SCSI_REV_SPC3;
1870    cts->transport = XPORT_SAS;
1871    cts->transport_version = 0;
1872
1873    sas->valid = CTS_SAS_VALID_SPEED;
1874
1875    /* this sets the "MB/s transfers" */
1876    if (pmcsc != NULL && targetID >= 0 && targetID < maxTargets)
1877    {
1878      if (pmcsc->pWWNList != NULL)
1879      {
1880        TID = INDEX(pmcsc, targetID);
1881        if (TID < maxTargets)
1882        {
1883          pDevHandle = pmcsc->pDevList[TID].pDevHandle;
1884        }
1885      }
1886    }
1887    if (pDevHandle)
1888    {
1889      tiINIGetDeviceInfo( &pmcsc->tiRoot, pDevHandle, &devInfo );
1890      switch (devInfo.info.devType_S_Rate & 0xF)
1891      {
1892        case 0x8: speed = 150000;
1893          break;
1894        case 0x9: speed = 300000;
1895          break;
1896        case 0xA: speed = 600000;
1897          break;
1898        case 0xB: speed = 1200000;
1899          break;
1900        default:  speed = 150000;
1901          break;
1902      }
1903    }
1904    sas->bitrate      = speed;
1905    scsi->valid       = CTS_SCSI_VALID_TQ;
1906    scsi->flags       = CTS_SCSI_FLAGS_TAG_ENB;
1907    ccb->ccb_h.status = CAM_REQ_CMP;
1908    break;
1909  }
1910  case XPT_RESET_BUS:
1911  {
1912    lRetVal = agtiapi_eh_HostReset( pmcsc, ccb ); // usually works first time
1913    if ( SUCCESS == lRetVal )
1914    {
1915      AGTIAPI_PRINTK( "agtiapi_cam_action: bus reset success.\n" );
1916    }
1917    else
1918    {
1919      AGTIAPI_PRINTK( "agtiapi_cam_action: bus reset failed.\n" );
1920    }
1921    ccb->ccb_h.status = CAM_REQ_CMP;
1922    break;
1923  }
1924  case XPT_RESET_DEV:
1925  {
1926    ccb->ccb_h.status = CAM_REQ_CMP;
1927    break;
1928  }
1929  case XPT_ABORT:
1930  {
1931    ccb->ccb_h.status = CAM_REQ_CMP;
1932    break;
1933  }
1934#if __FreeBSD_version >= 900026
1935  case XPT_SMP_IO:
1936  {
1937    agtiapi_QueueSMP( pmcsc, ccb );
1938    return;
1939  }
1940#endif /* __FreeBSD_version >= 900026 */
1941  case XPT_SCSI_IO:
1942  {
1943    if(pmcsc->dev_scan == agFALSE)
1944    {
1945       ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1946       break;
1947    }
1948    if (pmcsc->flags & AGTIAPI_SHUT_DOWN)
1949    {
1950      AGTIAPI_PRINTK( "agtiapi_cam_action: shutdown, XPT_SCSI_IO 0x%x\n",
1951                      XPT_SCSI_IO );
1952      ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1953      break;
1954    }
1955    else
1956    {
1957      AGTIAPI_IO( "agtiapi_cam_action: Zero XPT_SCSI_IO 0x%x, doing IOs\n",
1958                  XPT_SCSI_IO );
1959      agtiapi_QueueCmnd_( pmcsc, ccb );
1960      return;
1961    }
1962  }
1963
1964  case XPT_CALC_GEOMETRY:
1965  {
1966	  cam_calc_geometry(&ccb->ccg, 1);
1967	  ccb->ccb_h.status = CAM_REQ_CMP;
1968	  break;
1969  }
1970  default:
1971  {
1972    /*
1973      XPT_SET_TRAN_SETTINGS
1974    */
1975    AGTIAPI_IO( "agtiapi_cam_action: default function code 0x%x\n",
1976                ccb->ccb_h.func_code );
1977    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1978    break;
1979  }
1980  } /* switch */
1981  xpt_done(ccb);
1982}
1983
1984
1985/******************************************************************************
1986agtiapi_GetCCB()
1987
1988Purpose:
1989  Get a ccb from free list or allocate a new one
1990Parameters:
1991  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA structure
1992Return:
1993  Pointer to a ccb structure, or NULL if not available
1994Note:
1995******************************************************************************/
1996STATIC pccb_t agtiapi_GetCCB( struct agtiapi_softc *pmcsc )
1997{
1998  pccb_t pccb;
1999
2000  AGTIAPI_IO( "agtiapi_GetCCB: start\n" );
2001
2002  AG_LOCAL_LOCK( &pmcsc->ccbLock );
2003
2004  /* get the ccb from the head of the free list */
2005  if ((pccb = (pccb_t)pmcsc->ccbFreeList) != NULL)
2006  {
2007    pmcsc->ccbFreeList = (caddr_t *)pccb->pccbNext;
2008    pccb->pccbNext = NULL;
2009    pccb->flags = ACTIVE;
2010    pccb->startTime = 0;
2011    pmcsc->activeCCB++;
2012    AGTIAPI_IO( "agtiapi_GetCCB: re-allocated ccb %p\n", pccb );
2013  }
2014  else
2015  {
2016    AGTIAPI_PRINTK( "agtiapi_GetCCB: kmalloc ERROR - no ccb allocated\n" );
2017  }
2018
2019  AG_LOCAL_UNLOCK( &pmcsc->ccbLock );
2020  return pccb;
2021}
2022
2023/******************************************************************************
2024agtiapi_QueueCmnd_()
2025
2026Purpose:
2027  Calls for sending CCB and excuting on HBA.
2028Parameters:
2029  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2030  union ccb * ccb (IN)      Pointer to CAM ccb data structure
2031Return:
2032  0 - Command is pending to execute
2033  1 - Command returned without further process
2034Note:
2035******************************************************************************/
2036int agtiapi_QueueCmnd_(struct agtiapi_softc *pmcsc, union ccb * ccb)
2037{
2038  struct ccb_scsiio *csio = &ccb->csio;
2039  pccb_t     pccb = agNULL; // call dequeue
2040  int        status = tiSuccess;
2041  U32        Channel = CMND_TO_CHANNEL(ccb);
2042  U32        TID     = CMND_TO_TARGET(ccb);
2043  U32        LUN     = CMND_TO_LUN(ccb);
2044
2045  AGTIAPI_IO( "agtiapi_QueueCmnd_: start\n" );
2046
2047  /* no support for CBD > 16 */
2048  if (csio->cdb_len > 16)
2049  {
2050    AGTIAPI_PRINTK( "agtiapi_QueueCmnd_: unsupported CDB length %d\n",
2051                    csio->cdb_len );
2052    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2053    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2054    ccb->ccb_h.status |= CAM_REQ_INVALID;//CAM_REQ_CMP;
2055    xpt_done(ccb);
2056    return tiError;
2057  }
2058  if (TID < 0 || TID >= maxTargets)
2059  {
2060    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: INVALID TID ERROR\n");
2061    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2062    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2063    ccb->ccb_h.status |= CAM_DEV_NOT_THERE;//CAM_REQ_CMP;
2064    xpt_done(ccb);
2065    return tiError;
2066  }
2067  /* get a ccb */
2068  if ((pccb = agtiapi_GetCCB(pmcsc)) == NULL)
2069  {
2070    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: GetCCB ERROR\n");
2071    if (pmcsc != NULL)
2072    {
2073      ag_device_t *targ;
2074      TID = INDEX(pmcsc, TID);
2075      targ   = &pmcsc->pDevList[TID];
2076      agtiapi_adjust_queue_depth(ccb->ccb_h.path,targ->qdepth);
2077    }
2078    ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2079    ccb->ccb_h.status &= ~CAM_STATUS_MASK;
2080    ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2081    xpt_done(ccb);
2082    return tiBusy;
2083  }
2084  pccb->pmcsc = pmcsc;
2085  /* initialize Command Control Block (CCB) */
2086  pccb->targetId   = TID;
2087  pccb->lun        = LUN;
2088  pccb->channel    = Channel;
2089  pccb->ccb        = ccb; /* for struct scsi_cmnd */
2090  pccb->senseLen   = csio->sense_len;
2091  pccb->startTime  = ticks;
2092  pccb->pSenseData = (caddr_t) &csio->sense_data;
2093  pccb->tiSuperScsiRequest.flags = 0;
2094
2095  /* each channel is reserved for different addr modes */
2096  pccb->addrMode = agtiapi_AddrModes[Channel];
2097
2098  status = agtiapi_PrepareSGList(pmcsc, pccb);
2099  if (status != tiSuccess)
2100  {
2101    AGTIAPI_PRINTK("agtiapi_QueueCmnd_: agtiapi_PrepareSGList failure\n");
2102    agtiapi_FreeCCB(pmcsc, pccb);
2103    if (status == tiReject)
2104    {
2105      ccb->ccb_h.status = CAM_REQ_INVALID;
2106    }
2107    else
2108    {
2109      ccb->ccb_h.status = CAM_REQ_CMP;
2110    }
2111    xpt_done( ccb );
2112    return tiError;
2113  }
2114  return status;
2115}
2116
2117/******************************************************************************
2118agtiapi_DumpCDB()
2119
2120Purpose:
2121  Prints out CDB
2122Parameters:
2123  const char *ptitle (IN)  A string to be printed
2124  ccb_t *pccb (IN)         A pointer to the driver's own CCB, not CAM's CCB
2125Return:
2126Note:
2127******************************************************************************/
2128STATIC void agtiapi_DumpCDB(const char *ptitle, ccb_t *pccb)
2129{
2130  union ccb *ccb;
2131  struct ccb_scsiio *csio;
2132  bit8  cdb[64];
2133  int len;
2134
2135  if (pccb == NULL)
2136  {
2137    printf( "agtiapi_DumpCDB: no pccb here \n" );
2138    panic("agtiapi_DumpCDB: pccb is NULL. called from %s\n", ptitle);
2139    return;
2140  }
2141  ccb = pccb->ccb;
2142  if (ccb == NULL)
2143  {
2144    printf( "agtiapi_DumpCDB: no ccb here \n" );
2145    panic( "agtiapi_DumpCDB: pccb %p ccb %p flags %d ccb NULL! "
2146           "called from %s\n",
2147           pccb, pccb->ccb, pccb->flags, ptitle );
2148    return;
2149  }
2150  csio = &ccb->csio;
2151  if (csio == NULL)
2152  {
2153    printf( "agtiapi_DumpCDB: no csio here \n" );
2154    panic( "agtiapi_DumpCDB: pccb%p ccb%p flags%d csio NULL! called from %s\n",
2155           pccb, pccb->ccb, pccb->flags, ptitle );
2156    return;
2157  }
2158  len = MIN(64, csio->cdb_len);
2159  if (csio->ccb_h.flags & CAM_CDB_POINTER)
2160  {
2161    bcopy(csio->cdb_io.cdb_ptr, &cdb[0], len);
2162  }
2163  else
2164  {
2165    bcopy(csio->cdb_io.cdb_bytes, &cdb[0], len);
2166  }
2167
2168  AGTIAPI_IO( "agtiapi_DumpCDB: pccb%p CDB0x%x csio->cdb_len %d"
2169              " len %d from %s\n",
2170              pccb, cdb[0],
2171              csio->cdb_len,
2172              len,
2173              ptitle );
2174  return;
2175}
2176
2177/******************************************************************************
2178agtiapi_DoSoftReset()
2179
2180Purpose:
2181  Do card reset
2182Parameters:
2183  *data (IN)               point to pmcsc (struct agtiapi_softc *)
2184Return:
2185Note:
2186******************************************************************************/
2187int agtiapi_DoSoftReset (struct agtiapi_softc *pmcsc)
2188{
2189  int  ret;
2190  unsigned long flags;
2191
2192  pmcsc->flags |=  AGTIAPI_SOFT_RESET;
2193  AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
2194  ret = agtiapi_ResetCard( pmcsc, &flags );
2195  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
2196
2197  if( ret != AGTIAPI_SUCCESS )
2198    return tiError;
2199
2200  return SUCCESS;
2201}
2202
2203/******************************************************************************
2204agtiapi_CheckIOTimeout()
2205
2206Purpose:
2207  Timeout function for SCSI IO or TM
2208Parameters:
2209  *data (IN)               point to pCard (ag_card_t *)
2210Return:
2211Note:
2212******************************************************************************/
2213STATIC void agtiapi_CheckIOTimeout(void *data)
2214{
2215  U32       status = AGTIAPI_SUCCESS;
2216  ccb_t *pccb;
2217  struct agtiapi_softc *pmcsc;
2218  pccb_t pccb_curr;
2219  pccb_t pccb_next;
2220  pmcsc = (struct agtiapi_softc *)data;
2221
2222  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Enter\n");
2223
2224  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Active CCB %d\n", pmcsc->activeCCB);
2225
2226  pccb = (pccb_t)pmcsc->ccbChainList;
2227
2228  /* if link is down, do nothing */
2229  if ((pccb == NULL) || (pmcsc->activeCCB == 0))
2230  {
2231  //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: goto restart_timer\n");
2232    goto restart_timer;
2233  }
2234
2235  AG_SPIN_LOCK_IRQ(agtiapi_host_lock, flags);
2236  if (pmcsc->flags & AGTIAPI_SHUT_DOWN)
2237    goto ext;
2238
2239  pccb_curr = pccb;
2240
2241  /* Walk thorugh the IO Chain linked list to find the pending io */
2242  /* Set the TM flag based on the pccb type, i.e SCSI IO or TM cmd */
2243  while (pccb_curr != NULL)
2244  {
2245    /* start from 1st ccb in the chain */
2246    pccb_next = pccb_curr->pccbChainNext;
2247    if( (pccb_curr->flags == 0) || (pccb_curr->tiIORequest.tdData == NULL) ||
2248        (pccb_curr->startTime == 0) /* && (pccb->startTime == 0) */)
2249    {
2250      //AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: move to next element\n");
2251    }
2252    else if ( ( (ticks-pccb_curr->startTime) >= ag_timeout_secs ) &&
2253              !(pccb_curr->flags & TIMEDOUT) )
2254    {
2255      AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout: pccb %p timed out, call TM "
2256		      "function -- flags=%x startTime=%ld tdData = %p\n",
2257		      pccb_curr, pccb_curr->flags, pccb->startTime,
2258		      pccb_curr->tiIORequest.tdData );
2259      pccb_curr->flags |= TIMEDOUT;
2260      status = agtiapi_StartTM(pmcsc, pccb_curr);
2261      if (status == AGTIAPI_SUCCESS)
2262      {
2263        AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout: TM Request sent with "
2264                        "success\n" );
2265        goto restart_timer;
2266      }
2267      else
2268      {
2269#ifdef AGTIAPI_LOCAL_RESET
2270        /* abort request did not go through */
2271        AGTIAPI_PRINTK("agtiapi_CheckIOTimeout: Abort request failed\n");
2272        /* TODO: call Soft reset here */
2273        AGTIAPI_PRINTK( "agtiapi_CheckIOTimeout:in agtiapi_CheckIOTimeout() "
2274                        "abort request did not go thru ==> soft reset#7, then "
2275                        "restart timer\n" );
2276        agtiapi_DoSoftReset (pmcsc);
2277        goto restart_timer;
2278#endif
2279      }
2280    }
2281    pccb_curr = pccb_next;
2282  }
2283restart_timer:
2284  callout_reset(&pmcsc->IO_timer, 1*hz, agtiapi_CheckIOTimeout, pmcsc);
2285
2286ext:
2287  AG_SPIN_UNLOCK_IRQ(agtiapi_host_lock, flags);
2288  return;
2289}
2290
2291/******************************************************************************
2292agtiapi_StartTM()
2293
2294Purpose:
2295  DDI calls for aborting outstanding IO command
2296Parameters:
2297  struct scsi_cmnd *pccb (IN) Pointer to the command to be aborted
2298  unsigned long flags (IN/out) spinlock flags used in locking from
2299                              calling layers
2300Return:
2301  AGTIAPI_SUCCESS  - success
2302  AGTIAPI_FAIL     - fail
2303******************************************************************************/
2304int
2305agtiapi_StartTM(struct agtiapi_softc *pCard, ccb_t *pccb)
2306{
2307  ccb_t     *pTMccb = NULL;
2308  U32       status = AGTIAPI_SUCCESS;
2309  ag_device_t      *pDevice = NULL;
2310  U32       TMstatus = tiSuccess;
2311  AGTIAPI_PRINTK( "agtiapi_StartTM: pccb %p, pccb->flags %x\n",
2312                  pccb, pccb->flags );
2313  if (pccb == NULL)
2314  {
2315    AGTIAPI_PRINTK("agtiapi_StartTM: %p not found\n",pccb);
2316    status = AGTIAPI_SUCCESS;
2317    goto ext;
2318  }
2319  if (!pccb->tiIORequest.tdData)
2320  {
2321    /* should not be the case */
2322    AGTIAPI_PRINTK("agtiapi_StartTM: ccb %p flag 0x%x tid %d no tdData "
2323                   "ERROR\n", pccb, pccb->flags, pccb->targetId);
2324    status = AGTIAPI_FAIL;
2325  }
2326  else
2327  {
2328    /* If timedout CCB is TM_ABORT_TASK command, issue LocalAbort first to
2329       clear pending TM_ABORT_TASK */
2330    /* Else Device State will not be put back to Operational, (refer FW) */
2331    if (pccb->flags & TASK_MANAGEMENT)
2332    {
2333      if (tiINIIOAbort(&pCard->tiRoot, &pccb->tiIORequest) != tiSuccess)
2334      {
2335        AGTIAPI_PRINTK( "agtiapi_StartTM: LocalAbort Request for Abort_TASK "
2336                        "TM failed\n" );
2337        /* TODO: call Soft reset here */
2338        AGTIAPI_PRINTK( "agtiapi_StartTM: in agtiapi_StartTM() abort "
2339			"tiINIIOAbort() failed ==> soft reset#8\n" );
2340        agtiapi_DoSoftReset( pCard );
2341      }
2342      else
2343      {
2344        AGTIAPI_PRINTK( "agtiapi_StartTM: LocalAbort for Abort_TASK TM "
2345                        "Request sent\n" );
2346        status = AGTIAPI_SUCCESS;
2347      }
2348    }
2349    else
2350    {
2351      /* get a ccb */
2352      if ((pTMccb = agtiapi_GetCCB(pCard)) == NULL)
2353      {
2354        AGTIAPI_PRINTK("agtiapi_StartTM: TM resource unavailable!\n");
2355        status = AGTIAPI_FAIL;
2356        goto ext;
2357      }
2358      pTMccb->pmcsc = pCard;
2359      pTMccb->targetId = pccb->targetId;
2360      pTMccb->devHandle = pccb->devHandle;
2361      if (pTMccb->targetId >= pCard->devDiscover)
2362      {
2363        AGTIAPI_PRINTK("agtiapi_StartTM: Incorrect dev Id in TM!\n");
2364        status = AGTIAPI_FAIL;
2365        goto ext;
2366      }
2367      if (pTMccb->targetId < 0 || pTMccb->targetId >= maxTargets)
2368      {
2369        return AGTIAPI_FAIL;
2370      }
2371      if (INDEX(pCard, pTMccb->targetId) >= maxTargets)
2372      {
2373        return AGTIAPI_FAIL;
2374      }
2375      pDevice = &pCard->pDevList[INDEX(pCard, pTMccb->targetId)];
2376      if ((pDevice == NULL) || !(pDevice->flags & ACTIVE))
2377      {
2378        return AGTIAPI_FAIL;
2379      }
2380
2381      /* save pending io to issue local abort at Task mgmt CB */
2382      pTMccb->pccbIO = pccb;
2383      AGTIAPI_PRINTK( "agtiapi_StartTM: pTMccb %p flag %x tid %d via TM "
2384                      "request !\n",
2385                      pTMccb, pTMccb->flags, pTMccb->targetId );
2386      pTMccb->flags &= ~(TASK_SUCCESS | ACTIVE);
2387      pTMccb->flags |= TASK_MANAGEMENT;
2388      TMstatus = tiINITaskManagement(&pCard->tiRoot,
2389                              pccb->devHandle,
2390                              AG_ABORT_TASK,
2391                              &pccb->tiSuperScsiRequest.scsiCmnd.lun,
2392                              &pccb->tiIORequest,
2393                              &pTMccb->tiIORequest);
2394      if (TMstatus == tiSuccess)
2395      {
2396        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request success ccb "
2397                        "%p, pTMccb %p\n",
2398                        pccb, pTMccb );
2399        pTMccb->startTime = ticks;
2400        status = AGTIAPI_SUCCESS;
2401      }
2402      else if (TMstatus == tiIONoDevice)
2403      {
2404        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request tiIONoDevice ccb "
2405                        "%p, pTMccb %p\n",
2406                        pccb, pTMccb );
2407        status = AGTIAPI_SUCCESS;
2408      }
2409      else
2410      {
2411        AGTIAPI_PRINTK( "agtiapi_StartTM: TM_ABORT_TASK request failed ccb %p, "
2412                        "pTMccb %p\n",
2413                        pccb, pTMccb );
2414        status = AGTIAPI_FAIL;
2415        agtiapi_FreeTMCCB(pCard, pTMccb);
2416        /* TODO */
2417        /* call TM_TARGET_RESET */
2418      }
2419    }
2420  }
2421  ext:
2422  AGTIAPI_PRINTK("agtiapi_StartTM: return %d flgs %x\n", status,
2423                 (pccb) ? pccb->flags : -1);
2424  return status;
2425} /* agtiapi_StartTM */
2426
2427#if __FreeBSD_version > 901000
2428/******************************************************************************
2429agtiapi_PrepareSGList()
2430
2431Purpose:
2432  This function prepares scatter-gather list for the given ccb
2433Parameters:
2434  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2435  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
2436Return:
2437  0 - success
2438  1 - failure
2439
2440Note:
2441******************************************************************************/
2442static int agtiapi_PrepareSGList(struct agtiapi_softc *pmcsc, ccb_t *pccb)
2443{
2444  union ccb *ccb = pccb->ccb;
2445  struct ccb_scsiio *csio = &ccb->csio;
2446  struct ccb_hdr *ccbh = &ccb->ccb_h;
2447  AGTIAPI_IO( "agtiapi_PrepareSGList: start\n" );
2448
2449//  agtiapi_DumpCDB("agtiapi_PrepareSGList", pccb);
2450  AGTIAPI_IO( "agtiapi_PrepareSGList: dxfer_len %d\n", csio->dxfer_len );
2451
2452  if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE)
2453  {
2454	switch((ccbh->flags & CAM_DATA_MASK))
2455    	{
2456          int error;
2457          struct bus_dma_segment seg;
2458	  case CAM_DATA_VADDR:
2459        /* Virtual address that needs to translated into one or more physical address ranges. */
2460          //  int error;
2461            //  AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
2462            AGTIAPI_IO( "agtiapi_PrepareSGList: virtual address\n" );
2463            error = bus_dmamap_load( pmcsc->buffer_dmat,
2464                                 pccb->CCB_dmamap,
2465                                 csio->data_ptr,
2466                                 csio->dxfer_len,
2467                                 agtiapi_PrepareSGListCB,
2468                                 pccb,
2469                                 BUS_DMA_NOWAIT/* 0 */ );
2470            //  AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
2471
2472	    if (error == EINPROGRESS)
2473	    {
2474          /* So as to maintain ordering, freeze the controller queue until our mapping is returned. */
2475          AGTIAPI_PRINTK("agtiapi_PrepareSGList: EINPROGRESS\n");
2476          xpt_freeze_simq(pmcsc->sim, 1);
2477          pmcsc->SimQFrozen = agTRUE;
2478          ccbh->status |= CAM_RELEASE_SIMQ;
2479        }
2480	break;
2481	case CAM_DATA_PADDR:
2482	    /* We have been given a pointer to single physical buffer. */
2483	    /* pccb->tiSuperScsiRequest.sglVirtualAddr = seg.ds_addr; */
2484          //struct bus_dma_segment seg;
2485          AGTIAPI_PRINTK("agtiapi_PrepareSGList: physical address\n");
2486          seg.ds_addr =
2487            (bus_addr_t)(vm_offset_t)csio->data_ptr;
2488             seg.ds_len = csio->dxfer_len;
2489             // * 0xFF to be defined
2490             agtiapi_PrepareSGListCB(pccb, &seg, 1, 0xAABBCCDD);
2491	     break;
2492	default:
2493           AGTIAPI_PRINTK("agtiapi_PrepareSGList: unexpected case\n");
2494           return tiReject;
2495    }
2496  }
2497  else
2498  {
2499    agtiapi_PrepareSGListCB(pccb, NULL, 0, 0xAAAAAAAA);
2500  }
2501  return tiSuccess;
2502}
2503#else
2504/******************************************************************************
2505agtiapi_PrepareSGList()
2506
2507Purpose:
2508  This function prepares scatter-gather list for the given ccb
2509Parameters:
2510  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
2511  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
2512Return:
2513  0 - success
2514  1 - failure
2515
2516Note:
2517******************************************************************************/
2518static int agtiapi_PrepareSGList(struct agtiapi_softc *pmcsc, ccb_t *pccb)
2519{
2520  union ccb *ccb = pccb->ccb;
2521  struct ccb_scsiio *csio = &ccb->csio;
2522  struct ccb_hdr *ccbh = &ccb->ccb_h;
2523  AGTIAPI_IO( "agtiapi_PrepareSGList: start\n" );
2524//  agtiapi_DumpCDB("agtiapi_PrepareSGList", pccb);
2525  AGTIAPI_IO( "agtiapi_PrepareSGList: dxfer_len %d\n", csio->dxfer_len );
2526
2527  if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE)
2528  {
2529    if ((ccbh->flags & CAM_SCATTER_VALID) == 0)
2530    {
2531      /* We've been given a pointer to a single buffer. */
2532      if ((ccbh->flags & CAM_DATA_PHYS) == 0)
2533      {
2534        /* Virtual address that needs to translated into one or more physical address ranges. */
2535        int error;
2536      //  AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
2537        AGTIAPI_IO( "agtiapi_PrepareSGList: virtual address\n" );
2538        error = bus_dmamap_load( pmcsc->buffer_dmat,
2539                                 pccb->CCB_dmamap,
2540                                 csio->data_ptr,
2541                                 csio->dxfer_len,
2542                                 agtiapi_PrepareSGListCB,
2543                                 pccb,
2544                                 BUS_DMA_NOWAIT/* 0 */ );
2545      //  AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
2546
2547	    if (error == EINPROGRESS)
2548	    {
2549          /* So as to maintain ordering, freeze the controller queue until our mapping is returned. */
2550          AGTIAPI_PRINTK("agtiapi_PrepareSGList: EINPROGRESS\n");
2551          xpt_freeze_simq(pmcsc->sim, 1);
2552          pmcsc->SimQFrozen = agTRUE;
2553          ccbh->status |= CAM_RELEASE_SIMQ;
2554        }
2555      }
2556      else
2557      {
2558	    /* We have been given a pointer to single physical buffer. */
2559	    /* pccb->tiSuperScsiRequest.sglVirtualAddr = seg.ds_addr; */
2560        struct bus_dma_segment seg;
2561        AGTIAPI_PRINTK("agtiapi_PrepareSGList: physical address\n");
2562        seg.ds_addr =
2563          (bus_addr_t)(vm_offset_t)csio->data_ptr;
2564        seg.ds_len = csio->dxfer_len;
2565        // * 0xFF to be defined
2566        agtiapi_PrepareSGListCB(pccb, &seg, 1, 0xAABBCCDD);
2567      }
2568    }
2569    else
2570    {
2571
2572      AGTIAPI_PRINTK("agtiapi_PrepareSGList: unexpected case\n");
2573      return tiReject;
2574    }
2575  }
2576  else
2577  {
2578    agtiapi_PrepareSGListCB(pccb, NULL, 0, 0xAAAAAAAA);
2579  }
2580  return tiSuccess;
2581}
2582
2583#endif
2584/******************************************************************************
2585agtiapi_PrepareSGListCB()
2586
2587Purpose:
2588  Callback function for bus_dmamap_load()
2589  This fuctions sends IO to LL layer.
2590Parameters:
2591  void *arg (IN)                Pointer to the HBA data structure
2592  bus_dma_segment_t *segs (IN)  Pointer to dma segment
2593  int nsegs (IN)                number of dma segment
2594  int error (IN)                error
2595Return:
2596Note:
2597******************************************************************************/
2598static void agtiapi_PrepareSGListCB( void *arg,
2599                                     bus_dma_segment_t *segs,
2600                                     int nsegs,
2601                                     int error )
2602{
2603  pccb_t     pccb = arg;
2604  union ccb *ccb = pccb->ccb;
2605  struct ccb_scsiio *csio = &ccb->csio;
2606
2607  struct agtiapi_softc *pmcsc;
2608  tiIniScsiCmnd_t *pScsiCmnd;
2609  bit32 i;
2610  bus_dmasync_op_t op;
2611  U32_64     phys_addr;
2612  U08        *CDB;
2613  int        io_is_encryptable = 0;
2614  unsigned long long start_lba = 0;
2615  ag_device_t *pDev;
2616  U32        TID     = CMND_TO_TARGET(ccb);
2617
2618  AGTIAPI_IO( "agtiapi_PrepareSGListCB: start, nsegs %d error 0x%x\n",
2619              nsegs, error );
2620  pmcsc = pccb->pmcsc;
2621
2622  if (error != tiSuccess)
2623  {
2624    if (error == 0xAABBCCDD || error == 0xAAAAAAAA)
2625    {
2626      // do nothing
2627    }
2628    else
2629    {
2630      AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: error status 0x%x\n", error);
2631      bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2632      agtiapi_FreeCCB(pmcsc, pccb);
2633      if (error == EFBIG)
2634        ccb->ccb_h.status = CAM_REQ_TOO_BIG;
2635      else
2636        ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2637      xpt_done(ccb);
2638      return;
2639    }
2640  }
2641
2642  if (nsegs > AGTIAPI_MAX_DMA_SEGS)
2643  {
2644    AGTIAPI_PRINTK( "agtiapi_PrepareSGListCB: over the limit. nsegs %d"
2645                    " AGTIAPI_MAX_DMA_SEGS %d\n",
2646                    nsegs, AGTIAPI_MAX_DMA_SEGS );
2647    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
2648    agtiapi_FreeCCB(pmcsc, pccb);
2649    ccb->ccb_h.status = CAM_REQ_TOO_BIG;
2650    xpt_done(ccb);
2651    return;
2652  }
2653
2654
2655  /* fill in IO information */
2656  pccb->dataLen = csio->dxfer_len;
2657
2658  /* start fill in sgl structure */
2659  if (nsegs == 1 && error == 0xAABBCCDD)
2660  {
2661    /* to be tested */
2662    /* A single physical buffer */
2663    AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: nsegs is 1\n");
2664    CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, segs[0].ds_addr);
2665    pccb->tiSuperScsiRequest.agSgl1.len   = htole32(pccb->dataLen);
2666    pccb->tiSuperScsiRequest.agSgl1.type  = htole32(tiSgl);
2667    pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)segs->ds_addr;
2668    pccb->numSgElements = 1;
2669  }
2670  else if (nsegs == 0 && error == 0xAAAAAAAA)
2671  {
2672    /* no data transfer */
2673    AGTIAPI_IO( "agtiapi_PrepareSGListCB: no data transfer\n" );
2674    pccb->tiSuperScsiRequest.agSgl1.len = 0;
2675    pccb->dataLen = 0;
2676    pccb->numSgElements = 0;
2677  }
2678  else
2679  {
2680    /* virtual/logical buffer */
2681    if (nsegs == 1)
2682    {
2683      pccb->dataLen = segs[0].ds_len;
2684
2685      CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, segs[0].ds_addr);
2686      pccb->tiSuperScsiRequest.agSgl1.type = htole32(tiSgl);
2687      pccb->tiSuperScsiRequest.agSgl1.len = htole32(segs[0].ds_len);
2688      pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)csio->data_ptr;
2689      pccb->numSgElements = nsegs;
2690
2691    }
2692    else
2693    {
2694      pccb->dataLen = 0;
2695      /* loop */
2696      for (i = 0; i < nsegs; i++)
2697      {
2698        pccb->sgList[i].len = htole32(segs[i].ds_len);
2699        CPU_TO_LE32(pccb->sgList[i], segs[i].ds_addr);
2700        pccb->sgList[i].type = htole32(tiSgl);
2701        pccb->dataLen += segs[i].ds_len;
2702
2703      } /* for */
2704      pccb->numSgElements = nsegs;
2705      /* set up sgl buffer address */
2706      CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1,  pccb->tisgl_busaddr);
2707      pccb->tiSuperScsiRequest.agSgl1.type = htole32(tiSglList);
2708      pccb->tiSuperScsiRequest.agSgl1.len = htole32(pccb->dataLen);
2709      pccb->tiSuperScsiRequest.sglVirtualAddr = (void *)csio->data_ptr;
2710      pccb->numSgElements = nsegs;
2711    } /* else */
2712  }
2713
2714  /* set data transfer direction */
2715  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2716  {
2717    op = BUS_DMASYNC_PREWRITE;
2718    pccb->tiSuperScsiRequest.dataDirection = tiDirectionOut;
2719  }
2720  else
2721  {
2722    op = BUS_DMASYNC_PREREAD;
2723    pccb->tiSuperScsiRequest.dataDirection = tiDirectionIn;
2724  }
2725
2726  pScsiCmnd = &pccb->tiSuperScsiRequest.scsiCmnd;
2727
2728  pScsiCmnd->expDataLength = pccb->dataLen;
2729
2730  if (csio->ccb_h.flags & CAM_CDB_POINTER)
2731  {
2732    bcopy(csio->cdb_io.cdb_ptr, &pScsiCmnd->cdb[0], csio->cdb_len);
2733  }
2734  else
2735  {
2736    bcopy(csio->cdb_io.cdb_bytes, &pScsiCmnd->cdb[0],csio->cdb_len);
2737  }
2738
2739  CDB = &pScsiCmnd->cdb[0];
2740
2741  switch (CDB[0])
2742  {
2743  case REQUEST_SENSE:  /* requires different buffer */
2744    /* This code should not be excercised because SAS support auto sense
2745       For the completeness, vtophys() is still used here.
2746     */
2747    AGTIAPI_PRINTK("agtiapi_PrepareSGListCB: QueueCmnd - REQUEST SENSE new\n");
2748    pccb->tiSuperScsiRequest.agSgl1.len = htole32(pccb->senseLen);
2749    phys_addr = vtophys(&csio->sense_data);
2750    CPU_TO_LE32(pccb->tiSuperScsiRequest.agSgl1, phys_addr);
2751    pccb->tiSuperScsiRequest.agSgl1.type  = htole32(tiSgl);
2752    pccb->dataLen = pccb->senseLen;
2753    pccb->numSgElements = 1;
2754    break;
2755  case INQUIRY:
2756    /* only using lun 0 for device type detection */
2757    pccb->flags |= AGTIAPI_INQUIRY;
2758    break;
2759  case TEST_UNIT_READY:
2760  case RESERVE:
2761  case RELEASE:
2762  case START_STOP:
2763  	pccb->tiSuperScsiRequest.agSgl1.len = 0;
2764    pccb->dataLen = 0;
2765    break;
2766  case READ_6:
2767  case WRITE_6:
2768    /* Extract LBA */
2769    start_lba = ((CDB[1] & 0x1f) << 16) |
2770                 (CDB[2] << 8)          |
2771                 (CDB[3]);
2772#ifdef HIALEAH_ENCRYPTION
2773    io_is_encryptable = 1;
2774#endif
2775    break;
2776  case READ_10:
2777  case WRITE_10:
2778  case READ_12:
2779  case WRITE_12:
2780    /* Extract LBA */
2781    start_lba = (CDB[2] << 24) |
2782                (CDB[3] << 16) |
2783                (CDB[4] << 8)  |
2784                (CDB[5]);
2785#ifdef HIALEAH_ENCRYPTION
2786    io_is_encryptable = 1;
2787#endif
2788    break;
2789  case READ_16:
2790  case WRITE_16:
2791    /* Extract LBA */
2792    start_lba = (CDB[2] << 24) |
2793                (CDB[3] << 16) |
2794                (CDB[4] << 8)  |
2795                (CDB[5]);
2796    start_lba <<= 32;
2797    start_lba |= ((CDB[6] << 24) |
2798                  (CDB[7] << 16) |
2799                  (CDB[8] << 8)  |
2800                  (CDB[9]));
2801#ifdef HIALEAH_ENCRYPTION
2802    io_is_encryptable = 1;
2803#endif
2804    break;
2805  default:
2806    break;
2807  }
2808
2809  /* fill device lun based one address mode */
2810  agtiapi_SetLunField(pccb);
2811
2812  if (pccb->targetId < 0 || pccb->targetId >= maxTargets)
2813  {
2814    pccb->ccbStatus   = tiIOFailed;
2815    pccb->scsiStatus  = tiDetailNoLogin;
2816    agtiapi_FreeCCB(pmcsc, pccb);
2817    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
2818    xpt_done(ccb);
2819    pccb->ccb         = NULL;
2820    return;
2821  }
2822  if (INDEX(pmcsc, pccb->targetId) >= maxTargets)
2823  {
2824    pccb->ccbStatus   = tiIOFailed;
2825    pccb->scsiStatus  = tiDetailNoLogin;
2826    agtiapi_FreeCCB(pmcsc, pccb);
2827    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
2828    xpt_done(ccb);
2829    pccb->ccb         = NULL;
2830    return;
2831  }
2832  pDev = &pmcsc->pDevList[INDEX(pmcsc, pccb->targetId)];
2833
2834#if 1
2835  if ((pmcsc->flags & EDC_DATA) &&
2836      (pDev->flags & EDC_DATA))
2837  {
2838    /*
2839     * EDC support:
2840     *
2841     * Possible command supported -
2842     * READ_6, READ_10, READ_12, READ_16, READ_LONG, READ_BUFFER,
2843     * READ_DEFECT_DATA, etc.
2844     * WRITE_6, WRITE_10, WRITE_12, WRITE_16, WRITE_LONG, WRITE_LONG2,
2845     * WRITE_BUFFER, WRITE_VERIFY, WRITE_VERIFY_12, etc.
2846     *
2847     * Do some data length adjustment and set chip operation instruction.
2848     */
2849    switch (CDB[0])
2850    {
2851      case READ_6:
2852      case READ_10:
2853      case READ_12:
2854      case READ_16:
2855        //  BUG_ON(pccb->tiSuperScsiRequest.flags & TI_SCSI_INITIATOR_ENCRYPT);
2856#ifdef AGTIAPI_TEST_DIF
2857        pccb->tiSuperScsiRequest.flags |= TI_SCSI_INITIATOR_DIF;
2858#endif
2859        pccb->flags |= EDC_DATA;
2860
2861#ifdef TEST_VERIFY_AND_FORWARD
2862        pccb->tiSuperScsiRequest.Dif.flags =
2863          DIF_VERIFY_FORWARD | DIF_UDT_REF_BLOCK_COUNT;
2864        if(pDev->sector_size == 520) {
2865            pScsiCmnd->expDataLength += (pccb->dataLen / 512) * 8;
2866        } else if(pDev->sector_size == 4104) {
2867            pScsiCmnd->expDataLength += (pccb->dataLen / 4096) * 8;
2868        }
2869#else
2870#ifdef AGTIAPI_TEST_DIF
2871        pccb->tiSuperScsiRequest.Dif.flags =
2872          DIF_VERIFY_DELETE | DIF_UDT_REF_BLOCK_COUNT;
2873#endif
2874#endif
2875#ifdef AGTIAPI_TEST_DIF
2876        switch(pDev->sector_size) {
2877            case 528:
2878                pccb->tiSuperScsiRequest.Dif.flags |=
2879                  ( DIF_BLOCK_SIZE_520 << 16 );
2880                break;
2881            case 4104:
2882                pccb->tiSuperScsiRequest.Dif.flags |=
2883                  ( DIF_BLOCK_SIZE_4096 << 16 );
2884                break;
2885            case 4168:
2886                pccb->tiSuperScsiRequest.Dif.flags |=
2887                  ( DIF_BLOCK_SIZE_4160 << 16 );
2888                break;
2889        }
2890
2891        if(pCard->flags & EDC_DATA_CRC)
2892            pccb->tiSuperScsiRequest.Dif.flags |= DIF_CRC_VERIFICATION;
2893
2894        /* Turn on upper 4 bits of UVM */
2895        pccb->tiSuperScsiRequest.Dif.flags |= 0x03c00000;
2896
2897#endif
2898#ifdef AGTIAPI_TEST_DPL
2899        if(agtiapi_SetupDifPerLA(pCard, pccb, start_lba) < 0) {
2900            printk(KERN_ERR "SetupDifPerLA Failed.\n");
2901            cmnd->result = SCSI_HOST(DID_ERROR);
2902            goto err;
2903        }
2904        pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = TRUE;
2905#endif
2906#ifdef AGTIAPI_TEST_DIF
2907        /* Set App Tag */
2908        pccb->tiSuperScsiRequest.Dif.udtArray[0] = 0xaa;
2909        pccb->tiSuperScsiRequest.Dif.udtArray[1] = 0xbb;
2910
2911        /* Set LBA in UDT array */
2912        if(CDB[0] == READ_6) {
2913            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[3];
2914            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[2];
2915            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[1] & 0x1f;
2916            pccb->tiSuperScsiRequest.Dif.udtArray[5] = 0;
2917        } else if(CDB[0] == READ_10 || CDB[0] == READ_12) {
2918            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2919            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2920            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2921            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2922        } else if(CDB[0] == READ_16) {
2923            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[9];
2924            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[8];
2925            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[7];
2926            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[6];
2927            /* Note: 32 bits lost */
2928        }
2929#endif
2930
2931        break;
2932      case WRITE_6:
2933      case WRITE_10:
2934      case WRITE_12:
2935      case WRITE_16:
2936        //   BUG_ON(pccb->tiSuperScsiRequest.flags & TI_SCSI_INITIATOR_ENCRYPT);
2937        pccb->flags |= EDC_DATA;
2938#ifdef AGTIAPI_TEST_DIF
2939        pccb->tiSuperScsiRequest.flags |= TI_SCSI_INITIATOR_DIF;
2940        pccb->tiSuperScsiRequest.Dif.flags =
2941          DIF_INSERT | DIF_UDT_REF_BLOCK_COUNT;
2942        switch(pDev->sector_size) {
2943            case 528:
2944                pccb->tiSuperScsiRequest.Dif.flags |=
2945                  (DIF_BLOCK_SIZE_520 << 16);
2946                break;
2947            case 4104:
2948                pccb->tiSuperScsiRequest.Dif.flags |=
2949                  ( DIF_BLOCK_SIZE_4096 << 16 );
2950                break;
2951            case 4168:
2952                pccb->tiSuperScsiRequest.Dif.flags |=
2953                  ( DIF_BLOCK_SIZE_4160 << 16 );
2954                break;
2955        }
2956
2957        /* Turn on upper 4 bits of UUM */
2958        pccb->tiSuperScsiRequest.Dif.flags |= 0xf0000000;
2959#endif
2960#ifdef AGTIAPI_TEST_DPL
2961        if(agtiapi_SetupDifPerLA(pCard, pccb, start_lba) < 0) {
2962            printk(KERN_ERR "SetupDifPerLA Failed.\n");
2963            cmnd->result = SCSI_HOST(DID_ERROR);
2964            goto err;
2965        }
2966        pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = TRUE;
2967#endif
2968#ifdef AGTIAPI_TEST_DIF
2969        /* Set App Tag */
2970        pccb->tiSuperScsiRequest.Dif.udtArray[0] = 0xaa;
2971        pccb->tiSuperScsiRequest.Dif.udtArray[1] = 0xbb;
2972
2973        /* Set LBA in UDT array */
2974        if(CDB[0] == WRITE_6) {
2975            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[3];
2976            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[2];
2977            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[1] & 0x1f;
2978        } else if(CDB[0] == WRITE_10 || CDB[0] == WRITE_12) {
2979            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2980            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2981            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2982            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2983        } else if(CDB[0] == WRITE_16) {
2984            pccb->tiSuperScsiRequest.Dif.udtArray[2] = CDB[5];
2985            pccb->tiSuperScsiRequest.Dif.udtArray[3] = CDB[4];
2986            pccb->tiSuperScsiRequest.Dif.udtArray[4] = CDB[3];
2987            pccb->tiSuperScsiRequest.Dif.udtArray[5] = CDB[2];
2988            /* Note: 32 bits lost */
2989        }
2990#endif
2991        break;
2992    }
2993  }
2994#endif /* end of DIF */
2995
2996  if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
2997  {
2998    switch(csio->tag_action)
2999    {
3000    case MSG_HEAD_OF_Q_TAG:
3001      pScsiCmnd->taskAttribute = TASK_HEAD_OF_QUEUE;
3002      break;
3003    case MSG_ACA_TASK:
3004      pScsiCmnd->taskAttribute = TASK_ACA;
3005      break;
3006    case MSG_ORDERED_Q_TAG:
3007      pScsiCmnd->taskAttribute = TASK_ORDERED;
3008      break;
3009    case MSG_SIMPLE_Q_TAG: /* fall through */
3010    default:
3011      pScsiCmnd->taskAttribute = TASK_SIMPLE;
3012      break;
3013    }
3014  }
3015
3016  if (pccb->tiSuperScsiRequest.agSgl1.len != 0 && pccb->dataLen != 0)
3017  {
3018    /* should be just before start IO */
3019    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
3020  }
3021
3022  /*
3023   * If assigned pDevHandle is not available
3024   * then there is no need to send it to StartIO()
3025   */
3026  if (pccb->targetId < 0 || pccb->targetId >= maxTargets)
3027  {
3028    pccb->ccbStatus   = tiIOFailed;
3029    pccb->scsiStatus  = tiDetailNoLogin;
3030    agtiapi_FreeCCB(pmcsc, pccb);
3031    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
3032    xpt_done(ccb);
3033    pccb->ccb         = NULL;
3034    return;
3035  }
3036  TID = INDEX(pmcsc, pccb->targetId);
3037  if ((TID >= pmcsc->devDiscover) ||
3038      !(pccb->devHandle = pmcsc->pDevList[TID].pDevHandle))
3039  {
3040    /*
3041    AGTIAPI_PRINTK( "agtiapi_PrepareSGListCB: not sending ccb devH %p,"
3042                    " target %d tid %d/%d card %p ERROR pccb %p\n",
3043                    pccb->devHandle, pccb->targetId, TID,
3044                    pmcsc->devDiscover, pmcsc, pccb );
3045    */
3046    pccb->ccbStatus   = tiIOFailed;
3047    pccb->scsiStatus  = tiDetailNoLogin;
3048    agtiapi_FreeCCB(pmcsc, pccb);
3049    ccb->ccb_h.status = CAM_DEV_NOT_THERE; // ## v. CAM_FUNC_NOTAVAIL
3050    xpt_done(ccb);
3051    pccb->ccb         = NULL;
3052    return;
3053  }
3054  AGTIAPI_IO( "agtiapi_PrepareSGListCB: send ccb pccb->devHandle %p, "
3055                  "pccb->targetId %d TID %d pmcsc->devDiscover %d card %p\n",
3056                  pccb->devHandle, pccb->targetId, TID, pmcsc->devDiscover,
3057                  pmcsc );
3058#ifdef HIALEAH_ENCRYPTION
3059  if(pmcsc->encrypt && io_is_encryptable) {
3060    agtiapi_SetupEncryptedIO(pmcsc, pccb, start_lba);
3061  } else{
3062	io_is_encryptable = 0;
3063	pccb->tiSuperScsiRequest.flags = 0;
3064  }
3065#endif
3066  // put the request in send queue
3067  agtiapi_QueueCCB( pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
3068                    AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb );
3069  agtiapi_StartIO(pmcsc);
3070  return;
3071}
3072
3073/******************************************************************************
3074agtiapi_StartIO()
3075
3076Purpose:
3077  Send IO request down for processing.
3078Parameters:
3079  (struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
3080Return:
3081Note:
3082******************************************************************************/
3083STATIC void agtiapi_StartIO( struct agtiapi_softc *pmcsc )
3084{
3085  ccb_t *pccb;
3086  int TID;
3087  ag_device_t *targ;
3088
3089  AGTIAPI_IO( "agtiapi_StartIO: start\n" );
3090
3091  AG_LOCAL_LOCK( &pmcsc->sendLock );
3092  pccb = pmcsc->ccbSendHead;
3093
3094  /* if link is down, do nothing */
3095  if ((pccb == NULL) || pmcsc->flags & AGTIAPI_RESET)
3096  {
3097    AG_LOCAL_UNLOCK( &pmcsc->sendLock );
3098    AGTIAPI_PRINTK( "agtiapi_StartIO: goto ext\n" );
3099    goto ext;
3100  }
3101
3102
3103 if (pmcsc != NULL && pccb->targetId >= 0 && pccb->targetId < maxTargets)
3104  {
3105      TID = INDEX(pmcsc, pccb->targetId);
3106      targ   = &pmcsc->pDevList[TID];
3107  }
3108
3109
3110  /* clear send queue */
3111  pmcsc->ccbSendHead = NULL;
3112  pmcsc->ccbSendTail = NULL;
3113  AG_LOCAL_UNLOCK( &pmcsc->sendLock );
3114
3115  /* send all ccbs down */
3116  while (pccb)
3117  {
3118    pccb_t pccb_next;
3119    U32    status;
3120
3121    pccb_next = pccb->pccbNext;
3122    pccb->pccbNext = NULL;
3123
3124    if (!pccb->ccb)
3125    {
3126      AGTIAPI_PRINTK( "agtiapi_StartIO: pccb->ccb is NULL ERROR!\n" );
3127      pccb = pccb_next;
3128      continue;
3129    }
3130    AG_IO_DUMPCCB( pccb );
3131
3132    if (!pccb->devHandle)
3133    {
3134      agtiapi_DumpCCB( pccb );
3135      AGTIAPI_PRINTK( "agtiapi_StartIO: ccb NULL device ERROR!\n" );
3136      pccb = pccb_next;
3137      continue;
3138    }
3139    AGTIAPI_IO( "agtiapi_StartIO: ccb %p retry %d\n", pccb, pccb->retryCount );
3140
3141#ifndef ABORT_TEST
3142    if( !pccb->devHandle || !pccb->devHandle->osData || /* in rmmod case */
3143        !(((ag_device_t *)(pccb->devHandle->osData))->flags & ACTIVE))
3144    {
3145      AGTIAPI_PRINTK( "agtiapi_StartIO: device %p not active! ERROR\n",
3146                      pccb->devHandle );
3147      if( pccb->devHandle ) {
3148        AGTIAPI_PRINTK( "agtiapi_StartIO: device not active detail"
3149                        " -- osData:%p\n",
3150                        pccb->devHandle->osData );
3151        if( pccb->devHandle->osData ) {
3152          AGTIAPI_PRINTK( "agtiapi_StartIO: more device not active detail"
3153                          " -- active flag:%d\n",
3154                          ( (ag_device_t *)
3155                            (pccb->devHandle->osData))->flags & ACTIVE );
3156        }
3157      }
3158      pccb->ccbStatus  = tiIOFailed;
3159      pccb->scsiStatus = tiDetailNoLogin;
3160      agtiapi_Done( pmcsc, pccb );
3161      pccb = pccb_next;
3162      continue;
3163    }
3164#endif
3165
3166#ifdef FAST_IO_TEST
3167    status = agtiapi_FastIOTest( pmcsc, pccb );
3168#else
3169    status = tiINISuperIOStart( &pmcsc->tiRoot,
3170                                &pccb->tiIORequest,
3171                                pccb->devHandle,
3172                                &pccb->tiSuperScsiRequest,
3173                                (void *)&pccb->tdIOReqBody,
3174                                tiInterruptContext );
3175#endif
3176    switch( status )
3177    {
3178      case tiSuccess:
3179        /*
3180        static int squelchCount = 0;
3181        if ( 200000 == squelchCount++ ) // squelch prints
3182        {
3183          AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart stat tiSuccess %p\n",
3184                          pccb );
3185          squelchCount = 0; // reset count
3186        }
3187        */
3188
3189
3190        break;
3191      case tiDeviceBusy:
3192        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiDeviceBusy %p\n",
3193                        pccb->ccb );
3194#ifdef LOGEVENT
3195        agtiapi_LogEvent( pmcsc,
3196                          IOCTL_EVT_SEV_INFORMATIONAL,
3197                          0,
3198                          agNULL,
3199                          0,
3200                          "tiINIIOStart tiDeviceBusy " );
3201#endif
3202        pccb->ccbStatus = tiIOFailed;
3203        pccb->scsiStatus = tiDeviceBusy;
3204        agtiapi_Done(pmcsc, pccb);
3205        break;
3206      case tiBusy:
3207
3208        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiBusy %p\n",
3209                        pccb->ccb );
3210#ifdef LOGEVENT
3211        agtiapi_LogEvent( pmcsc,
3212                          IOCTL_EVT_SEV_INFORMATIONAL,
3213                          0,
3214                          agNULL,
3215                          0,
3216                          "tiINIIOStart tiBusy " );
3217#endif
3218
3219        pccb->ccbStatus = tiIOFailed;
3220        pccb->scsiStatus = tiBusy;
3221        agtiapi_Done(pmcsc, pccb);
3222
3223        break;
3224      case tiIONoDevice:
3225        AGTIAPI_PRINTK( "agtiapi_StartIO: tiINIIOStart status tiNoDevice %p "
3226                        "ERROR\n", pccb->ccb );
3227#ifdef LOGEVENT
3228        agtiapi_LogEvent( pmcsc,
3229                          IOCTL_EVT_SEV_INFORMATIONAL,
3230                          0,
3231                          agNULL,
3232                          0,
3233                          "tiINIIOStart invalid device handle " );
3234#endif
3235#ifndef ABORT_TEST
3236        /* return command back to OS due to no device available */
3237        ((ag_device_t *)(pccb->devHandle->osData))->flags &= ~ACTIVE;
3238        pccb->ccbStatus  = tiIOFailed;
3239        pccb->scsiStatus = tiDetailNoLogin;
3240        agtiapi_Done(pmcsc, pccb);
3241#else
3242        /* for short cable pull, we want IO retried - 3-18-2005 */
3243        agtiapi_QueueCCB(pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
3244                         AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb);
3245#endif
3246        break;
3247      case tiError:
3248        AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status tiError %p\n",
3249                       pccb->ccb);
3250#ifdef LOGEVENT
3251        agtiapi_LogEvent(pmcsc,
3252                         IOCTL_EVT_SEV_INFORMATIONAL,
3253                         0,
3254                         agNULL,
3255                         0,
3256                         "tiINIIOStart tiError ");
3257#endif
3258        pccb->ccbStatus  = tiIOFailed;
3259        pccb->scsiStatus = tiDetailOtherError;
3260        agtiapi_Done(pmcsc, pccb);
3261        break;
3262      default:
3263        AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status default %x %p\n",
3264                       status, pccb->ccb);
3265#ifdef LOGEVENT
3266        agtiapi_LogEvent(pmcsc,
3267                         IOCTL_EVT_SEV_ERROR,
3268                         0,
3269                         agNULL,
3270                         0,
3271                         "tiINIIOStart unexpected status ");
3272#endif
3273        pccb->ccbStatus  = tiIOFailed;
3274        pccb->scsiStatus = tiDetailOtherError;
3275        agtiapi_Done(pmcsc, pccb);
3276    }
3277
3278    pccb = pccb_next;
3279  }
3280ext:
3281  /* some IO requests might have been completed */
3282  AG_GET_DONE_PCCB(pccb, pmcsc);
3283  return;
3284}
3285
3286/******************************************************************************
3287agtiapi_StartSMP()
3288
3289Purpose:
3290  Send SMP request down for processing.
3291Parameters:
3292  (struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
3293Return:
3294Note:
3295******************************************************************************/
3296STATIC void agtiapi_StartSMP(struct agtiapi_softc *pmcsc)
3297{
3298  ccb_t *pccb;
3299
3300  AGTIAPI_PRINTK("agtiapi_StartSMP: start\n");
3301
3302  AG_LOCAL_LOCK(&pmcsc->sendSMPLock);
3303  pccb = pmcsc->smpSendHead;
3304
3305  /* if link is down, do nothing */
3306  if ((pccb == NULL) || pmcsc->flags & AGTIAPI_RESET)
3307  {
3308    AG_LOCAL_UNLOCK(&pmcsc->sendSMPLock);
3309    AGTIAPI_PRINTK("agtiapi_StartSMP: goto ext\n");
3310    goto ext;
3311  }
3312
3313  /* clear send queue */
3314  pmcsc->smpSendHead = NULL;
3315  pmcsc->smpSendTail = NULL;
3316  AG_LOCAL_UNLOCK(&pmcsc->sendSMPLock);
3317
3318  /* send all ccbs down */
3319  while (pccb)
3320  {
3321    pccb_t pccb_next;
3322    U32    status;
3323
3324    pccb_next = pccb->pccbNext;
3325    pccb->pccbNext = NULL;
3326
3327    if (!pccb->ccb)
3328    {
3329      AGTIAPI_PRINTK("agtiapi_StartSMP: pccb->ccb is NULL ERROR!\n");
3330      pccb = pccb_next;
3331      continue;
3332    }
3333
3334    if (!pccb->devHandle)
3335    {
3336      AGTIAPI_PRINTK("agtiapi_StartSMP: ccb NULL device ERROR!\n");
3337      pccb = pccb_next;
3338      continue;
3339    }
3340    pccb->flags |= TAG_SMP; // mark as SMP for later tracking
3341    AGTIAPI_PRINTK( "agtiapi_StartSMP: ccb %p retry %d\n",
3342                    pccb, pccb->retryCount );
3343    status = tiINISMPStart( &pmcsc->tiRoot,
3344                            &pccb->tiIORequest,
3345                            pccb->devHandle,
3346                            &pccb->tiSMPFrame,
3347                            (void *)&pccb->tdIOReqBody,
3348                            tiInterruptContext);
3349
3350    switch (status)
3351    {
3352    case tiSuccess:
3353      break;
3354    case tiBusy:
3355      AGTIAPI_PRINTK("agtiapi_StartSMP: tiINISMPStart status tiBusy %p\n",
3356                     pccb->ccb);
3357      /* pending ccb back to send queue */
3358      agtiapi_QueueCCB(pmcsc, &pmcsc->smpSendHead, &pmcsc->smpSendTail
3359                       AG_CARD_LOCAL_LOCK(&pmcsc->sendSMPLock), pccb);
3360      break;
3361    case tiError:
3362      AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status tiError %p\n",
3363                     pccb->ccb);
3364      pccb->ccbStatus = tiSMPFailed;
3365      agtiapi_SMPDone(pmcsc, pccb);
3366      break;
3367    default:
3368      AGTIAPI_PRINTK("agtiapi_StartIO: tiINIIOStart status default %x %p\n",
3369                     status, pccb->ccb);
3370      pccb->ccbStatus = tiSMPFailed;
3371      agtiapi_SMPDone(pmcsc, pccb);
3372    }
3373
3374    pccb = pccb_next;
3375  }
3376  ext:
3377  /* some SMP requests might have been completed */
3378  AG_GET_DONE_SMP_PCCB(pccb, pmcsc);
3379
3380  return;
3381}
3382
3383#if __FreeBSD_version > 901000
3384/******************************************************************************
3385agtiapi_PrepareSMPSGList()
3386
3387Purpose:
3388  This function prepares scatter-gather list for the given ccb
3389Parameters:
3390  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
3391  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
3392Return:
3393  0 - success
3394  1 - failure
3395
3396Note:
3397******************************************************************************/
3398static int agtiapi_PrepareSMPSGList( struct agtiapi_softc *pmcsc, ccb_t *pccb )
3399{
3400  /* Pointer to CAM's ccb */
3401  union ccb *ccb = pccb->ccb;
3402  struct ccb_smpio *csmpio = &ccb->smpio;
3403  struct ccb_hdr *ccbh = &ccb->ccb_h;
3404
3405  AGTIAPI_PRINTK("agtiapi_PrepareSMPSGList: start\n");
3406  switch((ccbh->flags & CAM_DATA_MASK))
3407  {
3408    case CAM_DATA_PADDR:
3409    case CAM_DATA_SG_PADDR:
3410      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Physical Address not supported\n");
3411      ccb->ccb_h.status = CAM_REQ_INVALID;
3412      xpt_done(ccb);
3413      return tiReject;
3414    case CAM_DATA_SG:
3415
3416    /*
3417     * Currently we do not support Multiple SG list
3418     * return error for now
3419     */
3420      if ( (csmpio->smp_request_sglist_cnt > 1)
3421           || (csmpio->smp_response_sglist_cnt > 1) )
3422      {
3423        AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Multiple SG list not supported\n");
3424        ccb->ccb_h.status = CAM_REQ_INVALID;
3425        xpt_done(ccb);
3426        return tiReject;
3427      }
3428    }
3429    if ( csmpio->smp_request_sglist_cnt != 0 )
3430    {
3431      /*
3432       * Virtual address that needs to translated into
3433       * one or more physical address ranges.
3434       */
3435      int error;
3436      //AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
3437      AGTIAPI_PRINTK("agtiapi_PrepareSGList: virtual address\n");
3438      error = bus_dmamap_load( pmcsc->buffer_dmat,
3439                               pccb->CCB_dmamap,
3440                               csmpio->smp_request,
3441                               csmpio->smp_request_len,
3442                               agtiapi_PrepareSMPSGListCB,
3443                               pccb,
3444                               BUS_DMA_NOWAIT /* 0 */ );
3445
3446      //AG_LOCAL_UNLOCK(&(pmcsc->pCardInfo->pmIOLock));
3447
3448      if (error == EINPROGRESS)
3449      {
3450        /*
3451         * So as to maintain ordering,
3452         * freeze the controller queue
3453         * until our mapping is
3454         * returned.
3455         */
3456        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3457        xpt_freeze_simq( pmcsc->sim, 1 );
3458        pmcsc->SimQFrozen = agTRUE;
3459        ccbh->status |= CAM_RELEASE_SIMQ;
3460      }
3461    }
3462    if( csmpio->smp_response_sglist_cnt != 0 )
3463    {
3464      /*
3465       * Virtual address that needs to translated into
3466       * one or more physical address ranges.
3467       */
3468      int error;
3469      //AG_LOCAL_LOCK( &(pmcsc->pCardInfo->pmIOLock) );
3470      AGTIAPI_PRINTK( "agtiapi_PrepareSGList: virtual address\n" );
3471      error = bus_dmamap_load( pmcsc->buffer_dmat,
3472                               pccb->CCB_dmamap,
3473                               csmpio->smp_response,
3474                               csmpio->smp_response_len,
3475                               agtiapi_PrepareSMPSGListCB,
3476                               pccb,
3477                               BUS_DMA_NOWAIT /* 0 */ );
3478
3479      //AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
3480
3481      if ( error == EINPROGRESS )
3482      {
3483        /*
3484         * So as to maintain ordering,
3485         * freeze the controller queue
3486         * until our mapping is
3487         * returned.
3488         */
3489        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3490        xpt_freeze_simq( pmcsc->sim, 1 );
3491        pmcsc->SimQFrozen = agTRUE;
3492        ccbh->status |= CAM_RELEASE_SIMQ;
3493      }
3494    }
3495
3496  else
3497  {
3498    if ( (csmpio->smp_request_sglist_cnt == 0) &&
3499         (csmpio->smp_response_sglist_cnt == 0) )
3500    {
3501      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: physical address\n" );
3502      pccb->tiSMPFrame.outFrameBuf = (void *)csmpio->smp_request;
3503      pccb->tiSMPFrame.outFrameLen = csmpio->smp_request_len;
3504      pccb->tiSMPFrame.expectedRespLen = csmpio->smp_response_len;
3505
3506      // 0xFF to be defined
3507      agtiapi_PrepareSMPSGListCB( pccb, NULL, 0, 0xAABBCCDD );
3508    }
3509    pccb->tiSMPFrame.flag = 0;
3510  }
3511
3512  return tiSuccess;
3513}
3514#else
3515
3516/******************************************************************************
3517agtiapi_PrepareSMPSGList()
3518
3519Purpose:
3520  This function prepares scatter-gather list for the given ccb
3521Parameters:
3522  struct agtiapi_softc *pmsc (IN)  Pointer to the HBA data structure
3523  ccb_t *pccb (IN)      A pointer to the driver's own CCB, not CAM's CCB
3524Return:
3525  0 - success
3526  1 - failure
3527
3528Note:
3529******************************************************************************/
3530static int agtiapi_PrepareSMPSGList( struct agtiapi_softc *pmcsc, ccb_t *pccb )
3531{
3532  /* Pointer to CAM's ccb */
3533  union ccb *ccb = pccb->ccb;
3534  struct ccb_smpio *csmpio = &ccb->smpio;
3535  struct ccb_hdr *ccbh = &ccb->ccb_h;
3536
3537  AGTIAPI_PRINTK("agtiapi_PrepareSMPSGList: start\n");
3538
3539  if (ccbh->flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS))
3540  {
3541    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Physical Address "
3542                    "not supported\n" );
3543    ccb->ccb_h.status = CAM_REQ_INVALID;
3544    xpt_done(ccb);
3545    return tiReject;;
3546  }
3547
3548  if (ccbh->flags & CAM_SCATTER_VALID)
3549  {
3550    /*
3551     * Currently we do not support Multiple SG list
3552     * return error for now
3553     */
3554    if ( (csmpio->smp_request_sglist_cnt > 1)
3555         || (csmpio->smp_response_sglist_cnt > 1) )
3556    {
3557      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: Multiple SG list "
3558                      "not supported\n" );
3559      ccb->ccb_h.status = CAM_REQ_INVALID;
3560      xpt_done(ccb);
3561      return tiReject;;
3562    }
3563    if ( csmpio->smp_request_sglist_cnt != 0 )
3564    {
3565      /*
3566       * Virtual address that needs to translated into
3567       * one or more physical address ranges.
3568       */
3569      int error;
3570      //AG_LOCAL_LOCK(&(pmcsc->pCardInfo->pmIOLock));
3571      AGTIAPI_PRINTK("agtiapi_PrepareSGList: virtual address\n");
3572      error = bus_dmamap_load( pmcsc->buffer_dmat,
3573                               pccb->CCB_dmamap,
3574                               csmpio->smp_request,
3575                               csmpio->smp_request_len,
3576                               agtiapi_PrepareSMPSGListCB,
3577                               pccb,
3578                               BUS_DMA_NOWAIT /* 0 */ );
3579
3580      //AG_LOCAL_UNLOCK(&(pmcsc->pCardInfo->pmIOLock));
3581
3582      if (error == EINPROGRESS)
3583      {
3584        /*
3585         * So as to maintain ordering,
3586         * freeze the controller queue
3587         * until our mapping is
3588         * returned.
3589         */
3590        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3591        xpt_freeze_simq( pmcsc->sim, 1 );
3592        pmcsc->SimQFrozen = agTRUE;
3593        ccbh->status |= CAM_RELEASE_SIMQ;
3594      }
3595    }
3596    if( csmpio->smp_response_sglist_cnt != 0 )
3597    {
3598      /*
3599       * Virtual address that needs to translated into
3600       * one or more physical address ranges.
3601       */
3602      int error;
3603      //AG_LOCAL_LOCK( &(pmcsc->pCardInfo->pmIOLock) );
3604      AGTIAPI_PRINTK( "agtiapi_PrepareSGList: virtual address\n" );
3605      error = bus_dmamap_load( pmcsc->buffer_dmat,
3606                               pccb->CCB_dmamap,
3607                               csmpio->smp_response,
3608                               csmpio->smp_response_len,
3609                               agtiapi_PrepareSMPSGListCB,
3610                               pccb,
3611                               BUS_DMA_NOWAIT /* 0 */ );
3612
3613      //AG_LOCAL_UNLOCK( &(pmcsc->pCardInfo->pmIOLock) );
3614
3615      if ( error == EINPROGRESS )
3616      {
3617        /*
3618         * So as to maintain ordering,
3619         * freeze the controller queue
3620         * until our mapping is
3621         * returned.
3622         */
3623        AGTIAPI_PRINTK( "agtiapi_PrepareSGList: EINPROGRESS\n" );
3624        xpt_freeze_simq( pmcsc->sim, 1 );
3625        pmcsc->SimQFrozen = agTRUE;
3626        ccbh->status |= CAM_RELEASE_SIMQ;
3627      }
3628    }
3629  }
3630  else
3631  {
3632    if ( (csmpio->smp_request_sglist_cnt == 0) &&
3633         (csmpio->smp_response_sglist_cnt == 0) )
3634    {
3635      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGList: physical address\n" );
3636      pccb->tiSMPFrame.outFrameBuf = (void *)csmpio->smp_request;
3637      pccb->tiSMPFrame.outFrameLen = csmpio->smp_request_len;
3638      pccb->tiSMPFrame.expectedRespLen = csmpio->smp_response_len;
3639
3640      // 0xFF to be defined
3641      agtiapi_PrepareSMPSGListCB( pccb, NULL, 0, 0xAABBCCDD );
3642    }
3643    pccb->tiSMPFrame.flag = 0;
3644  }
3645
3646  return tiSuccess;
3647}
3648
3649#endif
3650/******************************************************************************
3651agtiapi_PrepareSMPSGListCB()
3652
3653Purpose:
3654  Callback function for bus_dmamap_load()
3655  This fuctions sends IO to LL layer.
3656Parameters:
3657  void *arg (IN)                Pointer to the HBA data structure
3658  bus_dma_segment_t *segs (IN)  Pointer to dma segment
3659  int nsegs (IN)                number of dma segment
3660  int error (IN)                error
3661Return:
3662Note:
3663******************************************************************************/
3664static void agtiapi_PrepareSMPSGListCB( void *arg,
3665                                        bus_dma_segment_t *segs,
3666                                        int nsegs,
3667                                        int error )
3668{
3669  pccb_t                pccb = arg;
3670  union ccb            *ccb  = pccb->ccb;
3671  struct agtiapi_softc *pmcsc;
3672  U32        TID     = CMND_TO_TARGET(ccb);
3673  int status;
3674  tiDeviceHandle_t     *tiExpDevHandle;
3675  tiPortalContext_t    *tiExpPortalContext;
3676  ag_portal_info_t     *tiExpPortalInfo;
3677
3678  AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: start, nsegs %d error 0x%x\n",
3679                  nsegs, error );
3680  pmcsc = pccb->pmcsc;
3681
3682  if ( error != tiSuccess )
3683  {
3684    if (error == 0xAABBCCDD)
3685    {
3686      // do nothing
3687    }
3688    else
3689    {
3690      AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: error status 0x%x\n",
3691                      error );
3692      bus_dmamap_unload( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3693      agtiapi_FreeCCB( pmcsc, pccb );
3694      if (error == EFBIG)
3695        ccb->ccb_h.status = CAM_REQ_TOO_BIG;
3696      else
3697        ccb->ccb_h.status = CAM_REQ_CMP_ERR;
3698      xpt_done( ccb );
3699      return;
3700    }
3701  }
3702
3703  if ( nsegs > AGTIAPI_MAX_DMA_SEGS )
3704  {
3705    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: over the limit. nsegs %d "
3706                    "AGTIAPI_MAX_DMA_SEGS %d\n",
3707                    nsegs, AGTIAPI_MAX_DMA_SEGS );
3708    bus_dmamap_unload( pmcsc->buffer_dmat, pccb->CCB_dmamap );
3709    agtiapi_FreeCCB( pmcsc, pccb );
3710    ccb->ccb_h.status = CAM_REQ_TOO_BIG;
3711    xpt_done( ccb );
3712    return;
3713  }
3714
3715  /*
3716   * If assigned pDevHandle is not available
3717   * then there is no need to send it to StartIO()
3718   */
3719  /* TODO: Add check for deviceType */
3720  if ( pccb->targetId < 0 || pccb->targetId >= maxTargets )
3721  {
3722    agtiapi_FreeCCB( pmcsc, pccb );
3723    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3724    xpt_done(ccb);
3725    pccb->ccb        = NULL;
3726    return;
3727  }
3728  TID = INDEX( pmcsc, pccb->targetId );
3729  if ( (TID >= pmcsc->devDiscover) ||
3730       !(pccb->devHandle = pmcsc->pDevList[TID].pDevHandle) )
3731  {
3732    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: not sending ccb devH %p, "
3733                    "target %d tid %d/%d "
3734                    "card %p ERROR pccb %p\n",
3735                    pccb->devHandle,
3736                    pccb->targetId,
3737                    TID,
3738                    pmcsc->devDiscover,
3739                    pmcsc,
3740                    pccb );
3741    agtiapi_FreeCCB( pmcsc, pccb );
3742    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3743    xpt_done( ccb );
3744    pccb->ccb        = NULL;
3745    return;
3746  }
3747  /* TODO: add indirect handling */
3748  /* set the flag correctly based on Indiret SMP request and response */
3749
3750  AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: send ccb pccb->devHandle %p, "
3751                  "pccb->targetId %d TID %d pmcsc->devDiscover %d card %p\n",
3752                  pccb->devHandle,
3753                  pccb->targetId, TID,
3754                  pmcsc->devDiscover,
3755                  pmcsc );
3756  tiExpDevHandle = pccb->devHandle;
3757  tiExpPortalInfo = pmcsc->pDevList[TID].pPortalInfo;
3758  tiExpPortalContext = &tiExpPortalInfo->tiPortalContext;
3759  /* Look for the expander associated with the ses device */
3760  status = tiINIGetExpander( &pmcsc->tiRoot,
3761                             tiExpPortalContext,
3762                             pccb->devHandle,
3763                             &tiExpDevHandle );
3764
3765  if ( status != tiSuccess )
3766  {
3767    AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: Error getting Expander "
3768                    "device\n" );
3769    agtiapi_FreeCCB( pmcsc, pccb );
3770    ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
3771    xpt_done( ccb );
3772    pccb->ccb        = NULL;
3773    return;
3774  }
3775
3776  /* this is expander device */
3777  pccb->devHandle = tiExpDevHandle;
3778  /* put the request in send queue */
3779  agtiapi_QueueCCB( pmcsc, &pmcsc->smpSendHead, &pmcsc->smpSendTail
3780                    AG_CARD_LOCAL_LOCK(&pmcsc->sendSMPLock), pccb );
3781
3782  agtiapi_StartSMP( pmcsc );
3783
3784  return;
3785}
3786
3787
3788/******************************************************************************
3789agtiapi_Done()
3790
3791Purpose:
3792  Processing completed ccbs
3793Parameters:
3794  struct agtiapi_softc *pmcsc (IN)   Pointer to HBA data structure
3795  ccb_t *pccb (IN)     A pointer to the driver's own CCB, not CAM's CCB
3796Return:
3797Note:
3798******************************************************************************/
3799STATIC void agtiapi_Done(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3800{
3801  pccb_t pccb_curr = pccb;
3802  pccb_t pccb_next;
3803
3804  tiIniScsiCmnd_t *cmnd;
3805  union ccb * ccb;
3806
3807  AGTIAPI_IO("agtiapi_Done: start\n");
3808  while (pccb_curr)
3809  {
3810    /* start from 1st ccb in the chain */
3811    pccb_next = pccb_curr->pccbNext;
3812
3813    if (agtiapi_CheckError(pmcsc, pccb_curr) != 0)
3814    {
3815      /* send command back and release the ccb */
3816      cmnd = &pccb_curr->tiSuperScsiRequest.scsiCmnd;
3817
3818      if (cmnd->cdb[0] == RECEIVE_DIAGNOSTIC)
3819      {
3820        AGTIAPI_PRINTK("agtiapi_Done: RECEIVE_DIAG pg %d id %d cmnd %p pccb "
3821                       "%p\n", cmnd->cdb[2], pccb_curr->targetId, cmnd,
3822                       pccb_curr);
3823      }
3824
3825      CMND_DMA_UNMAP(pmcsc, ccb);
3826
3827      /* send the request back to the CAM */
3828      ccb = pccb_curr->ccb;
3829      agtiapi_FreeCCB(pmcsc, pccb_curr);
3830      xpt_done(ccb);
3831	}
3832    pccb_curr = pccb_next;
3833  }
3834  return;
3835}
3836
3837/******************************************************************************
3838agtiapi_SMPDone()
3839
3840Purpose:
3841  Processing completed ccbs
3842Parameters:
3843  struct agtiapi_softc *pmcsc (IN)  Ponter to HBA data structure
3844  ccb_t *pccb (IN)                  A pointer to the driver's own CCB, not
3845                                    CAM's CCB
3846Return:
3847Note:
3848******************************************************************************/
3849STATIC void agtiapi_SMPDone(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3850{
3851  pccb_t pccb_curr = pccb;
3852  pccb_t pccb_next;
3853
3854  union ccb * ccb;
3855
3856  AGTIAPI_PRINTK("agtiapi_SMPDone: start\n");
3857
3858  while (pccb_curr)
3859  {
3860    /* start from 1st ccb in the chain */
3861    pccb_next = pccb_curr->pccbNext;
3862
3863    if (agtiapi_CheckSMPError(pmcsc, pccb_curr) != 0)
3864    {
3865      CMND_DMA_UNMAP(pmcsc, ccb);
3866
3867      /* send the request back to the CAM */
3868      ccb = pccb_curr->ccb;
3869      agtiapi_FreeSMPCCB(pmcsc, pccb_curr);
3870      xpt_done(ccb);
3871
3872    }
3873    pccb_curr = pccb_next;
3874  }
3875
3876  AGTIAPI_PRINTK("agtiapi_SMPDone: Done\n");
3877  return;
3878}
3879
3880/******************************************************************************
3881agtiapi_hexdump()
3882
3883Purpose:
3884  Utility function for dumping in hex
3885Parameters:
3886  const char *ptitle (IN)  A string to be printed
3887  bit8 *pbuf (IN)          A pointer to a buffer to be printed.
3888  int len (IN)             The lengther of the buffer
3889Return:
3890Note:
3891******************************************************************************/
3892void agtiapi_hexdump(const char *ptitle, bit8 *pbuf, int len)
3893{
3894  int i;
3895  AGTIAPI_PRINTK("%s - hexdump(len=%d):\n", ptitle, (int)len);
3896  if (!pbuf)
3897  {
3898    AGTIAPI_PRINTK("pbuf is NULL\n");
3899    return;
3900  }
3901  for (i = 0; i < len; )
3902  {
3903    if (len - i > 4)
3904    {
3905      AGTIAPI_PRINTK( " 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", pbuf[i], pbuf[i+1],
3906                      pbuf[i+2], pbuf[i+3] );
3907      i += 4;
3908    }
3909    else
3910    {
3911      AGTIAPI_PRINTK(" 0x%02x,", pbuf[i]);
3912      i++;
3913    }
3914  }
3915  AGTIAPI_PRINTK("\n");
3916}
3917
3918
3919/******************************************************************************
3920agtiapi_CheckError()
3921
3922Purpose:
3923  Processes status pertaining to the ccb -- whether it was
3924  completed successfully, aborted, or error encountered.
3925Parameters:
3926  ag_card_t *pCard (IN)  Pointer to HBA data structure
3927  ccb_t *pccd (IN)       A pointer to the driver's own CCB, not CAM's CCB
3928Return:
3929  0 - the command retry is required
3930  1 - the command process is completed
3931Note:
3932
3933******************************************************************************/
3934STATIC U32 agtiapi_CheckError(struct agtiapi_softc *pmcsc, ccb_t *pccb)
3935{
3936  ag_device_t      *pDevice;
3937  // union ccb * ccb = pccb->ccb;
3938  union ccb * ccb;
3939  int is_error, TID;
3940
3941  if (pccb == NULL) {
3942    return 0;
3943  }
3944  ccb = pccb->ccb;
3945  AGTIAPI_IO("agtiapi_CheckError: start\n");
3946  if (ccb == NULL)
3947  {
3948    /* shouldn't be here but just in case we do */
3949    AGTIAPI_PRINTK("agtiapi_CheckError: CCB orphan = %p ERROR\n", pccb);
3950    agtiapi_FreeCCB(pmcsc, pccb);
3951    return 0;
3952  }
3953
3954  is_error = 1;
3955  pDevice = NULL;
3956  if (pmcsc != NULL && pccb->targetId >= 0 && pccb->targetId < maxTargets)
3957  {
3958    if (pmcsc->pWWNList != NULL)
3959    {
3960      TID = INDEX(pmcsc, pccb->targetId);
3961      if (TID < maxTargets)
3962      {
3963        pDevice = &pmcsc->pDevList[TID];
3964        if (pDevice != NULL)
3965        {
3966          is_error = 0;
3967        }
3968      }
3969    }
3970  }
3971  if (is_error)
3972  {
3973    AGTIAPI_PRINTK("agtiapi_CheckError: pDevice == NULL\n");
3974    agtiapi_FreeCCB(pmcsc, pccb);
3975    return 0;
3976  }
3977
3978  /* SCSI status */
3979  ccb->csio.scsi_status = pccb->scsiStatus;
3980
3981   if(pDevice->CCBCount > 0){
3982    atomic_subtract_int(&pDevice->CCBCount,1);
3983}
3984  AG_LOCAL_LOCK(&pmcsc->freezeLock);
3985  if(pmcsc->freezeSim == agTRUE)
3986  {
3987    pmcsc->freezeSim = agFALSE;
3988    xpt_release_simq(pmcsc->sim, 1);
3989  }
3990  AG_LOCAL_UNLOCK(&pmcsc->freezeLock);
3991
3992  switch (pccb->ccbStatus)
3993  {
3994  case tiIOSuccess:
3995    AGTIAPI_IO("agtiapi_CheckError: tiIOSuccess pccb %p\n", pccb);
3996    /* CAM status */
3997    if (pccb->scsiStatus == SCSI_STATUS_OK)
3998    {
3999      ccb->ccb_h.status = CAM_REQ_CMP;
4000    }
4001    else
4002      if (pccb->scsiStatus == SCSI_TASK_ABORTED)
4003    {
4004      ccb->ccb_h.status = CAM_REQ_ABORTED;
4005    }
4006    else
4007    {
4008      ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
4009    }
4010    if (ccb->csio.scsi_status == SCSI_CHECK_CONDITION)
4011    {
4012      ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
4013    }
4014
4015    break;
4016
4017  case tiIOOverRun:
4018    AGTIAPI_PRINTK("agtiapi_CheckError: tiIOOverRun pccb %p\n", pccb);
4019    /* resid is ignored for this condition */
4020    ccb->csio.resid = 0;
4021    ccb->ccb_h.status = CAM_DATA_RUN_ERR;
4022    break;
4023  case tiIOUnderRun:
4024    AGTIAPI_PRINTK("agtiapi_CheckError: tiIOUnderRun pccb %p\n", pccb);
4025    ccb->csio.resid = pccb->scsiStatus;
4026    ccb->ccb_h.status = CAM_REQ_CMP;
4027    ccb->csio.scsi_status = SCSI_STATUS_OK;
4028    break;
4029
4030  case tiIOFailed:
4031    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4032                    pccb, pccb->scsiStatus, pccb->targetId );
4033    if (pccb->scsiStatus == tiDeviceBusy)
4034    {
4035      AGTIAPI_IO( "agtiapi_CheckError: pccb %p tiIOFailed - tiDetailBusy\n",
4036                  pccb );
4037      ccb->ccb_h.status &= ~CAM_STATUS_MASK;
4038      ccb->ccb_h.status |= CAM_REQUEUE_REQ;
4039      if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0)
4040      {
4041        ccb->ccb_h.status |= CAM_DEV_QFRZN;
4042        xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
4043      }
4044    }
4045    else if(pccb->scsiStatus == tiBusy)
4046    {
4047      AG_LOCAL_LOCK(&pmcsc->freezeLock);
4048      if(pmcsc->freezeSim == agFALSE)
4049      {
4050        pmcsc->freezeSim = agTRUE;
4051        xpt_freeze_simq(pmcsc->sim, 1);
4052      }
4053      AG_LOCAL_UNLOCK(&pmcsc->freezeLock);
4054      ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
4055      ccb->ccb_h.status |= CAM_REQUEUE_REQ;
4056    }
4057    else if (pccb->scsiStatus == tiDetailNoLogin)
4058    {
4059      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4060                      "tiDetailNoLogin ERROR\n", pccb );
4061      ccb->ccb_h.status = CAM_DEV_NOT_THERE;
4062    }
4063    else if (pccb->scsiStatus == tiDetailNotValid)
4064    {
4065      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4066                      "tiDetailNotValid ERROR\n", pccb );
4067      ccb->ccb_h.status = CAM_REQ_INVALID;
4068    }
4069    else if (pccb->scsiStatus == tiDetailAbortLogin)
4070    {
4071      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4072                      "tiDetailAbortLogin ERROR\n", pccb );
4073      ccb->ccb_h.status = CAM_REQ_ABORTED;
4074    }
4075    else if (pccb->scsiStatus == tiDetailAbortReset)
4076    {
4077      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4078                      "tiDetailAbortReset ERROR\n", pccb );
4079      ccb->ccb_h.status = CAM_REQ_ABORTED;
4080    }
4081    else if (pccb->scsiStatus == tiDetailAborted)
4082    {
4083      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4084                      "tiDetailAborted ERROR\n", pccb );
4085      ccb->ccb_h.status = CAM_REQ_ABORTED;
4086    }
4087    else if (pccb->scsiStatus == tiDetailOtherError)
4088    {
4089      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4090                      "tiDetailOtherError ERROR\n", pccb );
4091      ccb->ccb_h.status = CAM_REQ_ABORTED;
4092    }
4093    break;
4094  case tiIODifError:
4095    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4096                    pccb, pccb->scsiStatus, pccb->targetId );
4097    if (pccb->scsiStatus == tiDetailDifAppTagMismatch)
4098    {
4099      AGTIAPI_IO( "agtiapi_CheckError: pccb %p tiIOFailed - "
4100                  "tiDetailDifAppTagMismatch\n", pccb );
4101      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4102    }
4103    else if (pccb->scsiStatus == tiDetailDifRefTagMismatch)
4104    {
4105      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4106                      "tiDetailDifRefTagMismatch\n", pccb );
4107      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4108    }
4109    else if (pccb->scsiStatus == tiDetailDifCrcMismatch)
4110    {
4111      AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed - "
4112                      "tiDetailDifCrcMismatch\n", pccb );
4113      ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4114    }
4115    break;
4116#ifdef HIALEAH_ENCRYPTION
4117  case tiIOEncryptError:
4118    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOFailed %d id %d ERROR\n",
4119                    pccb, pccb->scsiStatus, pccb->targetId );
4120    if (pccb->scsiStatus == tiDetailDekKeyCacheMiss)
4121    {
4122      AGTIAPI_PRINTK( "agtiapi_CheckError: %s: pccb %p tiIOFailed - "
4123                      "tiDetailDekKeyCacheMiss ERROR\n",
4124                      __FUNCTION__, pccb );
4125      ccb->ccb_h.status = CAM_REQ_ABORTED;
4126      agtiapi_HandleEncryptedIOFailure(pDevice, pccb);
4127    }
4128    else if (pccb->scsiStatus == tiDetailDekIVMismatch)
4129    {
4130      AGTIAPI_PRINTK( "agtiapi_CheckError: %s: pccb %p tiIOFailed - "
4131                      "tiDetailDekIVMismatch ERROR\n", __FUNCTION__, pccb );
4132      ccb->ccb_h.status = CAM_REQ_ABORTED;
4133      agtiapi_HandleEncryptedIOFailure(pDevice, pccb);
4134    }
4135    break;
4136#endif
4137  default:
4138    AGTIAPI_PRINTK( "agtiapi_CheckError: pccb %p tiIOdefault %d id %d ERROR\n",
4139                    pccb, pccb->ccbStatus, pccb->targetId );
4140    ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4141    break;
4142  }
4143
4144  return 1;
4145}
4146
4147
4148/******************************************************************************
4149agtiapi_SMPCheckError()
4150
4151Purpose:
4152  Processes status pertaining to the ccb -- whether it was
4153  completed successfully, aborted, or error encountered.
4154Parameters:
4155  ag_card_t *pCard (IN)  Pointer to HBA data structure
4156  ccb_t *pccd (IN)       A pointer to the driver's own CCB, not CAM's CCB
4157Return:
4158  0 - the command retry is required
4159  1 - the command process is completed
4160Note:
4161
4162******************************************************************************/
4163STATIC U32 agtiapi_CheckSMPError( struct agtiapi_softc *pmcsc, ccb_t *pccb )
4164{
4165	union ccb * ccb = pccb->ccb;
4166
4167	AGTIAPI_PRINTK("agtiapi_CheckSMPError: start\n");
4168
4169	if (!ccb)
4170	{
4171		/* shouldn't be here but just in case we do */
4172		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: CCB orphan = %p ERROR\n",
4173                              pccb );
4174		agtiapi_FreeSMPCCB(pmcsc, pccb);
4175		return 0;
4176	}
4177
4178	switch (pccb->ccbStatus)
4179	{
4180	case tiSMPSuccess:
4181		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: tiSMPSuccess pccb %p\n",
4182                              pccb );
4183		/* CAM status */
4184		ccb->ccb_h.status = CAM_REQ_CMP;
4185		break;
4186  case tiSMPFailed:
4187		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: tiSMPFailed pccb %p\n",
4188                              pccb );
4189		/* CAM status */
4190		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4191		break;
4192  default:
4193		AGTIAPI_PRINTK( "agtiapi_CheckSMPError: pccb %p tiSMPdefault %d "
4194                              "id %d ERROR\n",
4195                              pccb,
4196                              pccb->ccbStatus,
4197                              pccb->targetId );
4198		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4199		break;
4200	}
4201
4202
4203  return 1;
4204
4205}
4206
4207/******************************************************************************
4208agtiapi_HandleEncryptedIOFailure():
4209
4210Purpose:
4211Parameters:
4212Return:
4213Note:
4214  Currently not used.
4215******************************************************************************/
4216void agtiapi_HandleEncryptedIOFailure(ag_device_t *pDev, ccb_t *pccb)
4217{
4218
4219  AGTIAPI_PRINTK("agtiapi_HandleEncryptedIOFailure: start\n");
4220  return;
4221}
4222
4223/******************************************************************************
4224agtiapi_Retry()
4225
4226Purpose:
4227  Retry a ccb.
4228Parameters:
4229  struct agtiapi_softc *pmcsc (IN)  Pointer to the HBA structure
4230  ccb_t *pccb (IN)            A pointer to the driver's own CCB, not CAM's CCB
4231Return:
4232Note:
4233  Currently not used.
4234******************************************************************************/
4235STATIC void agtiapi_Retry(struct agtiapi_softc *pmcsc, ccb_t *pccb)
4236{
4237  pccb->retryCount++;
4238  pccb->flags      = ACTIVE | AGTIAPI_RETRY;
4239  pccb->ccbStatus  = 0;
4240  pccb->scsiStatus = 0;
4241  pccb->startTime  = ticks;
4242
4243  AGTIAPI_PRINTK( "agtiapi_Retry: start\n" );
4244  AGTIAPI_PRINTK( "agtiapi_Retry: ccb %p retry %d flgs x%x\n", pccb,
4245                  pccb->retryCount, pccb->flags );
4246
4247  agtiapi_QueueCCB(pmcsc, &pmcsc->ccbSendHead, &pmcsc->ccbSendTail
4248                   AG_CARD_LOCAL_LOCK(&pmcsc->sendLock), pccb);
4249  return;
4250}
4251
4252
4253/******************************************************************************
4254agtiapi_DumpCCB()
4255
4256Purpose:
4257  Dump CCB for debuging
4258Parameters:
4259  ccb_t *pccb (IN)  A pointer to the driver's own CCB, not CAM's CCB
4260Return:
4261Note:
4262******************************************************************************/
4263STATIC void agtiapi_DumpCCB(ccb_t *pccb)
4264{
4265  AGTIAPI_PRINTK("agtiapi_DumpCCB: pccb %p, devHandle %p, tid %d, lun %d\n",
4266         pccb,
4267         pccb->devHandle,
4268         pccb->targetId,
4269         pccb->lun);
4270  AGTIAPI_PRINTK("flag 0x%x, add_mode 0x%x, ccbStatus 0x%x, scsiStatus 0x%x\n",
4271         pccb->flags,
4272         pccb->addrMode,
4273         pccb->ccbStatus,
4274         pccb->scsiStatus);
4275  AGTIAPI_PRINTK("scsi comand = 0x%x, numSgElements = %d\n",
4276	 pccb->tiSuperScsiRequest.scsiCmnd.cdb[0],
4277         pccb->numSgElements);
4278  AGTIAPI_PRINTK("dataLen = 0x%x, sens_len = 0x%x\n",
4279         pccb->dataLen,
4280         pccb->senseLen);
4281  AGTIAPI_PRINTK("tiSuperScsiRequest:\n");
4282  AGTIAPI_PRINTK("scsiCmnd: expDataLength 0x%x, taskAttribute 0x%x\n",
4283         pccb->tiSuperScsiRequest.scsiCmnd.expDataLength,
4284         pccb->tiSuperScsiRequest.scsiCmnd.taskAttribute);
4285  AGTIAPI_PRINTK("cdb[0] = 0x%x, cdb[1] = 0x%x, cdb[2] = 0x%x, cdb[3] = 0x%x\n",
4286         pccb->tiSuperScsiRequest.scsiCmnd.cdb[0],
4287         pccb->tiSuperScsiRequest.scsiCmnd.cdb[1],
4288         pccb->tiSuperScsiRequest.scsiCmnd.cdb[2],
4289         pccb->tiSuperScsiRequest.scsiCmnd.cdb[3]);
4290  AGTIAPI_PRINTK("cdb[4] = 0x%x, cdb[5] = 0x%x, cdb[6] = 0x%x, cdb[7] = 0x%x\n",
4291         pccb->tiSuperScsiRequest.scsiCmnd.cdb[4],
4292         pccb->tiSuperScsiRequest.scsiCmnd.cdb[5],
4293         pccb->tiSuperScsiRequest.scsiCmnd.cdb[6],
4294         pccb->tiSuperScsiRequest.scsiCmnd.cdb[7]);
4295  AGTIAPI_PRINTK( "cdb[8] = 0x%x, cdb[9] = 0x%x, cdb[10] = 0x%x, "
4296                  "cdb[11] = 0x%x\n",
4297                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[8],
4298                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[9],
4299                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[10],
4300                  pccb->tiSuperScsiRequest.scsiCmnd.cdb[11] );
4301  AGTIAPI_PRINTK("agSgl1: upper 0x%x, lower 0x%x, len 0x%x, type %d\n",
4302         pccb->tiSuperScsiRequest.agSgl1.upper,
4303         pccb->tiSuperScsiRequest.agSgl1.lower,
4304         pccb->tiSuperScsiRequest.agSgl1.len,
4305         pccb->tiSuperScsiRequest.agSgl1.type);
4306}
4307
4308/******************************************************************************
4309agtiapi_eh_HostReset()
4310
4311Purpose:
4312  A new error handler of Host Reset command.
4313Parameters:
4314  scsi_cmnd *cmnd (IN)  Pointer to a command to the HBA to be reset
4315Return:
4316  SUCCESS - success
4317  FAILED  - fail
4318Note:
4319******************************************************************************/
4320int agtiapi_eh_HostReset( struct agtiapi_softc *pmcsc, union ccb *cmnd )
4321{
4322  AGTIAPI_PRINTK( "agtiapi_eh_HostReset: ccb pointer %p\n",
4323                  cmnd );
4324
4325  if( cmnd == NULL )
4326  {
4327    printf( "agtiapi_eh_HostReset: null command, skipping reset.\n" );
4328    return tiInvalidHandle;
4329  }
4330
4331#ifdef LOGEVENT
4332  agtiapi_LogEvent( pmcsc,
4333                    IOCTL_EVT_SEV_INFORMATIONAL,
4334                    0,
4335                    agNULL,
4336                    0,
4337                    "agtiapi_eh_HostReset! " );
4338#endif
4339
4340  return agtiapi_DoSoftReset( pmcsc );
4341}
4342
4343
4344/******************************************************************************
4345agtiapi_QueueCCB()
4346
4347Purpose:
4348  Put ccb in ccb queue at the tail
4349Parameters:
4350  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4351  pccb_t *phead (IN)                Double pointer to ccb queue head
4352  pccb_t *ptail (IN)                Double pointer to ccb queue tail
4353  ccb_t *pccb (IN)                  Poiner to a ccb to be queued
4354Return:
4355Note:
4356  Put the ccb to the tail of queue
4357******************************************************************************/
4358STATIC void agtiapi_QueueCCB( struct agtiapi_softc *pmcsc,
4359                              pccb_t *phead,
4360                              pccb_t *ptail,
4361#ifdef AGTIAPI_LOCAL_LOCK
4362                              struct mtx *mutex,
4363#endif
4364                              ccb_t *pccb )
4365{
4366  AGTIAPI_IO( "agtiapi_QueueCCB: start\n" );
4367  AGTIAPI_IO( "agtiapi_QueueCCB: %p to %p\n", pccb, phead );
4368  if (phead == NULL || ptail == NULL)
4369  {
4370    panic( "agtiapi_QueueCCB: phead %p ptail %p", phead, ptail );
4371  }
4372  pccb->pccbNext = NULL;
4373  AG_LOCAL_LOCK( mutex );
4374  if (*phead == NULL)
4375  {
4376    //WARN_ON(*ptail != NULL); /* critical, just get more logs */
4377    *phead = pccb;
4378  }
4379  else
4380  {
4381    //WARN_ON(*ptail == NULL); /* critical, just get more logs */
4382    if (*ptail)
4383      (*ptail)->pccbNext = pccb;
4384  }
4385  *ptail = pccb;
4386  AG_LOCAL_UNLOCK( mutex );
4387  return;
4388}
4389
4390
4391/******************************************************************************
4392agtiapi_QueueCCB()
4393
4394Purpose:
4395
4396Parameters:
4397
4398
4399Return:
4400Note:
4401
4402******************************************************************************/
4403static int agtiapi_QueueSMP(struct agtiapi_softc *pmcsc, union ccb * ccb)
4404{
4405  pccb_t pccb = agNULL; /* call dequeue */
4406  int        status = tiSuccess;
4407  int        targetID = xpt_path_target_id(ccb->ccb_h.path);
4408
4409  AGTIAPI_PRINTK("agtiapi_QueueSMP: start\n");
4410
4411  /* get a ccb */
4412  if ((pccb = agtiapi_GetCCB(pmcsc)) == NULL)
4413  {
4414    AGTIAPI_PRINTK("agtiapi_QueueSMP: GetCCB ERROR\n");
4415    ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4416    xpt_done(ccb);
4417    return tiBusy;
4418  }
4419  pccb->pmcsc = pmcsc;
4420
4421  /* initialize Command Control Block (CCB) */
4422  pccb->targetId   = targetID;
4423  pccb->ccb        = ccb;	/* for struct scsi_cmnd */
4424
4425  status = agtiapi_PrepareSMPSGList(pmcsc, pccb);
4426
4427  if (status != tiSuccess)
4428  {
4429    AGTIAPI_PRINTK("agtiapi_QueueSMP: agtiapi_PrepareSMPSGList failure\n");
4430    agtiapi_FreeCCB(pmcsc, pccb);
4431    if (status == tiReject)
4432    {
4433      ccb->ccb_h.status = CAM_REQ_INVALID;
4434    }
4435    else
4436    {
4437      ccb->ccb_h.status = CAM_REQ_CMP;
4438    }
4439    xpt_done(ccb);
4440    return tiError;
4441  }
4442
4443  return status;
4444}
4445
4446/******************************************************************************
4447agtiapi_SetLunField()
4448
4449Purpose:
4450  Set LUN field based on different address mode
4451Parameters:
4452  ccb_t *pccb (IN)  A pointer to the driver's own CCB, not CAM's CCB
4453Return:
4454Note:
4455******************************************************************************/
4456void agtiapi_SetLunField(ccb_t *pccb)
4457{
4458  U08 *pchar;
4459
4460  pchar = (U08 *)&pccb->tiSuperScsiRequest.scsiCmnd.lun;
4461
4462//  AGTIAPI_PRINTK("agtiapi_SetLunField: start\n");
4463
4464  switch (pccb->addrMode)
4465  {
4466  case AGTIAPI_PERIPHERAL:
4467       *pchar++ = 0;
4468       *pchar   = (U08)pccb->lun;
4469       break;
4470  case AGTIAPI_VOLUME_SET:
4471       *pchar++ = (AGTIAPI_VOLUME_SET << AGTIAPI_ADDRMODE_SHIFT) |
4472                  (U08)((pccb->lun >> 8) & 0x3F);
4473       *pchar   = (U08)pccb->lun;
4474       break;
4475  case AGTIAPI_LUN_ADDR:
4476       *pchar++ = (AGTIAPI_LUN_ADDR << AGTIAPI_ADDRMODE_SHIFT) |
4477                  pccb->targetId;
4478       *pchar   = (U08)pccb->lun;
4479       break;
4480  }
4481
4482
4483}
4484
4485
4486/*****************************************************************************
4487agtiapi_FreeCCB()
4488
4489Purpose:
4490  Free a ccb and put it back to ccbFreeList.
4491Parameters:
4492  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4493  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4494                                    CAM's CCB
4495Returns:
4496Note:
4497*****************************************************************************/
4498STATIC void agtiapi_FreeCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4499{
4500  union ccb *ccb = pccb->ccb;
4501  bus_dmasync_op_t op;
4502
4503  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4504  AGTIAPI_IO( "agtiapi_FreeCCB: start %p\n", pccb );
4505
4506#ifdef AGTIAPI_TEST_EPL
4507  tiEncrypt_t *encrypt;
4508#endif
4509
4510  agtiapi_DumpCDB( "agtiapi_FreeCCB", pccb );
4511
4512  if (pccb->sgList != agNULL)
4513  {
4514    AGTIAPI_IO( "agtiapi_FreeCCB: pccb->sgList is NOT null\n" );
4515  }
4516  else
4517  {
4518    AGTIAPI_PRINTK( "agtiapi_FreeCCB: pccb->sgList is null\n" );
4519  }
4520
4521  /* set data transfer direction */
4522  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
4523  {
4524    op = BUS_DMASYNC_POSTWRITE;
4525  }
4526  else
4527  {
4528    op = BUS_DMASYNC_POSTREAD;
4529  }
4530
4531  if (pccb->numSgElements == 0)
4532  {
4533    // do nothing
4534    AGTIAPI_IO( "agtiapi_FreeCCB: numSgElements zero\n" );
4535  }
4536  else if (pccb->numSgElements == 1)
4537  {
4538    AGTIAPI_IO( "agtiapi_FreeCCB: numSgElements is one\n" );
4539    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4540    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4541    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4542  }
4543  else
4544  {
4545    AGTIAPI_PRINTK( "agtiapi_FreeCCB: numSgElements 2 or higher \n" );
4546    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4547    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4548    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4549  }
4550
4551#ifdef AGTIAPI_TEST_DPL
4552  if (pccb->tiSuperScsiRequest.Dif.enableDIFPerLA == TRUE) {
4553    if(pccb->dplPtr)
4554        memset( (char *) pccb->dplPtr,
4555                0,
4556                MAX_DPL_REGIONS * sizeof(dplaRegion_t) );
4557    pccb->tiSuperScsiRequest.Dif.enableDIFPerLA = FALSE;
4558    pccb->tiSuperScsiRequest.Dif.DIFPerLAAddrLo = 0;
4559    pccb->tiSuperScsiRequest.Dif.DIFPerLAAddrHi = 0;
4560  }
4561#endif
4562
4563#ifdef AGTIAPI_TEST_EPL
4564  encrypt = &pccb->tiSuperScsiRequest.Encrypt;
4565  if (encrypt->enableEncryptionPerLA == TRUE) {
4566    encrypt->enableEncryptionPerLA = FALSE;
4567    encrypt->EncryptionPerLAAddrLo = 0;
4568    encrypt->EncryptionPerLAAddrHi = 0;
4569  }
4570#endif
4571
4572#ifdef ENABLE_SATA_DIF
4573  if (pccb->holePtr && pccb->dmaHandleHole)
4574    pci_free_consistent( pmcsc->pCardInfo->pPCIDev,
4575                         512,
4576                         pccb->holePtr,
4577                         pccb->dmaHandleHole );
4578  pccb->holePtr    = 0;
4579  pccb->dmaHandleHole = 0;
4580#endif
4581
4582  pccb->dataLen    = 0;
4583  pccb->retryCount = 0;
4584  pccb->ccbStatus  = 0;
4585  pccb->scsiStatus = 0;
4586  pccb->startTime  = 0;
4587  pccb->dmaHandle  = 0;
4588  pccb->numSgElements = 0;
4589  pccb->tiIORequest.tdData = 0;
4590  memset((void *)&pccb->tiSuperScsiRequest, 0, AGSCSI_INIT_XCHG_LEN);
4591
4592#ifdef HIALEAH_ENCRYPTION
4593  if (pmcsc->encrypt)
4594    agtiapi_CleanupEncryptedIO(pmcsc, pccb);
4595#endif
4596
4597  pccb->flags      = 0;
4598  pccb->ccb        = NULL;
4599  pccb->pccbIO = NULL;
4600  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4601  pmcsc->ccbFreeList = (caddr_t *)pccb;
4602
4603  pmcsc->activeCCB--;
4604
4605  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4606  return;
4607}
4608
4609
4610/******************************************************************************
4611agtiapi_FlushCCBs()
4612
4613Purpose:
4614  Flush all in processed ccbs.
4615Parameters:
4616  ag_card_t *pCard (IN)  Pointer to HBA data structure
4617  U32 flag (IN)            Flag to call back
4618Return:
4619Note:
4620******************************************************************************/
4621STATIC void agtiapi_FlushCCBs( struct agtiapi_softc *pCard, U32 flag )
4622{
4623  union ccb *ccb;
4624  ccb_t     *pccb;
4625
4626  AGTIAPI_PRINTK( "agtiapi_FlushCCBs: enter \n" );
4627  for( pccb = (pccb_t)pCard->ccbChainList;
4628       pccb != NULL;
4629       pccb = pccb->pccbChainNext ) {
4630    if( pccb->flags == 0 )
4631    {
4632      // printf( "agtiapi_FlushCCBs: nothing, continue \n" );
4633      continue;
4634    }
4635    ccb = pccb->ccb;
4636    if ( pccb->flags & ( TASK_MANAGEMENT | DEV_RESET ) )
4637    {
4638      AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeTMCCB \n" );
4639      agtiapi_FreeTMCCB( pCard, pccb );
4640    }
4641    else
4642    {
4643      if ( pccb->flags & TAG_SMP )
4644      {
4645        AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeSMPCCB \n" );
4646        agtiapi_FreeSMPCCB( pCard, pccb );
4647      }
4648      else
4649      {
4650        AGTIAPI_PRINTK( "agtiapi_FlushCCBs: agtiapi_FreeCCB \n" );
4651        agtiapi_FreeCCB( pCard, pccb );
4652      }
4653      if( ccb ) {
4654        CMND_DMA_UNMAP( pCard, ccb );
4655        if( flag == AGTIAPI_CALLBACK ) {
4656          ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
4657          xpt_done( ccb );
4658        }
4659      }
4660    }
4661  }
4662}
4663
4664/*****************************************************************************
4665agtiapi_FreeSMPCCB()
4666
4667Purpose:
4668  Free a ccb and put it back to ccbFreeList.
4669Parameters:
4670  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4671  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4672                                    CAM's CCB
4673Returns:
4674Note:
4675*****************************************************************************/
4676STATIC void agtiapi_FreeSMPCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4677{
4678  union ccb *ccb = pccb->ccb;
4679  bus_dmasync_op_t op;
4680
4681  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4682  AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: start %p\n", pccb);
4683
4684  /* set data transfer direction */
4685  if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
4686  {
4687    op = BUS_DMASYNC_POSTWRITE;
4688  }
4689  else
4690  {
4691    op = BUS_DMASYNC_POSTREAD;
4692  }
4693
4694  if (pccb->numSgElements == 0)
4695  {
4696    // do nothing
4697    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 0\n");
4698  }
4699  else if (pccb->numSgElements == 1)
4700  {
4701    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 1\n");
4702    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4703    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4704    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4705  }
4706  else
4707  {
4708    AGTIAPI_PRINTK("agtiapi_FreeSMPCCB: numSgElements 2 or higher \n");
4709    //op is either BUS_DMASYNC_POSTWRITE or BUS_DMASYNC_POSTREAD
4710    bus_dmamap_sync(pmcsc->buffer_dmat, pccb->CCB_dmamap, op);
4711    bus_dmamap_unload(pmcsc->buffer_dmat, pccb->CCB_dmamap);
4712  }
4713
4714  /*dma api cleanning*/
4715  pccb->dataLen    = 0;
4716  pccb->retryCount = 0;
4717  pccb->ccbStatus  = 0;
4718  pccb->startTime  = 0;
4719  pccb->dmaHandle  = 0;
4720  pccb->numSgElements = 0;
4721  pccb->tiIORequest.tdData = 0;
4722  memset((void *)&pccb->tiSMPFrame, 0, AGSMP_INIT_XCHG_LEN);
4723
4724  pccb->flags        = 0;
4725  pccb->ccb = NULL;
4726  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4727  pmcsc->ccbFreeList = (caddr_t *)pccb;
4728
4729  pmcsc->activeCCB--;
4730
4731  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4732  return;
4733
4734}
4735
4736/*****************************************************************************
4737agtiapi_FreeTMCCB()
4738
4739Purpose:
4740  Free a ccb and put it back to ccbFreeList.
4741Parameters:
4742  struct agtiapi_softc *pmcsc (IN)  Pointer to HBA data structure
4743  pccb_t pccb (IN)                  A pointer to the driver's own CCB, not
4744                                    CAM's CCB
4745Returns:
4746Note:
4747*****************************************************************************/
4748STATIC void agtiapi_FreeTMCCB(struct agtiapi_softc *pmcsc, pccb_t pccb)
4749{
4750  AG_LOCAL_LOCK(&pmcsc->ccbLock);
4751  AGTIAPI_PRINTK("agtiapi_FreeTMCCB: start %p\n", pccb);
4752  pccb->dataLen    = 0;
4753  pccb->retryCount = 0;
4754  pccb->ccbStatus  = 0;
4755  pccb->scsiStatus = 0;
4756  pccb->startTime  = 0;
4757  pccb->dmaHandle  = 0;
4758  pccb->numSgElements = 0;
4759  pccb->tiIORequest.tdData = 0;
4760  memset((void *)&pccb->tiSuperScsiRequest, 0, AGSCSI_INIT_XCHG_LEN);
4761  pccb->flags        = 0;
4762  pccb->ccb = NULL;
4763  pccb->pccbIO = NULL;
4764  pccb->pccbNext     = (pccb_t)pmcsc->ccbFreeList;
4765  pmcsc->ccbFreeList = (caddr_t *)pccb;
4766  pmcsc->activeCCB--;
4767  AG_LOCAL_UNLOCK(&pmcsc->ccbLock);
4768  return;
4769}
4770/******************************************************************************
4771agtiapi_CheckAllVectors():
4772
4773Purpose:
4774Parameters:
4775Return:
4776Note:
4777  Currently, not used.
4778******************************************************************************/
4779void agtiapi_CheckAllVectors( struct agtiapi_softc *pCard, bit32 context )
4780{
4781#ifdef SPC_MSIX_INTR
4782  if (!agtiapi_intx_mode)
4783  {
4784    int i;
4785
4786    for (i = 0; i < pCard->pCardInfo->maxInterruptVectors; i++)
4787      if (tiCOMInterruptHandler(&pCard->tiRoot, i) == agTRUE)
4788        tiCOMDelayedInterruptHandler(&pCard->tiRoot, i, 100, context);
4789  }
4790  else
4791  if (tiCOMInterruptHandler(&pCard->tiRoot, 0) == agTRUE)
4792    tiCOMDelayedInterruptHandler(&pCard->tiRoot, 0, 100, context);
4793#else
4794  if (tiCOMInterruptHandler(&pCard->tiRoot, 0) == agTRUE)
4795    tiCOMDelayedInterruptHandler(&pCard->tiRoot, 0, 100, context);
4796#endif
4797
4798}
4799
4800
4801/******************************************************************************
4802agtiapi_CheckCB()
4803
4804Purpose:
4805  Check call back function returned event for process completion
4806Parameters:
4807  struct agtiapi_softc *pCard  Pointer to card data structure
4808  U32 milisec (IN)       Waiting time for expected event
4809  U32 flag (IN)          Flag of the event to check
4810  U32 *pStatus (IN)      Pointer to status of the card or port to check
4811Return:
4812  AGTIAPI_SUCCESS - event comes as expected
4813  AGTIAPI_FAIL    - event not coming
4814Note:
4815  Currently, not used
4816******************************************************************************/
4817agBOOLEAN agtiapi_CheckCB( struct agtiapi_softc *pCard,
4818                           U32 milisec,
4819                           U32 flag,
4820                           volatile U32 *pStatus )
4821{
4822  U32    msecsPerTick = pCard->pCardInfo->tiRscInfo.tiInitiatorResource.
4823                        initiatorOption.usecsPerTick / 1000;
4824  S32    i = milisec/msecsPerTick;
4825  AG_GLOBAL_ARG( _flags );
4826
4827  AGTIAPI_PRINTK( "agtiapi_CheckCB: start\n" );
4828  AGTIAPI_FLOW(   "agtiapi_CheckCB: start\n" );
4829
4830  if( i <= 0 )
4831    i = 1;
4832  while (i > 0)
4833  {
4834    if (*pStatus & TASK_MANAGEMENT)
4835    {
4836      if (*pStatus & AGTIAPI_CB_DONE)
4837      {
4838        if( flag == 0 || *pStatus & flag )
4839          return AGTIAPI_SUCCESS;
4840        else
4841          return AGTIAPI_FAIL;
4842      }
4843    }
4844    else if (pCard->flags & AGTIAPI_CB_DONE)
4845    {
4846      if( flag == 0 || *pStatus & flag )
4847        return AGTIAPI_SUCCESS;
4848      else
4849        return AGTIAPI_FAIL;
4850    }
4851
4852    agtiapi_DelayMSec( msecsPerTick );
4853
4854    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, _flags );
4855    tiCOMTimerTick( &pCard->tiRoot );
4856
4857    agtiapi_CheckAllVectors( pCard, tiNonInterruptContext );
4858    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, _flags );
4859
4860    i--;
4861  }
4862
4863  if( *pStatus & TASK_MANAGEMENT )
4864    *pStatus |= TASK_TIMEOUT;
4865
4866  return AGTIAPI_FAIL;
4867}
4868
4869
4870/******************************************************************************
4871agtiapi_DiscoverTgt()
4872
4873Purpose:
4874  Discover available devices
4875Parameters:
4876  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
4877Return:
4878Note:
4879******************************************************************************/
4880STATIC void agtiapi_DiscoverTgt(struct agtiapi_softc *pCard)
4881{
4882
4883  ag_portal_data_t *pPortalData;
4884  U32              count;
4885
4886  AGTIAPI_PRINTK("agtiapi_DiscoverTgt: start\n");
4887  AGTIAPI_FLOW("agtiapi_DiscoverTgt\n");
4888  AGTIAPI_INIT("agtiapi_DiscoverTgt\n");
4889
4890  pPortalData = pCard->pPortalData;
4891  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4892  {
4893    pCard->flags &= ~AGTIAPI_CB_DONE;
4894    if (!(PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY))
4895    {
4896      if (pCard->flags & AGTIAPI_INIT_TIME)
4897      {
4898        if (agtiapi_CheckCB(pCard, 5000, AGTIAPI_PORT_DISC_READY,
4899            &PORTAL_STATUS(pPortalData)) == AGTIAPI_FAIL)
4900        {
4901          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Port %p / %d not ready for "
4902                          "discovery\n",
4903                          pPortalData, count );
4904          /*
4905           * There is no need to spend time on discovering device
4906           * if port is not ready to do so.
4907           */
4908          continue;
4909        }
4910      }
4911      else
4912        continue;
4913    }
4914
4915    AGTIAPI_FLOW( "agtiapi_DiscoverTgt: Portal %p DiscoverTargets starts\n",
4916                  pPortalData );
4917    AGTIAPI_INIT_DELAY(1000);
4918
4919    pCard->flags &= ~AGTIAPI_CB_DONE;
4920    if (tiINIDiscoverTargets(&pCard->tiRoot,
4921                             &pPortalData->portalInfo.tiPortalContext,
4922                             FORCE_PERSISTENT_ASSIGN_MASK)
4923        != tiSuccess)
4924      AGTIAPI_PRINTK("agtiapi_DiscoverTgt: tiINIDiscoverTargets ERROR\n");
4925
4926    /*
4927     * Should wait till discovery completion to start
4928     * next portal. However, lower layer have issue on
4929     * multi-portal case under Linux.
4930     */
4931  }
4932
4933  pPortalData = pCard->pPortalData;
4934  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4935  {
4936    if ((PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY))
4937    {
4938      if (agtiapi_CheckCB(pCard, 20000, AGTIAPI_DISC_COMPLETE,
4939          &PORTAL_STATUS(pPortalData)) == AGTIAPI_FAIL)
4940      {
4941        if ((PORTAL_STATUS(pPortalData) & AGTIAPI_DISC_COMPLETE))
4942          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %p discover complete, "
4943                          "status 0x%x\n",
4944                          pPortalData,
4945                          PORTAL_STATUS(pPortalData) );
4946        else
4947          AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %p discover is not "
4948                          "completed, status 0x%x\n",
4949                          pPortalData, PORTAL_STATUS(pPortalData) );
4950        continue;
4951      }
4952      AGTIAPI_PRINTK( "agtiapi_DiscoverTgt: Portal %d discover target "
4953                      "success\n",
4954                      count );
4955    }
4956  }
4957
4958  /*
4959   * Calling to get device handle should be done per portal based
4960   * and better right after discovery is done. However, lower iscsi
4961   * layer may not returns discovery complete in correct sequence or we
4962   * ran out time. We get device handle for all portals together
4963   * after discovery is done or timed out.
4964   */
4965  pPortalData = pCard->pPortalData;
4966  for (count = 0; count < pCard->portCount; count++, pPortalData++)
4967  {
4968    /*
4969     * We try to get device handle no matter
4970     * if discovery is completed or not.
4971     */
4972    if (PORTAL_STATUS(pPortalData) & AGTIAPI_PORT_DISC_READY)
4973    {
4974      U32 i;
4975
4976      for (i = 0; i < AGTIAPI_GET_DEV_MAX; i++)
4977      {
4978        if (agtiapi_GetDevHandle(pCard, &pPortalData->portalInfo, 0, 0) != 0)
4979          break;
4980        agtiapi_DelayMSec(AGTIAPI_EXTRA_DELAY);
4981      }
4982
4983      if ((PORTAL_STATUS(pPortalData) & AGTIAPI_DISC_COMPLETE) ||
4984          (pCard->tgtCount > 0))
4985        PORTAL_STATUS(pPortalData) |= ( AGTIAPI_DISC_DONE |
4986                                        AGTIAPI_PORT_LINK_UP );
4987    }
4988  }
4989
4990  return;
4991
4992}
4993
4994
4995
4996/******************************************************************************
4997agtiapi_PrepCCBs()
4998
4999Purpose:
5000  Prepares CCB including DMA map.
5001Parameters:
5002  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
5003  ccb_hdr_t *hdr (IN)               Pointer to the CCB header
5004  U32 size (IN)                     size
5005  U32 max_ccb (IN)                  count
5006
5007Return:
5008Note:
5009******************************************************************************/
5010STATIC void agtiapi_PrepCCBs( struct agtiapi_softc *pCard,
5011                              ccb_hdr_t *hdr,
5012                              U32 size,
5013                              U32 max_ccb,
5014                              int tid )
5015{
5016
5017  int i;
5018  U32 hdr_sz, ccb_sz;
5019  ccb_t *pccb = NULL;
5020  int offset = 0;
5021  int nsegs = 0;
5022  int sgl_sz = 0;
5023
5024  AGTIAPI_PRINTK("agtiapi_PrepCCBs: start\n");
5025  offset = tid * AGTIAPI_CCB_PER_DEVICE;
5026  nsegs = AGTIAPI_NSEGS;
5027  sgl_sz = sizeof(tiSgl_t) * nsegs;
5028  AGTIAPI_PRINTK( "agtiapi_PrepCCBs: tid %d offset %d nsegs %d sizeof(tiSgl_t) "
5029                  "%lu, max_ccb %d\n",
5030                  tid,
5031                  offset,
5032                  nsegs,
5033                  sizeof(tiSgl_t),
5034                  max_ccb );
5035
5036  ccb_sz = roundup2(AGTIAPI_CCB_SIZE, cache_line_size());
5037  hdr_sz = roundup2(sizeof(*hdr), cache_line_size());
5038
5039  AGTIAPI_PRINTK("agtiapi_PrepCCBs: after cache line\n");
5040
5041  memset((void *)hdr, 0, size);
5042  hdr->next = pCard->ccbAllocList;
5043  pCard->ccbAllocList = hdr;
5044
5045  AGTIAPI_PRINTK("agtiapi_PrepCCBs: after memset\n");
5046
5047  pccb = (ccb_t*) ((char*)hdr + hdr_sz);
5048
5049  for (i = 0; i < max_ccb; i++, pccb = (ccb_t*)((char*)pccb + ccb_sz))
5050  {
5051    pccb->tiIORequest.osData = (void *)pccb;
5052
5053    /*
5054     * Initially put all the ccbs on the free list
5055     * in addition to chainlist.
5056     * ccbChainList is a list of all available ccbs
5057     * (free/active everything)
5058     */
5059    pccb->pccbChainNext = (pccb_t)pCard->ccbChainList;
5060    pccb->pccbNext      = (pccb_t)pCard->ccbFreeList;
5061
5062    pCard->ccbChainList = (caddr_t *)pccb;
5063    pCard->ccbFreeList  = (caddr_t *)pccb;
5064    pCard->ccbTotal++;
5065
5066#ifdef AGTIAPI_ALIGN_CHECK
5067    if (&pccb & 0x63)
5068      AGTIAPI_PRINTK("pccb = %p\n", pccb);
5069    if (pccb->devHandle & 0x63)
5070      AGTIAPI_PRINTK("devHandle addr = %p\n", &pccb->devHandle);
5071    if (&pccb->lun & 0x63)
5072      AGTIAPI_PRINTK("lun addr = %p\n", &pccb->lun);
5073    if (&pccb->targetId & 0x63)
5074      AGTIAPI_PRINTK("tig addr = %p\n", &pccb->targetId);
5075    if (&pccb->ccbStatus & 0x63)
5076      AGTIAPI_PRINTK("ccbStatus addr = %p\n", &pccb->ccbStatus);
5077    if (&pccb->scsiStatus & 0x63)
5078      AGTIAPI_PRINTK("scsiStatus addr = %p\n", &pccb->scsiStatus);
5079    if (&pccb->dataLen & 0x63)
5080      AGTIAPI_PRINTK("dataLen addr = %p\n", &pccb->dataLen);
5081    if (&pccb->senseLen & 0x63)
5082      AGTIAPI_PRINTK("senseLen addr = %p\n", &pccb->senseLen);
5083    if (&pccb->numSgElements & 0x63)
5084      AGTIAPI_PRINTK("numSgElements addr = %p\n", &pccb->numSgElements);
5085    if (&pccb->retryCount & 0x63)
5086      AGTIAPI_PRINTK("retry cnt addr = %p\n", &pccb->retryCount);
5087    if (&pccb->flags & 0x63)
5088      AGTIAPI_PRINTK("flag addr = %p\n", &pccb->flags);
5089    if (&pccb->pSenseData & 0x63)
5090      AGTIAPI_PRINTK("senseData addr = %p\n", &pccb->pSenseData);
5091    if (&pccb->sgList[0] & 0x63)
5092      AGTIAPI_PRINTK("SgList 0 = %p\n", &pccb->sgList[0]);
5093    if (&pccb->pccbNext & 0x63)
5094      AGTIAPI_PRINTK("ccb next = %p\n", &pccb->pccbNext);
5095    if (&pccb->pccbChainNext & 0x63)
5096      AGTIAPI_PRINTK("ccbChainNext = %p\n", &pccb->pccbChainNext);
5097    if (&pccb->cmd & 0x63)
5098      AGTIAPI_PRINTK("command = %p\n", &pccb->cmd);
5099    if( &pccb->startTime & 0x63 )
5100      AGTIAPI_PRINTK( "startTime = %p\n", &pccb->startTime );
5101    if (&pccb->tiIORequest & 0x63)
5102      AGTIAPI_PRINTK("tiIOReq addr = %p\n", &pccb->tiIORequest);
5103    if (&pccb->tdIOReqBody & 0x63)
5104      AGTIAPI_PRINTK("tdIORequestBody addr = %p\n", &pccb->tdIOReqBody);
5105    if (&pccb->tiSuperScsiRequest & 0x63)
5106      AGTIAPI_PRINTK( "InitiatorExchange addr = %p\n",
5107                      &pccb->tiSuperScsiRequest );
5108#endif
5109    if ( bus_dmamap_create( pCard->buffer_dmat, 0, &pccb->CCB_dmamap ) !=
5110         tiSuccess)
5111    {
5112      AGTIAPI_PRINTK("agtiapi_PrepCCBs: can't create dma\n");
5113      return;
5114    }
5115    /* assigns tiSgl_t memory to pccb */
5116    pccb->sgList = (void*)((U64)pCard->tisgl_mem + ((i + offset) * sgl_sz));
5117    pccb->tisgl_busaddr = pCard->tisgl_busaddr + ((i + offset) * sgl_sz);
5118    pccb->ccb = NULL;
5119    pccb->pccbIO = NULL;
5120    pccb->startTime = 0;
5121  }
5122
5123#ifdef AGTIAPI_ALIGN_CHECK
5124  AGTIAPI_PRINTK("ccb size = %d / %d\n", sizeof(ccb_t), ccb_sz);
5125#endif
5126  return;
5127}
5128
5129/******************************************************************************
5130agtiapi_InitCCBs()
5131
5132Purpose:
5133  Create and initialize per card based CCB pool.
5134Parameters:
5135  struct agtiapi_softc *pCard (IN)  Pointer to the HBA data structure
5136  int tgtCount (IN)                 Count
5137Return:
5138  Total number of ccb allocated
5139Note:
5140******************************************************************************/
5141STATIC U32 agtiapi_InitCCBs(struct agtiapi_softc *pCard, int tgtCount, int tid)
5142{
5143
5144  U32   max_ccb, size, ccb_sz, hdr_sz;
5145  int   no_allocs = 0, i;
5146  ccb_hdr_t  *hdr = NULL;
5147
5148  AGTIAPI_PRINTK("agtiapi_InitCCBs: start\n");
5149  AGTIAPI_PRINTK("agtiapi_InitCCBs: tgtCount %d tid %d\n", tgtCount, tid);
5150  AGTIAPI_FLOW("agtiapi_InitCCBs: tgtCount %d tid %d\n", tgtCount, tid);
5151
5152#ifndef HOTPLUG_SUPPORT
5153  if (pCard->tgtCount > AGSA_MAX_INBOUND_Q)
5154    return 1;
5155#else
5156  if (tgtCount > AGSA_MAX_INBOUND_Q)
5157    tgtCount = AGSA_MAX_INBOUND_Q;
5158#endif
5159
5160  max_ccb = tgtCount * AGTIAPI_CCB_PER_DEVICE;//      / 4; // TBR
5161  ccb_sz = roundup2(AGTIAPI_CCB_SIZE, cache_line_size());
5162  hdr_sz = roundup2(sizeof(*hdr), cache_line_size());
5163  size = ccb_sz * max_ccb + hdr_sz;
5164
5165  for (i = 0; i < (1 << no_allocs); i++)
5166  {
5167    hdr = (ccb_hdr_t*)malloc( size, M_PMC_MCCB, M_NOWAIT );
5168    if( !hdr )
5169    {
5170      panic( "agtiapi_InitCCBs: bug!!!\n" );
5171    }
5172    else
5173    {
5174      agtiapi_PrepCCBs( pCard, hdr, size, max_ccb, tid );
5175    }
5176  }
5177
5178  return 1;
5179
5180}
5181
5182
5183#ifdef LINUX_PERBI_SUPPORT
5184/******************************************************************************
5185agtiapi_GetWWNMappings()
5186
5187Purpose:
5188  Get the mappings from target IDs to WWNs, if any.
5189  Store them in the WWN_list array, indexed by target ID.
5190  Leave the devListIndex field blank; this will be filled-in later.
5191Parameters:
5192  ag_card_t *pCard (IN)        Pointer to HBA data structure
5193  ag_mapping_t *pMapList (IN)  Pointer to mapped device list
5194Return:
5195Note:  The boot command line parameters are used to load the
5196  mapping information, which is contained in the system
5197  configuration file.
5198******************************************************************************/
5199STATIC void agtiapi_GetWWNMappings( struct agtiapi_softc *pCard,
5200                                    ag_mapping_t         *pMapList )
5201{
5202  int           devDisc;
5203  int           lIdx = 0;
5204  ag_tgt_map_t *pWWNList;
5205  ag_slr_map_t *pSLRList;
5206  ag_device_t  *pDevList;
5207
5208  if( !pCard )
5209    panic( "agtiapi_GetWWNMappings: no pCard \n" );
5210
5211  AGTIAPI_PRINTK( "agtiapi_GetWWNMappings: start\n" );
5212
5213  pWWNList = pCard->pWWNList;
5214  pSLRList = pCard->pSLRList;
5215  pDevList = pCard->pDevList;
5216  pCard->numTgtHardMapped = 0;
5217  devDisc = pCard->devDiscover;
5218
5219  pWWNList[devDisc-1].devListIndex  = maxTargets;
5220  pSLRList[devDisc-1].localeNameLen = -2;
5221  pSLRList[devDisc-1].remoteNameLen = -2;
5222  pDevList[devDisc-1].targetId      = maxTargets;
5223
5224  /*
5225   * Get the mappings from holding area which contains
5226   * the input of the system file and store them
5227   * in the WWN_list array, indexed by target ID.
5228   */
5229  for ( lIdx = 0; lIdx < devDisc - 1; lIdx++) {
5230    pWWNList[lIdx].flags = 0;
5231    pWWNList[lIdx].devListIndex  = maxTargets;
5232    pSLRList[lIdx].localeNameLen = -1;
5233    pSLRList[lIdx].remoteNameLen = -1;
5234  }
5235
5236  //  this is where we would propagate values fed to pMapList
5237
5238} /* agtiapi_GetWWNMappings */
5239
5240#endif
5241
5242
5243/******************************************************************************
5244agtiapi_FindWWNListNext()
5245Purpose:
5246  finds first available new (unused) wwn list entry
5247
5248Parameters:
5249  ag_tgt_map_t *pWWNList              Pointer to head of wwn list
5250  int lstMax                          Number of entries in WWNList
5251Return:
5252  index into WWNList indicating available entry space;
5253  if available entry space is not found, return negative value
5254******************************************************************************/
5255STATIC int agtiapi_FindWWNListNext( ag_tgt_map_t *pWWNList, int lstMax )
5256{
5257  int  lLstIdx;
5258
5259  for ( lLstIdx = 0; lLstIdx < lstMax; lLstIdx++ )
5260  {
5261    if ( pWWNList[lLstIdx].devListIndex == lstMax &&
5262         pWWNList[lLstIdx].targetLen == 0 )
5263    {
5264      AGTIAPI_PRINTK( "agtiapi_FindWWNListNext: %d %d %d %d v. %d\n",
5265                      lLstIdx,
5266                      pWWNList[lLstIdx].devListIndex,
5267                      pWWNList[lLstIdx].targetLen,
5268                      pWWNList[lLstIdx].portId,
5269                      lstMax );
5270      return lLstIdx;
5271    }
5272  }
5273  return -1;
5274}
5275
5276
5277/******************************************************************************
5278agtiapi_GetDevHandle()
5279
5280Purpose:
5281  Get device handle.  Handles will be placed in the
5282  devlist array with same order as TargetList provided and
5283  will be mapped to a scsi target id and registered to OS later.
5284Parameters:
5285  struct agtiapi_softc *pCard (IN)    Pointer to the HBA data structure
5286  ag_portal_info_t *pPortalInfo (IN)  Pointer to the portal data structure
5287  U32 eType (IN)                      Port event
5288  U32 eStatus (IN)                    Port event status
5289Return:
5290  Number of device handle slot present
5291Note:
5292  The sequence of device handle will match the sequence of taregt list
5293******************************************************************************/
5294STATIC U32 agtiapi_GetDevHandle( struct agtiapi_softc *pCard,
5295                                 ag_portal_info_t *pPortalInfo,
5296                                 U32 eType,
5297                                 U32 eStatus )
5298{
5299  ag_device_t       *pDevice;
5300  // tiDeviceHandle_t *agDev[pCard->devDiscover];
5301  tiDeviceHandle_t **agDev;
5302  int                devIdx, szdv, devTotal, cmpsetRtn;
5303  int                lDevIndex = 0, lRunScanFlag = FALSE;
5304  int               *lDevFlags;
5305  tiPortInfo_t       portInfT;
5306  ag_device_t        lTmpDevice;
5307  ag_tgt_map_t      *pWWNList;
5308  ag_slr_map_t      *pSLRList;
5309  bit32              lReadRm;
5310  bit16              lReadCt;
5311
5312
5313  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: start\n" );
5314  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: pCard->devDiscover %d / tgtCt %d\n",
5315                  pCard->devDiscover, pCard->tgtCount );
5316  AGTIAPI_FLOW( "agtiapi_GetDevHandle: portalInfo %p\n", pPortalInfo );
5317  AGTIAPI_INIT_DELAY( 1000 );
5318
5319  agDev = (tiDeviceHandle_t **) malloc( sizeof(tiDeviceHandle_t *) * pCard->devDiscover,
5320                                        M_PMC_MDEV, M_ZERO | M_NOWAIT);
5321  if (agDev == NULL)
5322  {
5323    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: failed to alloc agDev[]\n" );
5324    return 0;
5325  }
5326
5327  lDevFlags = (int *) malloc( sizeof(int) * pCard->devDiscover,
5328                              M_PMC_MFLG, M_ZERO | M_NOWAIT );
5329  if (lDevFlags == NULL)
5330  {
5331    free((caddr_t)agDev, M_PMC_MDEV);
5332    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: failed to alloc lDevFlags[]\n" );
5333    return 0;
5334  }
5335
5336  pWWNList = pCard->pWWNList;
5337  pSLRList = pCard->pSLRList;
5338
5339  memset( (void *)agDev, 0, sizeof(void *) * pCard->devDiscover );
5340  memset( lDevFlags,     0, sizeof(int)    * pCard->devDiscover );
5341
5342  // get device handles
5343  devTotal = tiINIGetDeviceHandles( &pCard->tiRoot,
5344                                    &pPortalInfo->tiPortalContext,
5345                                    (tiDeviceHandle_t **)agDev,
5346                                    pCard->devDiscover );
5347
5348  AGTIAPI_PRINTK( "agtiapi_GetDevHandle: portalInfo %p port id %d event %u "
5349                  "status %u card %p pCard->devDiscover %d devTotal %d "
5350                  "pPortalInfo->devTotal %d pPortalInfo->devPrev %d "
5351                  "AGTIAPI_INIT_TIME %x\n",
5352                  pPortalInfo, pPortalInfo->portID, eType, eStatus, pCard,
5353                  pCard->devDiscover, devTotal, pPortalInfo->devTotal,
5354                  pPortalInfo->devPrev,
5355                  pCard->flags & AGTIAPI_INIT_TIME );
5356
5357  // reset devTotal from any previous runs of this
5358  pPortalInfo->devPrev  = devTotal;
5359  pPortalInfo->devTotal = devTotal;
5360
5361  AG_LIST_LOCK( &pCard->devListLock );
5362
5363  if ( tiCOMGetPortInfo( &pCard->tiRoot,
5364                         &pPortalInfo->tiPortalContext,
5365                         &portInfT )
5366       != tiSuccess)
5367  {
5368    AGTIAPI_PRINTK( "agtiapi_GetDevHandle: tiCOMGetPortInfo did not succeed. \n" );
5369  }
5370
5371
5372  szdv = sizeof( pPortalInfo->pDevList ) / sizeof( pPortalInfo->pDevList[0] );
5373  if (szdv > pCard->devDiscover)
5374  {
5375    szdv = pCard->devDiscover;
5376  }
5377
5378  // reconstructing dev list via comparison of wwn
5379
5380  for ( devIdx = 0; devIdx < pCard->devDiscover; devIdx++ )
5381  {
5382    if ( agDev[devIdx] != NULL )
5383    {
5384      // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: agDev %d not NULL %p\n",
5385      //                 devIdx, agDev[devIdx] );
5386
5387      // pack temp device structure for tiINIGetDeviceInfo call
5388      pDevice                  = &lTmpDevice;
5389      pDevice->devType         = DIRECT_DEVICE;
5390      pDevice->pCard           = (void *)pCard;
5391      pDevice->flags           = ACTIVE;
5392      pDevice->pPortalInfo     = pPortalInfo;
5393      pDevice->pDevHandle      = agDev[devIdx];
5394      pDevice->qbusy           = agFALSE;
5395
5396      //AGTIAPI_PRINTK( "agtiapi_GetDevHandle: idx %d / %d : %p \n",
5397      //                devIdx, pCard->devDiscover, agDev[devIdx] );
5398
5399      tiINIGetDeviceInfo( &pCard->tiRoot, agDev[devIdx],
5400                          &pDevice->devInfo );
5401
5402      //AGTIAPI_PRINTK( "agtiapi_GetDevHandle: wwn sizes %ld %d/%d ",
5403      //                sizeof(pDevice->targetName),
5404      //                pDevice->devInfo.osAddress1,
5405      //                pDevice->devInfo.osAddress2 );
5406
5407      wwncpy( pDevice );
5408      wwnprintk( (unsigned char*)pDevice->targetName, pDevice->targetLen );
5409
5410      for ( lDevIndex = 0; lDevIndex < szdv; lDevIndex++ ) // match w/ wwn list
5411      {
5412        if ( (pCard->pDevList[lDevIndex].portalId == pPortalInfo->portID) &&
5413             pDevice->targetLen     > 0 &&
5414             portInfT.localNameLen  > 0 &&
5415             portInfT.remoteNameLen > 0 &&
5416             pSLRList[pWWNList[lDevIndex].sasLrIdx].localeNameLen > 0 &&
5417             pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteNameLen > 0 &&
5418             ( portInfT.localNameLen ==
5419               pSLRList[pWWNList[lDevIndex].sasLrIdx].localeNameLen ) &&
5420             ( portInfT.remoteNameLen ==
5421               pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteNameLen ) &&
5422             memcmp( pWWNList[lDevIndex].targetName, pDevice->targetName,
5423                     pDevice->targetLen )   == 0  &&
5424             memcmp( pSLRList[pWWNList[lDevIndex].sasLrIdx].localeName,
5425                     portInfT.localName,
5426                     portInfT.localNameLen )   == 0  &&
5427             memcmp( pSLRList[pWWNList[lDevIndex].sasLrIdx].remoteName,
5428                     portInfT.remoteName,
5429                     portInfT.remoteNameLen )   == 0  )
5430        {
5431          AGTIAPI_PRINTK( " pWWNList match @ %d/%d/%d \n",
5432                          lDevIndex, devIdx, pPortalInfo->portID );
5433
5434          if ( (pCard->pDevList[lDevIndex].targetId == lDevIndex) &&
5435               ( pPortalInfo->pDevList[lDevIndex] ==
5436                 &pCard->pDevList[lDevIndex] )  ) // active
5437          {
5438
5439            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: dev in use %d of %d/%d\n",
5440                            lDevIndex, devTotal, pPortalInfo->portID );
5441            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev handle
5442            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5443            lReadRm = atomic_readandclear_32( &pWWNList[lDevIndex].devRemoved );
5444            if ( lReadRm )   // cleared timeout, now remove count for timer
5445            {
5446              AGTIAPI_PRINTK( "agtiapi_GetDevHandle: clear timer count for"
5447                              " %d of %d\n",
5448                              lDevIndex, pPortalInfo->portID );
5449              atomic_subtract_16( &pCard->rmChkCt, 1 );
5450              lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
5451              if ( 0 == lReadCt )
5452              {
5453                callout_stop( &pCard->devRmTimer );
5454              }
5455            }
5456            break;
5457          }
5458
5459          AGTIAPI_PRINTK( "agtiapi_GetDevHandle: goin fresh on %d of %d/%d\n",
5460                          lDevIndex,  // reactivate now
5461                          devTotal, pPortalInfo->portID );
5462
5463          // pDevice going fresh
5464          lRunScanFlag = TRUE; // scan and clear outstanding removals
5465
5466          // pCard->tgtCount++; ##
5467          pDevice->targetId  = lDevIndex;
5468          pDevice->portalId  = pPortalInfo->portID;
5469
5470          memcpy ( &pCard->pDevList[lDevIndex], pDevice, sizeof(lTmpDevice) );
5471          agDev[devIdx]->osData = (void *)&pCard->pDevList[lDevIndex];
5472          if ( agtiapi_InitCCBs( pCard, 1, pDevice->targetId ) == 0 )
5473          {
5474            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: InitCCB "
5475                            "tgtCnt %d ERROR!\n", pCard->tgtCount );
5476            AG_LIST_UNLOCK( &pCard->devListLock );
5477            free((caddr_t)lDevFlags, M_PMC_MFLG);
5478            free((caddr_t)agDev, M_PMC_MDEV);
5479            return 0;
5480          }
5481          pPortalInfo->pDevList[lDevIndex] = &pCard->pDevList[lDevIndex];     // (ag_device_t *)
5482          if ( 0 == lDevFlags[devIdx] )
5483          {
5484            pPortalInfo->devTotal++;
5485            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev used
5486            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5487          }
5488          else
5489          {
5490            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: odd dev handle "
5491                            "status inspect %d %d %d\n",
5492                            lDevFlags[devIdx], devIdx, lDevIndex );
5493            pPortalInfo->devTotal++;
5494            lDevFlags[devIdx]    |= DPMC_LEANFLAG_AGDEVUSED; // agDev used
5495            lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // pDevice used
5496
5497          }
5498          break;
5499        }
5500      }
5501      // end: match this wwn with previous wwn list
5502
5503      // we have an agDev entry, but no pWWNList target for it
5504      if ( !(lDevFlags[devIdx] & DPMC_LEANFLAG_AGDEVUSED) )
5505      { // flag dev handle not accounted for yet
5506        lDevFlags[devIdx] |= DPMC_LEANFLAG_NOWWNLIST;
5507        // later, get an empty pDevice and map this agDev.
5508        // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: devIdx %d flags 0x%x, %d\n",
5509        //                 devIdx, lDevFlags[devIdx], (lDevFlags[devIdx] & 8) );
5510      }
5511    }
5512    else
5513    {
5514      lDevFlags[devIdx] |= DPMC_LEANFLAG_NOAGDEVYT; // known empty agDev handle
5515    }
5516  }
5517
5518  // AGTIAPI_PRINTK( "agtiapi_GetDevHandle: all WWN all the time, "
5519  //                 "devLstIdx/flags/(WWNL)portId ... \n" );
5520  // review device list for further action needed
5521  for ( devIdx = 0; devIdx < pCard->devDiscover; devIdx++ )
5522  {
5523    if ( lDevFlags[devIdx] & DPMC_LEANFLAG_NOWWNLIST ) // new target, register
5524    {
5525      int lNextDyad; // find next available dyad entry
5526
5527      AGTIAPI_PRINTK( "agtiapi_GetDevHandle: register new target, "
5528                      "devIdx %d -- %d \n", devIdx, pCard->devDiscover );
5529      lRunScanFlag = TRUE; // scan and clear outstanding removals
5530      for ( lNextDyad = 0; lNextDyad < pCard->devDiscover; lNextDyad++ )
5531      {
5532        if ( pSLRList[lNextDyad].localeNameLen < 0 &&
5533             pSLRList[lNextDyad].remoteNameLen < 0    )
5534          break;
5535      }
5536
5537      if ( lNextDyad == pCard->devDiscover )
5538      {
5539        printf( "agtiapi_GetDevHandle: failed to find available SAS LR\n" );
5540        AG_LIST_UNLOCK( &pCard->devListLock );
5541        free( (caddr_t)lDevFlags, M_PMC_MFLG );
5542        free( (caddr_t)agDev, M_PMC_MDEV );
5543        return 0;
5544      }
5545      // index of new entry
5546      lDevIndex = agtiapi_FindWWNListNext( pWWNList, pCard->devDiscover );
5547      AGTIAPI_PRINTK( "agtiapi_GetDevHandle: listIdx new target %d of %d/%d\n",
5548                      lDevIndex, devTotal, pPortalInfo->portID );
5549      if ( 0 > lDevIndex )
5550      {
5551        printf( "agtiapi_GetDevHandle: WARNING -- WWNList exhausted.\n" );
5552        continue;
5553      }
5554
5555      pDevice = &pCard->pDevList[lDevIndex];
5556
5557      tiINIGetDeviceInfo( &pCard->tiRoot, agDev[devIdx], &pDevice->devInfo );
5558      wwncpy( pDevice );
5559      agtiapi_InitCCBs( pCard, 1, lDevIndex );
5560
5561      pDevice->pCard   = (void *)pCard;
5562      pDevice->devType = DIRECT_DEVICE;
5563
5564      // begin to populate new WWNList entry
5565      memcpy( pWWNList[lDevIndex].targetName, pDevice->targetName, pDevice->targetLen );
5566      pWWNList[lDevIndex].targetLen = pDevice->targetLen;
5567
5568      pWWNList[lDevIndex].flags         = SOFT_MAPPED;
5569      pWWNList[lDevIndex].portId        = pPortalInfo->portID;
5570      pWWNList[lDevIndex].devListIndex  = lDevIndex;
5571      pWWNList[lDevIndex].sasLrIdx      = lNextDyad;
5572
5573      pSLRList[lNextDyad].localeNameLen = portInfT.localNameLen;
5574      pSLRList[lNextDyad].remoteNameLen = portInfT.remoteNameLen;
5575      memcpy( pSLRList[lNextDyad].localeName, portInfT.localName, portInfT.localNameLen );
5576      memcpy( pSLRList[lNextDyad].remoteName, portInfT.remoteName, portInfT.remoteNameLen );
5577      // end of populating new WWNList entry
5578
5579      pDevice->targetId = lDevIndex;
5580
5581      pDevice->flags = ACTIVE;
5582      pDevice->CCBCount = 0;
5583      pDevice->pDevHandle = agDev[devIdx];
5584      agDev[devIdx]->osData = (void*)pDevice;
5585
5586      pDevice->pPortalInfo = pPortalInfo;
5587      pDevice->portalId = pPortalInfo->portID;
5588      pPortalInfo->pDevList[lDevIndex] = (void*)pDevice;
5589      lDevFlags[lDevIndex] |= DPMC_LEANFLAG_PDEVSUSED; // mark pDevice slot used
5590    }
5591
5592    if ( (pCard->pDevList[devIdx].portalId == pPortalInfo->portID) &&
5593         !(lDevFlags[devIdx] & DPMC_LEANFLAG_PDEVSUSED) ) // pDevice not used
5594    {
5595      pDevice = &pCard->pDevList[devIdx];
5596      //pDevice->flags &= ~ACTIVE;
5597      if ( ( pDevice->pDevHandle != NULL ||
5598             pPortalInfo->pDevList[devIdx] != NULL ) )
5599      {
5600        atomic_add_16( &pCard->rmChkCt, 1 );      // show count of lost device
5601
5602        if (FALSE == lRunScanFlag)
5603        {
5604
5605          AGTIAPI_PRINTK( "agtiapi_GetDevHandle: targ dropped out %d of %d/%d\n",
5606                          devIdx, devTotal, pPortalInfo->portID );
5607          // if ( 0 == pWWNList[devIdx].devRemoved ) '.devRemoved = 5;
5608          cmpsetRtn = atomic_cmpset_32( &pWWNList[devIdx].devRemoved, 0, 5 );
5609          if ( 0 == cmpsetRtn )
5610          {
5611            AGTIAPI_PRINTK( "agtiapi_GetDevHandle: target %d timer already set\n",
5612                    devIdx );
5613          }
5614          else
5615          {
5616            callout_reset( &pCard->devRmTimer, 1 * hz, agtiapi_devRmCheck, pCard );
5617          }
5618        }
5619        // else ... scan coming soon enough anyway, ignore timer for dropout
5620      }
5621    }
5622  } // end of for ( devIdx = 0; ...
5623
5624  AG_LIST_UNLOCK( &pCard->devListLock );
5625
5626  free((caddr_t)lDevFlags, M_PMC_MFLG);
5627  free((caddr_t)agDev, M_PMC_MDEV);
5628
5629  if ( TRUE == lRunScanFlag )
5630    agtiapi_clrRmScan( pCard );
5631
5632  return devTotal;
5633} // end  agtiapi_GetDevHandle
5634
5635/******************************************************************************
5636agtiapi_scan()
5637
5638Purpose:
5639  Triggers CAM's scan
5640Parameters:
5641  struct agtiapi_softc *pCard (IN)    Pointer to the HBA data structure
5642Return:
5643Note:
5644******************************************************************************/
5645static void agtiapi_scan(struct agtiapi_softc *pmcsc)
5646{
5647  union ccb *ccb;
5648  int bus, tid, lun;
5649
5650  AGTIAPI_PRINTK("agtiapi_scan: start cardNO %d \n", pmcsc->cardNo);
5651
5652  bus = cam_sim_path(pmcsc->sim);
5653
5654  tid = CAM_TARGET_WILDCARD;
5655  lun = CAM_LUN_WILDCARD;
5656
5657  mtx_lock(&(pmcsc->pCardInfo->pmIOLock));
5658  ccb = xpt_alloc_ccb_nowait();
5659  if (ccb == agNULL)
5660  {
5661    mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5662    return;
5663  }
5664  if (xpt_create_path(&ccb->ccb_h.path, agNULL, bus, tid,
5665		      CAM_LUN_WILDCARD) != CAM_REQ_CMP)
5666  {
5667    mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5668    xpt_free_ccb(ccb);
5669    return;
5670  }
5671
5672  mtx_unlock(&(pmcsc->pCardInfo->pmIOLock));
5673  pmcsc->dev_scan = agTRUE;
5674  xpt_rescan(ccb);
5675  return;
5676}
5677
5678/******************************************************************************
5679agtiapi_DeQueueCCB()
5680
5681Purpose:
5682  Remove a ccb from a queue
5683Parameters:
5684  struct agtiapi_softc *pCard (IN)  Pointer to the card structure
5685  pccb_t *phead (IN)     Pointer to a head of ccb queue
5686  ccb_t  *pccd  (IN)     Pointer to the ccb to be processed
5687Return:
5688  AGTIAPI_SUCCESS - the ccb is removed from queue
5689  AGTIAPI_FAIL    - the ccb is not found from queue
5690Note:
5691******************************************************************************/
5692STATIC agBOOLEAN
5693agtiapi_DeQueueCCB(struct agtiapi_softc *pCard, pccb_t *phead, pccb_t *ptail,
5694#ifdef AGTIAPI_LOCAL_LOCK
5695                   struct mtx *lock,
5696#endif
5697                   ccb_t *pccb)
5698{
5699  ccb_t  *pccb_curr;
5700  U32     status = AGTIAPI_FAIL;
5701
5702  AGTIAPI_PRINTK("agtiapi_DeQueueCCB: %p from %p\n", pccb, phead);
5703
5704  if (pccb == NULL || *phead == NULL)
5705  {
5706    return AGTIAPI_FAIL;
5707  }
5708
5709  AGTIAPI_PRINTK("agtiapi_DeQueueCCB: %p from %p\n", pccb, phead);
5710  AG_LOCAL_LOCK(lock);
5711
5712  if (pccb == *phead)
5713  {
5714    *phead = (*phead)->pccbNext;
5715    if (pccb == *ptail)
5716    {
5717      *ptail = NULL;
5718    }
5719    else
5720      pccb->pccbNext = NULL;
5721    status = AGTIAPI_SUCCESS;
5722  }
5723  else
5724  {
5725    pccb_curr = *phead;
5726    while (pccb_curr->pccbNext != NULL)
5727    {
5728      if (pccb_curr->pccbNext == pccb)
5729      {
5730        pccb_curr->pccbNext = pccb->pccbNext;
5731        pccb->pccbNext = NULL;
5732        if (pccb == *ptail)
5733        {
5734          *ptail = pccb_curr;
5735        }
5736        else
5737          pccb->pccbNext = NULL;
5738        status = AGTIAPI_SUCCESS;
5739        break;
5740      }
5741      pccb_curr = pccb_curr->pccbNext;
5742    }
5743  }
5744  AG_LOCAL_UNLOCK(lock);
5745
5746  return status;
5747}
5748
5749
5750STATIC void wwnprintk( unsigned char *name, int len )
5751{
5752  int i;
5753
5754  for (i = 0; i < len; i++, name++)
5755    AGTIAPI_PRINTK("%02x", *name);
5756  AGTIAPI_PRINTK("\n");
5757}
5758/*
5759 * SAS and SATA behind expander has 8 byte long unique address.
5760 * However, direct connect SATA device use 512 byte unique device id.
5761 * SPC uses remoteName to indicate length of ID and remoteAddress for the
5762 * address of memory that holding ID.
5763 */
5764STATIC int wwncpy( ag_device_t      *pDevice )
5765{
5766  int rc = 0;
5767
5768  if (sizeof(pDevice->targetName) >= pDevice->devInfo.osAddress1 +
5769                                     pDevice->devInfo.osAddress2)
5770  {
5771    memcpy(pDevice->targetName,
5772             pDevice->devInfo.remoteName,
5773             pDevice->devInfo.osAddress1);
5774    memcpy(pDevice->targetName + pDevice->devInfo.osAddress1,
5775             pDevice->devInfo.remoteAddress,
5776             pDevice->devInfo.osAddress2);
5777    pDevice->targetLen = pDevice->devInfo.osAddress1 +
5778                         pDevice->devInfo.osAddress2;
5779    rc = pDevice->targetLen;
5780  }
5781  else
5782  {
5783    AGTIAPI_PRINTK("WWN wrong size: %d + %d ERROR\n",
5784           pDevice->devInfo.osAddress1, pDevice->devInfo.osAddress2);
5785    rc = -1;
5786  }
5787  return rc;
5788}
5789
5790
5791/******************************************************************************
5792agtiapi_ReleaseCCBs()
5793
5794Purpose:
5795  Free all allocated CCB memories for the Host Adapter.
5796Parameters:
5797  struct agtiapi_softc *pCard (IN)  Pointer to HBA data structure
5798Return:
5799Note:
5800******************************************************************************/
5801STATIC void agtiapi_ReleaseCCBs( struct agtiapi_softc *pCard )
5802{
5803
5804  ccb_hdr_t *hdr;
5805  U32 hdr_sz;
5806  ccb_t *pccb = NULL;
5807
5808  AGTIAPI_PRINTK( "agtiapi_ReleaseCCBs: start\n" );
5809
5810#if ( defined AGTIAPI_TEST_DPL || defined AGTIAPI_TEST_EPL )
5811  ccb_t *pccb;
5812#endif
5813
5814#ifdef AGTIAPI_TEST_DPL
5815  for (pccb = (pccb_t)pCard->ccbChainList; pccb != NULL;
5816       pccb = pccb->pccbChainNext)
5817  {
5818    if(pccb->dplPtr && pccb->dplDma)
5819      pci_pool_free(pCard->dpl_ctx_pool,   pccb->dplPtr, pccb->dplDma);
5820  }
5821#endif
5822
5823#ifdef AGTIAPI_TEST_EPL
5824  for (pccb = (pccb_t)pCard->ccbChainList; pccb != NULL;
5825       pccb = pccb->pccbChainNext)
5826  {
5827    if(pccb->epl_ptr && pccb->epl_dma_ptr)
5828        pci_pool_free(
5829            pCard->epl_ctx_pool,
5830            pccb->epl_ptr,
5831            pccb->epl_dma_ptr
5832        );
5833  }
5834#endif
5835
5836  while ((hdr = pCard->ccbAllocList) != NULL)
5837  {
5838    pCard->ccbAllocList = hdr->next;
5839    hdr_sz = roundup2(sizeof(*hdr), cache_line_size());
5840    pccb = (ccb_t*) ((char*)hdr + hdr_sz);
5841    if (pCard->buffer_dmat != NULL && pccb->CCB_dmamap != NULL)
5842    {
5843      bus_dmamap_destroy(pCard->buffer_dmat, pccb->CCB_dmamap);
5844    }
5845    free(hdr, M_PMC_MCCB);
5846  }
5847  pCard->ccbAllocList = NULL;
5848
5849
5850  return;
5851}
5852
5853/******************************************************************************
5854agtiapi_TITimer()
5855
5856Purpose:
5857  Timer tick for tisa common layer
5858Parameters:
5859  void *data (IN)  Pointer to the HBA data structure
5860Return:
5861Note:
5862******************************************************************************/
5863STATIC void agtiapi_TITimer( void *data )
5864{
5865
5866  U32                   next_tick;
5867  struct agtiapi_softc *pCard;
5868
5869  pCard = (struct agtiapi_softc *)data;
5870
5871//  AGTIAPI_PRINTK("agtiapi_TITimer: start\n");
5872  AG_GLOBAL_ARG( flags );
5873
5874  next_tick = pCard->pCardInfo->tiRscInfo.tiLoLevelResource.
5875              loLevelOption.usecsPerTick / USEC_PER_TICK;
5876
5877  if( next_tick == 0 )               /* no timer required */
5878    return;
5879  AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
5880  if( pCard->flags & AGTIAPI_SHUT_DOWN )
5881    goto ext;
5882  tiCOMTimerTick( &pCard->tiRoot );  /* tisa common layer timer tick */
5883
5884  //add for polling mode
5885#ifdef PMC_SPC
5886  if( agtiapi_polling_mode )
5887    agtiapi_CheckAllVectors( pCard, tiNonInterruptContext );
5888#endif
5889  callout_reset( &pCard->OS_timer, next_tick, agtiapi_TITimer, pCard );
5890ext:
5891  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
5892  return;
5893}
5894
5895/******************************************************************************
5896agtiapi_clrRmScan()
5897
5898Purpose:
5899  Clears device list entries scheduled for timeout and calls scan
5900Parameters:
5901  struct agtiapi_softc *pCard (IN)  Pointer to HBA data structure
5902******************************************************************************/
5903STATIC void agtiapi_clrRmScan( struct agtiapi_softc *pCard )
5904{
5905  ag_tgt_map_t         *pWWNList;
5906  ag_portal_info_t     *pPortalInfo;
5907  ag_portal_data_t     *pPortalData;
5908  int                   lIdx;
5909  bit32                 lReadRm;
5910  bit16                 lReadCt;
5911
5912  pWWNList = pCard->pWWNList;
5913
5914  AGTIAPI_PRINTK( "agtiapi_clrRmScan: start\n" );
5915
5916  AG_LIST_LOCK( &pCard->devListLock );
5917
5918  for ( lIdx = 0; lIdx < pCard->devDiscover; lIdx++ )
5919  {
5920    lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
5921    if ( 0 == lReadCt )
5922    {
5923      break;  // trim to who cares
5924    }
5925
5926    lReadRm = atomic_readandclear_32( &pWWNList[lIdx].devRemoved );
5927    if ( lReadRm > 0 )
5928    {
5929      pCard->pDevList[lIdx].flags &= ~ACTIVE;
5930      pCard->pDevList[lIdx].pDevHandle = NULL;
5931
5932      pPortalData = &pCard->pPortalData[pWWNList[lIdx].portId];
5933      pPortalInfo = &pPortalData->portalInfo;
5934      pPortalInfo->pDevList[lIdx] = NULL;
5935      AGTIAPI_PRINTK( "agtiapi_clrRmScan: cleared dev %d at port %d\n",
5936                      lIdx, pWWNList[lIdx].portId );
5937      atomic_subtract_16( &pCard->rmChkCt, 1 );
5938    }
5939  }
5940  AG_LIST_UNLOCK( &pCard->devListLock );
5941
5942  agtiapi_scan( pCard );
5943}
5944
5945
5946/******************************************************************************
5947agtiapi_devRmCheck()
5948
5949Purpose:
5950  Timer tick to check for timeout on missing targets
5951  Removes device list entry when timeout is reached
5952Parameters:
5953  void *data (IN)  Pointer to the HBA data structure
5954******************************************************************************/
5955STATIC void agtiapi_devRmCheck( void *data )
5956{
5957  struct agtiapi_softc *pCard;
5958  ag_tgt_map_t         *pWWNList;
5959  int                   lIdx, cmpsetRtn, lRunScanFlag = FALSE;
5960  bit16                 lReadCt;
5961  bit32                 lReadRm;
5962
5963  pCard = ( struct agtiapi_softc * )data;
5964
5965  // routine overhead
5966  if ( callout_pending( &pCard->devRmTimer ) )  // callout was reset
5967  {
5968    return;
5969  }
5970  if ( !callout_active( &pCard->devRmTimer ) )  // callout was stopped
5971  {
5972    return;
5973  }
5974  callout_deactivate( &pCard->devRmTimer );
5975
5976  if( pCard->flags & AGTIAPI_SHUT_DOWN )
5977  {
5978    return;  // implicit timer clear
5979  }
5980
5981  pWWNList = pCard->pWWNList;
5982
5983  AG_LIST_LOCK( &pCard->devListLock );
5984  lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
5985  if ( lReadCt )
5986  {
5987    if ( callout_pending(&pCard->devRmTimer) == FALSE )
5988    {
5989      callout_reset( &pCard->devRmTimer, 1 * hz, agtiapi_devRmCheck, pCard );
5990    }
5991    else
5992    {
5993      AG_LIST_UNLOCK( &pCard->devListLock );
5994	  return;
5995    }
5996
5997    for ( lIdx = 0; lIdx < pCard->devDiscover; lIdx++ )
5998    {
5999      lReadCt = atomic_load_acq_16( &pCard->rmChkCt );
6000      if ( 0 == lReadCt )
6001      {
6002        break;  // if handled somewhere else, get out
6003      }
6004
6005      lReadRm = atomic_load_acq_32( &pWWNList[lIdx].devRemoved );
6006      if ( lReadRm > 0 )
6007      {
6008        if ( 1 == lReadRm ) // timed out
6009        { // no decrement of devRemoved as way to leave a clrRmScan marker
6010          lRunScanFlag = TRUE; // other devRemoved values are about to get wiped
6011          break; // ... so bail out
6012        }
6013        else
6014        {
6015          AGTIAPI_PRINTK( "agtiapi_devRmCheck: counting down dev %d @ %d; %d\n",
6016                          lIdx, lReadRm, lReadCt );
6017          cmpsetRtn = atomic_cmpset_32( &pWWNList[lIdx].devRemoved,
6018                                        lReadRm,
6019                                        lReadRm-1 );
6020          if ( 0 == cmpsetRtn )
6021          {
6022            printf( "agtiapi_devRmCheck: %d decrement already handled\n",
6023                    lIdx );
6024          }
6025        }
6026      }
6027    }
6028    AG_LIST_UNLOCK( &pCard->devListLock );
6029
6030    if ( TRUE == lRunScanFlag )
6031      agtiapi_clrRmScan( pCard );
6032  }
6033  else
6034  {
6035    AG_LIST_UNLOCK( &pCard->devListLock );
6036  }
6037
6038  return;
6039}
6040
6041
6042static void agtiapi_cam_poll( struct cam_sim *asim )
6043{
6044  return;
6045}
6046
6047/*****************************************************************************
6048agtiapi_ResetCard()
6049
6050Purpose:
6051  Hard or soft reset on the controller and resend any
6052  outstanding requests if needed.
6053Parameters:
6054  struct agtiapi_softc *pCard (IN)  Pointer to HBA data structure
6055  unsigned lomg flags (IN/OUT) Flags used in locking done from calling layers
6056Return:
6057  AGTIAPI_SUCCESS - reset successful
6058  AGTIAPI_FAIL    - reset failed
6059Note:
6060*****************************************************************************/
6061U32 agtiapi_ResetCard( struct agtiapi_softc *pCard, unsigned long *flags )
6062{
6063  ag_device_t      *pDevice;
6064  U32               lIdx = 0;
6065  U32               lFlagVal;
6066  agBOOLEAN         ret;
6067  ag_portal_info_t *pPortalInfo;
6068  ag_portal_data_t *pPortalData;
6069  U32               count, loop;
6070  int               szdv;
6071
6072  if( pCard->flags & AGTIAPI_RESET ) {
6073    AGTIAPI_PRINTK( "agtiapi_ResetCard: reset card already in progress!\n" );
6074    return AGTIAPI_FAIL;
6075  }
6076
6077  AGTIAPI_PRINTK( "agtiapi_ResetCard: Enter cnt %d\n",
6078                  pCard->resetCount );
6079#ifdef LOGEVENT
6080  agtiapi_LogEvent( pCard,
6081                    IOCTL_EVT_SEV_INFORMATIONAL,
6082                    0,
6083                    agNULL,
6084                    0,
6085                    "Reset initiator time = %d!",
6086                    pCard->resetCount + 1 );
6087#endif
6088
6089  pCard->flags |= AGTIAPI_RESET;
6090  pCard->flags &= ~(AGTIAPI_CB_DONE | AGTIAPI_RESET_SUCCESS);
6091  tiCOMSystemInterruptsActive( &pCard->tiRoot, FALSE );
6092  pCard->flags &= ~AGTIAPI_SYS_INTR_ON;
6093
6094  agtiapi_FlushCCBs( pCard, AGTIAPI_CALLBACK );
6095
6096  for ( lIdx = 1; 3 >= lIdx; lIdx++ ) // we try reset up to 3 times
6097  {
6098    if( pCard->flags & AGTIAPI_SOFT_RESET )
6099    {
6100      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft variant\n" );
6101      tiCOMReset( &pCard->tiRoot, tiSoftReset );
6102    }
6103    else
6104    {
6105      AGTIAPI_PRINTK( "agtiapi_ResetCard: no flag, no reset!\n" );
6106    }
6107
6108    lFlagVal = AGTIAPI_RESET_SUCCESS;
6109    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, *flags );
6110    ret = agtiapi_CheckCB( pCard, 50000, lFlagVal, &pCard->flags );
6111    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, *flags );
6112
6113    if( ret == AGTIAPI_FAIL )
6114    {
6115      AGTIAPI_PRINTK( "agtiapi_ResetCard: CheckCB indicates failed reset call, "
6116              "try again?\n" );
6117    }
6118    else
6119    {
6120      break;
6121    }
6122  }
6123  if ( 1 < lIdx )
6124  {
6125    if ( AGTIAPI_FAIL == ret )
6126    {
6127      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft reset failed after try %d\n",
6128                      lIdx );
6129    }
6130    else
6131    {
6132      AGTIAPI_PRINTK( "agtiapi_ResetCard: soft reset success at try %d\n",
6133                      lIdx );
6134    }
6135  }
6136  if( AGTIAPI_FAIL == ret )
6137  {
6138    printf( "agtiapi_ResetCard: reset ERROR\n" );
6139    pCard->flags &= ~AGTIAPI_INSTALLED;
6140    return AGTIAPI_FAIL;
6141  }
6142
6143  pCard->flags &= ~AGTIAPI_SOFT_RESET;
6144
6145  // disable all devices
6146  pDevice = pCard->pDevList;
6147  for( lIdx = 0; lIdx < maxTargets; lIdx++, pDevice++ )
6148  {
6149    /* if ( pDevice->flags & ACTIVE )
6150    {
6151      printf( "agtiapi_ResetCard: before ... active device %d\n", lIdx );
6152    } */
6153    pDevice->flags &= ~ACTIVE;
6154  }
6155
6156  AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, *flags );
6157  if( tiCOMPortInit( &pCard->tiRoot, agFALSE ) != tiSuccess )
6158    printf( "agtiapi_ResetCard: tiCOMPortInit FAILED \n" );
6159  else
6160    AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortInit success\n" );
6161
6162  if( !pCard->pDevList ) {  // try to get a little sanity here
6163    AGTIAPI_PRINTK( "agtiapi_ResetCard: no pDevList ERROR %p\n",
6164                    pCard->pDevList );
6165    return AGTIAPI_FAIL;
6166  }
6167
6168  AGTIAPI_PRINTK( "agtiapi_ResetCard: pre target-count %d port-count %d\n",
6169                  pCard->tgtCount, pCard->portCount );
6170  pCard->tgtCount = 0;
6171
6172  DELAY( 500000 );
6173
6174  pCard->flags &= ~AGTIAPI_CB_DONE;
6175
6176  pPortalData = pCard->pPortalData;
6177
6178  for( count = 0; count < pCard->portCount; count++ ) {
6179    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
6180    pPortalInfo = &pPortalData->portalInfo;
6181    pPortalInfo->portStatus = 0;
6182    pPortalInfo->portStatus &= ~( AGTIAPI_PORT_START      |
6183                                  AGTIAPI_PORT_DISC_READY |
6184                                  AGTIAPI_DISC_DONE       |
6185                                  AGTIAPI_DISC_COMPLETE );
6186
6187    szdv =
6188      sizeof( pPortalInfo->pDevList ) / sizeof( pPortalInfo->pDevList[0] );
6189    if (szdv > pCard->devDiscover)
6190    {
6191      szdv = pCard->devDiscover;
6192    }
6193
6194    for( lIdx = 0, loop = 0;
6195         lIdx < szdv  &&  loop < pPortalInfo->devTotal;
6196         lIdx++ )
6197    {
6198      pDevice = (ag_device_t*)pPortalInfo->pDevList[lIdx];
6199      if( pDevice )
6200      {
6201        loop++;
6202        pDevice->pDevHandle = 0; // mark for availability in pCard->pDevList[]
6203        // don't erase more as the device is scheduled for removal on DPC
6204      }
6205      AGTIAPI_PRINTK( "agtiapi_ResetCard: reset pDev %p pDevList %p idx %d\n",
6206                      pDevice, pPortalInfo->pDevList, lIdx );
6207      pPortalInfo->devTotal = pPortalInfo->devPrev = 0;
6208    }
6209
6210    for( lIdx = 0; lIdx < maxTargets; lIdx++ )
6211    { // we reconstruct dev list later in get dev handle
6212      pPortalInfo->pDevList[lIdx] = NULL;
6213    }
6214
6215    for( loop = 0; loop < AGTIAPI_LOOP_MAX; loop++ )
6216    {
6217      AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortStart entry data "
6218                      "%p / %d / %p\n",
6219                      &pCard->tiRoot,
6220                      pPortalInfo->portID,
6221                      &pPortalInfo->tiPortalContext );
6222
6223      if( tiCOMPortStart( &pCard->tiRoot,
6224                          pPortalInfo->portID,
6225                          &pPortalInfo->tiPortalContext,
6226                          0 )
6227          != tiSuccess )
6228      {
6229        printf( "agtiapi_ResetCard: tiCOMPortStart %d FAILED\n",
6230                pPortalInfo->portID );
6231      }
6232      else
6233      {
6234        AGTIAPI_PRINTK( "agtiapi_ResetCard: tiCOMPortStart %d success\n",
6235                        pPortalInfo->portID );
6236        break;
6237      }
6238    }
6239    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
6240    tiCOMGetPortInfo( &pCard->tiRoot,
6241                      &pPortalInfo->tiPortalContext,
6242                      &pPortalInfo->tiPortInfo );
6243    pPortalData++;
6244  }
6245  // ## fail case:  pCard->flags &= ~AGTIAPI_INSTALLED;
6246
6247
6248  AG_SPIN_LOCK_IRQ(agtiapi_host_lock, *flags);
6249
6250  if( !(pCard->flags & AGTIAPI_INSTALLED) ) // driver not installed !
6251  {
6252    printf( "agtiapi_ResetCard: error, driver not intstalled? "
6253            "!AGTIAPI_INSTALLED \n" );
6254    return AGTIAPI_FAIL;
6255  }
6256
6257  AGTIAPI_PRINTK( "agtiapi_ResetCard: total device %d\n", pCard->tgtCount );
6258
6259#ifdef LOGEVENT
6260  agtiapi_LogEvent( pCard,
6261                    IOCTL_EVT_SEV_INFORMATIONAL,
6262                    0,
6263                    agNULL,
6264                    0,
6265                    "Reset initiator total device = %d!",
6266                    pCard->tgtCount );
6267#endif
6268  pCard->resetCount++;
6269
6270  AGTIAPI_PRINTK( "agtiapi_ResetCard: clear send and done queues\n" );
6271  // clear send & done queue
6272  AG_LOCAL_LOCK( &pCard->sendLock );
6273  pCard->ccbSendHead = NULL;
6274  pCard->ccbSendTail = NULL;
6275  AG_LOCAL_UNLOCK( &pCard->sendLock );
6276
6277  AG_LOCAL_LOCK( &pCard->doneLock );
6278  pCard->ccbDoneHead = NULL;
6279  pCard->ccbDoneTail = NULL;
6280  AG_LOCAL_UNLOCK( &pCard->doneLock );
6281
6282  // clear smp queues also
6283  AG_LOCAL_LOCK( &pCard->sendSMPLock );
6284  pCard->smpSendHead = NULL;
6285  pCard->smpSendTail = NULL;
6286  AG_LOCAL_UNLOCK( &pCard->sendSMPLock );
6287
6288  AG_LOCAL_LOCK( &pCard->doneSMPLock );
6289  pCard->smpDoneHead = NULL;
6290  pCard->smpDoneTail = NULL;
6291  AG_LOCAL_UNLOCK( &pCard->doneSMPLock );
6292
6293  // finished with all reset stuff, now start things back up
6294  tiCOMSystemInterruptsActive( &pCard->tiRoot, TRUE );
6295  pCard->flags |= AGTIAPI_SYS_INTR_ON;
6296  pCard->flags |= AGTIAPI_HAD_RESET;
6297  pCard->flags &= ~AGTIAPI_RESET;  // ##
6298  agtiapi_StartIO( pCard );
6299  AGTIAPI_PRINTK( "agtiapi_ResetCard: local return success\n" );
6300  return AGTIAPI_SUCCESS;
6301} // agtiapi_ResetCard
6302
6303
6304/******************************************************************************
6305agtiapi_ReleaseHBA()
6306
6307Purpose:
6308  Releases all resources previously acquired to support
6309  a specific Host Adapter, including the I/O Address range,
6310  and unregisters the agtiapi Host Adapter.
6311Parameters:
6312  device_t dev (IN)  - device pointer
6313Return:
6314  always return 0 - success
6315Note:
6316******************************************************************************/
6317int agtiapi_ReleaseHBA( device_t dev )
6318{
6319
6320  int thisCard = device_get_unit( dev ); // keeping get_unit call to once
6321  int i;
6322  ag_card_info_t *thisCardInst = &agCardInfoList[ thisCard ];
6323  struct ccb_setasync csa;
6324  struct agtiapi_softc *pCard;
6325  pCard = device_get_softc( dev );
6326  ag_card_info_t *pCardInfo = pCard->pCardInfo;
6327  ag_resource_info_t *pRscInfo = &thisCardInst->tiRscInfo;
6328
6329  AG_GLOBAL_ARG(flags);
6330
6331  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: start\n" );
6332
6333  if (thisCardInst != pCardInfo)
6334  {
6335    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: Wrong ag_card_info_t thisCardInst %p "
6336                    "pCardInfo %p\n",
6337                    thisCardInst,
6338                    pCardInfo );
6339    panic( "agtiapi_ReleaseHBA: Wrong ag_card_info_t thisCardInst %p pCardInfo "
6340           "%p\n",
6341           thisCardInst,
6342           pCardInfo );
6343    return( EIO );
6344  }
6345
6346
6347  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA card %p\n", pCard );
6348  pCard->flags |= AGTIAPI_SHUT_DOWN;
6349
6350
6351  // remove timer
6352  if (pCard->flags & AGTIAPI_TIMER_ON)
6353  {
6354    AG_SPIN_LOCK_IRQ( agtiapi_host_lock, flags );
6355    callout_drain( &pCard->OS_timer );
6356    callout_drain( &pCard->devRmTimer );
6357    callout_drain(&pCard->IO_timer);
6358    AG_SPIN_UNLOCK_IRQ( agtiapi_host_lock, flags );
6359    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: timer released\n" );
6360  }
6361
6362#ifdef HIALEAH_ENCRYPTION
6363//Release encryption table memory - Fix it
6364   //if(pCard->encrypt && (pCard->flags & AGTIAPI_INSTALLED))
6365	//agtiapi_CleanupEncryption(pCard);
6366#endif
6367
6368  /*
6369   * Shutdown the channel so that chip gets frozen
6370   * and it does not do any more pci-bus accesses.
6371   */
6372  if (pCard->flags & AGTIAPI_SYS_INTR_ON)
6373  {
6374    tiCOMSystemInterruptsActive( &pCard->tiRoot, FALSE );
6375    pCard->flags &= ~AGTIAPI_SYS_INTR_ON;
6376    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: card interrupt off\n" );
6377  }
6378  if (pCard->flags & AGTIAPI_INSTALLED)
6379  {
6380    tiCOMShutDown( &pCard->tiRoot );
6381    AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: low layers shutdown\n" );
6382  }
6383
6384  /*
6385   * first release IRQ, so that we do not get any more interrupts
6386   * from this host
6387   */
6388  if (pCard->flags & AGTIAPI_IRQ_REQUESTED)
6389  {
6390    if (!agtiapi_intx_mode)
6391    {
6392      int i;
6393      for (i = 0; i< MAX_MSIX_NUM_VECTOR; i++)
6394      {
6395        if (pCard->irq[i] != agNULL && pCard->rscID[i] != 0)
6396        {
6397          bus_teardown_intr(dev, pCard->irq[i], pCard->intrcookie[i]);
6398          bus_release_resource( dev,
6399                                SYS_RES_IRQ,
6400                                pCard->rscID[i],
6401                                pCard->irq[i] );
6402        }
6403      }
6404      pci_release_msi(dev);
6405    }
6406    pCard->flags &= ~AGTIAPI_IRQ_REQUESTED;
6407
6408
6409
6410#ifdef AGTIAPI_DPC
6411    for (i = 0; i < MAX_MSIX_NUM_DPC; i++)
6412      tasklet_kill(&pCard->tasklet_dpc[i]);
6413#endif
6414    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: IRQ released\n");
6415  }
6416
6417  // release memory vs. alloc in agtiapi_alloc_ostimem; used in ostiAllocMemory
6418  if( pCard->osti_busaddr != 0 ) {
6419    bus_dmamap_unload( pCard->osti_dmat, pCard->osti_mapp );
6420  }
6421  if( pCard->osti_mem != NULL )  {
6422    bus_dmamem_free( pCard->osti_dmat, pCard->osti_mem, pCard->osti_mapp );
6423  }
6424  if( pCard->osti_dmat != NULL ) {
6425    bus_dma_tag_destroy( pCard->osti_dmat );
6426  }
6427
6428  /* unmap the mapped PCI memory */
6429  /* calls bus_release_resource( ,SYS_RES_MEMORY, ..) */
6430  agtiapi_ReleasePCIMem(thisCardInst);
6431
6432  /* release all ccbs */
6433  if (pCard->ccbTotal)
6434  {
6435    //calls bus_dmamap_destroy() for all pccbs
6436    agtiapi_ReleaseCCBs(pCard);
6437    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: CCB released\n");
6438  }
6439
6440#ifdef HIALEAH_ENCRYPTION
6441/*release encryption resources - Fix it*/
6442  if(pCard->encrypt)
6443  {
6444    /*Check that all IO's are completed */
6445    if(atomic_read (&outstanding_encrypted_io_count) > 0)
6446    {
6447       printf("%s: WARNING: %d outstanding encrypted IOs !\n", __FUNCTION__, atomic_read(&outstanding_encrypted_io_count));
6448    }
6449    //agtiapi_CleanupEncryptionPools(pCard);
6450  }
6451#endif
6452
6453
6454  /* release device list */
6455  if( pCard->pDevList ) {
6456    free((caddr_t)pCard->pDevList, M_PMC_MDVT);
6457    pCard->pDevList = NULL;
6458    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: device list released\n");
6459  }
6460#ifdef LINUX_PERBI_SUPPORT // ## review use of PERBI
6461  AGTIAPI_PRINTK( "agtiapi_ReleaseHBA: WWN list %p \n", pCard->pWWNList );
6462  if( pCard->pWWNList ) {
6463    free( (caddr_t)pCard->pWWNList, M_PMC_MTGT );
6464    pCard->pWWNList = NULL;
6465    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: WWN list released\n");
6466  }
6467  if( pCard->pSLRList ) {
6468    free( (caddr_t)pCard->pSLRList, M_PMC_MSLR );
6469    pCard->pSLRList = NULL;
6470    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: SAS Local Remote list released\n");
6471  }
6472
6473#endif
6474  if (pCard->pPortalData)
6475  {
6476    free((caddr_t)pCard->pPortalData, M_PMC_MPRT);
6477    pCard->pPortalData = NULL;
6478    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: PortalData released\n");
6479  }
6480  //calls contigfree() or free()
6481  agtiapi_MemFree(pCardInfo);
6482  AGTIAPI_PRINTK("agtiapi_ReleaseHBA: low level resource released\n");
6483
6484#ifdef HOTPLUG_SUPPORT
6485  if (pCard->flags & AGTIAPI_PORT_INITIALIZED)
6486  {
6487    //    agtiapi_FreeDevWorkList(pCard);
6488    AGTIAPI_PRINTK("agtiapi_ReleaseHBA: (HP dev) work resources released\n");
6489  }
6490#endif
6491
6492  /*
6493   * TBD, scsi_unregister may release wrong host data structure
6494   * which cause NULL pointer shows up.
6495   */
6496  if (pCard->flags & AGTIAPI_SCSI_REGISTERED)
6497  {
6498    pCard->flags &= ~AGTIAPI_SCSI_REGISTERED;
6499
6500
6501#ifdef AGTIAPI_LOCAL_LOCK
6502    if (pCard->STLock)
6503    {
6504      //destroy mtx
6505      int maxLocks;
6506      maxLocks = pRscInfo->tiLoLevelResource.loLevelOption.numOfQueuesPerPort;
6507
6508      for( i = 0; i < maxLocks; i++ )
6509      {
6510        mtx_destroy(&pCard->STLock[i]);
6511      }
6512      free(pCard->STLock, M_PMC_MSTL);
6513      pCard->STLock = NULL;
6514    }
6515#endif
6516
6517  }
6518  ag_card_good--;
6519
6520  /* reset agtiapi_1st_time if this is the only card */
6521  if (!ag_card_good && !agtiapi_1st_time)
6522  {
6523    agtiapi_1st_time = 1;
6524  }
6525
6526  /* for tiSgl_t memeory */
6527  if (pCard->tisgl_busaddr != 0)
6528  {
6529    bus_dmamap_unload(pCard->tisgl_dmat, pCard->tisgl_map);
6530  }
6531  if (pCard->tisgl_mem != NULL)
6532  {
6533    bus_dmamem_free(pCard->tisgl_dmat, pCard->tisgl_mem, pCard->tisgl_map);
6534  }
6535  if (pCard->tisgl_dmat != NULL)
6536  {
6537    bus_dma_tag_destroy(pCard->tisgl_dmat);
6538  }
6539
6540  if (pCard->buffer_dmat != agNULL)
6541  {
6542    bus_dma_tag_destroy(pCard->buffer_dmat);
6543  }
6544
6545  if (pCard->sim != NULL)
6546  {
6547    mtx_lock(&thisCardInst->pmIOLock);
6548      xpt_setup_ccb(&csa.ccb_h, pCard->path, 5);
6549      csa.ccb_h.func_code = XPT_SASYNC_CB;
6550      csa.event_enable = 0;
6551      csa.callback = agtiapi_async;
6552      csa.callback_arg = pCard;
6553      xpt_action((union ccb *)&csa);
6554      xpt_free_path(pCard->path);
6555 //   if (pCard->ccbTotal == 0)
6556    if (pCard->ccbTotal <= thisCard)
6557    {
6558      /*
6559        no link up so that simq has not been released.
6560        In order to remove cam, we call this.
6561      */
6562      xpt_release_simq(pCard->sim, 1);
6563    }
6564    xpt_bus_deregister(cam_sim_path(pCard->sim));
6565    cam_sim_free(pCard->sim, FALSE);
6566    mtx_unlock(&thisCardInst->pmIOLock);
6567  }
6568  if (pCard->devq != NULL)
6569  {
6570    cam_simq_free(pCard->devq);
6571  }
6572
6573  //destroy mtx
6574  mtx_destroy( &thisCardInst->pmIOLock );
6575  mtx_destroy( &pCard->sendLock );
6576  mtx_destroy( &pCard->doneLock );
6577  mtx_destroy( &pCard->sendSMPLock );
6578  mtx_destroy( &pCard->doneSMPLock );
6579  mtx_destroy( &pCard->ccbLock );
6580  mtx_destroy( &pCard->devListLock );
6581  mtx_destroy( &pCard->OS_timer_lock );
6582  mtx_destroy( &pCard->devRmTimerLock );
6583  mtx_destroy( &pCard->memLock );
6584  mtx_destroy( &pCard->freezeLock );
6585
6586  destroy_dev( pCard->my_cdev );
6587  memset((void *)pCardInfo, 0, sizeof(ag_card_info_t));
6588  return 0;
6589}
6590
6591
6592// Called during system shutdown after sync
6593static int agtiapi_shutdown( device_t dev )
6594{
6595  AGTIAPI_PRINTK( "agtiapi_shutdown\n" );
6596  return( 0 );
6597}
6598
6599static int agtiapi_suspend( device_t dev )  // Device suspend routine.
6600{
6601  AGTIAPI_PRINTK( "agtiapi_suspend\n" );
6602  return( 0 );
6603}
6604
6605static int agtiapi_resume( device_t dev ) // Device resume routine.
6606{
6607  AGTIAPI_PRINTK( "agtiapi_resume\n" );
6608  return( 0 );
6609}
6610
6611static device_method_t agtiapi_methods[] = {   // Device interface
6612  DEVMETHOD( device_probe,    agtiapi_probe      ),
6613  DEVMETHOD( device_attach,   agtiapi_attach     ),
6614  DEVMETHOD( device_detach,   agtiapi_ReleaseHBA ),
6615  DEVMETHOD( device_shutdown, agtiapi_shutdown   ),
6616  DEVMETHOD( device_suspend,  agtiapi_suspend    ),
6617  DEVMETHOD( device_resume,   agtiapi_resume     ),
6618  { 0, 0 }
6619};
6620
6621static devclass_t pmspcv_devclass;
6622
6623static driver_t pmspcv_driver = {
6624  "pmspcv",
6625  agtiapi_methods,
6626  sizeof( struct agtiapi_softc )
6627};
6628
6629DRIVER_MODULE( pmspcv, pci, pmspcv_driver, pmspcv_devclass, 0, 0 );
6630MODULE_DEPEND( pmspcv, cam, 1, 1, 1 );
6631MODULE_DEPEND( pmspcv, pci, 1, 1, 1 );
6632
6633#include <dev/pms/freebsd/driver/common/lxosapi.c>
6634#include <dev/pms/freebsd/driver/ini/src/osapi.c>
6635#include <dev/pms/freebsd/driver/common/lxutil.c>
6636#include <dev/pms/freebsd/driver/common/lxencrypt.c>
6637
6638
6639