2 * Copyright (c) 2008 Semihalf, Rafal Jaworowski
3 * Copyright (c) 2009 Semihalf, Piotr Ziecik
4 * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Block storage I/O routines for U-Boot
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
39 #include <machine/stdarg.h>
42 #include "api_public.h"
43 #include "bootstrap.h"
48 #define stor_printf(fmt, args...) do { \
49 printf("%s%d: ", dev->d_dev->dv_name, dev->d_unit); \
50 printf(fmt, ##args); \
54 #define debugf(fmt, args...) do { printf("%s(): ", __func__); \
55 printf(fmt,##args); } while (0)
57 #define debugf(fmt, args...)
61 int opened
; /* device is opened */
62 int handle
; /* storage device handle */
63 int type
; /* storage type */
64 off_t blocks
; /* block count */
65 u_int bsize
; /* block size */
66 } stor_info
[UB_MAX_DEV
];
68 #define SI(dev) (stor_info[(dev)->d_unit])
70 static int stor_info_no
= 0;
71 static int stor_opendev(struct disk_devdesc
*);
72 static int stor_readdev(struct disk_devdesc
*, daddr_t
, size_t, char *);
75 static int stor_init(void);
76 static int stor_strategy(void *, int, daddr_t
, size_t, char *, size_t *);
77 static int stor_open(struct open_file
*, ...);
78 static int stor_close(struct open_file
*);
79 static int stor_ioctl(struct open_file
*f
, u_long cmd
, void *data
);
80 static int stor_print(int);
81 static void stor_cleanup(void);
83 struct devsw uboot_storage
= {
98 struct device_info
*di
;
102 printf("No U-Boot devices! Really enumerated?\n");
106 for (i
= 0; i
< devs_no
; i
++) {
108 if ((di
!= NULL
) && (di
->type
& DEV_TYP_STOR
)) {
109 if (stor_info_no
>= UB_MAX_DEV
) {
110 printf("Too many storage devices: %d\n",
114 stor_info
[stor_info_no
].handle
= i
;
115 stor_info
[stor_info_no
].opened
= 0;
116 stor_info
[stor_info_no
].type
= di
->type
;
117 stor_info
[stor_info_no
].blocks
=
118 di
->di_stor
.block_count
;
119 stor_info
[stor_info_no
].bsize
=
120 di
->di_stor
.block_size
;
126 debugf("No storage devices\n");
130 debugf("storage devices found: %d\n", stor_info_no
);
139 for (i
= 0; i
< stor_info_no
; i
++)
140 if (stor_info
[i
].opened
> 0)
141 ub_dev_close(stor_info
[i
].handle
);
142 disk_cleanup(&uboot_storage
);
146 stor_strategy(void *devdata
, int rw
, daddr_t blk
, size_t size
, char *buf
,
149 struct disk_devdesc
*dev
= (struct disk_devdesc
*)devdata
;
155 stor_printf("write attempt, operation not supported!\n");
159 if (size
% SI(dev
).bsize
) {
160 stor_printf("size=%zu not multiple of device "
162 size
, SI(dev
).bsize
);
165 bcount
= size
/ SI(dev
).bsize
;
169 err
= stor_readdev(dev
, blk
+ dev
->d_offset
, bcount
, buf
);
177 stor_open(struct open_file
*f
, ...)
180 struct disk_devdesc
*dev
;
183 dev
= va_arg(ap
, struct disk_devdesc
*);
186 return (stor_opendev(dev
));
190 stor_opendev(struct disk_devdesc
*dev
)
194 if (dev
->d_unit
< 0 || dev
->d_unit
>= stor_info_no
)
197 if (SI(dev
).opened
== 0) {
198 err
= ub_dev_open(SI(dev
).handle
);
200 stor_printf("device open failed with error=%d, "
201 "handle=%d\n", err
, SI(dev
).handle
);
206 return (disk_open(dev
, SI(dev
).blocks
* SI(dev
).bsize
, SI(dev
).bsize
));
210 stor_close(struct open_file
*f
)
212 struct disk_devdesc
*dev
;
214 dev
= (struct disk_devdesc
*)(f
->f_devdata
);
215 return (disk_close(dev
));
219 stor_readdev(struct disk_devdesc
*dev
, daddr_t blk
, size_t size
, char *buf
)
224 debugf("reading blk=%d size=%d @ 0x%08x\n", (int)blk
, size
, (uint32_t)buf
);
226 err
= ub_dev_read(SI(dev
).handle
, buf
, size
, blk
, &real_size
);
228 stor_printf("read failed, error=%d\n", err
);
232 if (real_size
!= size
) {
233 stor_printf("real size != size\n");
241 stor_print(int verbose
)
243 struct disk_devdesc dev
;
244 static char line
[80];
247 if (stor_info_no
== 0)
250 printf("%s devices:", uboot_storage
.dv_name
);
251 if ((ret
= pager_output("\n")) != 0)
254 for (i
= 0; i
< stor_info_no
; i
++) {
255 dev
.d_dev
= &uboot_storage
;
258 dev
.d_partition
= -1;
259 sprintf(line
, "\tdisk%d (%s)\n", i
,
260 ub_stor_type(SI(&dev
).type
));
262 if (stor_opendev(&dev
) == 0) {
263 sprintf(line
, "\tdisk%d", i
);
264 disk_print(&dev
, line
, verbose
);
271 stor_ioctl(struct open_file
*f
, u_long cmd
, void *data
)
273 struct disk_devdesc
*dev
;
275 dev
= (struct disk_devdesc
*)f
->f_devdata
;
277 case DIOCGSECTORSIZE
:
278 *(u_int
*)data
= SI(dev
).bsize
;
281 *(off_t
*)data
= SI(dev
).bsize
* SI(dev
).blocks
;
291 * Return the device unit number for the given type and type-relative unit
295 uboot_diskgetunit(int type
, int type_unit
)
301 for (i
= 0; i
< stor_info_no
; i
++) {
302 if ((stor_info
[i
].type
& type
) == type
) {
303 if (local_type_unit
== type_unit
) {