OSDN Git Service

* ps.cc (prog_name): New global variable.
[pf3gnuchains/pf3gnuchains4x.git] / utils / amd-udi / montip / pceb.c
1 static char _[] = "@(#)pceb.c   5.18 93/07/30 16:40:31, AMD.";
2 /******************************************************************************
3  * Copyright 1991 Advanced Micro Devices, Inc.
4  *
5  * This software is the property of Advanced Micro Devices, Inc  (AMD)  which
6  * specifically  grants the user the right to modify, use and distribute this
7  * software provided this notice is not removed or altered.  All other rights
8  * are reserved by AMD.
9  *
10  * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
11  * SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
12  * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
13  * USE OF THIS SOFTWARE.
14  *
15  * So that all may benefit from your experience, please report  any  problems
16  * or  suggestions about this software to the 29K Technical Support Center at
17  * 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in  the  UK,  or
18  * 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
19  *
20  * Advanced Micro Devices, Inc.
21  * 29K Support Products
22  * Mail Stop 573
23  * 5900 E. Ben White Blvd.
24  * Austin, TX 78741
25  * 800-292-9263
26  *****************************************************************************
27  *      Engineer: Srini Subramanian.
28  *****************************************************************************
29  ** 
30  **       This file defines functions which initialize and access the
31  **       the PCEB 29K board.
32  **
33  *****************************************************************************
34  */
35
36
37 #include <stdio.h>
38 #include <memory.h>
39 #include "messages.h"
40 #include "pceb.h"
41 #include "memspcs.h"
42 #include "macros.h"
43 #include "tdfunc.h"
44 #include "mtip.h"
45
46 #include <dos.h>
47 #include <conio.h>
48 void  endian_cvt PARAMS((union msg_t *, int));
49 void  tip_convert32 PARAMS((BYTE *));
50
51
52 /*
53 ** This function is used to initialize the communication
54 ** channel.  This consists of setting the window location
55 ** of the PCEB to the value defined by the values in
56 ** the file PCEB.h.
57 */
58
59 /*ARGSUSED*/
60 INT32
61 init_comm_pceb(PC_port_base, PC_mem_seg)
62 INT32   PC_port_base;
63 INT32   PC_mem_seg;
64    {
65    
66    /*** check for existence of the board ***/
67
68    /* Set up PCCNF and reset processor */
69    outp((unsigned int) (PC_port_base + PCEB_PCCNF_OFFSET),
70         ((int) (PC_mem_seg & 0x7000) >> 10));
71    outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
72         (int) (PCEB_LB_END | PCEB_WINENA | PCEB_S_HALT));
73
74    return(0);
75    }
76
77
78 /*
79 ** This function is used to send a message to the PCEB.
80 ** If the message is successfully sent, a zero is
81 ** returned.  If the message was not sendable, a -1
82 ** is returned.
83 **
84 ** Also note that this function does endian conversion on the
85 ** returned message.  This is necessary because the Am29000
86 ** target will be sending big-endian messages and the PC will
87 ** be expecting little-endian.
88 */
89
90 INT32
91 msg_send_pceb(msg_ptr, PC_port_base)
92    union  msg_t  *msg_ptr;
93    INT32        PC_port_base;
94    {
95    INT32    result;
96    int    pc229k;
97    INT32  message_size;
98    INT32        semaphore;
99    INT32        result3;
100
101          /* Set semaphore (PCEB_RECV_BUF_PTR) to zero */
102            semaphore = (INT32) 0;
103            result3 = Mini_write_memory ((INT32)   D_MEM,
104                                       (ADDR32) PCEB_RECV_BUF_PTR,
105                                       (INT32)  sizeof(INT32),
106                                       (BYTE *) &semaphore);
107    /* Get size of whole message */
108    message_size = (msg_ptr->generic_msg).length + (2 * sizeof(INT32));
109
110    /* Do endian conversion */
111    if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
112       endian_cvt(msg_ptr, OUTGOING_MSG);
113
114    /* Send message */
115    result = Mini_write_memory ((INT32)  D_MEM,
116                               (ADDR32) PCEB_SEND_BUF,
117                               (INT32)  message_size,
118                               (BYTE *) msg_ptr);
119
120    /* Interrupt target (write to pceb mailbox) */
121    pc229k = (PCEB_P_REQ | PCEB_WINENA | PCEB_LB_END | PCEB_S_NORMAL);
122    outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
123         (int) pc229k);
124
125    /* Did everything go ok? */
126    if (result != 0)
127       return(-1);
128       else
129          return(0);
130
131    }  /* end msg_send_pceb() */
132
133
134
135
136 /*
137 ** This function is used to receive a message to the PCEB.
138 ** If the message is waiting in the buffer, the message Code is
139 ** returned and the buffer pointed to by msg_ptr is filled
140 ** in.  If no message was available, a -1 is returned.
141 **
142 ** Note that this function does endian conversion on the
143 ** returned message.  This is necessary because the Am29000
144 ** target will be sending big-endian messages and the PC will
145 ** be expecting little-endian.
146 */
147
148 INT32
149 msg_recv_pceb(msg_ptr, PC_port_base, Mode)
150    union  msg_t  *msg_ptr;
151    INT32  PC_port_base;
152    INT32        Mode;
153    {
154    INT32    result1;
155    INT32    result2;
156    INT32    result3;
157    ADDR32 recv_buf_addr;
158    INT32  parms_length;
159    INT32  header_size;
160    INT32  semaphore;
161
162    /* Get receive buffer address */
163    result1 = Mini_read_memory ((INT32)  D_MEM,
164                               (ADDR32) PCEB_RECV_BUF_PTR,
165                               (INT32)  sizeof(ADDR32),
166                               (BYTE *) &recv_buf_addr);
167
168    /* Change endian of recv_buf_addr */
169    if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
170       tip_convert32((BYTE *) &recv_buf_addr);
171
172    /* Return if there is no message */
173    if (recv_buf_addr == 0) {
174       return(-1);
175       } else {
176          /* Get message header */
177          header_size = (INT32) (2 * sizeof(INT32));
178          result1 = Mini_read_memory ((INT32)  D_MEM,
179                                     (ADDR32) recv_buf_addr,
180                                     (INT32)  header_size,
181                                     (BYTE *) msg_ptr);
182
183          /* Get rest of message */
184          parms_length = (msg_ptr->generic_msg).length;
185          if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
186             tip_convert32((BYTE *) &parms_length);
187          result2 = Mini_read_memory ((INT32)  D_MEM,
188                                     (ADDR32) (recv_buf_addr + header_size),
189                                     (INT32)  parms_length,
190                                     (BYTE *) &(msg_ptr->generic_msg.byte));
191
192          /* Do endian conversion */
193          if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
194             endian_cvt(msg_ptr, INCOMING_MSG);
195
196          /* Set semaphore (PCEB_RECV_BUF_PTR) to zero */
197            semaphore = (INT32) 0;
198            result3 = Mini_write_memory ((INT32)   D_MEM,
199                                       (ADDR32) PCEB_RECV_BUF_PTR,
200                                       (INT32)  sizeof(INT32),
201                                       (BYTE *) &semaphore);
202       }
203
204    /* Did everything go ok? */
205    if ((result1 != (INT32) 0) ||
206        (result2 != (INT32) 0) ||
207        (result3 != (INT32) 0))
208          return(-1);
209       else
210          return(msg_ptr->generic_msg.code);
211
212    }  /* end msg_recv_pceb() */
213
214
215
216
217 /*
218 ** This function is used to close the communication
219 ** channel.  This is used when resyncing the host and
220 ** target and when exiting the monitor.
221 */
222
223 INT32
224 exit_comm_pceb(PC_port_base, PC_mem_seg)
225 INT32   PC_port_base;
226 INT32   PC_mem_seg;
227    {
228      return (0);
229    }
230
231 INT32
232 reset_comm_pceb(PC_port_base, PC_mem_seg)
233 INT32   PC_port_base;
234 INT32   PC_mem_seg;
235    {
236
237    return(0);
238
239    }  /* end reset_comm_pceb() */
240
241
242
243 /*
244 ** This function is used to "kick" the PCEB.  This
245 ** amounts to yanking the *RESET line low.  Code
246 ** will begin execution at ROM address 0.
247 */
248
249 void
250 go_pceb(PC_port_base, PC_mem_seg)
251 INT32   PC_port_base;
252 INT32   PC_mem_seg;
253    {
254    int  setup;
255
256    /* Reset processor */
257    setup = (PCEB_LB_END | PCEB_WINENA);
258
259    outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
260         (int) (setup | PCEB_S_RESET | PCEB_S_HALT));
261
262    outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
263         (int) (setup | PCEB_S_RESET | PCEB_S_NORMAL));
264
265    outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
266         (int ) (setup | PCEB_S_NORMAL));
267
268    }  /* end go_pceb() */
269
270
271
272
273
274
275 /*
276 ** This function is used to write a string of bytes to
277 ** the Am29000 memory on the PCEB board.
278 **
279 ** For more information on the PCEB interface, see
280 ** Chapter 5 of the "PCEB User's Manual".
281 **
282 ** Note:  This function aligns all 16 1K byte windows to make
283 ** a single 16K byte window on a 1K boundary.
284 */
285
286 INT32
287 write_memory_pceb(memory_space, address, data, byte_count, PC_port_base,
288                   PC_mem_seg)
289    INT32    memory_space;
290    ADDR32   address;
291    BYTE    *data;
292    INT32    byte_count;
293    INT32        PC_port_base;
294    INT32        PC_mem_seg;
295    {
296    INT32  i;
297    ADDR32 temp_address;
298    INT32  bytes_in_window;
299    INT32  copy_count;
300
301    while (byte_count > 0) {
302
303       /* Set up a single, contiguous 16K window (on a 1K boundary) */
304       temp_address = address;
305       for (i=0; i<16; i=i+1) {
306          /* Write out low PCEB addr bits */
307          outp((unsigned int) (PC_port_base+(INT32) (2*i)),
308               (int) ((temp_address >> 10) & 0xff));
309
310          /* Write out high PCEB addr bits */
311          outp((unsigned int) (PC_port_base+(INT32) (2*i)+(INT32) 1),
312               (int) ((temp_address >> 18) & 0x1f));
313          temp_address = temp_address + (ADDR32) 0x400;
314          }  /* end for */
315
316       bytes_in_window = (INT32) 0x4000 - (address & 0x3ff);
317       copy_count = (byte_count < bytes_in_window) ? byte_count : bytes_in_window;
318
319       (void) movedata((unsigned int) FP_SEG(data),
320                       (unsigned int) FP_OFF(data),
321                       (unsigned int) PC_mem_seg,
322                       (unsigned int) (address & 0x3ff),
323                       (int) copy_count);
324
325       data = data + copy_count;
326       address = address + copy_count;
327       byte_count = byte_count - copy_count;
328
329       }  /* end while loop */
330
331    return(0);
332
333    }  /* End write_memory_pceb() */
334
335
336
337
338 /*
339 ** This function is used to read a string of bytes from
340 ** the Am29000 memory on the PCEB board.   A zero is
341 ** returned if the data is read successfully, otherwise
342 ** a -1 is returned.
343 **
344 ** For more information on the PCEB interface, see
345 ** Chapter 5 of the "PCEB User's Manual".
346 **
347 ** Note:  This function aligns all 16 1K byte windows to make
348 ** a single 16K byte window on a 1K boundary.
349 */
350
351 INT32
352 read_memory_pceb(memory_space, address, data, byte_count, PC_port_base,
353                  PC_mem_seg)
354    INT32    memory_space;
355    ADDR32   address;
356    BYTE    *data;
357    INT32    byte_count;
358    INT32        PC_port_base;
359    INT32        PC_mem_seg;
360    {
361    INT32  i;
362    ADDR32 temp_address;
363    INT32  bytes_in_window;
364    INT32  copy_count;
365
366    while (byte_count > 0) {
367
368       /* Set up a single, contiguous 16K window (on a 1K boundary) */
369       temp_address = address;
370       for (i=0; i<16; i=i+1) {
371          /* Write out low PCEB addr bits */
372          outp((unsigned int) (PC_port_base+(2*i)),
373               (int) ((temp_address >> 10) & 0xff));
374
375          /* Write out high PCEB addr bits */
376          outp((unsigned int) (PC_port_base+(2*i)+(INT32) 1),
377               (int) ((temp_address >> 18) & 0x1f));
378          temp_address = temp_address + (ADDR32) 0x400;
379          }  /* end for */
380
381       bytes_in_window = (INT32) 0x4000 - (address & 0x3ff);
382       copy_count = (byte_count < bytes_in_window) ? byte_count : bytes_in_window;
383
384       (void) movedata((unsigned int) PC_mem_seg,
385                       (unsigned int) (address & 0x3ff),
386                       (unsigned int) FP_SEG(data),
387                       (unsigned int) FP_OFF(data),
388                       (int) copy_count);
389
390       data = data + copy_count;
391       address = address + copy_count;
392       byte_count = byte_count - copy_count;
393
394       }  /* end while loop */
395
396    return(0);
397
398    }  /* End read_memory_pceb() */
399
400 INT32
401 fill_memory_pceb()
402 {
403   return(0);
404 }