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

📄 sddr09.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	unsigned char deviceID;	int result;	US_DEBUGP("Reading capacity...\n");	result = sddr09_read_deviceID(us,		&manufacturerID,		&deviceID);	US_DEBUGP("Result of read_deviceID is %d\n",		result);	if (result != USB_STOR_TRANSPORT_GOOD)		return 0;	US_DEBUGP("Device ID = %02X\n", deviceID);	US_DEBUGP("Manuf  ID = %02X\n", manufacturerID);	*pagesize = 512;	*blocksize = 16;	switch (deviceID) {	case 0x6e: // 1MB	case 0xe8:	case 0xec:		*pagesize = 256;		return 0x00100000;	case 0xea: // 2MB	case 0x5d: // 5d is a ROM card with pagesize 512.	case 0x64:		if (deviceID!=0x5D)			*pagesize = 256;		return 0x00200000;	case 0xe3: // 4MB	case 0xe5:	case 0x6b:	case 0xd5:		return 0x00400000;	case 0xe6: // 8MB	case 0xd6:		return 0x00800000;	case 0x73: // 16MB		*blocksize = 32;		return 0x01000000;	case 0x75: // 32MB		*blocksize = 32;		return 0x02000000;	case 0x76: // 64MB		*blocksize = 32;		return 0x04000000;	case 0x79: // 128MB		*blocksize = 32;		return 0x08000000;	default: // unknown		return 0;	}}int sddr09_read_map(struct us_data *us) {	struct scatterlist *sg;	struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);	int numblocks;	int i;	unsigned char *ptr;	unsigned short lba;	unsigned char parity;	unsigned char fast_parity[16] = {		0, 1, 1, 0, 1, 0, 0, 1,		1, 0, 0, 1, 0, 1, 1, 0	};	int result;	int alloc_len;	int alloc_blocks;	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 - 6);	// 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);	if ( (result = sddr09_read_control(us, 0, numblocks,			(unsigned char *)sg, alloc_blocks)) !=			USB_STOR_TRANSPORT_GOOD) {		for (i=0; i<alloc_blocks; i++)			kfree(sg[i].address);		kfree(sg);		return -1;	}	if (info->lba_to_pba)		kfree(info->lba_to_pba);	if (info->pba_to_lba)		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) {		if (info->lba_to_pba != NULL)			kfree(info->lba_to_pba);		if (info->pba_to_lba != NULL)			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;	}	memset(info->lba_to_pba, 0, numblocks*sizeof(int));	memset(info->pba_to_lba, 0, numblocks*sizeof(int));	// 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)	for (i=0; i<numblocks; i++) {		ptr = sg[i>>11].address+((i&0x7ff)<<6);		if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF ||		    ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) {			US_DEBUGP("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]);			continue;		}		if ((ptr[6]>>4)!=0x01) {			US_DEBUGP("PBA %04X has invalid address field %02X%02X/%02X%02X\n",			  i, ptr[6], ptr[7], ptr[11], ptr[12]);			continue;		}		/* ensure even parity */		lba = short_pack(ptr[7], ptr[6]);		parity = 1; // the parity of 0x1000		parity ^= fast_parity[lba & 0x000F];		parity ^= fast_parity[(lba>>4) & 0x000F];		parity ^= fast_parity[(lba>>8) & 0x000F];		if (parity) { /* bad parity bit */			US_DEBUGP("Bad parity in LBA for block %04X\n", i);			continue;		}		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. Yes, this wastes 24			 * physical blocks per zone. Go figure.			 */		lba += 1000*(i/0x400);		if (lba>=numblocks) {			US_DEBUGP("Bad LBA %04X for block %04X\n", lba, i);			continue;		}		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;	}	for (i=0; i<alloc_blocks; i++)		kfree(sg[i].address);	kfree(sg);	return 0;}/*static int init_sddr09(struct us_data *us) {	int result;	unsigned char data[14];	unsigned char command[8] = {		0xc1, 0x01, 0, 0, 0, 0, 0, 0	};	unsigned char command2[8] = {		0x41, 0, 0, 0, 0, 0, 0, 0	};	unsigned char tur[12] = {		0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0	};	// What the hey is all this for? Doesn't seem to	// affect the device, so we won't do device inits.	if ( (result = sddr09_send_control(us, command, data, 2)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);	command[1] = 0x08;	if ( (result = sddr09_send_control(us, command, data, 2)) !=			USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);	if ( (result = sddr09_send_control(us, command2, tur, 12)) !=			USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("SDDR09: request sense failed\n");		return result;	}	if ( (result = sddr09_raw_bulk(		us, SCSI_DATA_READ, data, 14)) !=			USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("SDDR09: request sense bulk in failed\n");		return result;	}	US_DEBUGP("SDDR09: request sense worked\n");	return result;}*/void sddr09_card_info_destructor(void *extra) {	struct sddr09_card_info *info = (struct sddr09_card_info *)extra;	if (!extra)		return;	if (info->lba_to_pba)		kfree(info->lba_to_pba);	if (info->pba_to_lba)		kfree(info->pba_to_lba);}/* * Transport for the Sandisk SDDR-09 */int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us){	int result;	int i;	char string[64];	unsigned char inquiry_response[36] = {		0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00	};	unsigned char mode_page_01[16] = { // write-protected for now		0x03, 0x00, 0x80, 0x00,		0x01, 0x0A,		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	};	unsigned char *ptr;	unsigned long capacity;	unsigned int lba;	unsigned int pba;	unsigned int page;	unsigned short pages;	struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);	if (!us->extra) {		us->extra = kmalloc(			sizeof(struct sddr09_card_info), GFP_NOIO);		if (!us->extra)			return USB_STOR_TRANSPORT_ERROR;		memset(us->extra, 0, sizeof(struct sddr09_card_info));		us->extra_destructor = sddr09_card_info_destructor;	}	ptr = (unsigned char *)srb->request_buffer;	/* 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) {		capacity = sddr09_get_capacity(us, &info->pagesize,			&info->blocksize);		if (!capacity)			return USB_STOR_TRANSPORT_FAILED;		info->capacity = capacity;		for (info->pageshift=1; 			(info->pagesize>>info->pageshift);			info->pageshift++);		info->pageshift--;		for (info->blockshift=1; 			(info->blocksize>>info->blockshift);			info->blockshift++);		info->blockshift--;		info->blockmask = (1<<info->blockshift)-1;		// Last page in the card		capacity /= info->pagesize;		capacity--;		ptr[0] = MSB_of(capacity>>16);		ptr[1] = LSB_of(capacity>>16);		ptr[2] = MSB_of(capacity&0xFFFF);		ptr[3] = LSB_of(capacity&0xFFFF);		// The 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);		sddr09_read_map(us);		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;			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;		}		// FIXME: sense buffer?		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;	}	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]);		// convert page to block and page-within-block		lba = page >> info->blockshift;		page = page & info->blockmask;		// locate physical block corresponding to logical block		if (lba >=			(info->capacity >> 				(info->pageshift + info->blockshift) ) ) {			US_DEBUGP("Error: Requested LBA %04X exceeds maximum "			  "block %04lX\n", lba,			  (info->capacity >> (info->pageshift + info->blockshift))-1);			// FIXME: sense buffer?			return USB_STOR_TRANSPORT_ERROR;		}		pba = info->lba_to_pba[lba];		// if pba is 0, either it's really 0, in which case		// the pba-to-lba map for pba 0 will be the lba,		// or that lba doesn't exist.		if (pba==0 && info->pba_to_lba[0] != lba) {			// FIXME: sense buffer?			US_DEBUGP("Error: Requested LBA %04X has no physical block "			  "mapping.\n", lba);			return USB_STOR_TRANSPORT_ERROR;		}		US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"			" pages %d\n",			pba, lba, page, pages);		return sddr09_read_data(us,			( (pba << info->blockshift) + page) << info->pageshift,			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)		return USB_STOR_TRANSPORT_ERROR; // FIXME: sense buffer?	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);	if ( (result = sddr09_send_control(us,			usb_sndctrlpipe(us->pusb_dev,0),			0,			0x41,			0,			0,			srb->cmnd,			12)) != USB_STOR_TRANSPORT_GOOD)		return result;	US_DEBUGP("SDDR09: Control for command OK\n");	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 + -