以byte方式讀取SPD的數據(SMBus Controller在PCH中)

Reading A Byte of SMBus EEPROM Data
The following steps have to be followed for the System BIOS to read a byte of the Serial Presence Detect (SPD) data from the DIMM.
1.Program the SMBus Base Address Register, D31:F3:20h.
2.Set the I/O Space enable bit, D31:F3:04h[0].
3.Set the HST_EN bit, D31:F3:40h[0].
4.Clear the status bits by programming SMBBASE 00h to 1Eh.
5.Program the SMBus Transmit Slave Address Register with the DIMM SMBus address, SMBBASE 04h. For example: If the DIMM address is A2h and a byte is to be read from the DIMM, program SMBBASE 04h to A3h (A2h OR’ed with 1 (Read/Write bit)).
6.Program the SMBus Host Command Register with the DIMM’s SPD data offset to be read, SMBBASE 03h. For example: If reading from offset 04h in the DIMM’s SPD, this register will have a value of 04h (Offset of SPD data to be read).
7.Program the SMBus Host Control Register, SMBBASE 02h[7:0] to 48h.
8.Wait on the Host Busy (HOST_BUSY) bit to be clear in the Host Status Register, SMBBASE 00h[0]. The System BIOS should use the INTR bit, SMBBASE 00h[1] and the other error indicator bits in the SMBus Host Status Register to indicate the end of the operation before reading the SMBus data register.
9.After the HOST_BUSY bit is clear, check the DEV_ERR bit in the Host Status Register, SMBBASE 00h[2] = 0, if the HOST_BUSY bit is clear and the DEV_ERR bit is clear the BIOS can read the byte value from the SMBus Data 0 Register, SMBBASE 05h.
Step #1 to Step #3 will be programmed only once. The BIOS can follow Step #4 through Step#9 multiple times to get all the necessary EEPROM data from the SMBus devices.

源码(WIN-TC编译通过):

#include   

#include   

  

unsigned SearchBAR(unsigned long address_s)   

{     

    unsigned long int val;   

    asm mov dx,0xcf8   

    asm db 0x66   

    asm mov ax,address_s   

    asm db 0x66   

    asm out dx,ax   

    asm mov dx,0xcfc   

    asm db 0x66   

    asm in ax,dx   

    asm db 0x66   

    asm mov val,ax   

    return val;   

}   

  

void WriteFlags(unsigned long pci_addr,unsigned data)   

{   

    asm mov dx,0xcf8   

    asm db 0x66      

    asm mov ax,pci_addr   

    asm db 0x66   

    asm out dx,ax   

       

    asm mov dx,0xcfc   

    asm mov al,data   

    asm out dx,al   

}   

  

unsigned ReadByte(unsigned SMBase_addr,unsigned i)   

{   

    unsigned val;   

    outportb(SMBase_addr,0x1e);   

    outportb(SMBase_addr 0x04,0xa7);   

    outportb(SMBase_addr 0x03,i);   

    outportb(SMBase_addr 0x02,0x48);   

    while((inportb(SMBase_addr))&0x01){   

        delay(10);   

    }   

    val=inportb(SMBase_addr 0x05);   

    return val;   

}   

       

void main()     

{     

    unsigned long pci_addr,SMBase_addr,bus,dev,func,offset;   

    unsigned i,data;   

    bus=0x00;   

    dev=0x1f;   

    func=0x03;   

    pci_addr=0x80000000 (bus<<16) (dev<<11) (func<<8);   

    WriteFlags(pci_addr 0x04,0x03);   

    WriteFlags(pci_addr 0x40,0x11);   

       

    SMBase_addr=SearchBAR(pci_addr 0x20)&0xffe0;   

    printf("PCI Address:%x",pci_addr>>16);   

    printf("%x ",pci_addr);   

    printf("use IO :%x ",SMBase_addr);   

    printf("Read Byte: ");   

    for(i=0;i<</SPAN>64;i ){   

        data=ReadByte(SMBase_addr,i);   

        printf("%4x",data);   

        if(i%16==15)   

            printf(" ");   

    }   

       

    getchar();   

}    

转载:http://blog.sina.com.cn/s/blog_870045320102v60u.html

原文地址:https://www.cnblogs.com/chengqi521/p/8027672.html