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

📄 freecom.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Driver for Freecom USB/IDE adaptor * * $Id: freecom.c,v 1.21 2001/12/29 03:47:33 mdharm Exp $ * * Freecom v0.1: * * First release * * Current development and maintenance by: *   (C) 2000 David Brown <usb-storage@davidb.org> * * 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. * * This driver was developed with information provided in FREECOM's USB * Programmers Reference Guide.  For further information contact Freecom * (http://www.freecom.de/) */#include <linux/config.h>#include "transport.h"#include "protocol.h"#include "usb.h"#include "debug.h"#include "freecom.h"#include <linux/hdreg.h>#ifdef CONFIG_USB_STORAGE_DEBUGstatic void pdump (void *, int);#endifstruct freecom_udata {        __u8    buffer[64];             /* Common command block. */};typedef struct freecom_udata *freecom_udata_t;/* All of the outgoing packets are 64 bytes long. */struct freecom_cb_wrap {        __u8    Type;                   /* Command type. */        __u8    Timeout;                /* Timeout in seconds. */        __u8    Atapi[12];              /* An ATAPI packet. */        __u8    Filler[50];             /* Padding Data. */};struct freecom_xfer_wrap {        __u8    Type;                   /* Command type. */        __u8    Timeout;                /* Timeout in seconds. */        __u32   Count;                  /* Number of bytes to transfer. */        __u8    Pad[58];} __attribute__ ((packed));struct freecom_ide_out {        __u8    Type;                   /* Type + IDE register. */        __u8    Pad;        __u16   Value;                  /* Value to write. */        __u8    Pad2[60];};struct freecom_ide_in {        __u8    Type;                   /* Type | IDE register. */        __u8    Pad[63];};struct freecom_status {        __u8    Status;        __u8    Reason;        __u16   Count;        __u8    Pad[60];};/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide * register. */#define FCM_INT_STATUS		0x02 /* INDEX_STAT */#define FCM_STATUS_BUSY		0x80/* These are the packet types.  The low bit indicates that this command * should wait for an interrupt. */#define FCM_PACKET_ATAPI	0x21#define FCM_PACKET_STATUS	0x20/* Receive data from the IDE interface.  The ATAPI packet has already * waited, so the data should be immediately available. */#define FCM_PACKET_INPUT	0x81/* Send data to the IDE interface. */#define FCM_PACKET_OUTPUT	0x01/* Write a value to an ide register.  Or the ide register to write after * munging the address a bit. */#define FCM_PACKET_IDE_WRITE	0x40#define FCM_PACKET_IDE_READ	0xC0/* All packets (except for status) are 64 bytes long. */#define FCM_PACKET_LENGTH	64/* * Transfer an entire SCSI command's worth of data payload over the bulk * pipe. * * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this * function simply determines if we're going to use scatter-gather or not, * and acts appropriately.  For now, it also re-interprets the error codes. */static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer_amount){	int i;	int result = -1;	struct scatterlist *sg;	unsigned int total_transferred = 0;	/* was someone foolish enough to request more data than available	 * buffer space? */	if (transfer_amount > srb->request_bufflen)		transfer_amount = srb->request_bufflen;	/* are we scatter-gathering? */	if (srb->use_sg) {		/* loop over all the scatter gather structures and 		 * make the appropriate requests for each, until done		 */		sg = (struct scatterlist *) srb->request_buffer;		for (i = 0; i < srb->use_sg; i++) {			US_DEBUGP("transfer_amount: %d and total_transferred: %d\n", transfer_amount, total_transferred);			/* End this if we're done */			if (transfer_amount == total_transferred)				break;			/* transfer the lesser of the next buffer or the			 * remaining data */			if (transfer_amount - total_transferred >= 					sg[i].length) {				result = usb_stor_transfer_partial(us,						sg[i].address, sg[i].length);				total_transferred += sg[i].length;			} else {				result = usb_stor_transfer_partial(us,						sg[i].address,						transfer_amount - total_transferred);				total_transferred += transfer_amount - total_transferred;			}			/* if we get an error, end the loop here */			if (result)				break;		}	}	else		/* no scatter-gather, just make the request */		result = usb_stor_transfer_partial(us, srb->request_buffer, 					     transfer_amount);	/* return the result in the data structure itself */	srb->result = result;}#if 0/* Write a value to an ide register. */static intfreecom_ide_write (struct us_data *us, int reg, int value){        freecom_udata_t extra = (freecom_udata_t) us->extra;        struct freecom_ide_out *ideout =                (struct freecom_ide_out *) extra->buffer;        int opipe;        int result, partial;        US_DEBUGP("IDE out 0x%02x <- 0x%02x\n", reg, value);        /* Get handles for both transports. */        opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);        if (reg < 0 || reg > 8)                return USB_STOR_TRANSPORT_ERROR;        if (reg < 8)                reg |= 0x20;        else                reg = 0x0e;        ideout->Type = FCM_PACKET_IDE_WRITE | reg;        ideout->Pad = 0;        ideout->Value = cpu_to_le16 (value);        memset (ideout->Pad2, 0, sizeof (ideout->Pad2));        result = usb_stor_bulk_msg (us, ideout, opipe,                        FCM_PACKET_LENGTH, &partial);        if (result != 0) {                if (result == -ECONNRESET)                        return US_BULK_TRANSFER_ABORTED;                else                        return USB_STOR_TRANSPORT_ERROR;        }        return USB_STOR_TRANSPORT_GOOD;}/* Read a value from an ide register. */static intfreecom_ide_read (struct us_data *us, int reg, int *value){        freecom_udata_t extra = (freecom_udata_t) us->extra;        struct freecom_ide_in *idein =                (struct freecom_ide_in *) extra->buffer;        __u8 *buffer = extra->buffer;        int ipipe, opipe;        int result, partial;        int desired_length;        /* Get handles for both transports. */        opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);        ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);        if (reg < 0 || reg > 8)                return USB_STOR_TRANSPORT_ERROR;        if (reg < 8)                reg |= 0x10;        else                reg = 0x0e;        US_DEBUGP("IDE in request for register 0x%02x\n", reg);        idein->Type = FCM_PACKET_IDE_READ | reg;        memset (idein->Pad, 0, sizeof (idein->Pad));        result = usb_stor_bulk_msg (us, idein, opipe,                        FCM_PACKET_LENGTH, &partial);        if (result != 0) {                if (result == -ECONNRESET)                        return US_BULK_TRANSFER_ABORTED;                else                        return USB_STOR_TRANSPORT_ERROR;        }        desired_length = 1;        if (reg == 0x10)                desired_length = 2;        result = usb_stor_bulk_msg (us, buffer, ipipe,                        desired_length, &partial);        if (result != 0) {                if (result == -ECONNRESET)                        return US_BULK_TRANSFER_ABORTED;                else                        return USB_STOR_TRANSPORT_ERROR;        }        US_DEBUGP("IDE in partial is %d\n", partial);        if (desired_length == 1)                *value = buffer[0];        else                *value = le16_to_cpu (*(__u16 *) buffer);        US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);        return USB_STOR_TRANSPORT_GOOD;}#endifstatic intfreecom_readdata (Scsi_Cmnd *srb, struct us_data *us,                int ipipe, int opipe, int count){        freecom_udata_t extra = (freecom_udata_t) us->extra;        struct freecom_xfer_wrap *fxfr =                (struct freecom_xfer_wrap *) extra->buffer;        int result, partial;        fxfr->Type = FCM_PACKET_INPUT | 0x00;        fxfr->Timeout = 0;    /* Short timeout for debugging. */        fxfr->Count = cpu_to_le32 (count);        memset (fxfr->Pad, 0, sizeof (fxfr->Pad));        US_DEBUGP("Read data Freecom! (c=%d)\n", count);        /* Issue the transfer command. */        result = usb_stor_bulk_msg (us, fxfr, opipe,                        FCM_PACKET_LENGTH, &partial);        if (result != 0) {                US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n",                                result, partial);		/* -ECONNRESET -- we canceled this transfer */		if (result == -ECONNRESET) {			US_DEBUGP("freecom_readdata(): transfer aborted\n");			return US_BULK_TRANSFER_ABORTED;		}                return USB_STOR_TRANSPORT_ERROR;        }        US_DEBUGP("Done issuing read request: %d %d\n", result, partial);        /* Now transfer all of our blocks. */	US_DEBUGP("Start of read\n");	us_transfer_freecom(srb, us, count);        US_DEBUGP("freecom_readdata done!\n");        return USB_STOR_TRANSPORT_GOOD;}static intfreecom_writedata (Scsi_Cmnd *srb, struct us_data *us,                int ipipe, int opipe, int count){        freecom_udata_t extra = (freecom_udata_t) us->extra;        struct freecom_xfer_wrap *fxfr =                (struct freecom_xfer_wrap *) extra->buffer;        int result, partial;        fxfr->Type = FCM_PACKET_OUTPUT | 0x00;        fxfr->Timeout = 0;    /* Short timeout for debugging. */        fxfr->Count = cpu_to_le32 (count);        memset (fxfr->Pad, 0, sizeof (fxfr->Pad));        US_DEBUGP("Write data Freecom! (c=%d)\n", count);        /* Issue the transfer command. */        result = usb_stor_bulk_msg (us, fxfr, opipe,                        FCM_PACKET_LENGTH, &partial);        if (result != 0) {                US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n",                                result, partial);		/* -ECONNRESET -- we canceled this transfer */		if (result == -ECONNRESET) {			US_DEBUGP("freecom_writedata(): transfer aborted\n");			return US_BULK_TRANSFER_ABORTED;		}                return USB_STOR_TRANSPORT_ERROR;        }        US_DEBUGP("Done issuing write request: %d %d\n",                        result, partial);        /* Now transfer all of our blocks. */	US_DEBUGP("Start of write\n");	us_transfer_freecom(srb, us, count);        US_DEBUGP("freecom_writedata done!\n");        return USB_STOR_TRANSPORT_GOOD;}

⌨️ 快捷键说明

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