/* * SMSC 91C111 Ethernet interface emulation * * Copyright (c) 2005 CodeSourcery, LLC. * Written by Paul Brook * * This code is licenced under the GPL */ #include "vl.h" /* For crc32 */ #include /* Number of 2k memory pages available. */ #define NUM_PACKETS 4 typedef struct { uint32_t base; VLANClientState *vc; uint16_t tcr; uint16_t rcr; uint16_t cr; uint16_t ctr; uint16_t gpr; uint16_t ptr; uint16_t ercv; void *pic; int irq; int bank; int packet_num; int tx_alloc; /* Bitmask of allocated packets. */ int allocated; int tx_fifo_len; int tx_fifo[NUM_PACKETS]; int rx_fifo_len; int rx_fifo[NUM_PACKETS]; int tx_fifo_done_len; int tx_fifo_done[NUM_PACKETS]; /* Packet buffer memory. */ uint8_t data[NUM_PACKETS][2048]; uint8_t int_level; uint8_t int_mask; uint8_t macaddr[6]; } smc91c111_state; #define RCR_SOFT_RST 0x8000 #define RCR_STRIP_CRC 0x0200 #define RCR_RXEN 0x0100 #define TCR_EPH_LOOP 0x2000 #define TCR_NOCRC 0x0100 #define TCR_PAD_EN 0x0080 #define TCR_FORCOL 0x0004 #define TCR_LOOP 0x0002 #define TCR_TXEN 0x0001 #define INT_MD 0x80 #define INT_ERCV 0x40 #define INT_EPH 0x20 #define INT_RX_OVRN 0x10 #define INT_ALLOC 0x08 #define INT_TX_EMPTY 0x04 #define INT_TX 0x02 #define INT_RCV 0x01 #define CTR_AUTO_RELEASE 0x0800 #define CTR_RELOAD 0x0002 #define CTR_STORE 0x0001 #define RS_ALGNERR 0x8000 #define RS_BRODCAST 0x4000 #define RS_BADCRC 0x2000 #define RS_ODDFRAME 0x1000 #define RS_TOOLONG 0x0800 #define RS_TOOSHORT 0x0400 #define RS_MULTICAST 0x0001 /* Update interrupt status. */ static void smc91c111_update(smc91c111_state *s) { int level; if (s->tx_fifo_len == 0) s->int_level |= INT_TX_EMPTY; if (s->tx_fifo_done_len != 0) s->int_level |= INT_TX; level = (s->int_level & s->int_mask) != 0; pic_set_irq_new(s->pic, s->irq, level); } /* Try to allocate a packet. Returns 0x80 on failure. */ static int smc91c111_allocate_packet(smc91c111_state *s) { int i; if (s->allocated == (1 << NUM_PACKETS) - 1) { return 0x80; } for (i = 0; i < NUM_PACKETS; i++) { if ((s->allocated & (1 << i)) == 0) break; } s->allocated |= 1 << i; return i; } /* Process a pending TX allocate. */ static void smc91c111_tx_alloc(smc91c111_state *s) { s->tx_alloc = smc91c111_allocate_packet(s); if (s->tx_alloc == 0x80) return; s->int_level |= INT_ALLOC; smc91c111_update(s); } /* Remove and item from the RX FIFO. */ static void smc91c111_pop_rx_fifo(smc91c111_state *s) { int i; s->rx_fifo_len--; if (s->rx_fifo_len) { for (i = 0; i < s->rx_fifo_len; i++) s->rx_fifo[i] = s->rx_fifo[i + 1]; s->int_level |= INT_RCV; } else { s->int_level &= ~INT_RCV; } smc91c111_update(s); } /* Remove an item from the TX completion FIFO. */ static void smc91c111_pop_tx_fifo_done(smc91c111_state *s) { int i; if (s->tx_fifo_done_len == 0) return; s->tx_fifo_done_len--; for (i = 0; i < s->tx_fifo_done_len; i++) s->tx_fifo_done[i] = s->tx_fifo_done[i + 1]; } /* Release the memory allocated to a packet. */ static void smc91c111_release_packet(smc91c111_state *s, int packet) { s->allocated &= ~(1 << packet); if (s->tx_alloc == 0x80) smc91c111_tx_alloc(s); } /* Flush the TX FIFO. */ static void smc91c111_do_tx(smc91c111_state *s) { int i; int len; int control; int add_crc; int packetnum; uint8_t *p; if ((s->tcr & TCR_TXEN) == 0) return; if (s->tx_fifo_len == 0) return; for (i = 0; i < s->tx_fifo_len; i++) { packetnum = s->tx_fifo[i]; p = &s->data[packetnum][0]; /* Set status word. */ *(p++) = 0x01; *(p++) = 0x40; len = *(p++); len |= ((int)*(p++)) << 8; len -= 6; control = p[len + 1]; if (control & 0x20) len++; /* ??? This overwrites the data following the buffer. Don't know what real hardware does. */ if (len < 64 && (s->tcr & TCR_PAD_EN)) { memset(p + len, 0, 64 - len); len = 64; } #if 0 /* The card is supposed to append the CRC to the frame. However none of the other network traffic has the CRC appended. Suspect this is low level ethernet detail we don't need to worry about. */ add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0; if (add_crc) { uint32_t crc; crc = crc32(~0, p, len); memcpy(p + len, &crc, 4); len += 4; } #else add_crc = 0; #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; qemu_send_packet(s->vc, p, len); } s->tx_fifo_len = 0; smc91c111_update(s); } /* Add a packet to the TX FIFO. */ static void smc91c111_queue_tx(smc91c111_state *s, int packet) { if (s->tx_fifo_len == NUM_PACKETS) return; s->tx_fifo[s->tx_fifo_len++] = packet; smc91c111_do_tx(s); } static void smc91c111_reset(smc91c111_state *s) { s->bank = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->allocated = 0; s->packet_num = 0; s->tx_alloc = 0; s->tcr = 0; s->rcr = 0; s->cr = 0xa0b1; s->ctr = 0x1210; s->ptr = 0; s->ercv = 0x1f; s->int_level = INT_TX_EMPTY; s->int_mask = 0; smc91c111_update(s); } #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8) static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; offset -= s->base; if (offset == 14) { s->bank = value; return; } if (offset == 15) return; switch (s->bank) { case 0: switch (offset) { case 0: /* TCR */ SET_LOW(tcr, value); return; case 1: SET_HIGH(tcr, value); return; case 4: /* RCR */ SET_LOW(rcr, value); return; case 5: SET_HIGH(rcr, value); if (s->rcr & RCR_SOFT_RST) smc91c111_reset(s); return; case 10: case 11: /* RPCR */ /* Ignored */ return; } break; case 1: switch (offset) { case 0: /* CONFIG */ SET_LOW(cr, value); return; case 1: SET_HIGH(cr,value); return; case 2: case 3: /* BASE */ case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ /* Not implemented. */ return; case 10: /* Genral Purpose */ SET_LOW(gpr, value); return; case 11: SET_HIGH(gpr, value); return; case 12: /* Control */ if (value & 1) fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); if (value & 2) fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); value &= ~3; SET_LOW(ctr, value); return; case 13: SET_HIGH(ctr, value); return; } break; case 2: switch (offset) { case 0: /* MMU Command */ switch (value >> 5) { case 0: /* no-op */ break; case 1: /* Allocate for TX. */ s->tx_alloc = 0x80; s->int_level &= ~INT_ALLOC; smc91c111_update(s); smc91c111_tx_alloc(s); break; case 2: /* Reset MMU. */ s->allocated = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->tx_alloc = 0; break; case 3: /* Remove from RX FIFO. */ smc91c111_pop_rx_fifo(s); break; case 4: /* Remove from RX FIFO and release. */ if (s->rx_fifo_len > 0) { smc91c111_release_packet(s, s->rx_fifo[0]); } smc91c111_pop_rx_fifo(s); break; case 5: /* Release. */ smc91c111_release_packet(s, s->packet_num); break; case 6: /* Add to TX FIFO. */ smc91c111_queue_tx(s, s->packet_num); break; case 7: /* Reset TX FIFO. */ s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; break; } return; case 1: /* Ignore. */ return; case 2: /* Packet Number Register */ s->packet_num = value; return; case 3: case 4: case 5: /* Should be readonly, but linux writes to them anyway. Ignore. */ return; case 6: /* Pointer */ SET_LOW(ptr, value); return; case 7: SET_HIGH(ptr, value); return; case 8: case 9: case 10: case 11: /* Data */ { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#ifndef MCUCONF_H
#define MCUCONF_H

