Example #1
0
/**
 * 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;
}
Example #2
0
/**
 * 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;
}
Example #3
0
/**
 * 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 = &ethertab[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;
}
Example #4
0
/**
 * 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;
}