epirawdma.c
7.85 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/**************************************************************************
* *
* Copyright (C) 1995, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#include "osint.h"
#include "piint.h"
#include "rcp.h"
#include "assert.h"
/*
* Name: __osEPiRawStartDma
*
* Description:
* Based on the input direction (OS_READ or OS_WRITE), setup a DMA
* transfer between RDRAM and PI device address space.
* devAddr and dramAddr specifies the DMA buffer address of the device
* memory and RDRAM, respectively. size contains the number of bytes to
* transfer. Note that the ROM address needs to be 16-bit aligned and
* RDRAM address 64-bit aligned. Furthermore, the size must be a
* multiple of 2 bytes. Maximum transfer size is 16 MBytes (24-bit).
* If the interface is busy, return a "-1" and abort the operation.
*
*/
s32
__osEPiRawStartDma(OSPiHandle *pihandle, s32 direction, u32 devAddr,
void *dramAddr, u32 size)
{
u64 dummybuf[2];
u32 stat;
u32 domain;
u32 buffer;
u32 pgsize;
u16* adr;
u32 i;
#ifdef _DEBUG
/* Check for valid direction */
if ((direction != OS_READ) && (direction != OS_WRITE)) {
__osError(ERR_OSPIRAWSTARTDMA_DIR, 1, direction);
return(-1);
}
/* Need 16-bit alignment for ROM */
if (devAddr & 0x1) {
__osError(ERR_OSPIRAWSTARTDMA_DEVADDR, 1, devAddr);
return(-1);
}
/* Need 64-bit alignment for RDRAM */
if ((u32)dramAddr & 0x7) {
__osError(ERR_OSPIRAWSTARTDMA_ADDR, 1, dramAddr);
return(-1);
}
/* Size must be a multiple of 2 bytes */
if (size & 0x1) {
__osError(ERR_OSPIRAWSTARTDMA_SIZE, 1, size);
return(-1);
}
/* Check for valid range: 0 < size <= 16 MBytes */
if ((size == 0) || (size > (16*1024*1024))) {
__osError(ERR_OSPIRAWSTARTDMA_RANGE, 1, size);
return(-1);
}
#endif
stat = IO_READ(PI_STATUS_REG);
while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) {
stat = IO_READ(PI_STATUS_REG);
}
/* Configuring the PI if needed */
domain = (u32)pihandle->domain;
if (__osCurrentHandle[domain]->type != pihandle->type) {
OSPiHandle *cHandle = __osCurrentHandle[domain];
if (domain == PI_DOMAIN1) {
if (cHandle->latency != pihandle->latency)
IO_WRITE(PI_BSD_DOM1_LAT_REG,pihandle->latency);
if (cHandle->pageSize != pihandle->pageSize)
IO_WRITE(PI_BSD_DOM1_PGS_REG,pihandle->pageSize);
if (cHandle->relDuration != pihandle->relDuration)
IO_WRITE(PI_BSD_DOM1_RLS_REG,
pihandle->relDuration);
if (cHandle->pulse != pihandle->pulse)
IO_WRITE(PI_BSD_DOM1_PWD_REG,pihandle->pulse);
} else {
if (cHandle->latency != pihandle->latency)
IO_WRITE(PI_BSD_DOM2_LAT_REG,pihandle->latency);
if (cHandle->pageSize != pihandle->pageSize)
IO_WRITE(PI_BSD_DOM2_PGS_REG,pihandle->pageSize);
if (cHandle->relDuration != pihandle->relDuration)
IO_WRITE(PI_BSD_DOM2_RLS_REG,
pihandle->relDuration);
if (cHandle->pulse != pihandle->pulse)
IO_WRITE(PI_BSD_DOM2_PWD_REG,pihandle->pulse);
}
cHandle->type = pihandle->type;
cHandle->latency = pihandle->latency;
cHandle->pageSize = pihandle->pageSize;
cHandle->relDuration = pihandle->relDuration;
cHandle->pulse = pihandle->pulse;
}
/*----------松下製1Mフラッシュバグ対策 開始
/*
/* 松下製1Mフラッシュで問題となる2バイト(1ワード)DMAの発生防止のため1ワードDMAが発生しない
/* ように対策を行う。
/* 1ワードDMAになる部分はIOリードで前もって読んでおき、実際のDMAは1ワードDMA部分を除いた形で
/* 行う。
/*
*/
/* リードにのみ対応 */
if(direction==OS_READ){
/* ページサイズの計算 */
pgsize = 1;
for (i = 1; i <= pihandle->pageSize + 2; ++i)
pgsize = pgsize * 2;
/*
DMAの開始アドレスがページサイズアライメント-2だった場合
最初の2バイトを4バイトIOリードで読み込み、DMA開始位置をROM・RAM共に2プラスし、サイズを
2マイナスする。
ただし、このまま次のDMAを開始するとRAM側のアライメントが8バイト制限を満たさなくなるため、
残りDMAサイズに応じて合計8バイトのデータを4バイトIOリードでメモリにコピーする。
4バイト(使うのは後半2バイト)+4バイト+4バイト(使うのは前半2バイト)
最終的なDMA開始位置は元の位置からROM・RAM共に8バイトずれる。
*/
/* DMAの開始アドレスがページサイズアライメント-2だった場合 */
if ((devAddr & (pgsize-1)) == pgsize-2){
/* 本来の1ワードDMA部分を2バイト手前から4バイトIOリードで読む */
__osEPiRawReadIo(pihandle, devAddr-2, &buffer);
/* バッファから転送先に後半2バイトのみコピー */
adr = (u16 *) PHYS_TO_K1(dramAddr); *adr = (u16) (buffer & 0xffff);
/* ROMとRAMのアドレスを2プラスし、残りDMAサイズを2マイナスする */
devAddr += 2; ++adr; dramAddr = adr; size -= 2;
/*残りDMAサイズが4以上の場合、まず4バイト読む*/
if (size >= 4){
/* 次のDMAを正しいメモリ位置から開始するためにRAM側のDMA開始アドレス
を8バイトアライメントにするためのリード1*/
/* 4バイトIOリードでバッファに読む*/
__osEPiRawReadIo(pihandle, devAddr, &buffer);
/* バッファから転送先に4バイトコピー */
*adr = (u16)(buffer>>16);
++adr; *adr = (u16)(buffer&0xffff);
/* ROMとRAMのアドレスを4プラスし、残りDMAサイズを4マイナスする */
devAddr += 4; ++adr; dramAddr =adr; size -= 4;
/*まだ残りDMAサイズが存在する場合、最後の2バイトを4バイトIOリードで読む*/
if (size > 0){
/* 次のDMAを正しいメモリ位置から開始するためにRAM側のDMA開始アドレス
を8バイトアライメントにするためのリード2*/
/* 4バイトIOリードでバッファに読む */
__osEPiRawReadIo(pihandle, devAddr, &buffer);
/*バッファから転送先に前半2バイトのみコピー */
adr = (u16 *) PHYS_TO_K1(dramAddr); *adr = (u16)(buffer>>16);
/* ROMとRAMのアドレスを2プラスし、残りDMAサイズを2マイナスする */
devAddr += 2; ++adr; dramAddr =adr; size -= 2;
}
}
}
/*
DMAの終了アドレスがページサイズアライメント+2か、あるいは残りDMAサイズが2だった場合、
最後の2バイトを4バイトIOリードで読み込み、DMAサイズを2マイナスする
*/
if ((((devAddr+size) & (pgsize-1)) == 2)|(size==2)){
/* ROM側の終了アドレスが4バイトアライメントになっていない場合、終了アドレス
の2バイト手前からバッファに4バイトIOリードし、前半2バイトをメモリにコピーする*/
if(((devAddr+size)&0x2)==2){
__osEPiRawReadIo(pihandle, devAddr+size-2, &buffer);
adr = ((u16 *) PHYS_TO_K1(dramAddr)) + (size - 2)/sizeof(*adr);
*adr = (u16) (buffer>> 16);
}
/* ROM側の終了アドレスが4バイトアライメントになっている場合、終了アドレス
の4バイト手前からバッファに4バイトIOリードし、後半2バイトをメモリにコピーする
(このケースは残りDMAサイズが2だった場合にのみ起きる)*/
else{
__osEPiRawReadIo(pihandle, devAddr+size-4, &buffer);
adr = ((u16 *) PHYS_TO_K1(dramAddr)) + (size - 2)/sizeof(*adr);
*adr = (u16) (buffer & 0xffff);
}
size = size - 2;
}
/* 残りDMAsize が 0 になる場合はDMAが発生しなくなるため、代わりにダミーのDMA(ROM先頭
からダミーバッファへ8バイトのDMA)を行うようにセットする */
if (size == 0){
size = 8;
dramAddr = &dummybuf[0];
devAddr = 0;
}
}
/*----------松下製1Mフラッシュバグ対策 終了----------*/
IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr));
IO_WRITE(PI_CART_ADDR_REG, K1_TO_PHYS((u32)pihandle->baseAddress|devAddr));
/* Note that actual programmed size of transfer = size - 1 */
switch (direction) {
case OS_READ: { /* PI -> RDRAM */
IO_WRITE(PI_WR_LEN_REG, size-1);
break;
}
case OS_WRITE: { /* PI <- RDRAM */
IO_WRITE(PI_RD_LEN_REG, size-1);
break;
}
default: {
return(-1);
}
}
return(0);
} /* __osEPiRawStartDma */