1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/*
* Copyright 1996 The Australian National University.
* Copyright 1996 Fujitsu Laboratories Limited
*
* This software may be distributed under the terms of the Gnu
* Public License version 2 or later
*/
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/genhd.h>
#include <asm/pgtable.h>
#include <asm/ap1000/apreg.h>
#include <asm/ap1000/DdvReqTable.h>
#define GENDISK_STRUCT ddv_gendisk
struct RequestTable *RTable=NULL;
struct OPrintBufArray *PrintBufs=NULL;
struct OAlignBufArray *AlignBufs=NULL;
struct DiskInfo *DiskInfo=NULL;
extern int ddv_length[];
int ddv_mlist_available(void)
{
int start = RTable->start_mtable;
int end = RTable->end_mtable;
if (start >= end)
return (MTABLE_SIZE - start);
return (end+1) - start;
}
int ddv_get_mlist(unsigned mptr[],int bnum)
{
int available = ddv_mlist_available();
int i;
int start = RTable->start_mtable;
if (available < bnum) {
return -1;
}
for (i = 0; i < bnum; i++) {
unsigned phys = (unsigned)mmu_v2p((unsigned)mptr[i]);
if (phys == -1)
panic("bad address %x in ddv_get_mlist\n",mptr[i]);
RTable->mtable[RTable->start_mtable] = phys;
RTable->start_mtable = INC_ML(RTable->start_mtable);
}
return start;
}
void ddv_load_kernel(char *opcodep)
{
int tsize;
char *p;
struct exec *mhead;
mhead = (struct exec *)opcodep;
p = opcodep + sizeof(*mhead);
tsize = (mhead->a_text + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
memcpy((char *)OPIBUS_BASE+mhead->a_entry,p,mhead->a_text);
memcpy((char *)OPIBUS_BASE+mhead->a_entry+tsize,
p+mhead->a_text,mhead->a_data);
memset((char *)OPIBUS_BASE+mhead->a_entry+tsize+mhead->a_data,0,
mhead->a_bss+PAGE_SIZE);
#ifdef DDV_DEBUG
printk("CELL(%d) loaded opiu kernel of size %ld %ld %ld (%ld)\n",
ap_getcid(),
mhead->a_text,mhead->a_data,mhead->a_bss,mhead->a_entry);
#endif
}
int ddv_restart_cpu(void)
{
unsigned long timeout;
OPT_IO(OPIU_OP) = OPIU_RESET;
OPT_IO(PRST) = PRST_IRST;
if (OPT_IO(PRST) != PRST_IRST) {
printk("_iu_load reset release error.\n");
return(-1);
}
for (timeout=jiffies + 10;
(jiffies < timeout) || (OPT_IO(PBUF0) == 0);
) /* wait */ ;
if (OPT_IO(PBUF0) == 0) {
printk("WARNING: option kernel didn't startup\n");
return(-1);
} else {
printk("option kernel IU running\n");
DiskInfo = (struct DiskInfo *)(OPT_IO(PBUF0) + OPIBUS_BASE);
RTable = (struct RequestTable *)(DiskInfo->ptrs[0]+OPIBUS_BASE);
PrintBufs = (struct OPrintBufArray *)(DiskInfo->ptrs[1]+OPIBUS_BASE);
AlignBufs = (struct OAlignBufArray *)(DiskInfo->ptrs[2]+OPIBUS_BASE);
printk("Disk capacity: %d blocks of size %d\n",
(int)DiskInfo->blocks,(int)DiskInfo->blk_size);
OPT_IO(PBUF0) = 0;
}
return(0);
}
|