usb:adding usb mass storage driver.

Change-Id: I9e431d56eddfeec21413c290b2fa7ad35b566f6b

http://gerrit.minix3.org/#/c/2690/
This commit is contained in:
Kees Jongenburger 2014-05-26 16:47:48 +02:00 committed by Lionel Sambuc
parent ed3391fd23
commit dfb2b8398d
12 changed files with 2308 additions and 0 deletions

20
drivers/usb_storage/Makefile Executable file
View file

@ -0,0 +1,20 @@
# Makefile for Mass Storage driver
PROG= usb_storage
SRCS= urb_helper.c bulk.c scsi.c usb_storage.c
FILES= $(PROG).conf
FILESNAME= $(PROG)
FILESDIR= /etc/system.conf.d
DPADD+= ${LIBBLOCKDRIVER} ${LIBDDEKIT_USB_CLIENT} ${LIBSYS} ${LIBMINLIB} ${LIBDDEKIT} ${LIBUSB}
LDADD+= -lblockdriver -lddekit_usb_client -lsys -lminlib -lddekit -lusb
#For easier debugging, uncomment:
#LDADD+= -Wl,-Ttext=0x800000
#CPPFLAGS+= -DMASS_DEBUG
MAN=
BINDIR?= /usr/sbin
.include <minix.service.mk>

27
drivers/usb_storage/README.txt Executable file
View file

@ -0,0 +1,27 @@
-------------------------------------------------------------------------------
* INFORMATION: *
-------------------------------------------------------------------------------
README file for "USB Mass Storage driver" that uses DDEkit and libblockdriver.
created march-april 2014, JPEmbedded (info@jpembedded.eu)
-------------------------------------------------------------------------------
* KNOWN LIMITATIONS: *
-------------------------------------------------------------------------------
-Hardcoded interface number for bulk-only reset.
-Hardcoded configuration number for simple enumeration.
-Call to ddekit_minix_create_msg_q in _ddekit_usb_thread uses base that
overlaps that of blockdriver's (in mass_storage_task) so initialization
must be done in fixed order.
-Some of DDEKit's functions are declared in source files as they are missing
from headers.
-DDEKit has 'init' but no 'deinit' call, so memory is spilled.
-Hardcoded geometry.
-LUN always set to 0.
-SIGTERM handler uses exit instead of DDEkit semaphores.
-mass_storage.conf taken from dde-linux26-usb-drivers.
-Subpartitioning does not seem to work.
-Type ddekit_usb_dev is not defined in any header file but two variants of it
should exist (client and server).
-Magic number in URB setup buffer assignment as there is no header for that
(like usb_ch9.h for descriptors).

39
drivers/usb_storage/bulk.c Executable file
View file

@ -0,0 +1,39 @@
/*
* "Bulk only transfer" related implementation
*/
#include <assert.h>
#include <string.h> /* memset */
#include "common.h"
#include "bulk.h"
/*===========================================================================*
* init_cbw *
*===========================================================================*/
void
init_cbw(mass_storage_cbw * cbw, unsigned int tag)
{
assert(NULL != cbw);
/* Clearing "Command Block Wrapper" */
memset(cbw, 0, sizeof(*cbw));
/* Filling Command Block Wrapper */
cbw->dCBWSignature = CBW_SIGNATURE;
cbw->dCBWTag = tag;
cbw->bCBWLUN = 0;
}
/*===========================================================================*
* init_csw *
*===========================================================================*/
void
init_csw(mass_storage_csw * csw)
{
assert(NULL != csw);
/* Clearing "Command Status Wrapper" so we can receive data into it */
memset(csw, 0, sizeof(*csw));
}

52
drivers/usb_storage/bulk.h Executable file
View file

