asm { USE32 SYS_PCIBIOS_SERVICE_DIR:: DU32 0; SYS_PCI_SERVICES:: DU32 0; SYS_FIND_PCIBIOS_SERVICE_DIR:: MOV ESI,0xE0000 MOV ECX,(0x100000-0xE0000)/4 @@05: CMP U32 [ESI],'_32_' JNE @@20 PUSH ECX XOR ECX,ECX MOV CL,U8 9[ESI] SHL ECX,4 @@10: MOV EDI,ESI XOR EAX,EAX XOR EDX,EDX @@15: MOV DL,U8 [EDI] ADD EAX,EDX INC EDI DEC ECX JNZ @@15 POP ECX TEST AL,AL JNZ @@20 MOV U32 [SYS_PCIBIOS_SERVICE_DIR],ESI MOV ESI,U32 4[ESI] MOV U32 [SYS_PCIBIOS_SERVICE_CALL],ESI RET @@20: ADD ESI,4 LOOP @@05 MOV U32 [SYS_PCIBIOS_SERVICE_DIR],0 RET SYS_FIND_PCI_SERVICES:: MOV ESI,U32 [SYS_PCIBIOS_SERVICE_DIR] TEST ESI,ESI JNZ @@05 MOV U32 [SYS_PCI_SERVICES],0 RET @@05: MOV EAX,'$PCI' XOR EBX,EBX DU8 0x9A; //CALL CGDT.cs32:PCIBIOS_SERVICE SYS_PCIBIOS_SERVICE_CALL:: DU32 0; DU16 CGDT.cs32; TEST AL,AL JNZ @@05 LEA ESI,U32 [EBX+EDX] MOV U32 [SYS_PCI_SERVICES],ESI RET @@05: MOV U32 [SYS_PCI_SERVICES],0 RET USE64 C32_EAX:: DU32 0; C32_EBX:: DU32 0; C32_ECX:: DU32 0; C32_EDX:: DU32 0; C32_ESI:: DU32 0; C32_EDI:: DU32 0; C32_EFLAGS:: DU32 0; C32_RSP:: DU64 0; _FAR_CALL32:: //This calls a 32-bit mode routine. //(We must switch from 64-bit mode to do it.) // //NON REENTRANT // PUSH RBP MOV RBP,RSP MOV RAX,U64 SF_ARG1[RBP] TEST RAX,RAX JNZ @@05 POP RBP RET1 8 //return FALSE @@05: MOV U32 [C32_ADD],EAX PUSH_REGS PUSHFD XOR RAX,RAX PUSH U64 FS:CTask.addr[RAX] PUSH U64 GS:CCPU.addr[RAX] MOV U64 [C32_RSP],RSP PUSH U32 CGDT.ds //STKSEG PUSH U32 BOOT_RAM_LIMIT //STK PUSH U32 0 //FLAGS--interrupts off PUSH U32 CGDT.cs32 LEA RAX,[@@15] PUSH RAX IRET USE32 @@15: WBINVD //disable paging MOV_EAX_CR0 BTR EAX,31 MOV_CR0_EAX MOV ECX,IA32_EFER XOR EDX,EDX XOR EAX,EAX WRMSR MOV AX,CGDT.ds MOV FS,AX MOV GS,AX //SS already set MOV EAX,U32 [C32_EAX] MOV EBX,U32 [C32_EBX] MOV ECX,U32 [C32_ECX] MOV EDX,U32 [C32_EDX] MOV ESI,U32 [C32_ESI] MOV EDI,U32 [C32_EDI] MOV U32 [C32_EFLAGS],0 DU8 0x9A; //CALL CGDT.cs32:[C32_ADD] C32_ADD:: DU32 0; DU16 CGDT.cs32; PUSHFD POP U32 [C32_EFLAGS] MOV U32 [C32_EAX],EAX MOV U32 [C32_EBX],EBX MOV U32 [C32_ECX],ECX MOV U32 [C32_EDX],EDX MOV U32 [C32_ESI],ESI MOV U32 [C32_EDI],EDI PUSH U32 0 //Return from next call will be 64-bit CALL SYS_ENTER_LONG_MODE USE64 MOV RSP,U64 [C32_RSP] POP RAX CALL SET_GS_BASE POP RAX CALL SET_FS_BASE POPFD POP_REGS XOR RAX,RAX MOV AL,TRUE POP RBP RET1 8 } _extern C32_EAX U32 c32_eax; _extern C32_EBX U32 c32_ebx; _extern C32_ECX U32 c32_ecx; _extern C32_EDX U32 c32_edx; _extern C32_ESI U32 c32_esi; _extern C32_EDI U32 c32_edi; _extern C32_EFLAGS U32 c32_eflags; _extern SYS_PCI_SERVICES U32 sys_pci_services; _extern _FAR_CALL32 Bool FarCall32(U0 (*fp_addr)());//Not reentrant.For PCIBIOS. U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg) {//Read U8 in PCI configspace at bus,dev,fun,reg. I64 res; PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB108; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; if (FarCall32(sys_pci_services)) res=c32_ecx.u8[0]; else res=0xFF; LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD return res; } U16 PCIReadU16(I64 bus,I64 dev,I64 fun,I64 rg) {//Read U16 in PCI configspace at bus,dev,fun,reg. I64 res; PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB109; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; if (FarCall32(sys_pci_services)) res=c32_ecx.u16[0]; else res=0xFFFF; LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD return res; } U32 PCIReadU32(I64 bus,I64 dev,I64 fun,I64 rg) {//Read U32 in PCI configspace at bus,dev,fun,reg. I64 res; PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB10A; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; if (FarCall32(sys_pci_services)) res=c32_ecx; else res=0xFFFFFFFF; LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD return res; } U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val) {//Write U8 in PCI configspace at bus,dev,fun,reg. PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB10B; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; c32_ecx=val; FarCall32(sys_pci_services); LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD } U0 PCIWriteU16(I64 bus,I64 dev,I64 fun,I64 rg,I64 val) {//Write U16 in PCI configspace at bus,dev,fun,reg. PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB10C; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; c32_ecx=val; FarCall32(sys_pci_services); LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD } U0 PCIWriteU32(I64 bus,I64 dev,I64 fun,I64 rg,I64 val) {//Write U32 in PCI configspace at bus,dev,fun,reg. PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB10D; c32_ebx=bus<<8+dev<<3+fun; c32_edi=rg; c32_ecx=val; FarCall32(sys_pci_services); LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD } I64 PCIClassFind(I64 class_code,I64 n) {/*Find bus,dev,fun of Nth class_code dev. class_code is low three bytes n is index starting at zero Return: -1 not found else bus,dev,fun. */ I64 res; PUSHFD CLI while (LBts(&sys_semas[SEMA_FAR_CALL32],0)) Yield; c32_eax=0xB103; c32_esi=n; c32_ecx=class_code; if (FarCall32(sys_pci_services) && !c32_eax.u8[1]) res=c32_ebx.u8[1]<<16+(c32_ebx&0xF8)<<5+c32_ebx&7; else res=-1; LBtr(&sys_semas[SEMA_FAR_CALL32],0); POPFD return res; }