i82596.c (1ccda935d4fcc82a4371dc23d660197b0a6b6951) i82596.c (19f703477314a5db09ffc3c0f6be9c45645f8302)
1/*
2 * QEMU Intel i82596 (Apricot) emulation
3 *
4 * Copyright (c) 2019 Helge Deller <deller@gmx.de>
5 * This work is licensed under the GNU GPL license version 2 or later.
6 *
7 * This software was written to be compatible with the specification:
8 * https://www.intel.com/assets/pdf/general/82596ca.pdf

--- 134 unchanged lines hidden (view full) ---

143
144 size = get_uint16(tdb_p);
145 len = size & SIZE_MASK;
146 tba = get_uint32(tdb_p + 8);
147 trace_i82596_transmit(len, tba);
148
149 if (s->nic && len) {
150 assert(len <= sizeof(s->tx_buffer));
1/*
2 * QEMU Intel i82596 (Apricot) emulation
3 *
4 * Copyright (c) 2019 Helge Deller <deller@gmx.de>
5 * This work is licensed under the GNU GPL license version 2 or later.
6 *
7 * This software was written to be compatible with the specification:
8 * https://www.intel.com/assets/pdf/general/82596ca.pdf

--- 134 unchanged lines hidden (view full) ---

143
144 size = get_uint16(tdb_p);
145 len = size & SIZE_MASK;
146 tba = get_uint32(tdb_p + 8);
147 trace_i82596_transmit(len, tba);
148
149 if (s->nic && len) {
150 assert(len <= sizeof(s->tx_buffer));
151 address_space_rw(&address_space_memory, tba,
152 MEMTXATTRS_UNSPECIFIED, s->tx_buffer, len, false);
151 address_space_read(&address_space_memory, tba,
152 MEMTXATTRS_UNSPECIFIED, s->tx_buffer, len);
153 DBG(PRINT_PKTHDR("Send", &s->tx_buffer));
154 DBG(printf("Sending %d bytes\n", len));
155 qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, len);
156 }
157
158 /* was this the last package? */
159 if (size & I596_EOF) {
160 break;

--- 6 unchanged lines hidden (view full) ---

167
168static void set_individual_address(I82596State *s, uint32_t addr)
169{
170 NetClientState *nc;
171 uint8_t *m;
172
173 nc = qemu_get_queue(s->nic);
174 m = s->conf.macaddr.a;
153 DBG(PRINT_PKTHDR("Send", &s->tx_buffer));
154 DBG(printf("Sending %d bytes\n", len));
155 qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, len);
156 }
157
158 /* was this the last package? */
159 if (size & I596_EOF) {
160 break;

--- 6 unchanged lines hidden (view full) ---

167
168static void set_individual_address(I82596State *s, uint32_t addr)
169{
170 NetClientState *nc;
171 uint8_t *m;
172
173 nc = qemu_get_queue(s->nic);
174 m = s->conf.macaddr.a;
175 address_space_rw(&address_space_memory, addr + 8,
176 MEMTXATTRS_UNSPECIFIED, m, ETH_ALEN, false);
175 address_space_read(&address_space_memory, addr + 8,
176 MEMTXATTRS_UNSPECIFIED, m, ETH_ALEN);
177 qemu_format_nic_info_str(nc, m);
178 trace_i82596_new_mac(nc->info_str);
179}
180
181static void set_multicast_list(I82596State *s, uint32_t addr)
182{
183 uint16_t mc_count, i;
184
185 memset(&s->mult[0], 0, sizeof(s->mult));
186 mc_count = get_uint16(addr + 8) / ETH_ALEN;
187 addr += 10;
188 if (mc_count > MAX_MC_CNT) {
189 mc_count = MAX_MC_CNT;
190 }
191 for (i = 0; i < mc_count; i++) {
192 uint8_t multicast_addr[ETH_ALEN];
177 qemu_format_nic_info_str(nc, m);
178 trace_i82596_new_mac(nc->info_str);
179}
180
181static void set_multicast_list(I82596State *s, uint32_t addr)
182{
183 uint16_t mc_count, i;
184
185 memset(&s->mult[0], 0, sizeof(s->mult));
186 mc_count = get_uint16(addr + 8) / ETH_ALEN;
187 addr += 10;
188 if (mc_count > MAX_MC_CNT) {
189 mc_count = MAX_MC_CNT;
190 }
191 for (i = 0; i < mc_count; i++) {
192 uint8_t multicast_addr[ETH_ALEN];
193 address_space_rw(&address_space_memory,
194 addr + i * ETH_ALEN, MEMTXATTRS_UNSPECIFIED,
195 multicast_addr, ETH_ALEN, false);
193 address_space_read(&address_space_memory, addr + i * ETH_ALEN,
194 MEMTXATTRS_UNSPECIFIED, multicast_addr, ETH_ALEN);
196 DBG(printf("Add multicast entry " MAC_FMT "\n",
197 MAC_ARG(multicast_addr)));
198 unsigned mcast_idx = (net_crc32(multicast_addr, ETH_ALEN) &
199 BITS(7, 2)) >> 2;
200 assert(mcast_idx < 8 * sizeof(s->mult));
201 s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
202 }
203 trace_i82596_set_multicast(mc_count);

--- 51 unchanged lines hidden (view full) ---

255 case CmdSASetup:
256 set_individual_address(s, s->cmd_p);
257 break;
258 case CmdConfigure:
259 byte_cnt = get_byte(s->cmd_p + 8) & 0x0f;
260 byte_cnt = MAX(byte_cnt, 4);
261 byte_cnt = MIN(byte_cnt, sizeof(s->config));
262 /* copy byte_cnt max. */
195 DBG(printf("Add multicast entry " MAC_FMT "\n",
196 MAC_ARG(multicast_addr)));
197 unsigned mcast_idx = (net_crc32(multicast_addr, ETH_ALEN) &
198 BITS(7, 2)) >> 2;
199 assert(mcast_idx < 8 * sizeof(s->mult));
200 s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
201 }
202 trace_i82596_set_multicast(mc_count);

--- 51 unchanged lines hidden (view full) ---

254 case CmdSASetup:
255 set_individual_address(s, s->cmd_p);
256 break;
257 case CmdConfigure:
258 byte_cnt = get_byte(s->cmd_p + 8) & 0x0f;
259 byte_cnt = MAX(byte_cnt, 4);
260 byte_cnt = MIN(byte_cnt, sizeof(s->config));
261 /* copy byte_cnt max. */
263 address_space_rw(&address_space_memory, s->cmd_p + 8,
264 MEMTXATTRS_UNSPECIFIED, s->config, byte_cnt,
265 false);
262 address_space_read(&address_space_memory, s->cmd_p + 8,
263 MEMTXATTRS_UNSPECIFIED, s->config, byte_cnt);
266 /* config byte according to page 35ff */
267 s->config[2] &= 0x82; /* mask valid bits */
268 s->config[2] |= 0x40;
269 s->config[7] &= 0xf7; /* clear zero bit */
270 assert(I596_NOCRC_INS == 0); /* do CRC insertion */
271 s->config[10] = MAX(s->config[10], 5); /* min frame length */
272 s->config[12] &= 0x40; /* only full duplex field valid */
273 s->config[13] |= 0x3f; /* set ones in byte 13 */

--- 368 unchanged lines hidden (view full) ---

642 rba = get_uint32(rbd + 8);
643 /* printf("rba is 0x%x\n", rba); */
644 address_space_write(&address_space_memory, rba,
645 MEMTXATTRS_UNSPECIFIED, buf, num);
646 rba += num;
647 buf += num;
648 len -= num;
649 if (len == 0) { /* copy crc */
264 /* config byte according to page 35ff */
265 s->config[2] &= 0x82; /* mask valid bits */
266 s->config[2] |= 0x40;
267 s->config[7] &= 0xf7; /* clear zero bit */
268 assert(I596_NOCRC_INS == 0); /* do CRC insertion */
269 s->config[10] = MAX(s->config[10], 5); /* min frame length */
270 s->config[12] &= 0x40; /* only full duplex field valid */
271 s->config[13] |= 0x3f; /* set ones in byte 13 */

--- 368 unchanged lines hidden (view full) ---

640 rba = get_uint32(rbd + 8);
641 /* printf("rba is 0x%x\n", rba); */
642 address_space_write(&address_space_memory, rba,
643 MEMTXATTRS_UNSPECIFIED, buf, num);
644 rba += num;
645 buf += num;
646 len -= num;
647 if (len == 0) { /* copy crc */
650 address_space_rw(&address_space_memory, rba - 4,
651 MEMTXATTRS_UNSPECIFIED, crc_ptr, 4, true);
648 address_space_write(&address_space_memory, rba - 4,
649 MEMTXATTRS_UNSPECIFIED, crc_ptr, 4);
652 }
653
654 num |= 0x4000; /* set F BIT */
655 if (len == 0) {
656 num |= I596_EOF; /* set EOF BIT */
657 }
658 set_uint16(rbd + 0, num); /* write actual count with flags */
659

--- 76 unchanged lines hidden ---
650 }
651
652 num |= 0x4000; /* set F BIT */
653 if (len == 0) {
654 num |= I596_EOF; /* set EOF BIT */
655 }
656 set_uint16(rbd + 0, num); /* write actual count with flags */
657

--- 76 unchanged lines hidden ---