@ -0,0 +1,52 @@
/*
* "Bulk only transfer" related externally visible info
*/
#ifndef _BULK_H_
#define _BULK_H_
/*---------------------------*
* declared types *
*---------------------------*/
#define BULK_PACKED __attribute__((__packed__))
#define CBW_SIGNATURE (0x43425355)
#define CBW_FLAGS_OUT (0x00)
#define CBW_FLAGS_IN (0x80)
#define CBW_CB_LENGTH (16)
/* Command Block Wrapper */
typedef struct BULK_PACKED mass_storage_cbw {
uint32_t dCBWSignature;
uint32_t dCBWTag;
uint32_t dCBWDataTransferLength;
uint8_t bCBWFlags;
uint8_t bCBWLUN; /* 4 bits */
uint8_t bCDBLength; /* 5 bits */
uint8_t CBWCB[CBW_CB_LENGTH];
}
mass_storage_cbw;
#define CSW_SIGNATURE (0x53425355)
#define CSW_STATUS_GOOD (0x0)
#define CSWS_TATUS_FAILED (0x1)
#define CSW_STATUS_PHASE (0x2)
/* Command Status Wrapper */
typedef struct BULK_PACKED mass_storage_csw {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
}
mass_storage_csw;
#undef BULK_PACKED
/*---------------------------*
* declared functions *
*---------------------------*/
void init_cbw(mass_storage_cbw *, unsigned int);
void init_csw(mass_storage_csw *);
#endif /* !_BULK_H_ */

35
drivers/usb_storage/common.h Executable file
View file

@ -0,0 +1,35 @@
/*
* Whatever is commonly used in mass_storage driver, should be here
*/
#ifndef _COMMON_H_
#define _COMMON_H_
/*---------------------------*
* commonly used headers: *
*---------------------------*/
#include <stdlib.h> /* For things, like EXIT_*, NULL, ... */
#include <stdio.h>
/*---------------------------*
* commonly used defines: *
*---------------------------*/
#define THIS_EXEC_NAME "usb_storage"
#define MASS_MSG(...) do { \
printf(THIS_EXEC_NAME": "); \
printf(__VA_ARGS__); \
printf("; %s:%d\n", __func__, __LINE__); \
} while(0)
/*---------------------------*
* debug helpers: *
*---------------------------*/
#ifdef MASS_DEBUG
#define MASS_DEBUG_MSG MASS_MSG
#define MASS_DEBUG_DUMP printf("%s():%d\n", __func__, __LINE__)
#else
#define MASS_DEBUG_MSG(...)
#define MASS_DEBUG_DUMP
#endif
#endif /* !_COMMON_H_ */

266
drivers/usb_storage/scsi.c Executable file
View file

