rem: thread_id threadID = find_thread(NULL); int32 rxp, rxd;
context: device_read(void *data, off_t pos, void *buffer, size_t *_length){	struct sis_info *info;	status_t status;	size_t size;	int32 blockFlag;	thread_id threadID = find_thread(NULL);	int32 rxp, rxd;	uint32 check;	int16 current;	if (checkDeviceInfo(info = data) != B_OK) {		*_length = 0;		return EINVAL;	}	//dprintf("read: rx: isr = %d, free = %d, current = %d\n",	//		info->rxInterruptIndex, info->rxFree, info->rxCurrent);	blockFlag = info->blockFlag;	// read is not reentrant	if (atomic_or(&info->rxLock, 1)) {		*_length = 0;		return B_ERROR;	}	//TRACE(("current rx descr: %08x (last = %ld)\n", rxp = read32((uint32)info->registers + SiS900_MAC_Rx_DESCR),(info->rxLast+1) % NUM_Rx_DESCR));	// block until data is available (if blocking is allowed)	if ((status = acquire_sem_etc(info->rxSem, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_NO_ERROR) {		TRACE(("cannot acquire read sem: %x, %s\n", status, strerror(status)));		atomic_and(&info->rxLock, 0);		*_length = 0;		return status;	}	/* three cases, frame is good, bad, or we don't own the descriptor */	current = info->rxCurrent;	check = info->rxDescriptor[current].status;	if (!(check & SiS900_DESCR_OWN)) {	// the buffer is still in use!		TRACE(("ERROR: read: buffer %d still in use: %x\n", current, status));		atomic_and(&info->rxLock, 0);		*_length = 0;		return;	}	if (check & (SiS900_DESCR_Rx_ABORT | SiS900_DESCR_Rx_OVERRUN |				 SiS900_DESCR_Rx_LONG_PACKET | SiS900_DESCR_Rx_RUNT_PACKET |				 SiS900_DESCR_Rx_INVALID_SYM | SiS900_DESCR_Rx_FRAME_ALIGN |				 SiS900_DESCR_Rx_CRC_ERROR)) {		TRACE(("ERROR read: packet with errors: %ld\n", check));		*_length = 0;	} else {		// copy buffer		size = (check & SiS900_DESCR_SIZE_MASK) - CRC_SIZE;		if (size > MAX_FRAME_SIZE || size > *_length) {			TRACE(("ERROR read: bad frame size %d\n", size));			size = *_length;		}		memcpy(buffer, (void *)info->rxBuffer[current], size);	}	info->rxCurrent = (current + 1) & NUM_Rx_MASK;	/* update indexes and buffer ownership */	{		cpu_status former;		former = disable_interrupts();		acquire_spinlock(&info->rxSpinlock);		// release buffer to ring		info->rxDescriptor[current].status = MAX_FRAME_SIZE + CRC_SIZE;		info->rxFree++;		release_spinlock(&info->rxSpinlock);   		restore_interrupts(former);	}	atomic_and(&info->rxLock, 0);	return B_OK;}