github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/drivers/pci/addr.go (about)

     1  package pci
     2  
     3  import "github.com/jspc/eggos/kernel/sys"
     4  
     5  const (
     6  	configAddrPort = 0xcf8
     7  	configDataPort = 0xcfc
     8  )
     9  
    10  type Address struct {
    11  	Bus, Device, Func uint8
    12  }
    13  
    14  func (a Address) ReadBAR(bar uint8) (addr, len uint32, prefetch, isMem bool) {
    15  	if bar > 0x5 {
    16  		panic("invalid BAR")
    17  	}
    18  	reg := 0x10 + bar*4
    19  	addr0 := a.ReadPCIRegister(reg)
    20  	if addr0&1 != 0 {
    21  		// I/O address.
    22  		return uint32(addr0 &^ 0b11), 0, false, false
    23  	}
    24  	// Mask off flags.
    25  	addr = uint32(addr0 &^ 0xf)
    26  	switch (addr0 >> 1) & 0b11 {
    27  	case 0b01:
    28  		// 16-bit address. Not used.
    29  		return 0, 0, false, false
    30  	case 0b10:
    31  		// 64-bit address.
    32  		return 0, 0, false, false
    33  	case 0b00:
    34  		a.WritePCIRegister(reg, 0xffffffff)
    35  		len = ^(a.ReadPCIRegister(reg) & 0xfffffff0) + 1
    36  		a.WritePCIRegister(reg, addr0)
    37  	}
    38  	prefetch = addr0&0b1000 != 0
    39  	return addr, len, prefetch, true
    40  }
    41  
    42  func (a Address) ReadCapOffset() uint8 {
    43  	return uint8(a.ReadPCIRegister(0x34)) &^ 0x3
    44  }
    45  
    46  func (a Address) ReadStatus() uint16 {
    47  	return uint16(a.ReadPCIRegister(0x4) >> 16)
    48  }
    49  
    50  func (a Address) ReadDeviceID() uint16 {
    51  	return uint16(a.ReadPCIRegister(0x0) >> 16)
    52  }
    53  
    54  func (a Address) ReadVendorID() uint16 {
    55  	return uint16(a.ReadPCIRegister(0x0))
    56  }
    57  
    58  func (a Address) readHeaderType() uint8 {
    59  	return uint8(a.ReadPCIRegister(0xc) >> 16)
    60  }
    61  
    62  func (a Address) ReadPCIClass() uint16 {
    63  	return uint16(a.ReadPCIRegister(0x8) >> 16)
    64  }
    65  
    66  func (a Address) ReadIRQLine() uint8 {
    67  	return uint8(a.ReadPCIRegister(0x3C) & 0xff)
    68  }
    69  
    70  func (a Address) EnableBusMaster() {
    71  	a.WritePCIRegister(0x04, a.ReadPCIRegister(0x04)|(1<<2))
    72  }
    73  
    74  func (a Address) readSecondaryBus() uint8 {
    75  	return uint8(a.ReadPCIRegister(0x18) >> 8)
    76  }
    77  
    78  func (a Address) ReadPCIRegister(reg uint8) uint32 {
    79  	if reg&0x3 != 0 {
    80  		panic("unaligned PCI register access")
    81  	}
    82  	addr := 0x80000000 | uint32(a.Bus)<<16 | uint32(a.Device)<<11 | uint32(a.Func)<<8 | uint32(reg)
    83  	sys.Outl(configAddrPort, addr)
    84  	return sys.Inl(configDataPort)
    85  }
    86  
    87  func (a Address) WritePCIRegister(reg uint8, val uint32) {
    88  	if reg&0x3 != 0 {
    89  		panic("unaligned PCI register access")
    90  	}
    91  	addr := 0x80000000 | uint32(a.Bus)<<16 | uint32(a.Device)<<11 | uint32(a.Func)<<8 | uint32(reg)
    92  	sys.Outl(configAddrPort, addr)
    93  	sys.Outl(configDataPort, val)
    94  }