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