The Place to Start for Operating System Developers
It is currently Tue Aug 21, 2018 12:17 am

All times are UTC - 6 hours

Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: USB Mass Storage Read10(SCSI)
PostPosted: Thu Aug 02, 2018 3:23 pm 

Joined: Sat Sep 24, 2016 12:06 am
Posts: 48
Hi everyone!
Today i'm tried to write up mass storage driver. I'm already have working UHCI driver and almost working EHCI(only at QEMU).
I'm write function to make endpoint calls:
static void EhciDevIntr(UsbDevice *dev, UsbTransfer *t)
   EhciController *hc = (EhciController *)dev->hc;

   // Determine transfer properties
   uint speed = dev->speed;
   uint addr = dev->addr;
   uint maxSize = dev->maxPacketSize;
   uint endp = t->endp->desc->addr & 0xf;
   // Create queue of transfer descriptors
   EhciTD *td = EhciAllocTD(hc);
   if (!td)
      t->success = false;
      t->complete = true;

   EhciTD *head = td;
   EhciTD *prev = 0;

   // Data in/out packets
   uint toggle = t->endp->toggle;
   uint packetType = USB_PACKET_IN;
   if (t->endp->desc->addr&0x80!=0)
      packetType = USB_PACKET_OUT;
   kprintf("$#%x#$", packetType);
   uint packetSize = t->len;

   EhciInitTD(td, prev, toggle, packetType, packetSize, t->data);

   // Initialize queue head
   EhciQH *qh = EhciAllocQH(hc);
   EhciInitQH(qh, t, head, dev->parent, true, speed, addr, endp, maxSize);
   // Schedule queue
   EhciInsertPeriodicQH(hc->periodicQH, qh);
   EhciWaitForQH(hc, qh);

I'm have 100% working UsbDevRequest function to make devctrl requests(With it i'm reciving info, endpoints desc and etc).
So, firstly i'm reseting MassStorage and reciving lun count:
   UsbDevRequest(dev, RT_HOST_TO_DEV | RT_CLASS | RT_INTF, 0xff, 0, dev->intfDesc->intfIndex, 0, 0);
   u8 lunCnt = 0;
   UsbDevRequest(dev, 0b10100001, 0xfe, 0, dev->intfDesc->intfIndex, 1, &lunCnt);

Firstly, i'm dissapointed with recieved lun count: 0.
Next i'm getting two endpoints to in and out packets.
   UsbEndpoint * endpointIn = malloc(sizeof(UsbEndpoint));
   endpointIn->toggle = 1;
   if(dev->intfDesc->endpoints->addr & 0x80)
      endpointIn->desc = dev->intfDesc->endpoints;
      endpointIn->desc = dev->intfDesc->endpoints->next;
   UsbEndpoint * endpointOut = malloc(sizeof(UsbEndpoint));
   endpointOut->toggle = 0;
   if (dev->intfDesc->endpoints->addr & 0x80)
      endpointOut->desc = dev->intfDesc->endpoints->next;
      endpointOut->desc = dev->intfDesc->endpoints;

I'm creating my own UsbTransfer structure and filling up Read10 request, filling UsbTransfer structure to make Read10 request and making it:
// Prepare transfer
   UsbTransfer *t = malloc(sizeof(UsbTransfer));
   Read10 ro;
   memset(&ro, 0, sizeof(Read10));
   ro.signature = 0x43425355;
   ro.tag =0x21;
   ro.dataLength = 0x200;
   ro.flags = 0x80;
   ro.lun = 0;
   ro.cmdLength = 10;
   ro.opcode = 0x28;
   ro.LBA = 0;
   ro.cnt =1<<8;
   t->endp = endpointOut;
   t->req = 0;
   t->data = &ro;
   t->len = 0x1F;
   t->complete = false;
   t->success = false;
   dev->hcIntr(dev, t);

hcIntr - points to EhciDevIntr.
Next i'm read data:
   t->endp = endpointIn;
   t->req = 0;
   t->data = buf;
   t->len = 0x200;
   t->complete = false;
   t->success = false;
   dev->hcIntr(dev, t);

And nothing changed. What i'm doing wrong?
With best regards,

 Post subject: Re: USB Mass Storage Read10(SCSI)
PostPosted: Thu Aug 02, 2018 8:08 pm 
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 412
Location: USA
The LUN count is zero based. A return value of zero is for one LUN. Read Section 3.2 of usbmassbulk_10.pdf.

Depending on the type of interface, BBB or UASP, you can have numerous endpoints in both directions.

BBB or Bulk/Bulk/Bulk, aka Bulk Only Protocol, should only have one of each, an in and an out. The interface sub-class will have a value of 0x06.

UASP (USB Attached SCSI), will have four pipes, having pipe descriptors for all four.

As for reading from the drive, there are numerous things you must do first. For example, most MSD devices will assume the first data transfer is the IDENTIFY command. You must do this first for most devices.
You then might need to check the LUN by doing a TEST UNIT READY command. Some devices want this command too.

You then need to get the status of the device, as well as get the capacity of the device. (Note, some devices return an "off by one" count of sectors).

Some devices, though just a few, will not even let you read a single sector until you do one or more of these others first.

Manufacturers, when creating a cheap device, will test only with Windows and if it works, they put a pass on it and run with it. Windows does a certain sequence of events, so if this sequence is not followed, the device may fail. Happens when money is involved.

My book explains all of this and how to read and write to a MSD (Mass Storage Device) either as a BBB or a UASP device.

- http://www.fysnet.net/the_universal_serial_bus.htm

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours

Who is online

Users browsing this forum: No registered users and 5 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group