void fault_handler( void ) { INT32 device_id; INT32 status; INT32 Index = 0; // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); //printf( "Fault_handler: Found vector type %d with value %d\n", // device_id, status ); switch( device_id ) { case 2: FHMemoryFault(status); break; case 4: Z502Halt(); break; default: break; } // Clear out this device - we're done with it MEM_WRITE(Z502InterruptClear, &Index ); } /* End of fault_handler */
void interrupt_handler( void ) { INT32 device_id; INT32 status; INT32 Index = 0; static BOOL remove_this_in_your_code = TRUE; /** TEMP **/ static INT32 how_many_interrupt_entries = 0; /** TEMP **/ int current_time; int newtime; int diskid; INT32 diskstatus; // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); /** REMOVE THE NEXT SIX LINES **/ //tempPCB = timerfront; diskid = device_id - 4; MEM_WRITE(Z502DiskSetID, &diskid); MEM_READ(Z502DiskStatus, &diskstatus); switch(device_id) { case DISK_INTERRUPT_DISK1: if(diskfront!=NULL&&diskstatus == DEVICE_FREE) { remove_pcb_by_diskID(diskid); } break; case DISK_INTERRUPT_DISK2: if(diskfront!=NULL&&diskstatus == DEVICE_FREE) { remove_pcb_by_diskID(diskid); } break; case DISK_INTERRUPT_DISK3: if(diskfront!=NULL&&diskstatus == DEVICE_FREE) { remove_pcb_by_diskID(diskid); } break; case TIMER_INTERRUPT : while(timerfront!=NULL) { MEM_READ(Z502ClockStatus, ¤t_time); if(current_time > NextInterruptTime) { out_of_timerQ(timerfront); } else break; } if(timerfront!=NULL) { MEM_READ(Z502ClockStatus, ¤t_time); newtime = timerfront->wakeuptime - current_time; MEM_WRITE( Z502TimerStart, &newtime); } break; } //return_readyQ(tempPCB); } /* End of interrupt_handler */
void start_timer( int delaytime ) { int Status; PCB *head; Temp = delaytime; //MEM_READ( Z502TimerStatus, &Status); //READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED,&LockResult); if(Running == NULL) { dispatcher(); Z502SwitchContext( SWITCH_CONTEXT_SAVE_MODE, &(Running->context) ); } MEM_READ(Z502ClockStatus, &Time); MEM_WRITE( Z502TimerStart, &Temp); Running->wakeuptime = Time+Temp; add_to_timerQ(); dispatcher(); //READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED,&LockResult); if(Running == NULL) { CALL(Z502Idle()); } //Z502Idle(); }
//this remove the head of the timerQ from timerQ and set makeTimer as it //this can be used with addToReadyQ to move the dropped timerPCB to readyQ void makeTimerToReady(S_PCB *enter_ptr) { INT32 Time; CALL(MEM_READ( Z502ClockStatus, &Time )); if(enter_ptr==NULL) { makeTimer=NULL; printf("Nothing can be dropped to Ready"); } else if(enter_ptr->next==NULL) { makeTimer = enter_ptr; makeTimer->next=NULL; timerHead=NULL; timerTail=NULL; totalTimerPid--; } else { makeTimer = enter_ptr; timerHead = timerHead->next; makeTimer->next = NULL; totalTimerPid--; if(Time<timerHead->p_time) { start_timer(timerHead->p_time-Time); TimerStatusTime = timerHead->p_time; } } }
void FaultHandler(void) { INT32 DeviceID; INT32 Status; MEMORY_MAPPED_IO mmio; // Enables communication with hardware // Get cause of interrupt mmio.Mode = Z502GetInterruptInfo; MEM_READ(Z502InterruptDevice, &mmio); DeviceID = mmio.Field1; Status = mmio.Field2; if (PrintFAUCount>0){ printf("Fault_handler: Found vector type %d with value %d\n", DeviceID, Status); PrintFAUCount--; } if (DeviceID == PRIVILEGED_INSTRUCTION){ debug(RED, "PRIVILEGED INSTRUCTION"); //my_Halt(); } if (DeviceID == INVALID_MEMORY){ debug(RED, "Memory Fault on page %d", Status); my_AllocateNewPage(Status); } // Clear out this device - we're done with it mmio.Mode = Z502ClearInterruptStatus; mmio.Field1 = DeviceID; MEM_WRITE(Z502InterruptDevice, &mmio); //my_Dispatcher(); } // End of FaultHandler
INT32 my_GET_TIME_OF_DAY() { MEMORY_MAPPED_IO mmio; mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); return mmio.Field1; }
void FaultHandler(void) { INT32 DeviceID; INT32 Status; MEMORY_MAPPED_IO mmio; // Enables communication with hardware // Get cause of interrupt mmio.Mode = Z502GetInterruptInfo; MEM_READ(Z502InterruptDevice, &mmio); DeviceID = mmio.Field1; Status = mmio.Field2; printf("Fault_handler: Found vector type %d with value %d\n", DeviceID, Status); /*****************************My Code******************************/ //temperary code for test1k HaltProcess(); /******************************************************************/ // Clear out this device - we're done with it mmio.Mode = Z502ClearInterruptStatus; mmio.Field1 = DeviceID; MEM_WRITE(Z502InterruptDevice, &mmio); } // End of FaultHandler
/************************************************************************ INTERRUPT_HANDLER When the Z502 gets a hardware interrupt, it transfers control to this routine in the OS. ************************************************************************/ void InterruptHandler(void) { INT32 DeviceID; // INT32 Status; MEMORY_MAPPED_IO mmio; // Enables communication with hardware static BOOL remove_this_in_your_code = TRUE; /** TEMP **/ static INT32 how_many_interrupt_entries = 0; /** TEMP **/ // Get cause of interrupt mmio.Mode = Z502GetInterruptInfo; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502InterruptDevice, &mmio); DeviceID = mmio.Field1; //Status = mmio.Field2; /////////////////////////Code go here//////////////////////////////////// //take all timeout PCB from timer queue and put into ready queue struct Process_Control_Block *tmpPCB; do{ tmpPCB = deTimerQueue(); enReadyQueue(tmpPCB); } while (ResetTimer() == 0); /////////////////////////Code end here/////////////////////////////////// // Clear out this device - we're done with it mmio.Mode = Z502ClearInterruptStatus; mmio.Field1 = DeviceID; mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502InterruptDevice, &mmio); } // End of InterruptHandler
void my_SLEEP(INT32 duration) { INT32 wakeTime = my_GET_TIME_OF_DAY() + duration; debug(GREY, "WakeTime: %d", wakeTime); MEMORY_MAPPED_IO mmio; mmio.Mode = Z502GetCurrentContext; MEM_READ(Z502Context, &mmio); PCB *newPCB; if ((newPCB = PCB_Get_By_ContextID(mmio.Field1)) == NULL) { debug(RED, "ERROR: Process Terminated in Sleep\n"); return; } TimerQueue_Lock("SLEEP"); debug(GREY, "new Timer Queue Item: PID %d wakeTime %d", newPCB->PID, wakeTime); TimerQueue_Add(newPCB, wakeTime); newPCB->status = PROCESS_Waiting; if (currentTimer > wakeTime || currentTimer == 0) { currentTimer = wakeTime; setTimer(duration); } else { debug(BLUE, "No need to set timer %d < %d", currentTimer, wakeTime); } TimerQueue_Unlock("SLEEP"); debug(YELLOW, "Time Before Idle %d\n", my_GET_TIME_OF_DAY()); TestMode("Before Dispatcher"); my_Dispatcher(); debug(YELLOW, "Time After Idle %d\n", my_GET_TIME_OF_DAY()); }
JNIEXPORT jboolean JNICALL Java_go_Seq_readBool(JNIEnv *env, jobject obj) { int8_t *v = MEM_READ(obj, int8_t); if (v == NULL) { return 0; } return *v != 0 ? 1 : 0; }
//This function returns current running Context long CurrentContext() { MEMORY_MAPPED_IO mmio; //for hardware interface mmio.Mode = Z502GetCurrentContext; mmio.Field1 = mmio.Field2 = mmio.Field3 = mmio.Field4 = 0; MEM_READ(Z502Context, &mmio); return mmio.Field1; }
//This function returns current time of system long CurrentTime(){ MEMORY_MAPPED_IO mmio; //for hardware interface mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); return mmio.Field1; }
void test2e(void) { int Iterations; GET_PROCESS_ID("", &Z502_REG4, &Z502_REG9); printf("\n\nRelease %s:Test 2e: Pid %ld\n", CURRENT_REL, Z502_REG4); for (Iterations = 0; Iterations < VIRTUAL_MEM_PGS; Iterations += STEP_SIZE) { Z502_REG3 = PGSIZE * Iterations; // Generate address Z502_REG1 = Z502_REG3 + Z502_REG4; // Generate data MEM_WRITE(Z502_REG3, &Z502_REG1); // Write the data MEM_READ(Z502_REG3, &Z502_REG2); // Read back data if (Iterations % DISPLAY_GRANULARITY2e == 0) printf("PID= %ld address= %ld written= %ld read= %ld\n", Z502_REG4, Z502_REG3, Z502_REG1, Z502_REG2); if (Z502_REG2 != Z502_REG1) // Written = read? printf("AN ERROR HAS OCCURRED.\n"); // It makes life more fun!! to write the data again MEM_WRITE(Z502_REG3, &Z502_REG1); // Write the data } // End of for loop // Now read back the data we've written and paged printf("Reading back data: test 2e, PID %ld.\n", Z502_REG4); for (Iterations = 0; Iterations < VIRTUAL_MEM_PGS; Iterations += STEP_SIZE) { Z502_REG3 = PGSIZE * Iterations; // Generate address Z502_REG1 = Z502_REG3 + Z502_REG4; // Data expected MEM_READ(Z502_REG3, &Z502_REG2); // Read back data if (Iterations % DISPLAY_GRANULARITY2e == 0) printf("PID= %ld address= %ld written= %ld read= %ld\n", Z502_REG4, Z502_REG3, Z502_REG1, Z502_REG2); if (Z502_REG2 != Z502_REG1) // Written = read? printf("AN ERROR HAS OCCURRED.\n"); } // End of for loop TERMINATE_PROCESS(-2, &Z502_REG5); // Added 12/1/2013 } // End of test2e
JNIEXPORT jbyte JNICALL Java_go_Seq_readInt8(JNIEnv *env, jobject obj) { uint8_t *v = MEM_READ(obj, uint8_t); if (v == NULL) { return 0; } return *v; }
JNIEXPORT jstring JNICALL Java_go_Seq_readUTF16(JNIEnv *env, jobject obj) { int32_t size = *MEM_READ(obj, int32_t); if (size == 0) { return NULL; } return (*env)->NewString(env, (jchar*)mem_read(env, obj, 2*size, 1), size); }
void fault_handler( void ) { INT32 device_id; INT32 status; INT32 Index = 0; // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); printf( "Fault_handler: Found vector type %d with value %d\n", device_id, status ); // Clear out this device - we're done with it MEM_WRITE(Z502InterruptClear, &Index ); } /* End of fault_handler */
void start_timer(INT32 timer_time) { INT32 Time; INT32 SleepTime; CALL(MEM_READ( Z502ClockStatus, &Time )); CALL(MEM_WRITE( Z502TimerStart, &timer_time)); TimerStatusTime = Time+timer_time; }
short SPPrintLine(SP_INPUT_DATA *Input) { char OutputLine[900]; char temp[60]; // INT32 current_time; MEMORY_MAPPED_IO mmio; SetMode(KERNEL_MODE); // print out the header sprintf(OutputLine, "%s", SP_HEADER_STRING); // Get the current time and place it in the output string mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); sprintf(temp, "%5d", (int) mmio.Field1 % 100000); strcat(OutputLine, temp); // If user defines the target PID, place it here if (Input->TargetPID >= 0) sprintf(temp, "%5d ", Input->TargetPID); else sprintf(temp, "%s", " "); (void) strcat(OutputLine, temp); sprintf(temp, " %8s", Input->TargetAction); /* Action */ (void) strcat(OutputLine, temp); sprintf(temp, " %3d ", Input->CurrentlyRunningPID); (void) strcat(OutputLine, temp); // Multiple running processes is not implemented in Release 4.20 SPLineSetup(OutputLine, "RUNNING:", Input->NumberOfRunningProcesses, Input->RunningProcessPIDs); SPLineSetup(OutputLine, "READY :", Input->NumberOfReadyProcesses, Input->ReadyProcessPIDs); SPLineSetup(OutputLine, "SUS-PRC:", Input->NumberOfProcSuspendedProcesses, Input->ProcSuspendedProcessPIDs); SPLineSetup(OutputLine, "SUS-TMR:", Input->NumberOfTimerSuspendedProcesses, Input->TimerSuspendedProcessPIDs); SPLineSetup(OutputLine, "SUS-MSG:", Input->NumberOfMessageSuspendedProcesses, Input->MessageSuspendedProcessPIDs); SPLineSetup(OutputLine, "SUS-DSK:", Input->NumberOfDiskSuspendedProcesses, Input->DiskSuspendedProcessPIDs); SPLineSetup(OutputLine, "TERM'S :", Input->NumberOfTerminatedProcesses, Input->TerminatedProcessPIDs); SPDoOutput(OutputLine); // We've accumulated the whole line - print it. return 0; } // End of SP_print_line
void disk_write(long disk_id,long sector_id,char* write_buffer) { /* Do the hardware call to put data on disk */ INT32 diskstatus; MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &diskstatus); if (diskstatus == DEVICE_FREE) { // Disk hasn't been used - should be free } if(diskstatus == DEVICE_IN_USE) { Running->disk_id = disk_id; add_to_diskQ(Running); Running = NULL; dispatcher(); /*Z502SwitchContext( SWITCH_CONTEXT_SAVE_MODE, &(Running->context) );*/ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &diskstatus); } MEM_WRITE(Z502DiskSetSector, §or_id); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )write_buffer); diskstatus = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &diskstatus); diskstatus = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &diskstatus); // Disk should now be started - let's see /* MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &diskstatus); while (diskstatus != DEVICE_FREE) { Z502Idle(); MEM_READ(Z502DiskStatus, &diskstatus); }*/ Running->disk_id = disk_id; return_readyQ(Running); Running = NULL; dispatcher(); /*Z502SwitchContext( SWITCH_CONTEXT_SAVE_MODE, &(Running->context) );*/ }
void cpu_run(int cycles) { cycles_left = cycles; while (cycles_left > 0) { opcode = MEM_READ(REG_PC++); switch (opcode) { #include "opcodes.h" } cycles_left -= timings[opcode]; } }
void test2b(void) { static INT32 test_data[TEST_DATA_SIZE ] = {0, 4, PGSIZE - 2, PGSIZE, 3 * PGSIZE - 2, (VIRTUAL_MEM_PGS - 1) * PGSIZE, VIRTUAL_MEM_PGS * PGSIZE - 2}; GET_PROCESS_ID("", &Z502_REG4, &Z502_REG9); printf("\n\nRelease %s:Test 2b: Pid %ld\n", CURRENT_REL, Z502_REG4); Z502_REG8 = 5 * PGSIZE; Z502_REG6 = Z502_REG8 + Z502_REG4 + 7; MEM_WRITE(Z502_REG8, &Z502_REG6); // Loop through all the memory addresses defined while (TRUE) { Z502_REG3 = test_data[(INT16) Z502_REG5]; Z502_REG1 = Z502_REG3 + Z502_REG4 + 27; MEM_WRITE(Z502_REG3, &Z502_REG1); MEM_READ(Z502_REG3, &Z502_REG2); printf("PID= %ld address= %ld written= %ld read= %ld\n", Z502_REG4, Z502_REG3, Z502_REG1, Z502_REG2); if (Z502_REG2 != Z502_REG1) printf("AN ERROR HAS OCCURRED.\n"); // Go back and check earlier write MEM_READ(Z502_REG8, &Z502_REG7); printf("PID= %ld address= %ld written= %ld read= %ld\n", Z502_REG4, Z502_REG8, Z502_REG6, Z502_REG7); if (Z502_REG6 != Z502_REG7) printf("AN ERROR HAS OCCURRED.\n"); Z502_REG5++; } } // End of test2b
/************************************************************************ INTERRUPT_HANDLER When the Z502 gets a hardware interrupt, it transfers control to this routine in the OS. ************************************************************************/ void interrupt_handler( void ) { INT32 device_id; INT32 status; INT32 Time; INT32 Index = 0; static BOOL remove_this_in_your_code = TRUE; /** TEMP **/ static INT32 how_many_interrupt_entries = 0; /** TEMP **/ // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); switch(device_id) { case TIMER_ITR: CALL(MEM_READ(Z502ClockStatus, &Time)); while(timerHead!=NULL) { if(Time>(timerHead->p_time)) { printf("Interrupt_handler: Found device ID %d\n",timerHead->p_id); lockTimer(); //overTimeModify(); makeTimerToReady(timerHead); addToReadyQ(makeTimer); unlockTimer(); } else break; } break; } MEM_WRITE(Z502InterruptClear, &Index ); } /* End of interrupt_handler */
/************************************************************************ INTERRUPT_HANDLER When the Z502 gets a hardware interrupt, it transfers control to this routine in the OS. ************************************************************************/ void interrupt_handler( void ) { INT32 device_id; INT32 status; INT32 Index = 0; // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); switch( device_id ) { case 4: IHTimerInterrupt(); break; case 5: // disk 1 case 6: // disk 2 case 7: // disk 3 case 8: // disk 4 case 9: // disk 5 case 10: // disk 6 case 11: // disk 7 case 12: // disk 8 IHDiskInterrupt(device_id); break; default: break; } // Clear out this device - we're done with it MEM_WRITE(Z502InterruptClear, &Index ); } /* End of interrupt_handler */
/************************************************************************ INTERRUPT_HANDLER When the Z502 gets a hardware interrupt, it transfers control to this routine in the OS. ************************************************************************/ void interrupt_handler( void ) { INT32 device_id; INT32 status; INT32 Index = 0; static BOOL remove_this_in_your_code = TRUE; /** TEMP **/ static INT32 how_many_interrupt_entries = 0; /** TEMP **/ // Get cause of interrupt MEM_READ(Z502InterruptDevice, &device_id ); // Set this device as target of our query MEM_WRITE(Z502InterruptDevice, &device_id ); // Now read the status of this device MEM_READ(Z502InterruptStatus, &status ); /** REMOVE THE NEXT SIX LINES **/ how_many_interrupt_entries++; /** TEMP **/ if ( remove_this_in_your_code && ( how_many_interrupt_entries < 20 ) ) { printf( "Interrupt_handler: Found device ID %d with status %d\n", device_id, status ); } // Clear out this device - we're done with it MEM_WRITE(Z502InterruptClear, &Index ); } /* End of interrupt_handler */
/************************************************************************** Test2a exercises a simple memory write and read Use: Z502_REG1 data_written Z502_REG2 data_read Z502_REG3 address Z502_REG4 process_id Z502_REG9 error In global.h, there's a variable DO_MEMORY_DEBUG. Switching it to TRUE will allow you to see what the memory system thinks is happening. WARNING - it's verbose -- and I don't want to see such output - it's strictly for your debugging pleasure. **************************************************************************/ void test2a(void) { GET_PROCESS_ID("", &Z502_REG4, &Z502_REG9); printf("Release %s:Test 2a: Pid %ld\n", CURRENT_REL, Z502_REG4); Z502_REG3 = 412; Z502_REG1 = Z502_REG3 + Z502_REG4; MEM_WRITE(Z502_REG3, &Z502_REG1); MEM_READ(Z502_REG3, &Z502_REG2); printf("PID= %ld address= %ld written= %ld read= %ld\n", Z502_REG4, Z502_REG3, Z502_REG1, Z502_REG2); if (Z502_REG2 != Z502_REG1) printf("AN ERROR HAS OCCURRED.\n"); TERMINATE_PROCESS(-1, &Z502_REG9); } // End of test2a
//**************************************************************************** void OnRedispatch(void) { while( 1 ) { INT32 Status; MEM_READ(Z502TimerStatus, &Status); // No more active processes, halt the machine. if( gProcessManager->IsAllDead() == 1 ) { Z502Halt(); } // Dispatch a process that is ready. if( gProcessManager->GetReadyQueueProcessCount() > 0 ) { MakeReadyToRun(); } } }
//**************************************************************************** void PrintState() { INT32 currentTime; int i; int sleepCount; MEM_READ(Z502ClockStatus, ¤tTime); SP_setup(SP_TIME_MODE, currentTime); SP_setup(SP_RUNNING_MODE, GetRunningProcess()->processID); MinPriQueue tempQueue; HeapItem tempItem; MinPriQueueClone(gReadyQueue, &tempQueue); int readyCount = tempQueue.heap.size; for( i = 0; i < readyCount; ++i ) { MinPriQueuePop(&tempQueue, &tempItem); SP_setup(SP_READY_MODE, ((PCB*)tempItem.data)->processID); } MinPriQueueClone(gTimerQueue, &tempQueue); sleepCount = tempQueue.heap.size; for( i = 0; i < sleepCount; ++i ) { MinPriQueuePop(&tempQueue, &tempItem); SP_setup(SP_TIMER_SUSPENDED_MODE, ((PCB*)tempItem.data)->processID); } ListNode* current = gSuspendedList->head; while( current ) { SP_setup(SP_PROCESS_SUSPENDED_MODE, ((PCB*)current->data)->processID); current = current->next; } SP_print_line(); }
void my_AllocateNewPage(int vpn){ if (vpn >=VIRTUAL_MEM_PAGES){ my_Halt(); } MEMORY_MAPPED_IO mmio; short * PAGE_TBL_ADDR; mmio.Mode = Z502GetPageTable; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Context, &mmio); PAGE_TBL_ADDR = (short *) mmio.Field1; short entry; entry = PTBL_VALID_BIT; //find one empty slot in Mem_Alloc_Table int i = 0; for (i = 0; i<PHYS_MEM_PGS; i++){ if (!Mem_Alloc_Table[i].isUsed){ Mem_Alloc_Table[i].isUsed = TRUE; entry += i; break; } } debug(RED, "Allocate new page, parameter %x", entry); PAGE_TBL_ADDR[vpn] = entry; }
void sample_code(void) { INT32 i, j, k; /* Index & counters */ long Value; INT32 disk_id, sector; /* Used for disk requests */ char disk_buffer_write[PGSIZE ]; char disk_buffer_read[PGSIZE ]; char physical_memory_write[PGSIZE ]; char physical_memory_read[PGSIZE ]; void *context_pointer; /* Used for context commands*/ void *starting_address; BOOL kernel_or_user; short random_buckets[NUM_RAND_BUCKETS]; INT32 LockResult; INT32 Status; INT32 Temp, Temp1; /********************************************************************* Show the interface to the delay timer. Eventually the timer will interrupt ( in base.c there's a handler for this ), but here in sample_code.c we're merely showing the interface to start the call. *********************************************************************/ MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_FREE) printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); Temp = 777; /* You pick the time units */ MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_IN_USE) printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); printf("The next output from the Interrupt Handler should report that \n"); printf(" interrupt of device 4 has occurred with no error.\n"); Z502Idle(); // Let the interrupt for this timer occur // Now we're going to try an illegal time and ensure that the fault // handler reports an illegal status. Temp = -77; /* You pick the time units */ printf("The next output from the Interrupt Handler should report that \n"); printf( " interrupt of device 4 has occurred with an ERR_BAD_PARAM = 1.\n"); MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_FREE) // Bogus value shouldn't start timer printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); fflush(stdout); // ZCALL( Z502_IDLE() ); // Let the interrupt for this timer occur /* The interrupt handler will have exercised the code doing Z502InterruptDevice, Z502InterruptStatus, and Z502InterruptClear. But they will have been tested only for "correct" usage. Let's try a few erroneous/illegal operations. */ // Set an illegal device as target of our query Temp = LARGEST_STAT_VECTOR_INDEX + 1; MEM_WRITE(Z502InterruptDevice, &Temp); // Now read the status of this device MEM_READ(Z502InterruptStatus, &Status); if (Status == ERR_BAD_DEVICE_ID) printf("Got expected result for Status of Illegal Device\n"); else printf("Got erroneous result for Status of Illegal Device\n"); /********************************************************************* Show the interface to the Z502_CLOCK. This is easy - all we're going to do is read it twice and make sure the time is incrementing. *********************************************************************/ MEM_READ(Z502ClockStatus, &Temp); MEM_READ(Z502ClockStatus, &Temp1); if (Temp1 > Temp) printf("The clock time incremented correctly - %d1, %d2\n", Temp, Temp1); else printf("The clock time did NOT increment correctly - %d1, %d2\n", Temp, Temp1); /********************************************************************* Show the interface to the disk read and write. Eventually the disk will interrupt ( in base.c there's a handler for this ), but here in sample_code.c we're merely showing the interface to start the call. *********************************************************************/ disk_id = 1; /* Pick arbitrary disk location */ sector = 3; /* Put data into the buffer being written */ strncpy(disk_buffer_write, "123456789abcdef", 15); /* Do the hardware call to put data on disk */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_FREE) // Disk hasn't been used - should be free printf("Got expected result for Disk Status\n"); else printf("Got erroneous result for Disk Status - Device not free.\n"); MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_write); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Disk should now be started - let's see MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_IN_USE) // Disk should report being used printf("Got expected result for Disk Status\n"); else printf("Got erroneous result for Disk Status\n"); /* Wait until the disk "finishes" the write. the write is an "unpended-io", meaning the call returns before the work is completed. By doing the IDLE here, we wait for the disk action to complete. */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp != DEVICE_FREE) { Z502Idle(); MEM_READ(Z502DiskStatus, &Temp); } /* Now we read the data back from the disk. If we're lucky, we'll read the same thing we wrote! */ MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_read); Temp = 0; // Specify a read MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); /* wait for the disk action to complete. */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp != DEVICE_FREE) { Z502Idle(); MEM_READ(Z502DiskStatus, &Temp); } printf("\n\nThe disk data written is: %s\n", disk_buffer_write); printf("The disk data read is: %s\n", disk_buffer_read); /********************************************************************* Let's try some intentional errors to see what happens *********************************************************************/ Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Try reading the status without setting an ID MEM_READ(Z502DiskStatus, &Temp); if (Temp == ERR_BAD_DEVICE_ID) printf("Got expected result for Disk Status when using no ID\n"); else printf("Got erroneous result for Disk Status when using no ID\n"); // Try entering a bad ID and then reading the status disk_id = 999; MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == ERR_BAD_DEVICE_ID) printf("Got expected result for Disk Status when using bad ID\n"); else printf("Got erroneous result for Disk Status when using bad ID\n"); // Try doing everything right EXCEPT entering the buffer address, disk_id = 1; /* Pick arbitrary disk location */ sector = 3; MEM_WRITE(Z502DiskSetID, &disk_id); MEM_WRITE(Z502DiskSetSector, §or); // Don't do this -> MEM_WRITE( Z502DiskSetBuffer, (INT32 *)disk_buffer_write ); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Disk should now not be started - it was missing vital info MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_FREE) // Disk should report being free printf("Got expected result for Disk Status when missing data\n"); else printf("Got erroneous result for Disk Status when missing data\n"); /********************************************************************* Some of the tests put thousands of pages of data on the disk. Let's see if we can do that here. The pages ARE being written to the disk, but the interrupt handler doesn't show all of them happening because it's not catching multiple interrupts. *********************************************************************/ disk_id = 1; sector = 0; printf("The following section will take a few seconds\n"); for (j = 0; j < VIRTUAL_MEM_PGS + 100 /* arbitrary # */; j++) { MEM_WRITE(Z502DiskSetID, &disk_id); MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_write); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Start the disk MEM_WRITE(Z502DiskStart, &Temp); MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp == DEVICE_IN_USE) // Disk should report being used { //printf( "Got erroneous result for Disk Status when writing lots of blocks\n" ); Temp = 5; /* You pick the time units */ MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502DiskStatus, &Temp); } sector++; if (sector >= NUM_LOGICAL_SECTORS) { sector = 0; disk_id++; } } /********************************************************************* Do a physical memory access to check out that it works. *********************************************************************/ printf("\nStarting test of physical memory write and read.\n"); for (i = 0; i < PGSIZE ; i++) { physical_memory_write[i] = i; } Z502WritePhysicalMemory(17, (char *) physical_memory_write); Z502ReadPhysicalMemory(17, (char *) physical_memory_read); for (i = 0; i < PGSIZE ; i++) { if (physical_memory_write[i] != physical_memory_read[i]) printf("Error in Physical Memory Access\n"); } printf("Completed test of physical memory write and read.\n"); /********************************************************************* Start all of the disks at the same time and see what happens. *********************************************************************/ /* sector = 0; for ( disk_id = 1; disk_id <= MAX_NUMBER_OF_DISKS ; disk_id++ ) { MEM_WRITE( Z502DiskSetID, &disk_id ); MEM_WRITE( Z502DiskSetSector, §or ); MEM_WRITE( Z502DiskSetBuffer, (INT32 *)disk_buffer_write ); Temp = 1; // Specify a write MEM_WRITE( Z502DiskSetAction, &Temp ); Temp = 0; // Start the disk MEM_WRITE( Z502DiskStart, &Temp ); sector++; } // Now wait until all disks have finished for ( disk_id = 1; disk_id <= MAX_NUMBER_OF_DISKS ; disk_id++ ) { MEM_WRITE( Z502DiskSetID, &disk_id ); MEM_READ( Z502DiskStatus, &Temp ); while ( Temp == DEVICE_IN_USE ) // Disk should report being used { //ZCALL( Z502_IDLE() ); DoSleep(50); } } */ printf("Disk multiple-block test is complete\n\n"); /********************************************************************* Show the interface to read and write of real memory It turns out, that though these are hardware calls, the Z502 assumes the calls are being made in user mode. Because the process we're running here in "sample" is in kernel mode, the calls don't work correctly. For working examples of these calls, see test2a. *********************************************************************/ Z502_PAGE_TBL_LENGTH = 64; Z502_PAGE_TBL_ADDR = (UINT16 *) calloc(sizeof(UINT16), Z502_PAGE_TBL_LENGTH); i = PTBL_VALID_BIT; Z502_PAGE_TBL_ADDR[0] = (UINT16) i; i = 73; MEM_WRITE(0, &i); MEM_READ(0, &j); /* WE expect the data read back to be the same as what we wrote */ if (i == j) printf("Memory write and read completed successfully\n"); else printf("Memory write and read were NOT successful.\n"); /********************************************************************* This is the interface to the locking mechanism. These are hardware interlocks. We need to test that they work here. This is the interface we'll be using. void Z502_READ_MODIFY( INT32 VirtualAddress, INT32 NewLockValue, INT32 Suspend, INT32 *LockResult ) We've defined these above to help remember them. #define DO_LOCK 1 #define DO_UNLOCK 0 #define SUSPEND_UNTIL_LOCKED TRUE #define DO_NOT_SUSPEND FALSE *********************************************************************/ printf("++++ Starting Hardware Interlock Testing ++++\n"); // TRY A SERIES OF CALLS AS DESCRIBED HERE printf("These tests map into the matrix describing the Z502_READ_MODIFY\n"); printf(" described in Appendix A\n\n"); printf( "1. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "2. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "3. Start State = Unlocked: Action (Thread 1) = unLock: End State = UnLocked\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "4. Start State = unlocked: Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "5. Start State = Locked(1): Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "6. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "7. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // A thread that locks an item it has already locked will succeed printf( "8. Start State = locked(1): Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // Locking a thread that's already locked - but do it with a thread // other than the one that did the locking. printf( "9. Start State = Locked(1): Action (Thread 2) = tryLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOnelock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // Unlock a thread that's already locked - but unlock it with a thread // other than the one that did the locking. printf( "10. Start State = Locked(1): Action (Thread 2) = unLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The second thread will try to get the lock held by the first thread. This is OK // but the second thread will suspend until the first thread releases the lock. printf( "11. Start State = Locked(1): Action (Thread 2) = Lock: End State = Locked\n"); Status = CreateAThread((int *) DoOneTrylock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The first thread does an unlock. This means the second thread is now able to get // the lock so there is a "relock" when thread two succeeds. printf( "12. Start State = locked(1): Action (Thread 1) = unLock: End State = Locked(by 2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); DoSleep(100); /* Wait for locking action of 2nd thread to finish */ printf( "13. Start State = Locked(2): Action (Thread 3) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ printf( "14. Start State = Locked(2): Action (Thread 1) = tryLock: End State = Locked(2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "15. Start State = locked(2): Action (Thread 1) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf("++++ END of hardware interlock code ++++\n\n"); /********************************************************************* Show the interface to the CONTEXT calls. We aren't going to do a SWITCH_CONTEXT here, because that would cause us to start a process in a strange place and we might never return here. But we do all the setup required. *********************************************************************/ /* The context_pointer is returned by the MAKE_CONTEXT call. */ starting_address = (void *) starting_point_for_new_context; kernel_or_user = USER_MODE; Z502MakeContext(&context_pointer, starting_address, kernel_or_user); Z502DestroyContext(&context_pointer); /********************************************************************* Show the interface to the scheduler printer. *********************************************************************/ CALL(SP_setup( SP_TIME_MODE, 99999 )); CALL(SP_setup_action( SP_ACTION_MODE, "CREATE" )); CALL(SP_setup( SP_TARGET_MODE, 99L )); CALL(SP_setup( SP_RUNNING_MODE, 99L )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_READY_MODE, j )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_WAITING_MODE, j+20 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_SUSPENDED_MODE, j+40 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_SWAPPED_MODE, j+60 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_TERMINATED_MODE, j+80 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_NEW_MODE, j+50 )); CALL(SP_print_header()); CALL(SP_print_line()); /********************************************************************* Show the interface to the memory_printer. *********************************************************************/ for (j = 0; j < 64; j = j + 2) { MP_setup((INT32) (j), (INT32) (j / 2) % 10, (INT32) j * 16 + 10, (INT32) (j / 2) % 8); } MP_print_line(); /********************************************************************* Show how the skewed random numbers work on this platform. *********************************************************************/ for (j = 0; j < NUM_RAND_BUCKETS; j++) random_buckets[j] = 0; for (j = 0; j < 100000; j++) { get_skewed_random_number(&Value, NUM_RAND_BUCKETS); random_buckets[Value]++; } printf("\nTesting that your platform produces correctly skewed random\n"); printf("numbers. Each row should have higher count than the previous.\n"); printf(" Range: Counts in this range.\n"); for (j = 0; j < NUM_RAND_BUCKETS; j = j + 8) { k = 0; for (i = j; i < j + 8; i++) k += random_buckets[i]; printf("%3d - %3d: %d\n", j, j + 7, k); } /********************************************************************* Show the interface to the Z502Halt. Note that the program will end NOW, since we don't return from the command. *********************************************************************/ Z502Halt(); }
static inline unsigned int mfc_read_shared_mem_item(unsigned int host_wr_addr, unsigned int addr) { return MEM_READ(host_wr_addr + addr); }