summary refs log tree commit diff stats
path: root/results/scraper/launchpad-without-comments/1306818
blob: 36b2e4aa7509e12da5018f2656f3bf22b816cbbc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
resetting moder register in opencores_eth.c code (ethernet IP core specification  code)

Hi, I would like to report a possible error in the code  qemu/hw/net/opencores_eth.c

The corresponding data sheet : http://www.cprover.org/firmware/doc/ethoc/eth_speci.pdf


In the code, there is a function open_eth_moder_host_write. 

static void open_eth_moder_host_write(OpenEthState *s, uint32_t val)
{
    uint32_t set = val & ~s->regs[MODER];

    if (set & MODER_RST) {
        open_eth_reset(s);
    }

    s->regs[MODER] = val;

    if (set & MODER_RXEN) {
        s->rx_desc = s->regs[TX_BD_NUM];
        open_eth_notify_can_receive(s);
    }
    if (set & MODER_TXEN) {
        s->tx_desc = 0;
        open_eth_check_start_xmit(s);
    }
}

This piece of code is executed when MODER (Mode Register) resister is command to updated to ‘val’. 

In case of reset, as you can see, if the MODER_RST bit (0x800) bit is set && the old MODER_RST bit (0x800) of MODER register is clear, the code falls into the if(set & MODER_RST) branch. Then, it calls open_eth_reset(s), which does “s->regs[MODER] = 0xa000;”. Now, the MODER register is reset to 0xa000. Page 9 of the data sheet (http://www.cprover.org/firmware/doc/ethoc/eth_speci.pdf) specifies the reset value of the moder is 0000A000h. So far, the code works fine. 
Then, the open_eth_moder_host_write function does not end but executes but executes “s->regs[MODER] = val;” line. Now, the MODER register is not 0xa000 any more. 
In fact, since the MODER_RST bit of ‘val’ is 1, now the MODER_RST bit of the MODER register becomes 1 as well. Suppose one somehow calls this  open_eth_moder_host_write again with val = MODER_RST with purpose of resetting again. Since the MODER_RST bit is 1, (set = val & ~s->regs[MODER]) & MODER_RST is zero. So after this, resetting again is not possible. 

Hence, I doubt the function’s correctness here. I think it could be better if the function changes to : 

    if (set & MODER_RST) {
        open_eth_reset(s);
		return;
    }

Please let me know if I am correct.