disk.c revision 1.2 1 /* $NetBSD: disk.c,v 1.2 2006/08/26 14:13:40 tsutsui 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 boolean_t 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 boolean_t __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 boolean_t
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 __FUNCTION__, 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 boolean_t
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 boolean_t
181 sector_read(void *self, uint8_t *buf, int sector)
182 {
183
184 return __sector_rw(buf, sector, 0, 1);
185 }
186
187 boolean_t
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 boolean_t
197 sector_write(void *self, uint8_t *buf, int sector)
198 {
199
200 return __sector_rw(buf, sector, 0x1000, 1);
201 }
202
203 boolean_t
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 __FUNCTION__, __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", __FUNCTION__, 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", __FUNCTION__, 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