Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / serial / serial.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: serial.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/*
22 * Copyright (C) 1991, 2001 Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25#pragma ident "@(#)1.11 04/08/04 serial.cc"
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <assert.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <strings.h>
34#include <unistd.h>
35
36#include "types.h"
37#include "blaze_globals.h"
38#include "system.h"
39#include "dr.h"
40#include "term.h"
41#include "serial.h"
42#include "serial_impl.h"
43
44typedef void* TM_OPAQUE_DATA;
45#include "tracemod.h"
46
47#include "serial_mod.h"
48
49#define BYTE_OFFSET 7
50
51
52extern Serial *systemConsole;;
53
54/*
55 * This function is to allocate a serial object
56 */
57serialT *Serial::allocation_obj()
58{
59 msp = (serialT *) calloc(1, sizeof(serialT));
60
61 if (msp == NULL) {
62 debug_err("%s: malloc serial object failed\n", HERE);
63 return NULL;
64 }
65
66 reset_scc();
67
68 return (msp);
69}
70
71
72/*
73 * This routine is called to receive requests to read and write the serial's
74 * registers. Return a status of 1 if error
75 */
76int
77Serial::reg_access(char *buf, uint64_t paddr, bool wr)
78{
79
80 uint8_t *reg_value = (uint8_t *) (buf + BYTE_OFFSET); /* value of register read */
81 uint32_t addr = (uint32_t) paddr & SERIAL_PORT_ADDR_MASK;
82
83
84 if (!wr) {
85 switch (addr) {
86 case PORT_A_CONTROL:
87 *reg_value = rd_control(PORT_A);
88 break;
89
90 case PORT_B_CONTROL:
91 *reg_value = rd_control(PORT_B);
92 break;
93
94 case PORT_A_DATA:
95 *reg_value = rd_port(PORT_A);
96 break;
97
98 case PORT_B_DATA:
99 *reg_value = rd_port(PORT_B);
100 break;
101
102 default:
103 printf("%s: read invalid address 0x%lx\n", HERE, addr);
104 debug_err("%s: read invalid address 0x%lx\n", HERE, addr);
105 return 1;
106 }
107 } else {
108 switch (addr) {
109 case PORT_A_CONTROL:
110 wr_control(PORT_A,
111 *(uint8_t *) (buf + BYTE_OFFSET));
112 break;
113
114 case PORT_B_CONTROL:
115 wr_control(PORT_B,
116 *(uint8_t *) (buf + BYTE_OFFSET));
117 break;
118
119 case PORT_A_DATA:
120 wr_port(PORT_A,
121 *(uint8_t *) (buf + BYTE_OFFSET));
122 break;
123
124 case PORT_B_DATA:
125 wr_port(PORT_B,
126 *(uint8_t *) (buf + BYTE_OFFSET));
127 break;
128
129 default:
130 printf("%s: write invalid address 0x%lx\n", HERE,
131 paddr);
132 debug_err("%s: write invalid address 0x%lx\n", HERE,
133 paddr);
134 return 1;
135 }
136 }
137
138 return 0;
139}
140
141/*
142 * This routine is called to receive characters as they arrive. It queues
143 * them up in the serial's internal queue.
144 */
145void
146Serial::char_input(uint8_t c, int portnum)
147{
148 channel_regs *rcv_regs;
149
150 rcv_regs = &(msp->scc.port[portnum]);
151
152 enq(rcv_regs, c);
153
154 /* turn on the "ready to receive" flag */
155 rcv_regs->rr[0] |= RX_CHAR_AVAILABLE;
156
157 if (INTERRUPTS_ENABLED(msp, portnum) && !RCV_INT_PENDING(msp, portnum)
158 && RCV_INT_ENABLED(msp, portnum) && rcv_regs->qcnt) {
159 /*
160 * Update status reg - Interrupt Pending Send interrupt
161 */
162 channel_regs *channelA = &(msp->scc.port[PORT_A]);
163 channel_regs *channelB = &(msp->scc.port[PORT_B]);
164
165 /*
166 * if we're generating interrupts in Vector Include Status mode,
167 * the interrupt vector on channelB includes status in the lower
168 * nibble which is characteristic of the event causing the
169 * interrupt.
170 */
171 if (rcv_regs->wr[9] & VIS) {
172 /*
173 * if no interrupts are pending, clear out
174 * vector include status bits before or'ing in new state
175 * (channelA.rr3) is the interrupt pending register
176 * (channelB.rr2) is the interrupt vector (VIS) register
177 */
178 if (!channelA->rr[3])
179 /* clearing idle "special rcv condition" bits */
180 channelB->rr[2] &= ~VIS_LO_MASK;
181
182 /* add "Rx ready" to status vector */
183 SET_VIS_RX_CHAR_AVAIL(msp, portnum);
184 }
185
186 SET_RCV_INT_PENDING(msp, portnum);
187 //dev_interrupt_in(TRUE,device, 0);
188 pciMaster_set_int(0,true);
189 }
190}
191
192/*
193 * Add character 'c' to end of port receive queue.
194 */
195void
196Serial::enq(channel_regs * rcv_regs, char c)
197{
198 squeue *q, *cursor;
199
200
201
202
203 if ((q = (squeue *) calloc(1, sizeof(squeue))) == NULL) {
204 assert(0);
205/* fatal("serial: enq: Unable to malloc.\n"); */
206 }
207
208
209 q->c = c;
210 q->next = NULL;
211
212 mutex_lock(&rcv_regs->serial_lock);
213
214 cursor = &rcv_regs->q;
215
216 while (cursor->next) {
217 cursor = cursor->next;
218 }
219
220 cursor->next = q;
221 rcv_regs->qcnt++;
222
223 mutex_unlock(&rcv_regs->serial_lock);
224
225}
226
227/*
228 * Remove character from front of queue and return it. If no char, return
229 * the NULL character.
230 */
231char
232Serial::deq(channel_regs * rcv_regs)
233{
234 squeue *cursor;
235 char c = '\0'; /* still return 0 if nothing here */
236
237 mutex_lock(&rcv_regs->serial_lock);
238
239 if (rcv_regs->qcnt) {
240 cursor = &rcv_regs->q;
241 if (cursor->next) {
242 cursor = cursor->next;
243 c = cursor->c;
244 rcv_regs->q.next = cursor->next;
245 rcv_regs->qcnt--;
246 free((char *) cursor);
247 } else {
248 assert(0);
249/* fatal("serial: deq: qcnt inconsistent"); */
250 }
251 }
252
253 mutex_unlock(&rcv_regs->serial_lock);
254
255 return (c);
256}
257
258char
259Serial::rd_port(int portnum)
260{
261 char c;
262 channel_regs *rcv_regs;
263
264 rcv_regs = &(msp->scc.port[portnum]);
265
266 c = deq(rcv_regs);
267
268 /* turn off "ready to receive" flag if we're out of characters */
269 if (rcv_regs->qcnt == 0) {
270 rcv_regs->rr[0] &= ~RX_CHAR_AVAILABLE;
271 }
272
273 if (RCV_INT_PENDING(msp, portnum) && !(rcv_regs->qcnt)) {
274 CLEAR_RCV_INT_PENDING(msp, portnum);
275 //dev_interrupt_in(FALSE, device, 0);
276 pciMaster_set_int(0,false);
277 }
278
279 return c;
280}
281
282void
283Serial::wr_port(int portnum, uint8_t c)
284{
285 channel_regs *xmit_regs = &(msp->scc.port[portnum]);
286
287
288 xmit_regs->rr[0] &= ~TX_READY;
289 xmit_regs->rr[1] &= ~ALL_SENT;
290 xmit_regs->wr[8] = c;
291
292 /*
293 * Note! the transmit & subsequent status posting operation
294 * may need to be delayed an indeterminate number of cycles
295 * for kernel/zs driver purposes.
296 * ...leaving it as a synchronous function call for now.
297 */
298 transmit(portnum);
299}
300
301uint8_t
302Serial::rd_control(int portnum)
303{
304 AB_Regs_t *sccp = &msp->scc;
305 short read_reg;
306
307 /*--------------------------------------------------------
308 * Register Addressing
309 *
310 * WR0(D5-D3) WR0 RR
311 * (Point High) D2 D1 D0
312 * NOT 001 0 0 0 0
313 * " 0 0 1 1
314 * " 0 1 0 2
315 * " 0 1 1 3
316 * " 1 0 0 0
317 * " 1 0 1 1
318 * " 1 1 0 2
319 * " 1 1 1 3
320 * 001 0 0 0 data (not implemented in this func)
321 * 001 0 0 1 -
322 * 001 0 1 0 10
323 * 001 0 1 1 15
324 * 001 1 0 0 12
325 * 001 1 0 1 13
326 * 001 1 1 0 10
327 * 001 1 1 1 15
328 *------------------------------------------------------
329 */
330
331 /* Read WR0 (D2-D0) */
332 read_reg = (sccp->port[portnum].wr[0] & REG_NUMBER);
333
334 if ((sccp->port[portnum].wr[0] & WR0_BITS3_5) != POINT_HIGH) {
335 read_reg &= REGS_0_3;
336 } else {
337
338 if (read_reg & REG_2)
339 read_reg = 10;
340 else if (read_reg & REG_3)
341 read_reg = 15;
342 else if (read_reg == 1) {
343 debug_err("%s: rd_control: POINT_HIGH and WR0 D2-D0 is 1.\nRequest ignored.\n", HERE);
344 return (0);
345 } else {
346 read_reg += 8;
347 }
348 }
349
350 /*
351 * If just read a non-zero register, clear D2-D0 so it points to WR0
352 * or RR0 again
353 */
354 if (read_reg != 0)
355 sccp->port[portnum].wr[0] &= WR0_BITS0_4;
356
357 return (sccp->port[portnum].rr[read_reg]);
358}
359
360
361void
362Serial::wr_control(int portnum, unsigned char buf)
363{
364 AB_Regs_t *sccp = &msp->scc;
365 short write_reg;
366
367 /*--------------------------------------------------------
368 * Register Addressing
369 *
370 * WR0(D5-D3) WR0 WR
371 * (Point High) D2 D1 D0
372 * NOT 001 0 0 0 0 (comand register)
373 * " 0 0 1 1
374 * " 0 1 0 2
375 * " 0 1 1 3
376 * " 1 0 0 4
377 * " 1 0 1 5
378 * " 1 1 0 6
379 * " 1 1 1 7
380 * 001 0 0 0 data (DATA request - not in this func)
381 * 001 0 0 1 9
382 * 001 0 1 0 10
383 * 001 0 1 1 11
384 * 001 1 0 0 12
385 * 001 1 0 1 13
386 * 001 1 1 0 14
387 * 001 1 1 1 15
388 *------------------------------------------------------
389 */
390
391 /* Read WR0 D2-D0 */
392 write_reg = (sccp->port[portnum].wr[0] & REG_NUMBER);
393
394 if ((sccp->port[portnum].wr[0] & WR0_BITS3_5) == POINT_HIGH) {
395 if (write_reg == 0) {
396 /* should never get here */
397 debug_err("%s: wr_control: POINT_HIGH and WR0 D2-D0 is 0. Request Ignored.\n", HERE);
398 return;
399 }
400 write_reg += 8;
401 }
402
403
404 sccp->port[portnum].wr[write_reg] = buf;
405
406 /*
407 * WR0 - If a channel command is being requested,
408 * perform necessary house cleaning
409 */
410 if (sccp->port[portnum].wr[0] & WR0_BITS4_5)
411 channel_cmd(portnum);
412
413 /*
414 * WR2 and WR9 are shared by the two channels.
415 */
416 if (write_reg == 2 || write_reg == 9) {
417 int otherport;
418
419 if (portnum == PORT_A) {
420 otherport = PORT_B;
421 } else if (portnum == PORT_B) {
422 otherport = PORT_A;
423 }
424 sccp->port[otherport].wr[write_reg] = buf;
425 }
426
427 /* WR5 transmit parameter & control */
428 if (write_reg == 5) {
429 /* if DTR than set CD */
430 if (buf & DTR)
431 sccp->port[portnum].rr[0] |= DCD;
432
433 /* if RTS than set CTS */
434 if (buf & RTS)
435 sccp->port[portnum].rr[0] |= CTS;
436
437 /* for status update purposes ... */
438 if (buf & (DTR | RTS))
439 status(portnum);
440 }
441
442 /* RR2,RR12,RR13,RR15 reflect the values in the write registers */
443 if ((write_reg == 2) || (write_reg == 12) || (write_reg == 13) ||
444 (write_reg == 15))
445 sccp->port[portnum].rr[write_reg] = buf;
446
447 /*
448 * If just written a non-zero register, clear D2-D0 so it points to
449 * WR0 or RR0 again
450 */
451 if (write_reg != 0)
452 sccp->port[portnum].wr[0] &= WR0_BITS0_4;
453}
454
455
456void
457Serial::reset_scc()
458{
459 short port, i;
460
461 for (port = 0; port < NUM_PORTS; port++) {
462 /* Clear out all registers for port. */
463 msp->scc.port[port].qcnt = 0;
464 msp->scc.port[port].q.next = NULL;
465 for (i = 0; i < SERIAL_REGS; i++) {
466 msp->scc.port[port].wr[i] = 0;
467 msp->scc.port[port].rr[i] = 0;
468 }
469
470 /* set "ready to transmit" */
471 msp->scc.port[port].rr[0] = TX_READY;
472
473 /* set "all sent" */
474 msp->scc.port[port].rr[1] = ALL_SENT;
475
476 /*
477 * set to the "special receive condition" whose need
478 * was determined by the kernel zs bringup efforts.
479 */
480 msp->scc.port[port].rr[2] = SRC;
481
482
483 mutex_init(&(msp->scc.port[port].serial_lock), USYNC_THREAD,
484 (void *) NULL);
485
486 }
487
488 /*
489 * Set interrrupts enabled for port A if there is an interrupt
490 * interface, otherwise leave them disabled.
491 */
492 /*
493 * The state of WR1 after reset is all interrrupts disabled.
494 * The state of WR1 after reset is bitwise: <00x00x00>
495 * see pg 7-4; in the AMD Z85C30/SCC tech manual
496 *
497 * if (msp->intr_intf) {
498 * SET_INTERRUPTS_ENABLE(msp, PORT_A);
499 * SET_RCV_INT_ENABLE(msp, PORT_A);
500 * }
501 */
502}
503
504void
505Serial::transmit(int portnum)
506{
507 channel_regs *xmit_regs = &(msp->scc.port[portnum]);
508
509 /* transmit the data character */
510
511 term_write(&xmit_regs->wr[8],portHandle[portnum]);
512 //(msp == console_msp) ? portnum:portnum+2);
513
514 xmit_regs->rr[0] |= TX_READY;
515 xmit_regs->rr[1] |= ALL_SENT;
516
517 if (TX_INT_ENABLED(msp, portnum)) {
518 channel_regs *channelA = &(msp->scc.port[PORT_A]);
519 channel_regs *channelB = &(msp->scc.port[PORT_B]);
520
521 /*
522 * if generating interrupts in Vector Include Status mode,
523 * the interrupt vector on channelB includes status in the
524 * lower nibble which is characteristic of the event
525 * causing the interrupt.
526 */
527 if (xmit_regs->wr[9] & VIS) {
528 /*
529 * if no interrupts are pending, clear out
530 * vector include status bits before or'ing in new state
531 * (channelA.rr3) is the interrupt pending register
532 * (channelB.rr2) is the interrupt vector (VIS) register
533 */
534 if (!channelA->rr[3])
535 /* clearing idle "special rcv condition" bits */
536 channelB->rr[2] &= ~VIS_LO_MASK;
537
538 /* add "Tx ready" to status vector */
539 SET_VIS_TX_BUF_EMPTY(msp, portnum);
540 }
541
542 /* assert serial interrupt */
543 SET_TX_INT_PENDING(msp, portnum);
544 //dev_interrupt_in(TRUE, device, 0);
545 pciMaster_set_int(0,true);
546 }
547}
548
549/*
550 * Channel Command Register (WR0)
551 * - executes various channel/port commands
552 */
553void
554Serial::channel_cmd(int portnum)
555{
556 channel_regs *channelp = &(msp->scc.port[portnum]);
557 channel_regs *channelA = &(msp->scc.port[PORT_A]);
558 channel_regs *channelB = &(msp->scc.port[PORT_B]);
559 int otherport;
560
561 if (portnum == PORT_A) {
562 otherport = PORT_B;
563 } else if (portnum == PORT_B) {
564 otherport = PORT_A;
565 }
566
567 /*
568 * individual reset functions used by
569 * kernel zs drvier:
570 * reset external/status interrupts (0x10)
571 * reset TxINT pending (0x28)
572 * error reset (0x30)
573 * reset highest Interrupt Under Service (0x38)
574 */
575 switch (channelp->wr[0] & CMDCODE_MASK) {
576 case ENABLE_RX_INT:
577 /*
578 * enable int on next Rx, used for 1st receive interrupt
579 * ignore for now !
580 */
581 break;
582
583 case RESET_XS_INT:
584 /*
585 * reset external/status interrupts (0x10)
586 * (channelB RR2) is the interrupt vector (VIS) register
587 * (channelA RR3) is the interrupt pending register
588 */
589
590 /* reset ext/status interrrupt */
591 CLEAR_XS_INT_PENDING(msp, portnum);
592
593 /*
594 * if no XS interrupts pending for other channel,
595 * clear Ext/Status Vector Include Status bit
596 */
597 if (!XS_INT_PENDING(msp, otherport))
598 CLEAR_VIS_XS_CHANGE(msp);
599 break;
600
601 case RESET_TX_INT:
602 /*
603 * Reset TxINT Pending (0x28)
604 * (channelB RR2) is the interrupt vector (VIS) register
605 * (channelA RR3) is the interrupt pending register
606 */
607
608 /* reset transmit interrrupt */
609 CLEAR_TX_INT_PENDING(msp, portnum);
610 break;
611
612 case RESET_ERROR:
613 /*
614 * error reset (0x30)
615 */
616 channelB->rr[2] = 0;
617 channelA->rr[3] = 0;
618 break;
619
620 case RESET_IUS:
621 /*
622 * Reset Highest Interrupt Under Service command (0x38),
623 * clear respective bits in interrupt vector (RR2),
624 * and the interrupt pending register (RR3).
625 * Note, only channelB contains VIS bits, and
626 * only channelA contains the IP bits.
627 */
628
629 /* clear the highest pending interrupt */
630 if (RCV_INT_PENDING(msp, portnum)) {
631 CLEAR_RCV_INT_PENDING(msp, portnum);
632
633 /*
634 * if no Rx interrupts pending for other channel,
635 * clear Rx Vector Include Status bit
636 */
637 if (!RCV_INT_PENDING(msp, otherport))
638 CLEAR_VIS_RX_CHAR_AVAIL(msp);
639
640 } else if (TX_INT_PENDING(msp, portnum)) {
641 CLEAR_TX_INT_PENDING(msp, portnum);
642
643 /*
644 * no VIS bits to clear for Tx interrupts
645 */
646
647 } else if (XS_INT_PENDING(msp, portnum)) {
648 CLEAR_XS_INT_PENDING(msp, portnum);
649
650 /*
651 * if no XS interrupts pending for other channel,
652 * clear Ext/Status Vector Include Status bit
653 */
654 if (!XS_INT_PENDING(msp, otherport))
655 CLEAR_VIS_XS_CHANGE(msp);
656 }
657 break;
658
659 default:
660 debug_err("%s: blaze warning: unsupported SCC/wr[0] command 0x%x\n", HERE,
661 channelp->wr[0]);
662 }
663
664 /*
665 * if no more interrupts pending for channelA,
666 * clear the Vector Include Status channel bit
667 */
668 if (!(channelA->rr[3] & A_IP_MASK))
669 channelB->rr[2] &= ~CHAN_A;
670
671 /*
672 * if no interrupts are pending in RR3, de-assert the serial interrupt.
673 * if WR9 (master interrupt contorl) is in VIS mode,
674 * force the VIS bits to be: V3,V2,V1 = 011 "special receive condition"
675 * (...we currently *ONLY* support status low bits)
676 *
677 * (channelB RR2) is the interrupt vector (VIS) register
678 * (channelA RR3) is the interrupt pending register
679 */
680 if (channelA->rr[3] == 0) {
681 if (channelp->wr[9] & VIS)
682 channelB->rr[2] = SRC; /* special receive condition */
683 /* Deasserting the interrupt */
684 //dev_interrupt_in(FALSE,device, 0);
685 pciMaster_set_int(0,false);
686 }
687
688 /*
689 * After a reset request has been performed,
690 * clear the WR0 (command register)
691 * (including special resets, point high, and register indexes, ...)
692 */
693 channelp->wr[0] = 0;
694}
695
696/*
697 * Get the serial status
698 */
699void
700Serial::status(int portnum)
701{
702 channel_regs *channelp = &(msp->scc.port[portnum]);
703
704 /* if External/Status Master Interrupt Enable'd */
705 if (channelp->wr[1] & XS_INT_ENABLED) {
706 channel_regs *channelA = &(msp->scc.port[PORT_A]);
707 channel_regs *channelB = &(msp->scc.port[PORT_B]);
708
709 /*
710 * if we're generating interrupts in Vector Include Status
711 * mode, the interrupt vector on channelB includes status
712 * in the lower nibble which is characteristic of the
713 * event causing the interrupt.
714 */
715 if (channelp->wr[9] & VIS) {
716 /*
717 * if no interrupts are pending, clear out vector
718 * include status bits before or'ing in new state
719 * (channelA.rr3) is the interrupt pending register
720 * (channelB.rr2) is the interrupt vector (VIS) register
721 */
722 if (!channelA->rr[3])
723 /* clearing idle "special rcv condition" bits */
724 channelB->rr[2] &= ~VIS_LO_MASK;
725
726 /* add "external/status change" to status vector */
727 SET_VIS_XS_CHANGE(msp, portnum);
728 }
729
730 /* assert "external/status change" in rr3 */
731 SET_XS_INT_PENDING(msp, portnum);
732
733 /* assert serial interrupt */
734 //dev_interrupt_in(TRUE, device, 0);
735 pciMaster_set_int(0,true);
736 }
737}
738
739//
740// Insert the following string into the incomming stream for PORTA, the
741// console.
742//
743void
744Serial::chars_send(char *str, int portHandle)
745{
746 int len = (int)strlen(str);
747 int i;
748 int portnum = mapHandle2Port(portHandle);
749
750 for (i = 0; i < len; i++) {
751 /* Jam them one at a time into the input buffer */
752 char_input(str[i], portnum);
753 }
754
755}
756
757bool
758Serial::dump(FILE* fp)
759{
760 int portnum;
761 struct channel_regs *rcv_regs;
762 debug_err("%s: dump\n", HERE);
763 if (fwrite((char*)msp, sizeof(serial_structT), 1, fp) != 1) {
764 debug_err("%s: serial_dump: fwrite failed\n", HERE);
765 return FALSE;
766 }
767
768 /* Dump queue of chars waiting on each port. */
769
770 for (portnum = 0 ; portnum < NUM_PORTS ; portnum++) {
771 rcv_regs = &(msp->scc.port[portnum]);
772 while (rcv_regs->qcnt) {
773 putc(deq(rcv_regs), fp);
774 }
775 }
776 return genericPciDev::dump(DR_get_dir(),getName());
777}
778
779bool
780Serial::restore(FILE* fp)
781{
782
783 int portnum;
784 struct channel_regs *rcv_regs;
785 int count;
786
787
788 if (fread((char*)msp, sizeof(serial_structT), 1, fp) != 1) {
789 debug_err("%s: serial_restore: fread failed\n", HERE);
790 return FALSE;
791 }
792
793 /* Restore queue of chars waiting on each port. */
794 for (portnum = 0 ; portnum < NUM_PORTS ; portnum++) {
795 rcv_regs = &(msp->scc.port[portnum]);
796 /*
797 * # chars to load is in qcnt of state. Load them in but
798 * first set queue to empty state since the characters
799 * really aren't there yet.
800 */
801 count = rcv_regs->qcnt; /* save count */
802 rcv_regs->qcnt = 0;
803 rcv_regs->q.next = NULL;
804
805 while (count--) {
806 enq(rcv_regs, getc(fp));
807 }
808 }
809
810 if (dump_version() >= 5)
811 return genericPciDev::restore(DR_get_dir(),getName());
812 else {
813// slot_irl[0] = 54;
814 return TRUE;
815 }
816}