Browse Source

cointerra: Use lowl-usb endpoint interface to get VCOM-like characteristics

Luke Dashjr 12 years ago
parent
commit
1f34eacbb5
1 changed files with 52 additions and 48 deletions
  1. 52 48
      driver-cointerra.c

+ 52 - 48
driver-cointerra.c

@@ -59,6 +59,7 @@ enum cointerra_reset_level {
 
 
 struct cointerra_dev_state {
 struct cointerra_dev_state {
 	libusb_device_handle *usbh;
 	libusb_device_handle *usbh;
+	struct lowl_usb_endpoint *ep;
 	unsigned pipes_per_asic;
 	unsigned pipes_per_asic;
 	unsigned pipes_per_die;
 	unsigned pipes_per_die;
 	int works_requested;
 	int works_requested;
@@ -68,7 +69,26 @@ struct cointerra_dev_state {
 static const uint8_t cointerra_startseq[] = {COINTERRA_START_SEQ};
 static const uint8_t cointerra_startseq[] = {COINTERRA_START_SEQ};
 
 
 static
 static
-int cointerra_write_msg(libusb_device_handle * const usbh, const char * const repr, const uint8_t msgtype, const void * const msgbody, const unsigned timeout)
+bool cointerra_open(const struct lowlevel_device_info * const info, const char * const repr, libusb_device_handle ** const usbh_p, struct lowl_usb_endpoint ** const ep_p)
+{
+	if (libusb_open(info->lowl_data, usbh_p))
+		applogr(false, LOG_DEBUG, "%s: USB open failed on %s",
+		        repr, info->devid);
+	*ep_p = usb_open_ep_pair(*usbh_p, COINTERRA_EP_R, 64, COINTERRA_EP_W, 64);
+	usb_ep_set_timeouts_ms(*ep_p, COINTERRA_USB_TIMEOUT, COINTERRA_USB_TIMEOUT);
+	if (!*ep_p)
+	{
+		applog(LOG_DEBUG, "%s: Endpoint open failed on %s",
+		       repr, info->devid);
+		libusb_close(*usbh_p);
+		*usbh_p = NULL;
+		return false;
+	}
+	return true;
+}
+
+static
+bool cointerra_write_msg(struct lowl_usb_endpoint * const ep, const char * const repr, const uint8_t msgtype, const void * const msgbody)
 {
 {
 	uint8_t buf[COINTERRA_PACKET_SIZE], *p;
 	uint8_t buf[COINTERRA_PACKET_SIZE], *p;
 	memcpy(buf, cointerra_startseq, sizeof(cointerra_startseq));
 	memcpy(buf, cointerra_startseq, sizeof(cointerra_startseq));
@@ -76,53 +96,46 @@ int cointerra_write_msg(libusb_device_handle * const usbh, const char * const re
 	pk_u8(p, 0, msgtype);
 	pk_u8(p, 0, msgtype);
 	memcpy(&p[1], msgbody, COINTERRA_MSGBODY_SIZE);
 	memcpy(&p[1], msgbody, COINTERRA_MSGBODY_SIZE);
 	
 	
-	int e, xfer;
-	
-	e = libusb_bulk_transfer(usbh, COINTERRA_EP_W, buf, sizeof(buf), &xfer, timeout);
-	if (e)
-		return e;
-	
-	if (xfer != COINTERRA_PACKET_SIZE)
-		return LIBUSB_ERROR_OTHER;
+	if (usb_write(ep, buf, sizeof(buf)) != sizeof(buf))
+		return false;
 	
 	
-	return 0;
+	return true;
 }
 }
 
 
 static
 static
-int cointerra_read_msg(uint8_t * const out_msgtype, uint8_t * const out, libusb_device_handle * const usbh, const char * const repr, const unsigned timeout)
+bool cointerra_read_msg(uint8_t * const out_msgtype, uint8_t * const out, struct lowl_usb_endpoint * const ep, const char * const repr)
 {
 {
 	uint8_t ss[] = {COINTERRA_START_SEQ};
 	uint8_t ss[] = {COINTERRA_START_SEQ};
 	uint8_t buf[COINTERRA_PACKET_SIZE];
 	uint8_t buf[COINTERRA_PACKET_SIZE];
-	int e, xfer;
-	e = libusb_bulk_transfer(usbh, COINTERRA_EP_R, buf, sizeof(buf), &xfer, timeout);
-	if (e)
-		return e;
-	if (xfer != COINTERRA_PACKET_SIZE)
-		applogr(LIBUSB_ERROR_OTHER, LOG_ERR, "%s: Packet size mismatch (actual=%d expected=%d)",
-		        repr, xfer, (int)COINTERRA_PACKET_SIZE);
+	const int xfer = usb_read(ep, buf, sizeof(buf));
+	if (!xfer)
+		return false;
+	if (xfer != sizeof(buf))
+		applogr(false, LOG_ERR, "%s: Packet size mismatch (actual=%d expected=%d)",
+		        repr, xfer, (int)sizeof(buf));
 	for (int i = sizeof(ss); i--; )
 	for (int i = sizeof(ss); i--; )
 		if (ss[i] != buf[i])
 		if (ss[i] != buf[i])
 			applogr(LIBUSB_ERROR_OTHER;, LOG_ERR, "%s: Packet start sequence mismatch", repr);
 			applogr(LIBUSB_ERROR_OTHER;, LOG_ERR, "%s: Packet start sequence mismatch", repr);
 	uint8_t * const bufp = &buf[sizeof(ss)];
 	uint8_t * const bufp = &buf[sizeof(ss)];
 	*out_msgtype = upk_u8(bufp, 0);
 	*out_msgtype = upk_u8(bufp, 0);
 	memcpy(out, &bufp[1], COINTERRA_MSGBODY_SIZE);
 	memcpy(out, &bufp[1], COINTERRA_MSGBODY_SIZE);
-	return 0;
+	return true;
 }
 }
 
 
 static
 static
-int cointerra_request(libusb_device_handle * const usbh, const uint8_t msgtype, uint16_t interval_cs)
+bool cointerra_request(struct lowl_usb_endpoint * const ep, const uint8_t msgtype, uint16_t interval_cs)
 {
 {
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
 	pk_u16le(buf, 0, msgtype);
 	pk_u16le(buf, 0, msgtype);
 	pk_u16le(buf, 2, interval_cs);
 	pk_u16le(buf, 2, interval_cs);
-	return cointerra_write_msg(usbh, cointerra_drv.dname, CMTO_REQUEST, buf, COINTERRA_USB_TIMEOUT);
+	return cointerra_write_msg(ep, cointerra_drv.dname, CMTO_REQUEST, buf);
 }
 }
 
 
 static
 static
-int cointerra_reset(libusb_device_handle * const usbh, const enum cointerra_reset_level crl)
+bool cointerra_reset(struct lowl_usb_endpoint * const ep, const enum cointerra_reset_level crl)
 {
 {
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = { crl };
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = { crl };
-	return cointerra_write_msg(usbh, cointerra_drv.dname, CMTO_RESET, buf, COINTERRA_USB_TIMEOUT);
+	return cointerra_write_msg(ep, cointerra_drv.dname, CMTO_RESET, buf);
 }
 }
 
 
 static
 static
@@ -134,24 +147,22 @@ bool cointerra_lowl_match(const struct lowlevel_device_info * const info)
 static
 static
 bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
 bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
 {
 {
-	int e;
+	bool rv = false;
 	
 	
 	if (info->lowl != &lowl_usb)
 	if (info->lowl != &lowl_usb)
 		applogr(false, LOG_DEBUG, "%s: Matched \"%s\" %s, but lowlevel driver is not usb_generic!",
 		applogr(false, LOG_DEBUG, "%s: Matched \"%s\" %s, but lowlevel driver is not usb_generic!",
 		        __func__, info->product, info->devid);
 		        __func__, info->product, info->devid);
 	
 	
 	libusb_device_handle *usbh;
 	libusb_device_handle *usbh;
-	e = libusb_open(info->lowl_data, &usbh);
-	if (e)
-		applogr(false, LOG_ERR, "%s: Failed to open %s: %s",
-		        cointerra_drv.dname, info->devid, bfg_strerror(e, BST_LIBUSB));
+	struct lowl_usb_endpoint *ep;
+	if (!cointerra_open(info, cointerra_drv.dname, &usbh, &ep))
+		return false;
 	
 	
 	unsigned pipes;
 	unsigned pipes;
 	{
 	{
 		{
 		{
 			uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
 			uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
-			e = cointerra_write_msg(usbh, cointerra_drv.dname, CMTO_GET_INFO, buf, COINTERRA_USB_TIMEOUT);
-			if (e)
+			if (!cointerra_write_msg(ep, cointerra_drv.dname, CMTO_GET_INFO, buf))
 				goto err;
 				goto err;
 		}
 		}
 		
 		
@@ -159,8 +170,7 @@ bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
 		uint8_t buf[COINTERRA_MSG_SIZE];
 		uint8_t buf[COINTERRA_MSG_SIZE];
 		while (true)
 		while (true)
 		{
 		{
-			e = cointerra_read_msg(&msgtype, buf, usbh, cointerra_drv.dname, COINTERRA_USB_TIMEOUT);
-			if (e)
+			if (!cointerra_read_msg(&msgtype, buf, ep, cointerra_drv.dname))
 				goto err;
 				goto err;
 			if (msgtype == CMTI_INFO)
 			if (msgtype == CMTI_INFO)
 				break;
 				break;
@@ -185,11 +195,12 @@ bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
 		.dev_serial = maybe_strdup(info->serial),
 		.dev_serial = maybe_strdup(info->serial),
 		.deven = DEV_ENABLED,
 		.deven = DEV_ENABLED,
 	};
 	};
-	return add_cgpu(cgpu);
+	rv = add_cgpu(cgpu);
 
 
 err:
 err:
+	usb_close_ep(ep);
 	libusb_close(usbh);
 	libusb_close(usbh);
-	return false;
+	return rv;
 }
 }
 
 
 static
 static
@@ -198,23 +209,20 @@ bool cointerra_init(struct thr_info * const master_thr)
 	struct cgpu_info * const dev = master_thr->cgpu;
 	struct cgpu_info * const dev = master_thr->cgpu;
 	struct lowlevel_device_info * const info = dev->device_data;
 	struct lowlevel_device_info * const info = dev->device_data;
 	struct cointerra_dev_state * const devstate = malloc(sizeof(*devstate));
 	struct cointerra_dev_state * const devstate = malloc(sizeof(*devstate));
-	int e;
 	
 	
 	dev->device_data = devstate;
 	dev->device_data = devstate;
 	*devstate = (struct cointerra_dev_state){
 	*devstate = (struct cointerra_dev_state){
 		.pipes_per_die = 120,
 		.pipes_per_die = 120,
 		.pipes_per_asic = 240,
 		.pipes_per_asic = 240,
 	};
 	};
-	e = libusb_open(info->lowl_data, &devstate->usbh);
-	if (e)
-		applogr(false, LOG_ERR, "%s: Failed to open %s: %s",
-		        dev->dev_repr, info->devid, bfg_strerror(e, BST_LIBUSB));
-	libusb_device_handle * const usbh = devstate->usbh;
+	if (!cointerra_open(info, dev->dev_repr, &devstate->usbh, &devstate->ep))
+		return false;
+	struct lowl_usb_endpoint * const ep = devstate->ep;
 	
 	
 	// Request regular status updates
 	// Request regular status updates
-	cointerra_request(usbh, CMTI_STATUS, 0x83d);
+	cointerra_request(ep, CMTI_STATUS, 0x83d);
 	
 	
-	cointerra_reset(usbh, CRL_INIT);
+	cointerra_reset(ep, CRL_INIT);
 	
 	
 	// Queue is full until device asks for work
 	// Queue is full until device asks for work
 	set_on_all_procs(dev, thr[0]->queue_full, true);
 	set_on_all_procs(dev, thr[0]->queue_full, true);
@@ -231,7 +239,6 @@ bool cointerra_queue_append(struct thr_info * const thr, struct work * const wor
 	struct thr_info * const master_thr = dev->thr[0];
 	struct thr_info * const master_thr = dev->thr[0];
 	struct cointerra_dev_state * const devstate = dev->device_data;
 	struct cointerra_dev_state * const devstate = dev->device_data;
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
 	uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
-	int e;
 	
 	
 	if (unlikely(!devstate->works_requested))
 	if (unlikely(!devstate->works_requested))
 	{
 	{
@@ -246,8 +253,7 @@ bool cointerra_queue_append(struct thr_info * const thr, struct work * const wor
 	swap32yes(&buf[0x26], &work->data[0x40],  0xc / 4);
 	swap32yes(&buf[0x26], &work->data[0x40],  0xc / 4);
 	pk_u16le(buf, 50, 0);  // ntime roll limit
 	pk_u16le(buf, 50, 0);  // ntime roll limit
 	pk_u16le(buf, 52, 0x20);  // number of zero bits in results
 	pk_u16le(buf, 52, 0x20);  // number of zero bits in results
-	e = cointerra_write_msg(devstate->usbh, cointerra_drv.dname, CMTO_WORK, buf, COINTERRA_USB_TIMEOUT);
-	if (e)
+	if (!cointerra_write_msg(devstate->ep, cointerra_drv.dname, CMTO_WORK, buf))
 		return false;
 		return false;
 	
 	
 	HASH_ADD_INT(master_thr->work, device_id, work);
 	HASH_ADD_INT(master_thr->work, device_id, work);
@@ -269,12 +275,10 @@ bool cointerra_poll_msg(struct thr_info * const master_thr)
 	struct cgpu_info * const dev = master_thr->cgpu, *proc;
 	struct cgpu_info * const dev = master_thr->cgpu, *proc;
 	struct thr_info *mythr;
 	struct thr_info *mythr;
 	struct cointerra_dev_state * const devstate = dev->device_data;
 	struct cointerra_dev_state * const devstate = dev->device_data;
-	int e;
 	uint8_t msgtype;
 	uint8_t msgtype;
 	uint8_t buf[COINTERRA_MSGBODY_SIZE];
 	uint8_t buf[COINTERRA_MSGBODY_SIZE];
 	
 	
-	e = cointerra_read_msg(&msgtype, buf, devstate->usbh, dev->dev_repr, COINTERRA_USB_POLL_TIMEOUT);
-	if (e)
+	if (!cointerra_read_msg(&msgtype, buf, devstate->ep, dev->dev_repr))
 		return false;
 		return false;
 	
 	
 	switch (msgtype)
 	switch (msgtype)