static errno_t ps2ms_purge_buffer(int msec) { errno_t rc = ENODEV; //int tries = 10000; //bigtime_t start = hal_system_time() / 1000; // Purge buffer while( msec-- > 0 ) { if( inb( PS2_CTRL_ADDR ) & 0x01 ) { int b = inb( PS2_DATA_ADDR ) & 0xFFu; (void) b; SHOW_FLOW( 10 ,"purge 0x%2X ", b ); rc = 0; } //bigtime_t now = hal_system_time() / 1000; //if( now+msec > start ) break; phantom_spinwait(1); } return rc; }
errno_t acpi_reboot(void) { ACPI_STATUS status; status = AcpiReset(); if (status == AE_NOT_EXIST) return ENXIO; if (status != AE_OK) { SHOW_ERROR( 0, "Reset failed, status = %d", status ); return ENXIO; } phantom_spinwait(10000); // 10 sec SHOW_ERROR0( 0, "Reset failed, timeout" ); return ENXIO; }
static errno_t send_ipi(unsigned int dst, unsigned int v) { int to, send_status; IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (dst << 24)); IMPS_LAPIC_WRITE(LAPIC_ICR, v); /* Wait for send to finish */ to = 0; do { // TODO return to uSec spinwait //UDELAY(100); phantom_spinwait(1); send_status = IMPS_LAPIC_READ(LAPIC_ICR) & LAPIC_ICR_STATUS_PEND; } while (send_status && (to++ < 1000)); return (to < 1000) ? ETIMEDOUT : 0; }
static int boot_cpu(imps_processor *proc) { int apicid = proc->apic_id, success = 1, to; unsigned accept_status; unsigned bios_reset_vector = (int)PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR); int ver = IMPS_LAPIC_READ(LAPIC_VER); SHOW_FLOW( 0, "APIC ver = 0x%x (%d)", ver, APIC_VERSION(ver) ); // TODO define size? guard page? ap_stack = calloc(1, 64*1024); /* * Copy boot code for secondary CPUs here. Find it in between * "patch_code_start" and "patch_code_end" symbols. The other CPUs * will start there in 16-bit real mode under the 1MB boundary. * "patch_code_start" should be placed at a 4K-aligned address * under the 1MB boundary. */ //return 0; //panic("boot SMP cpu code is not ready"); //extern char patch_code_start[]; //extern char patch_code_end[]; //bootaddr = (512-64)*1024; //memcpy((char *)bootaddr, patch_code_start, patch_code_end - patch_code_start); install_ap_tramp((void *)bootaddr); smp_ap_booted = 0; //dump_mp_gdt((void *)&MP_GDT); /* * Generic CPU startup sequence starts here. */ /* set BIOS reset vector */ CMOS_WRITE_BYTE(CMOS_RESET_CODE, CMOS_RESET_JUMP); //*((volatile unsigned *) bios_reset_vector) = ((bootaddr & 0xFF000) << 12); //*((volatile unsigned *) bios_reset_vector) = ((bootaddr & 0xFF000) << 12); *((volatile unsigned short *) 0x469) = bootaddr >> 4; *((volatile unsigned short *) 0x467) = bootaddr & 0xf; /* clear the APIC error register */ IMPS_LAPIC_WRITE(LAPIC_ESR, 0); accept_status = IMPS_LAPIC_READ(LAPIC_ESR); /* assert INIT IPI */ send_ipi(apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT); //UDELAY(10000); phantom_spinwait(10); /* de-assert INIT IPI */ send_ipi(apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT); phantom_spinwait(10); //UDELAY(10000); #if 1 /* * Send Startup IPIs if not an old pre-integrated APIC. */ if (proc->apic_ver >= APIC_VER_NEW) { int i; for (i = 1; i <= 2; i++) { send_ipi(apicid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF)); //UDELAY(1000); phantom_spinwait(1); } }