Initial import from FreeBSD RELENG_4:
[games.git] / sys / i386 / boot / biosboot / disk.c
1 /*
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.
25  *
26  *      from: Mach, Revision 2.2  92/04/04  11:35:49  rpd
27  * $FreeBSD: src/sys/i386/boot/biosboot/disk.c,v 1.28 1999/12/08 09:32:48 phk 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.
38  */
39
40 #include "boot.h"
41 #include <sys/disklabel.h>
42 #include <sys/diskslice.h>
43
44 #define BIOS_DEV_FLOPPY 0x0
45 #define BIOS_DEV_WIN    0x80
46
47 #define BPS             512
48 #define SPT(di)         ((di)&0xff)
49 #define HEADS(di)       ((((di)>>8)&0xff)+1)
50
51 static int bsize;
52
53 static int spt, spc;
54
55 struct fs *fs;
56 struct inode inode;
57 int dosdev, unit, slice, part, maj, boff;
58
59 /*#define EMBEDDED_DISKLABEL 1*/
60
61 /* Read ahead buffer large enough for one track on a 1440K floppy.  For
62  * reading from floppies, the bootstrap has to be loaded on a 64K boundary
63  * to ensure that this buffer doesn't cross a 64K DMA boundary.
64  */
65 #define RA_SECTORS      18
66 static char ra_buf[RA_SECTORS * BPS];
67 static int ra_dev;
68 static int ra_end;
69 static int ra_first;
70
71 static char *Bread(int dosdev, int sector);
72
73 int
74 devopen(void)
75 {
76         struct dos_partition *dptr;
77         struct disklabel *dl;
78         char *p;
79         int i, sector = 0, di, dosdev_copy;
80
81         dosdev_copy = dosdev;
82         di = get_diskinfo(dosdev_copy);
83         spt = SPT(di);
84
85         /* Hack for 2.88MB floppy drives. */
86         if (!(dosdev_copy & 0x80) && spt == 36)
87                 spt = 18;
88
89         spc = spt * HEADS(di);
90
91 #ifndef RAWBOOT
92         {
93 #ifdef  EMBEDDED_DISKLABEL
94                 dl = &disklabel;
95 #else   EMBEDDED_DISKLABEL
96                 p = Bread(dosdev_copy, 0);
97                 dptr = (struct dos_partition *)(p+DOSPARTOFF);
98                 slice = WHOLE_DISK_SLICE;
99                 for (i = 0; i < NDOSPART; i++, dptr++)
100                         if (dptr->dp_typ == DOSPTYP_386BSD) {
101                                 slice = BASE_SLICE + i;
102                                 sector = dptr->dp_start;
103                                 break;
104                         }
105                 p = Bread(dosdev_copy, sector + LABELSECTOR);
106                 dl=((struct disklabel *)p);
107                 disklabel = *dl;        /* structure copy (maybe useful later)*/
108 #endif  EMBEDDED_DISKLABEL
109                 if (dl->d_magic != DISKMAGIC) {
110                         printf("bad disklabel\n");
111                         return 1;
112                 }
113                 if( (maj == 4) || (maj == 0) || (maj == 1))
114                 {
115                         if (dl->d_type == DTYPE_SCSI)
116                         {
117                                 maj = 4; /* use scsi as boot dev */
118                         }
119                         else
120                         {
121                                 maj = 0; /* must be ESDI/IDE */
122                         }
123                 }
124                 /* This little trick is for OnTrack DiskManager disks */
125                 boff = dl->d_partitions[part].p_offset -
126                         dl->d_partitions[2].p_offset + sector;
127
128                 bsize = dl->d_partitions[part].p_size;
129                 if (bsize == 0) {
130                         printf("empty partition\n");
131                         return 1;
132                 }
133
134         }
135 #endif /* RAWBOOT */
136         return 0;
137 }
138
139
140 /*
141  * Be aware that cnt is rounded up to N*BPS
142  */
143 void
144 devread(char *iodest, int sector, int cnt)
145 {
146         int offset;
147         char *p;
148         int dosdev_copy;
149
150         for (offset = 0; offset < cnt; offset += BPS)
151         {
152                 dosdev_copy = dosdev;
153                 p = Bread(dosdev_copy, sector++);
154                 bcopy(p, iodest+offset, BPS);
155         }
156 }
157
158
159 static char *
160 Bread(int dosdev, int sector)
161 {
162         if (dosdev != ra_dev || sector < ra_first || sector >= ra_end)
163         {
164                 int cyl, head, sec, nsec;
165
166                 cyl = sector/spc;
167                 if (cyl > 1023) {
168                         printf("Error: C:%d > 1023 (BIOS limit)\n", cyl);
169                         for(;;);        /* loop forever */
170                 }
171                 head = (sector % spc) / spt;
172                 sec = sector % spt;
173                 nsec = spt - sec;
174                 if (nsec > RA_SECTORS)
175                         nsec = RA_SECTORS;
176                 twiddle();
177                 if (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0)
178                 {
179                     nsec = 1;
180                     twiddle();
181                     while (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0) {
182                         printf("Error: D:0x%x C:%d H:%d S:%d\n",
183                                dosdev, cyl, head, sec);
184                         twiddle();
185                     }
186                 }
187                 ra_dev = dosdev;
188                 ra_first = sector;
189                 ra_end = sector + nsec;
190         }
191         return (ra_buf + (sector - ra_first) * BPS);
192 }