Example #1
0
status_t
device_write(void *data, off_t pos, const void *buffer, size_t *_length)
{
	struct sis_info *info;
	status_t status;
	uint16 frameSize;
	int16 current;
	uint32 check;

	if (checkDeviceInfo(info = data) != B_OK)
		return EINVAL;

	//TRACE(("****\t%5ld: write... %lx, %ld (%d) thread: %ld, counter = %ld\n", counter++, buf, *len, info->txLock, threadID, intrCounter));
	atomic_add(&info->txLock, 1);

	if (*_length > MAX_FRAME_SIZE)
		*_length = MAX_FRAME_SIZE;

	frameSize = *_length;
	current = info->txCurrent;

	//dprintf("\t%5ld: \twrite: tx: isr = %d, sent = %d, current = %d\n",counter++,
	//		info->txInterruptIndex,info->txSent,info->txCurrent);

	// block until a free tx descriptor is available
	if ((status = acquire_sem_etc(info->txSem, 1, B_TIMEOUT, ETHER_TRANSMIT_TIMEOUT)) < B_NO_ERROR) {
		write32(info->registers + SiS900_MAC_COMMAND, SiS900_MAC_CMD_Tx_ENABLE);
		TRACE(("write: acquiring sem failed: %lx, %s\n", status, strerror(status)));
		atomic_add(&info->txLock, -1);
		return status;
	}

	check = info->txDescriptor[current].status;
	if (check & SiS900_DESCR_OWN) {
		// descriptor is still in use
		dprintf(DEVICE_NAME ": card owns buffer %d\n", current);
		atomic_add(&info->txLock, -1);
		return B_ERROR;
	}

	/* Copy data to tx buffer */
	memcpy((void *)info->txBuffer[current], buffer, frameSize);
	info->txCurrent = (current + 1) & NUM_Tx_MASK;

	{
		cpu_status former;
		former = disable_interrupts();
		acquire_spinlock(&info->txSpinlock);

		info->txDescriptor[current].status = SiS900_DESCR_OWN | frameSize;
		info->txSent++;

#if 0
		{
			struct buffer_desc *b = (void *)read32(info->registers + SiS900_MAC_Tx_DESCR);
			int16 that;

			dprintf("\twrite: status %d = %lx, sent = %d\n", current, info->txDescriptor[current].status,info->txSent);
			dprintf("write: %d: mem = %lx : hardware = %lx\n", current, physicalAddress(&info->txDescriptor[current],sizeof(struct buffer_desc)),read32(info->registers + SiS900_MAC_Tx_DESCR));

			for (that = 0;that < NUM_Tx_DESCR && (void *)physicalAddress(&info->txDescriptor[that],sizeof(struct buffer_desc)) != b;that++);

			if (that == NUM_Tx_DESCR) {
				//dprintf("not in ring!\n");
				that = 0;
			}
			dprintf("(hardware status %d = %lx)!\n", that, info->txDescriptor[that].status);
		}
#endif
		release_spinlock(&info->txSpinlock);
   		restore_interrupts(former);
	}

	// enable transmit state machine
	write32(info->registers + SiS900_MAC_COMMAND, SiS900_MAC_CMD_Tx_ENABLE);

#ifdef EXCESSIVE_DEBUG
	acquire_sem(gIOLock);
	bug("\t\twrite last interrupts:\n");
	{
		int ii;
		for (ii = (intrCounter-2) % 100; ii < intrCounter; ii = (ii + 1) % 100)
			bug("\t\t\t%ld: %08lx\n", ii, lastIntr[ii % 100]);
	}
	bug("\t\twrite block (%ld bytes) thread = %ld:\n", frameSize, threadID);
	dumpBlock(buf,frameSize, "\t\t\t");
	release_sem(gIOLock);
#endif

	atomic_add(&info->txLock, -1);
	return B_OK;
}
Example #2
0
Byte readByte(Word offset, int seg = -1)
{
    return ram[physicalAddress(offset, seg) - 0x10000];
}
Example #3
0
void writeByte(Byte value, Word offset, int seg = -1)
{
    ram[physicalAddress(offset, seg) - 0x10000] = value;
}
Example #4
0
static int32
sis900_txInterrupt(struct sis_info *info)
{
	int16 releaseTxSem = 0;
	uint32 status;
	int16 limit;

	acquire_spinlock(&info->txSpinlock);

	HACK(spin(10000));

	for (limit = info->txSent; limit > 0; limit--) {
		status = info->txDescriptor[info->txInterruptIndex].status;

//dprintf("txIntr: %d: mem = %lx : hardware = %lx\n",info->txInterruptIndex,
//		physicalAddress(&info->txDescriptor[info->txInterruptIndex],sizeof(struct buffer_desc)),
//		read32(info->registers + SiS900_MAC_Tx_DESCR));

		/* Does the device generate extra interrupts? */
		if (status & SiS900_DESCR_OWN) {
			struct buffer_desc *descriptor = (void *)read32(info->registers + SiS900_MAC_Tx_DESCR);
			int16 that;
			for (that = 0;
				that < NUM_Tx_DESCR
					&& physicalAddress(&info->txDescriptor[that],
						sizeof(struct buffer_desc)) != (addr_t)descriptor;
				that++) {
			}
			if (that == NUM_Tx_DESCR)
				that = 0;

//dprintf("tx busy %d: %lx (hardware status %d = %lx)!\n",info->txInterruptIndex,status,that,info->txDescriptor[that].status);
//			if (limit == info->txSent)
//			{
//dprintf("oh no!\n");
//				limit++;
//				continue;
//			}
			break;
		}

		if (status & (SiS900_DESCR_Tx_ABORT | SiS900_DESCR_Tx_UNDERRUN
				| SiS900_DESCR_Tx_OOW_COLLISION)) {
			dprintf("tx error: %lx\n", status);
		} else
			info->txDescriptor[info->txInterruptIndex].status = 0;

		releaseTxSem++;	/* this many buffers are free */
		info->txInterruptIndex = (info->txInterruptIndex + 1) & NUM_Tx_MASK;
		info->txSent--;

		if (info->txSent < 0 || info->txSent > NUM_Tx_DESCR)
			dprintf("ERROR interrupt: txSent = %d\n", info->txSent);
	}
	release_spinlock(&info->txSpinlock);

	if (releaseTxSem) {
		release_sem_etc(info->txSem, releaseTxSem, B_DO_NOT_RESCHEDULE);
		return B_INVOKE_SCHEDULER;
	}

	return B_HANDLED_INTERRUPT;
}