Initial import from FreeBSD RELENG_4:
[games.git] / sys / boot / pc98 / boot2 / 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/boot/pc98/boot2/disk.c,v 1.4.2.1 2003/01/13 08:52:53 nyan Exp $
28  */
29
30 /*
31  * Ported to PC-9801 by Yoshio Kimura
32  */
33
34 /*
35  * 93/10/08  bde
36  *      If there is no 386BSD partition, initialize the label sector with
37  *      LABELSECTOR instead of with garbage.
38  *
39  * 93/08/22  bde
40  *      Fixed reading of bad sector table.  It is at the end of the 'c'
41  *      partition, which is not always at the end of the disk.
42  */
43
44 #include "boot.h"
45 #include <sys/disklabel.h>
46 #include <sys/diskslice.h>
47
48 #define BIOS_DEV_FLOPPY 0x0
49 #define BIOS_DEV_WIN    0x80
50
51 #define BPS             512
52 #define SPT(di)         ((di)&0xff)
53 #define HEADS(di)       (((di)>>8)&0xff)
54
55
56 static int spt, spc;
57
58 struct fs *fs;
59 struct inode inode;
60 int dosdev, unit, slice, part, maj, boff;
61
62 /*#define EMBEDDED_DISKLABEL 1*/
63
64 /* Read ahead buffer large enough for one track on a 1440K floppy.  For
65  * reading from floppies, the bootstrap has to be loaded on a 64K boundary
66  * to ensure that this buffer doesn't cross a 64K DMA boundary.
67  */
68 #define RA_SECTORS      18
69 static char ra_buf[RA_SECTORS * BPS];
70 static int ra_dev;
71 static int ra_end;
72 static int ra_first;
73
74 static char *Bread(int dosdev, int sector);
75
76 int
77 devopen(void)
78 {
79         struct dos_partition *dptr;
80         struct disklabel *dl;
81         char *p;
82         int i, sector = 0, di, dosdev_copy;
83
84         dosdev_copy = dosdev;
85         di = get_diskinfo(dosdev_copy);
86         spc = (spt = SPT(di)) * HEADS(di);
87
88 #ifndef RAWBOOT
89         if ((dosdev_copy & 0xf0) == 0x90)
90         {
91                 boff = 0;
92                 part = (spt == 15 ? 0 : 1);
93         }
94         else
95         {
96 #ifdef  EMBEDDED_DISKLABEL
97                 dl = &disklabel;
98 #else   EMBEDDED_DISKLABEL
99 #ifdef PC98
100                 p = Bread(dosdev_copy, 1);
101                 dptr = (struct dos_partition *)p;
102                 slice = WHOLE_DISK_SLICE;
103                 for (i = 0; i < NDOSPART; i++, dptr++)
104                         if (dptr->dp_mid == DOSPTYP_386BSD) {
105                                 slice = BASE_SLICE + i;
106                                 sector = dptr->dp_scyl * spc;
107                                 break;
108                         }
109                 p = Bread(dosdev, sector + LABELSECTOR);
110                 dl=((struct disklabel *)p);
111                 disklabel = *dl;        /* structure copy (maybe useful later)*/
112 #else
113                 p = Bread(dosdev_copy, 0);
114                 dptr = (struct dos_partition *)(p+DOSPARTOFF);
115                 slice = WHOLE_DISK_SLICE;
116                 for (i = 0; i < NDOSPART; i++, dptr++)
117                         if (dptr->dp_typ == DOSPTYP_386BSD) {
118                                 slice = BASE_SLICE + i;
119                                 sector = dptr->dp_start;
120                                 break;
121                         }
122                 p = Bread(dosdev_copy, sector + LABELSECTOR);
123                 dl=((struct disklabel *)p);
124                 disklabel = *dl;        /* structure copy (maybe useful later)*/
125 #endif /* PC98 */
126 #endif  EMBEDDED_DISKLABEL
127                 if (dl->d_magic != DISKMAGIC) {
128                         printf("bad disklabel\n");
129                         return 1;
130                 }
131                 /* This little trick is for OnTrack DiskManager disks */
132                 boff = dl->d_partitions[part].p_offset -
133                         dl->d_partitions[2].p_offset + sector;
134
135 #ifndef PC98
136                 bsize = dl->d_partitions[part].p_size;
137                 if (bsize == 0) {
138                         printf("empty partition\n");
139                         return 1;
140                 }
141
142 #endif
143
144         }
145 #endif /* RAWBOOT */
146         return 0;
147 }
148
149
150 /*
151  * Be aware that cnt is rounded up to N*BPS
152  */
153 void
154 devread(char *iodest, int sector, int cnt)
155 {
156         int offset;
157         char *p;
158         int dosdev_copy;
159
160         for (offset = 0; offset < cnt; offset += BPS)
161         {
162                 dosdev_copy = dosdev;
163                 p = Bread(dosdev_copy, sector++);
164                 bcopy(p, iodest+offset, BPS);
165         }
166 }
167
168
169 static char *
170 Bread(int dosdev, int sector)
171 {
172         if (dosdev != ra_dev || sector < ra_first || sector >= ra_end)
173         {
174                 int cyl, head, sec, nsec;
175
176                 cyl = sector/spc;
177 #ifndef PC98
178                 if (cyl > 1023) {
179                         printf("Error: C:%d > 1023 (BIOS limit)\n", cyl);
180                         for(;;);        /* loop forever */
181                 }
182 #endif
183                 head = (sector % spc) / spt;
184                 sec = sector % spt;
185                 nsec = spt - sec;
186                 if (nsec > RA_SECTORS)
187                         nsec = RA_SECTORS;
188                 twiddle();
189                 if (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0)
190                 {
191                     nsec = 1;
192                     twiddle();
193                     while (biosread(dosdev, cyl, head, sec, nsec, ra_buf) != 0) {
194                         printf("Error: D:0x%x C:%d H:%d S:%d\n",
195                                dosdev, cyl, head, sec);
196                         twiddle();
197                     }
198                 }
199                 ra_dev = dosdev;
200                 ra_first = sector;
201                 ra_end = sector + nsec;
202         }
203         return (ra_buf + (sector - ra_first) * BPS);
204 }