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

📄 sddr09.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	if (status & 0x40)		US_DEBUGP(" Ready");	if (status & 0x20)		US_DEBUGP(" Suspended");	if (status & 0x1)		US_DEBUGP(" Error");	US_DEBUGP("\n");	return USB_STOR_TRANSPORT_GOOD;}#if 0/* * Reset Command: 12 bytes. * byte 0: opcode: EB */static intsddr09_reset(struct us_data *us) {	unsigned char command[12] = {		0xeb, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0	};	return sddr09_send_scsi_command(us, command, sizeof(command));}#endifstatic struct nand_flash_dev *sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {	struct nand_flash_dev *cardinfo;	unsigned char deviceID[4];	char blurbtxt[256];	int result;	US_DEBUGP("Reading capacity...\n");	result = sddr09_read_deviceID(us, deviceID);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("Result of read_deviceID is %d\n", result);		printk("sddr09: could not read card info\n");		return 0;	}	sprintf(blurbtxt, "sddr09: Found Flash card, ID = %02X %02X %02X %02X",		deviceID[0], deviceID[1], deviceID[2], deviceID[3]);	/* Byte 0 is the manufacturer */	sprintf(blurbtxt + strlen(blurbtxt),		": Manuf. %s",		nand_flash_manufacturer(deviceID[0]));	/* Byte 1 is the device type */	cardinfo = nand_find_id(deviceID[1]);	if (cardinfo) {		/* MB or MiB? It is neither. A 16 MB card has		   17301504 raw bytes, of which 16384000 are		   usable for user data. */		sprintf(blurbtxt + strlen(blurbtxt),			", %d MB", 1<<(cardinfo->chipshift - 20));	} else {		sprintf(blurbtxt + strlen(blurbtxt),			", type unrecognized");	}	/* Byte 2 is code to signal availability of 128-bit ID */	if (deviceID[2] == 0xa5) {		sprintf(blurbtxt + strlen(blurbtxt),			", 128-bit ID");	}	/* Byte 3 announces the availability of another read ID command */	if (deviceID[3] == 0xc0) {		sprintf(blurbtxt + strlen(blurbtxt),			", extra cmd");	}	if (flags & SDDR09_WP)		sprintf(blurbtxt + strlen(blurbtxt),			", WP");	printk("%s\n", blurbtxt);	return cardinfo;}static intsddr09_read_map(struct us_data *us) {	struct scatterlist *sg;	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;	int numblocks, alloc_len, alloc_blocks;	int i, j, result;	unsigned char *ptr;	unsigned int lba, lbact;	if (!info->capacity)		return -1;	// read 64 (1<<6) bytes for every block 	// ( 1 << ( blockshift + pageshift ) bytes)	//	 of capacity:	// (1<<6)*capacity/(1<<(b+p)) =	// ((1<<6)*capacity)>>(b+p) =	// capacity>>(b+p-6)	alloc_len = info->capacity >> 		(info->blockshift + info->pageshift - CONTROL_SHIFT);	// Allocate a number of scatterlist structures according to	// the number of 128k blocks in the alloc_len. Adding 128k-1	// and then dividing by 128k gives the correct number of blocks.	// 128k = 1<<17	alloc_blocks = (alloc_len + (1<<17) - 1) >> 17;	sg = kmalloc(alloc_blocks*sizeof(struct scatterlist),		     GFP_NOIO);	if (sg == NULL)		return 0;	for (i=0; i<alloc_blocks; i++) {		if (i<alloc_blocks-1) {			sg[i].address = kmalloc( (1<<17), GFP_NOIO );			sg[i].page = NULL;			sg[i].length = (1<<17);		} else {			sg[i].address = kmalloc(alloc_len, GFP_NOIO);			sg[i].page = NULL;			sg[i].length = alloc_len;		}		alloc_len -= sg[i].length;	}	for (i=0; i<alloc_blocks; i++)		if (sg[i].address == NULL) {			for (i=0; i<alloc_blocks; i++)				if (sg[i].address != NULL)					kfree(sg[i].address);			kfree(sg);			return 0;		}	numblocks = info->capacity >> (info->blockshift + info->pageshift);	result = sddr09_read_control(us, 0, numblocks,				     (unsigned char *)sg, alloc_blocks);	if (result != USB_STOR_TRANSPORT_GOOD) {		for (i=0; i<alloc_blocks; i++)			kfree(sg[i].address);		kfree(sg);		return -1;	}	kfree(info->lba_to_pba);	kfree(info->pba_to_lba);	info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO);	info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);	if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {		kfree(info->lba_to_pba);		kfree(info->pba_to_lba);		info->lba_to_pba = NULL;		info->pba_to_lba = NULL;		for (i=0; i<alloc_blocks; i++)			kfree(sg[i].address);		kfree(sg);		return 0;	}	for (i = 0; i < numblocks; i++)		info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;	ptr = sg[0].address;	/*	 * Define lba-pba translation table	 */	// Each block is 64 bytes of control data, so block i is located in	// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)#if 0	/* No translation */	for (i=0; i<numblocks; i++) {		lba = i;		info->pba_to_lba[i] = lba;		info->lba_to_pba[lba] = i;	}	printk("sddr09: no translation today\n");#else	for (i=0; i<numblocks; i++) {		ptr = sg[i>>11].address + ((i&0x7ff)<<6);		if (i == 0 || i == 1) {			info->pba_to_lba[i] = UNUSABLE;			continue;		}		/* special PBAs have control field 0^16 */		for (j = 0; j < 16; j++)			if (ptr[j] != 0)				goto nonz;		info->pba_to_lba[i] = UNUSABLE;		printk("sddr09: PBA %04X has no logical mapping\n", i);		continue;	nonz:		/* unwritten PBAs have control field FF^16 */		for (j = 0; j < 16; j++)			if (ptr[j] != 0xff)				goto nonff;		continue;	nonff:		/* normal PBAs start with six FFs */		if (j < 6) {			printk("sddr09: PBA %04X has no logical mapping: "			       "reserved area = %02X%02X%02X%02X "			       "data status %02X block status %02X\n",			       i, ptr[0], ptr[1], ptr[2], ptr[3],			       ptr[4], ptr[5]);			info->pba_to_lba[i] = UNUSABLE;			continue;		}		if ((ptr[6] >> 4) != 0x01) {			printk("sddr09: PBA %04X has invalid address field "			       "%02X%02X/%02X%02X\n",			       i, ptr[6], ptr[7], ptr[11], ptr[12]);			info->pba_to_lba[i] = UNUSABLE;			continue;		}		/* check even parity */		if (parity[ptr[6] ^ ptr[7]]) {			printk("sddr09: Bad parity in LBA for block %04X"			       " (%02X %02X)\n", i, ptr[6], ptr[7]);			info->pba_to_lba[i] = UNUSABLE;			continue;		}		lba = short_pack(ptr[7], ptr[6]);		lba = (lba & 0x07FF) >> 1;		/*		 * Every 1024 physical blocks ("zone"), the LBA numbers		 * go back to zero, but are within a higher block of LBA's.		 * Also, there is a maximum of 1000 LBA's per zone.		 * In other words, in PBA 1024-2047 you will find LBA 0-999		 * which are really LBA 1000-1999. This allows for 24 bad		 * or special physical blocks per zone.		 */		if (lba >= 1000) {			printk("sddr09: Bad LBA %04X for block %04X\n",			       lba, i);			info->pba_to_lba[i] = UNDEF /* UNUSABLE */;			continue;		}		lba += 1000*(i/0x400);		if (lba<0x10 || (lba >= 0x3E0 && lba < 0x3EF))			US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);		info->pba_to_lba[i] = lba;		info->lba_to_pba[lba] = i;	}#endif	/*	 * Approximate capacity. This is not entirely correct yet,	 * since a zone with less than 1000 usable pages leads to	 * missing LBAs. Especially if it is the last zone, some	 * LBAs can be past capacity.	 */	lbact = 0;	for (i = 0; i < numblocks; i += 1024) {		int ct = 0;		for (j = 0; j < 1024 && i+j < numblocks; j++) {			if (info->pba_to_lba[i+j] != UNUSABLE) {				if (ct >= 1000)					info->pba_to_lba[i+j] = SPARE;				else					ct++;			}		}		lbact += ct;	}	info->lbact = lbact;	US_DEBUGP("Found %d LBA's\n", lbact);	for (i=0; i<alloc_blocks; i++)		kfree(sg[i].address);	kfree(sg);	return 0;}static voidsddr09_card_info_destructor(void *extra) {	struct sddr09_card_info *info = (struct sddr09_card_info *)extra;	if (!info)		return;	kfree(info->lba_to_pba);	kfree(info->pba_to_lba);}static voidsddr09_init_card_info(struct us_data *us) {	if (!us->extra) {		us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO);		if (us->extra) {			memset(us->extra, 0, sizeof(struct sddr09_card_info));			us->extra_destructor = sddr09_card_info_destructor;		}	}}/* * It is unclear whether this does anything. * However, the request sense succeeds only after a reboot, * not if we do this a second time. */intsddr09_init(struct us_data *us) {#if 0	int result;	unsigned char data[2];	printk("sddr09_init\n");	nand_init_ecc();	result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("sddr09_init: send_command fails\n");		return result;	}	US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);	// get 07 02	result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("sddr09_init: 2nd send_command fails\n");		return result;	}	US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);	// get 07 00#if 1	result = sddr09_request_sense(us, data, sizeof(data));	if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {		int j;		for (j=0; j<sizeof(data); j++)			printk(" %02X", data[j]);		printk("\n");		// get 70 00 00 00 00 00 00 * 00 00 00 00 00 00		// 70: current command		// sense key 0, sense code 0, extd sense code 0		// additional transfer length * = sizeof(data) - 7	}#endif#endif	return USB_STOR_TRANSPORT_GOOD;		/* not result */}/* * Transport for the Sandisk SDDR-09 */int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us){	static unsigned char sense = 0;	static unsigned char havefakesense = 0;	int result, i;	unsigned char *ptr;	unsigned long capacity;	unsigned int page, pages;	char string[64];	struct sddr09_card_info *info;	unsigned char inquiry_response[36] = {		0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00	};	unsigned char mode_page_01[16] = {		0x0F, 0x00, 0, 0x00,		0x01, 0x0A,		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	};	info = (struct sddr09_card_info *)us->extra;	if (!info) {		nand_init_ecc();		sddr09_init_card_info(us);		info = (struct sddr09_card_info *)us->extra;		if (!info)			return USB_STOR_TRANSPORT_ERROR;	}	ptr = (unsigned char *)srb->request_buffer;	if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {		/* for a faked command, we have to follow with a faked sense */		memset(ptr, 0, srb->request_bufflen);		if (srb->request_bufflen > 7) {			ptr[0] = 0x70;			ptr[2] = sense;			ptr[7] = srb->request_bufflen - 7;		}		sense = havefakesense = 0;		return USB_STOR_TRANSPORT_GOOD;	}	sense = 0;	havefakesense = 1;	/* Dummy up a response for INQUIRY since SDDR09 doesn't	   respond to INQUIRY commands */	if (srb->cmnd[0] == INQUIRY) {		memset(inquiry_response+8, 0, 28);		fill_inquiry_response(us, inquiry_response, 36);		return USB_STOR_TRANSPORT_GOOD;	}	if (srb->cmnd[0] == READ_CAPACITY) {		struct nand_flash_dev *cardinfo;		sddr09_get_wp(us, info);	/* read WP bit */		cardinfo = sddr09_get_cardinfo(us, info->flags);		if (!cardinfo)			return USB_STOR_TRANSPORT_FAILED;		info->capacity = (1 << cardinfo->chipshift);		info->pageshift = cardinfo->pageshift;		info->pagesize = (1 << info->pageshift);		info->blockshift = cardinfo->blockshift;		info->blocksize = (1 << info->blockshift);		info->blockmask = info->blocksize - 1;		// map initialization, must follow get_cardinfo()		sddr09_read_map(us);		// Report capacity		capacity = (info->lbact << info->blockshift) - 1;		ptr[0] = MSB_of(capacity>>16);		ptr[1] = LSB_of(capacity>>16);		ptr[2] = MSB_of(capacity&0xFFFF);		ptr[3] = LSB_of(capacity&0xFFFF);		// Report page size		ptr[4] = MSB_of(info->pagesize>>16);		ptr[5] = LSB_of(info->pagesize>>16);		ptr[6] = MSB_of(info->pagesize&0xFFFF);		ptr[7] = LSB_of(info->pagesize&0xFFFF);		return USB_STOR_TRANSPORT_GOOD;	}	if (srb->cmnd[0] == MODE_SENSE) {		// Read-write error recovery page: there needs to		// be a check for write-protect here		if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {			US_DEBUGP(				"SDDR09: Dummy up request for mode page 1\n");			if (ptr == NULL || 			    srb->request_bufflen<sizeof(mode_page_01))				return USB_STOR_TRANSPORT_ERROR;			mode_page_01[0] = sizeof(mode_page_01) - 1;			mode_page_01[2] = (info->flags & SDDR09_WP) ? 0x80 : 0;			memcpy(ptr, mode_page_01, sizeof(mode_page_01));			return USB_STOR_TRANSPORT_GOOD;		} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {			US_DEBUGP("SDDR09: Dummy up request for "				  "all mode pages\n");			if (ptr == NULL || 			    srb->request_bufflen<sizeof(mode_page_01))				return USB_STOR_TRANSPORT_ERROR;			memcpy(ptr, mode_page_01, sizeof(mode_page_01));			return USB_STOR_TRANSPORT_GOOD;		}		return USB_STOR_TRANSPORT_ERROR;	}	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {		US_DEBUGP(			"SDDR09: %s medium removal. Not that I can do"			" anything about it...\n",			(srb->cmnd[4]&0x03) ? "Prevent" : "Allow");		return USB_STOR_TRANSPORT_GOOD;	}	havefakesense = 0;	if (srb->cmnd[0] == READ_10) {		page = short_pack(srb->cmnd[3], srb->cmnd[2]);		page <<= 16;		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);		US_DEBUGP("READ_10: read page %d pagect %d\n",			  page, pages);		return sddr09_read_data(us, page, pages, ptr, srb->use_sg);	}	if (srb->cmnd[0] == WRITE_10) {		page = short_pack(srb->cmnd[3], srb->cmnd[2]);		page <<= 16;		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);		US_DEBUGP("WRITE_10: write page %d pagect %d\n",			  page, pages);		return sddr09_write_data(us, page, pages, ptr, srb->use_sg);	}	// Pass TEST_UNIT_READY and REQUEST_SENSE through	if (srb->cmnd[0] != TEST_UNIT_READY &&	    srb->cmnd[0] != REQUEST_SENSE) {		havefakesense = 1;		return USB_STOR_TRANSPORT_ERROR;	}	for (; srb->cmd_len<12; srb->cmd_len++)		srb->cmnd[srb->cmd_len] = 0;	srb->cmnd[1] = 0x20;	string[0] = 0;	for (i=0; i<12; i++)		sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);	US_DEBUGP("SDDR09: Send control for command %s\n",		  string);	result = sddr09_send_scsi_command(us, srb->cmnd, 12);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "			  "returns %d\n", result);		return result;	}	if (srb->request_bufflen == 0)		return USB_STOR_TRANSPORT_GOOD;	if (srb->sc_data_direction == SCSI_DATA_WRITE ||	    srb->sc_data_direction == SCSI_DATA_READ) {		US_DEBUGP("SDDR09: %s %d bytes\n",			  (srb->sc_data_direction == SCSI_DATA_WRITE) ?			  "sending" : "receiving",			  srb->request_bufflen);		result = sddr09_bulk_transport(us,					       srb->sc_data_direction,					       srb->request_buffer, 					       srb->request_bufflen,					       srb->use_sg);		return result;	} 	return USB_STOR_TRANSPORT_GOOD;}

⌨️ 快捷键说明

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