xref: /freebsd/sys/dev/bhnd/nvram/bhnd_nvram_iores.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1*77cb4d3eSLandon J. Fuller /*-
2*77cb4d3eSLandon J. Fuller  * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
3*77cb4d3eSLandon J. Fuller  * All rights reserved.
4*77cb4d3eSLandon J. Fuller  *
5*77cb4d3eSLandon J. Fuller  * Redistribution and use in source and binary forms, with or without
6*77cb4d3eSLandon J. Fuller  * modification, are permitted provided that the following conditions
7*77cb4d3eSLandon J. Fuller  * are met:
8*77cb4d3eSLandon J. Fuller  * 1. Redistributions of source code must retain the above copyright
9*77cb4d3eSLandon J. Fuller  *    notice, this list of conditions and the following disclaimer,
10*77cb4d3eSLandon J. Fuller  *    without modification.
11*77cb4d3eSLandon J. Fuller  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12*77cb4d3eSLandon J. Fuller  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13*77cb4d3eSLandon J. Fuller  *    redistribution must be conditioned upon including a substantially
14*77cb4d3eSLandon J. Fuller  *    similar Disclaimer requirement for further binary redistribution.
15*77cb4d3eSLandon J. Fuller  *
16*77cb4d3eSLandon J. Fuller  * NO WARRANTY
17*77cb4d3eSLandon J. Fuller  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*77cb4d3eSLandon J. Fuller  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*77cb4d3eSLandon J. Fuller  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20*77cb4d3eSLandon J. Fuller  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21*77cb4d3eSLandon J. Fuller  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22*77cb4d3eSLandon J. Fuller  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*77cb4d3eSLandon J. Fuller  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*77cb4d3eSLandon J. Fuller  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*77cb4d3eSLandon J. Fuller  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*77cb4d3eSLandon J. Fuller  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27*77cb4d3eSLandon J. Fuller  * THE POSSIBILITY OF SUCH DAMAGES.
28*77cb4d3eSLandon J. Fuller  */
29*77cb4d3eSLandon J. Fuller 
30*77cb4d3eSLandon J. Fuller #include <sys/param.h>
31*77cb4d3eSLandon J. Fuller #include <sys/bus.h>
32*77cb4d3eSLandon J. Fuller #include <sys/malloc.h>
33*77cb4d3eSLandon J. Fuller #include <sys/rman.h>
34*77cb4d3eSLandon J. Fuller 
35*77cb4d3eSLandon J. Fuller #include <machine/bus.h>
36*77cb4d3eSLandon J. Fuller 
37*77cb4d3eSLandon J. Fuller #include <dev/bhnd/bhnd.h>
38*77cb4d3eSLandon J. Fuller 
39*77cb4d3eSLandon J. Fuller #include "bhnd_nvram_private.h"
40*77cb4d3eSLandon J. Fuller 
41*77cb4d3eSLandon J. Fuller #include "bhnd_nvram_io.h"
42*77cb4d3eSLandon J. Fuller #include "bhnd_nvram_iovar.h"
43*77cb4d3eSLandon J. Fuller 
44*77cb4d3eSLandon J. Fuller /**
45*77cb4d3eSLandon J. Fuller  * BHND resource-backed NVRAM I/O context.
46*77cb4d3eSLandon J. Fuller  */
47*77cb4d3eSLandon J. Fuller struct bhnd_nvram_iores {
48*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_io	 io;		/**< common I/O instance state */
49*77cb4d3eSLandon J. Fuller 	struct bhnd_resource	*res;		/**< backing resource (borrowed ref) */
50*77cb4d3eSLandon J. Fuller 	size_t			 offset;	/**< offset within res */
51*77cb4d3eSLandon J. Fuller 	size_t			 size;		/**< size relative to the base offset */
52*77cb4d3eSLandon J. Fuller 	u_int			 bus_width;	/**< data type byte width to be used
53*77cb4d3eSLandon J. Fuller 						     when performing bus operations
54*77cb4d3eSLandon J. Fuller 						     on res. (1, 2, or 4 bytes) */
55*77cb4d3eSLandon J. Fuller };
56*77cb4d3eSLandon J. Fuller 
57*77cb4d3eSLandon J. Fuller BHND_NVRAM_IOPS_DEFN(iores);
58*77cb4d3eSLandon J. Fuller 
59*77cb4d3eSLandon J. Fuller /**
60*77cb4d3eSLandon J. Fuller  * Allocate and return a new I/O context backed by a borrowed reference to @p r.
61*77cb4d3eSLandon J. Fuller  *
62*77cb4d3eSLandon J. Fuller  * The caller is responsible for deallocating the returned I/O context via
63*77cb4d3eSLandon J. Fuller  * bhnd_nvram_io_free().
64*77cb4d3eSLandon J. Fuller  *
65*77cb4d3eSLandon J. Fuller  * @param	r		The resource to be mapped by the returned I/O
66*77cb4d3eSLandon J. Fuller  *				context.
67*77cb4d3eSLandon J. Fuller  * @param	offset		Offset
68*77cb4d3eSLandon J. Fuller  * @param	bus_width	The required I/O width (1, 2, or 4 bytes) to be
69*77cb4d3eSLandon J. Fuller  *				used when reading from @p r.
70*77cb4d3eSLandon J. Fuller  *
71*77cb4d3eSLandon J. Fuller  * @retval	bhnd_nvram_io	success.
72*77cb4d3eSLandon J. Fuller  * @retval	NULL		if allocation fails, or an invalid argument
73*77cb4d3eSLandon J. Fuller  *				is supplied.
74*77cb4d3eSLandon J. Fuller  */
75*77cb4d3eSLandon J. Fuller struct bhnd_nvram_io *
bhnd_nvram_iores_new(struct bhnd_resource * r,bus_size_t offset,bus_size_t size,u_int bus_width)76*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_new(struct bhnd_resource *r, bus_size_t offset,
77*77cb4d3eSLandon J. Fuller     bus_size_t size, u_int bus_width)
78*77cb4d3eSLandon J. Fuller {
79*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_iores	*iores;
80*77cb4d3eSLandon J. Fuller 	rman_res_t		 r_start, r_size;
81*77cb4d3eSLandon J. Fuller 
82*77cb4d3eSLandon J. Fuller 	/* Verify the bus width */
83*77cb4d3eSLandon J. Fuller 	switch (bus_width) {
84*77cb4d3eSLandon J. Fuller 	case 1:
85*77cb4d3eSLandon J. Fuller 	case 2:
86*77cb4d3eSLandon J. Fuller 	case 4:
87*77cb4d3eSLandon J. Fuller 		/* valid */
88*77cb4d3eSLandon J. Fuller 		break;
89*77cb4d3eSLandon J. Fuller 	default:
90*77cb4d3eSLandon J. Fuller 		BHND_NV_LOG("invalid bus width %u\n", bus_width);
91*77cb4d3eSLandon J. Fuller 		return (NULL);
92*77cb4d3eSLandon J. Fuller 	}
93*77cb4d3eSLandon J. Fuller 
94*77cb4d3eSLandon J. Fuller 	/* offset/size must not exceed our internal size_t representation,
95*77cb4d3eSLandon J. Fuller 	 * or our bus_size_t usage (note that BUS_SPACE_MAXSIZE may be less
96*77cb4d3eSLandon J. Fuller 	 * than 2^(sizeof(bus_size_t) * 32). */
97*77cb4d3eSLandon J. Fuller 	if (size > SIZE_MAX || offset > SIZE_MAX) {
98*77cb4d3eSLandon J. Fuller 		BHND_NV_LOG("offset %#jx+%#jx exceeds SIZE_MAX\n",
99*77cb4d3eSLandon J. Fuller 		    (uintmax_t)offset, (uintmax_t)offset);
100*77cb4d3eSLandon J. Fuller 		return (NULL);
101*77cb4d3eSLandon J. Fuller 	}
102*77cb4d3eSLandon J. Fuller 
103*77cb4d3eSLandon J. Fuller 	if (size > BUS_SPACE_MAXSIZE || offset > BUS_SPACE_MAXSIZE)
104*77cb4d3eSLandon J. Fuller 	{
105*77cb4d3eSLandon J. Fuller 		BHND_NV_LOG("offset %#jx+%#jx exceeds BUS_SPACE_MAXSIZE\n",
106*77cb4d3eSLandon J. Fuller 		    (uintmax_t)offset, (uintmax_t)offset);
107*77cb4d3eSLandon J. Fuller 		return (NULL);
108*77cb4d3eSLandon J. Fuller 	}
109*77cb4d3eSLandon J. Fuller 
110*77cb4d3eSLandon J. Fuller 	/* offset/size fall within the resource's mapped range */
111*77cb4d3eSLandon J. Fuller 	r_size = rman_get_size(r->res);
112*77cb4d3eSLandon J. Fuller 	r_start = rman_get_start(r->res);
113*77cb4d3eSLandon J. Fuller 	if (r_size < offset || r_size < size || r_size - size < offset)
114*77cb4d3eSLandon J. Fuller 		return (NULL);
115*77cb4d3eSLandon J. Fuller 
116*77cb4d3eSLandon J. Fuller 	/* offset/size must be bus_width aligned  */
117*77cb4d3eSLandon J. Fuller 	if ((r_start + offset) % bus_width != 0) {
118*77cb4d3eSLandon J. Fuller 		BHND_NV_LOG("base address %#jx+%#jx not aligned to bus width "
119*77cb4d3eSLandon J. Fuller 		    "%u\n", (uintmax_t)r_start, (uintmax_t)offset, bus_width);
120*77cb4d3eSLandon J. Fuller 		return (NULL);
121*77cb4d3eSLandon J. Fuller 	}
122*77cb4d3eSLandon J. Fuller 
123*77cb4d3eSLandon J. Fuller 	if (size % bus_width != 0) {
124*77cb4d3eSLandon J. Fuller 		BHND_NV_LOG("size %#jx not aligned to bus width %u\n",
125*77cb4d3eSLandon J. Fuller 		    (uintmax_t)size, bus_width);
126*77cb4d3eSLandon J. Fuller 		return (NULL);
127*77cb4d3eSLandon J. Fuller 	}
128*77cb4d3eSLandon J. Fuller 
129*77cb4d3eSLandon J. Fuller 	/* Allocate and return the I/O context */
130*77cb4d3eSLandon J. Fuller 	iores = malloc(sizeof(*iores), M_BHND_NVRAM, M_WAITOK);
131*77cb4d3eSLandon J. Fuller 	iores->io.iops = &bhnd_nvram_iores_ops;
132*77cb4d3eSLandon J. Fuller 	iores->res = r;
133*77cb4d3eSLandon J. Fuller 	iores->offset = offset;
134*77cb4d3eSLandon J. Fuller 	iores->size = size;
135*77cb4d3eSLandon J. Fuller 	iores->bus_width = bus_width;
136*77cb4d3eSLandon J. Fuller 
137*77cb4d3eSLandon J. Fuller 	return (&iores->io);
138*77cb4d3eSLandon J. Fuller }
139*77cb4d3eSLandon J. Fuller 
140*77cb4d3eSLandon J. Fuller static void
bhnd_nvram_iores_free(struct bhnd_nvram_io * io)141*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_free(struct bhnd_nvram_io *io)
142*77cb4d3eSLandon J. Fuller {
143*77cb4d3eSLandon J. Fuller 	free(io, M_BHND_NVRAM);
144*77cb4d3eSLandon J. Fuller }
145*77cb4d3eSLandon J. Fuller 
146*77cb4d3eSLandon J. Fuller static size_t
bhnd_nvram_iores_getsize(struct bhnd_nvram_io * io)147*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_getsize(struct bhnd_nvram_io *io)
148*77cb4d3eSLandon J. Fuller {
149*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_iores	*iores = (struct bhnd_nvram_iores *)io;
150*77cb4d3eSLandon J. Fuller 	return (iores->size);
151*77cb4d3eSLandon J. Fuller }
152*77cb4d3eSLandon J. Fuller 
153*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_setsize(struct bhnd_nvram_io * io,size_t size)154*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_setsize(struct bhnd_nvram_io *io, size_t size)
155*77cb4d3eSLandon J. Fuller {
156*77cb4d3eSLandon J. Fuller 	/* unsupported */
157*77cb4d3eSLandon J. Fuller 	return (ENODEV);
158*77cb4d3eSLandon J. Fuller }
159*77cb4d3eSLandon J. Fuller 
160*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_read_ptr(struct bhnd_nvram_io * io,size_t offset,const void ** ptr,size_t nbytes,size_t * navail)161*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_read_ptr(struct bhnd_nvram_io *io, size_t offset,
162*77cb4d3eSLandon J. Fuller     const void **ptr, size_t nbytes, size_t *navail)
163*77cb4d3eSLandon J. Fuller {
164*77cb4d3eSLandon J. Fuller 	/* unsupported */
165*77cb4d3eSLandon J. Fuller 	return (ENODEV);
166*77cb4d3eSLandon J. Fuller }
167*77cb4d3eSLandon J. Fuller 
168*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_write_ptr(struct bhnd_nvram_io * io,size_t offset,void ** ptr,size_t nbytes,size_t * navail)169*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_write_ptr(struct bhnd_nvram_io *io, size_t offset,
170*77cb4d3eSLandon J. Fuller     void **ptr, size_t nbytes, size_t *navail)
171*77cb4d3eSLandon J. Fuller {
172*77cb4d3eSLandon J. Fuller 	/* unsupported */
173*77cb4d3eSLandon J. Fuller 	return (ENODEV);
174*77cb4d3eSLandon J. Fuller }
175*77cb4d3eSLandon J. Fuller 
176*77cb4d3eSLandon J. Fuller /**
177*77cb4d3eSLandon J. Fuller  * Validate @p offset and @p nbytes:
178*77cb4d3eSLandon J. Fuller  *
179*77cb4d3eSLandon J. Fuller  * - Verify that @p offset is mapped by the backing resource.
180*77cb4d3eSLandon J. Fuller  * - If less than @p nbytes are available at @p offset, write the actual number
181*77cb4d3eSLandon J. Fuller  *   of bytes available to @p nbytes.
182*77cb4d3eSLandon J. Fuller  * - Verify that @p offset + @p nbytes are correctly aligned.
183*77cb4d3eSLandon J. Fuller  */
184*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_validate_req(struct bhnd_nvram_iores * iores,size_t offset,size_t * nbytes)185*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_validate_req(struct bhnd_nvram_iores *iores, size_t offset,
186*77cb4d3eSLandon J. Fuller     size_t *nbytes)
187*77cb4d3eSLandon J. Fuller {
188*77cb4d3eSLandon J. Fuller 	/* Verify offset falls within the resource range */
189*77cb4d3eSLandon J. Fuller 	if (offset > iores->size)
190*77cb4d3eSLandon J. Fuller 		return (ENXIO);
191*77cb4d3eSLandon J. Fuller 
192*77cb4d3eSLandon J. Fuller 	/* Check for eof */
193*77cb4d3eSLandon J. Fuller 	if (offset == iores->size) {
194*77cb4d3eSLandon J. Fuller 		*nbytes = 0;
195*77cb4d3eSLandon J. Fuller 		return (0);
196*77cb4d3eSLandon J. Fuller 	}
197*77cb4d3eSLandon J. Fuller 
198*77cb4d3eSLandon J. Fuller 	/* Verify offset alignment */
199*77cb4d3eSLandon J. Fuller 	if (offset % iores->bus_width != 0)
200*77cb4d3eSLandon J. Fuller 		return (EFAULT);
201*77cb4d3eSLandon J. Fuller 
202*77cb4d3eSLandon J. Fuller 	/* Limit nbytes to available range and verify size alignment */
203*77cb4d3eSLandon J. Fuller 	*nbytes = ummin(*nbytes, iores->size - offset);
204*77cb4d3eSLandon J. Fuller 	if (*nbytes < iores->bus_width && *nbytes % iores->bus_width != 0)
205*77cb4d3eSLandon J. Fuller 		return (EFAULT);
206*77cb4d3eSLandon J. Fuller 
207*77cb4d3eSLandon J. Fuller 	return (0);
208*77cb4d3eSLandon J. Fuller }
209*77cb4d3eSLandon J. Fuller 
210*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_read(struct bhnd_nvram_io * io,size_t offset,void * buffer,size_t nbytes)211*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_read(struct bhnd_nvram_io *io, size_t offset, void *buffer,
212*77cb4d3eSLandon J. Fuller     size_t nbytes)
213*77cb4d3eSLandon J. Fuller {
214*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_iores	*iores;
215*77cb4d3eSLandon J. Fuller 	bus_size_t		 r_offset;
216*77cb4d3eSLandon J. Fuller 	size_t			 navail;
217*77cb4d3eSLandon J. Fuller 	int			 error;
218*77cb4d3eSLandon J. Fuller 
219*77cb4d3eSLandon J. Fuller 	iores = (struct bhnd_nvram_iores *)io;
220*77cb4d3eSLandon J. Fuller 
221*77cb4d3eSLandon J. Fuller 	/* Validate the request and determine the actual number of readable
222*77cb4d3eSLandon J. Fuller 	 * bytes */
223*77cb4d3eSLandon J. Fuller 	navail = nbytes;
224*77cb4d3eSLandon J. Fuller 	if ((error = bhnd_nvram_iores_validate_req(iores, offset, &navail)))
225*77cb4d3eSLandon J. Fuller 		return (error);
226*77cb4d3eSLandon J. Fuller 
227*77cb4d3eSLandon J. Fuller 	/* At least nbytes must be readable */
228*77cb4d3eSLandon J. Fuller 	if (navail < nbytes)
229*77cb4d3eSLandon J. Fuller 		return (ENXIO);
230*77cb4d3eSLandon J. Fuller 
231*77cb4d3eSLandon J. Fuller 	/* Handle zero length read */
232*77cb4d3eSLandon J. Fuller 	if (nbytes == 0)
233*77cb4d3eSLandon J. Fuller 		return (0);
234*77cb4d3eSLandon J. Fuller 
235*77cb4d3eSLandon J. Fuller 	/* Determine actual resource offset and perform the read */
236*77cb4d3eSLandon J. Fuller 	r_offset = iores->offset + offset;
237*77cb4d3eSLandon J. Fuller 	switch (iores->bus_width) {
238*77cb4d3eSLandon J. Fuller 	case 1:
239*77cb4d3eSLandon J. Fuller 		bhnd_bus_read_region_stream_1(iores->res, r_offset, buffer,
240*77cb4d3eSLandon J. Fuller 		    nbytes);
241*77cb4d3eSLandon J. Fuller 		break;
242*77cb4d3eSLandon J. Fuller 	case 2:
243*77cb4d3eSLandon J. Fuller 		bhnd_bus_read_region_stream_2(iores->res, r_offset, buffer,
244*77cb4d3eSLandon J. Fuller 		    nbytes / 2);
245*77cb4d3eSLandon J. Fuller 		break;
246*77cb4d3eSLandon J. Fuller 	case 4:
247*77cb4d3eSLandon J. Fuller 		bhnd_bus_read_region_stream_4(iores->res, r_offset, buffer,
248*77cb4d3eSLandon J. Fuller 		    nbytes / 4);
249*77cb4d3eSLandon J. Fuller 		break;
250*77cb4d3eSLandon J. Fuller 	default:
251*77cb4d3eSLandon J. Fuller 		panic("unreachable!");
252*77cb4d3eSLandon J. Fuller 	}
253*77cb4d3eSLandon J. Fuller 
254*77cb4d3eSLandon J. Fuller 	return (0);
255*77cb4d3eSLandon J. Fuller }
256*77cb4d3eSLandon J. Fuller 
257*77cb4d3eSLandon J. Fuller static int
bhnd_nvram_iores_write(struct bhnd_nvram_io * io,size_t offset,void * buffer,size_t nbytes)258*77cb4d3eSLandon J. Fuller bhnd_nvram_iores_write(struct bhnd_nvram_io *io, size_t offset,
259*77cb4d3eSLandon J. Fuller     void *buffer, size_t nbytes)
260*77cb4d3eSLandon J. Fuller {
261*77cb4d3eSLandon J. Fuller 	struct bhnd_nvram_iores	*iores;
262*77cb4d3eSLandon J. Fuller 	size_t			 navail;
263*77cb4d3eSLandon J. Fuller 	bus_size_t		 r_offset;
264*77cb4d3eSLandon J. Fuller 	int			 error;
265*77cb4d3eSLandon J. Fuller 
266*77cb4d3eSLandon J. Fuller 	iores = (struct bhnd_nvram_iores *)io;
267*77cb4d3eSLandon J. Fuller 
268*77cb4d3eSLandon J. Fuller 	/* Validate the request and determine the actual number of writable
269*77cb4d3eSLandon J. Fuller 	 * bytes */
270*77cb4d3eSLandon J. Fuller 	navail = nbytes;
271*77cb4d3eSLandon J. Fuller 	if ((error = bhnd_nvram_iores_validate_req(iores, offset, &navail)))
272*77cb4d3eSLandon J. Fuller 		return (error);
273*77cb4d3eSLandon J. Fuller 
274*77cb4d3eSLandon J. Fuller 	/* At least nbytes must be writable */
275*77cb4d3eSLandon J. Fuller 	if (navail < nbytes)
276*77cb4d3eSLandon J. Fuller 		return (ENXIO);
277*77cb4d3eSLandon J. Fuller 
278*77cb4d3eSLandon J. Fuller 	/* Determine actual resource offset and perform the write */
279*77cb4d3eSLandon J. Fuller 	r_offset = iores->offset + offset;
280*77cb4d3eSLandon J. Fuller 	switch (iores->bus_width) {
281*77cb4d3eSLandon J. Fuller 	case 1:
282*77cb4d3eSLandon J. Fuller 		bhnd_bus_write_region_stream_1(iores->res, r_offset, buffer,
283*77cb4d3eSLandon J. Fuller 		    nbytes);
284*77cb4d3eSLandon J. Fuller 		break;
285*77cb4d3eSLandon J. Fuller 	case 2:
286*77cb4d3eSLandon J. Fuller 		bhnd_bus_write_region_stream_2(iores->res, r_offset, buffer,
287*77cb4d3eSLandon J. Fuller 		    nbytes / 2);
288*77cb4d3eSLandon J. Fuller 		break;
289*77cb4d3eSLandon J. Fuller 	case 4:
290*77cb4d3eSLandon J. Fuller 		bhnd_bus_write_region_stream_4(iores->res, r_offset, buffer,
291*77cb4d3eSLandon J. Fuller 		    nbytes / 4);
292*77cb4d3eSLandon J. Fuller 		break;
293*77cb4d3eSLandon J. Fuller 	default:
294*77cb4d3eSLandon J. Fuller 		panic("unreachable!");
295*77cb4d3eSLandon J. Fuller 	}
296*77cb4d3eSLandon J. Fuller 
297*77cb4d3eSLandon J. Fuller 	return (0);
298*77cb4d3eSLandon J. Fuller }
299