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

📄 freecom.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        struct freecom_status  *fst;        int ipipe, opipe;             /* We need both pipes. */        int result;        int partial;        int length;        freecom_udata_t extra;        extra = (freecom_udata_t) us->extra;        fcb = (struct freecom_cb_wrap *) extra->buffer;        fst = (struct freecom_status *) extra->buffer;        US_DEBUGP("Freecom TRANSPORT STARTED\n");        /* Get handles for both transports. */        opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);        ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);#if 0        /* Yuck, let's see if this helps us.  Artificially increase the         * length on this. */        if (srb->cmnd[0] == 0x03 && srb->cmnd[4] == 0x12)                srb->cmnd[4] = 0x0E;#endif        /* The ATAPI Command always goes out first. */        fcb->Type = FCM_PACKET_ATAPI | 0x00;        fcb->Timeout = 0;        memcpy (fcb->Atapi, srb->cmnd, 12);        memset (fcb->Filler, 0, sizeof (fcb->Filler));        US_DEBUG(pdump (srb->cmnd, 12));        /* Send it out. */        result = usb_stor_bulk_msg (us, fcb, opipe,                        FCM_PACKET_LENGTH, &partial);        /* The Freecom device will only fail if there is something wrong in         * USB land.  It returns the status in its own registers, which         * come back in the bulk pipe. */        if (result != 0) {                US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",                                result, partial);		/* -ENOENT -- we canceled this transfer */		if (result == -ENOENT) {			US_DEBUGP("freecom_transport(): transfer aborted\n");			return US_BULK_TRANSFER_ABORTED;		}                return USB_STOR_TRANSPORT_ERROR;        }        /* There are times we can optimize out this status read, but it         * doesn't hurt us to always do it now. */        result = usb_stor_bulk_msg (us, fst, ipipe,                        FCM_PACKET_LENGTH, &partial);        US_DEBUGP("foo Status result %d %d\n", result, partial);	/* -ENOENT -- we canceled this transfer */	if (result == -ENOENT) {		US_DEBUGP("freecom_transport(): transfer aborted\n");		return US_BULK_TRANSFER_ABORTED;	}        US_DEBUG(pdump ((void *) fst, partial));	/* while we haven't recieved the IRQ */	while (!(fst->Status & 0x2)) {		/* send a command to re-fetch the status */		US_DEBUGP("Re-attempting to get status...\n");		fcb->Type = FCM_PACKET_STATUS;		fcb->Timeout = 0;		memset (fcb->Atapi, 0, 12);		memset (fcb->Filler, 0, sizeof (fcb->Filler));		/* Send it out. */		result = usb_stor_bulk_msg (us, fcb, opipe,				FCM_PACKET_LENGTH, &partial);		/* The Freecom device will only fail if there is something		 * wrong in USB land.  It returns the status in its own		 * registers, which come back in the bulk pipe.		 */		if (result != 0) {			US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",					result, partial);			/* -ENOENT -- we canceled this transfer */			if (result == -ENOENT) {				US_DEBUGP("freecom_transport(): transfer aborted\n");				return US_BULK_TRANSFER_ABORTED;			}			return USB_STOR_TRANSPORT_ERROR;		}		/* actually get the status info */		result = usb_stor_bulk_msg (us, fst, ipipe,				FCM_PACKET_LENGTH, &partial);		US_DEBUGP("bar Status result %d %d\n", result, partial);		/* -ENOENT -- we canceled this transfer */		if (result == -ENOENT) {			US_DEBUGP("freecom_transport(): transfer aborted\n");			return US_BULK_TRANSFER_ABORTED;		}		US_DEBUG(pdump ((void *) fst, partial));	}        if (partial != 4 || result != 0) {                return USB_STOR_TRANSPORT_ERROR;        }        if ((fst->Status & 1) != 0) {                US_DEBUGP("operation failed\n");                return USB_STOR_TRANSPORT_FAILED;        }        /* The device might not have as much data available as we         * requested.  If you ask for more than the device has, this reads         * and such will hang. */        US_DEBUGP("Device indicates that it has %d bytes available\n",                        le16_to_cpu (fst->Count));        /* Find the length we desire to read.  It is the lesser of the SCSI         * layer's requested length, and the length the device claims to         * have available. */        length = usb_stor_transfer_length (srb);        US_DEBUGP("SCSI requested %d\n", length);        if (length > le16_to_cpu (fst->Count))                length = le16_to_cpu (fst->Count);        /* What we do now depends on what direction the data is supposed to         * move in. */        switch (us->srb->sc_data_direction) {        case SCSI_DATA_READ:                /* Make sure that the status indicates that the device                 * wants data as well. */                if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {                        US_DEBUGP("SCSI wants data, drive doesn't have any\n");                        return USB_STOR_TRANSPORT_FAILED;                }                result = freecom_readdata (srb, us, ipipe, opipe, length);                if (result != USB_STOR_TRANSPORT_GOOD)                        return result;                US_DEBUGP("FCM: Waiting for status\n");                result = usb_stor_bulk_msg (us, fst, ipipe,                                FCM_PACKET_LENGTH, &partial);		US_DEBUG(pdump ((void *) fst, partial));                if (result == -ENOENT) {                        US_DEBUGP ("freecom_transport: transfer aborted\n");                        return US_BULK_TRANSFER_ABORTED;                }                if (partial != 4 || result != 0)                        return USB_STOR_TRANSPORT_ERROR;                if ((fst->Status & ERR_STAT) != 0) {                        US_DEBUGP("operation failed\n");                        return USB_STOR_TRANSPORT_FAILED;                }                if ((fst->Reason & 3) != 3) {                        US_DEBUGP("Drive seems still hungry\n");                        return USB_STOR_TRANSPORT_FAILED;                }                US_DEBUGP("Transfer happy\n");                break;        case SCSI_DATA_WRITE:                /* Make sure the status indicates that the device wants to                 * send us data. */                /* !!IMPLEMENT!! */                result = freecom_writedata (srb, us, ipipe, opipe, length);                if (result != USB_STOR_TRANSPORT_GOOD)                        return result;#if 1                US_DEBUGP("FCM: Waiting for status\n");                result = usb_stor_bulk_msg (us, fst, ipipe,                                FCM_PACKET_LENGTH, &partial);                if (result == -ENOENT) {                        US_DEBUGP ("freecom_transport: transfer aborted\n");                        return US_BULK_TRANSFER_ABORTED;                }                if (partial != 4 || result != 0)                        return USB_STOR_TRANSPORT_ERROR;                if ((fst->Status & ERR_STAT) != 0) {                        US_DEBUGP("operation failed\n");                        return USB_STOR_TRANSPORT_FAILED;                }                if ((fst->Reason & 3) != 3) {                        US_DEBUGP("Drive seems still hungry\n");                        return USB_STOR_TRANSPORT_FAILED;                }#endif                US_DEBUGP("Transfer happy\n");                break;        case SCSI_DATA_NONE:                /* Easy, do nothing. */                break;        default:                US_DEBUGP ("freecom unimplemented direction: %d\n",                                us->srb->sc_data_direction);                // Return fail, SCSI seems to handle this better.                return USB_STOR_TRANSPORT_FAILED;                break;        }        return USB_STOR_TRANSPORT_GOOD;        US_DEBUGP("Freecom: transfer_length = %d\n",			usb_stor_transfer_length (srb));        US_DEBUGP("Freecom: direction = %d\n", srb->sc_data_direction);        return USB_STOR_TRANSPORT_ERROR;}intfreecom_init (struct us_data *us){        int result, value;        int counter;	char buffer[33];        /* Allocate a buffer for us.  The upper usb transport code will         * free this for us when cleaning up. */        if (us->extra == NULL) {                us->extra = kmalloc (sizeof (struct freecom_udata),                                GFP_KERNEL);                if (us->extra == NULL) {                        US_DEBUGP("Out of memory\n");                        return USB_STOR_TRANSPORT_ERROR;                }        }	result = usb_control_msg(us->pusb_dev,			usb_rcvctrlpipe(us->pusb_dev, 0),			0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);	buffer[32] = '\0';	US_DEBUGP("String returned from FC init is: %s\n", buffer);        result = freecom_ide_write (us, 0x06, 0xA0);        if (result != USB_STOR_TRANSPORT_GOOD)                return result;        result = freecom_ide_write (us, 0x01, 0x00);        if (result != USB_STOR_TRANSPORT_GOOD)                return result;        counter = 50;        do {                result = freecom_ide_read (us, 0x07, &value);                if (result != USB_STOR_TRANSPORT_GOOD)                        return result;                if (counter-- < 0) {                        US_DEBUGP("Timeout in freecom");                        return USB_STOR_TRANSPORT_ERROR;                }        } while ((value & 0x80) != 0);        result = freecom_ide_write (us, 0x07, 0x08);        if (result != USB_STOR_TRANSPORT_GOOD)                return result;        counter = 50;        do {                result = freecom_ide_read (us, 0x07, &value);                if (result != USB_STOR_TRANSPORT_GOOD)                        return result;                if (counter-- < 0) {                        US_DEBUGP("Timeout in freecom");                        return USB_STOR_TRANSPORT_ERROR;                }        } while ((value & 0x80) != 0);        result = freecom_ide_write (us, 0x08, 0x08);        if (result != USB_STOR_TRANSPORT_GOOD)                return result;        return USB_STOR_TRANSPORT_GOOD;}int usb_stor_freecom_reset(struct us_data *us){        printk (KERN_CRIT "freecom reset called\n");        /* We don't really have this feature. */        return FAILED;}#ifdef CONFIG_USB_STORAGE_DEBUGstatic void pdump (void *ibuffer, int length){	static char line[80];	int offset = 0;	unsigned char *buffer = (unsigned char *) ibuffer;	int i, j;	int from, base;	offset = 0;	for (i = 0; i < length; i++) {		if ((i & 15) == 0) {			if (i > 0) {				offset += sprintf (line+offset, " - ");				for (j = i - 16; j < i; j++) {					if (buffer[j] >= 32 && buffer[j] <= 126)						line[offset++] = buffer[j];					else						line[offset++] = '.';				}				line[offset] = 0;				US_DEBUGP("%s\n", line);				offset = 0;			}			offset += sprintf (line+offset, "%08x:", i);		}		else if ((i & 7) == 0) {			offset += sprintf (line+offset, " -");		}		offset += sprintf (line+offset, " %02x", buffer[i] & 0xff);	}	/* Add the last "chunk" of data. */	from = (length - 1) % 16;	base = ((length - 1) / 16) * 16;	for (i = from + 1; i < 16; i++)		offset += sprintf (line+offset, "   ");	if (from < 8)		offset += sprintf (line+offset, "  ");	offset += sprintf (line+offset, " - ");	for (i = 0; i <= from; i++) {		if (buffer[base+i] >= 32 && buffer[base+i] <= 126)			line[offset++] = buffer[base+i];		else			line[offset++] = '.';	}	line[offset] = 0;	US_DEBUGP("%s\n", line);	offset = 0;}#endif

⌨️ 快捷键说明

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