Esempio n. 1
0
 public virtual void ServiceTasks(uint curTicks, LinkTaskKind taskAction)
 {
 }
Esempio n. 2
0
        public override void ServiceTasks(uint curTicks, LinkTaskKind taskAction)
        {
            IsoTask t, s;
            int     h, j, k, ioIndex;
            byte    r;
            bool    checkSchedule = false, checkRemove = false;
            uint    elapsedTicks;

            if (NumTasks == 0)
            {
                return;
            }
            if (taskAction == LinkTaskKind.Reset)
            {
                ResetLinkTasks();
                return;
            }
            elapsedTicks       = curTicks - LastIsoUpdateTicks;
            LastIsoUpdateTicks = curTicks;
            for (k = 0; k < NumTasks; k++)
            {
                t = IsoTasks[IsoTaskQueue[k]];
                if (elapsedTicks >= t.msTicksRelativeToGo)        // Perform this task.
                {
                    do
                    {
                        bool isIsoMsg = (t.cmd == ProtocolConstants.MEDIATOR_DEVICE_ISOMSG);
                        if (isIsoMsg)
                        {
                            ioIndex = CopyMessage(t.ioIndex, 0);
                            if (ioIndex == -1)
                            {
                                break;
                            }
                        }
                        else
                        {
                            ioIndex = t.ioIndex;
                        }
                        MessageTransaction bmc = new MessageTransaction(Manager);
                        j = bmc.StartMessageTransaction(t.ioIndex);
                        if (j != 0)
                        {
                            break;
                        }
                        bmc.TaskCmd = (byte)t.cmd;
                        j           = t.ownerDriver.CommandHandler(bmc);
                        if (j != 0)
                        {
                            break;
                        }
                        // Make a copy before its finalised.
                        if (!isIsoMsg)
                        {
                            byte pktLen = (byte)(ProtocolConstants.GENERAL_OVERHEADS_SIZE + bmc.MsgBuffer.dataLength());
                            ioIndex = CopyMessage(t.ioIndex, pktLen);
                            if (ioIndex == -1)
                            {
                                break;
                            }
                            t.ioIndex     = ioIndex;
                            bmc.ReturnCmd = bmc.TaskCmd;
                        }
                        bmc.FinishMessageTransaction();
                    } while(false);
                    // Check if task to be removed.
                    if (t.repeatCount > 0)
                    {
                        if (--t.repeatCount == 0)
                        {
                            // Free message buffer.
                            Manager.IoBuffersFreeHeap.Release(t.ioIndex);
                            t.ioIndex = -1;
                            // Mark task for later removal.
                            t.state     = IsoRemove;
                            checkRemove = true;
                        }
                    }
                    if ((t.state & IsoRemove) == 0)
                    {
                        // Mark task as requiring rescheduling.
                        t.state      |= IsoReschedule;
                        checkSchedule = true;
                    }
                    // Update elapsedTicks:
                    elapsedTicks -= t.msTicksRelativeToGo;
                }
                else
                {
                    t.msTicksRelativeToGo -= elapsedTicks;
                    break;
                }
            }
            if (checkRemove)
            {
                r = 0;
                for (k = 0; k < NumTasks; k++)
                {
                    j = IsoTaskQueue[k];
                    if (IsoTasks[j].ioIndex != -1)
                    {
                        IsoTaskQueue[r++] = j;
                    }
                }
                NumTasks = r;
            }
            if (checkSchedule)                 // Reschedule tasks.
            {
                for (j = 0; j < NumTasks; j++) // Find first task that doesn't require rescheduling.
                {
                    if ((IsoTasks[IsoTaskQueue[j]].state & IsoReschedule) == 0)
                    {
                        break;
                    }
                }
                for (k = j - 1; k >= 0; k--)
                {
                    t       = IsoTasks[IsoTaskQueue[k]];
                    t.state = 0;
                    t.msTicksRelativeToGo = t.msInterval - 1; // Note, minus one because 1 tick used during scheduling.
                    r = (byte)k;
                    do                                        // Ripple current task down Q until position found.
                    {
                        if ((r + 1) == NumTasks)              // Check next not past end.
                        {
                            break;
                        }
                        s = IsoTasks[IsoTaskQueue[r + 1]];
                        if (t.msTicksRelativeToGo < s.msTicksRelativeToGo)   // '<' for fairness.
                        {
                            s.msTicksRelativeToGo -= t.msTicksRelativeToGo;
                            break;
                        }
                        // Find location deeper in schedule.
                        t.msTicksRelativeToGo -= s.msTicksRelativeToGo;
                        // Swap over tasks in Q.
                        h = IsoTaskQueue[r];
                        IsoTaskQueue[r]     = IsoTaskQueue[r + 1];
                        IsoTaskQueue[r + 1] = h;
                        ++r;
                    } while(r < NumTasks);
                    if (k == 0)
                    {
                        break;
                    }
                }
            }
        }