示例#1
0
        public static void RemoveHead(UHCIController controller, UHCIQueueHead *head)
        {
            mMutex.Lock();

            /**
             * Set next to previous
             */
            if (head->Previous != null)
            {
                if (head->Next != null)
                {
                    head->Previous->Head = head->Head;
                    head->Previous->Next = head->Next;
                }
                else
                {
                    head->Previous->Head = TD_POINTER_TERMINATE;
                    head->Previous->Next = null;
                }
            }

            /**
             * Set previous to next
             */
            if (head->Next != null)
            {
                head->Next->Previous = head->Previous;
            }

            FreeHead(controller, head);
            mMutex.Unlock();
        }
示例#2
0
        /// <summary>
        /// Prepare interrupt
        /// </summary>
        /// <param name="dev"></param>
        /// <param name="transfer"></param>
        private static void PrepareInterrupt(USBDevice dev, USBTransfer *transfer)
        {
            UHCIController controller = (UHCIController)dev.Controller;

            uint endp = (uint)(dev.EndPointDesc->Address & 0xF);

            UHCITransmitDescriptor *td = GetTransmit(controller);

            if (td == null)
            {
                transfer->Success  = false;
                transfer->Executed = true;
            }

            UHCITransmitDescriptor *head = td;

            /**
             * Initalize read
             */
            InitTransmit(td, null, dev.Speed, dev.Address, endp, dev.Toggle, TRANS_PACKET_IN, transfer->Length, transfer->Data);

            UHCIQueueHead *qh = GetQueueHead(controller);

            qh->Element  = (int)Paging.GetPhysicalFromVirtual(head);
            qh->Head     = 0;
            qh->Transfer = transfer;
            qh->Transmit = head;

            InsertHead(controller, qh);
        }
示例#3
0
 public static void WaitForQueueHead(UHCIController controller, UHCIQueueHead *head)
 {
     while (!head->Transfer->Executed)
     {
         ProcessHead(controller, head);
     }
 }
示例#4
0
        /// <summary>
        /// Unset bit on port
        /// </summary>
        /// <param name="port">Port number</param>
        /// <param name="bit">Bit to unset</param>
        private static void unsetPortBit(UHCIController uhciDev, ushort port, ushort bit)
        {
            ushort status = PortIO.In16((ushort)(uhciDev.IOBase + port));

            status &= (ushort)~bit;
            PortIO.Out16((ushort)(uhciDev.IOBase + port), status);
        }
示例#5
0
        /// <summary>
        /// Insert head
        /// </summary>
        /// <param name="controller">UHCIController</param>
        /// <param name="head"></param>
        public static void InsertHead(UHCIController controller, UHCIQueueHead *head)
        {
            mMutex.Lock();
            UHCIQueueHead *end = controller.FirstHead;

            while (true)
            {
                if (end->Next != null)
                {
                    end = end->Next;
                }
                else
                {
                    break;
                }
            }

            head->Head     = TD_POINTER_TERMINATE;
            head->Previous = end;
            head->Next     = null;

            end->Next = head;
            end->Head = (int)Paging.GetPhysicalFromVirtual(head) | TD_POINTER_QH;

            mMutex.Unlock();
        }
示例#6
0
        /// <summary>
        /// Reset port
        /// </summary>
        /// <param name="port">Port num to reset</param>
        private static void resetPort(UHCIController uhciDev, ushort port)
        {
            /**
             * Set reset bit
             */
            setPortBit(uhciDev, port, PORTSC_RESET);

            /**
             * Wait for 60 ms
             */
            Tasking.CurrentTask.CurrentThread.Sleep(0, 60);

            /**
             * Unset reset bit
             */
            unsetPortBit(uhciDev, port, PORTSC_RESET);

            /**
             * Wait for atleast 150ms for link to go up
             */
            for (int i = 0; i < 15; i++)
            {
                Tasking.CurrentTask.CurrentThread.Sleep(0, 10);

                ushort status = PortIO.In16((ushort)(uhciDev.IOBase + port));

                /**
                 * Is it even connected?
                 */
                if (((status) & PORTSC_CUR_STAT) == 0)
                {
                    break;
                }

                /**
                 * Status changed?
                 */
                if (((status) & (PORTSC_STAT_CHNG | PORTSC_ENABLE_STAT)) > 0)
                {
                    unsetPortBit(uhciDev, port, PORTSC_STAT_CHNG | PORTSC_ENABLE_STAT);
                    continue;
                }

                /**
                 * Enabled?
                 */
                if ((status & PORTSC_CUR_ENABLE) > 0)
                {
                    break;
                }
            }
        }
