]>
Commit | Line | Data |
---|---|---|
f083c6c3 | 1 | /* |
57c72a9a | 2 | * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. |
f083c6c3 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
57c72a9a | 6 | * Portions Copyright (c) 2002-2003 Apple Computer, Inc. All Rights |
4f6e3300 A |
7 | * Reserved. This file contains Original Code and/or Modifications of |
8 | * Original Code as defined in and that are subject to the Apple Public | |
57c72a9a | 9 | * Source License Version 2.0 (the "License"). You may not use this file |
4f6e3300 A |
10 | * except in compliance with the License. Please obtain a copy of the |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
f083c6c3 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
4f6e3300 | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
f083c6c3 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
4f6e3300 A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
f083c6c3 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | #include <string.h> | |
26 | #include "boot1u.h" | |
27 | #include <memory.h> | |
28 | #include <saio_types.h> | |
29 | #include <saio_internal.h> | |
30 | #include <fdisk.h> | |
31 | ||
32 | #include "ufs.h" | |
33 | ||
34 | /* | |
35 | * trackbuf points to the start of the track cache. Biosread() | |
36 | * will store the sectors read from disk to this memory area. | |
37 | * | |
38 | * biosbuf points to a sector within the track cache, and is | |
39 | * updated by Biosread(). | |
40 | */ | |
41 | #if 0 | |
42 | static const char * const trackbuf = (char *) ptov(BIOS_ADDR); | |
43 | #endif | |
44 | static const char * biosbuf = (char *) ptov(BIOS_ADDR); | |
45 | ||
46 | /* | |
47 | * diskinfo unpacking. | |
48 | */ | |
49 | #define SPT(di) ((di) & 0xff) | |
50 | #define HEADS(di) ((((di)>>8) & 0xff) + 1) | |
51 | #define SPC(di) (SPT(di) * HEADS(di)) | |
52 | ||
53 | #define BPS 512 /* sector size of the device */ | |
54 | #define N_CACHE_SECS (BIOS_LEN / BPS) | |
55 | #define UFS_FRONT_PORCH 0 | |
56 | ||
57 | #define ECC_CORRECTED_ERR 0x11 | |
58 | ||
f083c6c3 A |
59 | extern void bios(biosBuf_t *bb); |
60 | ||
61 | static biosBuf_t bb; | |
57c72a9a | 62 | |
f083c6c3 A |
63 | int ebiosread(int dev, long sec, int count) |
64 | { | |
65 | int i; | |
66 | static struct { | |
67 | unsigned char size; | |
68 | unsigned char reserved; | |
69 | unsigned char numblocks; | |
70 | unsigned char reserved2; | |
71 | unsigned short bufferOffset; | |
72 | unsigned short bufferSegment; | |
73 | unsigned long long startblock; | |
74 | } addrpacket = {0}; | |
75 | addrpacket.size = sizeof(addrpacket); | |
76 | ||
77 | for (i=0;;) { | |
78 | bb.intno = 0x13; | |
79 | bb.eax.r.h = 0x42; | |
80 | bb.edx.r.l = dev; | |
81 | bb.esi.rr = OFFSET((unsigned)&addrpacket); | |
82 | bb.ds = SEGMENT((unsigned)&addrpacket); | |
83 | addrpacket.reserved = addrpacket.reserved2 = 0; | |
84 | addrpacket.numblocks = count; | |
85 | addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR)); | |
86 | addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR)); | |
87 | addrpacket.startblock = sec; | |
88 | bios(&bb); | |
89 | if ((bb.eax.r.h == 0x00) || (i++ >= 5)) | |
90 | break; | |
91 | ||
92 | /* reset disk subsystem and try again */ | |
93 | bb.eax.r.h = 0x00; | |
94 | bios(&bb); | |
95 | } | |
96 | return bb.eax.r.h; | |
97 | } | |
98 | ||
99 | //========================================================================== | |
100 | // Use BIOS INT13 calls to read the sector specified. This function will | |
101 | // also perform read-ahead to cache a few subsequent sector to the sector | |
102 | // cache. | |
103 | // | |
104 | // Return: | |
105 | // 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call. | |
106 | ||
107 | static int Biosread( int biosdev, unsigned int secno ) | |
108 | { | |
109 | int rc; | |
110 | ||
111 | DEBUG_DISK(("Biosread dev %x sec %d \n", biosdev, secno)); | |
112 | ||
113 | rc = ebiosread(biosdev, secno, 1); | |
114 | if (rc == ECC_CORRECTED_ERR) { | |
115 | rc = 0; | |
116 | } | |
117 | return rc; | |
118 | } | |
119 | ||
120 | //========================================================================== | |
121 | ||
122 | static int readBytes( int biosdev, unsigned int blkno, | |
123 | unsigned int byteCount, void * buffer ) | |
124 | { | |
125 | ||
126 | char * cbuf = (char *) buffer; | |
127 | int error; | |
128 | int copy_len; | |
129 | ||
130 | DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__, | |
131 | biosdev, blkno, byteCount, (unsigned)cbuf)); | |
132 | ||
133 | for ( ; byteCount; cbuf += BPS, blkno++ ) | |
134 | { | |
135 | error = Biosread( biosdev, blkno ); | |
136 | if ( error ) | |
137 | { | |
138 | DEBUG_DISK(("error\n")); | |
139 | return (-1); | |
140 | } | |
141 | ||
142 | copy_len = (byteCount > BPS) ? BPS : byteCount; | |
143 | bcopy( biosbuf, cbuf, copy_len ); | |
144 | byteCount -= copy_len; | |
145 | } | |
146 | ||
147 | DEBUG_DISK(("done\n")); | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | //========================================================================== | |
153 | ||
154 | //========================================================================== | |
155 | // Handle seek request from filesystem modules. | |
156 | ||
157 | void diskSeek( BVRef bvr, long long position ) | |
158 | { | |
159 | bvr->fs_boff = position / BPS; | |
160 | } | |
161 | ||
162 | //========================================================================== | |
163 | // Handle read request from filesystem modules. | |
164 | ||
165 | int diskRead( BVRef bvr, long addr, long length ) | |
166 | { | |
167 | return readBytes( bvr->biosdev, | |
168 | bvr->fs_boff + bvr->part_boff, | |
169 | length, | |
170 | (void *) addr ); | |
171 | } | |
172 | ||
57c72a9a | 173 | |
f083c6c3 A |
174 | int |
175 | findUFSPartition(int dev, struct fdisk_part *_fp) | |
176 | { | |
177 | struct disk_blk0 *db; | |
178 | struct fdisk_part *fp; | |
179 | int i, cc; | |
180 | unsigned long offset = 0; | |
57c72a9a A |
181 | unsigned long firstoff = 0; |
182 | int ext_index = -1; | |
f083c6c3 A |
183 | |
184 | db = (struct disk_blk0 *)biosbuf; | |
57c72a9a A |
185 | do { |
186 | DEBUG_DISK(("reading at offset %d\n", offset)); | |
f083c6c3 A |
187 | cc = Biosread(dev, offset); |
188 | if (cc < 0) { | |
57c72a9a | 189 | return cc; |
f083c6c3 | 190 | } |
57c72a9a A |
191 | for (i=0; i<FDISK_NPART; i++) { |
192 | DEBUG_DISK(("i=%d, offset %ld\n", i, offset)); | |
193 | fp = (struct fdisk_part *)&db->parts[i]; | |
194 | DEBUG_DISK(("systid %x\n", fp->systid)); | |
195 | if (fp->systid == FDISK_UFS) { | |
196 | bcopy(fp, _fp, sizeof(struct fdisk_part)); | |
197 | _fp->relsect += offset; | |
198 | DEBUG_DISK(("** found UFS at partition %d\n", i)); | |
199 | return 0; | |
200 | } else if (fp->systid == FDISK_DOSEXT || | |
201 | fp->systid == 0x0F || | |
202 | fp->systid == 0x85) { | |
203 | ext_index = i; | |
204 | } | |
205 | } | |
206 | if (ext_index != -1) { | |
207 | DEBUG_DISK(("Found ext part at %d\n", ext_index)); | |
208 | fp = (struct fdisk_part *)&db->parts[ext_index]; | |
209 | ext_index = -1; | |
210 | offset = firstoff + fp->relsect; | |
211 | if (firstoff == 0) { | |
212 | firstoff = fp->relsect; | |
213 | } | |
214 | continue; | |
215 | } | |
216 | break; | |
217 | } while (1); | |
f083c6c3 A |
218 | return -1; |
219 | } | |
220 | ||
221 | ||
222 | void | |
223 | initUFSBVRef( BVRef bvr, int biosdev, const struct fdisk_part * part) | |
224 | { | |
57c72a9a A |
225 | bvr->biosdev = biosdev; |
226 | bvr->part_no = 0; | |
227 | bvr->part_boff = part->relsect + UFS_FRONT_PORCH/BPS, | |
f083c6c3 | 228 | bvr->part_type = part->systid; |
57c72a9a A |
229 | bvr->fs_loadfile = UFSLoadFile; |
230 | //bvr->fs_getdirentry = UFSGetDirEntry; | |
231 | bvr->description = 0; | |
f083c6c3 A |
232 | } |
233 | ||
234 | void putc(int ch) | |
235 | { | |
236 | bb.intno = 0x10; | |
237 | bb.ebx.r.h = 0x00; /* background black */ | |
238 | bb.ebx.r.l = 0x0F; /* foreground white */ | |
239 | bb.eax.r.h = 0x0e; | |
240 | bb.eax.r.l = ch; | |
241 | bios(&bb); | |
242 | } | |
243 | ||
244 | int bgetc(void) | |
245 | { | |
246 | bb.intno = 0x16; | |
247 | bb.eax.r.h = 0x00; | |
248 | bios(&bb); | |
249 | return bb.eax.rr; | |
250 | } | |
251 | ||
252 | void delay(int ms) | |
253 | { | |
254 | bb.intno = 0x15; | |
255 | bb.eax.r.h = 0x86; | |
256 | bb.ecx.rr = ms >> 16; | |
257 | bb.edx.rr = ms & 0xFFFF; | |
258 | bios(&bb); | |
259 | } |