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

📄 sddr09.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Driver for SanDisk SDDR-09 SmartMedia reader * *   (c) 2000, 2001 Robert Baruch (autophile@starband.net) *   (c) 2002 Andries Brouwer (aeb@cwi.nl) * * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip. * This chip is a programmable USB controller. In the SDDR-09, it has * been programmed to obey a certain limited set of SCSI commands. * This driver translates the "real" SCSI commands to the SDDR-09 SCSI * commands. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include "transport.h"#include "protocol.h"#include "usb.h"#include "debug.h"#include "sddr09.h"#include <linux/sched.h>#include <linux/errno.h>#include <linux/slab.h>#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )#define LSB_of(s) ((s)&0xFF)#define MSB_of(s) ((s)>>8)/* #define US_DEBUGP printk *//* * First some stuff that does not belong here: * data on SmartMedia and other cards, completely * unrelated to this driver. * Similar stuff occurs in <linux/mtd/nand_ids.h>. */struct nand_flash_dev {	int model_id;	int chipshift;		/* 1<<cs bytes total capacity */	char pageshift;		/* 1<<ps bytes in a page */	char blockshift;	/* 1<<bs pages in an erase block */	char zoneshift;		/* 1<<zs blocks in a zone */				/* # of logical blocks is 125/128 of this */	char pageadrlen;	/* length of an address in bytes - 1 */};/* * NAND Flash Manufacturer ID Codes */#define NAND_MFR_AMD		0x01#define NAND_MFR_TOSHIBA	0x98#define NAND_MFR_SAMSUNG	0xecstatic inline char *nand_flash_manufacturer(int manuf_id) {	switch(manuf_id) {	case NAND_MFR_AMD:		return "AMD";	case NAND_MFR_TOSHIBA:		return "Toshiba";	case NAND_MFR_SAMSUNG:		return "Samsung";	default:		return "unknown";	}}/* * It looks like it is unnecessary to attach manufacturer to the * remaining data: SSFDC prescribes manufacturer-independent id codes. */static struct nand_flash_dev nand_flash_ids[] = {	/* NAND flash - these I verified */	{ 0x6e, 20, 8, 4, 8, 2},	/* 1 MB */	{ 0xe8, 20, 8, 4, 8, 2},	/* 1 MB */	{ 0xec, 20, 8, 4, 8, 2},	/* 1 MB */	{ 0x64, 21, 8, 4, 9, 2}, 	/* 2 MB */	{ 0xea, 21, 8, 4, 9, 2},	/* 2 MB */	{ 0x6b, 22, 9, 4, 9, 2},	/* 4 MB */	{ 0xe3, 22, 9, 4, 9, 2},	/* 4 MB */	{ 0xe5, 22, 9, 4, 9, 2},	/* 4 MB */	{ 0xe6, 23, 9, 4, 10, 2},	/* 8 MB */	{ 0x73, 24, 9, 5, 10, 2},	/* 16 MB */	{ 0x75, 25, 9, 5, 10, 2},	/* 32 MB */	{ 0x76, 26, 9, 5, 10, 3},	/* 64 MB */	{ 0x79, 27, 9, 5, 10, 3},	/* 128 MB */	/* MASK ROM - from unknown source */	{ 0x5d, 21, 9, 4, 8, 2},	/* 2 MB */	{ 0xd5, 22, 9, 4, 9, 2},	/* 4 MB */	{ 0xd6, 23, 9, 4, 10, 2},	/* 8 MB */	{ 0,}};#define SIZE(a)	(sizeof(a)/sizeof((a)[0]))static struct nand_flash_dev *nand_find_id(unsigned char id) {	int i;	for (i = 0; i < SIZE(nand_flash_ids); i++)		if (nand_flash_ids[i].model_id == id)			return &(nand_flash_ids[i]);	return NULL;}/* * ECC computation. */static unsigned char parity[256];static unsigned char ecc2[256];static void nand_init_ecc(void) {	int i, j, a;	parity[0] = 0;	for (i = 1; i < 256; i++)		parity[i] = (parity[i&(i-1)] ^ 1);	for (i = 0; i < 256; i++) {		a = 0;		for (j = 0; j < 8; j++) {			if (i & (1<<j)) {				if ((j & 1) == 0)					a ^= 0x04;				if ((j & 2) == 0)					a ^= 0x10;				if ((j & 4) == 0)					a ^= 0x40;			}		}		ecc2[i] = ~(a ^ (a<<1) ^ (parity[i] ? 0xa8 : 0));	}}/* compute 3-byte ecc on 256 bytes */static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {	int i, j, a;	unsigned char par, bit, bits[8];	par = 0;	for (j = 0; j < 8; j++)		bits[j] = 0;	/* collect 16 checksum bits */	for (i = 0; i < 256; i++) {		par ^= data[i];		bit = parity[data[i]];		for (j = 0; j < 8; j++)			if ((i & (1<<j)) == 0)				bits[j] ^= bit;	}	/* put 4+4+4 = 12 bits in the ecc */	a = (bits[3] << 6) + (bits[2] << 4) + (bits[1] << 2) + bits[0];	ecc[0] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));	a = (bits[7] << 6) + (bits[6] << 4) + (bits[5] << 2) + bits[4];	ecc[1] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));	ecc[2] = ecc2[par];}static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) {	return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]);}static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {	memcpy(data, ecc, 3);}/* * The actual driver starts here. *//* * On my 16MB card, control blocks have size 64 (16 real control bytes, * and 48 junk bytes). In reality of course the card uses 16 control bytes, * so the reader makes up the remaining 48. Don't know whether these numbers * depend on the card. For now a constant. */#define CONTROL_SHIFT 6/* * LBA and PBA are unsigned ints. Special values. */#define UNDEF    0xffffffff#define SPARE    0xfffffffe#define UNUSABLE 0xfffffffd/* * Send a control message and wait for the response. * * us - the pointer to the us_data structure for the device to use * * request - the URB Setup Packet's first 6 bytes. The first byte always *  corresponds to the request type, and the second byte always corresponds *  to the request.  The other 4 bytes do not correspond to value and index, *  since they are used in a custom way by the SCM protocol. * * xfer_data - a buffer from which to get, or to which to store, any data *  that gets send or received, respectively, with the URB. Even though *  it looks like we allocate a buffer in this code for the data, xfer_data *  must contain enough allocated space. * * xfer_len - the number of bytes to send or receive with the URB. * */static intsddr09_send_control(struct us_data *us,		    int pipe,		    unsigned char request,		    unsigned char requesttype,		    unsigned int value,		    unsigned int index,		    unsigned char *xfer_data,		    unsigned int xfer_len) {	int result;	// Send the URB to the device and wait for a response.	/* Why are request and request type reversed in this call? */	result = usb_stor_control_msg(us, pipe,			request, requesttype, value, index,			xfer_data, xfer_len);	// Check the return code for the command.	if (result < 0) {		/* if the command was aborted, indicate that */		if (result == -ECONNRESET)			return USB_STOR_TRANSPORT_ABORTED;		/* a stall is a fatal condition from the device */		if (result == -EPIPE) {			US_DEBUGP("-- Stall on control pipe. Clearing\n");			result = usb_clear_halt(us->pusb_dev, pipe);			US_DEBUGP("-- usb_clear_halt() returns %d\n", result);			return USB_STOR_TRANSPORT_FAILED;		}		return USB_STOR_TRANSPORT_ERROR;	}	return USB_STOR_TRANSPORT_GOOD;}/* send vendor interface command (0x41) *//* called for requests 0, 1, 8 */static intsddr09_send_command(struct us_data *us,		    unsigned char request,		    unsigned char direction,		    unsigned char *xfer_data,		    unsigned int xfer_len) {	int pipe;	unsigned char requesttype = (0x41 | direction);	// Get the receive or send control pipe number	if (direction == USB_DIR_IN)		pipe = usb_rcvctrlpipe(us->pusb_dev,0);	else		pipe = usb_sndctrlpipe(us->pusb_dev,0);	return sddr09_send_control(us, pipe, request, requesttype,				   0, 0, xfer_data, xfer_len);}static intsddr09_send_scsi_command(struct us_data *us,			 unsigned char *command,			 unsigned int command_len) {	return sddr09_send_command(us, 0, USB_DIR_OUT, command, command_len);}static intsddr09_raw_bulk(struct us_data *us, int direction,		unsigned char *data, unsigned int len) {	int result;	int act_len;	int pipe;	if (direction == SCSI_DATA_READ)		pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);	else		pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);	result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);        /* if we stall, we need to clear it before we go on */        if (result == -EPIPE) {       	        US_DEBUGP("EPIPE: clearing endpoint halt for"			  " pipe 0x%x, stalled at %d bytes\n",			  pipe, act_len);		usb_clear_halt(us->pusb_dev, pipe);        }	if (result) {                /* -ECONNRESET -- we canceled this transfer */                if (result == -ECONNRESET) {                        US_DEBUGP("usbat_raw_bulk(): transfer aborted\n");                        return US_BULK_TRANSFER_ABORTED;                }                /* NAK - that means we've retried a few times already */       	        if (result == -ETIMEDOUT)                        US_DEBUGP("usbat_raw_bulk(): device NAKed\n");		else if (result == -EOVERFLOW)			US_DEBUGP("us_transfer_partial(): babble/overflow\n");		else if (result != -EPIPE)			US_DEBUGP("us_transfer_partial(): unknown error %d\n",				  result);                return US_BULK_TRANSFER_FAILED;        }	if (act_len != len) {		US_DEBUGP("Warning: Transferred only %d of %d bytes\n",			  act_len, len);		return US_BULK_TRANSFER_SHORT;	}	return US_BULK_TRANSFER_GOOD;}static intsddr09_bulk_transport(struct us_data *us, int direction,		      unsigned char *data, unsigned int len,		      int use_sg) {	int result = USB_STOR_TRANSPORT_GOOD;	int transferred = 0;	int i;	struct scatterlist *sg;	char string[64];#define DEBUG_PRCT 12	if (len == 0)		return USB_STOR_TRANSPORT_GOOD;	if (direction == SCSI_DATA_WRITE && !use_sg) {		/* Debug-print the first N bytes of the write transfer */		strcpy(string, "wr: ");		for (i=0; i<len && i<DEBUG_PRCT; i++) {			sprintf(string+strlen(string), "%02X ",				data[i]);			if ((i%16) == 15) {				US_DEBUGP("%s\n", string);				strcpy(string, "wr: ");			}		}		if ((i%16)!=0)			US_DEBUGP("%s\n", string);	}	US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",		  (direction == SCSI_DATA_READ) ? "in" : "out",		  len, use_sg);	if (!use_sg)		result = sddr09_raw_bulk(us, direction, data, len);	else {		sg = (struct scatterlist *)data;		for (i=0; i<use_sg && transferred<len; i++) {			unsigned char *buf;			unsigned int length;			buf = sg[i].address;			length = len-transferred;			if (length > sg[i].length)				length = sg[i].length;			result = sddr09_raw_bulk(us, direction, buf, length);			if (result != US_BULK_TRANSFER_GOOD)				break;			transferred += sg[i].length;		}	}	if (direction == SCSI_DATA_READ && !use_sg) {		/* Debug-print the first N bytes of the read transfer */		strcpy(string, "rd: ");		for (i=0; i<len && i<DEBUG_PRCT; i++) {			sprintf(string+strlen(string), "%02X ",				data[i]);			if ((i%16) == 15) {				US_DEBUGP("%s\n", string);				strcpy(string, "rd: ");			}		}		if ((i%16)!=0)			US_DEBUGP("%s\n", string);	}	return result;}#if 0/* * Test Unit Ready Command: 12 bytes. * byte 0: opcode: 00 */static intsddr09_test_unit_ready(struct us_data *us) {	unsigned char command[6] = {		0, 0x20, 0, 0, 0, 0	};	int result;	result = sddr09_send_scsi_command(us, command, sizeof(command));	US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);	return result;}#endif/* * Request Sense Command: 12 bytes. * byte 0: opcode: 03 * byte 4: data length */#if 0static intsddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {	unsigned char command[12] = {		0x03, 0x20, 0, 0, buflen, 0, 0, 0, 0, 0, 0, 0	};	int result;	result = sddr09_send_scsi_command(us, command, sizeof(command));	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("request sense failed\n");		return result;	}	result = sddr09_raw_bulk(us, SCSI_DATA_READ, sensebuf, buflen);	if (result != USB_STOR_TRANSPORT_GOOD)		US_DEBUGP("request sense bulk in failed\n");	else		US_DEBUGP("request sense worked\n");	return result;}#endif/* * Read Command: 12 bytes. * byte 0: opcode: E8 * byte 1: last two bits: 00: read data, 01: read blockwise control, *                        10: read both, 11: read pagewise control. *         It turns out we need values 20, 21, 22, 23 here (LUN 1). * bytes 2-5: address (interpretation depends on byte 1, see below) * bytes 10-11: count (idem) * * A page has 512 data bytes and 64 control bytes (16 control and 48 junk). * A read data command gets data in 512-byte pages. * A read control command gets control in 64-byte chunks. * A read both command gets data+control in 576-byte chunks. * * Blocks are groups of 32 pages, and read blockwise control jumps to the * next block, while read pagewise control jumps to the next page after * reading a group of 64 control bytes. * [Here 512 = 1<<pageshift, 32 = 1<<blockshift, 64 is constant?] * * (1 MB and 2 MB cards are a bit different, but I have only a 16 MB card.) */static intsddr09_readX(struct us_data *us, int x, unsigned long fromaddress,	     int nr_of_pages, int bulklen, unsigned char *buf,	     int use_sg) {	unsigned char command[12] = {		0xe8, 0x20 | x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0	};	int result;	command[2] = MSB_of(fromaddress>>16);	command[3] = LSB_of(fromaddress>>16); 	command[4] = MSB_of(fromaddress & 0xFFFF);	command[5] = LSB_of(fromaddress & 0xFFFF); 	command[10] = MSB_of(nr_of_pages);	command[11] = LSB_of(nr_of_pages);	result = sddr09_send_scsi_command(us, command, sizeof(command));	if (result != USB_STOR_TRANSPORT_GOOD) {		US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",			  x, result);		return result;	}	result = sddr09_bulk_transport(us, SCSI_DATA_READ,				       buf, bulklen, use_sg);	if (result != USB_STOR_TRANSPORT_GOOD)		US_DEBUGP("Result for bulk_transport in sddr09_read2%d %d\n",			  x, result);	return result;}/* * Read Data * * fromaddress counts data shorts: * increasing it by 256 shifts the bytestream by 512 bytes; * the last 8 bits are ignored. * * nr_of_pages counts pages of size (1 << pageshift). */static intsddr09_read20(struct us_data *us, unsigned long fromaddress,	      int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {	int bulklen = nr_of_pages << pageshift;	/* The last 8 bits of fromaddress are ignored. */	return sddr09_readX(us, 0, fromaddress, nr_of_pages, bulklen,			    buf, use_sg);}/* * Read Blockwise Control * * fromaddress gives the starting position (as in read data; * the last 8 bits are ignored); increasing it by 32*256 shifts * the output stream by 64 bytes. * * count counts control groups of size (1 << controlshift). * For me, controlshift = 6. Is this constant? * * After getting one control group, jump to the next block * (fromaddress += 8192). */static intsddr09_read21(struct us_data *us, unsigned long fromaddress,	      int count, int controlshift, unsigned char *buf, int use_sg) {	int bulklen = (count << controlshift);	return sddr09_readX(us, 1, fromaddress, count, bulklen,			    buf, use_sg);}/* * Read both Data and Control * * fromaddress counts data shorts, ignoring control: * increasing it by 256 shifts the bytestream by 576 = 512+64 bytes; * the last 8 bits are ignored. * * nr_of_pages counts pages of size (1 << pageshift) + (1 << controlshift). */static intsddr09_read22(struct us_data *us, unsigned long fromaddress,	      int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {	int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT);	US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n",		  nr_of_pages, bulklen);	return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen,			    buf, use_sg);}#if 0/* * Read Pagewise Control * * fromaddress gives the starting position (as in read data; * the last 8 bits are ignored); increasing it by 256 shifts

⌨️ 快捷键说明

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