@@ -22,6 +22,13 @@
/* Number of 2k memory pages available. */
#define NUM_PACKETS 4
+/*
+ * Maximum size of a data frame, including the leading status word
+ * and byte count fields and the trailing CRC, last data byte
+ * and control byte (per figure 8-1 in the Microchip Technology
+ * LAN91C111 datasheet).
+ */
+#define MAX_PACKET_SIZE 2048
#define TYPE_SMC91C111 "smc91c111"
OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state, SMC91C111)
@@ -240,6 +247,16 @@ static void smc91c111_release_packet(smc91c111_state *s, int packet)
smc91c111_flush_queued_packets(s);
}
+static void smc91c111_complete_tx_packet(smc91c111_state *s, int packetnum)
+{
+ if (s->ctr & CTR_AUTO_RELEASE) {
+ /* Race? */
+ smc91c111_release_packet(s, packetnum);
+ } else if (s->tx_fifo_done_len < NUM_PACKETS) {
+ s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
+ }
+}
+
/* Flush the TX FIFO. */
static void smc91c111_do_tx(smc91c111_state *s)
{
@@ -263,6 +280,17 @@ static void smc91c111_do_tx(smc91c111_state *s)
*(p++) = 0x40;
len = *(p++);
len |= ((int)*(p++)) << 8;
+ if (len > MAX_PACKET_SIZE) {
+ /*
+ * Datasheet doesn't say what to do here, and there is no
+ * relevant tx error condition listed. Log, and drop the packet.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "smc91c111: tx packet with bad length %d, dropping\n",
+ len);
+ smc91c111_complete_tx_packet(s, packetnum);
+ continue;
+ }
len -= 6;
control = p[len + 1];
if (control & 0x20)
@@ -291,11 +319,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
}
}
#endif
- if (s->ctr & CTR_AUTO_RELEASE)
- /* Race? */
- smc91c111_release_packet(s, packetnum);
- else if (s->tx_fifo_done_len < NUM_PACKETS)
- s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
+ smc91c111_complete_tx_packet(s, packetnum);
qemu_send_packet(qemu_get_queue(s->nic), p, len);
}
s->tx_fifo_len = 0;