示例#7
0
        /// <summary>
        /// Poll queue heads
        /// </summary>
        /// <param name="controller"></param>
        public static void Poll(IUSBController controller)
        {
            UHCIController uhciController = (UHCIController)controller;

            for (int i = 0; i < MAX_HEADS; i++)
            {
                if (uhciController.QueueHeadPool[i].Transfer != null)
                {
                    int address = (int)uhciController.QueueHeadPool;
                    address += sizeof(UHCIQueueHead) * i;

                    ProcessHead(uhciController, (UHCIQueueHead *)(address));
                }
            }
        }
示例#8
0
        public static void RemoveTransmit(UHCIController controller, UHCITransmitDescriptor *transmit)
        {
            if (transmit->Previous != null)
            {
                if (transmit->Next != null)
                {
                    transmit->Previous->Link = transmit->Next->Link;
                    transmit->Previous->Next = transmit->Next;
                }
                else
                {
                    transmit->Previous->Link = 0;
                    transmit->Previous->Next = null;
                }
            }

            FreeTransmit(controller, transmit);
        }
示例#9
0
        /// <summary>
        /// Probe usb devices on port
        /// </summary>
        /// <param name="uhciDev">The UHCI device</param>
        private static void probe(UHCIController uhciDev)
        {
            /**
             * UHCI only supports 2 ports, so just 2 :-)
             */
            for (int i = 0; i < 2; i++)
            {
                ushort port = (i == 0)? REG_PORTSC1 : REG_PORTSC2;

                resetPort(uhciDev, port);


                ushort status = PortIO.In16((ushort)(uhciDev.IOBase + port));

                /**
                 * Is the port even connected?
                 */
                if ((status & PORTSC_CUR_STAT) == 0)
                {
                    continue;
                }

                bool lowSpeed = ((status & PORTSC_LOW_SPEED) > 0);

                USBDevice dev = new USBDevice();
                dev.Controller       = uhciDev;
                dev.Control          = Control;
                dev.PrepareInterrupt = PrepareInterrupt;
                dev.TransferOne      = TransferOne;

                /**
                 * Root hub
                 */
                dev.Parent = null;
                dev.Port   = port;
                dev.State  = USBDeviceState.ATTACHED;
                dev.Speed  = (lowSpeed) ? USBDeviceSpeed.LOW_SPEED : USBDeviceSpeed.HIGH_SPEED;

                if (!dev.Init())
                {
                    Heap.Free(dev);
                }
            }
        }
示例#10
0
        /// <summary>
        /// Transfer
        /// </summary>
        /// <param name="dev">Device</param>
        /// <param name="transfer">Transfers</param>
        /// <param name="length">Number of transfers</param>
        private static unsafe void TransferOne(USBDevice dev, USBTransfer *transfer)
        {
            USBDeviceRequest request = transfer->Request;

            UHCIController controller = (UHCIController)dev.Controller;

            UHCITransmitDescriptor *td = GetTransmit(controller);

            InitTransmit(td, null, dev.Speed, dev.Address, transfer->Endpoint, dev.Toggle, (transfer->Type == 0) ? TRANS_PACKET_IN : TRANS_PACKET_OUT, transfer->Length, transfer->Data);

            UHCIQueueHead *qh = GetQueueHead(controller);

            qh->Element  = (int)Paging.GetPhysicalFromVirtual(td);
            qh->Head     = 0;
            qh->Transfer = transfer;
            qh->Transmit = td;

            InsertHead(controller, qh);
            WaitForQueueHead(controller, qh);
        }
示例#11
0
        /// <summary>
        /// Insert head
        /// </summary>
        /// <param name="controller">UHCIController</param>
        /// <param name="head"></param>
        public static void InsertTransmit(UHCIController controller, UHCITransmitDescriptor *transmit)
        {
            UHCITransmitDescriptor *end = transmit;

            while (true)
            {
                if (end->Next != null)
                {
                    end = end->Next;
                }
                else
                {
                    break;
                }
            }

            end->Next      = transmit;
            end->Link      = (int)transmit | 1;
            transmit->Link = 0;
        }
示例#12
0
        /// <summary>
        /// Get Queue head item
        /// </summary>
        /// <param name="dev">Device</param>
        /// <returns></returns>
        private static UHCITransmitDescriptor *GetTransmit(UHCIController dev)
        {
            int i = 0;

            while (i < MAX_TRANSMIT)
            {
                if (!dev.TransmitPool[i].Allocated)
                {
                    dev.TransmitPool[i].Allocated = true;
                    dev.TransmitPool[i].Next      = null;
                    dev.TransmitPool[i].Previous  = null;

                    return((UHCITransmitDescriptor *)(((int)dev.TransmitPool) + (sizeof(UHCITransmitDescriptor) * i)));
                }

                i++;
            }

            Console.WriteLine("NO TRANSMIT LEFT");

            return(null);
        }
