No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / mvme68k / stand / bootst / rawfs.c
blobc9e84a015bb774ab506519d785fb56df8251f056
1 /* $NetBSD: rawfs.c,v 1.10 2008/01/12 09:54:30 tsutsui Exp $ */
3 /*
4 * Copyright (c) 1995 Gordon W. Ross
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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 ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Raw file system - for stream devices like tapes.
30 * No random access, only sequential read allowed.
31 * This exists only to allow upper level code to be
32 * shielded from the fact that the device must be
33 * read only with whole block position and size.
36 #include <sys/param.h>
37 #include <lib/libsa/stand.h>
38 #include <rawfs.h>
40 extern int debug;
42 #define RAWFS_BSIZE 8192
45 * In-core open file.
47 struct file {
48 daddr_t fs_nextblk; /* block number to read next */
49 daddr_t fs_curblk; /* block number currently in buffer */
50 int fs_len; /* amount left in f_buf */
51 char *fs_ptr; /* read pointer into f_buf */
52 char fs_buf[RAWFS_BSIZE];
55 static int rawfs_get_block(struct open_file *);
57 int rawfs_open(const char *path, struct open_file *f)
59 struct file *fs;
62 * The actual PROM driver has already been opened.
63 * Just allocate the I/O buffer, etc.
65 fs = alloc(sizeof(struct file));
66 fs->fs_nextblk = 0;
67 fs->fs_curblk = -1;
68 fs->fs_len = 0;
69 fs->fs_ptr = fs->fs_buf;
71 f->f_fsdata = fs;
72 return 0;
75 int rawfs_close(struct open_file *f)
77 struct file *fs;
79 fs = (struct file *)f->f_fsdata;
80 f->f_fsdata = NULL;
82 if (fs != NULL)
83 dealloc(fs, sizeof(*fs));
85 return 0;
88 int rawfs_read(struct open_file *f, void *start, u_int size, u_int *resid)
90 struct file *fs = (struct file *)f->f_fsdata;
91 char *addr = start;
92 int error = 0;
93 size_t csize;
95 while (size != 0) {
97 if (fs->fs_len == 0)
98 if ((error = rawfs_get_block(f)) != 0)
99 break;
101 if (fs->fs_len <= 0)
102 break; /* EOF */
104 csize = size;
105 if (csize > fs->fs_len)
106 csize = fs->fs_len;
108 memcpy(addr, fs->fs_ptr, csize);
109 fs->fs_ptr += csize;
110 fs->fs_len -= csize;
111 addr += csize;
112 size -= csize;
114 if (resid)
115 *resid = size;
117 if (error) {
118 errno = error;
119 error = -1;
122 return error;
125 int rawfs_write(struct open_file *f, void *start, size_t size, size_t *resid)
128 errno = EROFS;
129 return -1;
132 off_t rawfs_seek(struct open_file *f, off_t offset, int where)
134 struct file *fs = (struct file *)f->f_fsdata;
135 daddr_t curblk, targblk;
136 off_t newoff;
137 int err, idx;
140 * We support a very minimal feature set for lseek(2); just
141 * enough to allow loadfile() to work with the parameters
142 * we pass to it on boot.
144 * In all cases, we can't seek back past the start of the
145 * current block.
147 curblk = (fs->fs_curblk < 0) ? 0 : fs->fs_curblk;
150 * Only support SEEK_SET and SEEK_CUR which result in offsets
151 * which don't require seeking backwards.
153 switch (where) {
154 case SEEK_SET:
155 newoff = offset;
156 break;
158 case SEEK_CUR:
159 if (fs->fs_curblk < 0)
160 newoff = 0;
161 else {
162 newoff = fs->fs_curblk * RAWFS_BSIZE;
163 newoff += RAWFS_BSIZE - fs->fs_len;
165 newoff += offset;
166 break;
168 default:
169 errno = EINVAL;
170 return -1;
173 if (newoff < (curblk * RAWFS_BSIZE)) {
174 errno = EINVAL;
175 return -1;
178 targblk = newoff / RAWFS_BSIZE;
181 * If necessary, skip blocks until we hit the required target
183 err = 0;
184 while (fs->fs_curblk != targblk && (err = rawfs_get_block(f)) == 0)
187 if (err) {
188 errno = err;
189 return -1;
193 * Update the index within the loaded block
195 idx = newoff % RAWFS_BSIZE;
196 fs->fs_len = RAWFS_BSIZE - idx;
197 fs->fs_ptr = &fs->fs_buf[idx];
199 return newoff;
202 int rawfs_stat(struct open_file *f, struct stat *sb)
205 errno = EFTYPE;
206 return -1;
211 * Read a block from the underlying stream device
212 * (In our case, a tape drive.)
214 static int
215 rawfs_get_block(struct open_file *f)
217 struct file *fs;
218 int error;
219 size_t len;
221 fs = (struct file *)f->f_fsdata;
222 fs->fs_ptr = fs->fs_buf;
224 twiddle();
225 error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
226 fs->fs_nextblk * (RAWFS_BSIZE / DEV_BSIZE),
227 RAWFS_BSIZE, fs->fs_buf, &len);
229 if (error == 0) {
230 fs->fs_len = len;
231 fs->fs_curblk = fs->fs_nextblk;
232 fs->fs_nextblk += 1;
233 } else {
234 errno = error;
235 error = -1;
238 return error;