+ tUHCI_QH *qh;
+ const int qh_offsets[] = {126, 124, 120, 112, 96, 64, 0};
+ const int qh_sizes[] = { 1, 2, 4, 8, 16, 32, 64};
+
+ // Bounds limit
+ if( Period < 0 ) return ;
+ if( Period > 256 ) Period = 256;
+ if( Period == 255 ) Period = 256;
+
+ // Get the log base2 of the period
+ int period_slot = 0;
+ while( Period >>= 1 ) period_slot ++;
+
+ // Adjust for the 4ms minimum period
+ if( period_slot < 2 ) period_slot = 0;
+ else period_slot -= 2;
+
+ // _AppendTD calculates this from qh, but we use it to determine qh
+ TD->_info.QueueIndex = qh_offsets[period_slot];
+ // TODO: Find queue with lowest load
+#if 1
+ int min_load = 0;
+ int min_load_slot = 0;
+ for( int i = 0; i < qh_sizes[period_slot]; i ++ )
+ {
+ int load, index;
+ index = qh_offsets[period_slot] + i;
+ load = 0;
+ while( index >= 0 && index < 127 )
+ {
+ qh = Cont->TDQHPage->InterruptQHs + index;
+ load += Cont->InterruptLoad[index];
+ index = ((qh->Next & ~3) - Cont->PhysTDQHPage)/sizeof(tUHCI_QH);
+ }
+
+ LOG("Slot %i (and below) load %i", qh_offsets[period_slot] + i, load);
+
+ // i = 0 will initialise the values, otherwise update if lower
+ if( i == 0 || load < min_load )
+ {
+ min_load = load;
+ min_load_slot = i;
+ }
+ // - Fast return if no load
+ if( load == 0 ) break;
+ }
+ min_load_slot += qh_offsets[period_slot];
+ TD->_info.QueueIndex = min_load_slot;
+ if( min_load + (TD->Control & 0x7FF) > MAX_INTERRUPT_LOAD )
+ {
+ Log_Warning("UHCI", "Interrupt load on %i ms is too high (slot %i load %i bytes)",
+ 1 << (period_slot+2), min_load_slot, min_load
+ );
+ }
+ Cont->InterruptLoad[min_load_slot] += (TD->Control & 0x7FF);
+#endif
+ qh = Cont->TDQHPage->InterruptQHs + TD->_info.QueueIndex;
+
+ LOG("period_slot = %i, QueueIndex = %i",
+ period_slot, TD->_info.QueueIndex);
+
+ // Stop any errors causing the TD to stop (NAK will error)
+ // - If the device is unplugged, the removal code should remove the interrupt
+ TD->Control &= ~(3 << 27);
+
+ UHCI_int_AppendTD(Cont, qh, TD);