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

📄 sddr55.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 leave:	kfree(buffer);	return result;}static int sddr55_read_deviceID(struct us_data *us,		unsigned char *manufacturerID,		unsigned char *deviceID) {	int result;	unsigned char *command = us->iobuf;	unsigned char *content = us->iobuf;	memset(command, 0, 8);	command[5] = 0xB0;	command[7] = 0x84;	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);	US_DEBUGP("Result of send_control for device ID is %d\n",		result);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	result = sddr55_bulk_transport(us,		SCSI_DATA_READ, content, 4);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	*manufacturerID = content[0];	*deviceID = content[1];	if (content[0] != 0xff)	{    		result = sddr55_bulk_transport(us,			SCSI_DATA_READ, content, 2);	}	return USB_STOR_TRANSPORT_GOOD;}int sddr55_reset(struct us_data *us) {	return 0;}static unsigned long sddr55_get_capacity(struct us_data *us) {	unsigned char manufacturerID;	unsigned char deviceID;	int result;	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;	US_DEBUGP("Reading capacity...\n");	result = sddr55_read_deviceID(us,		&manufacturerID,		&deviceID);	US_DEBUGP("Result of read_deviceID is %d\n",		result);	if (result != USB_STOR_XFER_GOOD)		return 0;	US_DEBUGP("Device ID = %02X\n", deviceID);	US_DEBUGP("Manuf  ID = %02X\n", manufacturerID);	info->pageshift = 9;	info->smallpageshift = 0;	info->blocksize = 16;	info->blockshift = 4;	info->blockmask = 15;	switch (deviceID) {	case 0x6e: // 1MB	case 0xe8:	case 0xec:		info->pageshift = 8;		info->smallpageshift = 1;		return 0x00100000;	case 0xea: // 2MB	case 0x64:		info->pageshift = 8;		info->smallpageshift = 1;	case 0x5d: // 5d is a ROM card with pagesize 512.		return 0x00200000;	case 0xe3: // 4MB	case 0xe5:	case 0x6b:	case 0xd5:		return 0x00400000;	case 0xe6: // 8MB	case 0xd6:		return 0x00800000;	case 0x73: // 16MB		info->blocksize = 32;		info->blockshift = 5;		info->blockmask = 31;		return 0x01000000;	case 0x75: // 32MB		info->blocksize = 32;		info->blockshift = 5;		info->blockmask = 31;		return 0x02000000;	case 0x76: // 64MB		info->blocksize = 32;		info->blockshift = 5;		info->blockmask = 31;		return 0x04000000;	case 0x79: // 128MB		info->blocksize = 32;		info->blockshift = 5;		info->blockmask = 31;		return 0x08000000;	default: // unknown		return 0;	}}static int sddr55_read_map(struct us_data *us) {	struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra);	int numblocks;	unsigned char *buffer;	unsigned char *command = us->iobuf;	int i;	unsigned short lba;	unsigned short max_lba;	int result;	if (!info->capacity)		return -1;	numblocks = info->capacity >> (info->blockshift + info->pageshift);		buffer = kmalloc( numblocks * 2, GFP_NOIO );		if (!buffer)		return -1;	memset(command, 0, 8);	command[5] = 0xB0;	command[6] = numblocks * 2 / 256;	command[7] = 0x8A;	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);	if ( result != USB_STOR_XFER_GOOD) {		kfree (buffer);		return -1;	}	result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2);	if ( result != USB_STOR_XFER_GOOD) {		kfree (buffer);		return -1;	}	result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2);	if ( result != USB_STOR_XFER_GOOD) {		kfree (buffer);		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;		kfree(buffer);		return -1;	}	memset(info->lba_to_pba, 0xff, numblocks*sizeof(int));	memset(info->pba_to_lba, 0xff, numblocks*sizeof(int));	/* set maximum lba */	max_lba = info->max_log_blks;	if (max_lba > 1000)		max_lba = 1000;	// 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++) {		int zone = i / 1024;		lba = short_pack(buffer[i * 2], buffer[i * 2 + 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. 			 * These devices can have blocks go bad, so there			 * are 24 spare blocks to use when blocks do go bad.			 */			/* SDDR55 returns 0xffff for a bad block, and 0x400 for the 			 * CIS block. (Is this true for cards 8MB or less??)			 * Record these in the physical to logical map			 */ 		info->pba_to_lba[i] = lba;		if (lba >= max_lba) {			continue;		}				if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED &&		    !info->force_read_only) {			printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000);			info->force_read_only = 1;		}		if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF))			US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);		info->lba_to_pba[lba + zone * 1000] = i;	}	kfree(buffer);	return 0;}static void sddr55_card_info_destructor(void *extra) {	struct sddr55_card_info *info = (struct sddr55_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-55 */int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us){	int result;	static unsigned char inquiry_response[8] = {		0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00	}; 	// write-protected for now, no block descriptor support	static unsigned char mode_page_01[20] = {		0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0,		0x01, 0x0A,		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	};	unsigned char *ptr = us->iobuf;	unsigned long capacity;	unsigned int lba;	unsigned int pba;	unsigned int page;	unsigned short pages;	struct sddr55_card_info *info;	if (!us->extra) {		us->extra = kmalloc(			sizeof(struct sddr55_card_info), GFP_NOIO);		if (!us->extra)			return USB_STOR_TRANSPORT_ERROR;		memset(us->extra, 0, sizeof(struct sddr55_card_info));		us->extra_destructor = sddr55_card_info_destructor;	}	info = (struct sddr55_card_info *)(us->extra);	if (srb->cmnd[0] == REQUEST_SENSE) {		US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]);		memcpy (ptr, info->sense_data, sizeof info->sense_data);		ptr[0] = 0x70;		ptr[7] = 11;		usb_stor_set_xfer_buf (ptr, sizeof info->sense_data, srb);		memset (info->sense_data, 0, sizeof info->sense_data);		return USB_STOR_TRANSPORT_GOOD;	}	memset (info->sense_data, 0, sizeof info->sense_data);	/* Dummy up a response for INQUIRY since SDDR55 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;	}	/* only check card status if the map isn't allocated, ie no card seen yet	 * or if it's been over half a second since we last accessed it	 */	if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) {		/* check to see if a card is fitted */		result = sddr55_status (us);		if (result) {			result = sddr55_status (us);			if (!result) {			set_sense_info (6, 0x28, 0);	/* new media, set unit attention, not ready to ready */			}			return USB_STOR_TRANSPORT_FAILED;		}	}	/* if we detected a problem with the map when writing,	   don't allow any more access */	if (info->fatal_error) {		set_sense_info (3, 0x31, 0);		return USB_STOR_TRANSPORT_FAILED;	}	if (srb->cmnd[0] == READ_CAPACITY) {		capacity = sddr55_get_capacity(us);		if (!capacity) {			set_sense_info (3, 0x30, 0); /* incompatible medium */			return USB_STOR_TRANSPORT_FAILED;		}		info->capacity = capacity;		/* figure out the maximum logical block number, allowing for		 * the fact that only 250 out of every 256 are used */		info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250;		/* Last page in the card, adjust as we only use 250 out of		 * every 256 pages */		capacity = (capacity / 256) * 250;		capacity /= PAGESIZE;		capacity--;		((u32 *) ptr)[0] = cpu_to_be32(capacity);		((u32 *) ptr)[1] = cpu_to_be32(PAGESIZE);		usb_stor_set_xfer_buf(ptr, 8, srb);		sddr55_read_map(us);		return USB_STOR_TRANSPORT_GOOD;	}	if (srb->cmnd[0] == MODE_SENSE_10) {		memcpy(ptr, mode_page_01, sizeof mode_page_01);		ptr[3] = (info->read_only || info->force_read_only) ? 0x80 : 0;		usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);		if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {			US_DEBUGP(			  "SDDR55: Dummy up request for mode page 1\n");			return USB_STOR_TRANSPORT_GOOD;		} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {			US_DEBUGP(			  "SDDR55: Dummy up request for all mode pages\n");			return USB_STOR_TRANSPORT_GOOD;		}		set_sense_info (5, 0x24, 0);	/* invalid field in command */		return USB_STOR_TRANSPORT_FAILED;	}	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {		US_DEBUGP(		  "SDDR55: %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 || 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]);		page <<= info->smallpageshift;		// 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->max_log_blks) {			US_DEBUGP("Error: Requested LBA %04X exceeds maximum "			  "block %04X\n", lba, info->max_log_blks-1);			set_sense_info (5, 0x24, 0);	/* invalid field in command */			return USB_STOR_TRANSPORT_FAILED;		}		pba = info->lba_to_pba[lba];		if (srb->cmnd[0] == WRITE_10) {			US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X"				" pages %d\n",				pba, lba, page, pages);			return sddr55_write_data(us, lba, page, pages);		} else {			US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"				" pages %d\n",				pba, lba, page, pages);			return sddr55_read_data(us, lba, page, pages);		}	}	if (srb->cmnd[0] == TEST_UNIT_READY) {		return USB_STOR_TRANSPORT_GOOD;	}	if (srb->cmnd[0] == START_STOP) {		return USB_STOR_TRANSPORT_GOOD;	}	set_sense_info (5, 0x20, 0);	/* illegal command */	return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer?}

⌨️ 快捷键说明

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