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