HRESULT nciCBGeneric(PB *packetBlock, uint32 nciCBtype) { HRESULT hResult = NO_ERROR; uint32 numBytes = 0; uint16 i; PB_HEADER *pHeader = NULL; QUADLET *pPayload = NULL; QUADLET *pRespPayload = NULL; PB* respPacket = NULL; PB_PACKETTYPE packetType = PB_TYPE_UNDEF; PB_LOCKTYPE lockType = PB_LOCKTYPE_NONE; RCODE_1394 rCode = RSP_ADDRESS_ERROR; OFFSET_1394 destOffset; uint16 reqType = LHL_REQ_READ; hResult = pbGetPacketHeader(packetBlock, &pHeader); if (hResult != NO_ERROR) return hResult; hResult = pbGetPacketType(packetBlock, &packetType); if (hResult != NO_ERROR) return hResult; hResult = pbGetLockType(packetBlock, &lockType); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(packetBlock, (void **) &pPayload); if (hResult != NO_ERROR) return hResult; // no broadcasts supported here if (pbPacketIsBroadcast(packetBlock)) { return hResult; } switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: reqType = LHL_REQ_READ; break; case PB_TYPE_WRITE_REQUEST_QUADLET: case PB_TYPE_WRITE_REQUEST: reqType = LHL_REQ_WRITE; break; case PB_TYPE_LOCK_REQUEST: reqType = LHL_REQ_LOCK; break; } switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_WRITE_REQUEST_QUADLET: numBytes = 4; break; case PB_TYPE_READ_REQUEST: case PB_TYPE_WRITE_REQUEST: case PB_TYPE_LOCK_REQUEST: hResult = pbGetDataLen(packetBlock, &numBytes); if (hResult != NO_ERROR) return hResult; break; } hResult = pbGetDestinationOffset(packetBlock, &destOffset); if (hResult != NO_ERROR) return hResult; switch (nciCBtype) { case NCI_CB_ARCH_SPACE: switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: case PB_TYPE_WRITE_REQUEST_QUADLET: case PB_TYPE_WRITE_REQUEST: if (destOffset.Low + numBytes <= CSR_ARCH_SPACE_END + 1) { QUADLET **pData = NULL; uint32 respLen = 0; switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: pData = &pRespPayload; respLen = numBytes; break; case PB_TYPE_WRITE_REQUEST_QUADLET: case PB_TYPE_WRITE_REQUEST: pData = &pPayload; respLen = 0; break; } hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) respLen, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; for (i = 0; i < numBytes / 4; i++) { hResult = lhlLLCHandleCSR(destOffset, 4, *pData + i, reqType); if (hResult != NO_ERROR) { break; } destOffset.Low += 4; } if (hResult == NO_ERROR) { rCode = RSP_COMPLETE; } numBytes = respLen; } break; } break; case NCI_CB_SB_SPACE: switch (destOffset.Low) { case CSR_SB_CYCLE_TIME: case CSR_SB_BUS_TIME: case CSR_SB_BUSY_TIME_OUT: switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; rCode = lhlWatchTransRead(destOffset.Low, pRespPayload); break; case PB_TYPE_WRITE_REQUEST_QUADLET: if (numBytes == 4) // only allow quadlet write { hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) 0, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; rCode = lhlWatchTransWrite(destOffset.Low, pPayload[0]); } break; } break; case CSR_SB_BM_ID: case CSR_SB_BW_AVAIL: case CSR_SB_CH_AVAIL_HI: case CSR_SB_CH_AVAIL_LO: case CSR_SB_BROADCAST_CH: #ifdef _IRMC_CAPS if (nciIRMIsThisNodeIRM()) { // handle IRM Registers here switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; rCode = nciIRMRead(destOffset.Low, pRespPayload); break; case PB_TYPE_LOCK_REQUEST: if (numBytes == 8) // only allow quadlet lock { if (lockType == PB_LOCKTYPE_COMPARE_SWAP) { uint32 lockArg = pPayload[0]; uint32 lockData = pPayload[1]; // response payload length is 1/2 size of request packet numBytes /= 2; hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; rCode = nciIRMLock(destOffset.Low, lockArg, lockData, pRespPayload); } } break; case PB_TYPE_WRITE_REQUEST: if (numBytes == 4) // only allow quadlet lock { hResult = pbCreateDuplicatePacketWithSize (packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; rCode = nciIRMWrite(destOffset.Low, pPayload[0]); } break; } } #endif //_IRMC_CAPS break; } break; case NCI_CB_CONFIG_ROM: switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: if ((destOffset.Low >= CSR_ROM_SPACE_START) && (destOffset.Low + numBytes <= CSR_ROM_SPACE_START + csrGetConfigROMQuadletSize() * 4)) { hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; for (i = 0; i < numBytes / 4; i++) { pRespPayload[i] = csrReadConfigROMQuadlet(destOffset.Low + (i * 4)); } rCode = RSP_COMPLETE; } break; } break; #ifdef _BMC_CAPS case NCI_CB_TOPOLOGY_MAP: switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: if (destOffset.Low + numBytes <= CSR_TOPOLOGY_MAP_END + 1) { uint32 index = (destOffset.Low - CSR_TOPOLOGY_MAP_START) / 4; BOOL bBusMaster = TRUE; hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; for (i = 0; i < numBytes / 4; i++) { hResult = nciBMGetTopologyMapIndex(bBusMaster, index + i, &(pRespPayload[i])); if (hResult != NO_ERROR) { break; } } if (hResult == NO_ERROR) { rCode = RSP_COMPLETE; } } break; } break; case NCI_CB_SPEED_MAP: switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: if (destOffset.Low + numBytes <= CSR_SPEED_MAP_END + 1) { uint32 index = (destOffset.Low - CSR_SPEED_MAP_START) / 4; BOOL bBusMaster = TRUE; hResult = pbCreateDuplicatePacketWithSize(packetBlock, &respPacket, (uint16) numBytes, NULL, PB_CREATE_NCI_CB); if (hResult != NO_ERROR) return hResult; hResult = pbGetPayload(respPacket, (void **) &pRespPayload); if (hResult != NO_ERROR) return hResult; for (i = 0; i < numBytes / 4; i++) { hResult = nciBMGetSpeedMapIndex(bBusMaster, index + i, &(pRespPayload[i])); if (hResult != NO_ERROR) { break; } } if (hResult == NO_ERROR) { rCode = RSP_COMPLETE; } } break; } break; #endif //_BMC_CAPS default: hResult = E_BAD_INPUT_PARAMETERS; sysLogError(hResult, __LINE__, moduleName); return hResult; } if (rCode != RSP_COMPLETE) { lhlReplyErrorResponse(packetBlock, rCode, TRUE); hResult = (HRESULT) (E_LHL_RSP_BASE + rCode); } else { switch (packetType) { case PB_TYPE_READ_REQUEST_QUADLET: case PB_TYPE_READ_REQUEST: hResult = lhlSendReadResponse(respPacket, rCode, (uint16) numBytes, pRespPayload); break; case PB_TYPE_WRITE_REQUEST_QUADLET: case PB_TYPE_WRITE_REQUEST: hResult = lhlSendWriteResponse(respPacket, rCode); break; case PB_TYPE_LOCK_REQUEST: hResult = lhlSendLockResponse(respPacket, rCode, (uint16) numBytes, pRespPayload); break; } } // clean up the resp packetBlock if (pbIsValid(respPacket)) { pbPacketDone(respPacket, PB_DONE_NCI_CB); } return hResult; }
BOOL csrIsCMCCapable(void) { return ((csrReadConfigROMQuadlet(CSR_ROM_BUS_INFO_2ND) & BUSINFO_CMC) == BUSINFO_CMC); }