status_t DavicomDevice::Write(const uint8 *buffer, size_t *numBytes) { size_t numBytesToWrite = *numBytes; *numBytes = 0; if (fRemoved) { TRACE_ALWAYS("Error of writing %d bytes to removed device.\n", numBytesToWrite); return B_ERROR; } if (!fHasConnection) { TRACE_ALWAYS("Error of writing %d bytes to device while down.\n", numBytesToWrite); return B_ERROR; } if (fTXBufferFull) { TRACE_ALWAYS("Error of writing %d bytes to device while TX buffer full.\n", numBytesToWrite); return B_ERROR; } TRACE_FLOW("Write %d bytes.\n", numBytesToWrite); uint8 header[kTXHeaderSize]; header[0] = *numBytes & 0xFF; header[1] = *numBytes >> 8; iovec txData[] = { { &header, kTXHeaderSize }, { (uint8*)buffer, numBytesToWrite } }; status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint, txData, 2, _WriteCallback, this); if (result != B_OK) { TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result); return result; } result = acquire_sem_etc(fNotifyWriteSem, 1, B_CAN_INTERRUPT, 0); if (result < B_OK) { TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result); return result; } if (fStatusWrite != B_OK && fStatusWrite != B_CANCELED && !fRemoved) { TRACE_ALWAYS("Device status error:%#010x\n", fStatusWrite); return fStatusWrite; } *numBytes = fActualLengthWrite - kTXHeaderSize;; TRACE_FLOW("Written %d bytes.\n", *numBytes); return B_OK; }
status_t ASIXDevice::Write(const uint8 *buffer, size_t *numBytes) { size_t numBytesToWrite = *numBytes; *numBytes = 0; if (fRemoved) { TRACE_ALWAYS("Error of writing %d bytes to removed device.\n", numBytesToWrite); return B_DEVICE_NOT_FOUND; } TRACE_FLOW("Write %d bytes.\n", numBytesToWrite); TRXHeader header(numBytesToWrite); iovec txData[] = { { &header, sizeof(TRXHeader) }, { (uint8*)buffer, numBytesToWrite } }; size_t startIndex = fUseTRXHeader ? 0 : 1 ; size_t chunkCount = fUseTRXHeader ? 2 : 1 ; status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint, &txData[startIndex], chunkCount, _WriteCallback, this); if (result != B_OK) { TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result); return result; } result = acquire_sem_etc(fNotifyWriteSem, 1, B_CAN_INTERRUPT, 0); if (result < B_OK) { TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result); return result; } if (fStatusWrite != B_OK && fStatusWrite != B_CANCELED && !fRemoved) { TRACE_ALWAYS("Device status error:%#010x\n", fStatusWrite); result = gUSBModule->clear_feature(fWriteEndpoint, USB_FEATURE_ENDPOINT_HALT); if (result != B_OK) { TRACE_ALWAYS("Error during clearing of HALT state:%#010x\n", result); return result; } } if (fUseTRXHeader) { *numBytes = fActualLengthWrite - sizeof(TRXHeader); } else { *numBytes = fActualLengthWrite; } TRACE_FLOW("Written %d bytes.\n", *numBytes); return B_OK; }
void _removeBlockFromList(Address addr, size_t blockSize) { TRACE_FLOW("(%lu, %lu)", addr, blockSize); Address previousBlockAddress = GET_ADDRESS_OF_PREVIOUS_SIBLING(addr); Address nextBlockAddress = GET_ADDRESS_OF_FOLLOWING_SIBLING(addr); SET_ADDRESS_OF_PREVIOUS_SIBLING(addr, ~((Address)0)); SET_ADDRESS_OF_FOLLOWING_SIBLING(addr, ~((Address)0)); // extra handling for single block in the list if ((previousBlockAddress == 0) && (nextBlockAddress == 0)) { WRITE_FIRST_BLOCK_ADDRESS(blockSize, 0); return; } // also first in the list got special handling if (previousBlockAddress == 0) { WRITE_FIRST_BLOCK_ADDRESS(blockSize, nextBlockAddress); SET_ADDRESS_OF_PREVIOUS_SIBLING(nextBlockAddress, 0); return; } // also the last item deserves special handling if (nextBlockAddress == 0) { SET_ADDRESS_OF_FOLLOWING_SIBLING(previousBlockAddress, 0); return; } // now we know that we are somewhere in the middle // of the list SET_ADDRESS_OF_PREVIOUS_SIBLING(nextBlockAddress, previousBlockAddress); SET_ADDRESS_OF_FOLLOWING_SIBLING(previousBlockAddress, nextBlockAddress); }
void DavicomDevice::_WriteCallback(void *cookie, int32 status, void *data, uint32 actualLength) { TRACE_FLOW("WriteCB: %d bytes; status:%#010x\n", actualLength, status); DavicomDevice *device = (DavicomDevice *)cookie; device->fActualLengthWrite = actualLength; device->fStatusWrite = status; release_sem_etc(device->fNotifyWriteSem, 1, B_DO_NOT_RESCHEDULE); }
void ASIXDevice::_ReadCallback(void *cookie, int32 status, void *data, uint32 actualLength) { TRACE_FLOW("ReadCB: %d bytes; status:%#010x\n", actualLength, status); ASIXDevice *device = (ASIXDevice *)cookie; device->fActualLengthRead = actualLength; device->fStatusRead = status; release_sem_etc(device->fNotifyReadSem, 1, B_DO_NOT_RESCHEDULE); }
void * buddyMalloc(size_t amount) { TRACE_FLOW("(%lu)", amount); size_t amountNeeded = amount + 4 * sizeof(Address); size_t blockSize = _getBlockSizeNeeded(amountNeeded); TRACE_DUMP("will allocate %lu size block", blockSize); Address result = _allocateBlock(blockSize); if (result == 0) { return NULL; } TRACE_DUMP("returning offset %lu", result); return heap + result + 4*sizeof(Address); }
status_t AX88772Device::GetLinkState(ether_link_state *linkState) { size_t actualLength = 0; uint16 mediumStatus = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus), &mediumStatus, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of reading medium status:%#010x.\n", result); return result; } if (actualLength != sizeof(mediumStatus)) { TRACE_ALWAYS("Mismatch of reading medium status." "Read %d bytes instead of %d\n", actualLength, sizeof(mediumStatus)); } TRACE_FLOW("Medium status is %#04x\n", mediumStatus); linkState->quality = 1000; linkState->media = IFM_ETHER | (fHasConnection ? IFM_ACTIVE : 0); linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX; linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000000 : 10000000; TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n", (linkState->media & IFM_ACTIVE) ? "active" : "inactive", linkState->speed / 1000000, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; }
status_t AX88172Device::GetLinkState(ether_link_state *linkState) { uint16 miiANAR = 0; uint16 miiANLPAR = 0; status_t result = fMII.Read(MII_ANAR, &miiANAR); if(result != B_OK) { TRACE_ALWAYS("Error reading MII ANAR register:%#010x\n", result); return result; } result = fMII.Read(MII_ANLPAR, &miiANLPAR); if(result != B_OK) { TRACE_ALWAYS("Error reading MII ANLPAR register:%#010x\n", result); return result; } TRACE_FLOW("ANAR:%04x ANLPAR:%04x\n", miiANAR, miiANLPAR); uint16 mediumStatus = miiANAR & miiANLPAR; linkState->quality = 1000; linkState->media = IFM_ETHER | (fHasConnection ? IFM_ACTIVE : 0); linkState->media |= mediumStatus & (ANLPAR_TX_FD | ANLPAR_10_FD) ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX; linkState->speed = mediumStatus & (ANLPAR_TX_FD | ANLPAR_TX_HD) ? 100000000 : 10000000; TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n", (linkState->media & IFM_ACTIVE) ? "active" : "inactive", linkState->speed, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; }
int _createBlock(const size_t blockSize) { TRACE_FLOW("(%lu)", blockSize); if (_hasAvailableBlock(blockSize)) { return 0; } if (blockSize > READ_FROM_HEAP(lookupTableOffset, Address)) { assert(0); } // all right, block of this size does not exist - we need to // split a bigger block int parentOkay = _createBlock(blockSize + 1); if (parentOkay != 0) { return parentOkay; } // ========= // we can now safely assume that there is a block of // blockSize+1 size that we can split // get the first from the list Address parentBlockAddress = GET_FIRST_BLOCK_ADDRESS(blockSize + 1); // remove it from the list _removeBlockFromList(parentBlockAddress, blockSize + 1); // and split it // as we know that there is no other block available, we can write // it's address to look-up table WRITE_FIRST_BLOCK_ADDRESS(blockSize, parentBlockAddress); // let's find the center of the block (there we split) Address blockHalfAddress = parentBlockAddress + UNIT * ((Address)1 << (blockSize-1)); Address leftBlockAddress = parentBlockAddress; Address rightBlockAddress = blockHalfAddress; TRACE_DUMP("left block starts at %lu, right at %lu (parent starts at %lu)", leftBlockAddress, rightBlockAddress, parentBlockAddress); // set addresses and size on the left half... WRITE_ON_HEAP(leftBlockAddress, Address, blockSize); MARK_BLOCK_FREE(leftBlockAddress); SET_ADDRESS_OF_PREVIOUS_SIBLING(leftBlockAddress, 0); SET_ADDRESS_OF_FOLLOWING_SIBLING(leftBlockAddress, rightBlockAddress); // ... as well as on the right one WRITE_ON_HEAP(rightBlockAddress, Address, blockSize); MARK_BLOCK_FREE(rightBlockAddress); SET_ADDRESS_OF_PREVIOUS_SIBLING(rightBlockAddress, leftBlockAddress); SET_ADDRESS_OF_FOLLOWING_SIBLING(rightBlockAddress, 0); buddyDump(); // and that's it! return 0; }
Address _allocateBlock(const size_t blockSize) { TRACE_FLOW("(%lu)", blockSize); int createOkay = _createBlock(blockSize); if (createOkay != 0) { return 0; } // we will get the first one Address firstBlockAddress = GET_FIRST_BLOCK_ADDRESS(blockSize); Address nextBlockAddress = GET_ADDRESS_OF_FOLLOWING_SIBLING(firstBlockAddress); // remove it from the list _removeBlockFromList(firstBlockAddress, blockSize); // set new first block WRITE_FIRST_BLOCK_ADDRESS(nextBlockAddress, blockSize); // mark it as used MARK_BLOCK_USED(firstBlockAddress); // and return it return firstBlockAddress; }
void _buddyInitTable(size_t sizesCount) { TRACE_FLOW("(%lu)", sizesCount); lookupTableOffset = UNIT * ((Address)1 << (sizesCount-1)) + sizeof(Address); // write where the table starts WRITE_ON_HEAP(0, Address, lookupTableOffset); // write how many items are there WRITE_ON_HEAP(lookupTableOffset, Address, sizesCount); // write the pointers to the first free block of given size for (size_t i = 1; i < sizesCount; i++) { WRITE_ON_HEAP(lookupTableOffset + sizeof(Address)*i, Address, 0); } WRITE_ON_HEAP(lookupTableOffset + sizeof(Address)*sizesCount, Address, sizeof(Address)); // initialize the (only) block WRITE_ON_HEAP(sizeof(Address) , Address, sizesCount); MARK_BLOCK_FREE(sizeof(Address) * 2); WRITE_ON_HEAP(sizeof(Address) * 3, Address, 0); WRITE_ON_HEAP(sizeof(Address) * 4, Address, 0); }
status_t DavicomDevice::GetLinkState(ether_link_state *linkState) { uint8 registerValue = 0; status_t result = _ReadRegister(NSR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading NSR register! %x\n",result); return result; } if (registerValue & NSR_SPEED) linkState->speed = 10000; else linkState->speed = 100000; linkState->quality = 1000; linkState->media = IFM_ETHER | IFM_100_TX; if (fHasConnection) { linkState->media |= IFM_ACTIVE; result = _ReadRegister(NCR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading NCR register! %x\n",result); return result; } if (registerValue & NCR_FDX) linkState->media |= IFM_FULL_DUPLEX; else linkState->media |= IFM_HALF_DUPLEX; if (registerValue & NCR_LBK) linkState->media |= IFM_LOOP; } TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n", (linkState->media & IFM_ACTIVE) ? "active" : "inactive", linkState->speed / 1000, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; }
status_t DavicomDevice::Read(uint8 *buffer, size_t *numBytes) { size_t numBytesToRead = *numBytes; *numBytes = 0; if (fRemoved) { TRACE_ALWAYS("Error of receiving %d bytes from removed device.\n", numBytesToRead); return B_ERROR; } TRACE_FLOW("Request %d bytes.\n", numBytesToRead); uint8 header[kRXHeaderSize]; iovec rxData[] = { { &header, kRXHeaderSize }, { buffer, numBytesToRead } }; status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, rxData, 1, _ReadCallback, this); if (result != B_OK) { TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result); return result; } uint32 flags = B_CAN_INTERRUPT | (fNonBlocking ? B_TIMEOUT : 0); result = acquire_sem_etc(fNotifyReadSem, 1, flags, 0); if (result < B_OK) { TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result); return result; } if (fStatusRead != B_OK && fStatusRead != B_CANCELED && !fRemoved) { TRACE_ALWAYS("Device status error:%#010x\n", fStatusRead); return fStatusRead; } if(fActualLengthRead < kRXHeaderSize) { TRACE_ALWAYS("Error: no place for TRXHeader:only %d of %d bytes.\n", fActualLengthRead, kRXHeaderSize); return B_ERROR; //TODO: ??? } /* * TODO :see what the first byte holds ? if(!header.IsValid()) { TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n", header.fLength, header.fInvertedLength); return B_ERROR; //TODO: ??? } */ *numBytes = header[1] | ( header[2] << 8 ); if (header[0] & 0xBF ) { TRACE_ALWAYS("RX error %d occured !\n", header[0]); } if(fActualLengthRead - kRXHeaderSize > *numBytes) { TRACE_ALWAYS("MISMATCH of the frame length: hdr %d; received:%d\n", *numBytes, fActualLengthRead - kRXHeaderSize); } TRACE_FLOW("Read %d bytes.\n", *numBytes); return B_OK; }
status_t ASIXDevice::Read(uint8 *buffer, size_t *numBytes) { size_t numBytesToRead = *numBytes; *numBytes = 0; if (fRemoved) { TRACE_ALWAYS("Error of receiving %d bytes from removed device.\n", numBytesToRead); return B_DEVICE_NOT_FOUND; } TRACE_FLOW("Request %d bytes.\n", numBytesToRead); TRXHeader header; iovec rxData[] = { { &header, sizeof(TRXHeader) }, { buffer, numBytesToRead } }; size_t startIndex = fUseTRXHeader ? 0 : 1 ; size_t chunkCount = fUseTRXHeader ? 2 : 1 ; status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, &rxData[startIndex], chunkCount, _ReadCallback, this); if (result != B_OK) { TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result); return result; } uint32 flags = B_CAN_INTERRUPT | (fNonBlocking ? B_TIMEOUT : 0); result = acquire_sem_etc(fNotifyReadSem, 1, flags, 0); if (result < B_OK) { TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result); return result; } if (fStatusRead != B_OK && fStatusRead != B_CANCELED && !fRemoved) { TRACE_ALWAYS("Device status error:%#010x\n", fStatusRead); result = gUSBModule->clear_feature(fReadEndpoint, USB_FEATURE_ENDPOINT_HALT); if (result != B_OK) { TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result); return result; } } if (fUseTRXHeader) { if (fActualLengthRead < sizeof(TRXHeader)) { TRACE_ALWAYS("Error: no place for TRXHeader:only %d of %d bytes.\n", fActualLengthRead, sizeof(TRXHeader)); return B_ERROR; // TODO: ??? } if (!header.IsValid()) { TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n", header.fLength, header.fInvertedLength); return B_ERROR; // TODO: ??? } *numBytes = header.Length(); if (fActualLengthRead - sizeof(TRXHeader) > header.Length()) { TRACE_ALWAYS("MISMATCH of the frame length: hdr %d; received:%d\n", header.Length(), fActualLengthRead - sizeof(TRXHeader)); } } else { *numBytes = fActualLengthRead; } TRACE_FLOW("Read %d bytes.\n", *numBytes); return B_OK; }
int _hasAvailableBlock(const size_t blockSize) { TRACE_FLOW("(%lu)", blockSize); return GET_FIRST_BLOCK_ADDRESS(blockSize) != 0; }