DF-4266 / wb_logic.c
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /* * DF-4266 / DF-4267 logic harness (userland, host-runnable) * * Transcribes verbatim the loop-termination and ring-linking code from * sys/dev/netif/wb/if_wb.c (DragonFly, audited tree) * sys/pci/if_wb.c (FreeBSD 4.11 original, for comparison) * and drives it against a faithful model of the W89C840F descriptor * ownership protocol (OWN=1 -> chip owns/free-to-fill; chip clears OWN * and sets RXCMP when a frame is written back). * * Build: cc -O2 -o wb_logic wb_logic.c * Run: ./wb_logic */ #include <stdio.h> #include <stdint.h> #include <string.h> #define WB_RX_LIST_CNT 64 #define WB_TX_LIST_CNT 128 #define WB_RXSTAT_RXLEN 0x3FFF0000u #define WB_RXSTAT_LASTFRAG 0x00000100u #define WB_RXSTAT_FIRSTFRAG 0x00000200u #define WB_RXSTAT_RXCMP 0x40000000u #define WB_RXSTAT_OWN 0x80000000u #define WB_RXBYTES(x) (((x) & WB_RXSTAT_RXLEN) >> 16) #define WB_RXSTAT (WB_RXSTAT_FIRSTFRAG|WB_RXSTAT_LASTFRAG|WB_RXSTAT_OWN) #define WB_MIN_FRAMELEN 60 #define ETHER_CRC_LEN 4 struct wb_desc { uint32_t wb_status, wb_ctl, wb_ptr1, wb_ptr2; }; /* ---- DragonFly wb_list_rx_init() linking loop (if_wb.c:904-912) ---- */ static int dfly_nexti(int i) { int nexti; nexti = (WB_RX_LIST_CNT - 1) ? 0 : i + 1; /* constant condition! */ return nexti; } /* ---- FreeBSD 4.11 wb_list_rx_init() linking loop (reference) ---- */ static int fbsd_nextdesc_idx(int i) { if (i == (WB_RX_LIST_CNT - 1)) return 0; return i + 1; } static void ring_report(const char *tag, int (*nextfn)(int)) { int next[WB_RX_LIST_CNT], i, visited = 1, cur = 0, seen[WB_RX_LIST_CNT]; for (i = 0; i < WB_RX_LIST_CNT; i++) next[i] = nextfn(i); memset(seen, 0, sizeof(seen)); seen[0] = 1; for (;;) { cur = next[cur]; if (seen[cur]) break; seen[cur] = 1; visited++; } printf("%-12s ring: next[0]=%d next[1]=%d next[63]=%d | distinct descriptors " "reachable from head: %d / %d\n", tag, next[0], next[1], next[WB_RX_LIST_CNT - 1], visited, WB_RX_LIST_CNT); } /* * RX processing loop simulation. * chip: -1 = chip mid-write on the head descriptor (OWN still set, no RXCMP) * 0 = idle * 1 = chip completed head descriptor (OWN cleared, RXCMP set, len 1518) */ static int run_rx_loop(const char *tag, int chip_state, int *babbling_out, int *frames_out) { struct wb_desc descs[WB_RX_LIST_CNT]; int i, processed = 0, babbling = 0, head = 0; for (i = 0; i < WB_RX_LIST_CNT; i++) descs[i].wb_status = WB_RXSTAT; /* wb_newbuf(): armed, chip-owned */ if (chip_state == 1) descs[0].wb_status = (WB_RXSTAT & ~WB_RXSTAT_OWN) | WB_RXSTAT_RXCMP | (1518 << 16); /* completed frame, OWN=0 */ else if (chip_state == -1) descs[0].wb_status = WB_RXSTAT | (37 << 16); /* mid-write, no RXCMP */ /* DragonFly wb_rxeof() loop (if_wb.c:972-1001), verbatim condition: */ for (;;) { uint32_t rxstat = descs[head].wb_status; if ((rxstat & WB_RXSTAT_OWN) == 0) break; /* body: length/validity checks */ if ((rxstat & WB_RXSTAT_RXCMP) == 0 || WB_RXBYTES(rxstat) < WB_MIN_FRAMELEN || WB_RXBYTES(rxstat) > 1536) { babbling = 1; /* "receiver babbling ... forcing reset" */ break; } processed++; /* deliver frame */ break; /* harness: single iteration decision */ } /* FreeBSD 4.11 wb_rxeof() loop condition, verbatim: process while !OWN */ { uint32_t rxstat = descs[head].wb_status; int fprocessed = ((rxstat & WB_RXSTAT_OWN) == 0) && (rxstat & WB_RXSTAT_RXCMP); printf("%-28s chip_state=%-9s DFLY: processed=%d babbling-reset=%d | " "FBSD411-COND: processed=%d\n", tag, chip_state == 1 ? "completed" : chip_state == -1 ? "mid-write" : "idle-none", processed, babbling, fprocessed); } *babbling_out = babbling; *frames_out = processed; return 0; } int main(void) { printf("== DF-4267: RX ring construction ==\n"); ring_report("DragonFly", dfly_nexti); ring_report("FreeBSD411", fbsd_nextdesc_idx); printf("\n== DF-4266: wb_rxeof loop direction vs chip ownership ==\n"); { int b, f; run_rx_loop("frame completed by chip", 1, &b, &f); run_rx_loop("chip still writing desc", -1, &b, &f); run_rx_loop("no rx activity", 0, &b, &f); } printf("\nExpected (correct driver): completed -> processed, mid-write/idle -> wait.\n"); return 0; } |