void osd_opl_control(int chip,int reg) { if (Machine->sample_rate == 0) return; if (chip >= MAX_OPLCHIP ) return; tenmicrosec(); outportb(0x388+chip*2,reg); }
void osd_opl_write(int chip,int data) { if (Machine->sample_rate == 0) return; if (chip >=MAX_OPLCHIP ) return; tenmicrosec(); outportb(0x389+chip*2,data); if(chip >= num_used_opl) num_used_opl = chip+1; }
static void FMSynth_opl_control(int chip, int reg) { #if defined(_M_IX86) if (enabled) { if (chip >= MAX_OPLCHIP) return; tenmicrosec(); _outp((unsigned short)(0x388 + chip * 2), reg); } #endif }
static void FMSynth_opl_write(int chip, int data) { #if defined(_M_IX86) if (enabled) { if (chip >= MAX_OPLCHIP) return; tenmicrosec(); _outp((unsigned short)(0x389 + chip * 2), data); if (chip >= num_used_opl) num_used_opl = chip + 1; } #endif }
/* * handler for APIC Error interrupt. Just print a warning and continue */ int apic_error_intr() { uint_t error0, error1, error; uint_t i; /* * We need to write before read as per 7.4.17 of system prog manual. * We do both and or the results to be safe */ error0 = apic_reg_ops->apic_read(APIC_ERROR_STATUS); apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0); error1 = apic_reg_ops->apic_read(APIC_ERROR_STATUS); error = error0 | error1; /* * Clear the APIC error status (do this on all cpus that enter here) * (two writes are required due to the semantics of accessing the * error status register.) */ apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0); apic_reg_ops->apic_write(APIC_ERROR_STATUS, 0); /* * Prevent more than 1 CPU from handling error interrupt causing * double printing (interleave of characters from multiple * CPU's when using prom_printf) */ if (lock_try(&apic_error_lock) == 0) return (error ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED); if (error) { #if DEBUG if (apic_debug) debug_enter("pcplusmp: APIC Error interrupt received"); #endif /* DEBUG */ if (apic_panic_on_apic_error) cmn_err(CE_PANIC, "APIC Error interrupt on CPU %d. Status = %x", psm_get_cpu_id(), error); else { if ((error & ~APIC_CS_ERRORS) == 0) { /* cksum error only */ apic_error |= APIC_ERR_APIC_ERROR; apic_apic_error |= error; apic_num_apic_errors++; apic_num_cksum_errors++; } else { /* * prom_printf is the best shot we have of * something which is problem free from * high level/NMI type of interrupts */ prom_printf("APIC Error interrupt on CPU %d. " "Status 0 = %x, Status 1 = %x\n", psm_get_cpu_id(), error0, error1); apic_error |= APIC_ERR_APIC_ERROR; apic_apic_error |= error; apic_num_apic_errors++; for (i = 0; i < apic_error_display_delay; i++) { tenmicrosec(); } /* * provide more delay next time limited to * roughly 1 clock tick time */ if (apic_error_display_delay < 500) apic_error_display_delay *= 2; } } lock_clear(&apic_error_lock); return (DDI_INTR_CLAIMED); } else { lock_clear(&apic_error_lock); return (DDI_INTR_UNCLAIMED); } }
void microfind(void) { uint64_t max, count = MICROCOUNT; /* * The algorithm tries to guess a loop count for tenmicrosec such * that found will be 0xf000 PIT counts, but because it is only a * rough guess there is no guarantee that tenmicrosec will take * exactly 0xf000 PIT counts. min is set initially to 0xe000 and * represents the number of PIT counts that must elapse in * tenmicrosec for microfind to calculate the correct loop count for * tenmicrosec. The algorith will successively set count to better * approximations until the number of PIT counts elapsed are greater * than min. Ideally the first guess should be correct, but as cpu's * become faster MICROCOUNT may have to be increased to ensure * that the first guess for count is correct. There is no harm * leaving MICRCOUNT at 0x2000, the results will be correct, it just * may take longer to calculate the correct value for the loop * count used by tenmicrosec. In some cases min may be reset as the * algorithm progresses in order to facilitate faster cpu's. */ unsigned long found, min = 0xe000; ulong_t s; unsigned char status; s = clear_int_flag(); /* disable interrupts */ /*CONSTCOND*/ while (1) { /* * microdata is the loop count used in tenmicrosec. The first * time around microdata is set to 1 to make tenmicrosec * return quickly. The purpose of this while loop is to * warm the cache for the next time around when the number * of PIT counts are measured. */ microdata = 1; /*CONSTCOND*/ while (1) { /* Put counter 0 in mode 0 */ outb(PITCTL_PORT, PIT_LOADMODE); /* output a count of -1 to counter 0 */ outb(PITCTR0_PORT, 0xff); outb(PITCTR0_PORT, 0xff); tenmicrosec(); /* READ BACK counter 0 to latch status and count */ outb(PITCTL_PORT, PIT_READBACK|PIT_READBACKC0); /* Read status of counter 0 */ status = inb(PITCTR0_PORT); /* Read the value left in the counter */ found = inb(PITCTR0_PORT) | (inb(PITCTR0_PORT) << 8); if (microdata != 1) break; microdata = count; } /* verify that the counter began the count-down */ if (status & (1 << PITSTAT_NULLCNT)) { /* microdata is too small */ count = count << 1; /* * If the cpu is so fast that it cannot load the * counting element of the PIT with a very large * value for the loop used in tenmicrosec, then * the algorithm will not work for this cpu. * It is very unlikely there will ever be such * an x86. */ if (count > 0x100000000) panic("microfind: cpu is too fast"); continue; } /* verify that the counter did not wrap around */ if (status & (1 << PITSTAT_OUTPUT)) { /* * microdata is too large. Since there are counts * that would have been appropriate for the PIT * not to wrap on even a lowly AT, count will never * decrease to 1. */ count = count >> 1; continue; } /* mode 0 is an n + 1 counter */ found = 0x10000 - found; if (found > min) break; /* verify that the cpu is slow enough to count to 0xf000 */ count *= 0xf000; max = 0x100000001 * found; /* * It is possible that at some point cpu's will become * sufficiently fast such that the PIT will not be able to * count to 0xf000 within the maximum loop count used in * tenmicrosec. In that case the loop count in tenmicrosec * may be set to the maximum value because it is unlikely * that the cpu will be so fast that tenmicrosec with the * maximum loop count will take more than ten microseconds. * If the cpu is indeed too fast for the current * implementation of tenmicrosec, then there is code below * intended to catch that situation. */ if (count >= max) { /* cpu is fast, just make it count as high it can */ count = 0x100000000; min = 0; continue; } /* * Count in the neighborhood of 0xf000 next time around * There is no risk of dividing by zero since found is in the * range of 0x1 to 0x1000. */ count = count / found; }