1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
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
10 *with the distribution.
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21 *******************************************************************************/
24 MALLOC_DEFINE( M_PMC_OSTI, "osti_cacheable", "allocated from ostiAllocMemory as cacheable memory" );
27 /******************************************************************************
30 TD layer calls to get dma memory
32 tiRoot_t *ptiRoot (IN) Pointer refers to the current root
33 void **osMemHandle (IN_OUT) Pointer To OS Mem handle to fill in
34 void **agVirtAddr (IN_OUT) Pointer to allocated memory address
35 U32 *agPhysUpper32 (IN_OUT) Pointer to Up 32 bit mem phys addr.
36 U32 *agPhysLower32 (IN_OUT) Pointer to low 32 bit mem phys addr.
37 U32 alignment (IN) Alignment requirement
38 U32 allocLength (IN) Required memory length
39 agBOOLEAN isChacheable (IN) Required memory type
42 tiMemoryTooLarge - requested memory size too large
43 tiMemoryNotAvail - no dma memory available
46 where a cacheable allocation inherently may be swapped, the values
47 agPhysUpper32 and agPhysLower32 are understood to mean nothing when the
48 value isCacheable is set to true. these phys values must not be used by
50 ******************************************************************************/
51 osGLOBAL U32 ostiAllocMemory( tiRoot_t *ptiRoot,
58 agBOOLEAN isCacheable )
60 ag_card_info_t *pCardInfo = TIROOT_TO_CARDINFO( ptiRoot );
62 struct agtiapi_softc *pCard;
63 pCard = TIROOT_TO_CARD(ptiRoot);
65 AGTIAPI_PRINTK( "ostiAllocMemory: debug, cache? %d size %d alloc algn %d ### \n",
66 isCacheable, allocLength, alignment );
68 if( pCardInfo->topOfFreeDynamicMem == 0 ) {
69 AGTIAPI_PRINTK( "ostiAllocMemory: No space left, increase "
70 "AGTIAPI_DYNAMIC_MAX! ERROR\n" );
71 return tiMemoryNotAvail;
74 pMem = pCardInfo->freeDynamicMem[pCardInfo->topOfFreeDynamicMem - 1];
76 // where this memory has bee preallocated, be sure requirements do not
77 // exceed the limits of resources available
78 if( allocLength > 4096 ) {
79 AGTIAPI_PRINTK( "ostiAllocMemory: no-cache size 0x%x alloc NOT AVAILABLE\n",
81 return tiMemoryNotAvail;
83 if( alignment > 32 ) {
84 AGTIAPI_PRINTK( "ostiAllocMemory: no-cache alignment 0x%x NOT AVAILABLE\n",
86 return tiMemoryNotAvail;
89 pMem->dmaPhysAddr = pMem->nocache_busaddr;
90 pMem->dmaVirtAddr = pMem->nocache_mem;
91 pMem->memSize = allocLength;
92 *agVirtAddr = pMem->dmaVirtAddr;
94 *agPhysUpper32 = HIGH_32_BITS( pMem->dmaPhysAddr );
95 *agPhysLower32 = LOW_32_BITS( pMem->dmaPhysAddr );
97 mtx_lock(&pCard->memLock);
98 pCardInfo->topOfFreeDynamicMem--;
99 *osMemHandle = (void *)pMem; // virtAddr;
100 mtx_unlock(&pCard->memLock);
105 /******************************************************************************
106 ostiIOCTLWaitForSignal()
108 Function to wait semaphore during ioctl
110 tiRoot_t *ptiRoot (IN) Pointer to the current HBA
111 void **agParam1 (IN_OUT) Pointer to context to be passed
112 void **agParam2 (IN_OUT) Pointer to context to be passed
113 void **agParam (IN_OUT) Pointer to context to be passed
116 ******************************************************************************/
118 ostiIOCTLWaitForSignal(tiRoot_t *ptiRoot,
123 struct agtiapi_softc *pCard;
124 pCard = TIROOT_TO_CARD(ptiRoot);
127 sema_wait (pCard->pIoctlSem);
130 /* Below function has to be changed to use wait for completion */
132 ostiIOCTLWaitForComplete(tiRoot_t *ptiRoot,
137 struct agtiapi_softc *pCard;
138 pCard = TIROOT_TO_CARD(ptiRoot);
141 sema_wait (pCard->pIoctlSem);
145 /******************************************************************************
146 ostiChipConfigReadBit32()
148 Read 32-bit value from PCI configuration register
150 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
151 U32 chipConfigOffset (IN) Offset to PCI configuration register
154 ******************************************************************************/
155 U32 ostiChipConfigReadBit32( tiRoot_t *ptiRoot, U32 chipConfigOffset )
157 device_t lDev = TIROOT_TO_PCIDEV(ptiRoot);
160 lData = pci_read_config( lDev, chipConfigOffset, 4 );
166 /******************************************************************************
167 ostiChipConfigWriteBit32()
169 Write 32-bit value to PCI configuration register
171 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
172 U32 chipConfigOffset (IN) Offset to PCI configuration register
173 U32 chipConfigValue (IN) Value to be written
175 ******************************************************************************/
176 void ostiChipConfigWriteBit32( tiRoot_t *ptiRoot,
177 U32 chipConfigOffset,
178 U32 chipConfigValue )
180 device_t lDev = TIROOT_TO_PCIDEV(ptiRoot);
181 pci_write_config( lDev, chipConfigOffset, chipConfigValue, 4 );
184 /******************************************************************************
187 Read 32-bit value from PCI address register
189 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
190 U32 chipOffset (IN) Offset to PCI configuration register
193 ******************************************************************************/
194 U32 ostiChipReadBit32(tiRoot_t *ptiRoot, U32 chipOffset)
197 ag_card_info_t *pCardInfo;
199 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
200 data = *(U32 *)(pCardInfo->pciMemVirtAddr + chipOffset);
204 /******************************************************************************
207 Write 32-bit value to PCI address register
209 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
210 U32 chipOffset (IN) Offset to PCI configuration register
211 U32 chipValue (IN) Value to be written
213 ******************************************************************************/
214 void ostiChipWriteBit32( tiRoot_t *ptiRoot, U32 chipOffset, U32 chipValue )
216 ag_card_info_t *pCardInfo;
217 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
218 *(U32 *)(pCardInfo->pciMemVirtAddr + chipOffset) = chipValue;
221 /******************************************************************************
222 ostiChipReadBit32Ext()
224 Read 32-bit value from PCI address register
226 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
227 busBaseNumber PCI BAR number
228 U32 chipOffset (IN) Offset to PCI configuration register
231 ******************************************************************************/
232 U32 ostiChipReadBit32Ext( tiRoot_t *ptiRoot,
237 ag_card_info_t *pCardInfo;
239 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
240 data = *(U32 *)((pCardInfo->pciMemVirtAddrSpc[busBaseNumber]) + chipOffset );
244 /******************************************************************************
245 ostiChipWriteBit32Ext()
247 Write 32-bit value to PCI address register
249 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
250 busBaseNumber PCI BAR number
251 U32 chipOffset (IN) Offset to PCI configuration register
252 U32 chipValue (IN) Value to be written
254 ******************************************************************************/
255 void ostiChipWriteBit32Ext( tiRoot_t *ptiRoot,
260 ag_card_info_t *pCardInfo;
261 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
262 *(U32 *)((pCardInfo->pciMemVirtAddrSpc[busBaseNumber]) + chipOffset ) = aData;
265 /******************************************************************************
268 Read 8-bit value from PCI address register
270 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
271 U32 chipOffset (IN) Offset to PCI configuration register
274 ******************************************************************************/
275 U08 ostiChipReadBit8( tiRoot_t *ptiRoot, U32 chipOffset )
277 ag_card_info_t *pCardInfo;
278 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
279 return *(U08 *)( pCardInfo->pciMemVirtAddr + chipOffset );
282 /******************************************************************************
285 Write 8-bit value to PCI address register
287 tiRoot_t *ptiRoot (IN) Pointer to tiRoot structure
288 U32 chipOffset (IN) Offset to PCI configuration register
289 U8 chipValue (IN) Value to be written
291 ******************************************************************************/
292 void ostiChipWriteBit8( tiRoot_t *ptiRoot, U32 chipOffset, U08 chipValue )
294 ag_card_info_t *pCardInfo;
295 pCardInfo = TIROOT_TO_CARDINFO(ptiRoot);
296 *(U08 *)( pCardInfo->pciMemVirtAddr + chipOffset ) = chipValue;
300 void ostiFlashReadBlock(tiRoot_t *ptiRoot,
305 AGTIAPI_PRINTK( "ostiFlashReadBlock: No support for iscsi device\n" );
308 /******************************************************************************
311 TD layer calls to free allocated dma memory
313 tiRoot_t *ptiRoot (IN) Pointer refers to the current root
314 void *osMemHandle (IN) Pointer to OS mem handle to be released
315 u32 allocLength (IN) Aloocated memory length in byte
318 tiInvalidHandle - handle is invalid
319 ******************************************************************************/
320 osGLOBAL U32 ostiFreeMemory( tiRoot_t *ptiRoot,
324 ag_card_info_t *pCardInfo = TIROOT_TO_CARDINFO( ptiRoot );
325 ag_dma_addr_t *pMem = (ag_dma_addr_t*)osMemHandle;
326 struct agtiapi_softc *pCard;
327 pCard = TIROOT_TO_CARD(ptiRoot);
330 AGTIAPI_PRINTK( "ostiFreeMemory: NULL handle ERROR\n" );
331 return tiInvalidHandle;
334 AGTIAPI_PRINTK( "ostiFreeMemory: debug messsage %p ### \n",
335 (void*)pMem->dmaPhysAddr );
339 pMem->dmaVirtAddr = NULL;
340 pMem->dmaPhysAddr = 0;
342 if (pCardInfo->topOfFreeDynamicMem == AGTIAPI_DYNAMIC_MAX) {
343 AGTIAPI_PRINTK( "ostiFreeMemory: too many free slots ERROR\n" );
344 return tiInvalidHandle;
347 mtx_lock(&pCard->memLock);
348 pCardInfo->freeDynamicMem[pCardInfo->topOfFreeDynamicMem++] = pMem;
349 mtx_unlock(&pCard->memLock);
355 /******************************************************************************
356 ostiMakeParamString()
358 Utility function to simplify flow in ostiGetTransportParam(). Produces
359 a string handle constructed from ostiGetTransportParam() values:
360 key, subkey1, subkey2, subkey3, subkey4, subkey5, and valueName.
362 S08 *aKey (IN) Pointer to 1st level parameter string
363 S08 *aSubkey1 (IN) Pointer to 2nd level parameter string
364 S08 *aSubkey2 (IN) Pointer to 3rd level parameter string
365 S08 *aSubkey3 (IN) Pointer to 4th level parameter string
366 S08 *aSubkey4 (IN) Pointer to 5th level parameter string
367 S08 *aSubkey5 (IN) Pointer to 6th level parameter string
368 S08 *aValueName (IN) Pointer to name string of the value under keys
369 S08 *aFullKey (OUT) Pointer to returned key-value-handle buffer
370 U32 *apLenFullKey (OUT) String length in the key-value-handle buffer
375 If all input strings are NULL, tiError will return with zero in apLenFullKey
376 *****************************************************************************/
377 inline static U32 ostiMakeParamString( S08 *aKey,
387 // preliminary sanity checks
388 if( agNULL == aKey ) {
390 printf( "ostiGetTransportParam called with no key. how odd.\n" );
393 if( agNULL == aValueName ) {
395 printf( "ostiGetTransportParam called with no value-name. how odd.\n" );
399 strcpy( aFullKey, "DPMC_" ); // start at the beginning of the string
400 strcat( aFullKey, aKey );
403 S08 *lStrIdx = agNULL;
404 for( lIdx = 1; lIdx <= 5; lIdx++ ) {
405 if( 1 == lIdx) lStrIdx = aSubkey1;
406 if( 2 == lIdx) lStrIdx = aSubkey2;
407 if( 3 == lIdx) lStrIdx = aSubkey3;
408 if( 4 == lIdx) lStrIdx = aSubkey4;
409 if( 5 == lIdx) lStrIdx = aSubkey5;
410 if( agNULL == lStrIdx ) break; // no more key information
411 // append key information
412 strcat( aFullKey, "_" );
413 strcat( aFullKey, lStrIdx );
416 // only the value name is left to append
417 strcat( aFullKey, "_" );
418 strcat( aFullKey, aValueName );
420 *apLenFullKey = strlen( aFullKey ); // 58 is max len seen; June 11, 2012
421 // printf( "ostiMakeParamString: x%d out-str:%s\n", // debug print
422 // *apLenFullKey, aFullKey );
424 return tiSuccess; // ship it chief
428 /******************************************************************************
429 ostiGetTransportParam()
431 Call back function from lower layer to get parameters.
433 tiRoot_t *ptiRoot (IN) Pointer to driver root data structure
434 S08 *key (IN) Pointer to 1st level parameter
435 S08 *subkey1 (IN) Pointer to 2nd level parameter
436 S08 *subkey2 (IN) Pointer to 3rd level parameter
437 S08 *subkey3 (IN) Pointer to 4th level parameter
438 S08 *subkey4 (IN) Pointer to 5th level parameter
439 S08 *subkey5 (IN) Pointer to 6th level parameter
440 S08 *valueName (IN) Pointer to name of the value under keys
441 S08 *buffer (OUT) Pointer to returned information buffer
442 U32 bufferLen (OUT) Buffer length
443 U32 *lenReceived (OUT) String length in the buffer
448 The scheme of searching adjustable parameter tree is the following:
456 If no match in any case, tiError will return with zero length.
458 Where there is no indication of max key and subkey length,
459 an upper limit guess of 200 is used.
460 Perhaps a prudent revision would be to add some argument(s) to be
461 able to manage/check these "key" string lengths.
462 This function does no checking of buffer being a valid pointer.
463 *****************************************************************************/
464 U32 ostiGetTransportParam( tiRoot_t *ptiRoot,
481 strcpy( buffer, "" );
483 printf( "ostiGetTransportParam: buffer too small at only %d",
485 return tiError; // not a reasonable buffer to work with
487 ostiMakeParamString( key, subkey1, subkey2, subkey3, subkey4, subkey5,
488 valueName, lFullKey, &lLenFullKey );
489 if( lLenFullKey ) // clean ParamString extraction
490 TUNABLE_STR_FETCH( lFullKey, buffer, bufferLen );
492 return tiError; // not working out, bail now
494 *lenReceived = strlen( buffer );
496 //if( *lenReceived ) // handy debug print
497 // printf( "ostiGetTransportParam: sz%d val:%s hdl-str:%s\n",
498 // *lenReceived, buffer, lFullKey );
500 return tiSuccess; // ship it chief
504 /******************************************************************************
505 ostiIOCTLClearSignal()
508 Function to clear or reset semaphore during ioctl
510 tiRoot_t *ptiRoot (IN) Pointer to the current HBA
511 void **agParam1 (IN_OUT) Pointer to context to be passed
512 void **agParam2 (IN_OUT) Pointer to context to be passed
513 void **agParam (IN_OUT) Pointer to context to be passed
516 TBD, need more work for card based semaphore. Also needs to
517 consider the calling sequence.
518 ******************************************************************************/
520 ostiIOCTLClearSignal(tiRoot_t *ptiRoot,
528 /******************************************************************************
529 ostiIOCTLSetSignal() ### function currently stubbed out
531 Function to set semaphore during ioctl
533 tiRoot_t *ptiRoot (IN) Pointer to the current HBA
534 void **agParam1 (IN_OUT) Pointer to context to be passed
535 void **agParam2 (IN_OUT) Pointer to context to be passed
536 void **agParam (IN_OUT) Pointer to context to be passed
539 ******************************************************************************/
541 ostiIOCTLSetSignal(tiRoot_t *ptiRoot,
546 struct agtiapi_softc *pCard;
547 pCard = TIROOT_TO_CARD(ptiRoot);
548 if (pCard->down_count != pCard->up_count)
551 sema_post (pCard->pIoctlSem);
556 ostiIOCTLComplete(tiRoot_t *ptiRoot,
561 struct agtiapi_softc *pCard;
562 pCard = TIROOT_TO_CARD(ptiRoot);
563 if (pCard->down_count != pCard->up_count)
566 sema_post (pCard->pIoctlSem);
570 /******************************************************************************
573 Call back function to inform OS the events of port state change.
575 tiRoot_t *ptiRoot(IN) Pointer to driver root data structure
576 tiPortEvent_t eventType (IN) Type of port event:
586 void *pParm(IN) Pointer to event specific structure
589 ******************************************************************************/
591 ostiPortEvent(tiRoot_t *ptiRoot,
592 tiPortEvent_t eventType,
596 struct agtiapi_softc *pCard;
597 ag_portal_data_t *pPortalData;
599 AGTIAPI_PRINTK("ostiPortEvent: start eventType 0x%x\n", eventType);
601 pCard = TIROOT_TO_CARD(ptiRoot);
606 pCard->flags |= AGTIAPI_CB_DONE;
607 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
608 PORTAL_STATUS(pPortalData) |= AGTIAPI_PORT_START;
609 AGTIAPI_PRINTK("PortStarted - portal %p, status %x\n",
610 pPortalData, PORTAL_STATUS(pPortalData));
613 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
614 PORTAL_STATUS(pPortalData) &= ~AGTIAPI_PORT_LINK_UP;
615 AGTIAPI_PRINTK("PortLinkDown - portal %p\n", pPortalData);
618 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
619 PORTAL_STATUS(pPortalData) |= AGTIAPI_PORT_LINK_UP;
620 AGTIAPI_PRINTK("PortLinkUp - portal %p\n", pPortalData);
621 #ifdef INITIATOR_DRIVER
622 #ifndef HOTPLUG_SUPPORT
623 if (!(pCard->flags & AGTIAPI_INIT_TIME))
625 // agtiapi_StartIO(pCard);
628 case tiPortDiscoveryReady:
629 pCard->flags |= AGTIAPI_CB_DONE;
630 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
631 PORTAL_STATUS(pPortalData) |= AGTIAPI_PORT_DISC_READY;
632 AGTIAPI_PRINTK("PortDiscoveryReady - portal %p, status 0x%x\n",
633 pPortalData, PORTAL_STATUS(pPortalData));
634 #ifdef INITIATOR_DRIVER
635 #ifndef HOTPLUG_SUPPORT
636 if (!(pCard->flags & AGTIAPI_INIT_TIME))
638 tiINIDiscoverTargets(&pCard->tiRoot,
639 &pPortalData->portalInfo.tiPortalContext,
640 FORCE_PERSISTENT_ASSIGN_MASK);
643 case tiPortNameServerDown:
644 AGTIAPI_PRINTK("PortNameSeverDown\n");
645 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
646 PORTAL_STATUS(pPortalData) &= ~AGTIAPI_NAME_SERVER_UP;
649 AGTIAPI_PRINTK("PortPanic\n");
650 AGTIAPI_PRINTK( "## PortEvent\n" );
651 pCard->flags |= AGTIAPI_PORT_PANIC;
653 case tiPortResetComplete:
654 AGTIAPI_PRINTK("PortResetComplete\n");
655 pCard->flags |= AGTIAPI_CB_DONE;
656 if (status == tiSuccess)
657 pCard->flags |= AGTIAPI_RESET_SUCCESS;
660 AGTIAPI_PRINTK("PortShutdown\n");
661 pCard->flags |= AGTIAPI_CB_DONE;
662 pCard->flags |= AGTIAPI_PORT_SHUTDOWN;
665 pCard->flags |= AGTIAPI_CB_DONE;
666 pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(pParm);
667 PORTAL_STATUS(pPortalData) |= AGTIAPI_PORT_STOPPED;
668 AGTIAPI_PRINTK("PortStopped - portal %p\n", pPortalData);
670 case tiEncryptOperation:
672 case tiModePageOperation:
675 AGTIAPI_PRINTK("PortEvent - %d (Unknown)\n", eventType);
682 /******************************************************************************
685 Stall the thread (busy wait) for a number of microseconds.
687 tiRoot_t *ptiRoot (IN) Pointer to the tiRoot data structure
688 U32 microseconds (IN) Micro-seconds to be hold
690 ******************************************************************************/
691 void ostiStallThread( tiRoot_t *ptiRoot, U32 microseconds )
693 DELAY( microseconds );
697 /******************************************************************************
698 ostiTimeStamp() ### stubbed out for now
702 tiRoot_t *ptiRoot (IN) Pointer to the tiRoot data structure
704 Time stamp in milisecond
705 ******************************************************************************/
707 ostiTimeStamp(tiRoot_t *ptiRoot)
712 // meant as stubbed out 64 bit version.
713 U64 ostiTimeStamp64( tiRoot_t *ptiRoot )
716 retVal = ostiTimeStamp( ptiRoot );
720 /******************************************************************************
721 ostiCacheFlush() ### stubbed out for now
722 ostiCacheInvalidate()
732 These 3 functions are to support new cache coherency applications.
733 Currently the APIs are implemented in FC for PPC platform. The
734 define CACHED_DMA enable for dma_cache_sync function call. However
735 this define is restricted for certain version of linux, such as
736 Linux 2.6.x and above, and certain platform such as PPC.
738 DO NOT define the CACHED_DMA if the cache coherency is not required
739 or the environment does not match.
740 ******************************************************************************/
741 osGLOBAL void ostiCacheFlush(
750 osGLOBAL void ostiCacheInvalidate(
759 osGLOBAL void ostiCachePreFlush(
771 this is called by ossaInterrruptEnable
773 GLOBAL void ostiInterruptEnable( tiRoot_t *ptiRoot, bit32 channelNum )
775 // yep, really nothing.
779 this is called by ossaInterrruptDisable
781 GLOBAL void ostiInterruptDisable( tiRoot_t *ptiRoot, bit32 channelNum )
783 // yep, really nothing.