Ejemplo n.º 1
0
static void
pegasus_tx_callback(void *cookie, status_t status, void *data, size_t actual_len)
{
	pegasus_dev *dev = (pegasus_dev *)cookie;

	DPRINTF_INFO("pegasus_tx_callback() %ld %ld\n", status, actual_len);
	if (status == B_CANCELED) {
		/* cancelled: device is unplugged */
		DPRINTF_ERR("pegasus_tx_callback() cancelled\n");
		return;
	}

	ASSERT(cookie != NULL);
	dev->tx_actual_length = actual_len;
	dev->tx_status = status;	/* B_USB_STATUS_* */
	release_sem(dev->tx_sem_cb);
	DPRINTF_INFO("pegasus_tx_callback release sem %ld\n", dev->tx_sem_cb);
}
Ejemplo n.º 2
0
static status_t
aue_init_phy(pegasus_dev *dev)
{
	uint16 phy, status;
	int i;
	
	dev->phy = 255;

	// search for total of 32 possible MII PHY addresses
	for (phy = 0; phy < 32; phy++) {
		uint16 status;

		status = aue_miibus_status_from_phy(dev, phy);
		if (status == 0xffff || status == 0x0000)
			// this MII is not accessable
			continue;

		dev->phy = phy;
	}

	if (dev->phy == 255) {
		DPRINTF_ERR("No MII PHY transceiver found!\n");
		return B_ENTRY_NOT_FOUND;
	}
	DPRINTF_INFO("aue_init_phy MII PHY found at %d\n", dev->phy);
	
	status = aue_miibus_read(dev, MII_CONTROL);
	status &= ~MII_CONTROL_ISOLATE;

	aue_miibus_write(dev, MII_CONTROL, status);

	aue_miibus_write(dev, MII_CONTROL, MII_CONTROL_RESET);
	for (i = 0; i < 100; i++) {
		if ((aue_miibus_read(dev, MII_STATUS) & MII_CONTROL_RESET) == 0)
			break;
		DELAY(1000);
	}
	
	dev->link = aue_miibus_status(dev) & MII_STATUS_LINK;

	return B_OK;
}
Ejemplo n.º 3
0
static status_t
pegasus_device_write(driver_cookie *cookie, off_t position,	const void *buffer, size_t *_length)
{
	pegasus_dev *dev;
	status_t status;
	uint16 frameSize;

	DPRINTF_INFO("device %p write %ld\n", cookie, *_length);

	if (pegasus_checkdeviceinfo(dev = cookie->device) != B_OK) {
		DPRINTF_ERR("EINVAL\n");
		return EINVAL;
	}

	if (dev->aue_dying)
		return B_DEVICE_NOT_FOUND;		/* already unplugged */

		// block until a free tx descriptor is available
	if ((status = acquire_sem_etc(dev->tx_sem, 1, B_TIMEOUT, ETHER_TRANSMIT_TIMEOUT)) < B_NO_ERROR) {
		DPRINTF_ERR("write: acquiring sem failed: %" B_PRIx32 ", %s\n", status, strerror(status));
		return status;
	}


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

	frameSize = *_length;

	/* Copy data to tx buffer */
	memcpy(dev->tx_buffer+2, buffer, frameSize);

	/*
	 * The ADMtek documentation says that the packet length is
	 * supposed to be specified in the first two bytes of the
	 * transfer, however it actually seems to ignore this info
	 * and base the frame size on the bulk transfer length.
	 */
	dev->tx_buffer[0] = (uint8)frameSize;
	dev->tx_buffer[1] = (uint8)(frameSize >> 8);

	// queue new request, bulk length is one more if size is a multiple of 64
	status = usb->queue_bulk(dev->pipe_out, dev->tx_buffer, ((frameSize + 2) & 0x3f) ? frameSize + 2 : frameSize + 3,
		&pegasus_tx_callback, dev);

	if (status != B_OK){
		DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32 "\n", status);
		goto tx_done;
	}

	// block until data is sent (if blocking is allowed)
	if ((status = acquire_sem_etc(dev->tx_sem_cb, 1, B_CAN_INTERRUPT, 0)) != B_NO_ERROR) {
		DPRINTF_ERR("cannot acquire write done sem: %" B_PRIx32 ", %s\n", status, strerror(status));
#ifndef __HAIKU__
		*_length = 0;
#endif
		goto tx_done;
	}

	if (dev->tx_status != B_OK) {
		status = usb->clear_feature(dev->pipe_out, USB_FEATURE_ENDPOINT_HALT);
		if (status != B_OK)
			DPRINTF_ERR("clear_feature() error %s\n", strerror(status));
		goto tx_done;
	}

	*_length = frameSize;

