readhost.c
5.91 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
/**************************************************************************
* *
* 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 <os.h>
#include <os_bb.h>
#include <os_internal.h>
#include <rdb.h>
#ifndef _FINALROM
static int readHostInitialized = 0;
static OSMesgQueue readHostMesgQueue;
#ifdef BBPLAYER
static OSMesg readHostMesgBuf[2];
#else
static OSMesg readHostMesgBuf[1];
#endif
/*
* Name: osReadHost
*
* Description:
* Copy nbytes of data from the host to DRAM starting at dramAddr
*
* CAUTION: Application must insure that only one call to osReadHost at a time!!!
*
* How it works:
* An application on the indy must open /dev/u64_data. Then the host app
* calls uhWriteGame with the data to be sent. The write call will block until
* the game sends a signal, indicating that it is ready to receive the data.
* When the write call receives the signal, it will start sending data over the
* rdb port, which will be stored in the buffer pointed to by __osRdb_Read_Data_Buf.
* When __osRdb_Read_Data_Ct is reached, exceptasm will generate a message of
* OS_EVENT_RDB_READ_DONE.
*
* Timing of which call is made first, osReadHost, or uhWriteGame is not critical.
* If uhWriteGame occurs first, host will block, if osReadHost occurs first, host
* kernal will save the ready message, and start once uhWriteGame occurs. Meanwhile,
* osReadHost will block waiting for done message. Note that osReadHost does block,
* and stops the running of the thread that called it.
*
* Potential problems occur if osReadHost is called, but not matched by an equivilent
* uhWriteGame call from the host.
*/
u8 *__osRdb_Read_Data_Buf;
u32 __osRdb_Read_Data_Ct;
#ifndef BBPLAYER /* Original N64 version */
void osReadHost(void *dramAddr, u32 nbytes)
{
unsigned char tstr[4];
u32 sent = 0;
/* The first time through, initialize a message queue for completion ack */
if (!readHostInitialized)
{
osCreateMesgQueue(&readHostMesgQueue, readHostMesgBuf, 1);
osSetEventMesg(OS_EVENT_RDB_READ_DONE, &readHostMesgQueue,NULL);
readHostInitialized = 1;
}
/* set up pointers and counters used by exceptasm */
__osRdb_Read_Data_Buf = (u8*)dramAddr;
__osRdb_Read_Data_Ct = nbytes;
/* send message to host telling host, you are ready for data */
while(sent < 1)
sent += __osRdbSend(&tstr[0],1,RDB_TYPE_GtoH_READY_FOR_DATA);
/* block waiting for all data to be transferred */
(void)osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_BLOCK);
return;
}
#else /* BBPLAYER */
/*
* Name:__osReadHost
* Description: Internal helper function that attempts to read nbytes into
* dramAddr. Will exit if when nbytes read or error occurred.
* Returns: Number of bytes read.
*/
u32 __osReadHost(void *dramAddr, u32 nbytes)
{
unsigned char tstr[4];
u32 sent = 0, nBytesRead = 0;
u32 saveMask;
/* The first time through, initialize a message queue for completion ack */
if (!readHostInitialized)
{
osCreateMesgQueue(&readHostMesgQueue, readHostMesgBuf, 2);
osSetEventMesg(OS_EVENT_RDB_READ_DONE, &readHostMesgQueue,
(OSMesg) OS_MESG_TYPE_RDB_READ_DONE);
osSetEventMesg(OS_EVENT_RDB_READ_RESET, &readHostMesgQueue,
(OSMesg) OS_MESG_TYPE_RDB_READ_RESET);
readHostInitialized = 1;
}
/* set up pointers and counters used by exceptasm */
saveMask = __osDisableInt();
__osRdb_Read_Data_Buf = (u8*)dramAddr;
__osRdb_Read_Data_Ct = nbytes;
__osRestoreInt(saveMask);
/* send message to host telling host, you are ready for data */
while(sent < 1) {
if (osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_NOBLOCK) == 0) {
/* Ooh, we already got a message */
/* If there are two, get the other one also */
(void)osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_NOBLOCK);
break;
}
tstr[0] = 0;
sent += __osRdbSend(&tstr[0],1,RDB_TYPE_GtoH_READY_FOR_DATA);
}
if (sent >= 1) {
/* block waiting for all data to be transferred */
(void)osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_BLOCK);
/* if there are two messages, snag them both */
(void)osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_NOBLOCK);
}
/* Reset the Rdb read pointers and counters */
saveMask = __osDisableInt();
nBytesRead = nbytes - __osRdb_Read_Data_Ct;
__osRdb_Read_Data_Buf = 0;
__osRdb_Read_Data_Ct = 0;
__osRestoreInt(saveMask);
/* Return number of bytes read */
return nBytesRead;
}
/*
* Name: osReadHost
* Description: Backward compatible version of osReadHost that
* blocks until all nbytes have been read into dramAddr.
* NOTE: Only one call to osReadHost or osBbReadHost at a time!!!
*/
void osReadHost(void *dramAddr, u32 nbytes)
{
u32 nBytesRead = 0;
while (nBytesRead < nbytes) {
nBytesRead += __osReadHost(((u8*)dramAddr)+nBytesRead, nbytes);
}
}
/*
* Name: osBbReadHost
* Description: Version of osReadHost for the BB that will
* return if there is an error.
* Returns: < 0 if error
* 0 if nbytes successfully read into dramAddr
* NOTE: Only one call to osReadHost or osBbReadHost at a time!!!
*/
s32 osBbReadHost(void *dramAddr, u32 nbytes)
{
u32 nBytesRead = __osReadHost(dramAddr, nbytes);
if (nBytesRead < nbytes)
return -1;
return 0;
}
#endif /* BBPLAYER */
#endif /* ifndef _FINALROM */