📄 pcmb_smp.c
字号:
CYG_BYTE id; char bustype[7]; HAL_READMEM_UINT8( entry+MPCT_ENTRY_BUS_ID, id );#if SHOW_DIAGNOSTICS diag_printf(" Bus\n"); diag_printf(" ID: %02x\n",id);#endif { int i; for( i = 0; i < 6; i++ ) { HAL_READMEM_UINT8( entry+MPCT_ENTRY_BUS_TYPE_STRING+i, val8 ); bustype[i] = val8; } bustype[i] = 0;#if SHOW_DIAGNOSTICS diag_printf(" Type: %s\n",&bustype[0]);#endif } if( streq( bustype, "ISA " ) ) { cyg_hal_isa_bus_id = id; for( i = 0; i < 16; i++ ) cyg_hal_isa_bus_irq[i] = 100; } if( streq( bustype, "PCI " ) ) { cyg_hal_pci_bus_id = id; } } entry += MPCT_ENTRY_BUS_SIZE; break; case MPCT_ENTRY_TYPE_IOAPIC:#if SHOW_DIAGNOSTICS diag_printf(" I/O APIC\n"); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOAPIC_ID, val8 ); diag_printf(" ID: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOAPIC_VER, val8 ); diag_printf(" Version: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOAPIC_FLAGS, val8 ); diag_printf(" Flags: %02x\n",val8); HAL_READMEM_UINT32( entry+MPCT_ENTRY_IOAPIC_ADDRESS, val32 ); diag_printf(" Address: %08x\n",val32);#endif HAL_READMEM_UINT32( entry+MPCT_ENTRY_IOAPIC_ADDRESS, cyg_hal_smp_io_apic ); entry += MPCT_ENTRY_IOAPIC_SIZE; break; case MPCT_ENTRY_TYPE_INTERRUPT_IO: { CYG_BYTE bus, irq, dst; HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_SOURCE_BUS, bus ); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_SOURCE_IRQ, irq ); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_DEST_INT, dst );#if SHOW_DIAGNOSTICS diag_printf(" I/O interrupt assignment\n"); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_TYPE, val8 ); diag_printf(" Type: %02x\n",val8); HAL_READMEM_UINT16( entry+MPCT_ENTRY_IOINT_TYPE, val16 ); diag_printf(" Flags: %04x\n",val16); diag_printf(" Source bus: %02x\n",bus); diag_printf(" Source IRQ: %02x\n",irq); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_DEST_APIC, val8 ); diag_printf(" Dest APIC: %02x\n",val8); diag_printf(" Dest Interrupt: %02x\n",dst);#endif if( bus == cyg_hal_isa_bus_id ) cyg_hal_isa_bus_irq[irq] = dst;// if( bus == cyg_hal_pci_bus_id )// cyg_hal_pci_bus_irq[irq] = dst; } entry += MPCT_ENTRY_IOINT_SIZE; break; case MPCT_ENTRY_TYPE_INTERRUPT_LOCAL:#if SHOW_DIAGNOSTICS diag_printf(" Local interrupt assignment\n"); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_TYPE, val8 ); diag_printf(" Type: %02x\n",val8); HAL_READMEM_UINT16( entry+MPCT_ENTRY_IOINT_TYPE, val16 ); diag_printf(" Flags: %04x\n",val16); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_SOURCE_BUS, val8 ); diag_printf(" Source bus: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_SOURCE_IRQ, val8 ); diag_printf(" Source IRQ: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_DEST_APIC, val8 ); diag_printf(" Dest APIC: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_IOINT_DEST_INT, val8 ); diag_printf(" Dest Interrupt: %02x\n",val8);#endif entry += MPCT_ENTRY_LOCINT_SIZE; break; default:#if SHOW_DIAGNOSTICS diag_printf(" MPCT Entry: unknown type %02x\n",type);#endif entry += 8; break; } } } }#if SHOW_DIAGNOSTICS diag_printf("Exported configuration:\n"); diag_printf(" Local APIC: %08x\n", cyg_hal_smp_local_apic ); diag_printf(" I/O APIC: %08x\n", cyg_hal_smp_io_apic ); diag_printf(" CPU count: %d\n", cyg_hal_smp_cpu_count ); for( i = 0; i < cyg_hal_smp_cpu_count; i++ ) { diag_printf(" CPU %d %sactive %s\n",i, ((cyg_hal_smp_cpu_flags[i]&1)?"":"in"), ((cyg_hal_smp_cpu_flags[i]&2)?"master":"slave") ); } diag_printf(" ISA IRQ map:\n"); for( i = 0; i < 16; i++ ) { diag_printf(" IRQ %2d -> IOAPIC INT %2d\n",i,cyg_hal_isa_bus_irq[i]); } #endif return 1;}/*------------------------------------------------------------------------*/// Init local APICstatic cyg_bool cyg_hal_smp_init_apic(void){ cyg_uint32 maxlvt; cyg_uint32 val; HAL_SMP_CPU_TYPE cpu; HAL_APIC_READ(HAL_APIC_ID, val ); cpu = val>>24; #if SHOW_DIAGNOSTICS diag_printf("Local APIC: %08x\n",cyg_hal_smp_local_apic); diag_printf(" ID: %08x\n",val);#endif // get max local vector table entry offset HAL_APIC_READ(HAL_APIC_VER, maxlvt );#if SHOW_DIAGNOSTICS diag_printf(" VERSION: %08x\n",maxlvt);#endif maxlvt >>= 16; maxlvt &= 0xFF; #if SHOW_DIAGNOSTICS diag_printf("maxlvt = %d\n",maxlvt);#endif // Start by ensuring that all interrupt sources are disabled. The // following code ensures that this happens cleanly. // Local timer vector HAL_APIC_READ( HAL_APIC_LVT_TIMER, val ); val |= HAL_APIC_LVT_MASK ; HAL_APIC_WRITE( HAL_APIC_LVT_TIMER, val );#if SHOW_DIAGNOSTICS diag_printf(" APIC_LVT_TIMER: %08x\n",val);#endif // Local interrupt vectors HAL_APIC_READ( HAL_APIC_LVT_INT0, val ); val |= HAL_APIC_LVT_MASK ; HAL_APIC_WRITE( HAL_APIC_LVT_INT0, val );#if SHOW_DIAGNOSTICS diag_printf(" APIC_LVT_INT0: %08x\n",val);#endif HAL_APIC_READ( HAL_APIC_LVT_INT1, val ); val |= HAL_APIC_LVT_MASK ; HAL_APIC_WRITE( HAL_APIC_LVT_INT1, val );#if SHOW_DIAGNOSTICS diag_printf(" APIC_LVT_INT1: %08x\n",val);#endif if (maxlvt >= 3 ) { HAL_APIC_READ( HAL_APIC_LVT_ERROR, val ); val |= HAL_APIC_LVT_MASK ; HAL_APIC_WRITE( HAL_APIC_LVT_ERROR, val );#if SHOW_DIAGNOSTICS diag_printf(" APIC_LVT_ERROR: %08x\n",val);#endif } if (maxlvt >= 4 ) { HAL_APIC_READ( HAL_APIC_LVT_PC, val ); val |= HAL_APIC_LVT_MASK ; HAL_APIC_WRITE( HAL_APIC_LVT_PC, val );#if SHOW_DIAGNOSTICS diag_printf(" APIC_LVT_PC: %08x\n",val);#endif } // Now initialize the local vector table. HAL_APIC_WRITE( HAL_APIC_LVT_TIMER, HAL_APIC_LVT_MASK ); HAL_APIC_WRITE( HAL_APIC_LVT_INT0, HAL_APIC_LVT_MASK ); HAL_APIC_WRITE( HAL_APIC_LVT_INT1, HAL_APIC_LVT_MASK ); if( maxlvt >= 3 ) HAL_APIC_WRITE( HAL_APIC_LVT_ERROR, HAL_APIC_LVT_MASK ); if( maxlvt >= 4 ) HAL_APIC_WRITE( HAL_APIC_LVT_PC, HAL_APIC_LVT_MASK ); // Set up DFR to flat delivery mode. HAL_APIC_WRITE( HAL_APIC_DFR, 0xffffffff ); // Set up logical destination id. We set bit 1<<cpuid in the LDR // register. HAL_APIC_READ( HAL_APIC_LDR, val ); val |= 1<<(cpu+24); HAL_APIC_WRITE( HAL_APIC_LDR, val ); // Set TPR register to accept all. HAL_APIC_WRITE( HAL_APIC_TPR, 0 ); // Enable APIC in SPIV HAL_APIC_WRITE( HAL_APIC_SPIV, 0x00000100 ); if( cyg_hal_smp_cpu_flags[HAL_SMP_CPU_THIS()] & 2 ) { // This is the boot CPU, switch its PIC into APIC mode // Non-boot CPUs are already in APIC mode. HAL_WRITE_UINT8( 0x22, 0x70 ); HAL_WRITE_UINT8( 0x23, 0x01 ); } return 1;}/*------------------------------------------------------------------------*/// Initialize I/O APICstatic cyg_bool cyg_hal_smp_init_ioapic(void){ CYG_WORD32 val; cyg_uint32 tabsize = 0; int i; HAL_SMP_CPU_TYPE cpu_this = HAL_SMP_CPU_THIS(); HAL_SPINLOCK_CLEAR( cyg_hal_ioapic_lock ); HAL_SPINLOCK_SPIN( cyg_hal_ioapic_lock ); HAL_IOAPIC_READ( HAL_IOAPIC_REG_APICVER, val ); tabsize = (val>>16)&0xFF; // Set up ISA interrupts for( i = 0; i < 16; i++ ) { if( cyg_hal_isa_bus_irq[i] != 100 ) { CYG_WORD32 tehi = 0, telo = 0x00010000; tehi |= cpu_this<<24; telo |= CYGNUM_HAL_ISR_MIN+i; HAL_IOAPIC_WRITE( HAL_IOAPIC_REG_REDIR_LO(cyg_hal_isa_bus_irq[i]), telo ); HAL_IOAPIC_WRITE( HAL_IOAPIC_REG_REDIR_HI(cyg_hal_isa_bus_irq[i]), tehi ); } } #if SHOW_DIAGNOSTICS diag_printf("I/O APIC: %08x\n",cyg_hal_smp_io_apic); HAL_IOAPIC_READ( HAL_IOAPIC_REG_APICID, val ); diag_printf(" ID: %08x\n",val); HAL_IOAPIC_READ( HAL_IOAPIC_REG_APICVER, val ); diag_printf(" VER: %08x\n",val); HAL_IOAPIC_READ( HAL_IOAPIC_REG_APICARB, val ); diag_printf(" ARB: %08x\n",val); diag_printf(" Redirection Table:\n"); for( i = 0; i < tabsize; i++ ) { CYG_WORD32 tehi, telo; HAL_IOAPIC_READ( HAL_IOAPIC_REG_REDIR_LO(i), telo ); HAL_IOAPIC_READ( HAL_IOAPIC_REG_REDIR_HI(i), tehi ); diag_printf(" %02d: %08x %08x\n",i,tehi,telo); }#endif HAL_SPINLOCK_CLEAR( cyg_hal_ioapic_lock ); return 1;}/*------------------------------------------------------------------------*/static volatile CYG_WORD32 init_deasserted;__externC volatile CYG_WORD32 cyg_hal_smp_cpu_sync_flag[HAL_SMP_CPU_MAX];__externC volatile CYG_WORD32 cyg_hal_smp_cpu_sync[HAL_SMP_CPU_MAX];__externC volatile void (*cyg_hal_smp_cpu_entry[HAL_SMP_CPU_MAX])(void);__externC volatile CYG_WORD32 cyg_hal_smp_vsr_sync_flag;__externC volatile CYG_WORD32 cyg_hal_smp_cpu_running[HAL_SMP_CPU_MAX];/*------------------------------------------------------------------------*/__externC void cyg_hal_smp_start(void);__externC CYG_BYTE cyg_hal_slave_trampoline[];__externC CYG_BYTE cyg_hal_slave_trampoline_end[];#define HAL_SLAVE_START_ADDRESS 0x00002000__externC void cyg_hal_cpu_start( HAL_SMP_CPU_TYPE cpu ){#if 1 CYG_WORD32 icrlo, icrhi; CYG_BYTE *p = &cyg_hal_slave_trampoline[0]; CYG_BYTE *q = (CYG_BYTE *)HAL_SLAVE_START_ADDRESS; CYG_BYTE old_cmos; int i; // Copy the trampoline over... do { *q++ = *p++; } while( p != &cyg_hal_slave_trampoline_end[0]); // Init synchronization spinlock to locked to halt slave CPU in // cyg_hal_smp_startup(). init_deasserted = 0; // We now have to execute the grungy and unpleasant AP startup // sequence to get the cpu running. I'm sure that not all of this // is strictly necessary, but it works and it is too much effort // to work out the minimal subset. // Write warm-reset code into CMOS RAM and write the address of // the trampoline entry point into location 40:67. HAL_READ_CMOS( 0x0f, old_cmos ); HAL_WRITE_CMOS( 0x0f, 0x0a ); HAL_WRITEMEM_UINT16( 0x467, HAL_SLAVE_START_ADDRESS & 0xf ); HAL_WRITEMEM_UINT16( 0x469, HAL_SLAVE_START_ADDRESS>>4 ); // Send an INIT interrupt to the dest CPU icrhi = cpu<<24; icrlo = 0x0000C500; HAL_APIC_WRITE( HAL_APIC_ICR_HI, icrhi ); HAL_APIC_WRITE( HAL_APIC_ICR_LO, icrlo ); hal_delay_us( 10 * 1000 ); // Wait 10ms // Wait for the ICR to become inactive do { HAL_APIC_READ( HAL_APIC_ICR_LO, icrlo ); } while( (icrlo & 0x00001000) != 0 ); // Now de-assert INIT icrlo = 0x00008500; HAL_APIC_WRITE( HAL_APIC_ICR_HI, icrhi ); HAL_APIC_WRITE( HAL_APIC_ICR_LO, icrlo ); init_deasserted = 1; // Now we send two STARTUP IPIs for( i = 0; i < 2; i++ ) { icrlo = 0x00000600 | (HAL_SLAVE_START_ADDRESS>>12); // Send the STARTUP IPI HAL_APIC_WRITE( HAL_APIC_ICR_HI, icrhi ); HAL_APIC_WRITE( HAL_APIC_ICR_LO, icrlo ); hal_delay_us( 300 ); // Wait for the ICR to become inactive do { HAL_APIC_READ( HAL_APIC_ICR_LO, icrlo ); } while( (icrlo & 0x00001000) != 0 ); hal_delay_us( 300 ); } HAL_WRITE_CMOS( 0x0f, old_cmos );// PC_WRITE_SCREEN( PC_SCREEN_LINE(5)+0, '!' ); hal_delay_us( 300 ); // PC_WRITE_SCREEN( PC_SCREEN_LINE(5)+1, '!' ); #endif }/*------------------------------------------------------------------------*/__externC void cyg_hal_smp_start(void);__externC void cyg_hal_smp_startup(void);__externC void cyg_hal_cpu_release( HAL_SMP_CPU_TYPE cpu ){// PC_WRITE_SCREEN( PC_SCREEN_LINE(13), '!' ); // PC_WRITE_SCREEN_8( PC_SCREEN_LINE(13), cpu ); cyg_hal_smp_cpu_entry[cpu] = cyg_hal_smp_start; while( cyg_hal_smp_cpu_entry[cpu] != 0 ) {// PC_WRITE_SCREEN_32( PC_SCREEN_LINE(13)+4, cyg_hal_smp_cpu_entry[cpu] ); hal_delay_us( 100 ); continue; }}/*------------------------------------------------------------------------*/__externC void cyg_hal_smp_startup(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -