]> git.saurik.com Git - apple/boot.git/blame - gen/libsaio/disk.c
boot-132.tar.gz
[apple/boot.git] / gen / libsaio / disk.c
CommitLineData
14c7c974
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
4f6e3300
A
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
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
9 * Source License Version 1.1 (the "License"). You may not use this file
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.
14c7c974
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
14c7c974
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.
14c7c974
A
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * All rights reserved. The CMU software License Agreement specifies
29 * the terms and conditions for use and redistribution.
30 */
31
32/*
33 * INTEL CORPORATION PROPRIETARY INFORMATION
34 *
35 * This software is supplied under the terms of a license agreement or
36 * nondisclosure agreement with Intel Corporation and may not be copied
37 * nor disclosed except in accordance with the terms of that agreement.
38 *
39 * Copyright 1988, 1989 Intel Corporation
40 */
41
42/*
43 * Copyright 1993 NeXT Computer, Inc.
44 * All rights reserved.
45 */
46
47#define DRIVER_PRIVATE
48
49#import "sys/types.h"
f083c6c3 50#import <sys/disk.h>
75b89a82 51#import <dev/i386/disk.h>
14c7c974
A
52#import "libsaio.h"
53#import "memory.h"
54
55static Biosread(int biosdev, int secno);
56static read_label(char *name, int biosdev, daddr_t *boff, int partition);
57void diskActivityHook(void);
58extern void spinActivityIndicator(void);
59
60/* diskinfo unpacking */
61#define SPT(di) ((di)&0xff)
62#define HEADS(di) ((((di)>>8)&0xff)+1)
63#define SPC(di) (SPT(di)*HEADS(di))
64#define BPS 512 /* sector size of the device */
65#define N_CACHE_SECS (BIOS_LEN / BPS)
66
67#define DOS_BSIZE 512
68#define DISKLABEL 15 /* sector num of disk label */
69
70char *devsw[] = {
71 "sd",
72 "hd",
73 "fd",
74 NULL
75};
76
77struct diskinfo {
78 int spt; /* sectors per track */
79 int spc; /* sectors per cylinder */
80} diskinfo;
81
82char *b[NBUFS];
83daddr_t blknos[NBUFS];
84struct iob iob[NFILES];
85int label_secsize;
86static int label_cached;
87
88// intbuf is the whole buffer, biosbuf is the current cached sector
89static char * const intbuf = (char *)ptov(BIOS_ADDR);
90char *biosbuf;
91
92void
93devopen(name, io)
94 char * name;
95 struct iob * io;
96{
97 long di;
98
99 di = get_diskinfo(io->biosdev);
100
101 /* initialize disk parameters -- spt and spc */
102 io->i_error = 0;
103 io->dirbuf_blkno = -1;
104
105 diskinfo.spt = SPT(di);
106 diskinfo.spc = diskinfo.spt * HEADS(di);
107 if (read_label(name, io->biosdev, &io->i_boff, io->partition) < 0)
108 {
109 io->i_error = EIO;
110 }
111}
112
113void devflush()
114{
115 Biosread(0,-1);
116}
117
118
119int devread(io)
120 struct iob *io;
121{
122 long sector;
123 int offset;
124 int dev;
125
126 io->i_flgs |= F_RDDATA;
127
128 /* assume the best */
129 io->i_error = 0;
130
131 dev = io->i_ino.i_dev;
132
133 sector = io->i_bn * (label_secsize/DOS_BSIZE);
134
135 for (offset = 0; offset < io->i_cc; offset += BPS) {
136
137 io->i_error = Biosread(io->biosdev, sector);
138 if (io->i_error) {
139 return(-1);
140 }
141
142 /* copy 1 sector from the internal buffer biosbuf into buf */
143 bcopy(biosbuf, &io->i_ma[offset], BPS);
144
145 sector++;
146 }
147
148 io->i_flgs &= ~F_TYPEMASK;
149 return (io->i_cc);
150}
151
152/* A haque: Biosread(0,-1) means flush the sector cache.
153 */
154static int
155Biosread(int biosdev, int secno)
156{
157 static int xbiosdev, xcyl=-1, xhead, xsec, xnsecs;
158
159 int rc;
160 int cyl, head, sec;
161 int spt, spc;
162 int tries = 0;
163
164 if (biosdev == 0 && secno == -1) {
165 xcyl = -1;
166 label_cached = 0;
167 return 0;
168 }
169 spt = diskinfo.spt;
170 spc = diskinfo.spc;
171
172 cyl = secno / spc;
173 head = (secno % spc) / spt;
174 sec = secno % spt;
175
176 if (biosdev == xbiosdev && cyl == xcyl && head == xhead &&
177 sec >= xsec && sec < (xsec + xnsecs))
178 { // this sector is in intbuf cache
179 biosbuf = intbuf + (BPS * (sec-xsec));
180 return 0;
181 }
182
183 xcyl = cyl;
184 label_cached = 1;
185 xhead = head;
186 xsec = sec;
187 xbiosdev = biosdev;
188 xnsecs = ((sec + N_CACHE_SECS) > spt) ? (spt - sec) : N_CACHE_SECS;
189 biosbuf = intbuf;
190
191 while ((rc = biosread(biosdev,cyl,head,sec, xnsecs)) && (++tries < 5))
192 {
193#ifndef SMALL
194 error(" biosread error 0x%x @ %d, C:%d H:%d S:%d\n",
195 rc, secno, cyl, head, sec);
196#endif
197 sleep(1); // on disk errors, bleh!
198 }
199 diskActivityHook();
200 return rc;
201}
202
203// extern char name[];
204
205#ifndef SMALL
206static int
207read_label(
208 char *name,
209 int biosdev,
210 daddr_t *boff,
211 int partition
212)
213{
214 struct disk_label *dlp;
215 struct fdisk_part *fd;
216 struct disk_blk0 *blk0;
217 char *cp;
218 int n, rc;
219 int part_offset = 0;
220 static int cached_boff;
221
222 if (label_cached) {
223 *boff = cached_boff;
224 return 0;
225 }
226
227 // read sector 0 into the internal buffer "biosbuf"
228 if ( rc = Biosread(biosdev, 0) )
229 return -1;
230
231 // Check for a valid boot block.
232 blk0 = (struct disk_blk0 *)biosbuf;
233 if (blk0->signature == DISK_SIGNATURE) {
234 // Check to see if the disk has been partitioned with FDISK
235 // to allow DOS and ufs filesystems to exist on the same spindle.
236 fd = (struct fdisk_part *)blk0->parts;
237 for ( n = 0; n < FDISK_NPART; n++, fd++)
238 if (fd->systid == FDISK_NEXTNAME)
239 {
240 part_offset = fd->relsect;
241 break;
242 }
243 }
244 /* It's not an error if there is not a valid boot block. */
245
246 /* Read the NeXT disk label.
247 * Since we can't count on it fitting in the sector cache,
248 * we'll put it elsewhere.
249 */
250 dlp = (struct disk_label *)malloc(sizeof(*dlp) + BPS);
251 for(n = 0, cp = (char *)dlp;
252 n < ((sizeof(*dlp) + BPS - 1) / BPS);
253 n++, cp += BPS) {
254 if (rc = Biosread(biosdev, DISKLABEL + part_offset + n))
255 goto error;
256 bcopy(biosbuf, cp, BPS);
257 }
258
259 byte_swap_disklabel_in(dlp);
260
261 /* Check label */
262
263 if (dlp->dl_version != DL_V3) {
264 error("bad disk label magic\n");
265 goto error;
266 }
267
268 label_secsize = dlp->dl_secsize;
269
270 if ((dlp->dl_part[partition].p_base) < 0) {
271 error("no such partition\n");
272 goto error;
273 }
274
275 *boff = cached_boff = dlp->dl_front + dlp->dl_part[partition].p_base;
276
277 if (!strcmp(name,"$LBL")) strcpy(name, dlp->dl_bootfile);
278
279 free((char *)dlp);
280 return 0;
281error:
282 free((char *)dlp);
283 return -1;
284}
285
286#endif SMALL
287
288
289/* replace this function if you want to change
290 * the way disk activity is indicated to the user.
291 */
292
293void
294diskActivityHook(void)
295{
296 spinActivityIndicator();
297}
298
299
300