0001
0002
0003
0004
0005
0006
0007 #include "vbox_drv.h"
0008 #include "vboxvideo_vbe.h"
0009 #include "hgsmi_defs.h"
0010
0011
0012 static u32 hgsmi_hash_process(u32 hash, const u8 *data, int size)
0013 {
0014 while (size--) {
0015 hash += *data++;
0016 hash += (hash << 10);
0017 hash ^= (hash >> 6);
0018 }
0019
0020 return hash;
0021 }
0022
0023 static u32 hgsmi_hash_end(u32 hash)
0024 {
0025 hash += (hash << 3);
0026 hash ^= (hash >> 11);
0027 hash += (hash << 15);
0028
0029 return hash;
0030 }
0031
0032
0033 static u32 hgsmi_checksum(u32 offset,
0034 const struct hgsmi_buffer_header *header,
0035 const struct hgsmi_buffer_tail *tail)
0036 {
0037 u32 checksum;
0038
0039 checksum = hgsmi_hash_process(0, (u8 *)&offset, sizeof(offset));
0040 checksum = hgsmi_hash_process(checksum, (u8 *)header, sizeof(*header));
0041
0042 checksum = hgsmi_hash_process(checksum, (u8 *)tail, 4);
0043
0044 return hgsmi_hash_end(checksum);
0045 }
0046
0047 void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size,
0048 u8 channel, u16 channel_info)
0049 {
0050 struct hgsmi_buffer_header *h;
0051 struct hgsmi_buffer_tail *t;
0052 size_t total_size;
0053 dma_addr_t offset;
0054
0055 total_size = size + sizeof(*h) + sizeof(*t);
0056 h = gen_pool_dma_alloc(guest_pool, total_size, &offset);
0057 if (!h)
0058 return NULL;
0059
0060 t = (struct hgsmi_buffer_tail *)((u8 *)h + sizeof(*h) + size);
0061
0062 h->flags = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
0063 h->data_size = size;
0064 h->channel = channel;
0065 h->channel_info = channel_info;
0066 memset(&h->u.header_data, 0, sizeof(h->u.header_data));
0067
0068 t->reserved = 0;
0069 t->checksum = hgsmi_checksum(offset, h, t);
0070
0071 return (u8 *)h + sizeof(*h);
0072 }
0073
0074 void hgsmi_buffer_free(struct gen_pool *guest_pool, void *buf)
0075 {
0076 struct hgsmi_buffer_header *h =
0077 (struct hgsmi_buffer_header *)((u8 *)buf - sizeof(*h));
0078 size_t total_size = h->data_size + sizeof(*h) +
0079 sizeof(struct hgsmi_buffer_tail);
0080
0081 gen_pool_free(guest_pool, (unsigned long)h, total_size);
0082 }
0083
0084 int hgsmi_buffer_submit(struct gen_pool *guest_pool, void *buf)
0085 {
0086 phys_addr_t offset;
0087
0088 offset = gen_pool_virt_to_phys(guest_pool, (unsigned long)buf -
0089 sizeof(struct hgsmi_buffer_header));
0090 outl(offset, VGA_PORT_HGSMI_GUEST);
0091
0092 mb();
0093
0094 return 0;
0095 }