/*
 * STM32F0xx drivers configuration.
 * The following settings override the default settings present in
 * the various device driver implementation headers.
 * Note that the settings for each driver only have effect if the whole
 * driver is enabled in halconf.h.
 *
 * IRQ priorities:
 * 3...0       Lowest...Highest.
 *
 * DMA priorities:
 * 0...3        Lowest...Highest.
 */

#define STM32F0xx_MCUCONF

/*
 * HAL driver system settings.
 */
#define STM32_NO_INIT                       FALSE
#define STM32_PVD_ENABLE                    FALSE
#define STM32_PLS                           STM32_PLS_LEV0
#define STM32_HSI_ENABLED                   TRUE
#define STM32_HSI14_ENABLED                 TRUE
#define STM32_HSI48_ENABLED                 FALSE
#define STM32_LSI_ENABLED                   TRUE
#define STM32_HSE_ENABLED                   FALSE
#define STM32_LSE_ENABLED                   FALSE
#define STM32_SW                            STM32_SW_PLL
#define STM32_PLLSRC                        STM32_PLLSRC_HSI_DIV2
#define STM32_PREDIV_VALUE                  1
#define STM32_PLLMUL_VALUE                  12
#define STM32_HPRE                          STM32_HPRE_DIV1
#define STM32_PPRE                          STM32_PPRE_DIV1
#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK
#define STM32_MCOPRE                        STM32_MCOPRE_DIV1
#define STM32_PLLNODIV                      STM32_PLLNODIV_DIV2
#define STM32_USBSW                         STM32_USBSW_HSI48
#define STM32_CECSW                         STM32_CECSW_HSI
#define STM32_I2C1SW                        STM32_I2C1SW_HSI
#define STM32_USART1SW                      STM32_USART1SW_PCLK
#define STM32_RTCSEL                        STM32_RTCSEL_LSI