示例#13
0
        /// <summary>
        /// Get Queue head item
        /// </summary>
        /// <param name="dev">Device</param>
        /// <returns></returns>
        private static UHCIQueueHead *GetQueueHead(UHCIController dev)
        {
            mMutex.Lock();
            int i = 0;

            while (i < MAX_HEADS)
            {
                if (!dev.QueueHeadPool[i].Allocated)
                {
                    dev.QueueHeadPool[i].Allocated = true;
                    dev.QueueHeadPool[i].Next      = null;
                    dev.QueueHeadPool[i].Previous  = null;

                    mMutex.Unlock();
                    return((UHCIQueueHead *)(((int)dev.QueueHeadPool) + (sizeof(UHCIQueueHead) * i)));
                }

                i++;
            }

            mMutex.Unlock();
            return(null);
        }
示例#14
0
        private static void initDevice(PciDevice dev)
        {
            if ((dev.BAR4.flags & Pci.BAR_IO) == 0)
            {
                Console.WriteLine("[UHCI] Only Portio supported");
            }

            Pci.EnableBusMastering(dev);

            UHCIController uhciDev = new UHCIController();

            uhciDev.IOBase = (ushort)dev.BAR4.Address;
            uhciDev.Poll   = Poll;


            Console.Write("[UHCI] Initalize at 0x");
            Console.WriteHex(uhciDev.IOBase);
            Console.WriteLine("");

            uhciDev.FrameList     = (int *)Heap.AlignedAlloc(0x1000, sizeof(int) * 1024);
            uhciDev.QueueHeadPool = (UHCIQueueHead *)Heap.AlignedAlloc(0x1000, sizeof(UHCIQueueHead) * MAX_HEADS);
            uhciDev.TransmitPool  = (UHCITransmitDescriptor *)Heap.AlignedAlloc(0x1000, sizeof(UHCITransmitDescriptor) * MAX_TRANSMIT);
            Memory.Memclear(uhciDev.QueueHeadPool, sizeof(UHCIQueueHead) * MAX_HEADS);
            Memory.Memclear(uhciDev.TransmitPool, sizeof(UHCITransmitDescriptor) * MAX_TRANSMIT);

            UHCIQueueHead *head = GetQueueHead(uhciDev);

            head->Head    = TD_POINTER_TERMINATE;
            head->Element = TD_POINTER_TERMINATE;

            uhciDev.FirstHead = head;


            for (int i = 0; i < 1024; i++)
            {
                uhciDev.FrameList[i] = TD_POINTER_QH | (int)Paging.GetPhysicalFromVirtual(head);
            }


            PortIO.Out16((ushort)(uhciDev.IOBase + REG_LEGSUP), 0x8f00);

            /**
             * Initalize framelist
             */
            PortIO.Out16((ushort)(uhciDev.IOBase + REG_FRNUM), 0);
            PortIO.Out32((ushort)(uhciDev.IOBase + REG_FRBASEADD), (uint)Paging.GetPhysicalFromVirtual(uhciDev.FrameList));
            PortIO.Out8(((ushort)(uhciDev.IOBase + REG_SOFMOD)), 0x40); // Ensure default value of 64 (aka cycle time of 12000)

            /**
             * We are going to poll!
             */
            PortIO.Out16((ushort)(uhciDev.IOBase + REG_USBINTR), 0x00);

            /**
             * Clear any pending statusses
             */
            PortIO.Out16((ushort)(uhciDev.IOBase + REG_USBSTS), 0xFFFF);

            /**
             * Enable device
             */
            PortIO.Out16((ushort)(uhciDev.IOBase + REG_USBCMD), USBCMD_RS);

            probe(uhciDev);

            Sharpen.USB.USB.RegisterController(uhciDev);
        }
示例#15
0
 public static void FreeTransmit(UHCIController controller, UHCITransmitDescriptor *transmit)
 {
     transmit->Allocated = false;
 }
