1 /* $NetBSD: sdcd.c,v 1.7 2007/11/11 05:20:27 isaki Exp $ */
4 * Copyright (c) 2001 MINOURA Makoto.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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>
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);
47 #define DPRINTF(x) printf x
55 #define BUFFER_SIZE 8192
57 void *buffer
= alloca(BUFFER_SIZE
);
64 error
= IOCS_S_TESTUNIT(id
);
65 if (error
< 0) { /* not ready */
71 struct iocs_inquiry
*inqdata
= buffer
;
73 error
= IOCS_S_INQUIRY(100, id
, inqdata
);
74 if (error
< 0) { /* WHY??? */
78 if ((inqdata
->unit
!= 0) && /* direct */
79 (inqdata
->unit
!= 7)) { /* optical */
86 struct iocs_readcap
*rcdata
= buffer
;
88 error
= IOCS_S_READCAP(id
, rcdata
);
89 if (error
< 0) { /* WHY??? */
93 current_blklen
= rcdata
->size
>> 9;
94 current_devsize
= rcdata
->block
;
98 error
= IOCS_S_READ(0, 1, id
, current_blklen
, buffer
);
103 if (strncmp((char *)buffer
, "X68SCSI1", 8) != 0) {
114 readdisklabel(int id
)
118 struct disklabel
*label
;
119 struct dos_partition
*parttbl
;
121 if (current_id
== id
)
125 error
= check_unit(id
);
128 if (current_blklen
> 4) {
129 printf ("FATAL: Unsupported block size %d.\n",
130 256 << current_blklen
);
134 /* Try BSD disklabel first */
135 buffer
= alloca(2048);
136 error
= IOCS_S_READ(LABELSECTOR
, 1, id
, current_blklen
, buffer
);
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
;
151 /* Try Human68K-style partition table */
153 /* assumes 512byte/sec */
154 error
= IOCS_S_READ(DOSPARTOFF
, 2, id
, current_blklen
, buffer
);
156 error
= IOCS_S_READ(8 >> current_blklen
, 8 >> current_blklen
,
157 id
, current_blklen
, buffer
);
161 parttbl
= (void *)(buffer
+ DOSBBSECTOR
);
162 if (strncmp(buffer
, "X68K", 4) != 0)
165 for (current_npart
= 0, i
= 0;
166 current_npart
< MAXPARTITIONS
&& i
< 15 && parttbl
[i
].dp_size
;
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 */
180 for (i
= 0; i
< current_npart
; i
++) {
181 printf ("%d: starts %d, size %d\n", i
,
192 sd_getbsdpartition(int id
, int humanpart
)
196 struct dos_partition
*parttbl
;
202 error
= readdisklabel(id
);
204 printf("Reading disklabel: %s\n", strerror(error
));
207 buffer
= alloca(2048);
208 error
= IOCS_S_READ(8 >> current_blklen
, 8 >> current_blklen
,
209 id
, current_blklen
, buffer
);
211 printf("Reading partition table: %s\n", strerror(error
));
214 parttbl
= (void *)(buffer
+ DOSBBSECTOR
);
215 if (strncmp(buffer
, "X68K", 4) != 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
)
225 printf("Could not determine the boot partition.\n");
232 struct boot_partinfo sc_partinfo
;
236 /* sdopen(struct open_file *f, int id, int part) */
238 sdopen(struct open_file
*f
, ...)
241 struct sdcd_softc
*sc
;
246 id
= va_arg(ap
, int);
247 part
= va_arg(ap
, int);
250 if (id
< 0 || id
> 7)
252 if (current_id
!= id
) {
253 error
= readdisklabel(id
);
257 if (part
>= current_npart
)
260 sc
= alloc(sizeof(struct sdcd_softc
));
262 sc
->sc_partinfo
= partitions
[part
];
263 sc
->sc_blocksize
= current_blklen
<< 9;
269 sdclose(struct open_file
*f
)
271 dealloc(f
->f_devdata
, sizeof(struct sdcd_softc
));
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
;
289 nblks
= howmany(size
, 256 << current_blklen
);
291 if ((dblk
& 0x1fffff) == 0x1fffff && (nblks
& 0xff) == nblks
) {
293 error
= IOCS_S_WRITE(start
, nblks
, current_id
,
294 current_blklen
, buf
);
296 error
= IOCS_S_READ(start
, nblks
, current_id
,
297 current_blklen
, buf
);
300 error
= IOCS_S_WRITEEXT(start
, nblks
, current_id
,
301 current_blklen
, buf
);
303 error
= IOCS_S_READEXT(start
, nblks
, current_id
,
304 current_blklen
, buf
);
314 /* cdopen(struct open_file *f, int id, int part) */
316 cdopen(struct open_file
*f
, ...)
319 struct sdcd_softc
*sc
;
324 id
= va_arg(ap
, int);
325 part
= va_arg(ap
, int);
328 if (id
< 0 || id
> 7)
330 if (part
== 0 || part
== 2)
332 if (current_id
!= id
) {
333 error
= check_unit(id
);
338 sc
= alloc(sizeof(struct sdcd_softc
));
341 sc
->sc_partinfo
.size
= sc
->sc_partinfo
.size
= current_devsize
;
342 sc
->sc_blocksize
= current_blklen
<< 9;
348 cdclose(struct open_file
*f
)
350 dealloc(f
->f_devdata
, sizeof(struct sdcd_softc
));
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
,