/*
 * ADC driver system settings.
 */
#define STM32_ADC_USE_ADC1                  TRUE
#define STM32_ADC_ADC1_CKMODE               STM32_ADC_CKMODE_ADCCLK
#define STM32_ADC_ADC1_DMA_PRIORITY         2
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY     2
#define STM32_ADC_ADC1_DMA_STREAM           STM32_DMA_STREAM_ID(1, 1)

/*
 * EXT driver system settings.
 */
#define STM32_EXT_EXTI0_1_IRQ_PRIORITY      3
#define STM32_EXT_EXTI2_3_IRQ_PRIORITY      3
#define STM32_EXT_EXTI4_15_IRQ_PRIORITY     3
#define STM32_EXT_EXTI16_IRQ_PRIORITY       3
#define STM32_EXT_EXTI17_20_IRQ_PRIORITY    3
#define STM32_EXT_EXTI21_22_IRQ_PRIORITY    3

/*
 * GPT driver system settings.
 */
#define STM32_GPT_USE_TIM1                  FALSE
#define STM32_GPT_USE_TIM2                  FALSE
#define STM32_GPT_USE_TIM3                  FALSE
#define STM32_GPT_USE_TIM14                 FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY         2
#define STM32_GPT_TIM2_IRQ_PRIORITY         2
#define STM32_GPT_TIM3_IRQ_PRIORITY         2
#define STM32_GPT_TIM14_IRQ_PRIORITY        2

/*
 * I2C driver system settings.
 */
#define STM32_I2C_USE_I2C1                  FALSE
#define STM32_I2C_USE_I2C2                  FALSE
#define STM32_I2C_BUSY_TIMEOUT              50
#define STM32_I2C_I2C1_IRQ_PRIORITY         3
#define STM32_I2C_I2C2_IRQ_PRIORITY         3
#define STM32_I2C_USE_DMA                   TRUE
#define STM32_I2C_I2C1_DMA_PRIORITY         1
#define STM32_I2C_I2C2_DMA_PRIORITY         1
#define STM32_I2C_I2C1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 3)
#define STM32_I2C_I2C1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2C_I2C2_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 5)
#define STM32_I2C_I2C2_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 4)
#define STM32_I2C_DMA_ERROR_HOOK(i2cp)      osalSysHalt("DMA failure")

