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