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

📄 sddr09.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return sddr09_send_scsi_command(us, command, 12);}#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 NULL;	}	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 sddr09_card_info *info = (struct sddr09_card_info *) us->extra;	int numblocks, alloc_len, alloc_blocks;	int i, j, result;	unsigned char *buffer, *buffer_end, *ptr;	unsigned int lba, lbact;	if (!info->capacity)		return -1;	// size of a block is 1 << (blockshift + pageshift) bytes	// divide into the total capacity to get the number of blocks	numblocks = info->capacity >> (info->blockshift + info->pageshift);	// read 64 bytes for every block (actually 1 << CONTROL_SHIFT)	// but only use a 64 KB buffer	// buffer size used must be a multiple of (1 << CONTROL_SHIFT)#define SDDR09_READ_MAP_BUFSZ 65536	alloc_blocks = min(numblocks, SDDR09_READ_MAP_BUFSZ >> CONTROL_SHIFT);	alloc_len = (alloc_blocks << CONTROL_SHIFT);	buffer = kmalloc(alloc_len, GFP_NOIO);	if (buffer == NULL) {		printk("sddr09_read_map: out of memory\n");		result = -1;		goto done;	}	buffer_end = buffer + alloc_len;#undef SDDR09_READ_MAP_BUFSZ	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) {		printk("sddr09_read_map: out of memory\n");		result = -1;		goto done;	}	for (i = 0; i < numblocks; i++)		info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;	/*	 * Define lba-pba translation table	 */	ptr = buffer_end;	for (i = 0; i < numblocks; i++) {		ptr += (1 << CONTROL_SHIFT);		if (ptr >= buffer_end) {			unsigned long address;			address = i << (info->pageshift + info->blockshift);			result = sddr09_read_control(				us, address>>1,				min(alloc_blocks, numblocks - i),				buffer, 0);			if (result != USB_STOR_TRANSPORT_GOOD) {				result = -1;				goto done;			}			ptr = buffer;		}		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 %d 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 %d 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 %d 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 %d"			       " (%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 low LBA %d for block %d\n",			       lba, i);			goto possibly_erase;		}		lba += 1000*(i/0x400);		if (info->lba_to_pba[lba] != UNDEF) {			printk("sddr09: LBA %d seen for PBA %d and %d\n",			       lba, info->lba_to_pba[lba], i);			goto possibly_erase;		}		info->pba_to_lba[i] = lba;		info->lba_to_pba[lba] = i;		continue;	possibly_erase:		if (erase_bad_lba_entries) {			unsigned long address;			address = (i << (info->pageshift + info->blockshift));			sddr09_erase(us, address>>1);			info->pba_to_lba[i] = UNDEF;		} else			info->pba_to_lba[i] = UNUSABLE;	}	/*	 * 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);	result = 0; done:	if (result != 0) {		kfree(info->lba_to_pba);		kfree(info->pba_to_lba);		info->lba_to_pba = NULL;		info->pba_to_lba = NULL;	}	kfree(buffer);	return result;}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;		}	}}/* * This is needed at a very early stage. If this is not listed in the * unusual devices list but called from here then LUN 0 of the combo reader * is not recognized. But I do not know what precisely these calls do. */intsddr09_init(struct us_data *us) {	int result;	unsigned char *data = us->iobuf;	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	result = sddr09_request_sense(us, data, 18);	if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {		int j;		for (j=0; j<18; 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		// Or: 70 00 06 00 00 00 00 0b 00 00 00 00 28 00 00 00 00 00		// sense key 06, sense code 28: unit attention,		// not ready to ready transition	}	// test unit ready	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 sensekey = 0, sensecode = 0;	static unsigned char havefakesense = 0;	int result, i;	unsigned char *ptr = us->iobuf;	unsigned long capacity;	unsigned int page, pages;	struct sddr09_card_info *info;	static unsigned char inquiry_response[8] = {		0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00	};	/* note: no block descriptor support */	static unsigned char mode_page_01[19] = {		0x00, 0x0F, 0x00, 0x0, 0x0, 0x0, 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;	}	if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {		/* for a faked command, we have to follow with a faked sense */		memset(ptr, 0, 18);		ptr[0] = 0x70;		ptr[2] = sensekey;		ptr[7] = 11;		ptr[12] = sensecode;		usb_stor_set_xfer_buf(ptr, 18, srb);		sensekey = sensecode = havefakesense = 0;		return USB_STOR_TRANSPORT_GOOD;	}	havefakesense = 1;	/* Dummy up a response for INQUIRY since SDDR09 doesn't	   respond to INQUIRY commands */	if (srb->cmnd[0] == INQUIRY) {		memcpy(ptr, inquiry_response, 8);		fill_inquiry_response(us, ptr, 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) {			/* probably no media */		init_error:			sensekey = 0x02;	/* not ready */			sensecode = 0x3a;	/* medium not present */			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()		if (sddr09_read_map(us)) {			/* probably out of memory */			goto init_error;		}		// Report capacity		capacity = (info->lbact << info->blockshift) - 1;		((u32 *) ptr)[0] = cpu_to_be32(capacity);		// Report page size		((u32 *) ptr)[1] = cpu_to_be32(info->pagesize);		usb_stor_set_xfer_buf(ptr, 8, srb);		return USB_STOR_TRANSPORT_GOOD;	}	if (srb->cmnd[0] == MODE_SENSE_10) {		int modepage = (srb->cmnd[2] & 0x3F);		/* They ask for the Read/Write error recovery page,		   or for all pages. */		/* %% We should check DBD %% */		if (modepage == 0x01 || modepage == 0x3F) {			US_DEBUGP("SDDR09: Dummy up request for "				  "mode page 0x%x\n", modepage);			memcpy(ptr, mode_page_01, sizeof(mode_page_01));			((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);			ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0;			usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);			return USB_STOR_TRANSPORT_GOOD;		}		sensekey = 0x05;	/* illegal request */		sensecode = 0x24;	/* invalid field in CDB */		return USB_STOR_TRANSPORT_FAILED;	}	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL)		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);	}	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);	}	/* catch-all for all other commands, except	 * pass TEST_UNIT_READY and REQUEST_SENSE through	 */	if (srb->cmnd[0] != TEST_UNIT_READY &&	    srb->cmnd[0] != REQUEST_SENSE) {		sensekey = 0x05;	/* illegal request */		sensecode = 0x20;	/* invalid command */		havefakesense = 1;		return USB_STOR_TRANSPORT_FAILED;	}	for (; srb->cmd_len<12; srb->cmd_len++)		srb->cmnd[srb->cmd_len] = 0;	srb->cmnd[1] = LUNBITS;	ptr[0] = 0;	for (i=0; i<12; i++)		sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]);	US_DEBUGP("SDDR09: Send control for command %s\n", ptr);	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) {		unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE)				? us->send_bulk_pipe : us->recv_bulk_pipe;		US_DEBUGP("SDDR09: %s %d bytes\n",			  (srb->sc_data_direction == SCSI_DATA_WRITE) ?			  "sending" : "receiving",			  srb->request_bufflen);		result = usb_stor_bulk_transfer_sg(us, pipe,					srb->request_buffer,					srb->request_bufflen,					srb->use_sg, &srb->resid);		return (result == USB_STOR_XFER_GOOD ?			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);	} 	return USB_STOR_TRANSPORT_GOOD;}

⌨️ 快捷键说明

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