/*
 * I2S driver system settings.
 */
#define STM32_I2S_USE_SPI1                  FALSE
#define STM32_I2S_USE_SPI2                  FALSE
#define STM32_I2S_SPI1_MODE                 (STM32_I2S_MODE_MASTER |        \
                                             STM32_I2S_MODE_RX)
#define STM32_I2S_SPI2_MODE                 (STM32_I2S_MODE_MASTER |        \
                                             STM32_I2S_MODE_RX)
#define STM32_I2S_SPI1_IRQ_PRIORITY         2
#define STM32_I2S_SPI2_IRQ_PRIORITY         2
#define STM32_I2S_SPI1_DMA_PRIORITY         1
#define STM32_I2S_SPI2_DMA_PRIORITY         1
#define STM32_I2S_SPI1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2S_SPI1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 3)
#define STM32_I2S_SPI2_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 4)
#define STM32_I2S_SPI2_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 5)
#define STM32_I2S_DMA_ERROR_HOOK(i2sp)      osalSysHalt("DMA failure")

/*
 * ICU driver system settings.
 */
#define STM32_ICU_USE_TIM1                  FALSE
#define STM32_ICU_USE_TIM2                  FALSE
#define STM32_ICU_USE_TIM3                  FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY         3
#define STM32_ICU_TIM2_IRQ_PRIORITY         3
#define STM32_ICU_TIM3_IRQ_PRIORITY         3

/*
 * PWM driver system settings.
 */
#define STM32_PWM_USE_ADVANCED              FALSE
#define STM32_PWM_USE_TIM1                  FALSE
#define STM32_PWM_USE_TIM2                  FALSE
#define STM32_PWM_USE_TIM3                  FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY         3
#define STM32_PWM_TIM2_IRQ_PRIORITY         3
#define STM32_PWM_TIM3_IRQ_PRIORITY         3

/*
 * SERIAL driver system settings.
 */
#define STM32_SERIAL_USE_USART1             FALSE
#define STM32_SERIAL_USE_USART2             FALSE
#define STM32_SERIAL_USART1_PRIORITY        3
#define STM32_SERIAL_USART2_PRIORITY        3

/*
 * SPI driver system settings.
 */
#define STM32_SPI_USE_SPI1                  FALSE
#define STM32_SPI_USE_SPI2                  FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY         1
#define STM32_SPI_SPI2_DMA_PRIORITY         1
#define STM32_SPI_SPI1_IRQ_PRIORITY         2
#define STM32_SPI_SPI2_IRQ_PRIORITY         2
#define STM32_SPI_SPI1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2)
#define STM32_SPI_SPI1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 3)
#define STM32_SPI_SPI2_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 4)
#define STM32_SPI_SPI2_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 5)
#define STM32_SPI_DMA_ERROR_HOOK(spip)      osalSysHalt("DMA failure")

/*
 * ST driver system settings.
 */
#define STM32_ST_IRQ_PRIORITY               2
#define STM32_ST_USE_TIMER                  2

/*
 * UART driver system settings.
 */
#define STM32_UART_USE_USART1               FALSE
#define STM32_UART_USE_USART2               FALSE
#define STM32_UART_USART1_IRQ_PRIORITY      3
#define STM32_UART_USART2_IRQ_PRIORITY      3
#define STM32_UART_USART1_DMA_PRIORITY      0
#define STM32_UART_USART2_DMA_PRIORITY      0
#define STM32_UART_USART1_RX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 3)
#define STM32_UART_USART1_TX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 2)
#define STM32_UART_USART2_RX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 5)
#define STM32_UART_USART2_TX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 4)
#define STM32_UART_DMA_ERROR_HOOK(uartp)    osalSysHalt("DMA failure")

/*
 * WDG driver system settings.
 */
#define STM32_WDG_USE_IWDG                  FALSE

#endif /* MCUCONF_H */