Commit | Line | Data |
---|---|---|
15637ed4 | 1 | /* |
15637ed4 RG |
2 | * Mach Operating System |
3 | * Copyright (c) 1992, 1991 Carnegie Mellon University | |
4 | * All Rights Reserved. | |
5 | * | |
6 | * Permission to use, copy, modify and distribute this software and its | |
7 | * documentation is hereby granted, provided that both the copyright | |
8 | * notice and this permission notice appear in all copies of the | |
9 | * software, derivative works or modified versions, and any portions | |
10 | * thereof, and that both notices appear in supporting documentation. | |
11 | * | |
12 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
13 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
14 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
15 | * | |
16 | * Carnegie Mellon requests users of this software to return to | |
17 | * | |
18 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
19 | * School of Computer Science | |
20 | * Carnegie Mellon University | |
21 | * Pittsburgh PA 15213-3890 | |
22 | * | |
23 | * any improvements or extensions that they make and grant Carnegie Mellon | |
24 | * the rights to redistribute these changes. | |
a27f4645 | 25 | * |
e4270b63 | 26 | * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd |
091a0361 AC |
27 | * $Id: disk.c,v 1.4 1994/02/22 22:59:40 rgrimes Exp $ |
28 | */ | |
29 | ||
30 | /* | |
31 | * 93/10/08 bde | |
32 | * If there is no 386BSD partition, initialize the label sector with | |
33 | * LABELSECTOR instead of with garbage. | |
34 | * | |
35 | * 93/08/22 bde | |
36 | * Fixed reading of bad sector table. It is at the end of the 'c' | |
37 | * partition, which is not always at the end of the disk. | |
15637ed4 RG |
38 | */ |
39 | ||
40 | #include "boot.h" | |
41 | #ifdef DO_BAD144 | |
42 | #include <sys/dkbad.h> | |
43 | #endif DO_BAD144 | |
44 | #include <sys/disklabel.h> | |
45 | ||
46 | #define BIOS_DEV_FLOPPY 0x0 | |
47 | #define BIOS_DEV_WIN 0x80 | |
48 | ||
49 | #define BPS 512 | |
50 | #define SPT(di) ((di)&0xff) | |
51 | #define HEADS(di) ((((di)>>8)&0xff)+1) | |
52 | ||
53 | char *devs[] = {"wd", "hd", "fd", "wt", "sd", 0}; | |
54 | ||
55 | #ifdef DO_BAD144 | |
56 | struct dkbad dkb; | |
57 | int do_bad144; | |
58 | int bsize; | |
59 | #endif DO_BAD144 | |
60 | ||
61 | int spt, spc; | |
62 | ||
63 | char *iodest; | |
64 | struct fs *fs; | |
65 | struct inode inode; | |
66 | int dosdev, unit, part, maj, boff, poff, bnum, cnt; | |
67 | ||
68 | /*#define EMBEDDED_DISKLABEL 1*/ | |
69 | extern struct disklabel disklabel; | |
70 | /*struct disklabel disklabel;*/ | |
71 | ||
72 | devopen() | |
73 | { | |
74 | struct dos_partition *dptr; | |
75 | struct disklabel *dl; | |
76 | int dosdev = inode.i_dev; | |
77 | int i, sector, di; | |
78 | ||
79 | di = get_diskinfo(dosdev); | |
80 | spc = (spt = SPT(di)) * HEADS(di); | |
81 | if (dosdev == 2) | |
82 | { | |
83 | boff = 0; | |
84 | part = (spt == 15 ? 3 : 1); | |
85 | } | |
86 | else | |
87 | { | |
88 | #ifdef EMBEDDED_DISKLABEL | |
89 | dl = &disklabel; | |
90 | #else EMBEDDED_DISKLABEL | |
91 | Bread(dosdev, 0); | |
92 | dptr = (struct dos_partition *)(((char *)0)+DOSPARTOFF); | |
091a0361 | 93 | sector = LABELSECTOR; |
15637ed4 | 94 | for (i = 0; i < NDOSPART; i++, dptr++) |
091a0361 AC |
95 | if (dptr->dp_typ == DOSPTYP_386BSD) { |
96 | sector = dptr->dp_start + LABELSECTOR; | |
15637ed4 | 97 | break; |
091a0361 | 98 | } |
15637ed4 RG |
99 | Bread(dosdev, sector++); |
100 | dl=((struct disklabel *)0); | |
101 | disklabel = *dl; /* structure copy (maybe useful later)*/ | |
102 | #endif EMBEDDED_DISKLABEL | |
103 | if (dl->d_magic != DISKMAGIC) { | |
104 | printf("bad disklabel"); | |
105 | return 1; | |
106 | } | |
107 | if( (maj == 4) || (maj == 0) || (maj == 1)) | |
108 | { | |
109 | if (dl->d_type == DTYPE_SCSI) | |
110 | { | |
111 | maj = 4; /* use scsi as boot dev */ | |
112 | } | |
113 | else | |
114 | { | |
115 | maj = 0; /* must be ESDI/IDE */ | |
116 | } | |
117 | } | |
118 | boff = dl->d_partitions[part].p_offset; | |
119 | #ifdef DO_BAD144 | |
120 | bsize = dl->d_partitions[part].p_size; | |
121 | do_bad144 = 0; | |
122 | if (dl->d_flags & D_BADSECT) { | |
123 | /* this disk uses bad144 */ | |
124 | int i; | |
125 | int dkbbnum; | |
126 | struct dkbad *dkbptr; | |
127 | ||
091a0361 AC |
128 | /* find the first readable bad sector table */ |
129 | /* some of this code is copied from ufs/ufs_disksubr.c */ | |
130 | /* including the bugs :-( */ | |
15637ed4 | 131 | /* read a bad sector table */ |
091a0361 AC |
132 | |
133 | #define BAD144_PART 2 /* XXX scattered magic numbers */ | |
134 | #define BSD_PART 0 /* XXX should be 2 but bad144.c uses 0 */ | |
135 | if (dl->d_partitions[BSD_PART].p_offset != 0) | |
136 | dkbbnum = dl->d_partitions[BAD144_PART].p_offset | |
137 | + dl->d_partitions[BAD144_PART].p_size; | |
138 | else | |
139 | dkbbnum = dl->d_secperunit; | |
140 | dkbbnum -= dl->d_nsectors; | |
141 | ||
15637ed4 RG |
142 | if (dl->d_secsize > DEV_BSIZE) |
143 | dkbbnum *= dl->d_secsize / DEV_BSIZE; | |
144 | else | |
145 | dkbbnum /= DEV_BSIZE / dl->d_secsize; | |
146 | i = 0; | |
147 | do_bad144 = 0; | |
148 | do { | |
149 | /* XXX: what if the "DOS sector" < 512 bytes ??? */ | |
150 | Bread(dosdev, dkbbnum + i); | |
151 | dkbptr = (struct dkbad *) 0; | |
152 | /* XXX why is this not in <sys/dkbad.h> ??? */ | |
153 | #define DKBAD_MAGIC 0x4321 | |
154 | if (dkbptr->bt_mbz == 0 && | |
155 | dkbptr->bt_flag == DKBAD_MAGIC) { | |
156 | dkb = *dkbptr; /* structure copy */ | |
157 | do_bad144 = 1; | |
158 | break; | |
159 | } | |
160 | i += 2; | |
161 | } while (i < 10 && i < dl->d_nsectors); | |
162 | if (!do_bad144) | |
091a0361 | 163 | printf("Bad bad sector table\n"); |
15637ed4 | 164 | else |
091a0361 | 165 | printf("Using bad sector table at %d\n", dkbbnum+i); |
15637ed4 RG |
166 | } |
167 | #endif DO_BAD144 | |
168 | } | |
169 | return 0; | |
170 | } | |
171 | ||
172 | devread() | |
173 | { | |
174 | int offset, sector = bnum; | |
175 | int dosdev = inode.i_dev; | |
176 | for (offset = 0; offset < cnt; offset += BPS) | |
177 | { | |
178 | Bread(dosdev, badsect(dosdev, sector++)); | |
179 | bcopy(0, iodest+offset, BPS); | |
180 | } | |
181 | } | |
182 | ||
a27f4645 RM |
183 | #define I_ADDR ((void *) 0) /* XXX where all reads go */ |
184 | ||
185 | /* Read ahead buffer large enough for one track on a 1440K floppy. For | |
186 | * reading from floppies, the bootstrap has to be loaded on a 64K boundary | |
187 | * to ensure that this buffer doesn't cross a 64K DMA boundary. | |
188 | */ | |
189 | #define RA_SECTORS 18 | |
190 | static char ra_buf[RA_SECTORS * BPS]; | |
2d95de23 | 191 | static int ra_dev; |
a27f4645 RM |
192 | static int ra_end; |
193 | static int ra_first; | |
194 | ||
15637ed4 RG |
195 | Bread(dosdev,sector) |
196 | int dosdev,sector; | |
197 | { | |
2d95de23 | 198 | if (dosdev != ra_dev || sector < ra_first || sector >= ra_end) |
15637ed4 | 199 | { |
a27f4645 RM |
200 | int cyl, head, sec, nsec; |
201 | ||
202 | cyl = sector/spc; | |
203 | head = (sector % spc) / spt; | |
204 | sec = sector % spt; | |
205 | nsec = spt - sec; | |
206 | if (nsec > RA_SECTORS) | |
207 | nsec = RA_SECTORS; | |
208 | twiddle(); | |
209 | if (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0) | |
210 | { | |
211 | nsec = 1; | |
212 | twiddle(); | |
213 | while (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0) { | |
214 | printf("Error: C:%d H:%d S:%d\n", cyl, head, sec); | |
215 | twiddle(); | |
216 | } | |
217 | } | |
2d95de23 | 218 | ra_dev = dosdev; |
a27f4645 RM |
219 | ra_first = sector; |
220 | ra_end = sector + nsec; | |
15637ed4 | 221 | } |
a27f4645 | 222 | bcopy(ra_buf + (sector - ra_first) * BPS, I_ADDR, BPS); |
15637ed4 RG |
223 | } |
224 | ||
225 | badsect(dosdev, sector) | |
226 | int dosdev, sector; | |
227 | { | |
228 | int i; | |
229 | #ifdef DO_BAD144 | |
230 | if (do_bad144) { | |
231 | u_short cyl; | |
232 | u_short head; | |
233 | u_short sec; | |
234 | int newsec; | |
235 | struct disklabel *dl = &disklabel; | |
236 | ||
237 | /* XXX */ | |
238 | /* from wd.c */ | |
239 | /* bt_cyl = cylinder number in sorted order */ | |
240 | /* bt_trksec is actually (head << 8) + sec */ | |
241 | ||
242 | /* only remap sectors in the partition */ | |
243 | if (sector < boff || sector >= boff + bsize) { | |
244 | goto no_remap; | |
245 | } | |
246 | ||
247 | cyl = sector / dl->d_secpercyl; | |
248 | head = (sector % dl->d_secpercyl) / dl->d_nsectors; | |
249 | sec = sector % dl->d_nsectors; | |
250 | sec = (head<<8) + sec; | |
251 | ||
252 | /* now, look in the table for a possible bad sector */ | |
253 | for (i=0; i<126; i++) { | |
254 | if (dkb.bt_bad[i].bt_cyl == cyl) { | |
255 | /* found same cylinder */ | |
256 | if (dkb.bt_bad[i].bt_trksec == sec) { | |
257 | /* FOUND! */ | |
258 | break; | |
259 | } | |
260 | } else if (dkb.bt_bad[i].bt_cyl > cyl) { | |
261 | i = 126; | |
262 | break; | |
263 | } | |
264 | } | |
265 | if (i == 126) { | |
266 | /* didn't find bad sector */ | |
267 | goto no_remap; | |
268 | } | |
269 | /* otherwise find replacement sector */ | |
091a0361 AC |
270 | if (dl->d_partitions[BSD_PART].p_offset != 0) |
271 | newsec = dl->d_partitions[BAD144_PART].p_offset | |
272 | + dl->d_partitions[BAD144_PART].p_size; | |
273 | else | |
274 | newsec = dl->d_secperunit; | |
275 | newsec -= dl->d_nsectors + i + 1; | |
15637ed4 RG |
276 | return newsec; |
277 | } | |
278 | #endif DO_BAD144 | |
279 | no_remap: | |
280 | return sector; | |
281 | } |