1 static char _[] = "@(#)pceb.c 5.18 93/07/30 16:40:31, 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 *****************************************************************************
30 ** This file defines functions which initialize and access the
31 ** the PCEB 29K board.
33 *****************************************************************************
48 void endian_cvt PARAMS((union msg_t *, int));
49 void tip_convert32 PARAMS((BYTE *));
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
61 init_comm_pceb(PC_port_base, PC_mem_seg)
66 /*** check for existence of the board ***/
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));
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
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.
91 msg_send_pceb(msg_ptr, PC_port_base)
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));
110 /* Do endian conversion */
111 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
112 endian_cvt(msg_ptr, OUTGOING_MSG);
115 result = Mini_write_memory ((INT32) D_MEM,
116 (ADDR32) PCEB_SEND_BUF,
117 (INT32) message_size,
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),
125 /* Did everything go ok? */
131 } /* end msg_send_pceb() */
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.
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.
149 msg_recv_pceb(msg_ptr, PC_port_base, Mode)
150 union msg_t *msg_ptr;
157 ADDR32 recv_buf_addr;
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);
168 /* Change endian of recv_buf_addr */
169 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
170 tip_convert32((BYTE *) &recv_buf_addr);
172 /* Return if there is no message */
173 if (recv_buf_addr == 0) {
176 /* Get message header */
177 header_size = (INT32) (2 * sizeof(INT32));
178 result1 = Mini_read_memory ((INT32) D_MEM,
179 (ADDR32) recv_buf_addr,
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));
192 /* Do endian conversion */
193 if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
194 endian_cvt(msg_ptr, INCOMING_MSG);
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);
204 /* Did everything go ok? */
205 if ((result1 != (INT32) 0) ||
206 (result2 != (INT32) 0) ||
207 (result3 != (INT32) 0))
210 return(msg_ptr->generic_msg.code);
212 } /* end msg_recv_pceb() */
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.
224 exit_comm_pceb(PC_port_base, PC_mem_seg)
232 reset_comm_pceb(PC_port_base, PC_mem_seg)
239 } /* end reset_comm_pceb() */
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.
250 go_pceb(PC_port_base, PC_mem_seg)
256 /* Reset processor */
257 setup = (PCEB_LB_END | PCEB_WINENA);
259 outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
260 (int) (setup | PCEB_S_RESET | PCEB_S_HALT));
262 outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
263 (int) (setup | PCEB_S_RESET | PCEB_S_NORMAL));
265 outp((unsigned int) (PC_port_base + PCEB_PC229K_OFFSET),
266 (int ) (setup | PCEB_S_NORMAL));
268 } /* end go_pceb() */
276 ** This function is used to write a string of bytes to
277 ** the Am29000 memory on the PCEB board.
279 ** For more information on the PCEB interface, see
280 ** Chapter 5 of the "PCEB User's Manual".
282 ** Note: This function aligns all 16 1K byte windows to make
283 ** a single 16K byte window on a 1K boundary.
287 write_memory_pceb(memory_space, address, data, byte_count, PC_port_base,
298 INT32 bytes_in_window;
301 while (byte_count > 0) {
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));
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;
316 bytes_in_window = (INT32) 0x4000 - (address & 0x3ff);
317 copy_count = (byte_count < bytes_in_window) ? byte_count : bytes_in_window;
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),
325 data = data + copy_count;
326 address = address + copy_count;
327 byte_count = byte_count - copy_count;
329 } /* end while loop */
333 } /* End write_memory_pceb() */
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
344 ** For more information on the PCEB interface, see
345 ** Chapter 5 of the "PCEB User's Manual".
347 ** Note: This function aligns all 16 1K byte windows to make
348 ** a single 16K byte window on a 1K boundary.
352 read_memory_pceb(memory_space, address, data, byte_count, PC_port_base,
363 INT32 bytes_in_window;
366 while (byte_count > 0) {
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));
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;
381 bytes_in_window = (INT32) 0x4000 - (address & 0x3ff);
382 copy_count = (byte_count < bytes_in_window) ? byte_count : bytes_in_window;
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),
390 data = data + copy_count;
391 address = address + copy_count;
392 byte_count = byte_count - copy_count;
394 } /* end while loop */
398 } /* End read_memory_pceb() */