⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shuttle_usbat.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",		direction==SCSI_DATA_WRITE ? "Writing" : "Reading");	return USB_STOR_TRANSPORT_FAILED;}/* * Write data to multiple registers at once. Not meant for large * transfers of data! */int usbat_multiple_write(struct us_data *us, 			unsigned char access,			unsigned char *registers,			unsigned char *data_out,			unsigned short num_registers) {	int result;	unsigned char data[num_registers*2];	int i;	unsigned char command[8] = {		0x40, access|0x07, 0x00, 0x00, 0x00, 0x00,		LSB_of(num_registers*2), MSB_of(num_registers*2)	};	for (i=0; i<num_registers; i++) {		data[i<<1] = registers[i];		data[1+(i<<1)] = data_out[i];	}	result = usbat_send_control(us,		usb_sndctrlpipe(us->pusb_dev,0),		0x80,		0x40,		0,		0,		command,		8);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	result = usbat_bulk_transport(us,		NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);	if (result!=USB_STOR_TRANSPORT_GOOD)		return result;	return usbat_wait_not_busy(us, 0);}int usbat_read_user_io(struct us_data *us,		unsigned char *data_flags) {	int result;	result = usbat_send_control(us,		usb_rcvctrlpipe(us->pusb_dev,0),		0x82,		0xC0,		0,		0,		data_flags,		1);	return result;}int usbat_write_user_io(struct us_data *us,		unsigned char enable_flags,		unsigned char data_flags) {	int result;	result = usbat_send_control(us,		usb_sndctrlpipe(us->pusb_dev,0),		0x82,		0x40,		short_pack(enable_flags, data_flags),		0,		NULL,		0);	return result;}/* * Squeeze a potentially huge (> 65535 byte) read10 command into * a little ( <= 65535 byte) ATAPI pipe */int usbat_handle_read10(struct us_data *us,		unsigned char *registers,		unsigned char *data,		Scsi_Cmnd *srb) {	int result = USB_STOR_TRANSPORT_GOOD;	unsigned char *buffer;	unsigned int len;	unsigned int sector;	unsigned int amount;	struct scatterlist *sg = NULL;	int sg_segment = 0;	int sg_offset = 0;	US_DEBUGP("handle_read10: transfersize %d\n",		srb->transfersize);	if (srb->request_bufflen < 0x10000) {		result = usbat_rw_block_test(us, USBAT_ATA, 			registers, data, 19,			0x10, 0x17, 0xFD, 0x30,			SCSI_DATA_READ,			srb->request_buffer, 			srb->request_bufflen, srb->use_sg, 1);		return result;	}	/*	 * Since we're requesting more data than we can handle in	 * a single read command (max is 64k-1), we will perform	 * multiple reads, but each read must be in multiples of	 * a sector.  Luckily the sector size is in srb->transfersize	 * (see linux/drivers/scsi/sr.c).	 */	if (data[7+0] == GPCMD_READ_CD) {		len = short_pack(data[7+9], data[7+8]);		len <<= 16;		len |= data[7+7];		US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);		srb->transfersize = srb->request_bufflen/len;	}	if (!srb->transfersize)  {		srb->transfersize = 2048; /* A guess */		US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",			srb->transfersize);	}	len = (65535/srb->transfersize) * srb->transfersize;	US_DEBUGP("Max read is %d bytes\n", len);	buffer = kmalloc(len, GFP_NOIO);	if (buffer == NULL) // bloody hell!		return USB_STOR_TRANSPORT_FAILED;	sector = short_pack(data[7+3], data[7+2]);	sector <<= 16;	sector |= short_pack(data[7+5], data[7+4]);	transferred = 0;	if (srb->use_sg) {		sg = (struct scatterlist *)srb->request_buffer;		sg_segment = 0; // for keeping track of where we are in		sg_offset = 0;  // the scatter/gather list	}	while (transferred != srb->request_bufflen) {		if (len > srb->request_bufflen - transferred)			len = srb->request_bufflen - transferred;		data[3] = len&0xFF; 	  // (cylL) = expected length (L)		data[4] = (len>>8)&0xFF;  // (cylH) = expected length (H)		// Fix up the SCSI command sector and num sectors		data[7+2] = MSB_of(sector>>16); // SCSI command sector		data[7+3] = LSB_of(sector>>16);		data[7+4] = MSB_of(sector&0xFFFF);		data[7+5] = LSB_of(sector&0xFFFF);		if (data[7+0] == GPCMD_READ_CD)			data[7+6] = 0;		data[7+7] = MSB_of(len / srb->transfersize); // SCSI command		data[7+8] = LSB_of(len / srb->transfersize); // num sectors		result = usbat_rw_block_test(us, USBAT_ATA, 			registers, data, 19,			0x10, 0x17, 0xFD, 0x30,			SCSI_DATA_READ,			buffer,			len, 0, 1);		if (result != USB_STOR_TRANSPORT_GOOD)			break;		// Transfer the received data into the srb buffer		if (!srb->use_sg) {			memcpy(srb->request_buffer+transferred, buffer, len);		} else {			amount = 0;			while (amount<len) {				if (len - amount >= 					  sg[sg_segment].length-sg_offset) {				  memcpy(sg[sg_segment].address + sg_offset,					buffer + amount,					sg[sg_segment].length - sg_offset);				  amount += 					  sg[sg_segment].length-sg_offset;				  sg_segment++;				  sg_offset=0;				} else {				  memcpy(sg[sg_segment].address + sg_offset,					buffer + amount,					len - amount);				  sg_offset += (len - amount);				  amount = len;				}			}		}		// Update the amount transferred and the sector number		transferred += len;		sector += len / srb->transfersize;	} // while transferred != srb->request_bufflen	kfree(buffer);	return result;}static int hp_8200e_select_and_test_registers(struct us_data *us) {	int result;	int selector;	unsigned char status;	// try device = master, then device = slave.	for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {		if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;		if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != 				USB_STOR_TRANSPORT_GOOD)			return result;	}	return result;}int init_8200e(struct us_data *us) {	int result;	unsigned char status;	// Enable peripheral control signals	if ( (result = usbat_write_user_io(us,	  USBAT_UIO_OE1 | USBAT_UIO_OE0,	  USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 1\n");	wait_ms(2000);	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 2\n");	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 3\n");	// Reset peripheral, enable periph control signals	// (bring reset signal up)	if ( (result = usbat_write_user_io(us,	  USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,	  USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 4\n");	// Enable periph control signals	// (bring reset signal down)	if ( (result = usbat_write_user_io(us,	  USBAT_UIO_OE1 | USBAT_UIO_OE0,	  USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 5\n");	wait_ms(250);	// Write 0x80 to ISA port 0x3F	if ( (result = usbat_write(us, USBAT_ISA, 0x3F, 0x80)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 6\n");	// Read ISA port 0x27	if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 7\n");	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 8\n");	if ( (result = hp_8200e_select_and_test_registers(us)) !=			 USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 9\n");	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 10\n");	// Enable periph control signals and card detect	if ( (result = usbat_write_user_io(us,	  USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,	  USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 11\n");	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 12\n");	wait_ms(1400);	if ( (result = usbat_read_user_io(us, &status)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 13\n");	if ( (result = hp_8200e_select_and_test_registers(us)) !=			 USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 14\n");	if ( (result = usbat_set_shuttle_features(us, 			0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) !=			 USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("INIT 15\n");	return result;}/* * Transport for the HP 8200e */int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us){	int result;	unsigned char status;	unsigned char registers[32];	unsigned char data[32];	unsigned int len;	int i;	char string[64];	len = srb->request_bufflen;	/* Send A0 (ATA PACKET COMMAND).	   Note: I guess we're never going to get any of the ATA	   commands... just ATA Packet Commands. 	 */	registers[0] = 0x11;	registers[1] = 0x12;	registers[2] = 0x13;	registers[3] = 0x14;	registers[4] = 0x15;	registers[5] = 0x16;	registers[6] = 0x17;	data[0] = 0x00;	data[1] = 0x00;	data[2] = 0x00;	data[3] = len&0xFF; 		// (cylL) = expected length (L)	data[4] = (len>>8)&0xFF; 	// (cylH) = expected length (H)	data[5] = 0xB0; 		// (device sel) = slave	data[6] = 0xA0; 		// (command) = ATA PACKET COMMAND	for (i=7; i<19; i++) {		registers[i] = 0x10;		data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];	}	result = usbat_read(us, USBAT_ATA, 0x17, &status);	US_DEBUGP("Status = %02X\n", status);	if (srb->cmnd[0] == TEST_UNIT_READY)		transferred = 0;	if (srb->sc_data_direction == SCSI_DATA_WRITE) {		result = usbat_rw_block_test(us, USBAT_ATA, 			registers, data, 19,			0x10, 0x17, 0xFD, 0x30,			SCSI_DATA_WRITE,			srb->request_buffer, 			len, srb->use_sg, 10);		if (result == USB_STOR_TRANSPORT_GOOD) {			transferred += len;			US_DEBUGP("Wrote %08X bytes\n", transferred);		}		return result;	} else if (srb->cmnd[0] == READ_10 ||		   srb->cmnd[0] == GPCMD_READ_CD) {		return usbat_handle_read10(us, registers, data, srb);	}	if (len > 0xFFFF) {		US_DEBUGP("Error: len = %08X... what do I do now?\n",			len);		return USB_STOR_TRANSPORT_ERROR;	}	if ( (result = usbat_multiple_write(us, 			USBAT_ATA,			registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {		return result;	}	// Write the 12-byte command header.	// If the command is BLANK then set the timer for 75 minutes.	// Otherwise set it for 10 minutes.	// NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW	// AT SPEED 4 IS UNRELIABLE!!!	if ( (result = usbat_write_block(us, 			USBAT_ATA, 0x10, srb->cmnd, 12, 0,			srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=				USB_STOR_TRANSPORT_GOOD) {		return result;	}	// If there is response data to be read in 	// then do it here.	if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {		// How many bytes to read in? Check cylL register		if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != 		    USB_STOR_TRANSPORT_GOOD) {			return result;		}		if (len>0xFF) { // need to read cylH also			len = status;			if ( (result = usbat_read(us, USBAT_ATA, 0x15,				&status)) !=				    USB_STOR_TRANSPORT_GOOD) {				return result;			}			len += ((unsigned int)status)<<8;		}		else			len = status;		result = usbat_read_block(us, USBAT_ATA, 0x10, 			srb->request_buffer, len, srb->use_sg);		/* Debug-print the first 32 bytes of the transfer */		if (!srb->use_sg) {			string[0] = 0;			for (i=0; i<len && i<32; i++) {				sprintf(string+strlen(string), "%02X ",				  ((unsigned char *)srb->request_buffer)[i]);				if ((i%16)==15) {					US_DEBUGP("%s\n", string);					string[0] = 0;				}			}			if (string[0]!=0)				US_DEBUGP("%s\n", string);		}	}	return result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -