1 1.13 christos /* $NetBSD: dev_tape.c,v 1.13 2014/03/30 15:20:54 christos Exp $ */ 2 1.1 chuck 3 1.3 pk /*- 4 1.3 pk * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 chuck * All rights reserved. 6 1.1 chuck * 7 1.3 pk * This code is derived from software contributed to The NetBSD Foundation 8 1.3 pk * by Paul Kranenburg. 9 1.3 pk * 10 1.1 chuck * Redistribution and use in source and binary forms, with or without 11 1.1 chuck * modification, are permitted provided that the following conditions 12 1.1 chuck * are met: 13 1.1 chuck * 1. Redistributions of source code must retain the above copyright 14 1.1 chuck * notice, this list of conditions and the following disclaimer. 15 1.1 chuck * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 chuck * notice, this list of conditions and the following disclaimer in the 17 1.1 chuck * documentation and/or other materials provided with the distribution. 18 1.1 chuck * 19 1.3 pk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.3 pk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.3 pk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.3 pk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.3 pk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.3 pk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.3 pk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.3 pk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.3 pk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.3 pk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.3 pk * POSSIBILITY OF SUCH DAMAGE. 30 1.1 chuck */ 31 1.1 chuck 32 1.1 chuck /* 33 1.1 chuck * This module implements a "raw device" interface suitable for 34 1.1 chuck * use by the stand-alone I/O library UFS file-system code, and 35 1.1 chuck * possibly for direct access (i.e. boot from tape). 36 1.1 chuck */ 37 1.1 chuck 38 1.1 chuck #include <sys/types.h> 39 1.1 chuck #include <machine/prom.h> 40 1.4 jdolecek 41 1.4 jdolecek #include <lib/libkern/libkern.h> 42 1.1 chuck 43 1.6 junyoung #include <lib/libsa/stand.h> 44 1.1 chuck #include "libsa.h" 45 1.4 jdolecek #include "dev_tape.h" 46 1.1 chuck 47 1.1 chuck extern int debug; 48 1.1 chuck 49 1.1 chuck struct mvmeprom_dskio tape_ioreq; 50 1.1 chuck 51 1.2 scw static int hackprom_diskrd(struct mvmeprom_dskio *); 52 1.2 scw 53 1.1 chuck /* 54 1.1 chuck * This is a special version of devopen() for tape boot. 55 1.1 chuck * In this version, the file name is a numeric string of 56 1.1 chuck * one digit, which is passed to the device open so it 57 1.1 chuck * can open the appropriate tape segment. 58 1.1 chuck */ 59 1.1 chuck int 60 1.9 tsutsui devopen(struct open_file *f, const char *fname, char **file) 61 1.1 chuck { 62 1.1 chuck struct devsw *dp; 63 1.1 chuck 64 1.9 tsutsui *file = (char *)fname; 65 1.1 chuck dp = &devsw[0]; 66 1.1 chuck f->f_dev = dp; 67 1.1 chuck 68 1.1 chuck /* The following will call tape_open() */ 69 1.9 tsutsui return dp->dv_open(f, fname); 70 1.1 chuck } 71 1.1 chuck 72 1.1 chuck int 73 1.4 jdolecek tape_open(struct open_file *f, ...) 74 1.4 jdolecek { 75 1.1 chuck char *fname; /* partition number, i.e. "1" */ 76 1.9 tsutsui int part; 77 1.1 chuck struct mvmeprom_dskio *ti; 78 1.4 jdolecek va_list ap; 79 1.4 jdolecek 80 1.4 jdolecek va_start(ap, f); 81 1.4 jdolecek fname = va_arg(ap, char *); 82 1.4 jdolecek va_end(ap); 83 1.1 chuck 84 1.1 chuck /* 85 1.1 chuck * Set the tape segment number to the one indicated 86 1.1 chuck * by the single digit fname passed in above. 87 1.1 chuck */ 88 1.1 chuck if ((fname[0] < '0') && (fname[0] > '9')) { 89 1.1 chuck return ENOENT; 90 1.1 chuck } 91 1.1 chuck part = fname[0] - '0'; 92 1.1 chuck 93 1.1 chuck /* 94 1.1 chuck * Setup our part of the saioreq. 95 1.1 chuck * (determines what gets opened) 96 1.1 chuck */ 97 1.1 chuck ti = &tape_ioreq; 98 1.8 christos memset((void *)ti, 0, sizeof(*ti)); 99 1.1 chuck 100 1.1 chuck ti->ctrl_lun = bugargs.ctrl_lun; 101 1.1 chuck ti->dev_lun = bugargs.dev_lun; 102 1.1 chuck ti->status = 0; 103 1.1 chuck ti->pbuffer = NULL; 104 1.1 chuck ti->blk_num = part; 105 1.1 chuck ti->blk_cnt = 0; 106 1.1 chuck ti->flag = 0; 107 1.1 chuck ti->addr_mod = 0; 108 1.1 chuck 109 1.1 chuck f->f_devdata = ti; 110 1.1 chuck 111 1.9 tsutsui return 0; 112 1.1 chuck } 113 1.1 chuck 114 1.1 chuck int 115 1.9 tsutsui tape_close(struct open_file *f) 116 1.1 chuck { 117 1.1 chuck f->f_devdata = NULL; 118 1.1 chuck return 0; 119 1.1 chuck } 120 1.1 chuck 121 1.1 chuck #define MVMEPROM_SCALE (512/MVMEPROM_BLOCK_SIZE) 122 1.1 chuck 123 1.1 chuck int 124 1.9 tsutsui tape_strategy(void *devdata, int flag, daddr_t dblk, u_int size, void *buf, 125 1.9 tsutsui u_int *rsize) 126 1.1 chuck { 127 1.1 chuck struct mvmeprom_dskio *ti; 128 1.1 chuck int ret; 129 1.1 chuck 130 1.1 chuck ti = devdata; 131 1.1 chuck 132 1.1 chuck if (flag != F_READ) 133 1.9 tsutsui return EROFS; 134 1.1 chuck 135 1.1 chuck ti->status = 0; 136 1.1 chuck ti->pbuffer = buf; 137 1.1 chuck /* don't change block #, set in open */ 138 1.1 chuck ti->blk_cnt = size / (512 / MVMEPROM_SCALE); 139 1.1 chuck 140 1.2 scw /* work around for stupid '147 prom bug */ 141 1.9 tsutsui if (bugargs.cputyp == 0x147) 142 1.2 scw ret = hackprom_diskrd(ti); 143 1.2 scw else 144 1.2 scw ret = mvmeprom_diskrd(ti); 145 1.1 chuck 146 1.1 chuck if (ret != 0) 147 1.9 tsutsui return EIO; 148 1.1 chuck 149 1.1 chuck *rsize = (ti->blk_cnt / MVMEPROM_SCALE) * 512; 150 1.1 chuck ti->flag |= IGNORE_FILENUM; /* ignore next time */ 151 1.1 chuck 152 1.9 tsutsui return 0; 153 1.1 chuck } 154 1.1 chuck 155 1.1 chuck int 156 1.8 christos tape_ioctl(struct open_file *f, u_long cmd, void *data) 157 1.1 chuck { 158 1.9 tsutsui 159 1.1 chuck return EIO; 160 1.1 chuck } 161 1.1 chuck 162 1.2 scw static int 163 1.2 scw hackprom_diskrd(struct mvmeprom_dskio *ti) 164 1.2 scw { 165 1.2 scw static int blkoffset = 0; 166 1.2 scw 167 1.9 tsutsui #define hackload_addr ((char *)0x080000) /* Load tape segment here */ 168 1.11 scw #define hackload_blocks 0x3000 /* 3Mb worth */ 169 1.2 scw 170 1.9 tsutsui if ((ti->flag & IGNORE_FILENUM) == 0) { 171 1.2 scw /* 172 1.2 scw * First time through. Load the whole tape segment... 173 1.2 scw */ 174 1.2 scw struct mvmeprom_dskio nti; 175 1.2 scw int ret; 176 1.2 scw 177 1.2 scw nti = *ti; 178 1.2 scw 179 1.2 scw nti.pbuffer = hackload_addr; 180 1.2 scw nti.blk_cnt = hackload_blocks; 181 1.2 scw nti.flag |= END_OF_FILE; 182 1.2 scw 183 1.2 scw ret = mvmeprom_diskrd(&nti); 184 1.2 scw 185 1.2 scw /* 186 1.2 scw * PROM returns 1 on end-of-file. This isn't an 187 1.2 scw * error in this instance, just in case you're wondering! ;-) 188 1.2 scw */ 189 1.9 tsutsui if (ret < 0 || ret > 1) 190 1.2 scw return ret; 191 1.2 scw 192 1.2 scw blkoffset = 0; 193 1.2 scw } 194 1.2 scw 195 1.2 scw /* 196 1.2 scw * Grab the required number of block(s) 197 1.2 scw */ 198 1.5 scw memcpy(ti->pbuffer, &(hackload_addr[blkoffset]), 199 1.9 tsutsui ti->blk_cnt * MVMEPROM_BLOCK_SIZE); 200 1.2 scw 201 1.2 scw blkoffset += (ti->blk_cnt * MVMEPROM_BLOCK_SIZE); 202 1.2 scw 203 1.2 scw return 0; 204 1.2 scw } 205