/** * Intializes all Xinu data structures and devices. * @return OK if everything is initialized successfully */ static int sysinit(void) { int i; struct thrent *thrptr; /* thread control block pointer */ struct memblock *pmblock; /* memory block pointer */ /* Initialize system variables */ /* Count this NULLTHREAD as the first thread in the system. */ thrcount = 1; /* Initialize free memory list */ memheap = roundmb(memheap); platform.maxaddr = truncmb(platform.maxaddr); memlist.next = pmblock = (struct memblock *)memheap; memlist.length = (uint)(platform.maxaddr - memheap); pmblock->next = NULL; pmblock->length = (uint)(platform.maxaddr - memheap); /* Initialize thread table */ for (i = 0; i < NTHREAD; i++) { thrtab[i].state = THRFREE; } /* initialize null thread entry */ thrptr = &thrtab[NULLTHREAD]; thrptr->state = THRCURR; thrptr->prio = 0; strlcpy(thrptr->name, "prnull", TNMLEN); thrptr->stkbase = (void *)&_end; thrptr->stklen = (ulong)memheap - (ulong)&_end; thrptr->stkptr = 0; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; thrcurrent = NULLTHREAD; /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { semtab[i].state = SFREE; semtab[i].queue = queinit(); } /* Initialize monitors */ for (i = 0; i < NMON; i++) { montab[i].state = MFREE; } /* Initialize buffer pools */ for (i = 0; i < NPOOL; i++) { bfptab[i].state = BFPFREE; } /* initialize thread ready list */ readylist = queinit(); #if SB_BUS backplaneInit(NULL); #endif /* SB_BUS */ #if RTCLOCK /* initialize real time clock */ clkinit(); #endif /* RTCLOCK */ #ifdef UHEAP_SIZE /* Initialize user memory manager */ { void *userheap; /* pointer to user memory heap */ userheap = stkget(UHEAP_SIZE); if (SYSERR != (int)userheap) { userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); memRegionInit(userheap, UHEAP_SIZE); /* initialize memory protection */ safeInit(); /* initialize kernel page mappings */ safeKmapInit(); } } #endif #if USE_TLB /* initialize TLB */ tlbInit(); /* register system call handler */ exceptionVector[EXC_SYS] = syscall_entry; #endif /* USE_TLB */ #if NMAILBOX /* intialize mailboxes */ mailboxInit(); #endif #if NDEVS for (i = 0; i < NDEVS; i++) { devtab[i].init((device*)&devtab[i]); } #endif #ifdef WITH_USB usbinit(); #endif #if NVRAM nvramInit(); #endif #if NNETIF netInit(); #endif #if GPIO gpioLEDOn(GPIO_LED_CISCOWHT); #endif return OK; }
/** * Intializes all Xinu data structures and devices. * @return OK if everything is initialized successfully */ static int sysinit(void) { int i; void *userheap; /* pointer to user memory heap */ struct thrent *thrptr; /* thread control block pointer */ device *devptr; /* device entry pointer */ struct sement *semptr; /* semaphore entry pointer */ struct memblock *pmblock; /* memory block pointer */ struct bfpentry *bfpptr; /* Initialize system variables */ /* Count this NULLTHREAD as the first thread in the system. */ thrcount = 1; kprintf("variable i in this function is at 0x%x\r\n", &i); kprintf("this function sysinit is at 0x%x\r\n", &sysinit); kprintf("_start is at 0x%x\r\n", _start); kprintf("_end is at (the end) at 0x%x\r\n", &_end); kprintf("readylist is at 0x%x\r\n", &readylist); kprintf("kputc is at 0x%x\r\n", &kputc); kprintf("NTHREAD is %d\r\n", NTHREAD); kprintf("memheap is 0x%x\r\n", memheap); /* Initialize free memory list */ memheap = roundmb(memheap); platform.maxaddr = truncmb(platform.maxaddr); kprintf("platform.maxaddr is 0x%x\r\n", platform.maxaddr); memlist.next = pmblock = (struct memblock *)memheap; memlist.length = (uint)(platform.maxaddr - memheap); pmblock->next = NULL; pmblock->length = (uint)(platform.maxaddr - memheap); /* Initialize thread table */ for (i = 0; i < NTHREAD; i++) { thrtab[i].state = THRFREE; } kprintf("thrtab is at 0x%x, size %d\r\n", thrtab, sizeof(thrtab)); /* initialize null thread entry */ thrptr = &thrtab[NULLTHREAD]; thrptr->state = THRCURR; thrptr->prio = 0; strncpy(thrptr->name, "prnull", 7); thrptr->stkbase = (void *)&_end; thrptr->stklen = (ulong)memheap - (ulong)&_end; thrptr->stkptr = 0; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; thrcurrent = NULLTHREAD; kprintf("&_end is 0x%x\n", &_end); /* Initialize semaphores */ for (i = 0; i < NSEM; i++) { semptr = &semtab[i]; semptr->state = SFREE; semptr->count = 0; semptr->queue = queinit(); } kprintf("NPOOL is %d\n", NPOOL); /* Initialize buffer pools */ for (i = 0; i < NPOOL; i++) { bfpptr = &bfptab[i]; bfpptr->state = BFPFREE; } kprintf("calling queinit() for readylist\r\n"); /* initialize thread ready list */ readylist = queinit(); #if SB_BUS backplaneInit(NULL); #endif /* SB_BUS */ #if RTCLOCK /* initialize real time clock */ kprintf("Clock being initialized.\r\n" ); clkinit(); #endif /* RTCLOCK */ #ifdef UHEAP_SIZE /* Initialize user memory manager */ userheap = stkget(UHEAP_SIZE); if (SYSERR != (int)userheap) { userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); memRegionInit(userheap, UHEAP_SIZE); /* initialize memory protection */ safeInit(); /* initialize kernel page mappings */ safeKmapInit(); } #else userheap = NULL; #endif /* UHEAP_SIZE */ #if USE_TLB /* initialize TLB */ tlbInit(); /* register system call handler */ exceptionVector[EXC_SYS] = syscall_entry; #endif /* USE_TLB */ #if NMAILBOX /* intialize mailboxes */ mailboxInit(); #endif #if NDEVS for (i = 0; i < NDEVS; i++) { if (!isbaddev(i)) { devptr = (device *)&devtab[i]; (devptr->init) (devptr); } } #endif #if 0 #if NVRAM nvramInit(); #endif kprintf("SO MUCH MORE NOT done with sysinit()\r\n"); #if NNETIF netInit(); #endif kprintf("NOT done with sysinit()\r\n"); #if GPIO gpioLEDOn(GPIO_LED_CISCOWHT); #endif #endif kprintf("done with sysinit()\r\n"); return OK; }
/** * Initialize ethernet device structures. * @param devptr ETH device table entry * @return OK if device is intialized successfully, otherwise SYSERR */ devcall etherInit(device *devptr) { struct ether *ethptr; struct ag71xx *nicptr; uint *rstptr; uint rstbit; /* Initialize structure pointers */ ethptr = ðertab[devptr->minor]; bzero(ethptr, sizeof(struct ether)); ethptr->dev = devptr; ethptr->csr = devptr->csr; nicptr = (struct ag71xx *)devptr->csr; rstptr = (uint *)RESET_CORE; if (0 == devptr->minor) { rstbit = RESET_E0_MAC; } else { rstbit = RESET_E1_MAC; } ethptr->state = ETH_STATE_DOWN; ethptr->rxRingSize = ETH_RX_RING_ENTRIES; ethptr->txRingSize = ETH_TX_RING_ENTRIES; ethptr->mtu = ETH_MTU; ethptr->interruptMask = IRQ_TX_PKTSENT | IRQ_TX_BUSERR | IRQ_RX_PKTRECV | IRQ_RX_OVERFLOW | IRQ_RX_BUSERR; ethptr->errors = 0; ethptr->isema = semcreate(0); ethptr->istart = 0; ethptr->icount = 0; ethptr->ovrrun = 0; ethptr->rxOffset = ETH_PKT_RESERVE; // FIXME: Actual MAC lookup in nvram. /* Lookup canonical MAC in NVRAM, and store in ether struct */ // colon2mac(nvramGet("et0macaddr"), ethptr->devAddress); char mac[] = { 0x00, 0x01, 0x36, 0x22, 0x7e, 0xf1 }; memcpy(ethptr->devAddress, mac, ETH_ADDR_LEN); ethptr->addressLength = ETH_ADDR_LEN; // Reset the device. nicptr->macConfig1 |= MAC_CFG1_SOFTRESET; udelay(20); *rstptr |= rstbit; mdelay(100); *rstptr &= ~rstbit; mdelay(100); // Enable Tx and Rx. nicptr->macConfig1 = MAC_CFG1_TX | MAC_CFG1_SYNC_TX | MAC_CFG1_RX | MAC_CFG1_SYNC_RX; // Configure full duplex, auto padding CRC, and interface mode. nicptr->macConfig2 |= MAC_CFG2_FDX | MAC_CFG2_PAD | MAC_CFG2_LEN_CHECK | MAC_CFG2_IMNIBBLE; // Enable FIFO modules. nicptr->fifoConfig0 = FIFO_CFG0_WTMENREQ | FIFO_CFG0_SRFENREQ | FIFO_CFG0_FRFENREQ | FIFO_CFG0_STFENREQ | FIFO_CFG0_FTFENREQ; // FIXME // -> ag71xx_mii_ctrl_set_if(ag, pdata->mii_if); // Stores a '1' in 0x18070000 (MII mode) // Stores a '1' in 0x18070004 (RMII mode) // FRRD may be asserted only after the completion of the input frame. nicptr->fifoConfig1 = 0x0FFF0000; // Max out number of words to store in Rx RAM; nicptr->fifoConfig2 = 0x00001FFF; // Drop anything with errors in the Rx stats vector. nicptr->fifoConfig4 = 0x0003FFFF; // Drop short packets, set "don't care" on Rx stats vector bits. nicptr->fifoConfig5 = 0x0003FFFF; /* NOTE: because device initialization runs early in the system, */ /* we are assured that this stkget() call will return */ /* page-aligned (and cache-aligned) boundaries. */ ethptr->rxBufs = stkget(PAGE_SIZE); ethptr->txBufs = stkget(PAGE_SIZE); ethptr->rxRing = stkget(PAGE_SIZE); ethptr->txRing = stkget(PAGE_SIZE); if ((SYSERR == (int)ethptr->rxBufs) || (SYSERR == (int)ethptr->txBufs) || (SYSERR == (int)ethptr->rxRing) || (SYSERR == (int)ethptr->txRing)) { #ifdef DETAIL kprintf("eth%d ring buffer allocation error.\r\n", devptr->minor); #endif /* DETAIL */ return SYSERR; } /* bump buffer pointers/rings to KSEG1 */ ethptr->rxBufs = (struct ethPktBuffer **)(((ulong)ethptr->rxBufs - PAGE_SIZE + sizeof(int)) | KSEG1_BASE); ethptr->txBufs = (struct ethPktBuffer **)(((ulong)ethptr->txBufs - PAGE_SIZE + sizeof(int)) | KSEG1_BASE); ethptr->rxRing = (struct dmaDescriptor *)(((ulong)ethptr->rxRing - PAGE_SIZE + sizeof(int)) | KSEG1_BASE); ethptr->txRing = (struct dmaDescriptor *)(((ulong)ethptr->txRing - PAGE_SIZE + sizeof(int)) | KSEG1_BASE); /* Zero out the buffer pointers and rings */ bzero(ethptr->rxBufs, PAGE_SIZE); bzero(ethptr->txBufs, PAGE_SIZE); bzero(ethptr->rxRing, PAGE_SIZE); bzero(ethptr->txRing, PAGE_SIZE); register_irq(devptr->irq, devptr->intr); enable_irq(devptr->irq); return OK; }
/** * Create a thread to start running a procedure. * @param procaddr procedure address * @param ssize stack size in bytes * @param priority thread priority * @param name name of the thread * @param nargs number of args that follow * @return new thread ID */ tid_typ create(void *procaddr, uint ssize, int priority, char *name, int nargs, ...) { register struct thrent *thrptr; /* thread control block */ intptr_t *saddr; /* stack address */ intptr_t *savargs; /* pointer to arg saving region */ tid_typ tid; /* stores new thread id */ va_list ap; /* points to list of var args */ int pads; /* padding entries in record. */ uint32_t i; void INITRET(void); irqmask im; im = disable(); if (ssize < MINSTK) { ssize = MINSTK; } saddr = stkget(ssize); /* allocate new stack */ tid = thrnew(); /* allocate new thread ID */ if (((SYSERR) == (int)saddr) || (SYSERR == tid)) { restore(im); return SYSERR; } thrcount++; thrptr = &thrtab[tid]; /* setup thread control block for new thread */ thrptr->state = THRSUSP; thrptr->prio = priority; thrptr->stkbase = saddr; thrptr->stklen = ssize; thrptr->stkptr = saddr; strncpy(thrptr->name, name, TNMLEN); thrptr->parent = gettid(); thrptr->hasmsg = FALSE; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; //TEB: this is hardcoded for ARM //This is to enable the timer interrupt thrptr->intmask = 0x10010; /* set up default file descriptors */ /** \todo When the CONSOLE stuff works on fluke-arm, we need to reenable stdio for threads. */ #if 0 thrptr->fdesc[0] = CONSOLE; /* stdin is console */ thrptr->fdesc[1] = CONSOLE; /* stdout is console */ thrptr->fdesc[2] = CONSOLE; /* stderr is console */ #endif /* 0 */ /* Initialize stack with accounting block. */ *saddr = STACKMAGIC; *--saddr = tid; *--saddr = thrptr->stklen; *--saddr = (intptr_t)thrptr->stkbase - thrptr->stklen + sizeof(intptr_t); /* max stack addr */ if (0 == nargs) { pads = 4; } else if (0 == (nargs % 4)) /* pad size to multiple of 4 */ { pads = 0; } else { pads = 4 - (nargs % 4); } for (i = 0; i < pads; i++) { *--saddr = 0; } /* reserve space for all args. */ for (i = nargs; i > 4; i--) { *--saddr = 0; } savargs = saddr; /* build the context record as expected by ctxsw */ for (i = CONTEXT_WORDS; i > 0; i--) { *--saddr = 0; } thrptr->stkptr = saddr; /* address of thread entry point */ saddr[CONTEXT_WORDS - 1] = (intptr_t)procaddr; /* * Store the process's (where to jump to if the procaddr function returns) * return address value */ saddr[CONTEXT_WORDS - 2] = (intptr_t)INITRET; /* * Pass arguments to new processes. * * The ARM Procedure Call Standard (APCS) specifies that the first 4 * arguments be passed via r0-r3 (aka v1-v4). Additional arguments are * located on the stack at ((argnum-4) * 4) * SP (i.e. argument 5 is at * [sp, #0], 6 is at [sp, #4] and so on...) from the perspective of the * callee. */ va_start(ap, nargs); /* Store the first four arguments in the first 4 registers */ for( i = 0; i < 4 && i < nargs; i++ ) { saddr[i] = va_arg(ap, intptr_t); } /* Store the remaining arguments on the stack */ for( i = 4; i < nargs; i++ ) { *savargs++ = va_arg(ap, intptr_t); } va_end(ap); /* check if the parent is in a job */ int jobID = getJobId(thrptr->parent); if(jobID >= 0) { /* If it is, add it. Testing for functionality for now, should be thrown in a seperate function in jobgroup.c */ Job* job; for( i = 0; i < numberOfJobs; i++ ) { job = listOfJobs[i]; if( job->ID == jobID ) { break; } } //Grab the headProcess to assign the groupID to this child process Process* parentProcess = job->headProcess; Process* process = (Process*)malloc(sizeof(Process)); process->groupID = jobID; //Initialize the other properties of the child process process->dataThreadID = i; process->isParentProcess = FALSE; process->dataThread = thrptr; process->nextProcess = NULL; //Grab the last process in the job and assign it's next thread to the newly created child process Process* lastProcessInJob = job->tailProcess; lastProcessInJob->nextProcess = process; //Make the new process the tail thread job->tailProcess = process; } restore(im); return tid; }