Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / x68k / stand / libsa / sdcd.c
blobd804516576ceb3bfb649971a3f204747025e4b8e
1 /* $NetBSD: sdcd.c,v 1.7 2007/11/11 05:20:27 isaki Exp $ */
3 /*
4 * Copyright (c) 2001 MINOURA Makoto.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/param.h>
29 #include <sys/disklabel.h>
30 #include <machine/stdarg.h>
31 #include <lib/libkern/libkern.h>
32 #include <lib/libsa/stand.h>
34 #include "libx68k.h"
35 #include "sdcdvar.h"
36 #include "iocs.h"
39 static int current_id = -1;
40 static int current_blklen, current_devsize, current_npart;
41 static struct boot_partinfo partitions[MAXPARTITIONS];
43 static int readdisklabel(int);
44 static int check_unit(int);
46 #ifdef DEBUG
47 #define DPRINTF(x) printf x
48 #else
49 #define DPRINTF(x)
50 #endif
52 static int
53 check_unit(int id)
55 #define BUFFER_SIZE 8192
56 int error;
57 void *buffer = alloca(BUFFER_SIZE);
59 if (current_id == id)
60 return 0;
62 current_id = -1;
64 error = IOCS_S_TESTUNIT(id);
65 if (error < 0) { /* not ready */
66 error = ENXIO;
67 goto out;
71 struct iocs_inquiry *inqdata = buffer;
73 error = IOCS_S_INQUIRY(100, id, inqdata);
74 if (error < 0) { /* WHY??? */
75 error = ENXIO;
76 goto out;
78 if ((inqdata->unit != 0) && /* direct */
79 (inqdata->unit != 7)) { /* optical */
80 error = EUNIT;
81 goto out;
86 struct iocs_readcap *rcdata = buffer;
88 error = IOCS_S_READCAP(id, rcdata);
89 if (error < 0) { /* WHY??? */
90 error = EUNIT;
91 goto out;
93 current_blklen = rcdata->size >> 9;
94 current_devsize = rcdata->block;
98 error = IOCS_S_READ(0, 1, id, current_blklen, buffer);
99 if (error < 0) {
100 error = EIO;
101 goto out;
103 if (strncmp((char *)buffer, "X68SCSI1", 8) != 0) {
104 error = EUNLAB;
105 goto out;
109 out:
110 return error;
113 static int
114 readdisklabel(int id)
116 int error, i;
117 char *buffer;
118 struct disklabel *label;
119 struct dos_partition *parttbl;
121 if (current_id == id)
122 return 0;
123 current_id = -1;
125 error = check_unit(id);
126 if (error)
127 return error;
128 if (current_blklen > 4) {
129 printf ("FATAL: Unsupported block size %d.\n",
130 256 << current_blklen);
131 return ERDLAB;
134 /* Try BSD disklabel first */
135 buffer = alloca(2048);
136 error = IOCS_S_READ(LABELSECTOR, 1, id, current_blklen, buffer);
137 if (error < 0)
138 return EIO;
139 label = (void *)(buffer + LABELOFFSET);
140 if (label->d_magic == DISKMAGIC &&
141 label->d_magic2 == DISKMAGIC) {
142 for (i = 0; i < label->d_npartitions; i++) {
143 partitions[i].start = label->d_partitions[i].p_offset;
144 partitions[i].size = label->d_partitions[i].p_size;
146 current_npart = label->d_npartitions;
148 goto done;
151 /* Try Human68K-style partition table */
152 #if 0
153 /* assumes 512byte/sec */
154 error = IOCS_S_READ(DOSPARTOFF, 2, id, current_blklen, buffer);
155 #else
156 error = IOCS_S_READ(8 >> current_blklen, 8 >> current_blklen,
157 id, current_blklen, buffer);
158 #endif
159 if (error < 0)
160 return EIO;
161 parttbl = (void *)(buffer + DOSBBSECTOR);
162 if (strncmp(buffer, "X68K", 4) != 0)
163 return EUNLAB;
164 parttbl++;
165 for (current_npart = 0, i = 0;
166 current_npart < MAXPARTITIONS && i < 15 && parttbl[i].dp_size;
167 i++) {
168 partitions[current_npart].start
169 = parttbl[i].dp_start * 2;
170 partitions[current_npart].size
171 = parttbl[i].dp_size * 2;
172 if (++current_npart == RAW_PART) {
173 partitions[current_npart].start = 0;
174 partitions[current_npart].size = -1; /* XXX */
175 current_npart++;
178 done:
179 #ifdef DEBUG
180 for (i = 0; i < current_npart; i++) {
181 printf ("%d: starts %d, size %d\n", i,
182 partitions[i].start,
183 partitions[i].size);
185 #endif
186 current_id = id;
188 return 0;
192 sd_getbsdpartition(int id, int humanpart)
194 int error, i;
195 char *buffer;
196 struct dos_partition *parttbl;
197 unsigned parttop;
199 if (humanpart < 2)
200 humanpart++;
202 error = readdisklabel(id);
203 if (error) {
204 printf("Reading disklabel: %s\n", strerror(error));
205 return -1;
207 buffer = alloca(2048);
208 error = IOCS_S_READ(8 >> current_blklen, 8 >> current_blklen,
209 id, current_blklen, buffer);
210 if (error < 0) {
211 printf("Reading partition table: %s\n", strerror(error));
212 return -1;
214 parttbl = (void *)(buffer + DOSBBSECTOR);
215 if (strncmp(buffer, "X68K", 4) != 0)
216 return 0;
217 parttop = parttbl[humanpart].dp_start;
218 parttop = parttop << (2 - current_blklen);
220 for (i = 0; i < current_npart; i++) {
221 if (partitions[i].start == parttop)
222 return i;
225 printf("Could not determine the boot partition.\n");
227 return -1;
230 struct sdcd_softc {
231 int sc_part;
232 struct boot_partinfo sc_partinfo;
233 int sc_blocksize;
236 /* sdopen(struct open_file *f, int id, int part) */
238 sdopen(struct open_file *f, ...)
240 int error;
241 struct sdcd_softc *sc;
242 int id, part;
243 va_list ap;
245 va_start(ap, f);
246 id = va_arg(ap, int);
247 part = va_arg(ap, int);
248 va_end(ap);
250 if (id < 0 || id > 7)
251 return ENXIO;
252 if (current_id != id) {
253 error = readdisklabel(id);
254 if (error)
255 return error;
257 if (part >= current_npart)
258 return ENXIO;
260 sc = alloc(sizeof(struct sdcd_softc));
261 sc->sc_part = part;
262 sc->sc_partinfo = partitions[part];
263 sc->sc_blocksize = current_blklen << 9;
264 f->f_devdata = sc;
265 return 0;
269 sdclose(struct open_file *f)
271 dealloc(f->f_devdata, sizeof(struct sdcd_softc));
272 return 0;
276 sdstrategy(void *arg, int rw, daddr_t dblk, size_t size,
277 void *buf, size_t *rsize)
279 struct sdcd_softc *sc = arg;
280 u_int32_t start = sc->sc_partinfo.start + dblk;
281 size_t nblks;
282 int error;
284 if (size == 0) {
285 if (rsize)
286 *rsize = 0;
287 return 0;
289 nblks = howmany(size, 256 << current_blklen);
291 if ((dblk & 0x1fffff) == 0x1fffff && (nblks & 0xff) == nblks) {
292 if (rw & F_WRITE)
293 error = IOCS_S_WRITE(start, nblks, current_id,
294 current_blklen, buf);
295 else
296 error = IOCS_S_READ(start, nblks, current_id,
297 current_blklen, buf);
298 } else {
299 if (rw & F_WRITE)
300 error = IOCS_S_WRITEEXT(start, nblks, current_id,
301 current_blklen, buf);
302 else
303 error = IOCS_S_READEXT(start, nblks, current_id,
304 current_blklen, buf);
306 if (error < 0)
307 return EIO;
309 if (rsize)
310 *rsize = size;
311 return 0;
314 /* cdopen(struct open_file *f, int id, int part) */
316 cdopen(struct open_file *f, ...)
318 int error;
319 struct sdcd_softc *sc;
320 int id, part;
321 va_list ap;
323 va_start(ap, f);
324 id = va_arg(ap, int);
325 part = va_arg(ap, int);
326 va_end(ap);
328 if (id < 0 || id > 7)
329 return ENXIO;
330 if (part == 0 || part == 2)
331 return ENXIO;
332 if (current_id != id) {
333 error = check_unit(id);
334 if (error)
335 return error;
338 sc = alloc(sizeof(struct sdcd_softc));
339 current_npart = 3;
340 sc->sc_part = 0;
341 sc->sc_partinfo.size = sc->sc_partinfo.size = current_devsize;
342 sc->sc_blocksize = current_blklen << 9;
343 f->f_devdata = sc;
344 return 0;
348 cdclose(struct open_file *f)
350 dealloc(f->f_devdata, sizeof(struct sdcd_softc));
351 return 0;
355 cdstrategy(void *arg, int rw, daddr_t dblk, size_t size,
356 void *buf, size_t *rsize)
358 struct sdcd_softc *sc = arg;
360 return sdstrategy(arg, rw, dblk * DEV_BSIZE / sc->sc_blocksize,
361 size, buf, rsize);