From 747ed9b516ed53f84bfc47479835c82ac36eef5e Mon Sep 17 00:00:00 2001 From: GUI <39894654+GuEe-GUI@users.noreply.github.com> Date: Sat, 30 Jul 2022 14:04:25 +0800 Subject: [PATCH] [bsp/qemu-virt64-aarch64] Update drivers' code (#6194) * [bsp/qemu-virt64-aarch64] RTC add hard alarm support * [bsp/qemu-virt64-aarch64] Fixup VirtIO-GPU init buffer fail by cpu out-of-order execution * [bsp/qemu-virt64-aarch64] Fixup VirtIO-NET transmit payload split Add Virtio-GPU cursor demo --- bsp/qemu-virt64-aarch64/README.md | 9 + bsp/qemu-virt64-aarch64/README_zh.md | 9 + .../applications/graphic.c | 13 ++ bsp/qemu-virt64-aarch64/driver/drv_rtc.c | 172 +++++++++++++----- .../driver/virtio/virtio_gpu.c | 6 +- .../driver/virtio/virtio_net.c | 67 +++---- .../driver/virtio/virtio_net.h | 24 ++- 7 files changed, 210 insertions(+), 90 deletions(-) diff --git a/bsp/qemu-virt64-aarch64/README.md b/bsp/qemu-virt64-aarch64/README.md index 2e050e0123..f350b3c641 100644 --- a/bsp/qemu-virt64-aarch64/README.md +++ b/bsp/qemu-virt64-aarch64/README.md @@ -50,6 +50,15 @@ Use VirtIO-Console in new terminal by: telnet 127.0.0.1 4321 ```` +If use tap net mode with tap0 card, modify qemu run script config +``` +-netdev user,id=net0 +``` +to +``` +-netdev tap,id=net0,ifname=tap0 +``` + ## 4. Condition | Driver | Condition | Remark | diff --git a/bsp/qemu-virt64-aarch64/README_zh.md b/bsp/qemu-virt64-aarch64/README_zh.md index dcefee4c65..f809505b23 100644 --- a/bsp/qemu-virt64-aarch64/README_zh.md +++ b/bsp/qemu-virt64-aarch64/README_zh.md @@ -51,6 +51,15 @@ msh /> telnet 127.0.0.1 4321 ``` +如果使用tap网卡模式,以设备tap0为例,将qemu运行脚本 +``` +-netdev user,id=net0 +``` +修改为 +``` +-netdev tap,id=net0,ifname=tap0 +``` + ## 4.支持情况 | 驱动 | 支持情况 | 备注 | diff --git a/bsp/qemu-virt64-aarch64/applications/graphic.c b/bsp/qemu-virt64-aarch64/applications/graphic.c index 2207f9f887..933e970428 100644 --- a/bsp/qemu-virt64-aarch64/applications/graphic.c +++ b/bsp/qemu-virt64-aarch64/applications/graphic.c @@ -24,6 +24,7 @@ static rt_uint32_t cur_points[2]; static rt_uint32_t cur_last_points[2]; static rt_bool_t cur_event_sync; static rt_uint32_t color[2] = { 0xff0000, 0x0000ff }; +static rt_uint8_t cursor[VIRTIO_GPU_CURSOR_IMG_SIZE] ALIGN(VIRTIO_PAGE_SIZE); void tablet_event_handler(struct virtio_input_event event) { @@ -100,6 +101,8 @@ void graphic_thread(void *param) if (graphic_info.framebuffer != RT_NULL) { + int i = 0; + rt_memset(graphic_info.framebuffer, 0xff, graphic_info.width * graphic_info.height * graphic_info.bits_per_pixel); @@ -111,6 +114,16 @@ void graphic_thread(void *param) rt_device_control(device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info); + while (i < sizeof(cursor) / sizeof(rt_uint32_t)) + { + /* R: 0x4c G: 0xaf B: 0x50 A: 0.8 */ + ((rt_uint32_t *)cursor)[i] = 0xcc4caf50; + ++i; + } + + rt_device_control(device, VIRTIO_DEVICE_CTRL_CURSOR_SETUP, cursor); + rt_device_control(device, VIRTIO_DEVICE_CTRL_CURSOR_MOVE, (rt_uint32_t[]){0, 0}); + gpu_dev = device; } } diff --git a/bsp/qemu-virt64-aarch64/driver/drv_rtc.c b/bsp/qemu-virt64-aarch64/driver/drv_rtc.c index db7e118c7c..55c7b6dc63 100644 --- a/bsp/qemu-virt64-aarch64/driver/drv_rtc.c +++ b/bsp/qemu-virt64-aarch64/driver/drv_rtc.c @@ -1,13 +1,15 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-11-4 GuEe-GUI first version + * 2022-07-15 GuEe-GUI add alarm ops support */ +#include #include #include #include @@ -28,8 +30,13 @@ #define RTC_CR_OPEN 1 #define RTC_CR_CLOSE 0 +#define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */ +#define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */ -static struct hw_rtc_device rtc_device; +static rt_rtc_dev_t _rtc_device; +#ifdef RT_USING_ALARM +static struct rt_rtc_wkalarm _wkalarm; +#endif rt_inline rt_uint32_t pl031_read32(rt_ubase_t offset) { @@ -41,76 +48,157 @@ rt_inline void pl031_write32(rt_ubase_t offset, rt_uint32_t value) (*((volatile unsigned int *)(PL031_RTC_BASE + offset))) = value; } -static rt_err_t pl031_rtc_init(rt_device_t dev) +static rt_err_t pl031_rtc_init(void) { + pl031_write32(RTC_CR, RTC_CR_OPEN); + return RT_EOK; } -static rt_err_t pl031_rtc_open(rt_device_t dev, rt_uint16_t oflag) +static rt_err_t pl031_get_secs(time_t *sec) { - pl031_write32(RTC_CR, RTC_CR_OPEN); - return RT_EOK; + if (sec != RT_NULL) + { + *(rt_uint32_t *)sec = pl031_read32(RTC_DR); + + return RT_EOK; + } + + return -RT_EINVAL; } -static rt_err_t pl031_rtc_close(rt_device_t dev) +static rt_err_t pl031_set_secs(time_t *sec) { - pl031_write32(RTC_CR, RTC_CR_CLOSE); - return RT_EOK; + if (sec != RT_NULL) + { + pl031_write32(RTC_LR, *(rt_uint32_t *)sec); + + return RT_EOK; + } + + return -RT_EINVAL; } -static rt_err_t pl031_rtc_control(rt_device_t dev, int cmd, void *args) +#ifdef RT_USING_ALARM +static rt_err_t pl031_set_alarm(struct rt_rtc_wkalarm *alarm) { + if (alarm != RT_NULL) + { + rt_uint32_t imsc, time; + + _wkalarm.enable = alarm->enable; + _wkalarm.tm_hour = alarm->tm_hour; + _wkalarm.tm_min = alarm->tm_min; + _wkalarm.tm_sec = alarm->tm_sec; + + time = pl031_read32(RTC_DR); + + /* Back to 08:00 today */ + time = time / (3600 * 24) * (3600 * 24); + + /* Get alarm time */ + time += alarm->tm_hour * 3600 + alarm->tm_min * 60 + alarm->tm_sec; + + pl031_write32(RTC_MR, time); + + /* Clear any pending alarm interrupts. */ + pl031_write32(RTC_ICR, RTC_BIT_AI); + + imsc = pl031_read32(RTC_IMSC); + + if (alarm->enable) + { + pl031_write32(RTC_IMSC, imsc | RTC_BIT_AI); + } + else + { + pl031_write32(RTC_IMSC, imsc & ~RTC_BIT_AI); + } + + return RT_EOK; + } - RT_ASSERT(dev != RT_NULL); + return -RT_EINVAL; +} - switch (cmd) +static rt_err_t pl031_get_alarm(struct rt_rtc_wkalarm *alarm) +{ + if (alarm != RT_NULL) { - case RT_DEVICE_CTRL_RTC_GET_TIME: - *(rt_uint32_t *)args = pl031_read32(RTC_DR); - break; - case RT_DEVICE_CTRL_RTC_SET_TIME: - pl031_write32(RTC_LR, *(time_t *)args); - break; - default: - return RT_EINVAL; + *alarm = _wkalarm; + + return RT_EOK; } - return RT_EOK; + + return -RT_EINVAL; } +#endif /* RT_USING_ALARM */ -static rt_size_t pl031_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +static rt_err_t pl031_get_timeval(struct timeval *tv) { - pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer); - return size; + if (tv != RT_NULL) + { + tv->tv_sec = pl031_read32(RTC_DR); + + return RT_EOK; + } + + return -RT_EINVAL; } -static rt_size_t pl031_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +static rt_err_t pl031_set_timeval(struct timeval *tv) { - pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer); - return size; + if (tv != RT_NULL) + { + pl031_write32(RTC_LR, *(rt_uint32_t *)tv->tv_sec); + + return RT_EOK; + } + + return -RT_EINVAL; } -const static struct rt_device_ops pl031_rtc_ops = +static const struct rt_rtc_ops rtc_ops = { - .init = pl031_rtc_init, - .open = pl031_rtc_open, - .close = pl031_rtc_close, - .read = pl031_rtc_read, - .write = pl031_rtc_write, - .control = pl031_rtc_control + .init = pl031_rtc_init, + .get_secs = pl031_get_secs, + .set_secs = pl031_set_secs, +#ifdef RT_USING_ALARM + .get_alarm = pl031_get_alarm, + .set_alarm = pl031_set_alarm, +#else + .get_alarm = RT_NULL, + .set_alarm = RT_NULL, +#endif + .get_timeval = pl031_get_timeval, + .set_timeval = pl031_set_timeval, }; -int rt_hw_rtc_init(void) +#ifdef RT_USING_ALARM +static void rt_hw_rtc_isr(int irqno, void *param) { - rt_memset(&rtc_device, 0, sizeof(rtc_device)); + rt_uint32_t rtcmis = pl031_read32(RTC_MIS); - rtc_device.device.type = RT_Device_Class_RTC; - rtc_device.device.rx_indicate = RT_NULL; - rtc_device.device.tx_complete = RT_NULL; - rtc_device.device.ops = &pl031_rtc_ops; - rtc_device.device.user_data = RT_NULL; + if (rtcmis & RTC_BIT_AI) + { + pl031_write32(RTC_ICR, RTC_BIT_AI); + + rt_alarm_update(&_rtc_device.parent, 1); + } +} +#endif /* RT_USING_ALARM */ + +int rt_hw_rtc_init(void) +{ + _rtc_device.ops = &rtc_ops; /* register a rtc device */ - rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR); + rt_hw_rtc_register(&_rtc_device, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL); + +#ifdef RT_USING_ALARM + rt_hw_interrupt_install(PL031_RTC_IRQNUM, rt_hw_rtc_isr, RT_NULL, "rtc"); + rt_hw_interrupt_umask(PL031_RTC_IRQNUM); +#endif /* RT_USING_ALARM */ return 0; } diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_gpu.c b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_gpu.c index c6849ae250..06ea662f95 100644 --- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_gpu.c +++ b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_gpu.c @@ -84,10 +84,6 @@ static void virtio_gpu_ctrl_send_command(struct virtio_gpu_device *virtio_gpu_de #endif } - rt_hw_dsb(); - - virtio_gpu_dev->info[idx[0]].ctrl_valid = RT_TRUE; - rt_memcpy(&virtio_gpu_dev->gpu_request, cmd, cmd_len); virtio_fill_desc(virtio_dev, VIRTIO_GPU_QUEUE_CTRL, idx[0], @@ -98,6 +94,8 @@ static void virtio_gpu_ctrl_send_command(struct virtio_gpu_device *virtio_gpu_de rt_memset(ret_res, 0, res_len); + virtio_gpu_dev->info[idx[0]].ctrl_valid = RT_TRUE; + virtio_submit_chain(virtio_dev, VIRTIO_GPU_QUEUE_CTRL, idx[0]); virtio_queue_notify(virtio_dev, VIRTIO_GPU_QUEUE_CTRL); diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.c b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.c index 38d45766ac..c44793be2b 100644 --- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.c +++ b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.c @@ -23,41 +23,41 @@ static rt_err_t virtio_net_tx(rt_device_t dev, struct pbuf *p) struct virtio_device *virtio_dev = &virtio_net_dev->virtio_dev; struct virtq *queue_tx = &virtio_dev->queues[VIRTIO_NET_QUEUE_TX]; - while (p != RT_NULL) - { #ifdef RT_USING_SMP - rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock); + rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock); #endif - id = (queue_tx->avail->idx * 2) % queue_tx->num; - virtio_net_dev->info[id].hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - virtio_net_dev->info[id].hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; - virtio_net_dev->info[id].hdr.hdr_len = 0; - virtio_net_dev->info[id].hdr.gso_size = 0; - virtio_net_dev->info[id].hdr.csum_start = 0; - virtio_net_dev->info[id].hdr.csum_offset = p->tot_len + sizeof(virtio_net_dev->info[id].hdr); + id = (queue_tx->avail->idx * 2) % queue_tx->num; + + virtio_net_dev->info[id].hdr.flags = 0; + virtio_net_dev->info[id].hdr.gso_type = 0; + virtio_net_dev->info[id].hdr.hdr_len = 0; + virtio_net_dev->info[id].hdr.gso_size = 0; + virtio_net_dev->info[id].hdr.csum_start = 0; + virtio_net_dev->info[id].hdr.csum_offset = 0; + virtio_net_dev->info[id].hdr.num_buffers = 0; - virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id); - virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1); + pbuf_copy_partial(p, virtio_net_dev->info[id].rx_buffer, p->tot_len, 0); - virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id, - VIRTIO_VA2PA(&virtio_net_dev->info[id].hdr), VIRTIO_NET_HDR_SIZE, VIRTQ_DESC_F_NEXT, id + 1); + virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id); + virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1); - virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1, - VIRTIO_VA2PA(p->payload), p->tot_len, 0, 0); + virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id, + VIRTIO_VA2PA(&virtio_net_dev->info[id].hdr), VIRTIO_NET_HDR_SIZE, VIRTQ_DESC_F_NEXT, id + 1); - virtio_submit_chain(virtio_dev, VIRTIO_NET_QUEUE_TX, id); + virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1, + VIRTIO_VA2PA(virtio_net_dev->info[id].rx_buffer), p->tot_len, 0, 0); - virtio_queue_notify(virtio_dev, VIRTIO_NET_QUEUE_TX); + virtio_submit_chain(virtio_dev, VIRTIO_NET_QUEUE_TX, id); - virtio_alloc_desc(virtio_dev, VIRTIO_NET_QUEUE_TX); - virtio_alloc_desc(virtio_dev, VIRTIO_NET_QUEUE_TX); + virtio_queue_notify(virtio_dev, VIRTIO_NET_QUEUE_TX); + + virtio_alloc_desc(virtio_dev, VIRTIO_NET_QUEUE_TX); + virtio_alloc_desc(virtio_dev, VIRTIO_NET_QUEUE_TX); #ifdef RT_USING_SMP - rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level); + rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level); #endif - p = p->next; - } return RT_EOK; } @@ -144,7 +144,7 @@ static rt_err_t virtio_net_init(rt_device_t dev) for (i = 0; i < queue_rx->num; ++i) { rt_uint16_t id = (i * 2) % queue_rx->num; - void *addr = virtio_net_dev->info[i].buffer; + void *addr = virtio_net_dev->info[i].tx_buffer; /* Descriptor for net_hdr */ virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_RX, id, @@ -185,7 +185,7 @@ static rt_err_t virtio_net_control(rt_device_t dev, int cmd, void *args) break; } - rt_memcpy(args, virtio_net_dev->mac, sizeof(virtio_net_dev->mac)); + rt_memcpy(args, virtio_net_dev->config->mac, sizeof(virtio_net_dev->config->mac)); break; default: status = -RT_EINVAL; @@ -232,7 +232,6 @@ static void virtio_net_isr(int irqno, void *param) rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) { - int i; static int dev_no = 0; char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; @@ -249,6 +248,8 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_net_dev->config = (struct virtio_net_config *)virtio_dev->mmio_config->config; + #ifdef RT_USING_SMP rt_spin_lock_init(&virtio_dev->spinlock); #endif @@ -258,14 +259,7 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( (1 << VIRTIO_NET_F_CTRL_VQ) | - (1 << VIRTIO_NET_F_GUEST_TSO4) | - (1 << VIRTIO_NET_F_GUEST_TSO6) | - (1 << VIRTIO_NET_F_GUEST_UFO) | - (1 << VIRTIO_NET_F_MRG_RXBUF) | - (1 << VIRTIO_F_RING_EVENT_IDX)) & - (1 << VIRTIO_NET_F_CSUM) & - (1 << VIRTIO_NET_F_GUEST_CSUM) & - (1 << VIRTIO_NET_F_MAC); + (1 << VIRTIO_F_RING_EVENT_IDX)); virtio_status_driver_ok(virtio_dev); @@ -285,11 +279,6 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) goto _alloc_fail; } - for (i = 0; i < sizeof(virtio_net_dev->mac) / sizeof(virtio_net_dev->mac[0]); ++i) - { - virtio_net_dev->mac[i] = virtio_dev->mmio_config->config[i]; - } - virtio_net_dev->parent.parent.type = RT_Device_Class_NetIf; virtio_net_dev->parent.parent.ops = &virtio_net_ops; virtio_net_dev->parent.eth_tx = virtio_net_tx; diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.h b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.h index ab41ccfead..369979019d 100644 --- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.h +++ b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_net.h @@ -71,28 +71,42 @@ struct virtio_net_hdr rt_uint16_t gso_size; rt_uint16_t csum_start; rt_uint16_t csum_offset; - rt_uint16_t num_buffers; /* Only if VIRTIO_NET_F_MRG_RXBUF */ + rt_uint16_t num_buffers; } __attribute__ ((packed)); #define VIRTIO_NET_MSS 1514 -/* Disable VIRTIO_NET_F_MRG_RXBUF */ -#define VIRTIO_NET_HDR_SIZE (sizeof(struct virtio_net_hdr) - sizeof(rt_uint16_t)) +#define VIRTIO_NET_HDR_SIZE (sizeof(struct virtio_net_hdr)) #define VIRTIO_NET_PAYLOAD_MAX_SIZE (VIRTIO_NET_HDR_SIZE + VIRTIO_NET_MSS) +struct virtio_net_config +{ + rt_uint8_t mac[6]; + rt_uint16_t status; + rt_uint16_t max_virtqueue_pairs; + rt_uint16_t mtu; + rt_uint32_t speed; + rt_uint8_t duplex; + rt_uint8_t rss_max_key_size; + rt_uint16_t rss_max_indirection_table_length; + rt_uint32_t supported_hash_types; +} __attribute__((packed)); + struct virtio_net_device { struct eth_device parent; struct virtio_device virtio_dev; - rt_uint8_t mac[6]; + struct virtio_net_config *config; struct { /* Transmit hdr */ struct virtio_net_hdr hdr; + /* Transmit buffer */ + rt_uint8_t tx_buffer[VIRTIO_NET_PAYLOAD_MAX_SIZE]; /* Receive buffer */ - rt_uint8_t buffer[VIRTIO_NET_PAYLOAD_MAX_SIZE]; + rt_uint8_t rx_buffer[VIRTIO_NET_PAYLOAD_MAX_SIZE]; } info[VIRTIO_NET_RTX_QUEUE_SIZE]; }; -- GitLab