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  }