示例#16
0
        /// <summary>
        /// Control USB Device
        /// </summary>
        /// <param name="dev"></param>
        /// <param name="transfer"></param>
        private static void Control(USBDevice dev, USBTransfer *transfer)
        {
            USBDeviceRequest request = transfer->Request;

#if __UHCI_DIAG
            Console.WriteLine("------ UHCI Control message ---------");
            Console.Write("Request: ");
            Console.WriteHex(request.Request);
            Console.WriteLine("");
            Console.Write("Index: ");
            Console.WriteHex(request.Index);
            Console.WriteLine("");
            Console.Write("Length:");
            Console.WriteHex(request.Length);
            Console.WriteLine("");
            Console.Write("Type:");
            Console.WriteHex(request.Type);
            Console.WriteLine("");
            Console.Write("Value:");
            Console.WriteHex(request.Value);
            Console.WriteLine("");
            Console.WriteLine("--------------------------------------");
#endif

            UHCIController controller = (UHCIController)dev.Controller;

            UHCITransmitDescriptor *td = GetTransmit(controller);

            UHCITransmitDescriptor *head = td;
            UHCITransmitDescriptor *prev = null;

            USBDeviceRequest *a = (USBDeviceRequest *)Heap.Alloc(sizeof(USBDeviceRequest));
            a->Request = request.Request;
            a->Index   = request.Index;
            a->Length  = request.Length;
            a->Type    = request.Type;
            a->Value   = request.Value;

            InitTransmit(td, prev, dev.Speed, dev.Address, 0, 0, TRANS_PACKET_SETUP, (uint)sizeof(USBDeviceRequest), (byte *)a);
            prev = td;

            uint packetType = ((request.Type & USBDevice.TYPE_DEVICETOHOST) > 0) ? TRANS_PACKET_IN : TRANS_PACKET_OUT;

            byte *ptr        = transfer->Data;
            uint  packetSize = transfer->Length;
            uint  offset     = 0;

            uint toggle = 0;

            uint remaining = packetSize;

            while (remaining > 0)
            {
                td = GetTransmit(controller);
                if (td == null)
                {
                    return;
                }

                packetSize = remaining;
                if (packetSize > dev.MaxPacketSize)
                {
                    packetSize = dev.MaxPacketSize;
                }

                remaining -= packetSize;

                toggle ^= 1;

                InitTransmit(td, prev, dev.Speed, dev.Address, 0, toggle, packetType, packetSize, ptr + offset);
                prev = td;

                offset += packetSize;
            }

            td = GetTransmit(controller);
            if (td == null)
            {
                return;
            }

            packetType = ((request.Type & USBDevice.TYPE_DEVICETOHOST) > 0) ? TRANS_PACKET_OUT : TRANS_PACKET_IN;

            toggle = 1;
            InitTransmit(td, prev, dev.Speed, dev.Address, 0, toggle, packetType, 0, null);


            UHCIQueueHead *qh = GetQueueHead(controller);
            qh->Element  = (int)Paging.GetPhysicalFromVirtual(head);
            qh->Head     = 0;
            qh->Transfer = transfer;
            qh->Transmit = head;

            InsertHead(controller, qh);
            WaitForQueueHead(controller, qh);
        }
示例#17
0
 public static void FreeHead(UHCIController controller, UHCIQueueHead *head)
 {
     head->Allocated = false;
 }
示例#18
0
        /// <summary>
        /// Process Queue Head
        /// </summary>
        /// <param name="device"></param>
        /// <param name="head"></param>
        public static void ProcessHead(UHCIController controller, UHCIQueueHead *head)
        {
            USBTransfer *transfer = head->Transfer;

            UHCITransmitDescriptor *td = head->Transmit;

            if ((head->Element & ~0xF) == 0)
            {
                transfer->Executed = true;
                transfer->Success  = true;
            }
            else
            {
                if ((td->Control & TD_CONTROL_NAK) > 0)
                {
                }

                if ((td->Control & TD_CONTROL_STALLED) > 0)
                {
                    Console.WriteLine("Stalled");
                    transfer->Executed = true;
                    transfer->Success  = false;
                }


                if ((td->Control & TD_CONTROL_BABBLE) > 0)
                {
                    Console.WriteLine("Control Babble error");
                }


                if ((td->Control & TD_CONTROL_CRC) > 0)
                {
                    Console.WriteLine("CRC Timeout");

                    transfer->Executed = true;
                    transfer->Success  = false;
                }


                if ((td->Control & TD_CONTROL_BITSTUFF) > 0)
                {
                    Console.WriteLine("Bitstuff error");
                }
            }

            if (transfer->Executed)
            {
                //if(transfer->ID > 0)
                //{
                //    PrintQueue(transfer->ID, head);
                //}

                head->Transfer = null;

                /**
                 * We need to toggle endpoint state here
                 */

                /**
                 * Remove head from schedule
                 */
                RemoveHead(controller, head);

                /**
                 * Free transmit descriptors
                 */
                UHCITransmitDescriptor *tdE = td;

                while (tdE != null)
                {
                    UHCITransmitDescriptor *next = tdE->Next;
                    FreeTransmit(controller, tdE);
                    tdE = next;
                }
            }
        }