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