Home | History | Annotate | Line # | Download | only in tapeboot
rawfs.c revision 1.6.76.2
      1 /*	$NetBSD: rawfs.c,v 1.6.76.2 2010/03/11 15:03:04 yamt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Gordon W. Ross
      5  * All rights reserved.
      6  *
      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.
     15  *
     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.
     26  */
     27 
     28 /*
     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.
     34  */
     35 
     36 #include <sys/param.h>
     37 #include <stand.h>
     38 
     39 #include "rawfs.h"
     40 
     41 extern int debug;
     42 
     43 /* Our devices are generally willing to do 8K transfers. */
     44 #define	RAWFS_BSIZE	0x2000
     45 
     46 /*
     47  * In-core open file.
     48  */
     49 struct file {
     50 	daddr_t		fs_nextblk;	/* block number to read next */
     51 	off_t		fs_off;		/* seek offset in file */
     52 	int		fs_len;		/* amount left in f_buf */
     53 	char *		fs_ptr;		/* read pointer into f_buf */
     54 	char		fs_buf[RAWFS_BSIZE];
     55 };
     56 
     57 static int rawfs_get_block(struct open_file *);
     58 
     59 int
     60 rawfs_open(const char *path, struct open_file *f)
     61 {
     62 	struct file *fs;
     63 
     64 	/*
     65 	 * The actual PROM driver has already been opened.
     66 	 * Just allocate the I/O buffer, etc.
     67 	 */
     68 	fs = alloc(sizeof(struct file));
     69 	fs->fs_nextblk = 0;
     70 	fs->fs_off = 0;
     71 	fs->fs_len = 0;
     72 	fs->fs_ptr = fs->fs_buf;
     73 
     74 #ifdef	DEBUG_RAWFS
     75 	printf("rawfs_open: fs=0x%x\n", fs);
     76 #endif
     77 
     78 	f->f_fsdata = fs;
     79 	return (0);
     80 }
     81 
     82 int
     83 rawfs_close(struct open_file *f)
     84 {
     85 	struct file *fs;
     86 
     87 	fs = (struct file *) f->f_fsdata;
     88 	f->f_fsdata = NULL;
     89 
     90 #ifdef	DEBUG_RAWFS
     91 	if (debug) {
     92 		printf("rawfs_close: breakpoint...", fs->fs_buf);
     93 		__asm ("	trap #0");
     94 	}
     95 #endif
     96 
     97 	if (fs != NULL)
     98 		dealloc(fs, sizeof(*fs));
     99 
    100 	return (0);
    101 }
    102 
    103 int
    104 rawfs_read(struct open_file *f, void *start, u_int size, u_int *resid)
    105 {
    106 	struct file *fs = (struct file *)f->f_fsdata;
    107 	char *addr = start;
    108 	int error = 0;
    109 	size_t csize;
    110 
    111 	while (size != 0) {
    112 		if (fs->fs_len == 0)
    113 			if ((error = rawfs_get_block(f)) != 0)
    114 				break;
    115 
    116 		if (fs->fs_len <= 0)
    117 			break;	/* EOF */
    118 
    119 		csize = size;
    120 		if (csize > fs->fs_len)
    121 			csize = fs->fs_len;
    122 
    123 		memcpy(addr, fs->fs_ptr, csize);
    124 		fs->fs_off += csize;
    125 		fs->fs_ptr += csize;
    126 		fs->fs_len -= csize;
    127 		addr += csize;
    128 		size -= csize;
    129 	}
    130 	if (resid)
    131 		*resid = size;
    132 	return (error);
    133 }
    134 
    135 int
    136 rawfs_write(struct open_file *f, void *start, size_t size, size_t *resid)
    137 {
    138 #ifdef	DEBUG_RAWFS
    139 	panic("rawfs_write");
    140 #endif
    141 	return (EROFS);
    142 }
    143 
    144 off_t
    145 rawfs_seek(struct open_file *f, off_t offset, int where)
    146 {
    147 	struct file *fs = (struct file *)f->f_fsdata;
    148 	off_t csize;
    149 
    150 	switch (where) {
    151 	case SEEK_SET:
    152 		offset -= fs->fs_off;
    153 		/* FALLTHROUGH */
    154 	case SEEK_CUR:
    155 		if (offset >= 0)
    156 			break;
    157 		/* FALLTHROUGH */
    158 	case SEEK_END:
    159 	default:
    160 		return (-1);
    161 	}
    162 
    163 	while (offset != 0) {
    164 
    165 		if (fs->fs_len == 0)
    166 			if (rawfs_get_block(f) != 0)
    167 				return (-1);
    168 
    169 		if (fs->fs_len <= 0)
    170 			break;	/* EOF */
    171 
    172 		csize = offset;
    173 		if (csize > fs->fs_len)
    174 			csize = fs->fs_len;
    175 
    176 		fs->fs_off += csize;
    177 		fs->fs_ptr += csize;
    178 		fs->fs_len -= csize;
    179 		offset -= csize;
    180 	}
    181 	return (fs->fs_off);
    182 }
    183 
    184 int
    185 rawfs_stat(struct open_file *f, struct stat *sb)
    186 {
    187 #ifdef	DEBUG_RAWFS
    188 	panic("rawfs_stat");
    189 #endif
    190 	return (EFTYPE);
    191 }
    192 
    193 
    194 /*
    195  * Read a block from the underlying stream device
    196  * (In our case, a tape drive.)
    197  */
    198 static int
    199 rawfs_get_block(struct open_file *f)
    200 {
    201 	struct file *fs;
    202 	size_t len;
    203 	int error;
    204 
    205 	fs = (struct file *)f->f_fsdata;
    206 	fs->fs_ptr = fs->fs_buf;
    207 
    208 	twiddle();
    209 	error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
    210 		fs->fs_nextblk, RAWFS_BSIZE,	fs->fs_buf, &len);
    211 
    212 	if (!error) {
    213 		fs->fs_len = len;
    214 		fs->fs_nextblk += (RAWFS_BSIZE / DEV_BSIZE);
    215 	}
    216 
    217 	return (error);
    218 }
    219