[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
This commit is contained in:
parent
9ee9b9205c
commit
747ed9b516
|
@ -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 |
|
||||
|
|
|
@ -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.支持情况
|
||||
|
||||
| 驱动 | 支持情况 | 备注 |
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -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)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pl031_rtc_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
static rt_err_t pl031_rtc_init(void)
|
||||
{
|
||||
pl031_write32(RTC_CR, RTC_CR_OPEN);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pl031_rtc_close(rt_device_t dev)
|
||||
static rt_err_t pl031_get_secs(time_t *sec)
|
||||
{
|
||||
pl031_write32(RTC_CR, RTC_CR_CLOSE);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pl031_rtc_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
|
||||
switch (cmd)
|
||||
if (sec != 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;
|
||||
}
|
||||
*(rt_uint32_t *)sec = pl031_read32(RTC_DR);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
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_set_secs(time_t *sec)
|
||||
{
|
||||
pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
|
||||
return size;
|
||||
if (sec != RT_NULL)
|
||||
{
|
||||
pl031_write32(RTC_LR, *(rt_uint32_t *)sec);
|
||||
|
||||
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)
|
||||
#ifdef RT_USING_ALARM
|
||||
static rt_err_t pl031_set_alarm(struct rt_rtc_wkalarm *alarm)
|
||||
{
|
||||
pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
|
||||
return size;
|
||||
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;
|
||||
}
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
const static struct rt_device_ops pl031_rtc_ops =
|
||||
static rt_err_t pl031_get_alarm(struct rt_rtc_wkalarm *alarm)
|
||||
{
|
||||
if (alarm != RT_NULL)
|
||||
{
|
||||
*alarm = _wkalarm;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
#endif /* RT_USING_ALARM */
|
||||
|
||||
static rt_err_t pl031_get_timeval(struct timeval *tv)
|
||||
{
|
||||
if (tv != RT_NULL)
|
||||
{
|
||||
tv->tv_sec = pl031_read32(RTC_DR);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
static rt_err_t pl031_set_timeval(struct timeval *tv)
|
||||
{
|
||||
if (tv != RT_NULL)
|
||||
{
|
||||
pl031_write32(RTC_LR, *(rt_uint32_t *)tv->tv_sec);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
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
|
||||
.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,
|
||||
};
|
||||
|
||||
#ifdef RT_USING_ALARM
|
||||
static void rt_hw_rtc_isr(int irqno, void *param)
|
||||
{
|
||||
rt_uint32_t rtcmis = pl031_read32(RTC_MIS);
|
||||
|
||||
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)
|
||||
{
|
||||
rt_memset(&rtc_device, 0, sizeof(rtc_device));
|
||||
|
||||
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;
|
||||
_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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,19 +23,21 @@ 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);
|
||||
#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.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 = p->tot_len + sizeof(virtio_net_dev->info[id].hdr);
|
||||
virtio_net_dev->info[id].hdr.csum_offset = 0;
|
||||
virtio_net_dev->info[id].hdr.num_buffers = 0;
|
||||
|
||||
pbuf_copy_partial(p, virtio_net_dev->info[id].rx_buffer, p->tot_len, 0);
|
||||
|
||||
virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id);
|
||||
virtio_free_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1);
|
||||
|
@ -44,7 +46,7 @@ static rt_err_t virtio_net_tx(rt_device_t dev, struct pbuf *p)
|
|||
VIRTIO_VA2PA(&virtio_net_dev->info[id].hdr), VIRTIO_NET_HDR_SIZE, VIRTQ_DESC_F_NEXT, id + 1);
|
||||
|
||||
virtio_fill_desc(virtio_dev, VIRTIO_NET_QUEUE_TX, id + 1,
|
||||
VIRTIO_VA2PA(p->payload), p->tot_len, 0, 0);
|
||||
VIRTIO_VA2PA(virtio_net_dev->info[id].rx_buffer), p->tot_len, 0, 0);
|
||||
|
||||
virtio_submit_chain(virtio_dev, VIRTIO_NET_QUEUE_TX, id);
|
||||
|
||||
|
@ -56,8 +58,6 @@ static rt_err_t virtio_net_tx(rt_device_t dev, struct pbuf *p)
|
|||
#ifdef RT_USING_SMP
|
||||
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;
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue