Ejemplo n.º 1
0
struct intrinfo_entry *
add_interrupt(const struct startup_intrinfo *startup_intr) {
	struct intrinfo_entry	*intr;
	unsigned				i;

	if(intr_prev_output_rtn == NULL) {
		//Hook into the sizing/writing list
		intr_prev_output_rtn = callout_output_rtn;
		callout_output_rtn = (output_callout_t *)callout_output_intr;
	}

	intr = grow_syspage_section(&lsp.intrinfo, sizeof(*intr));
	//Point at newly allocated entry
	intr = (void *)((uint8_t *)intr + lsp.intrinfo.size - sizeof(*intr));
	*intr = *(struct intrinfo_entry *)startup_intr;
	if(startup_intr->id.rtn != NULL) {
		intr->id.size = startup_intr->id.rtn->rtn_size;
	}
	if(startup_intr->eoi.rtn != NULL) {
		intr->eoi.size = startup_intr->eoi.rtn->rtn_size;
	}
	
	for(i = 0; i < NUM_ELTS(offsets); ++i) {
		void	(**rtn)(void) = (void (**)(void))((uintptr_t)intr + offsets[i]);
		
		callout_register_data(rtn, startup_intr->patch_data);
	}
	return(intr);
}
Ejemplo n.º 2
0
char *InitSys( void )
{
        static char name[] = "\\\\.\\DBGPORT1";
        int         i;

        if( !(GetVersion() & 0x80000000) ) {
                PortHdl = CreateFile( name,
                                        GENERIC_READ | GENERIC_WRITE,
                                        FILE_SHARE_READ,
                                        NULL,
                                        OPEN_EXISTING,
                                        0,
                                        NULL
                                        );
                if ( PortHdl == INVALID_HANDLE_VALUE )
                        return( TRP_ERR_cannot_access_parallel_ports );
        }
        PortsFound = 0;
        for( i = 0; i < NUM_ELTS( PortTest ); ++i ) {
                if( CheckForPort( i, 0x55 ) && CheckForPort( i, 0xaa ) ) {
                        PortAddress[ PortsFound++ ] = PortTest[ i ];
                }
        }
        return( NULL );
}
Ejemplo n.º 3
0
mad_status RegInit()
{
    unsigned    i;
    unsigned    max;
    unsigned    curr;
    unsigned    half_idx = 0;
    mad_status  ms;

    max = 0;
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_DWORD:
            curr = TYPEIDX( RegList[i].info.bit_start, unsigned_64 );
            if( curr > max )
                max = curr;
            RegListHalf[half_idx] = RegList[i];
#if defined( __BIG_ENDIAN__ )
            // kludge for 64-bit registers displayed as 32-bit - need to
            // skip 32 bits!
            RegListHalf[half_idx].info.bit_start += 32;
#endif
            RegListHalf[half_idx].info.bit_size = 32;
            ++half_idx;
            break;
        }
    }
    RegSubList = MCAlloc( ( max + 1 ) * sizeof( *RegSubList ) );
    if( RegSubList == NULL )
        return( MS_ERR | MS_NO_MEM );
    memset( RegSubList, 0, ( max + 1 ) * sizeof( *RegSubList ) );
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_DWORD:
            ms = AddSubList( i, IntRegSubData, NUM_ELTS( IntRegSubData ) );
            if( ms != MS_OK )
                return( ms );
            break;
        }
    }
    return( MS_OK );
}
Ejemplo n.º 4
0
void
config_cpu(unsigned pvr, const struct exc_copy_block **entry, const struct exc_copy_block **exitlocal) {

	// The 970 doesn't support the "tlbia" instruction, which is what
	// tlb_flush_all defaults to using. However, the tlb_flush_all_64 
	// routine doesn't flush enough entries. We can get away without defining
	// a proper routine however because the only thing this is used for is
	// handling IPI_TLB_FLUSH and that is only needed if PPC_CPU_SW_TLBSYNC
	// is on, which it won't be for any 900 series processor.
//	tlb_flush_all = tlb_flush_all_64;
	CRASHCHECK(__cpu_flags & PPC_CPU_SW_TLBSYNC);

	trap_install_set(ppc_traps, NUM_ELTS(ppc_traps));

	/*
	 * Install the Altivec exception handler if this CPU supports it.
	 */
	if(__cpu_flags & PPC_CPU_ALTIVEC) {
		trap_install_set(ppc_traps_altivec, NUM_ELTS(ppc_traps_altivec));
		alt_souls.size = sizeof(PPC_VMX_REGISTERS);
	}

	if(fpuemul) {
		// Emulation
		trap_install(PPC_EXC_FPU_UNAVAILABLE, __exc_fpu_emulation, &__common_exc_entry);
	} else {
		// Real floating point
		trap_install(PPC_EXC_FPU_UNAVAILABLE, __exc_fpu_unavail, &__exc_ffpu);
	}

	if(__cpu_flags & PPC_CPU_EAR) {
		*entry++ = &ctx_save_ear;
		*exitlocal++ = &ctx_restore_ear;
	}
	if(__cpu_flags & PPC_CPU_ALTIVEC) {
		*entry++ = &ctx_save_vmx;
	}
	*entry = NULL;
	*exitlocal = NULL;
}
Ejemplo n.º 5
0
static return_val initHashTables( void )
{
    int         loop;
    return_val  error;

    error = createHashTables();
    if( error == OKAY ) {
        for( loop = 0; loop < NUM_ELTS( RecognizedName ); loop++ ) {
            HashTableInsert( NameRecognitionTable, (hash_value) RecognizedName[loop].name, RecognizedName[loop].type );
        }
    }
    return( error );
}
Ejemplo n.º 6
0
mad_status RegInit( void )
{
    unsigned    i;
    unsigned    max;
    unsigned    curr;
    mad_status  ms;

    max = 0;
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_INT:
        case RS_FLT:
            curr = TYPEIDX( RegList[i].info.bit_start, axpreg );
            if( curr > max )
                max = curr;
            break;
        }
    }
    RegSubList = MCAlloc( ( max + 1 ) * sizeof( *RegSubList ) );
    if( RegSubList == NULL )
        return( MS_ERR | MS_NO_MEM );
    memset( RegSubList, 0, ( max + 1 ) * sizeof( *RegSubList ) );
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_INT:
            ms = AddSubList( i, IntRegSubData, NUM_ELTS( IntRegSubData ) );
            if( ms != MS_OK )
                return( ms );
            break;
        case RS_FLT:
            ms = AddSubList( i, FltRegSubData, NUM_ELTS( FltRegSubData ) );
            if( ms != MS_OK )
                return( ms );
            break;
        }
    }
    return( MS_OK );
}
Ejemplo n.º 7
0
static return_val initHashTables( void )
{
    int             i;
    return_val      error;
    hash_entry_data key_entry;

    error = createHashTables();
    if( error == RC_OKAY ) {
        for( i = 0; i < NUM_ELTS( RecognizedName ); i++ ) {
            key_entry.key.u.string = RecognizedName[i].name;
            key_entry.data.u.sec_type = RecognizedName[i].type;
            HashTableInsert( NameRecognitionTable, &key_entry );
        }
    }
    return( error );
}
Ejemplo n.º 8
0
char *InitSys()
{
    int i;

    PortsFound = 0;
    for( i = 0; i < NUM_ELTS( PortTest ); ++i ) {
        if (!AccessPorts(PortTest[i], PortTest[i])) {
            printf("Failed to get I/O permissions. This program must run as root!\n");
            exit(-1);
            }
        if( CheckForPort( i, 0x55 ) && CheckForPort( i, 0xaa ) ) {
            PortAddress[ PortsFound++ ] = PortTest[ i ];
        }
        FreePorts(PortTest[i], PortTest[i]);
    }
    return( NULL );
}
Ejemplo n.º 9
0
void
set_debug(unsigned channel, const struct debug_device *dev, const char *options) {
	unsigned	base;
	unsigned	i;

	dev->init(channel, options, dev->defaults[channel]);
	if(channel == 0) set_print_char(dev->put);
	base = offsetof(struct callout_entry, debug);
	base += channel * sizeof(struct debug_callout);
	for(i = 0; i < NUM_ELTS(dev->callouts); ++i) {
		const struct callout_rtn	*rtn = dev->callouts[i];

		if(rtn != NULL) {
			add_callout(base + i*sizeof(callout_fp_t), rtn);
		}
	}
}
Ejemplo n.º 10
0
static output_callout_t *
callout_output_intr(int sizing) {
	unsigned	i;
	unsigned	nelts;

	nelts = lsp.intrinfo.size / sizeof(*lsp.intrinfo.p);
	for(i = 0; i < nelts; ++i) {
		uint8_t		*base = (uint8_t *)&lsp.intrinfo.p[i];
		unsigned	j;
		
		for(j = 0; j < NUM_ELTS(offsets); ++j) {
			void	(**rtn)(void) = (void (**)(void))(base + offsets[j]);
			
			callout_output_one(sizing, rtn);
		}
	}
	return(intr_prev_output_rtn);
}
Ejemplo n.º 11
0
void RegFini()
{
    unsigned    i;
    unsigned    max;
    unsigned    curr;

    max = 0;
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_DWORD:
            curr = RegList[i].info.bit_start / (sizeof(unsigned_64)*BITS_PER_BYTE);
            if( curr > max ) max = curr;
            break;
        }
    }
    for( i = 0; i <= max; ++i ) MCFree( RegSubList[i] );
    MCFree( RegSubList );
    RegSubList = NULL;
}
Ejemplo n.º 12
0
char *InitSys()
{
    SEL         global;
    SEL         local;
    int         i;

    DosGetInfoSeg( &global, &local );
    GInfoSeg = MK_FP( global, 0 );

    PortsFound = 0;
    for( i = 0; i < NUM_ELTS( PortTest ); ++i ) {
        AccessPorts( PortTest[i], PortTest[i] );
        if( CheckForPort( i, 0x55 ) && CheckForPort( i, 0xaa ) ) {
            PortAddress[ PortsFound++ ] = PortTest[ i ];
        }
        FreePorts( PortTest[i], PortTest[i] );
    }
    return( 0 );
}
Ejemplo n.º 13
0
void RegFini( void )
{
    unsigned    i;
    unsigned    max;
    unsigned    curr;

    max = 0;
    for( i = 0; i < NUM_ELTS( RegList ); ++i ) {
        switch( RegList[i].sublist_code ) {
        case RS_INT:
        case RS_FLT:
            curr = TYPEIDX( RegList[i].info.bit_start, axpreg );
            if( curr > max )
                max = curr;
            break;
        }
    }
    for( i = 0; i <= max; ++i )
        MCFree( RegSubList[i] );
    MCFree( RegSubList );
    RegSubList = NULL;
}
Ejemplo n.º 14
0
/*
 * We've run out of intrevent structures. This means that some process
 * has messed up its ISR. We'll find the errant process and kill it
 * without mercy.
 *
 * This code is actually bogus, since it doesn't really solve the
 * problem - the messed up ISR may not be adding any events to the
 * intrevent_pending queue, so it won't be found by scanning the
 * list. We'd need to keep track of active interrupts and find the
 * deepest nesting one that keeps on asserting when we re-enable interrupts
 * in the kernel interrupt exit processing, but I can't see any way
 * of doing that without slowing down the normal interrupt handling code,
 * which we don't want to do. It's also got race conditions - think
 * about what happens if another nested interrupt goes off while in
 * here and the code is re-entrantly started. Things to think about...
 *
 * Beginings of an idea.
 *  In intrevent_add(), when get down to a critical number of
 *  free INTREVENT's (~20), turn on a flag. In the interrupt()
 *  processing loop, if that flag is on, mask any interrupt that
 *  occurs and set a flag on the INTERRUPT structure saying that
 *  it's been masked. Eventually the problem interrupt will be masked
 *  and forward progress will be made. Once we get into intrevent_drain(),
 *  and have drained all the pending events, check the global flag. If
 *  it's on, scan the INTERRUPT structures looking for ones that have
 *  been masked by the interrupt() loop. For each, clear a state flag,
 *  unmask the level and then set the state flag. In the interrupt() loop,
 *  more code counts the number of times it gets entered. If we get above
 *  a predetermined number (~100) without seeing the state flag gets set,
 *  we assume that this is the permanently asserted interrupt and
 *  remask it. All the processes with ISR's attached to that interrupt
 *  need to be killed. Where this has problems is with SMP, since the
 *  interrupt() loop may be handled by a different CPU than the one
 *  that's doing intrevent_drain().

 */
static int
intrevent_error(THREAD *thp, INTERRUPT *isr) {
	INTREVENT	*curr_intr;
	INTREVENT	**owner;
	PROCESS		*curr_proc;
	PROCESS		*high_intrs_proc;
	pid_t		curr_pid;
	int			high_intrs_count;
	INTRLEVEL	*intr_level;
	unsigned	intr_vector;
	INTREVENT	*killer;

	/*
	 * First, run thru the pending interrupt list and 'mark' each process
	 * with the number of pending events.
	 */
	INTR_LOCK(&intrevent_lock);
	for(curr_intr = intrevent_pending; curr_intr != NULL; curr_intr = curr_intr->next) {
		curr_intr->thread->process->pending_interrupts++;
	}
	INTR_UNLOCK(&intrevent_lock);

	/*
	 * Walk the process table and find the process with the most pending
	 * interrupts. Zero the list behind us (so we don't have to do another
	 * pass later).
	 */
	high_intrs_proc = NULL;
	high_intrs_count = 0;
	for(curr_pid = 2; curr_pid < process_vector.nentries; ++curr_pid) {
		if(VECP(curr_proc, &process_vector, curr_pid)) {
			if(curr_proc->pending_interrupts > high_intrs_count) {
				high_intrs_count = curr_proc->pending_interrupts;
				high_intrs_proc = curr_proc;
			}
			curr_proc->pending_interrupts = 0;
		}
	}

	intr_level = &interrupt_level[isr->level];
	intr_vector = intr_level->info->vector_base + isr->level - intr_level->level_base;
#define MIN_INTRS_BAD 10
	if(high_intrs_count < MIN_INTRS_BAD) {
		/* There wasn't enough pending interrupts on any particular process to justify
		 * canceling them.
		 */
		char	*name = thp->process->debug_name;

		if(name == NULL) name = "";
		kprintf("Out of interrupt events! (vector=%u process=%u [%s])\n",
				intr_vector, thp->process->pid, name);

		if(ker_verbose >= 2) {
		/* debug assist information when of out interrupt events occurs */
			unsigned  i;
			INTREVENT * irplocal = intrevent_pending;
#if defined(__GNUC__)
/* this enum order safe init is not supported by the WATCOM compiler */
	#define ARRAY_EL(e)	[(e)] =
#else
	#define ARRAY_EL(e)
#endif
			static const char * const fmt[] =
			{
				ARRAY_EL(SIGEV_NONE) "t-%02u:  SIGEV_NONE(%u) -> %u (%s)  (--/--/--/--)\n",
				ARRAY_EL(SIGEV_SIGNAL) "t-%02u:  SIGEV_SIGNAL(%u) -> %u (%s)  (0x%x/0x%x/--/--)\n",
				ARRAY_EL(SIGEV_SIGNAL_CODE) "t-%02u:  SIGEV_SIGNAL_CODE(%u) -> %u (%s)  (0x%x/0x%x/0x%x/--)\n",
				ARRAY_EL(SIGEV_SIGNAL_THREAD) "t-%02u:  SIGEV_SIGNAL_THREAD(%u) -> %u (%s)  (0x%x/0x%x/0x%x/--)\n",
				ARRAY_EL(SIGEV_PULSE) "t-%02u:  SIGEV_PULSE(%u) -> %u (%s)  (0x%x/0x%x/0x%x/0x%x)\n",
				ARRAY_EL(SIGEV_UNBLOCK) "t-%02u:  SIGEV_UNBLOCK(%u) -> %u (%s)  (--/--/--/--)\n",
				ARRAY_EL(SIGEV_INTR) "t-%02u:  SIGEV_INTR(%u) -> %u (%s)  (--/--/--/--)\n",
				ARRAY_EL(SIGEV_THREAD) "t-%02u:  SIGEV_THREAD(%u) -> %u (%s)  (--/--/--/--)\n",
			};
			kprintf("Last %u:   event  ->   pid  (signo/val/code/pri)\n", 2 * MIN_INTRS_BAD);
			for (i=0; i<(2 * MIN_INTRS_BAD); i++, irplocal=irplocal->next)
				kprintf(fmt[SIGEV_GET_TYPE(&irplocal->event) % NUM_ELTS(fmt)],
							i+1, SIGEV_GET_TYPE(&irplocal->event),
							(irplocal->thread && irplocal->thread->process) ? irplocal->thread->process->pid : 0,
							(irplocal->thread && irplocal->thread->process) ? irplocal->thread->process->debug_name : "?",
							irplocal->event.sigev_signo, irplocal->event.sigev_value.sival_int,
							irplocal->event.sigev_code, irplocal->event.sigev_priority);
		}
		return 0;
	}


	/*
	 * Cancel all interrupts pending for that process.
	 */
	killer = NULL;
	INTR_LOCK(&intrevent_lock);
	owner = &intrevent_pending;
	for( ;; ) {
		curr_intr = *owner;
		if(curr_intr == NULL) break;
		if(curr_intr->thread->process == high_intrs_proc) {
			*owner = curr_intr->next;
			if(intrevent_tail == &curr_intr->next) {
				intrevent_tail = owner;
			}
			if(killer == NULL) {
				killer = curr_intr;
			} else {
				curr_intr->next = intrevent_free;
				intrevent_free = curr_intr;
				++num_pev_free;
			}
		} else {
			owner = &curr_intr->next;
		}
	}

	if((killer == NULL) || (high_intrs_proc == NULL)) crash();
	killer->thread = high_intrs_proc->valid_thp;
	// Use a uniqe code that people can recognize
	SIGEV_SIGNAL_CODE_INIT(&killer->event, SIGKILL, 1, SI_IRQ);
	killer->next = intrevent_pending;
	intrevent_pending = killer;

	INTR_UNLOCK(&intrevent_lock);

	if(high_intrs_proc == thp->process) {
		if(intr_vector != SYSPAGE_ENTRY(qtime)->intr) {
			// The current interrupt came from the failed process. Mask it.
			//NYI: There should be a tracevent for this....
			(void) interrupt_mask(isr->level, isr);
		}
	}

	// Tell intrevent_add() to try again, we've freed stuff up.
	return 1;
}
Ejemplo n.º 15
0
                                         unsigned short );

extern unsigned short pascal far DosPortAccess( unsigned short reserverd,
                                                unsigned short req_release,
                                                unsigned short first_port,
                                                unsigned short last_port );

#define NUM_ELTS( a )   (sizeof( a ) / sizeof( a[0] ))

GINFOSEG                                far *GInfoSeg;

unsigned short PortTest[] = {
        0x378, 0x3bc, 0x278
};

unsigned short PortAddress[NUM_ELTS( PortTest )] = {
        0,0,0
};

unsigned PortsFound;

int NumPrinters()
{
    char                num_printers;
    unsigned short      rc;

    rc = DosDevConfig( &num_printers, 0, 0 );
    if( rc != 0 ) return( 0 );
    if( num_printers > PortsFound ) num_printers = PortsFound;
    return( num_printers );
}
Ejemplo n.º 16
0
void
config_cpu(unsigned pvr, const struct exc_copy_block **entry, const struct exc_copy_block **exitlocal) {
    set_spr( PPCBKE_SPR_DBCR0, 0 );
#ifdef VARIANT_booke
    SYSPAGE_CPU_ENTRY(ppc,kerinfo)->init_msr |= PPC_MSR_DE;
#endif

    switch(PPC_GET_FAM_MEMBER(pvr)) {
    case PPC_440GP:
        ppcbke_tlb_select = PPCBKE_TLB_SELECT_IBM;
        trap_install_set(traps_440gp, NUM_ELTS(traps_440gp));
        fix_pgsizes();
        break;
    case PPC_440GX:
        ppcbke_tlb_select = PPCBKE_TLB_SELECT_IBM;
        trap_install_set(traps_440gx, NUM_ELTS(traps_440gx));
        fix_pgsizes();
        break;
    case PPC_E500V2:
        ppcbke_tlb_select = PPCBKE_TLB_SELECT_E500v2;
        trap_install_set(traps_e500, NUM_ELTS(traps_e500));
        alt_souls.size = sizeof(PPC_SPE_REGISTERS);
        *entry++ = &ctx_save_e500_extra;
        *exitlocal++ = &ctx_restore_e500_extra;
        break;
    case PPC_E500:
        ppcbke_tlb_select = PPCBKE_TLB_SELECT_E500;
        trap_install_set(traps_e500, NUM_ELTS(traps_e500));
        alt_souls.size = sizeof(PPC_SPE_REGISTERS);
        *entry++ = &ctx_save_e500_extra;
        *exitlocal++ = &ctx_restore_e500_extra;
        break;
    default:
        kprintf("Unsupported PVR value: %x\n", pvr);
        crash();
        break;
    }

    trap_install_set(traps_booke, NUM_ELTS(traps_booke));

    if(__cpu_flags & CPU_FLAG_FPU) {
        if(fpuemul) {
            // Emulation
            trap_install(PPCBKE_SPR_IVOR7,
                         __exc_fpu_emulation, &__common_exc_entry);
        } else {
            // Real floating point
            trap_install(PPCBKE_SPR_IVOR7,
                         __exc_fpu_unavail, &__exc_ffpu);

        }
    }

    // Make data & instruction TLB misses go to the
    // data and instruction storage exceptions. This will
    // be changed if/when copy_vm_code() gets called and
    // we know we're running in virtual mode.
    set_spr(PPCBKE_SPR_IVOR13, get_spr(PPCBKE_SPR_IVOR2));
    set_spr(PPCBKE_SPR_IVOR14, get_spr(PPCBKE_SPR_IVOR3));

    *entry++ = &ctx_save_usprg0;
    *exitlocal++ = &ctx_restore_usprg0;
    *entry = NULL;
    *exitlocal = NULL;

    ppc_ienable_bits |= PPC_MSR_CE | PPC_MSR_ME;
}
Ejemplo n.º 17
0
int 
main(int argc, char *argv[]) {
	int			opt;
	char		*devicename = NULL;
	int			baud;
	int			nbytes;
	FILE		*imagefp;
	int			devicefd;
	int			n;
	int			r;
	unsigned	i;
	char		*expect = NULL;
	int			timeout = -1;

	// Calculate the endian of the host this program is running on.
	n = 1;
	host_endian = (*(char *)&n != 1);
	// assume target is the same for the moment
	target_endian = host_endian;

	gdb_pc_regnum = -1;
	gdb_pc_regsize = 4;

	baud = -1;
	while ((opt = getopt(argc, argv, "b:d:ei:l:LvqE:p:P:w:")) != -1) {
		switch(opt) {
		case 'E':
			force_error = atoi(optarg);
			break;

		case 'b':
			baud = atoi(optarg);
			break;

		case 'd':
			devicename = optarg;
			outputdevice();
			break;

		case 'i':
			devicename = optarg;
			outputinet();
			break;

		case 'v':
			verbose++;
			break;

		case 'e':
			echo = 1;
			break;

		case 'l':
			laplink = atoi(optarg);
			break;

		case 'L':
			devicename = "loopback";
			outputpipe();
			break;

		case 'q':
			quiet = 1;
			break;

		case 'p':
			i = 0;
			for( ;; ) {
				if(i >= NUM_ELTS(xfers)) {
					fprintf(stderr, "unrecognized protocol '%s'\n", optarg);
					return(EXIT_FAILURE);
				}
				if(strcmp(optarg, xfers[i].name) == 0) break;
				++i;
			}
			xfer = &xfers[i];
			break;

		case 'P':
			{
				char	*p;

				gdb_pc_regnum = strtoul(optarg, &p, 0);
				if(*p == ',') {
					gdb_pc_regsize = strtoul(p + 1, NULL, 0);
				}
			}
			break;

		case 'w':	
			{
				char	*p;
				
				timeout = strtoul(optarg, &p, 0);
				if(timeout == 0) timeout = 10;
				if(*p == ':') ++p;
				if(*p != '\0') expect = p;
			}
			break;

		default:
			fprintf(stderr, "Unknown option.\n");
			break;
		}
	}

	if(devicename == NULL) {
		fprintf(stderr, "You must specify a device name using the -d option.\n");
		exit(EXIT_FAILURE);
	}

	output.init();

	// Open the device to send the image over.
	devicefd = output.open(devicename, baud);
	if(devicefd == -1) {
		fprintf(stderr, "%s : %s\n", optarg, strerror(errno));
		exit(EXIT_FAILURE);
	}

	// If a file open it, otherwise assume piped input from stdin
	if(optind < argc) {
		if((imagefp = fopen(imagename = argv[optind], "rb")) == NULL) {
			fprintf(stderr, "%s : %s\n", argv[optind], strerror(errno));
			exit(EXIT_FAILURE);
		}
	} else {
		imagename = "-stdin-";
		imagefp = stdin;
		MAKE_BINARY_FP(imagefp);
	}

	//Discard any echo'd input
    output.flush(devicefd);

	nbytes = fread(data, 1, sizeof(data), imagefp);
	if(nbytes != sizeof(data)) {
		fprintf(stderr, "Short read for source file header %d\n", nbytes);
		return(EXIT_FAILURE);
	}

	i = 0;
	do {
		r = send_func[i++](imagefp, devicefd, data, nbytes);
	} while(r < 0);

	if(timeout > 0) {
		int		c;
		char	*p;
		time_t	start_time;

		start_time = time(0);
		p = expect;

		for( ;; ) {
			c = output.get(devicefd, 10);
			if(expect != NULL) {
				if(c == *p) {
					++p;
					if(*p == '\0') break;
				} else if(c != -1) {
					// didn't match the expected char - restart the
					// search from the begining
					p = expect;
				}
			}
			if((time(0) - start_time) > timeout) {
				// We've timed out
				if(expect != NULL) {
					// If we were expecting a response string, that's
					// a failure
					fprintf(stderr, "Timed out waiting for '%s'\n", expect);
					r = EXIT_FAILURE;
				}
				break;
			}
		}
	}

	output.close(devicefd);

	return(r);
}
Ejemplo n.º 18
0
/*******************************************************************************
 * ep9301_config_pic
 *
 * This routine will initialize the 2 Vectored Interrupt Controllers in the
 * Cirrus Logic EP93xx family of processors.
 *
 * In order to handle the number of interrupts within the EP93xx, 2 separate
 * interrupt controllers are cascaded together to form 1 larger controller.
 * There is not much documentation on how this cascading of interrupts works as
 * it is not a true cascade. There is some logic which allows the second
 * controller to be daisy chained through the first controller which is actually
 * connected to the processor. There is no documentation on how prioritization
 * works for non vectored interrupts or the prioritization of the second
 * controller relative to the first. The only remote suggestion that they are
 * handled as 32 priority interrupts starting with controller 1 followed by
 * controller 2 is on page 118 of the User Guide which says ...
 *
 * 		"Vector Control Registers. The 32 VICxVectCntl0 through VICxVectCnt15
 * 		 registers select the interrupt source for the vectored interrupt."
 *
 * My interpretation is that vector 0 through 15 on controller 1 followed by
 * vector 0 through 15 on controller 2 is the prioritization.
 *
 * This still leaves the problem that we don't know which controller to look
 * at first without looking at the status register for each ... which implies
 * that the prioritization is completely under software control. In other words,
 * software must decide to either read controller 1 or 2 status first, effectively
 * prioritizing one set of 32 interrupts over the other 32. Then, because some of
 * the interrupts are not vectored, we must choose bits in the status register.
 * However, if the vector address read when none of the interrupts programmed as
 * vectored interrupts is the default vector, then the sequence can flow as
 * follows (I will prioritize controller 1 interrupts over controller 2)
 *
 * 		if (vic1_status != 0)
 * 		{
 * 			if (vic1_vector != default vector)
 * 				id = vect_table[vic1_vector]
 * 			else
 * 				id = first bit set in vic1_status
 * 		}
 * 		else if (vic2_status != 0)
 * 		{
 * 			if (vic1_vector != default vector)
 * 				id = vect_table[vic2_vector]
 * 			else
 * 				id = first bit set in vic2_status
 * 		}
 * 		else
 * 			spurious interrupt
 *
 * 		return id
 *
 * This is all greatly complicated by the fact that only 1/2 of the interrupts
 * in each controller are vectored and prioritized not to mention the
 * prioritization between IRQ and FIQ interrupts.
 * To properly support prioritized interrupts and decouple them from the assigned
 * internal id's is going to require some more thought so for now I am not going
 * to use the hardware prioritization of the vectored interrupts and instead
 * simply do a first bit set prioritization of interrupts as follows
 *
 * 			VIC1, 31 -> 0
 * 			VIC2, 31 -> 0
 *
 * implying that in the case of multiple occurring interrupts, VIC1, interrupt
 * 31 (documented interrupt source 31) is the highest in the system and VIC2,
 * interrupt 0 (documented interrupt source 32) is the lowest.
 *
 * Additionally, FIQ is not going to be used for now.
 *
 * Returns: the number of interrupt vectors assigned
 *
 * Implementation Note:
 *
*/
uint32_t ep9301_config_pic(uint32_t os_vector_base, uint32_t pic_vector_base, vector_tbl_t *reg_vectors)
{
	uintptr_t base = startup_io_map((EP93xx_VIC_CTRL2_BASE - EP93xx_VIC_CTRL1_BASE) + EP93xx_VIC_CTRL2_SIZE, EP93xx_VIC_CTRL1_BASE);
	unsigned hwi_off;
	unsigned i;

	/*
	 * check the peripheral ID registers. We will assert on the truth of valid_pic_id() since a change
	 * may suggest a difference in the device behaviour which may need to be reflected in a
	 * code change
	*/
	ASSERT(valid_pic_id());
	ASSERT(pic_vector_base == os_vector_base);	// re-mapping not supported (yet)

	reg_vectors->start = pic_vector_base;
	reg_vectors->num = 0;

	/* set all the vector bases */
	intrs[0].vector_base = os_vector_base;
	ASSERT(intrs[0].num_vectors > 0);
	reg_vectors->num += intrs[0].num_vectors;
	for (i=1; i<NUM_ELTS(intrs); i++)
	{
		intrs[i].vector_base = intrs[i - 1].vector_base + intrs[i - 1].num_vectors;
		ASSERT(intrs[i].num_vectors > 0);
		reg_vectors->num += intrs[i].num_vectors;
	}
	/* add the interrupt info section */
	add_interrupt_array(intrs, sizeof(intrs));

	/* disable and clear all interrupts. Note that we do not check EP93xx_VIC_INT_RAW because
	 * some devices do actually have interrupts asserted and this is reflected in the RAW register(s) */
	out32(VIC1(EP93xx_VIC_INT_CLEAR), 0xFFFFFFFFU);
	out32(VIC1(EP93xx_VIC_SWINT_CLEAR), 0xFFFFFFFFU);
	ASSERT(in32(VIC1(EP93xx_VIC_INT_ENABLE)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_SWINT_ENABLE)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_IRQ_STATUS)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_FIQ_STATUS)) == 0);

	out32(VIC2(EP93xx_VIC_INT_CLEAR), 0xFFFFFFFFU);
	out32(VIC2(EP93xx_VIC_SWINT_CLEAR), 0xFFFFFFFFU);
	ASSERT(in32(VIC2(EP93xx_VIC_INT_ENABLE)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_SWINT_ENABLE)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_IRQ_STATUS)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_FIQ_STATUS)) == 0);

	/* set privileged access to interrupt controller registers */
	out32(VIC1(EP93xx_VIC_PROTECTION), 0x0);
	out32(VIC2(EP93xx_VIC_PROTECTION), 0x0);

	/* by default, all interrupts will generate an IRQ (FIQ not used) */
	out32(VIC1(EP93xx_VIC_INT_SELECT), 0);
	out32(VIC2(EP93xx_VIC_INT_SELECT), 0);

	/* place HWI_ILLEGAL_VECTOR into the default vector(s) */
	out32(VIC1(EP93xx_VIC_VEC_ADDR_DFLT), HWI_ILLEGAL_VECTOR);
	out32(VIC2(EP93xx_VIC_VEC_ADDR_DFLT), HWI_ILLEGAL_VECTOR);

	/* disable the use of vectored interrupts for now */
	in32(VIC1(EP93xx_VIC_VEC_ADDR_CURR));
	out32(VIC1(EP93xx_VIC_VEC_ADDR_CURR), 0);
	in32(VIC2(EP93xx_VIC_VEC_ADDR_CURR));
	out32(VIC2(EP93xx_VIC_VEC_ADDR_CURR), 0);
	for (i=0; i<16; i++)
	{
		out32(VIC1(EP93xx_VIC_VEC_ADDR(i)), HWI_ILLEGAL_VECTOR);
		out32(VIC1(EP93xx_VIC_VEC_CTRL(i)), 0);
		out32(VIC2(EP93xx_VIC_VEC_ADDR(i)), HWI_ILLEGAL_VECTOR);
		out32(VIC2(EP93xx_VIC_VEC_CTRL(i)), 0);
	}

	/* TIMER1 - interrupt 4 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 0), -1, 4);

	/* TIMER2 - interrupt 5 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 1), -1, 5);

	/* TIMER3 - interrupt 51 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 2), -1, 51);

	/* WATCHDOG TIMER - interrupt 36 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_WDOG, 0), -1, 36);

	/* DMA channels - Note that the order of vector assignment in the HWINFO section will be
	 * memory to memory 0 - 17
	 * memory to memory 1 - 18
	 * memory to peripheral 0 - 7
	 * memory to peripheral 1 - 8
	 * memory to peripheral 2 - 9
	 * memory to peripheral 3 - 10
	 * memory to peripheral 4 - 11
	 * memory to peripheral 5 - 12
	 * memory to peripheral 6 - 13
	 * memory to peripheral 7 - 14
	 * memory to peripheral 8 - 15
	 * memory to peripheral 9 - 16
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_DMA, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 17);
		hwitag_set_ivec(hwi_off, 1, 18);
		hwitag_set_ivec(hwi_off, 2, 7);
		hwitag_set_ivec(hwi_off, 3, 8);
		hwitag_set_ivec(hwi_off, 4, 9);
		hwitag_set_ivec(hwi_off, 5, 10);
		hwitag_set_ivec(hwi_off, 6, 11);
		hwitag_set_ivec(hwi_off, 7, 12);
		hwitag_set_ivec(hwi_off, 8, 13);
		hwitag_set_ivec(hwi_off, 9, 14);
		hwitag_set_ivec(hwi_off, 10, 15);
		hwitag_set_ivec(hwi_off, 11, 16);
	}

	/* GPIO
	 * 19 of the EP9301 GPIO ports are interruptible and are handled via a
	 * cascaded interrupt entry. In order for devices specifically connected to
	 * those GPIO pins to have a driver InterruptAttach() we provide the assigned
	 * vector ranges with 3 irqrange tags corresponding to the PORTA, PORTB and
	 * PORTF interrupting port pins respectively. Within the range tag assignments,
	 * the 'irq' field corresponds to the LSb (pin 0 of the port) and 'irq' + 'num' - 1
	 * corresponds to the MSb (pin 7 of the port).
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_GPIO, 0)) != HWI_NULL_OFF)
	{
		const unsigned num_pAB_vectors = intrs[1].num_vectors / 2;
		const unsigned num_pF_vectors = intrs[2].num_vectors + intrs[3].num_vectors + intrs[4].num_vectors;
		hwitag_set_ivecrange(hwi_off, 0, intrs[1].vector_base, num_pAB_vectors);	// PORT A
		hwitag_set_ivecrange(hwi_off, 1, intrs[1].vector_base + num_pAB_vectors, num_pAB_vectors);	// PORT B
		hwitag_set_ivecrange(hwi_off, 2, intrs[2].vector_base, num_pF_vectors);	// PORT F
	}

	/* UART1 - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 52
	 * Rx - 23
	 * Tx - 24
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_UART, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 52);
		hwitag_set_ivec(hwi_off, 1, 23);
		hwitag_set_ivec(hwi_off, 2, 24);
	}

	/* UART2 - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 54
	 * Rx - 25
	 * Tx - 26
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_UART, 1)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 54);
		hwitag_set_ivec(hwi_off, 1, 25);
		hwitag_set_ivec(hwi_off, 2, 26);
	}

	/* EXTERNAL IRQ - 2 interrupts 32, 33 and 40 for IQR0, IRQ1 and IRQ2 respectively */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_EXT_IRQ, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 32);
		hwitag_set_ivec(hwi_off, 1, 33);
		hwitag_set_ivec(hwi_off, 2, 40);
	}

	/* RTC - Note that the order of vector assignment in the HWINFO section will be
	 * rtc - 37
	 * 64 Hz clock - 35
	 * 1 Hz clock - 42 (edge sensitive)
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_RTC, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 37);
		hwitag_set_ivec(hwi_off, 1, 35);
		hwitag_set_ivec(hwi_off, 2, 42);
	}

	/* IrDA Device - 38 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_IrDA, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 38);
	}

	/* Ethernet Device */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_ENET, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 39);
	}

	/* SSP - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 53
	 * Rx - 45
	 * Tx - 46
	*/
	if ((hwi_off = hwi_find_bus(EP93xx_HWI_SSP, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 53);
		hwitag_set_ivec(hwi_off, 1, 45);
		hwitag_set_ivec(hwi_off, 2, 46);
	}

	/* USB host controller - 56 */
	if ((hwi_off = hwi_find_bus(EP93xx_HWI_USB, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 56);
	}

	/* I2S device - 60 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_I2S, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 60);
	}

	/* ACC (AC97) device - 6 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_AUDIO, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 6);
	}

	startup_io_unmap(base);

	return reg_vectors->num;
}