This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / i386 / boot / disk.c
CommitLineData
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.
78ed81a3 25 *
26 * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd
27 * $Id$
15637ed4
RG
28 */
29
30#include "boot.h"
31#ifdef DO_BAD144
32#include <sys/dkbad.h>
33#endif DO_BAD144
34#include <sys/disklabel.h>
35
36#define BIOS_DEV_FLOPPY 0x0
37#define BIOS_DEV_WIN 0x80
38
39#define BPS 512
40#define SPT(di) ((di)&0xff)
41#define HEADS(di) ((((di)>>8)&0xff)+1)
42
43char *devs[] = {"wd", "hd", "fd", "wt", "sd", 0};
44
45#ifdef DO_BAD144
46struct dkbad dkb;
47int do_bad144;
48int bsize;
49#endif DO_BAD144
50
51int spt, spc;
52
53char *iodest;
54struct fs *fs;
55struct inode inode;
56int dosdev, unit, part, maj, boff, poff, bnum, cnt;
57
58/*#define EMBEDDED_DISKLABEL 1*/
59extern struct disklabel disklabel;
60/*struct disklabel disklabel;*/
61
62devopen()
63{
64 struct dos_partition *dptr;
65 struct disklabel *dl;
66 int dosdev = inode.i_dev;
67 int i, sector, di;
68
69 di = get_diskinfo(dosdev);
70 spc = (spt = SPT(di)) * HEADS(di);
71 if (dosdev == 2)
72 {
73 boff = 0;
74 part = (spt == 15 ? 3 : 1);
75 }
76 else
77 {
78#ifdef EMBEDDED_DISKLABEL
79 dl = &disklabel;
80#else EMBEDDED_DISKLABEL
81 Bread(dosdev, 0);
82 dptr = (struct dos_partition *)(((char *)0)+DOSPARTOFF);
83 for (i = 0; i < NDOSPART; i++, dptr++)
84 if (dptr->dp_typ == DOSPTYP_386BSD)
85 break;
86 sector = dptr->dp_start + LABELSECTOR;
87 Bread(dosdev, sector++);
88 dl=((struct disklabel *)0);
89 disklabel = *dl; /* structure copy (maybe useful later)*/
90#endif EMBEDDED_DISKLABEL
91 if (dl->d_magic != DISKMAGIC) {
92 printf("bad disklabel");
93 return 1;
94 }
95 if( (maj == 4) || (maj == 0) || (maj == 1))
96 {
97 if (dl->d_type == DTYPE_SCSI)
98 {
99 maj = 4; /* use scsi as boot dev */
100 }
101 else
102 {
103 maj = 0; /* must be ESDI/IDE */
104 }
105 }
106 boff = dl->d_partitions[part].p_offset;
107#ifdef DO_BAD144
108 bsize = dl->d_partitions[part].p_size;
109 do_bad144 = 0;
110 if (dl->d_flags & D_BADSECT) {
111 /* this disk uses bad144 */
112 int i;
113 int dkbbnum;
114 struct dkbad *dkbptr;
115
116 /* find the first readable bad144 sector */
117 /* some of this code is copied from ufs/disk_subr.c */
118 /* read a bad sector table */
119 dkbbnum = dl->d_secperunit - dl->d_nsectors;
120 if (dl->d_secsize > DEV_BSIZE)
121 dkbbnum *= dl->d_secsize / DEV_BSIZE;
122 else
123 dkbbnum /= DEV_BSIZE / dl->d_secsize;
124 i = 0;
125 do_bad144 = 0;
126 do {
127 /* XXX: what if the "DOS sector" < 512 bytes ??? */
128 Bread(dosdev, dkbbnum + i);
129 dkbptr = (struct dkbad *) 0;
130/* XXX why is this not in <sys/dkbad.h> ??? */
131#define DKBAD_MAGIC 0x4321
132 if (dkbptr->bt_mbz == 0 &&
133 dkbptr->bt_flag == DKBAD_MAGIC) {
134 dkb = *dkbptr; /* structure copy */
135 do_bad144 = 1;
136 break;
137 }
138 i += 2;
139 } while (i < 10 && i < dl->d_nsectors);
140 if (!do_bad144)
141 printf("Bad badsect table\n");
142 else
143 printf("Using bad144 bad sector at %d\n", dkbbnum+i);
144 }
145#endif DO_BAD144
146 }
147 return 0;
148}
149
150devread()
151{
152 int offset, sector = bnum;
153 int dosdev = inode.i_dev;
154 for (offset = 0; offset < cnt; offset += BPS)
155 {
156 Bread(dosdev, badsect(dosdev, sector++));
157 bcopy(0, iodest+offset, BPS);
158 }
159}
160
78ed81a3 161#define I_ADDR ((void *) 0) /* XXX where all reads go */
162
163/* Read ahead buffer large enough for one track on a 1440K floppy. For
164 * reading from floppies, the bootstrap has to be loaded on a 64K boundary
165 * to ensure that this buffer doesn't cross a 64K DMA boundary.
166 */
167#define RA_SECTORS 18
168static char ra_buf[RA_SECTORS * BPS];
169static int ra_end;
170static int ra_first;
171
15637ed4
RG
172Bread(dosdev,sector)
173 int dosdev,sector;
174{
78ed81a3 175 if (sector < ra_first || sector >= ra_end)
15637ed4 176 {
78ed81a3 177 int cyl, head, sec, nsec;
178
179 cyl = sector/spc;
180 head = (sector % spc) / spt;
181 sec = sector % spt;
182 nsec = spt - sec;
183 if (nsec > RA_SECTORS)
184 nsec = RA_SECTORS;
185 twiddle();
186 if (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0)
187 {
188 nsec = 1;
189 twiddle();
190 while (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0) {
191 printf("Error: C:%d H:%d S:%d\n", cyl, head, sec);
192 twiddle();
193 }
194 }
195 ra_first = sector;
196 ra_end = sector + nsec;
15637ed4 197 }
78ed81a3 198 bcopy(ra_buf + (sector - ra_first) * BPS, I_ADDR, BPS);
15637ed4
RG
199}
200
201badsect(dosdev, sector)
202 int dosdev, sector;
203{
204 int i;
205#ifdef DO_BAD144
206 if (do_bad144) {
207 u_short cyl;
208 u_short head;
209 u_short sec;
210 int newsec;
211 struct disklabel *dl = &disklabel;
212
213 /* XXX */
214 /* from wd.c */
215 /* bt_cyl = cylinder number in sorted order */
216 /* bt_trksec is actually (head << 8) + sec */
217
218 /* only remap sectors in the partition */
219 if (sector < boff || sector >= boff + bsize) {
220 goto no_remap;
221 }
222
223 cyl = sector / dl->d_secpercyl;
224 head = (sector % dl->d_secpercyl) / dl->d_nsectors;
225 sec = sector % dl->d_nsectors;
226 sec = (head<<8) + sec;
227
228 /* now, look in the table for a possible bad sector */
229 for (i=0; i<126; i++) {
230 if (dkb.bt_bad[i].bt_cyl == cyl) {
231 /* found same cylinder */
232 if (dkb.bt_bad[i].bt_trksec == sec) {
233 /* FOUND! */
234 break;
235 }
236 } else if (dkb.bt_bad[i].bt_cyl > cyl) {
237 i = 126;
238 break;
239 }
240 }
241 if (i == 126) {
242 /* didn't find bad sector */
243 goto no_remap;
244 }
245 /* otherwise find replacement sector */
246 newsec = dl->d_secperunit - dl->d_nsectors - i -1;
247 return newsec;
248 }
249#endif DO_BAD144
250 no_remap:
251 return sector;
252}