@ -0,0 +1,266 @@
/*
* SCSI commands related implementation
*/
#include <minix/blockdriver.h> /* SECTOR_SIZE */
#include <assert.h>
#include <string.h> /* strncpy */
#include "common.h"
#include "scsi.h"
/*---------------------------*
* declared functions *
*---------------------------*/
/* To work correctly cbw->CBWCB must be zeroed before calling these: */
static int create_inquiry_scsi_cmd(mass_storage_cbw *);
static int create_test_scsi_cmd(mass_storage_cbw *);
static int create_read_capacity_scsi_cmd(mass_storage_cbw *);
static int create_write_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
static int create_read_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
static int create_mode_sense_scsi_cmd(mass_storage_cbw *);
/*---------------------------*
* defined functions *
*---------------------------*/
/*===========================================================================*
* create_scsi_cmd *
*===========================================================================*/
int
create_scsi_cmd(mass_storage_cbw * cbw, int cmd, scsi_transfer * info)
{
MASS_DEBUG_DUMP;
assert(NULL != cbw);
switch (cmd) {
case SCSI_INQUIRY:
return create_inquiry_scsi_cmd(cbw);
case SCSI_TEST_UNIT_READY:
return create_test_scsi_cmd(cbw);
case SCSI_READ_CAPACITY:
return create_read_capacity_scsi_cmd(cbw);
case SCSI_WRITE:
return create_write_scsi_cmd(cbw, info);
case SCSI_READ:
return create_read_scsi_cmd(cbw, info);
case SCSI_MODE_SENSE:
return create_mode_sense_scsi_cmd(cbw);
default:
MASS_MSG("Invalid SCSI command!");
return EXIT_FAILURE;
}
}
/*===========================================================================*
* create_inquiry_scsi_cmd *
*===========================================================================*/
static int
create_inquiry_scsi_cmd(mass_storage_cbw * cbw)
{
MASS_DEBUG_DUMP;
cbw->dCBWDataTransferLength = SCSI_INQUIRY_DATA_LEN;
cbw->bCBWFlags = CBW_FLAGS_IN;
cbw->bCDBLength = SCSI_INQUIRY_CMD_LEN;
SCSI_SET_INQUIRY_OP_CODE(cbw->CBWCB);
SCSI_SET_INQUIRY_PAGE_CODE(cbw->CBWCB, 0);
SCSI_SET_INQUIRY_ALLOC_LEN(cbw->CBWCB, SCSI_INQUIRY_DATA_LEN);
return EXIT_SUCCESS;
}
/*===========================================================================*
* create_test_scsi_cmd *
*===========================================================================*/
static int
create_test_scsi_cmd(mass_storage_cbw * cbw)
{
MASS_DEBUG_DUMP;
cbw->bCDBLength = SCSI_TEST_CMD_LEN;
SCSI_SET_TEST_OP_CODE(cbw->CBWCB);
return EXIT_SUCCESS;
}
/*===========================================================================*
* create_read_capacity_scsi_cmd *
*===========================================================================*/
static int
create_read_capacity_scsi_cmd(mass_storage_cbw * cbw)
{
MASS_DEBUG_DUMP;
cbw->dCBWDataTransferLength = SCSI_READ_CAPACITY_DATA_LEN;
cbw->bCBWFlags = CBW_FLAGS_IN;
cbw->bCDBLength = SCSI_READ_CAPACITY_CMD_LEN;
SCSI_SET_READ_CAPACITY_OP_CODE(cbw->CBWCB);
SCSI_SET_READ_CAPACITY_LBA(cbw->CBWCB, 0x00);
return EXIT_SUCCESS;
}
/*===========================================================================*
* create_write_scsi_cmd *
*===========================================================================*/
static int
create_write_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
{
MASS_DEBUG_DUMP;
assert(NULL != info);
assert(0 == (info->length % SECTOR_SIZE));
cbw->dCBWDataTransferLength = info->length;
cbw->bCBWFlags = CBW_FLAGS_OUT;
cbw->bCDBLength = SCSI_WRITE_CMD_LEN;
SCSI_SET_WRITE_OP_CODE(cbw->CBWCB);
SCSI_SET_WRITE_LBA(cbw->CBWCB, info->lba);
SCSI_SET_WRITE_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
return EXIT_SUCCESS;
}
/*===========================================================================*
* create_read_scsi_cmd *
*===========================================================================*/
static int
create_read_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
{
MASS_DEBUG_DUMP;
assert(NULL != info);
assert(0 == (info->length % SECTOR_SIZE));
cbw->dCBWDataTransferLength = info->length;
cbw->bCBWFlags = CBW_FLAGS_IN;
cbw->bCDBLength = SCSI_READ_CMD_LEN;
SCSI_SET_READ_OP_CODE(cbw->CBWCB);
SCSI_SET_READ_LBA(cbw->CBWCB, info->lba);
SCSI_SET_READ_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
return EXIT_SUCCESS;
}
/*===========================================================================*
* create_mode_sense_scsi_cmd *
*===========================================================================*/
static int
create_mode_sense_scsi_cmd(mass_storage_cbw * cbw)
{
MASS_DEBUG_DUMP;
cbw->dCBWDataTransferLength = SCSI_MODE_SENSE_FLEX_DATA_LEN;
cbw->bCBWFlags = CBW_FLAGS_IN;
cbw->bCDBLength = SCSI_MODE_SENSE_CMD_LEN;
SCSI_SET_MODE_SENSE_OP_CODE(cbw->CBWCB);
SCSI_SET_MODE_SENSE_PAGE_CODE(cbw->CBWCB,
SCSI_MODE_SENSE_FLEXIBLE_DISK_PAGE);
return EXIT_SUCCESS;
}
/*===========================================================================*
* check_inquiry_reply *
*===========================================================================*/
int
check_inquiry_reply(uint8_t * scsi_reply)
{
char vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN + 1];
char product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN + 1];
MASS_DEBUG_DUMP;
/* Stop condition for printing as strncpy() does not add it */
vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN] = '\0';
product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN] = '\0';
if (SCSI_GET_INQUIRY_PERIPH_QUALIF(scsi_reply)) {
MASS_MSG("Device not connected");
return EXIT_FAILURE;
}
strncpy(vendor_name, SCSI_GET_INQUIRY_VENDOR_NAME(scsi_reply),
SCSI_INQUIRY_VENDOR_NAME_LEN);
strncpy(product_name, SCSI_GET_INQUIRY_PRODUCT_NAME(scsi_reply),
SCSI_INQUIRY_PRODUCT_NAME_LEN);
MASS_DEBUG_MSG("Vendor name: %s", vendor_name);
MASS_DEBUG_MSG("Product name %s", product_name);
return EXIT_SUCCESS;
}
/*===========================================================================*
* check_read_capacity_reply *
*===========================================================================*/
int
check_read_capacity_reply(uint8_t * scsi_reply, uint32_t * lba, uint32_t * blen)
{
MASS_DEBUG_DUMP;
*lba = SCSI_GET_READ_CAPACITY_LBA(scsi_reply);
*blen = SCSI_GET_READ_CAPACITY_BLEN(scsi_reply);
return EXIT_SUCCESS;
}
/*===========================================================================*
* check_mode_sense_reply *
*===========================================================================*/
int
check_mode_sense_reply(uint8_t * scsi_reply, unsigned * cyl,
unsigned * head, unsigned * sect)
{
MASS_DEBUG_DUMP;
*cyl = SCSI_GET_MODE_SENSE_CYLINDERS(scsi_reply);
*head = SCSI_GET_MODE_SENSE_HEADS(scsi_reply);
*sect = SCSI_GET_MODE_SENSE_SECTORS(scsi_reply);
return EXIT_SUCCESS;
}
/*===========================================================================*
* check_csw *
*===========================================================================*/
int
check_csw(mass_storage_csw * csw, unsigned int tag)
{
MASS_DEBUG_DUMP;
if (csw->dCSWTag != tag) {
MASS_MSG("CSW tag mismatch!");
return EXIT_FAILURE;
}
if (CSW_SIGNATURE != csw->dCSWSignature) {
MASS_MSG("CSW signature mismatch!");
return EXIT_FAILURE;
}
if (CSW_STATUS_GOOD != csw->bCSWStatus) {
MASS_MSG("CSW status error!");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

143
drivers/usb_storage/scsi.h Executable file
View file

@ -0,0 +1,143 @@
/*
* SCSI commands related definitions
*/
#ifndef _SCSI_H_
#define _SCSI_H_
#if 0
#include <sys/endian.h> /* be16dec... */
#else
#define be16enc(base, val) { \
(base)[0] = (((val) >> 8) & 0xff); \
(base)[1] = ((val) & 0xff); \
}
#define be16dec(base) \
(((base)[0] << 8) | (base)[1])
#define be32enc(base, val) { \
(base)[0] = (((val) >> 24) & 0xff); \
(base)[1] = (((val) >> 16) & 0xff); \
(base)[2] = (((val) >> 8) & 0xff); \
(base)[3] = ((val) & 0xff); \
}
#define be32dec(base) \
(((base)[0] << 24) | ((base)[1] << 16) | \
((base)[2] << 8) | (base)[3])
#endif
#include "bulk.h"
#define SCSI_FORMAT_UNIT (0x04)
#define SCSI_INQUIRY (0x12)
#define SCSI_START_STOP (0x1B)
#define SCSI_MODE_SELECT (0x55)
#define SCSI_MODE_SENSE (0x5A)
#define SCSI_PREVENT_ALLOW (0x1E)
#define SCSI_READ (0x28)
#define SCSI_READ_12 (0xA8)
#define SCSI_READ_CAPACITY (0x25)
#define SCSI_READ_FORMAT_CAP (0x23)
#define SCSI_REQUEST_SENSE (0x03)
#define SCSI_REZERO_UNIT (0x01)
#define SCSI_SEEK (0x2B)
#define SCSI_SEND_DIAGNOSTIC (0x1D)
#define SCSI_TEST_UNIT_READY (0x00)
#define SCSI_VERIFY (0x2F)
#define SCSI_WRITE (0x2A)
#define SCSI_WRITE_12 (0xAA)
#define SCSI_WRITE_VERIFY (0x2E)
#define SCSI_INQUIRY_DATA_LEN (36)
#define SCSI_INQUIRY_CMD_LEN (6)
#define SCSI_MODE_SENSE_FLEX_DATA_LEN (32)
#define SCSI_MODE_SENSE_CMD_LEN (12)
#define SCSI_READ_DATA_LEN (0)
#define SCSI_READ_CMD_LEN (10)
#define SCSI_READ_CAPACITY_DATA_LEN (8)
#define SCSI_READ_CAPACITY_CMD_LEN (10)
#define SCSI_TEST_DATA_LEN (0)
#define SCSI_TEST_CMD_LEN (6)
#define SCSI_WRITE_DATA_LEN (0)
#define SCSI_WRITE_CMD_LEN (10)
/* These macros are immune to unaligned access
* so they can be used on any address */
/* 1 Byte SCSI operation */
#define SCSI_WR1(base, offset, value)\
(((uint8_t*)(base))[offset] = value)
#define SCSI_RD1(base, offset)\
(((uint8_t*)(base))[offset])
#define SCSI_SET1(base, offset, value)\
(((uint8_t*)(base))[offset] |= value)
/* 2 Byte SCSI operation */
#define SCSI_WR2(base, offset, value)\
be16enc( &(((uint8_t*)(base))[offset]), value )
#define SCSI_RD2(base, offset)\
be16dec( &(((uint8_t*)(base))[offset]) )
/* 4 Byte SCSI operation */
#define SCSI_WR4(base, offset, value)\
be32enc( &(((uint8_t*)(base))[offset]), value )
#define SCSI_RD4(base, offset)\
be32dec( &(((uint8_t*)(base))[offset]) )
#define SCSI_SET_INQUIRY_OP_CODE(x) SCSI_WR1((x), 0, SCSI_INQUIRY)
#define SCSI_SET_INQUIRY_EVPD(x) SCSI_SET1((x), 1, 0x01)
#define SCSI_SET_INQUIRY_CMDDT(x) SCSI_SET1((x), 1, 0x02)
#define SCSI_SET_INQUIRY_PAGE_CODE(x, code) SCSI_WR1((x), 2, code)
#define SCSI_SET_INQUIRY_ALLOC_LEN(x, len) SCSI_WR1((x), 4, len)
#define SCSI_GET_INQUIRY_PERIPH_QUALIF(x) ((SCSI_RD1(x, 0) >> 5) & 0x7)
#define SCSI_GET_INQUIRY_VENDOR_NAME(x) ((const char *)(&((x)[8])))
#define SCSI_INQUIRY_VENDOR_NAME_LEN (8)
#define SCSI_GET_INQUIRY_PRODUCT_NAME(x) ((const char *)(&((x)[16])))
#define SCSI_INQUIRY_PRODUCT_NAME_LEN (16)
#define SCSI_MODE_SENSE_FLEXIBLE_DISK_PAGE (0x5)
#define SCSI_SET_MODE_SENSE_OP_CODE(x) SCSI_WR1((x), 0, \
SCSI_MODE_SENSE)
#define SCSI_SET_MODE_SENSE_PAGE_CODE(x, code) SCSI_SET1((x), 2, \
(code)&0x3F)
#define SCSI_GET_MODE_SENSE_CYLINDERS(x) SCSI_RD2((x), 8)
#define SCSI_GET_MODE_SENSE_HEADS(x) SCSI_RD1((x), 4)
#define SCSI_GET_MODE_SENSE_SECTORS(x) SCSI_RD1((x), 5)
#define SCSI_SET_READ_OP_CODE(x) SCSI_WR1((x), 0, SCSI_READ)
#define SCSI_SET_READ_LBA(x, lba) SCSI_WR4((x), 2, (lba))
#define SCSI_SET_READ_BLEN(x, len) SCSI_WR2((x), 7, (len))
#define SCSI_SET_READ_CAPACITY_OP_CODE(x) SCSI_WR1((x), 0, \
SCSI_READ_CAPACITY)
#define SCSI_SET_READ_CAPACITY_LBA(x, lba) SCSI_WR4((x), 2, (lba))
#define SCSI_SET_READ_CAPACITY_PMI(x) SCSI_SET1((x), 8, 0x01)
#define SCSI_GET_READ_CAPACITY_LBA(x) SCSI_RD4((x), 0)
#define SCSI_GET_READ_CAPACITY_BLEN(x) SCSI_RD4((x), 4)
#define SCSI_SET_TEST_OP_CODE(x) SCSI_WR1((x), 0, \
SCSI_TEST_UNIT_READY)
#define SCSI_SET_WRITE_OP_CODE(x) SCSI_WR1((x), 0, SCSI_WRITE)
#define SCSI_SET_WRITE_LBA(x, lba) SCSI_WR4((x), 2, (lba))
#define SCSI_SET_WRITE_BLEN(x, len) SCSI_WR2((x), 7, (len))
typedef struct scsi_transfer {
unsigned int lba; /* logical block address */
unsigned int length; /* transfer length */
}
scsi_transfer;
/*---------------------------*
* declared functions *
*---------------------------*/
int create_scsi_cmd(mass_storage_cbw *, int, struct scsi_transfer *);
int check_inquiry_reply(uint8_t *);
int check_read_capacity_reply(uint8_t *, uint32_t *, uint32_t *);
int check_mode_sense_reply(uint8_t *, unsigned *, unsigned *, unsigned *);
int check_csw(mass_storage_csw *, unsigned int);
#endif /* !_SCSI_H_ */

