public virtual void ServiceTasks(uint curTicks, LinkTaskKind taskAction) { }
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; } } } }