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

📄 sddr09.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	command[0] = 0xE9;	command[1] = LUNBITS;	command[2] = MSB_of(Waddress>>16);	command[3] = LSB_of(Waddress>>16);	command[4] = MSB_of(Waddress & 0xFFFF);	command[5] = LSB_of(Waddress & 0xFFFF);	command[6] = MSB_of(Eaddress>>16);	command[7] = LSB_of(Eaddress>>16);	command[8] = MSB_of(Eaddress & 0xFFFF);	command[9] = LSB_of(Eaddress & 0xFFFF);	command[10] = MSB_of(nr_of_pages);	command[11] = LSB_of(nr_of_pages);	result = sddr09_send_scsi_command(us, command, 12);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("Result for send_control in sddr09_writeX %d\n",			  result);		return result;	}	result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,				       buf, bulklen, use_sg, NULL);	if (result != USB_STOR_XFER_GOOD) {		US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",			  result);		return USB_STOR_TRANSPORT_ERROR;	}	return USB_STOR_TRANSPORT_GOOD;}/* erase address, write same address */static intsddr09_write_inplace(struct us_data *us, unsigned long address,		     int nr_of_pages, int pageshift, unsigned char *buf,		     int use_sg) {	int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT);	return sddr09_writeX(us, address, address, nr_of_pages, bulklen,			     buf, use_sg);}#if 0/* * Read Scatter Gather Command: 3+4n bytes. * byte 0: opcode E7 * byte 2: n * bytes 4i-1,4i,4i+1: page address * byte 4i+2: page count * (i=1..n) * * This reads several pages from the card to a single memory buffer. * The last two bits of byte 1 have the same meaning as for E8. */static intsddr09_read_sg_test_only(struct us_data *us) {	unsigned char *command = us->iobuf;	int result, bulklen, nsg, ct;	unsigned char *buf;	unsigned long address;	nsg = bulklen = 0;	command[0] = 0xE7;	command[1] = LUNBITS;	command[2] = 0;	address = 040000; ct = 1;	nsg++;	bulklen += (ct << 9);	command[4*nsg+2] = ct;	command[4*nsg+1] = ((address >> 9) & 0xFF);	command[4*nsg+0] = ((address >> 17) & 0xFF);	command[4*nsg-1] = ((address >> 25) & 0xFF);	address = 0340000; ct = 1;	nsg++;	bulklen += (ct << 9);	command[4*nsg+2] = ct;	command[4*nsg+1] = ((address >> 9) & 0xFF);	command[4*nsg+0] = ((address >> 17) & 0xFF);	command[4*nsg-1] = ((address >> 25) & 0xFF);	address = 01000000; ct = 2;	nsg++;	bulklen += (ct << 9);	command[4*nsg+2] = ct;	command[4*nsg+1] = ((address >> 9) & 0xFF);	command[4*nsg+0] = ((address >> 17) & 0xFF);	command[4*nsg-1] = ((address >> 25) & 0xFF);	command[2] = nsg;	result = sddr09_send_scsi_command(us, command, 4*nsg+3);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",			  result);		return result;	}	buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);	if (!buf)		return USB_STOR_TRANSPORT_ERROR;	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,				       buf, bulklen, NULL);	kfree(buf);	if (result != USB_STOR_XFER_GOOD) {		US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",			  result);		return USB_STOR_TRANSPORT_ERROR;	}	return USB_STOR_TRANSPORT_GOOD;}#endif/* * Read Status Command: 12 bytes. * byte 0: opcode: EC * * Returns 64 bytes, all zero except for the first. * bit 0: 1: Error * bit 5: 1: Suspended * bit 6: 1: Ready * bit 7: 1: Not write-protected */static intsddr09_read_status(struct us_data *us, unsigned char *status) {	unsigned char *command = us->iobuf;	unsigned char *data = us->iobuf;	int result;	US_DEBUGP("Reading status...\n");	memset(command, 0, 12);	command[0] = 0xEC;	command[1] = LUNBITS;	result = sddr09_send_scsi_command(us, command, 12);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,				       data, 64, NULL);	*status = data[0];	return (result == USB_STOR_XFER_GOOD ?			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);}static intsddr09_read_data(struct us_data *us,		 unsigned long address,		 unsigned int sectors) {	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;	unsigned char *buffer;	unsigned int lba, maxlba, pba;	unsigned int page, pages;	unsigned int len, index, offset;	int result;	// Since we only read in one block at a time, we have to create	// a bounce buffer and move the data a piece at a time between the	// bounce buffer and the actual transfer buffer.	len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;	buffer = kmalloc(len, GFP_NOIO);	if (buffer == NULL) {		printk("sddr09_read_data: Out of memory\n");		return USB_STOR_TRANSPORT_ERROR;	}	// Figure out the initial LBA and page	lba = address >> info->blockshift;	page = (address & info->blockmask);	maxlba = info->capacity >> (info->pageshift + info->blockshift);	// This could be made much more efficient by checking for	// contiguous LBA's. Another exercise left to the student.	result = USB_STOR_TRANSPORT_GOOD;	index = offset = 0;	while (sectors > 0) {		/* Find number of pages we can read in this block */		pages = min(sectors, info->blocksize - page);		len = pages << info->pageshift;		/* Not overflowing capacity? */		if (lba >= maxlba) {			US_DEBUGP("Error: Requested lba %u exceeds "				  "maximum %u\n", lba, maxlba);			result = USB_STOR_TRANSPORT_ERROR;			break;		}		/* Find where this lba lives on disk */		pba = info->lba_to_pba[lba];		if (pba == UNDEF) {	/* this lba was never written */			US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",				  pages, lba, page);			/* This is not really an error. It just means			   that the block has never been written.			   Instead of returning USB_STOR_TRANSPORT_ERROR			   it is better to return all zero data. */			memset(buffer, 0, len);		} else {			US_DEBUGP("Read %d pages, from PBA %d"				  " (LBA %d) page %d\n",				  pages, pba, lba, page);			address = ((pba << info->blockshift) + page) << 				info->pageshift;			result = sddr09_read20(us, address>>1,					pages, info->pageshift, buffer, 0);			if (result != USB_STOR_TRANSPORT_GOOD)				break;		}		// Store the data in the transfer buffer		usb_stor_access_xfer_buf(buffer, len, us->srb,				&index, &offset, TO_XFER_BUF);		page = 0;		lba++;		sectors -= pages;	}	kfree(buffer);	return result;}static unsigned intsddr09_find_unused_pba(struct sddr09_card_info *info, unsigned int lba) {	static unsigned int lastpba = 1;	int zonestart, end, i;	zonestart = (lba/1000) << 10;	end = info->capacity >> (info->blockshift + info->pageshift);	end -= zonestart;	if (end > 1024)		end = 1024;	for (i = lastpba+1; i < end; i++) {		if (info->pba_to_lba[zonestart+i] == UNDEF) {			lastpba = i;			return zonestart+i;		}	}	for (i = 0; i <= lastpba; i++) {		if (info->pba_to_lba[zonestart+i] == UNDEF) {			lastpba = i;			return zonestart+i;		}	}	return 0;}static intsddr09_write_lba(struct us_data *us, unsigned int lba,		 unsigned int page, unsigned int pages,		 unsigned char *ptr, unsigned char *blockbuffer) {	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;	unsigned long address;	unsigned int pba, lbap;	unsigned int pagelen;	unsigned char *bptr, *cptr, *xptr;	unsigned char ecc[3];	int i, result, isnew;	lbap = ((lba % 1000) << 1) | 0x1000;	if (parity[MSB_of(lbap) ^ LSB_of(lbap)])		lbap ^= 1;	pba = info->lba_to_pba[lba];	isnew = 0;	if (pba == UNDEF) {		pba = sddr09_find_unused_pba(info, lba);		if (!pba) {			printk("sddr09_write_lba: Out of unused blocks\n");			return USB_STOR_TRANSPORT_ERROR;		}		info->pba_to_lba[pba] = lba;		info->lba_to_pba[lba] = pba;		isnew = 1;	}	if (pba == 1) {		/* Maybe it is impossible to write to PBA 1.		   Fake success, but don't do anything. */		printk("sddr09: avoid writing to pba 1\n");		return USB_STOR_TRANSPORT_GOOD;	}	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);	/* read old contents */	address = (pba << (info->pageshift + info->blockshift));	result = sddr09_read22(us, address>>1, info->blocksize,			       info->pageshift, blockbuffer, 0);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	/* check old contents and fill lba */	for (i = 0; i < info->blocksize; i++) {		bptr = blockbuffer + i*pagelen;		cptr = bptr + info->pagesize;		nand_compute_ecc(bptr, ecc);		if (!nand_compare_ecc(cptr+13, ecc)) {			US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",				  i, pba);			nand_store_ecc(cptr+13, ecc);		}		nand_compute_ecc(bptr+(info->pagesize / 2), ecc);		if (!nand_compare_ecc(cptr+8, ecc)) {			US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",				  i, pba);			nand_store_ecc(cptr+8, ecc);		}		cptr[6] = cptr[11] = MSB_of(lbap);		cptr[7] = cptr[12] = LSB_of(lbap);	}	/* copy in new stuff and compute ECC */	xptr = ptr;	for (i = page; i < page+pages; i++) {		bptr = blockbuffer + i*pagelen;		cptr = bptr + info->pagesize;		memcpy(bptr, xptr, info->pagesize);		xptr += info->pagesize;		nand_compute_ecc(bptr, ecc);		nand_store_ecc(cptr+13, ecc);		nand_compute_ecc(bptr+(info->pagesize / 2), ecc);		nand_store_ecc(cptr+8, ecc);	}	US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba);	result = sddr09_write_inplace(us, address>>1, info->blocksize,				      info->pageshift, blockbuffer, 0);	US_DEBUGP("sddr09_write_inplace returns %d\n", result);#if 0	{		unsigned char status = 0;		int result2 = sddr09_read_status(us, &status);		if (result2 != USB_STOR_TRANSPORT_GOOD)			US_DEBUGP("sddr09_write_inplace: cannot read status\n");		else if (status != 0xc0)			US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",				  status);	}#endif#if 0	{		int result2 = sddr09_test_unit_ready(us);	}#endif	return result;}static intsddr09_write_data(struct us_data *us,		  unsigned long address,		  unsigned int sectors) {	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;	unsigned int lba, page, pages;	unsigned int pagelen, blocklen;	unsigned char *blockbuffer;	unsigned char *buffer;	unsigned int len, index, offset;	int result;	// blockbuffer is used for reading in the old data, overwriting	// with the new data, and performing ECC calculations	/* TODO: instead of doing kmalloc/kfree for each write,	   add a bufferpointer to the info structure */	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);	blocklen = (pagelen << info->blockshift);	blockbuffer = kmalloc(blocklen, GFP_NOIO);	if (!blockbuffer) {		printk("sddr09_write_data: Out of memory\n");		return USB_STOR_TRANSPORT_ERROR;	}	// Since we don't write the user data directly to the device,	// we have to create a bounce buffer and move the data a piece	// at a time between the bounce buffer and the actual transfer buffer.	len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;	buffer = kmalloc(len, GFP_NOIO);	if (buffer == NULL) {		printk("sddr09_write_data: Out of memory\n");		kfree(blockbuffer);		return USB_STOR_TRANSPORT_ERROR;	}	// Figure out the initial LBA and page	lba = address >> info->blockshift;	page = (address & info->blockmask);	result = USB_STOR_TRANSPORT_GOOD;	index = offset = 0;	while (sectors > 0) {		// Write as many sectors as possible in this block		pages = min(sectors, info->blocksize - page);		len = (pages << info->pageshift);		// Get the data from the transfer buffer		usb_stor_access_xfer_buf(buffer, len, us->srb,				&index, &offset, FROM_XFER_BUF);		result = sddr09_write_lba(us, lba, page, pages,				buffer, blockbuffer);		if (result != USB_STOR_TRANSPORT_GOOD)			break;		page = 0;		lba++;		sectors -= pages;	}	kfree(buffer);	kfree(blockbuffer);	return result;}static intsddr09_read_control(struct us_data *us,		unsigned long address,		unsigned int blocks,		unsigned char *content,		int use_sg) {	US_DEBUGP("Read control address %lu, blocks %d\n",		address, blocks);	return sddr09_read21(us, address, blocks,			     CONTROL_SHIFT, content, use_sg);}/* * Read Device ID Command: 12 bytes. * byte 0: opcode: ED * * Returns 2 bytes: Manufacturer ID and Device ID. * On more recent cards 3 bytes: the third byte is an option code A5 * signifying that the secret command to read an 128-bit ID is available. * On still more recent cards 4 bytes: the fourth byte C0 means that * a second read ID cmd is available. */static intsddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {	unsigned char *command = us->iobuf;	unsigned char *content = us->iobuf;	int result, i;	memset(command, 0, 12);	command[0] = 0xED;	command[1] = LUNBITS;	result = sddr09_send_scsi_command(us, command, 12);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,			content, 64, NULL);	for (i = 0; i < 4; i++)		deviceID[i] = content[i];	return (result == USB_STOR_XFER_GOOD ?			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);}static intsddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {	int result;	unsigned char status;	result = sddr09_read_status(us, &status);	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("sddr09_get_wp: read_status fails\n");		return result;	}	US_DEBUGP("sddr09_get_wp: status 0x%02X", status);	if ((status & 0x80) == 0) {		info->flags |= SDDR09_WP;	/* write protected */		US_DEBUGP(" WP");	}	if (status & 0x40)		US_DEBUGP(" Ready");	if (status & LUNBITS)		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 = us->iobuf;	memset(command, 0, 12);	command[0] = 0xEB;	command[1] = LUNBITS;

⌨️ 快捷键说明

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