1 static char _[] = "@(#)eb030.c 5.20 93/10/26 09:57:05, Srini, AMD.";
2 /******************************************************************************
3 * Copyright 1991 Advanced Micro Devices, Inc.
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
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.
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.
20 * Advanced Micro Devices, Inc.
21 * 29K Support Products
23 * 5900 E. Ben White Blvd.
26 *****************************************************************************
27 * Engineer: Srini Subramanian.
28 *****************************************************************************
29 ** This file defines functions which initialize and access the
30 ** the EB030 "Lynx" board. This file is based heavily on the
32 *****************************************************************************
47 void endian_cvt PARAMS((union msg_t *, int));
48 void tip_convert32 PARAMS((BYTE *));
57 ** This function is used to initialize the communication
58 ** channel. This consists of setting the window location
59 ** of the EB030 to the value defined by the values in
64 init_comm_eb030(PC_port_base, PC_mem_seg)
70 /*** check for existence of the board ***/
72 /* Set up memory window location */
73 result = outp((unsigned int) PC_port_base,
74 ((int) ((PC_mem_seg >> 10) & 0x1f)));
76 /* Set up window base to zero */
77 outp ((unsigned int) (PC_port_base+1), (unsigned int) 0);
78 outp ((unsigned int) (PC_port_base+2), (unsigned int) 0);
81 } /* end init_comm_eb030() */
85 ** This function is used to send a message to the EB030.
86 ** If the message is successfully sent, a zero is
87 ** returned. If the message was not sendable, a -1
90 ** Also note that this function does endian conversion on the
91 ** returned message. This is necessary because the Am29000
92 ** target will be sending big-endian messages and the PC will
93 ** be expecting little-endian.
97 msg_send_eb030(msg_ptr, PC_port_base)
106 /* Set semaphore (EB030_RECV_BUF_PTR) to zero */
108 result = Mini_write_memory((INT32) D_MEM,
109 (ADDR32) EB030_RECV_BUF_PTR,
110 (INT32) sizeof (INT32),
111 (BYTE *) &semaphore);
114 /* Get size of whole message */
115 message_size = (msg_ptr->generic_msg).length + (2 * sizeof(INT32));
117 /* Is the size of the message valid? */
119 /* Do endian conversion */
120 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
121 endian_cvt(msg_ptr, OUTGOING_MSG);
124 result = Mini_write_memory((INT32) D_MEM,
125 (ADDR32) EB030_SEND_BUF,
126 (INT32) message_size,
129 if (result != (INT32) 0)
132 /* Interrupt target (write to EB030 mailbox) */
133 result = outp((unsigned int) (PC_port_base+3),
138 } /* end msg_send_eb030() */
144 ** This function is used to receive a message to the EB030.
145 ** If the message is waiting in the buffer, a zero is
146 ** returned and the buffer pointed to by msg_ptr is filled
147 ** in. If no message was available, a -1 is returned.
149 ** Note that this function does endian conversion on the
150 ** returned message. This is necessary because the Am29000
151 ** target will be sending big-endian messages and the PC will
152 ** be expecting little-endian.
156 msg_recv_eb030(msg_ptr, PC_port_base, Mode)
157 union msg_t *msg_ptr;
162 ADDR32 recv_buf_addr;
168 /* Poll EB030 mailbox */
169 /* (If mailbox contains 0xff, a message is waiting) */
170 retval = inp((unsigned int) (PC_port_base+3));
172 /* If no message waiting, return -1 */
176 /* Get receive buffer address */
177 result = Mini_read_memory ((INT32) D_MEM,
178 (ADDR32) EB030_RECV_BUF_PTR,
179 (INT32) sizeof (ADDR32),
180 (BYTE *) &recv_buf_addr);
182 if (result != (INT32) 0)
185 /* Change endian of recv_buf_addr (if necessary) */
186 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
187 tip_convert32((BYTE *) &recv_buf_addr);
189 if (recv_buf_addr == (ADDR32) 0) {
192 /* Get message header */
193 header_size = (INT32) (2 * sizeof(INT32));
194 result = Mini_read_memory ((INT32) D_MEM,
195 (ADDR32) recv_buf_addr,
202 /* Get rest of message */
203 parms_length = (msg_ptr->generic_msg).length;
205 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
206 tip_convert32((BYTE *) &parms_length);
208 /* Is the size of the message valid? */
210 result = Mini_read_memory ((INT32) D_MEM,
211 (ADDR32) (recv_buf_addr + header_size),
212 (INT32) parms_length,
213 (BYTE *) &(msg_ptr->generic_msg.byte));
217 /* Do endian conversion (if necessary) */
218 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
219 endian_cvt(msg_ptr, INCOMING_MSG);
221 /* Write 0xff to EB030 mailbox */
222 /* (This tells EB030 that message has been received) */
223 retval = outp((unsigned int) (PC_port_base+3), (int) 0xff);
225 /* Set semaphore (EB030_RECV_BUF_PTR) to zero */
227 result = Mini_write_memory((INT32) D_MEM,
228 (ADDR32) EB030_RECV_BUF_PTR,
229 (INT32) sizeof (INT32),
230 (BYTE *) &semaphore);
235 return((INT32) msg_ptr->generic_msg.code);
237 } /* end msg_recv_eb030() */
243 ** This function is used to reset the communication
244 ** channel. This is used when resyncing the host and
245 ** target and when exiting the monitor.
249 exit_comm_eb030(PC_port_base, PC_mem_seg)
257 reset_comm_eb030(PC_port_base, PC_mem_seg)
262 /* Set up memory window location */
263 outp((unsigned int) PC_port_base,
264 ((int) ((PC_mem_seg >> 10) & 0x1f)));
266 /* Set up window base to zero */
267 outp ((unsigned int) (PC_port_base+1), (unsigned int) 0);
268 outp ((unsigned int) (PC_port_base+2), (unsigned int) 0);
272 } /* end reset_comm_eb030() */
277 ** This function is used to "kick" the EB030. This
278 ** amounts to yanking the *RESET line low. Code
279 ** will begin execution at ROM address 0.
283 go_eb030(PC_port_base, PC_mem_seg)
289 /* Toggle the RESET bit in Control Port Register 0 */
290 result = outp((unsigned int) PC_port_base,
291 ((int) ((PC_mem_seg >> 10) & 0x1f)));
292 result = outp((unsigned int) PC_port_base,
293 ((int) (((PC_mem_seg >> 10) & 0x1f) |
296 } /* end go_eb030() */
301 ** This function is used to write a string of bytes to
302 ** the Am29000 memory on the EB030 board.
307 write_memory_eb030(memory_space, address, data, byte_count, PC_port_base, PC_mem_seg)
315 INT32 bytes_in_window;
318 while (byte_count > 0) {
320 /* Write out low order EB030_addr bits */
321 outp((unsigned int) (PC_port_base+1), (int) ((address >> 14) & 0xff));
322 /* Write out high order EB030_addr bits I-/D-Mem are same */
323 outp((unsigned int) (PC_port_base+2), (int) ((address >> 22) & 0x7f));
325 bytes_in_window = 0x4000 - (address & 0x3fff);
326 copy_count = MIN(byte_count, bytes_in_window);
328 (void) memmove ((void *) ((PC_mem_seg << 16) + (address & 0x3fff)),
330 (size_t) copy_count);
332 (void) movedata((unsigned int) FP_SEG(data),
333 (unsigned int) FP_OFF(data),
334 (unsigned int) PC_mem_seg,
335 (unsigned int) (address & 0x3fff),
339 data = data + copy_count;
340 address = address + copy_count;
341 byte_count = byte_count - copy_count;
343 } /* end while loop */
347 } /* End write_memory_eb030() */
353 ** This function is used to read a string of bytes from
354 ** the Am29000 memory on the EB030 board. A zero is
355 ** returned if the data is read successfully, otherwise
361 read_memory_eb030(memory_space, address, data, byte_count, PC_port_base, PC_mem_seg)
369 INT32 bytes_in_window;
372 while (byte_count > 0) {
374 /* Write out low order EB030_addr bits */
375 outp((unsigned int) (PC_port_base+1), (int) ((address >> 14) & 0xff));
376 /* Write out high order EB030_addr bits I/D are same */
377 outp((unsigned int) (PC_port_base+2), (int) ((address >> 22) & 0x7f));
379 bytes_in_window = 0x4000 - (address & 0x3fff);
380 copy_count = MIN(byte_count, bytes_in_window);
383 (void) memmove ((void *) data,
384 (void *) ((PC_mem_seg << 16) + (address & 0x3fff)),
385 (size_t) copy_count);
387 (void) movedata((unsigned int) PC_mem_seg,
388 (unsigned int) (address & 0x3fff),
389 (unsigned int) FP_SEG(data),
390 (unsigned int) FP_OFF(data),
393 data = data + copy_count;
394 address = address + copy_count;
395 byte_count = byte_count - copy_count;
397 } /* end while loop */
401 } /* End read_memory_eb030() */