github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/drivers/e1000/e1000.go (about) 1 package e1000 2 3 import ( 4 "errors" 5 "sync/atomic" 6 "time" 7 "unsafe" 8 9 "github.com/jspc/eggos/drivers/pci" 10 "github.com/jspc/eggos/drivers/pic" 11 "github.com/jspc/eggos/inet" 12 "github.com/jspc/eggos/kernel/mm" 13 "github.com/jspc/eggos/kernel/sys" 14 "github.com/jspc/eggos/log" 15 16 "gvisor.dev/gvisor/pkg/tcpip/buffer" 17 "gvisor.dev/gvisor/pkg/tcpip/stack" 18 ) 19 20 var _ pci.Driver = (*driver)(nil) 21 22 type driver struct { 23 mac [6]byte 24 ident []pci.Identity 25 26 rxdescs *[NUM_RX_DESCS]rxdesc 27 txdescs *[NUM_TX_DESCS]txdesc 28 29 txidx, rxidx uint32 30 31 rxfunc func([]byte) 32 33 bar uintptr 34 dev *pci.Device 35 } 36 37 func newDriver() *driver { 38 return &driver{} 39 } 40 41 func (d *driver) Name() string { 42 return "e1000" 43 } 44 45 func (d *driver) Idents() []pci.Identity { 46 return []pci.Identity{ 47 {0x8086, 0x100e}, 48 {0x8086, 0x153a}, 49 {0x8086, 0x10ea}, 50 {0x8086, 0x10d3}, 51 {0x8086, 0x15b8}, 52 } 53 } 54 55 func (d *driver) Mac() [6]byte { 56 return d.mac 57 } 58 59 func (d *driver) SetReceiveCallback(cb func([]byte)) { 60 d.rxfunc = cb 61 } 62 63 func (d *driver) writecmd(reg uint16, val uint32) { 64 addr := (*uint32)(unsafe.Pointer(d.bar + uintptr(reg))) 65 atomic.StoreUint32(addr, val) 66 } 67 68 func (d *driver) readcmd(reg uint16) uint32 { 69 addr := (*uint32)(unsafe.Pointer(d.bar + uintptr(reg))) 70 return atomic.LoadUint32(addr) 71 } 72 73 func (d *driver) detecteeprom() bool { 74 haseeprom := false 75 d.writecmd(REG_EEPROM, 1) 76 for i := 0; i < 1000 && !haseeprom; i++ { 77 val := d.readcmd(REG_EEPROM) 78 if val&0x10 != 0 { 79 haseeprom = true 80 } 81 } 82 return haseeprom 83 } 84 85 func (d *driver) readeeprom(addr uint8) uint16 { 86 var temp uint32 87 d.writecmd(REG_EEPROM, 1|(uint32(addr)<<8)) 88 for { 89 temp = d.readcmd(REG_EEPROM) 90 if temp&(1<<4) != 0 { 91 break 92 } 93 } 94 return uint16((temp >> 16) & 0xFFFF) 95 } 96 97 func (d *driver) readmac() { 98 haseeprom := d.detecteeprom() 99 if !haseeprom { 100 temp := d.readcmd(REG_RXADDR) 101 d.mac[0] = byte(temp & 0xff) 102 d.mac[1] = byte(temp >> 8 & 0xff) 103 d.mac[2] = byte(temp >> 16 & 0xff) 104 d.mac[3] = byte(temp >> 24 & 0xff) 105 temp = d.readcmd(REG_RXADDR + 4) 106 d.mac[4] = byte(temp & 0xff) 107 d.mac[5] = byte(temp >> 8 & 0xff) 108 return 109 } 110 111 var temp uint16 112 temp = d.readeeprom(0) 113 d.mac[0] = byte(temp & 0xff) 114 d.mac[1] = byte(temp >> 8 & 0xff) 115 temp = d.readeeprom(1) 116 d.mac[2] = byte(temp & 0xff) 117 d.mac[3] = byte(temp >> 8 & 0xff) 118 temp = d.readeeprom(2) 119 d.mac[4] = byte(temp & 0xff) 120 d.mac[5] = byte(temp >> 8 & 0xff) 121 } 122 123 func (d *driver) Init(dev *pci.Device) error { 124 if unsafe.Sizeof(rxdesc{}) != 16 { 125 panic("bad rxdesc size") 126 } 127 128 if unsafe.Sizeof(txdesc{}) != 16 { 129 panic("bad txdesc size") 130 } 131 132 d.dev = dev 133 134 log.Infof("[e1000] enable bus master") 135 dev.Addr.EnableBusMaster() 136 137 // mmap bar address 138 baddr, blen, _, ismem := dev.Addr.ReadBAR(0) 139 if !ismem { 140 panic("not memory bar") 141 } 142 mm.SysFixedMmap(uintptr(baddr), uintptr(baddr), uintptr(blen)) 143 d.bar = uintptr(baddr) 144 log.Infof("[e1000] mmap for bar0 0x%x", d.bar) 145 146 // alloc desc 147 descptr := mm.Alloc() 148 d.rxdescs = (*[NUM_RX_DESCS]rxdesc)(unsafe.Pointer(descptr)) 149 descptr += unsafe.Sizeof([NUM_RX_DESCS + 1]rxdesc{}) 150 d.txdescs = (*[NUM_TX_DESCS]txdesc)(unsafe.Pointer(descptr)) 151 152 // disable all intrs 153 d.writecmd(REG_IMC, 0xffffffff) 154 155 log.Infof("[e1000] begin reset") 156 // Reset the device. 157 d.writecmd(REG_CTRL, d.readcmd(REG_CTRL)|CTRL_RST) 158 159 // Wait until the device gets reset. 160 // for (d.readcmd(REG_CTRL) & CTRL_RST) != 0 { 161 // } 162 time.Sleep(time.Microsecond) 163 log.Infof("[e1000] reset done") 164 // again disable all intrs after reset 165 d.writecmd(REG_IMC, 0xffffffff) 166 167 // Link up! 168 d.writecmd(REG_CTRL, d.readcmd(REG_CTRL)|CTRL_SLU|CTRL_ASDE) 169 log.Infof("[e1000] link up") 170 171 // Fill Multicast Table Array with zeros. 172 for i := uint16(0); i < 0x80; i++ { 173 d.writecmd(REG_MTA_BASE+i*4, 0) 174 } 175 176 // Initialize RX queue. 177 for i := 0; i < NUM_RX_DESCS; i++ { 178 desc := &d.rxdescs[i] 179 desc.paddr = uint64(mm.Alloc()) 180 } 181 182 rxDescAddr := uintptr(unsafe.Pointer(&d.rxdescs[0])) 183 if rxDescAddr&0xfffffff0 != rxDescAddr { 184 panic("addr of rx desc must be 16 byte align") 185 } 186 d.writecmd(REG_RDBAL, uint32(rxDescAddr&0xfffffff0)) 187 d.writecmd(REG_RDBAH, 0) 188 d.writecmd(REG_RDLEN, uint32(unsafe.Sizeof(*d.rxdescs))) 189 d.writecmd(REG_RDH, 0) 190 d.writecmd(REG_RDT, NUM_RX_DESCS-1) 191 d.writecmd(REG_RCTL, RCTL_EN|RCTL_SECRC|RCTL_BSIZE|RCTL_BAM) 192 193 // Initialize TX queue. 194 for i := 0; i < NUM_TX_DESCS; i++ { 195 desc := &d.txdescs[i] 196 desc.paddr = uint64(mm.Alloc()) 197 desc.status = 1 198 } 199 txDescAddr := uintptr(unsafe.Pointer(&d.txdescs[0])) 200 if txDescAddr&0xfffffff0 != txDescAddr { 201 panic("addr of tx desc must be 16 byte align") 202 } 203 d.writecmd(REG_TDBAL, uint32(txDescAddr&0xffffffff)) 204 d.writecmd(REG_TDBAH, 0) 205 d.writecmd(REG_TDLEN, uint32(unsafe.Sizeof(*d.txdescs))) 206 d.writecmd(REG_TDH, 0) 207 d.writecmd(REG_TDT, 0) 208 d.writecmd(REG_TCTL, TCTL_EN|TCTL_PSP) 209 210 // Enable interrupts. 211 d.writecmd(REG_IMS, IMS_RXT0) 212 // clear pending intrs 213 d.readcmd(REG_ICR) 214 d.writecmd(REG_ICR, ^uint32(0)) 215 216 log.Infof("[e1000] begin read mac") 217 d.readmac() 218 log.Infof("[e1000] mac:%x", d.mac) 219 // go d.recvloop() 220 return nil 221 } 222 223 func (d *driver) Transmit(pkt *stack.PacketBuffer) error { 224 desc := &d.txdescs[d.txidx] 225 if desc.status == 0 { 226 return errors.New("tx queue full") 227 } 228 229 txbuf := sys.UnsafeBuffer(uintptr(desc.paddr), mm.PGSIZE) 230 231 r := buffer.NewVectorisedView(pkt.Size(), pkt.Views()) 232 pktlen, _ := r.Read(txbuf) 233 234 desc.cmd = TX_DESC_IFCS | TX_DESC_EOP | TX_DESC_RS 235 desc.len = uint16(pktlen) 236 desc.cso = 0 237 desc.status = 0 238 desc.css = 0 239 desc.special = 0 240 241 // Notify the device. 242 d.txidx = (d.txidx + 1) % NUM_TX_DESCS 243 d.writecmd(REG_TDT, uint32(d.txidx)) 244 245 // for atomic.LoadInt32((*int32)(unsafe.Pointer(&desc.status))) == 0 { 246 // } 247 // log.Infof("[e1000] send %d bytes", pktlen) 248 return nil 249 } 250 251 func (d *driver) Intr() { 252 defer pic.EnableIRQ(uint16(d.dev.IRQLine)) 253 defer pic.EOI(uintptr(d.dev.IRQNO)) 254 cause := d.readcmd(REG_ICR) 255 // log.Infof("[e1000] cause %x", cause) 256 // clear ICR register 257 // e1000e may not clear upon read 258 d.writecmd(REG_ICR, ^uint32(0)) 259 if cause&ICR_RXT0 == 0 { 260 return 261 } 262 263 for d.readpkt() { 264 } 265 } 266 267 func (d *driver) recvloop() { 268 for { 269 // syscall.Nanosleep(&syscall.Timespec{ 270 // Nsec: 1000000 * 10, 271 // }, nil) 272 time.Sleep(time.Millisecond * 10) 273 for d.readpkt() { 274 } 275 } 276 } 277 278 func (d *driver) readpkt() bool { 279 d.rxidx = d.readcmd(REG_RDT) 280 d.rxidx = (d.rxidx + 1) % NUM_RX_DESCS 281 // log.Infof("[e1000] head:%d", d.readcmd(0x02810)) 282 // log.Infof("[e1000] tail:%d", d.readcmd(0x02818)) 283 // log.Infof("[e1000] rxidx:%d", d.rxidx) 284 desc := &d.rxdescs[d.rxidx] 285 286 // fmt.Printf("status:%x\n", atomic.LoadUint32((*uint32)(unsafe.Pointer(&desc.status)))) 287 // We don't support a large packet which spans multiple descriptors. 288 const bits = RX_DESC_DD | RX_DESC_EOP 289 if (desc.status & bits) != bits { 290 return false 291 } 292 293 buf := sys.UnsafeBuffer(uintptr(desc.paddr), int(desc.len)) 294 // log.Infof("[e1000] read %d bytes", desc.len) 295 if d.rxfunc != nil { 296 d.rxfunc(buf) 297 } 298 299 // Tell the device that we've tasked a received packet. 300 desc.status = 0 301 d.writecmd(REG_RDT, d.rxidx) 302 303 return true 304 } 305 306 func init() { 307 d := newDriver() 308 inet.RegisterDevice(d) 309 pci.Register(d) 310 }