1 /* $NetBSD: shmif_busops.c,v 1.4 2010/08/15 18:55:03 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by The Nokia Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: shmif_busops.c,v 1.4 2010/08/15 18:55:03 pooka Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/atomic.h> 35 36 #include "shmifvar.h" 37 38 #ifndef _KERNEL 39 #include <assert.h> 40 #define KASSERT(a) assert(a) 41 #else 42 #include <rump/rumpuser.h> 43 #endif 44 45 uint32_t 46 shmif_advance(uint32_t oldoff, uint32_t delta) 47 { 48 uint32_t newoff; 49 50 newoff = oldoff + delta; 51 if (newoff >= BUSMEM_DATASIZE) 52 newoff -= (BUSMEM_DATASIZE); 53 return newoff; 54 55 } 56 57 uint32_t 58 shmif_busread(struct shmif_mem *busmem, void *dest, uint32_t off, size_t len, 59 bool *wrap) 60 { 61 size_t chunk; 62 63 KASSERT(len < (BUSMEM_DATASIZE) && off <= BUSMEM_DATASIZE); 64 chunk = MIN(len, BUSMEM_DATASIZE - off); 65 memcpy(dest, busmem->shm_data + off, chunk); 66 len -= chunk; 67 68 if (len == 0) 69 return off + chunk; 70 71 /* else, wraps around */ 72 off = 0; 73 *wrap = true; 74 75 /* finish reading */ 76 memcpy((uint8_t *)dest + chunk, busmem->shm_data + off, len); 77 return off + len; 78 } 79 80 void 81 shmif_advancefirst(struct shmif_mem *busmem, uint32_t off, size_t len) 82 { 83 84 while (off <= busmem->shm_first + sizeof(struct shmif_pkthdr) 85 && off+len > busmem->shm_first) { 86 DPRINTF(("advancefirst: old offset %d, ", busmem->shm_first)); 87 busmem->shm_first = shmif_nextpktoff(busmem, busmem->shm_first); 88 DPRINTF(("new offset: %d\n", busmem->shm_first)); 89 } 90 } 91 92 uint32_t 93 shmif_buswrite(struct shmif_mem *busmem, uint32_t off, void *data, size_t len, 94 bool *wrap) 95 { 96 size_t chunk; 97 98 KASSERT(len < (BUSMEM_DATASIZE) && off <= BUSMEM_DATASIZE); 99 100 chunk = MIN(len, BUSMEM_DATASIZE - off); 101 len -= chunk; 102 103 shmif_advancefirst(busmem, off, chunk + (len ? 1 : 0)); 104 105 memcpy(busmem->shm_data + off, data, chunk); 106 107 DPRINTF(("buswrite: wrote %d bytes to %d", chunk, off)); 108 109 if (len == 0) { 110 DPRINTF(("\n")); 111 return off + chunk; 112 } 113 114 DPRINTF((", wrapped bytes %d to 0\n", len)); 115 116 /* else, wraps around */ 117 off = 0; 118 *wrap = true; 119 120 shmif_advancefirst(busmem, off, len); 121 122 /* finish writing */ 123 memcpy(busmem->shm_data + off, (uint8_t *)data + chunk, len); 124 return off + len; 125 } 126 127 uint32_t 128 shmif_nextpktoff(struct shmif_mem *busmem, uint32_t oldoff) 129 { 130 struct shmif_pkthdr sp; 131 bool dummy; 132 133 shmif_busread(busmem, &sp, oldoff, sizeof(sp), &dummy); 134 KASSERT(sp.sp_len < BUSMEM_DATASIZE); 135 136 return shmif_advance(oldoff, sizeof(sp) + sp.sp_len); 137 } 138