3
Copyright (C) 1996 Pete A. Zaitcev
4
1996,1997 Jakub Jelinek
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22
#include <stringops.h>
25
static int floppy = 0;
26
static unsigned int flash = 0;
28
static unsigned long long seekp;
29
static char bootdevice[4096];
30
static char currentdevice[4096];
32
char *silo_disk_get_bootdevice(void)
37
int silo_disk_open(char *device)
39
strcpy (currentdevice, device);
42
seekp = 0xffffffffffffffffULL;
48
if (strlen (device) < 20) {
49
/* v0 prom likes to paint in devopen parameter sometimes... */
50
strcpy (buffer, device);
53
fd = (*romvec->pv_v0devops.v0_devopen) (p);
54
if (device[0] == 'f' && device[1] == 'd')
56
else if ((device[0] == 'l' || device[0] == 'i') && device[1] == 'e')
66
fd = (*romvec->pv_v2devops.v2_dev_open) (device);
67
if ((unsigned)(fd + 1) > 1) {
68
node = (romvec->pv_v2devops.v2_inst2pkg) (fd);
69
prom_getstring (node, "device_type", buffer, 20);
70
if (!strcmp (buffer, "network"))
80
fd = p1275_cmd ("open", 1, device);
81
if ((unsigned)(fd + 1) > 1) {
82
node = p1275_cmd ("instance-to-package", 1, fd);
84
* Don't use our argument due to devalias.
85
* Alas, flash has no device_type property.
87
prom_getstring (node, "name", buffer, 20);
88
if (!strcmp (buffer, "flash-memory")) {
90
reg[0] = 0; reg[1] = 0; reg[2] = 0;
91
prom_getproperty (node, "reg", (char*)®[0], sizeof (reg));
94
prom_getstring (node, "device_type", buffer, 20);
95
if (!strcmp (buffer, "network"))
102
if (fd == 0 || fd == -1) {
103
printf ("\nFatal error: Couldn't open device %s\n", device);
109
extern unsigned char boot_part, boot_parts[32];
110
extern unsigned char raid_dsk_number;
112
int get_boot_part(void)
115
if (raid_dsk_number > 32)
116
printf("Internal error. RAID disk number should be at most 32.\n");
117
else if (raid_dsk_number)
118
ret = boot_parts[raid_dsk_number - 1];
122
int silo_diskinit(void)
125
if (prom_vers == PROM_V0) {
126
struct linux_arguments_v0 *ap = *romvec->pv_v0bootargs;
127
char *s = bootdevice;
129
*s++ = ap->boot_dev[0];
130
*s++ = ap->boot_dev[1];
132
*s++ = (ap->boot_dev_ctrl & 07) + '0';
134
if ((*s = ap->boot_dev_unit / 10 + '0') != '0')
136
*s++ = ap->boot_dev_unit % 10 + '0';
138
*s++ = get_boot_part() + '0';
143
if (prom_vers == PROM_P1275)
144
prom_getproperty (prom_chosen, "bootpath", bootdevice, sizeof(bootdevice));
146
strcpy (bootdevice, *romvec->pv_v2bootargs.bootpath);
147
p = strchr (bootdevice, ':');
149
p = strchr (bootdevice, 0); *p++ = ':'; *p++ = get_boot_part() + 'a'; *p = 0;
150
} else if (p[1] >= 'a' && p[1] <= 'z' && !p[2])
151
p[1] = get_boot_part() + 'a';
153
return silo_disk_open(bootdevice);
156
static void silo_disk_reopen(void)
163
silo_disk_open(currentdevice);
166
static unsigned int flash_ld(unsigned int offset)
171
__asm__ __volatile__("lda [%2] %1, %0\n\t" :
172
"=r" (retval) : "i" (0x20), "r" (offset));
176
int silo_disk_read(char *buff, int size, unsigned long long offset)
180
if (prom_vers == PROM_V0) {
182
return (*romvec->pv_v0devops.v0_rdnetdev) (fd, size, buff);
185
int i = 0, j, k, rc = 0, ret = 0;
187
if (offset & 0x1ff) {
188
if (size > 512 - (offset & 0x1ff))
189
i = 512 - (offset & 0x1ff);
192
for (j = 0; j < 5; j++) {
193
rc = (*romvec->pv_v0devops.v0_rdblkdev) (fd, 1, (unsigned)(offset >> 9), buffer);
199
memcpy (buff, buffer + (offset & 0x1ff), i);
202
offset = ((offset + 512) & ~0x1ffULL);
206
for (j = 0; j < 5; j++) {
207
rc = (*romvec->pv_v0devops.v0_rdblkdev) (fd, size >> 9, (unsigned)(offset >> 9), buff);
211
if (rc != (size >> 9)) {
212
/* Lets try if the floppy is not happy because the read size is too large for it */
213
for (k = 0; k < (size >> 9); k++) {
214
for (j = 0; j < 5; j++) {
215
rc = (*romvec->pv_v0devops.v0_rdblkdev) (fd, 1, (unsigned)(offset >> 9) + k, buff + (k << 9));
223
i = (size & (~0x1ff));
230
for (j = 0; j < 5; j++) {
231
rc = (*romvec->pv_v0devops.v0_rdblkdev) (fd, 1, (unsigned)(offset >> 9), buffer);
237
memcpy (buff, buffer, size);
250
if (offset >= 0x1000000) { /* Not very precise but will work... */
251
printf ("Reading beyond 16MB of flash, bad filesystem.\n");
256
* Right thing is to map stuff in, then do a copy.
257
* We, however, are not sure that PROM does not leak mappings.
258
* So, let's kludge data in with ASI_BYPASS.
259
* Note that flash must be accessed with 32 bits loads.
261
offset += 1024; /* XXX Offset of flash filesystem */
264
xlen = 4 - (offset & 3);
266
word = flash_ld (offset & ~3);
267
memcpy (buff, ((char *)&word) + (4 - xlen), xlen);
273
while (count + 4 <= size) {
274
word = flash_ld (offset);
275
memcpy (buff, (char *)&word, 4);
283
word = flash_ld (offset);
284
memcpy (buff, (char *)&word, xlen);
294
if (prom_vers != PROM_P1275) {
295
if (((romvec->pv_printrev >> 16) < 2 ||
296
((romvec->pv_printrev >> 16) == 2 && (romvec->pv_printrev && 0xffff) < 6))
297
&& offset >= 0x40000000) {
298
printf ("Buggy old PROMs don't allow reading past 1GB from start of the disk. Send complaints to SMCC\n");
302
if (seekp != offset) {
303
if (prom_vers == PROM_P1275) {
304
if ((rc = p1275_cmd ("seek", P1275_ARG_64B(2) | 3, fd, 0, offset)) == -1)
307
if ((*romvec->pv_v2devops.v2_dev_seek) (fd, (unsigned)(offset >> 32), (unsigned)offset) == -1)
313
if (prom_vers == PROM_P1275) {
314
rc = p1275_cmd ("read", 3, fd, buff, size);
317
for (i = 0; i < 2; i++) {
318
rc = (*romvec->pv_v2devops.v2_dev_read) (fd, buff, size);
319
if (rc == size) break;
321
if ((*romvec->pv_v2devops.v2_dev_seek) (fd, (unsigned)(offset >> 32), (unsigned)offset) == -1)
324
if (rc != size && size > 32768) {
328
if (size < 32768) j = size; else j = 32768;
329
if (silo_disk_read(buff, j, offset) != j)
348
void silo_disk_close(void)
350
if (*currentdevice) {
353
(*romvec->pv_v0devops.v0_devclose) (fd); break;
356
(*romvec->pv_v2devops.v2_dev_close) (fd); break;
358
p1275_cmd ("close", 1, fd); break;
364
int silo_disk_setdisk(char *device)
366
if (!strcmp(currentdevice, device))
370
return silo_disk_open(device);
374
* XXX Good thing would be to have an argument, perhaps some device name.
375
* XXX Other option is to make silo_disk_open() to return partitionable flag.
376
* XXX Retrofit floppy ((flash == 0) && (floppy == 0) && (net == 0));
378
int silo_disk_partitionable(void)