112
drivers/usb_storage/urb_helper.c Executable file
View file

@ -0,0 +1,112 @@
/*
* URB formatting related implementation
*/
#include <minix/sysutil.h> /* panic */
#include <minix/usb.h> /* struct usb_ctrlrequest */
#include <string.h> /* memset */
#include <assert.h>
#include "common.h"
#include "urb_helper.h"
/*---------------------------*
* defined functions *
*---------------------------*/
/*===========================================================================*
* init_urb *
*===========================================================================*/
void
init_urb(struct ddekit_usb_urb * urb, struct ddekit_usb_dev * dev,
ddekit_int32_t urb_type, ddekit_int32_t urb_endpoint,
ddekit_int32_t urb_direction, ddekit_uint32_t urb_transfer_flags)
{
MASS_DEBUG_DUMP;
/* Sanity checks */
assert(NULL != urb);
assert(NULL != dev);
assert((DDEKIT_USB_TRANSFER_BLK == urb_type) ||
(DDEKIT_USB_TRANSFER_CTL == urb_type) ||
(DDEKIT_USB_TRANSFER_INT == urb_type) ||
(DDEKIT_USB_TRANSFER_ISO == urb_type));
assert(urb_endpoint < 16);
assert((DDEKIT_USB_IN == urb_direction) ||
(DDEKIT_USB_OUT == urb_direction));
/* Clear block first */
memset(urb, 0, sizeof(*urb));
/* Set supplied values */
urb->dev = dev;
urb->type = urb_type;
urb->endpoint = urb_endpoint;
urb->direction = urb_direction;
urb->transfer_flags = urb_transfer_flags;
}
/*===========================================================================*
* attach_urb_data *
*===========================================================================*/
void
attach_urb_data(struct ddekit_usb_urb * urb, int buf_type,
void * buf, ddekit_uint32_t buf_len)
{
MASS_DEBUG_DUMP;
assert(NULL != urb);
assert(NULL != buf);
/* Mutual exclusion */
if (URB_BUF_TYPE_DATA == buf_type) {
urb->data = buf;
urb->size = buf_len;
} else if ( URB_BUF_TYPE_SETUP == buf_type ) {
assert(sizeof(struct usb_ctrlrequest) == buf_len);
urb->setup_packet = buf;
} else
panic("Unexpected buffer type!");
}
/*===========================================================================*
* blocking_urb_submit *
*===========================================================================*/
int
blocking_urb_submit(struct ddekit_usb_urb * urb, ddekit_sem_t * sem,
int check_len)
{
MASS_DEBUG_DUMP;
assert(NULL != urb);
assert(NULL != sem);
assert((check_len == URB_SUBMIT_CHECK_LEN) ||
(check_len == URB_SUBMIT_ALLOW_MISMATCH));
/* Submit and block until semaphore gets up */
if (ddekit_usb_submit_urb(urb)) {
MASS_MSG("Submitting DDEKit URB failed");
return EXIT_FAILURE;
} else {
/* Submitting succeeded so block and wait for reply */
ddekit_sem_down(sem);
/* Check for DDEKit status first */
if (urb->status) {
MASS_MSG("Invalid DDEKit URB status");
return EXIT_FAILURE;
} else {
if (URB_SUBMIT_CHECK_LEN == check_len) {
/* Compare lengths */
if (urb->actual_length != urb->size) {
MASS_MSG("URB different than expected");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
}
}

View file

@ -0,0 +1,30 @@
/*
* URB formatting related definitions
*/
#ifndef _URB_HELPER_H_
#define _URB_HELPER_H_
#include <ddekit/usb.h>
#include <ddekit/semaphore.h>
/* Possible values for attach_urb_data's buf_type */
/* Both may be used for single URB */
#define URB_BUF_TYPE_DATA 0 /* attached buffer is data buffer */
#define URB_BUF_TYPE_SETUP 1 /* attached buffer is setup structure */
/* Possible values for blocking_urb_submit's check_len */
/* Use URB_SUBMIT_CHECK_LEN when actual data buffer length returned
* by HCD must match expected length, supplied in attach_urb_data */
#define URB_SUBMIT_CHECK_LEN 0 /* return error on length mismatch */
#define URB_SUBMIT_ALLOW_MISMATCH 1 /* ignore length check */
/*---------------------------*
* declared functions *
*---------------------------*/
void init_urb(struct ddekit_usb_urb *, struct ddekit_usb_dev *, ddekit_int32_t,
ddekit_int32_t, ddekit_int32_t, ddekit_uint32_t);
void attach_urb_data(struct ddekit_usb_urb *, int, void *, ddekit_uint32_t);
int blocking_urb_submit(struct ddekit_usb_urb *, ddekit_sem_t *, int);
#endif /* !_URB_HELPER_H_ */

1491
drivers/usb_storage/usb_storage.c Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
service usb_storage
{
system
PRIVCTL # 4
UMAP # 14
IRQCTL # 19
DEVIO # 21
SDEVIO # 22
;
ipc
SYSTEM pm rs log tty ds vfs vm amddev devman
pci usbd
;
uid 0;
};

View file

@ -0,0 +1,78 @@
/*
* Minix3 USB mass storage driver definitions
*/
#ifndef _USB_STORAGE_H_
#define _USB_STORAGE_H_
#include <minix/driver.h> /* struct device */
#include <minix/type.h> /* vir_bytes */
/* TODO: no header for ddekit_usb_dev */
/* Number of handled peripherals (USB devices) */
#define MAX_PERIPHS (1)
/* Number of handled disks per driver */
#define MAX_DRIVES (4)
/* 4 partitions per disk */
#define PART_PER_DISK (4)
/* 4 sub partitions per partition */
#define SUBPART_PER_PART (4)
/* 16 sub partitions per disk */
#define SUBPART_PER_DISK (PART_PER_DISK * SUBPART_PER_PART)
/*---------------------------*
* declared types *
*---------------------------*/
/* Information on opened mass storage drives */
typedef struct mass_storage_drive {
struct device disk; /* disk device */
struct device part[PART_PER_DISK]; /* partition devices */
struct device subpart[SUBPART_PER_DISK];/* sub-partition devices */
unsigned long open_ct; /* opening counter */
int drive_idx; /* Index of this drive */
}
mass_storage_drive;
/* Information on attached peripherals (USB devices) */
typedef struct mass_storage_periph {
mass_storage_drive drives[MAX_DRIVES]; /* Possible drive info */
struct ddekit_usb_dev * dev; /* DDEKit device handler */
unsigned int interfaces; /* Interfaces bitmap */
int ep_in; /* Bulk IN endpoint*/
int ep_out; /* Bulk OUT endpoint*/
}
mass_storage_periph;
/* Structure for the information on current state of driver */
typedef struct mass_storage_state {
/* DDEKit device handlers */
mass_storage_periph periph[MAX_PERIPHS];
/* Currently used peripheral */
mass_storage_periph * cur_periph;
/* Currently used drive */
mass_storage_drive * cur_drive;
/* Currently used device (drive/partition/sub-partition) */
struct device * cur_device;
/* Driver instance */
long instance;
}
mass_storage_state;
/* State of current IO vector array for transfer operations */
typedef struct iov_state {
vir_bytes base_addr; /* Address to read/write or grant ID */
vir_bytes remaining_bytes; /* How many bytes remain in vector */
vir_bytes offset; /* How many bytes were copied */
unsigned int iov_idx; /* Index of currently selected vector */
}
iov_state;
#endif /* !_USB_STORAGE_H_ */