FreeBSD/sys/x86/x86/local_apic.c
/*
 * Request 'count' free contiguous IDT vectors to be used by 'count'
 * IRQs.  'count' must be a power of two and the vectors will be
 * aligned on a boundary of 'align'.  If the request cannot be
 * satisfied, 0 is returned.
 */
Request 'count' free contiguous IDT vectors to be used by 'count'
IRQs.  'count' must be a power of two and the vectors will be
aligned on a boundary of 'align'.  If the request cannot be
satisfied, 0 is returned.
Request ' count ' free contiguous IDT vectors to be used by ' count ' IRQs . ' count ' must be a power of two and the vectors will be aligned on a boundary of ' align ' . If the request cannot be satisfied 0 is returned .
static u_int
native_apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
{
	u_int first, run, vector;
	KASSERT(powerof2(count), ("bad count"));
	KASSERT(powerof2(align), ("bad align"));
	KASSERT(align >= count, ("align < count"));
#ifdef INVARIANTS
	for (run = 0; run < count; run++)
		KASSERT(irqs[run] < NUM_IO_INTS, ("Invalid IRQ %u at index %u",
		    irqs[run], run));
#endif
	run = 0;
	first = 0;
	mtx_lock_spin(&icu_lock);
	for (vector = 0; vector < APIC_NUM_IOINTS; vector++) {
		if (lapics[apic_id].la_ioint_irqs[vector] != -1) {
			run = 0;
			first = 0;
			continue;
		}
		if (run == 0) {
			if ((vector & (align - 1)) != 0)
				continue;
			first = vector;
		}
		run++;
		if (run < count)
			continue;
		for (vector = 0; vector < count; vector++)
			lapics[apic_id].la_ioint_irqs[first + vector] =
			    irqs[vector];
		mtx_unlock_spin(&icu_lock);
		return (first + APIC_IO_INTS);
	}
	mtx_unlock_spin(&icu_lock);
	printf("APIC: Couldn't find APIC vectors for %u IRQs\n", count);
	return (0);
}
static u_int native_apic_alloc_vectors ( u_int apic_id , u_int * irqs , u_int count , u_int align ) { u_int first , run , vector ; KASSERT ( powerof2 ( count ) , ( " " ) ) ; KASSERT ( powerof2 ( align ) , ( " " ) ) ; KASSERT ( align >= count , ( " " ) ) ; #ifdef INVARIANTS for ( run = 0 ; run < count ; run ++ ) KASSERT ( irqs [ run ] < NUM_IO_INTS , ( " " , irqs [ run ] , run ) ) ; #endif run = 0 ; first = 0 ; mtx_lock_spin ( & icu_lock ) ; for ( vector = 0 ; vector < APIC_NUM_IOINTS ; vector ++ ) { if ( lapics [ apic_id ] . la_ioint_irqs [ vector ] != -1 ) { run = 0 ; first = 0 ; continue ; } if ( run == 0 ) { if ( ( vector & ( align - 1 ) ) != 0 ) continue ; first = vector ; } run ++ ; if ( run < count ) continue ; for ( vector = 0 ; vector < count ; vector ++ ) lapics [ apic_id ] . la_ioint_irqs [ first + vector ] = irqs [ vector ] ; mtx_unlock_spin ( & icu_lock ) ; return ( first + APIC_IO_INTS ) ; } mtx_unlock_spin ( & icu_lock ) ; printf ( " \n " , count ) ; return ( 0 ) ; }
Request 'count' free contiguous IDT vectors to be used by 'count'
 IRQs.
Request ' count ' free contiguous IDT vectors to be used by ' count ' IRQs .
/*
	 * Search for 'count' free vectors.  As with apic_alloc_vector(),
	 * this just uses a simple first fit algorithm.
	 */ /* Vector is in use, end run. */ /* Start a new run if run == 0 and vector is aligned. */ /* Keep looping if the run isn't long enough yet. */ /* Found a run, assign IRQs and return the first vector. */