1 /* $NetBSD: disk.c,v 1.5 2007/12/15 00:39:16 perry Exp $ */ 2 3 /*- 4 * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <lib/libsa/stand.h> 40 #include <lib/libkern/libkern.h> 41 42 #include <machine/param.h> 43 #include <machine/sbd.h> 44 #include <machine/sector.h> 45 46 #include "local.h" 47 #include "common.h" 48 49 int dkopen(struct open_file *, ...); 50 int dkclose(struct open_file *); 51 int dkstrategy(void *, int, daddr_t, size_t, void *, size_t *); 52 53 struct devsw dkdevsw = { 54 "dk", dkstrategy, dkopen, dkclose, noioctl 55 }; 56 57 struct disk { 58 bool active; 59 int type; /* FD/HD */ 60 int unit; 61 int format; /* 2D/2HD */ 62 int partition; 63 int offset; 64 int (*rw)(uint8_t *, int, int, int); 65 } __disk; 66 67 void sector_init(void); 68 bool __sector_rw(uint8_t *, int, int, int); 69 int __hd_rw(uint8_t *, int, int, int); 70 int __fd_2d_rw(uint8_t *, int, int, int); 71 int __fd_2hd_rw(uint8_t *, int, int, int); 72 void __fd_progress_msg(int); 73 74 bool 75 device_attach(int type, int unit, int partition) 76 { 77 78 /* Inquire boot device type and unit from NVSRAM */ 79 boot_device(&__disk.type, &__disk.unit, &__disk.format); 80 81 if (type >= 0) 82 __disk.type = type; 83 if (unit >= 0) 84 __disk.unit = unit; 85 86 __disk.partition = partition; 87 88 __disk.active = true; 89 __disk.offset = 0; 90 91 if (partition >= 0) { 92 if (!find_partition_start(__disk.partition, &__disk.offset)) { 93 printf("type %d, unit %d partition %d not found.\n", 94 __disk.type, __disk.unit, __disk.partition); 95 return false; 96 } 97 } 98 DEVICE_CAPABILITY.active_device = type; 99 100 /* Set actual read/write routine */ 101 if (__disk.type == NVSRAM_BOOTDEV_HARDDISK) { 102 __disk.rw = __hd_rw; 103 } else if (__disk.type == NVSRAM_BOOTDEV_FLOPPYDISK) { 104 if (__disk.format == FD_FORMAT_2HD) { 105 __disk.rw = __fd_2hd_rw; 106 } else if (__disk.format == FD_FORMAT_2D) { 107 __disk.rw = __fd_2d_rw; 108 } else { 109 printf("unknown floppy disk format %d.\n", 110 __disk.format); 111 return false; 112 } 113 } else { 114 printf("unknown disk type %d.\n", __disk.type); 115 return false; 116 } 117 118 return true; 119 } 120 121 int 122 dkopen(struct open_file *f, ...) 123 { 124 125 return 0; 126 } 127 128 int 129 dkclose(struct open_file *f) 130 { 131 132 return 0; 133 } 134 135 int 136 dkstrategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, 137 size_t *rsize) 138 { 139 int n; 140 141 if ((int)size < 0) { 142 printf("%s: invalid request block %d size %d base %d\n", 143 __func__, blk, size, __disk.offset); 144 return -1; 145 } 146 147 n = ROUND_SECTOR(size) >> DEV_BSHIFT; 148 if (!sector_read_n(0, buf, __disk.offset + blk, n)) 149 return -1; 150 151 *rsize = size; 152 153 return 0; 154 } 155 156 void 157 sector_init(void) 158 { 159 160 if (!__disk.active) 161 device_attach(-1, -1, -1); 162 } 163 164 void 165 sector_fini(void *self) 166 { 167 168 __disk.active = false; 169 } 170 171 bool 172 sector_read_n(void *self, uint8_t *buf, int sector, int count) 173 { 174 175 if (!__sector_rw(buf, sector, 0, count)) 176 return false; 177 return true; 178 } 179 180 bool 181 sector_read(void *self, uint8_t *buf, int sector) 182 { 183 184 return __sector_rw(buf, sector, 0, 1); 185 } 186 187 bool 188 sector_write_n(void *self, uint8_t *buf, int sector, int count) 189 { 190 191 if (!__sector_rw(buf, sector, 0x1000, count)) 192 return false; 193 return true; 194 } 195 196 bool 197 sector_write(void *self, uint8_t *buf, int sector) 198 { 199 200 return __sector_rw(buf, sector, 0x1000, 1); 201 } 202 203 bool 204 __sector_rw(uint8_t *buf, int block, int flag, int count) 205 { 206 int err; 207 208 if (!__disk.active) 209 sector_init(); 210 211 if ((err = __disk.rw(buf, block, flag, count)) != 0) 212 printf("%s: type=%d unit=%d offset=%d block=%d err=%d\n", 213 __func__, __disk.type, __disk.unit, __disk.offset, 214 block, err); 215 216 return err == 0; 217 } 218 219 int 220 __hd_rw(uint8_t *buf, int block, int flag, int count) 221 { 222 223 return (ROM_DK_RW(flag | __disk.unit, block, count, buf) & 0x7f); 224 } 225 226 int 227 __fd_2d_rw(uint8_t *buf, int block, int flag, int count) 228 { 229 int cnt, i, err; 230 uint32_t pos; 231 232 if (!blk_to_2d_position(block, &pos, &cnt)) { 233 printf("%s: invalid block #%d.\n", __func__, block); 234 return -1; 235 } 236 __fd_progress_msg(pos); 237 238 for (i = 0; i < count; i++, buf += DEV_BSIZE) { 239 err = ROM_FD_RW(flag | __disk.unit, pos, cnt, buf); 240 if (err) 241 return err; 242 } 243 return 0; 244 } 245 246 int 247 __fd_2hd_rw(uint8_t *buf, int block, int flag, int count) 248 { 249 int cnt, i, err; 250 uint32_t pos; 251 252 if (!blk_to_2hd_position(block, &pos, &cnt)) { 253 printf("%s: invalid block #%d.\n", __func__, block); 254 return -1; 255 } 256 __fd_progress_msg(pos); 257 258 for (i = 0; i < count; i++, buf += DEV_BSIZE) { 259 err = ROM_FD_RW(flag | __disk.unit | 0x1000000, pos, cnt, buf); 260 if (err) 261 return err; 262 } 263 return 0; 264 } 265 266 void 267 __fd_progress_msg(int pos) 268 { 269 char msg[16]; 270 271 memset(msg, 0, sizeof msg); 272 sprintf(msg, "C%d H%d S%d\r", (pos >> 16) & 0xff, (pos >> 8) & 0xff, 273 pos & 0xff); 274 printf("%s", msg); 275 } 276