1 /* $NetBSD: shmif_busops.c,v 1.8 2011/01/12 16:12:30 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.8 2011/01/12 16:12:30 pooka Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/atomic.h> 35 36 #ifndef _KERNEL 37 #include <assert.h> 38 #include <stdbool.h> 39 #include <string.h> 40 41 #define KASSERT(a) assert(a) 42 #else 43 #include <rump/rumpuser.h> 44 #endif 45 46 #include "shmifvar.h" 47 48 uint32_t 49 shmif_advance(uint32_t oldoff, uint32_t delta) 50 { 51 uint32_t newoff; 52 53 newoff = oldoff + delta; 54 if (newoff >= BUSMEM_DATASIZE) 55 newoff -= BUSMEM_DATASIZE; 56 return newoff; 57 } 58 59 uint32_t 60 shmif_busread(struct shmif_mem *busmem, void *dest, uint32_t off, size_t len, 61 bool *wrap) 62 { 63 size_t chunk; 64 65 KASSERT(len < (BUSMEM_DATASIZE/2) && off <= BUSMEM_DATASIZE); 66 chunk = MIN(len, BUSMEM_DATASIZE - off); 67 memcpy(dest, busmem->shm_data + off, chunk); 68 len -= chunk; 69 70 if (off + chunk == BUSMEM_DATASIZE) 71 *wrap = true; 72 73 if (len == 0) { 74 return (off + chunk) % BUSMEM_DATASIZE; 75 } 76 77 /* finish reading */ 78 memcpy((uint8_t *)dest + chunk, busmem->shm_data, len); 79 return len; 80 } 81 82 void 83 shmif_advancefirst(struct shmif_mem *busmem, uint32_t off, size_t len) 84 { 85 86 while (off <= busmem->shm_first + sizeof(struct shmif_pkthdr) 87 && off+len > busmem->shm_first) { 88 DPRINTF(("advancefirst: old offset %d, ", busmem->shm_first)); 89 busmem->shm_first = shmif_nextpktoff(busmem, busmem->shm_first); 90 DPRINTF(("new offset: %d\n", busmem->shm_first)); 91 } 92 } 93 94 uint32_t 95 shmif_buswrite(struct shmif_mem *busmem, uint32_t off, void *data, size_t len, 96 bool *wrap) 97 { 98 size_t chunk; 99 bool filledbus; 100 101 KASSERT(len < (BUSMEM_DATASIZE/2) && off <= BUSMEM_DATASIZE); 102 103 chunk = MIN(len, BUSMEM_DATASIZE - off); 104 len -= chunk; 105 filledbus = (off+chunk == BUSMEM_DATASIZE); 106 107 shmif_advancefirst(busmem, off, chunk + (filledbus ? 1 : 0)); 108 109 memcpy(busmem->shm_data + off, data, chunk); 110 111 DPRINTF(("buswrite: wrote %d bytes to %d", chunk, off)); 112 113 if (filledbus) { 114 *wrap = true; 115 } 116 117 if (len == 0) { 118 DPRINTF(("\n")); 119 return (off + chunk) % BUSMEM_DATASIZE; 120 } 121 122 DPRINTF((", wrapped bytes %d to 0\n", len)); 123 124 shmif_advancefirst(busmem, 0, len); 125 126 /* finish writing */ 127 memcpy(busmem->shm_data, (uint8_t *)data + chunk, len); 128 return len; 129 } 130 131 uint32_t 132 shmif_nextpktoff(struct shmif_mem *busmem, uint32_t oldoff) 133 { 134 struct shmif_pkthdr sp; 135 bool dummy; 136 137 shmif_busread(busmem, &sp, oldoff, sizeof(sp), &dummy); 138 KASSERT(sp.sp_len < BUSMEM_DATASIZE); 139 140 return shmif_advance(oldoff, sizeof(sp) + sp.sp_len); 141 } 142