Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
status_t
DavicomDevice::GetLinkState(ether_link_state *linkState)
{
	uint8 registerValue = 0;
	status_t result = _ReadRegister(NSR, 1, &registerValue);
	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, &registerValue);
		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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
int _hasAvailableBlock(const size_t blockSize) {
	TRACE_FLOW("(%lu)", blockSize);
	return GET_FIRST_BLOCK_ADDRESS(blockSize) != 0;
}