i8254xGBe.cc revision 4218
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31/* @file
32 * Device model for Intel's 8254x line of gigabit ethernet controllers.
33 * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the
34 * fewest workarounds in the driver. It will probably work with most of the
35 * other MACs with slight modifications.
36 */
37
38#include "base/inet.hh"
39#include "dev/i8254xGBe.hh"
40#include "mem/packet.hh"
41#include "mem/packet_access.hh"
42#include "sim/builder.hh"
43#include "sim/stats.hh"
44#include "sim/system.hh"
45
46using namespace iGbReg;
47
48IGbE::IGbE(Params *p)
49    : PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control)
50{
51    // Initialized internal registers per Intel documentation
52    regs.tctl(0);
53    regs.rctl(0);
54    regs.ctrl(0);
55    regs.ctrl.fd(1);
56    regs.ctrl.lrst(1);
57    regs.ctrl.speed(2);
58    regs.ctrl.frcspd(1);
59    regs.sts(0);
60    regs.sts.speed(3); // Say we're 1000Mbps
61    regs.sts.fd(1); // full duplex
62    regs.eecd(0);
63    regs.eecd.fwe(1);
64    regs.eecd.ee_type(1);
65    regs.eerd(0);
66    regs.icr(0);
67    regs.rctl(0);
68    regs.tctl(0);
69    regs.fcrtl(0);
70    regs.fcrth(1);
71    regs.manc(0);
72
73    regs.pba.rxa(0x30);
74    regs.pba.txa(0x10);
75
76    eeOpBits            = 0;
77    eeAddrBits          = 0;
78    eeDataBits          = 0;
79    eeOpcode            = 0;
80
81    // clear all 64 16 bit words of the eeprom
82    memset(&flash, 0, EEPROM_SIZE*2);
83
84    //We'll need to instert the MAC address into the flash
85    flash[0] = 0xA4A4;
86    flash[1] = 0xB6B6;
87    flash[2] = 0xC8C8;
88
89    uint16_t csum = 0;
90    for (int x = 0; x < EEPROM_SIZE; x++)
91        csum += flash[x];
92
93    // Magic happy checksum value
94    flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum));
95}
96
97
98Tick
99IGbE::writeConfig(PacketPtr pkt)
100{
101    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
102    if (offset < PCI_DEVICE_SPECIFIC)
103        PciDev::writeConfig(pkt);
104    else
105        panic("Device specific PCI config space not implemented.\n");
106
107    ///
108    /// Some work may need to be done here based for the pci COMMAND bits.
109    ///
110
111    return pioDelay;
112}
113
114Tick
115IGbE::read(PacketPtr pkt)
116{
117    int bar;
118    Addr daddr;
119
120    if (!getBAR(pkt->getAddr(), bar, daddr))
121        panic("Invalid PCI memory access to unmapped memory.\n");
122
123    // Only Memory register BAR is allowed
124    assert(bar == 0);
125
126    // Only 32bit accesses allowed
127    assert(pkt->getSize() == 4);
128
129    //DPRINTF(Ethernet, "Read device register %#X\n", daddr);
130
131    pkt->allocate();
132
133    ///
134    /// Handle read of register here
135    ///
136
137
138    switch (daddr) {
139      case REG_CTRL:
140        pkt->set<uint32_t>(regs.ctrl());
141        break;
142      case REG_STATUS:
143        pkt->set<uint32_t>(regs.sts());
144        break;
145      case REG_EECD:
146        pkt->set<uint32_t>(regs.eecd());
147        break;
148      case REG_EERD:
149        pkt->set<uint32_t>(regs.eerd());
150        break;
151      case REG_CTRL_EXT:
152        pkt->set<uint32_t>(regs.ctrl_ext());
153        break;
154      case REG_MDIC:
155        pkt->set<uint32_t>(regs.mdic());
156        break;
157      case REG_ICR:
158        pkt->set<uint32_t>(regs.icr());
159        // handle auto setting mask from IAM
160        break;
161      case REG_ITR:
162        pkt->set<uint32_t>(regs.itr());
163        break;
164      case REG_RCTL:
165        pkt->set<uint32_t>(regs.rctl());
166        break;
167      case REG_FCTTV:
168        pkt->set<uint32_t>(regs.fcttv());
169        break;
170      case REG_TCTL:
171        pkt->set<uint32_t>(regs.tctl());
172        break;
173      case REG_PBA:
174        pkt->set<uint32_t>(regs.pba());
175        break;
176      case REG_WUC:
177      case REG_LEDCTL:
178        pkt->set<uint32_t>(0); // We don't care, so just return 0
179        break;
180      case REG_FCRTL:
181        pkt->set<uint32_t>(regs.fcrtl());
182        break;
183      case REG_FCRTH:
184        pkt->set<uint32_t>(regs.fcrth());
185        break;
186      case REG_RDBAL:
187        pkt->set<uint32_t>(regs.rdba.rdbal());
188        break;
189      case REG_RDBAH:
190        pkt->set<uint32_t>(regs.rdba.rdbah());
191        break;
192      case REG_RDLEN:
193        pkt->set<uint32_t>(regs.rdlen());
194        break;
195      case REG_RDH:
196        pkt->set<uint32_t>(regs.rdh());
197        break;
198      case REG_RDT:
199        pkt->set<uint32_t>(regs.rdt());
200        break;
201      case REG_RDTR:
202        pkt->set<uint32_t>(regs.rdtr());
203        break;
204      case REG_RADV:
205        pkt->set<uint32_t>(regs.radv());
206        break;
207      case REG_TDBAL:
208        pkt->set<uint32_t>(regs.tdba.tdbal());
209        break;
210      case REG_TDBAH:
211        pkt->set<uint32_t>(regs.tdba.tdbah());
212        break;
213      case REG_TDLEN:
214        pkt->set<uint32_t>(regs.tdlen());
215        break;
216      case REG_TDH:
217        pkt->set<uint32_t>(regs.tdh());
218        break;
219      case REG_TDT:
220        pkt->set<uint32_t>(regs.tdt());
221        break;
222      case REG_TIDV:
223        pkt->set<uint32_t>(regs.tidv());
224        break;
225      case REG_TXDCTL:
226        pkt->set<uint32_t>(regs.txdctl());
227        break;
228      case REG_TADV:
229        pkt->set<uint32_t>(regs.tadv());
230        break;
231      case REG_RXCSUM:
232        pkt->set<uint32_t>(regs.rxcsum());
233        break;
234      case REG_MANC:
235        pkt->set<uint32_t>(regs.manc());
236        break;
237      default:
238        if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
239            !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
240            !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)) &&
241            !(daddr >= REG_CRCERRS && daddr < (REG_CRCERRS + STATS_REGS_SIZE)))
242            panic("Read request to unknown register number: %#x\n", daddr);
243        else
244            pkt->set<uint32_t>(0);
245    };
246
247    pkt->result = Packet::Success;
248    return pioDelay;
249}
250
251Tick
252IGbE::write(PacketPtr pkt)
253{
254    int bar;
255    Addr daddr;
256
257
258    if (!getBAR(pkt->getAddr(), bar, daddr))
259        panic("Invalid PCI memory access to unmapped memory.\n");
260
261    // Only Memory register BAR is allowed
262    assert(bar == 0);
263
264    // Only 32bit accesses allowed
265    assert(pkt->getSize() == sizeof(uint32_t));
266
267    //DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
268
269    ///
270    /// Handle write of register here
271    ///
272    uint32_t val = pkt->get<uint32_t>();
273
274    switch (daddr) {
275      case REG_CTRL:
276        regs.ctrl = val;
277        if (regs.ctrl.tfce())
278            warn("TX Flow control enabled, should implement\n");
279        if (regs.ctrl.rfce())
280            warn("RX Flow control enabled, should implement\n");
281        break;
282      case REG_CTRL_EXT:
283        regs.ctrl_ext = val;
284        break;
285      case REG_STATUS:
286        regs.sts = val;
287        break;
288      case REG_EECD:
289        int oldClk;
290        oldClk = regs.eecd.sk();
291        regs.eecd = val;
292        // See if this is a eeprom access and emulate accordingly
293        if (!oldClk && regs.eecd.sk()) {
294            if (eeOpBits < 8) {
295                eeOpcode = eeOpcode << 1 | regs.eecd.din();
296                eeOpBits++;
297            } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
298                eeAddr = eeAddr << 1 | regs.eecd.din();
299                eeAddrBits++;
300            } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
301                assert(eeAddr>>1 < EEPROM_SIZE);
302                DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
303                        flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]);
304                regs.eecd.dout((flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1);
305                eeDataBits++;
306            } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
307                regs.eecd.dout(0);
308                eeDataBits++;
309            } else
310                panic("What's going on with eeprom interface? opcode:"
311                       " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode,
312                       (uint32_t)eeOpBits, (uint32_t)eeAddr,
313                       (uint32_t)eeAddrBits, (uint32_t)eeDataBits);
314
315            // Reset everything for the next command
316            if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) ||
317               (eeDataBits == 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI)) {
318                eeOpBits = 0;
319                eeAddrBits = 0;
320                eeDataBits = 0;
321               eeOpcode = 0;
322                eeAddr = 0;
323            }
324
325           DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
326                    (uint32_t)eeOpcode, (uint32_t) eeOpBits,
327                    (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
328           if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI ||
329                                   eeOpcode == EEPROM_RDSR_OPCODE_SPI ))
330                panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
331                        (uint32_t)eeOpBits);
332
333
334        }
335        // If driver requests eeprom access, immediately give it to it
336        regs.eecd.ee_gnt(regs.eecd.ee_req());
337        break;
338      case REG_EERD:
339        regs.eerd = val;
340        break;
341      case REG_MDIC:
342        regs.mdic = val;
343        if (regs.mdic.i())
344            panic("No support for interrupt on mdic complete\n");
345        if (regs.mdic.phyadd() != 1)
346            panic("No support for reading anything but phy\n");
347        DPRINTF(Ethernet, "%s phy address %x\n", regs.mdic.op() == 1 ? "Writing"
348                : "Reading", regs.mdic.regadd());
349        switch (regs.mdic.regadd()) {
350            case PHY_PSTATUS:
351                regs.mdic.data(0x796D); // link up
352                break;
353            case PHY_PID:
354                regs.mdic.data(0x02A8);
355                break;
356            case PHY_EPID:
357                regs.mdic.data(0x0380);
358                break;
359            case PHY_GSTATUS:
360                regs.mdic.data(0x7C00);
361                break;
362            case PHY_EPSTATUS:
363                regs.mdic.data(0x3000);
364                break;
365            case PHY_AGC:
366                regs.mdic.data(0x180); // some random length
367                break;
368            default:
369                regs.mdic.data(0);
370                warn("Accessing unknown phy register %d\n", regs.mdic.regadd());
371        }
372        regs.mdic.r(1);
373        break;
374      case REG_ICR:
375        regs.icr = val;
376        // handle auto setting mask from IAM
377        break;
378      case REG_ITR:
379        regs.itr = val;
380        break;
381      case REG_ICS:
382        regs.icr = val | regs.icr();
383        // generate an interrupt if needed here
384        break;
385       case REG_IMS:
386        regs.imr |= val;
387        // handle interrupts if needed here
388        break;
389      case REG_IMC:
390        regs.imr |= ~val;
391        // handle interrupts if needed here
392        break;
393      case REG_IAM:
394        regs.iam = val;
395        break;
396      case REG_RCTL:
397        regs.rctl = val;
398        break;
399      case REG_FCTTV:
400        regs.fcttv = val;
401        break;
402      case REG_TCTL:
403        regs.tctl = val;
404        break;
405      case REG_PBA:
406        regs.pba.rxa(val);
407        regs.pba.txa(64 - regs.pba.rxa());
408        break;
409      case REG_WUC:
410      case REG_LEDCTL:
411      case REG_FCAL:
412      case REG_FCAH:
413      case REG_FCT:
414      case REG_VET:
415      case REG_AIFS:
416      case REG_TIPG:
417        ; // We don't care, so don't store anything
418        break;
419      case REG_FCRTL:
420        regs.fcrtl = val;
421        break;
422      case REG_FCRTH:
423        regs.fcrth = val;
424        break;
425      case REG_RDBAL:
426        regs.rdba.rdbal( val & ~mask(4));
427        break;
428      case REG_RDBAH:
429        regs.rdba.rdbah(val);
430        break;
431      case REG_RDLEN:
432        regs.rdlen = val & ~mask(7);
433        break;
434      case REG_RDH:
435        regs.rdh = val;
436        break;
437      case REG_RDT:
438        regs.rdt = val;
439        break;
440      case REG_RDTR:
441        regs.rdtr = val;
442        break;
443      case REG_RADV:
444        regs.radv = val;
445        break;
446      case REG_TDBAL:
447        regs.tdba.tdbal( val & ~mask(4));
448        break;
449      case REG_TDBAH:
450        regs.tdba.tdbah(val);
451        break;
452      case REG_TDLEN:
453        regs.tdlen = val & ~mask(7);
454        break;
455      case REG_TDH:
456        regs.tdh = val;
457        break;
458      case REG_TDT:
459        regs.tdt = val;
460        break;
461      case REG_TIDV:
462        regs.tidv = val;
463        break;
464      case REG_TXDCTL:
465        regs.txdctl = val;
466        break;
467      case REG_TADV:
468        regs.tadv = val;
469        break;
470      case REG_RXCSUM:
471        regs.rxcsum = val;
472        break;
473      case REG_MANC:
474        regs.manc = val;
475        break;
476      default:
477       if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
478           !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
479           !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)))
480           panic("Write request to unknown register number: %#x\n", daddr);
481    };
482
483    pkt->result = Packet::Success;
484    return pioDelay;
485}
486
487
488bool
489IGbE::ethRxPkt(EthPacketPtr packet)
490{
491    panic("Need to implemenet\n");
492}
493
494
495void
496IGbE::ethTxDone()
497{
498    panic("Need to implemenet\n");
499}
500
501void
502IGbE::serialize(std::ostream &os)
503{
504    panic("Need to implemenet\n");
505}
506
507void
508IGbE::unserialize(Checkpoint *cp, const std::string &section)
509{
510    panic("Need to implemenet\n");
511}
512
513
514BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt)
515
516    SimObjectParam<EtherInt *> peer;
517    SimObjectParam<IGbE *> device;
518
519END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt)
520
521BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt)
522
523    INIT_PARAM_DFLT(peer, "peer interface", NULL),
524    INIT_PARAM(device, "Ethernet device of this interface")
525
526END_INIT_SIM_OBJECT_PARAMS(IGbEInt)
527
528CREATE_SIM_OBJECT(IGbEInt)
529{
530    IGbEInt *dev_int = new IGbEInt(getInstanceName(), device);
531
532    EtherInt *p = (EtherInt *)peer;
533    if (p) {
534        dev_int->setPeer(p);
535        p->setPeer(dev_int);
536    }
537
538    return dev_int;
539}
540
541REGISTER_SIM_OBJECT("IGbEInt", IGbEInt)
542
543
544BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE)
545
546    SimObjectParam<System *> system;
547    SimObjectParam<Platform *> platform;
548    SimObjectParam<PciConfigData *> configdata;
549    Param<uint32_t> pci_bus;
550    Param<uint32_t> pci_dev;
551    Param<uint32_t> pci_func;
552    Param<Tick> pio_latency;
553    Param<Tick> config_latency;
554
555END_DECLARE_SIM_OBJECT_PARAMS(IGbE)
556
557BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE)
558
559    INIT_PARAM(system, "System pointer"),
560    INIT_PARAM(platform, "Platform pointer"),
561    INIT_PARAM(configdata, "PCI Config data"),
562    INIT_PARAM(pci_bus, "PCI bus ID"),
563    INIT_PARAM(pci_dev, "PCI device number"),
564    INIT_PARAM(pci_func, "PCI function code"),
565    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
566    INIT_PARAM(config_latency, "Number of cycles for a config read or write")
567
568END_INIT_SIM_OBJECT_PARAMS(IGbE)
569
570
571CREATE_SIM_OBJECT(IGbE)
572{
573    IGbE::Params *params = new IGbE::Params;
574
575    params->name = getInstanceName();
576    params->platform = platform;
577    params->system = system;
578    params->configData = configdata;
579    params->busNum = pci_bus;
580    params->deviceNum = pci_dev;
581    params->functionNum = pci_func;
582    params->pio_delay = pio_latency;
583    params->config_delay = config_latency;
584
585    return new IGbE(params);
586}
587
588REGISTER_SIM_OBJECT("IGbE", IGbE)
589