xref: /netbsd-src/sys/arch/ews4800mips/stand/common/disk.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
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