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