github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/drivers/pci/addr.go (about) 1 package pci 2 3 import "github.com/icexin/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 }