tx_done:
	release_sem(dev->tx_sem);
	return status;
}
Ejemplo n.º 4
0
static status_t
pegasus_device_read(driver_cookie *cookie, off_t position, void *buffer, size_t *_length)
{
	pegasus_dev *dev;
	status_t status;
	int32 blockFlag;
	size_t size;

	DPRINTF_INFO("device %p read\n", cookie);

	if (pegasus_checkdeviceinfo(dev = cookie->device) != B_OK) {
		DPRINTF_ERR("EINVAL\n");
#ifndef __HAIKU__
		*_length = 0;
			// net_server work-around; it obviously doesn't care about error conditions
			// For Haiku, this can be removed
#endif
		return B_BAD_VALUE;
	}

	if (dev->aue_dying)
		return B_DEVICE_NOT_FOUND;		/* already unplugged */

	blockFlag = dev->nonblocking ? B_TIMEOUT : 0;

	// block until receive is available (if blocking is allowed)
	if ((status = acquire_sem_etc(dev->rx_sem, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_NO_ERROR) {
		DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32 ", %s\n", status, strerror(status));
#ifndef __HAIKU__
		*_length = 0;
#endif
		return status;
	}

	// queue new request
	status = usb->queue_bulk(dev->pipe_in, dev->rx_buffer, MAX_FRAME_SIZE, &pegasus_rx_callback, dev);

	if (status != B_OK) {
		DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32 "\n", status);
		goto rx_done;
	}

	// block until data is available (if blocking is allowed)
	if ((status = acquire_sem_etc(dev->rx_sem_cb, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_NO_ERROR) {
		DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32 ", %s\n", status, strerror(status));
#ifndef __HAIKU__
		*_length = 0;
#endif
		goto rx_done;
	}

	if (dev->rx_status != B_OK) {
		status = usb->clear_feature(dev->pipe_in, USB_FEATURE_ENDPOINT_HALT);
		if (status != B_OK)
			DPRINTF_ERR("clear_feature() error %s\n", strerror(status));
		goto rx_done;
	}

	// copy buffer
	size = dev->rx_actual_length;
	if (size > MAX_FRAME_SIZE || (size - 2) > *_length) {
		DPRINTF_ERR("ERROR read: bad frame size %ld\n", size);
		size = *_length;
	} else if (size < *_length)
		*_length = size - 2;

	memcpy(buffer, dev->rx_buffer, size);

	DPRINTF_INFO("read done %ld\n", *_length);

rx_done:
	release_sem(dev->rx_sem);
	return status;
}
Ejemplo n.º 5
0
static status_t
pegasus_device_added(const usb_device dev, void **cookie)
{
	pegasus_dev *device;
	const usb_device_descriptor *dev_desc;
	const usb_configuration_info *conf;
	const usb_interface_info *intf;
	status_t status;
	uint16 ifno;
	int i;

	ASSERT(dev != 0 && cookie != NULL);
	DPRINTF_INFO("device_added()\n");

	dev_desc = usb->get_device_descriptor(dev);

	DPRINTF_INFO("vendor ID 0x%04X, product ID 0x%04X\n", dev_desc->vendor_id,
		dev_desc->product_id);

	if ((conf = usb->get_nth_configuration(dev, DEFAULT_CONFIGURATION))
		== NULL) {
		DPRINTF_ERR("cannot get default configuration\n");
		return B_ERROR;
	}

	ifno = AUE_IFACE_IDX;
	intf = conf->interface [ifno].active;

	/* configuration */

	if ((status = usb->set_configuration(dev, conf)) != B_OK) {
		DPRINTF_ERR("set_configuration() failed %s\n", strerror(status));
		return B_ERROR;
	}

	if ((device = create_device(dev, intf, ifno)) == NULL) {
		DPRINTF_ERR("create_device() failed\n");
		return B_ERROR;
	}

	device->aue_vendor = dev_desc->vendor_id;
	device->aue_product = dev_desc->product_id;

	for (i=0; i < sizeof(aue_devs) / sizeof(struct aue_type); i++)
		if (aue_devs[i].aue_dev.vendor == dev_desc->vendor_id
			&& aue_devs[i].aue_dev.product == dev_desc->product_id) {
			device->aue_flags = aue_devs[i].aue_flags;
			break;
		}

	/* Find endpoints. */
	setup_endpoints(intf, device);

	aue_attach(device);

	DPRINTF_INFO("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
		device->macaddr[0], device->macaddr[1], device->macaddr[2],
		device->macaddr[3], device->macaddr[4], device->macaddr[5]);

	aue_init(device);

	/* create a port */
	add_device_info(device);

	*cookie = device;
	DPRINTF_INFO("added %s\n", device->name);
	return B_OK;
}
Ejemplo n.º 6
0
pegasus_dev *
create_device(const usb_device dev, const usb_interface_info *ii, uint16 ifno)
{
	pegasus_dev *device = NULL;
	sem_id sem;

	ASSERT(usb != NULL && dev != 0);

	device = malloc(sizeof(pegasus_dev));
	if (device == NULL)
		return NULL;

	memset(device, 0, sizeof(pegasus_dev));

	device->sem_lock = sem = create_sem(1, DRIVER_NAME "_lock");
	if (sem < B_OK) {
		DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
		free(device);
		return NULL;
	}

	device->rx_sem = sem = create_sem(1, DRIVER_NAME"_receive");
	if (sem < B_OK) {
		DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
		delete_sem(device->sem_lock);
		free(device);
		return NULL;
	}
	set_sem_owner(device->rx_sem, B_SYSTEM_TEAM);

	device->rx_sem_cb = sem = create_sem(0, DRIVER_NAME"_receive_cb");
	if (sem < B_OK) {
		DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
		delete_sem(device->rx_sem);
		delete_sem(device->sem_lock);
		free(device);
		return NULL;
	}
	set_sem_owner(device->rx_sem_cb, B_SYSTEM_TEAM);

	device->tx_sem = sem = create_sem(1, DRIVER_NAME"_transmit");
	if (sem < B_OK) {
		delete_sem(device->sem_lock);
		delete_sem(device->rx_sem);
		delete_sem(device->rx_sem_cb);
		free(device);
		return NULL;
	}
	set_sem_owner(device->tx_sem, B_SYSTEM_TEAM);

	device->tx_sem_cb = sem = create_sem(0, DRIVER_NAME"_transmit_cb");
	if (sem < B_OK) {
		delete_sem(device->sem_lock);
		delete_sem(device->rx_sem);
		delete_sem(device->rx_sem_cb);
		delete_sem(device->tx_sem);
		free(device);
		return NULL;
	}
	set_sem_owner(device->tx_sem_cb, B_SYSTEM_TEAM);

	device->number = sDeviceNumber++;
	device->cookieMagic = PEGASUS_COOKIE_MAGIC;
	sprintf(device->name, "%s%d", kBaseName, device->number);
	device->dev = dev;
	device->ifno = ifno;
	device->open = 0;
	device->open_fds = NULL;
	device->aue_dying = false;
	device->flags = 0;
	device->maxframesize = 1514; // XXX is MAXIMUM_ETHERNET_FRAME_SIZE = 1518 too much?

	return device;
}