//---------------------------------- // // your solution to this question should look something like this // // if you run userprog3.dlx.obj 2, it should output // // A0 // B0 // A1 // A2 // A3 // A4 // A5 // A6 // B1 // A7 // A8 // A9 // B2 // A10 // B3 // A11 // B4 // A12 // B5 // A13 // B6 // A14 // B7 // A15 // B8 // A16 // B9 // A17 // B10 // A18 // B11 // A19 // B12 // A20 // B13 // A21 // B14 // A22 // B15 // A23 // B16 // A24 // B17 // A25 // B18 // A26 // B19 // A27 // B20 // A28 // B21 // A29 // B22 // A0 // B23 // A1 // B24 // A2 // B25 // A3 // B26 // A4 // B27 // A5 // B28 // A6 // B29 // A7 // B0 // A8 // B1 // A9 // B2 // A10 // B3 // A11 // B4 // A12 // B5 // A13 // B6 // A14 // B7 // A15 // B8 // A16 // B9 // A17 // B10 // A18 // B11 // A19 // B12 // A20 // B13 // A21 // B14 // A22 // B15 // A23 // B16 // A24 // B17 // A25 // B18 // A26 // B19 // A27 // B20 // A28 // B21 // A29 // B22 // B23 // B24 // B25 // B26 // B27 // B28 // B29 // make sure you understand the scheduling algorithm works b4 you strart hacking // // You are free to modify this file (and other userprogs) to test your solution // We will not use the same files to test your code. // //---------------------------------------------------------------------------- main (int argc, char *argv[]) { int number, i,j,offset; uint32 handle; sem_t semaphore; char num_str[10], semaphore_str[10]; Printf("\n\n**** argc = %d\n\n\n", argc); switch(argc) { case 2: Printf("timer = %d\n", TimerGet()); number = dstrtol(argv[1], NULL, 10); Printf("Setting number = %d\n", number); for(i=0; i<50; i++) Printf("1"); Printf("timer = %d\n", TimerGet()); semaphore = sem_create(1); ditoa(semaphore, semaphore_str); //Convert the semaphore to a string Printf("timer = %d\n", TimerGet()); for(i=0; i<number; i++) { ditoa(i, num_str); process_create(i,0,"userprog4.dlx.obj", num_str,semaphore_str, NULL); } Printf("timer = %d\n", TimerGet()); yield(); break; case 3: offset = dstrtol(argv[1], NULL, 10); //Get semaphore semaphore = dstrtol(argv[2], NULL, 10); //Get semaphore for(i=0;i<30;i++) { for(j=0;j<50000;j++); Printf("%c%d\n",'A'+offset,i); } for(i=0;i<30;i++) { sem_wait(semaphore); for(j=0;j<50000;j++); Printf("%c%d\n",'A'+offset,i); sem_signal(semaphore); } break; default: Printf("Usage: "); Printf(argv[0]); Printf(" number\n"); Printf("argc = %d\n", argc); exit(); } }
void FlightSimClass::xmit_big_packet(const void *p1, uint8_t n1, const void *p2, uint8_t n2) { if (!enabled || !usb_configuration) return; uint16_t remaining = n1 + n2; if (remaining > 255) return; bool part2 = false; uint8_t remainingPart1 = n1; const uint8_t *dataPtr = (const uint8_t*)p1; bool writeFragmentHeader = false; uint8_t fragmentCounter = 1; tx_noautoflush =1; // don't mess with my data, I'm working on it! if (tx_packet) { // If we have a current packet, fill it with whatever fits uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen > n1) partLen=n1; // copy first part, containing total packet length memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); remainingPart1 -= partLen; tx_packet->index += partLen; if (remainingPart1) { // there still is data from the first part that // will go to the next packet. The boolean variable // part2 remains false remaining = remainingPart1+n2; dataPtr += partLen; } else { // maybe we have space for some data from the second part part2=true; partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; // there is no need here to check whether partLen is // bigger than n2. It's not. If it were, all the data // would have fit in a single packet and xmit_big_packet // would never have been called... remaining = n2; if (partLen) { memcpy(tx_packet->buf + tx_packet->index, p2, partLen); remaining -= partLen; tx_packet->index += partLen; } dataPtr = (const uint8_t*)p2 + partLen; } // Packet padding should not be necessary, as xmit_big_packet // will only be called for data that doesn't fit in a single // packet. So, the previous code should always fill up the // first packet. Right? for (int i = tx_packet->index; i < FLIGHTSIM_TX_SIZE; i++) { tx_packet->buf[i] = 0; } // queue first packet for sending tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; writeFragmentHeader = true; } else { remaining = n1+n2; } while (remaining >0) { while (1) { // get memory for next packet if (usb_tx_packet_count(FLIGHTSIM_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) { break; } } if (!enabled || !usb_configuration) { // teensy disconnected tx_noautoflush = 0; return; } tx_noautoflush = 0; // you can pick up my data, if you like yield(); // do other things and wait for memory to become free tx_noautoflush = 1; // wait, I'm working on the packet data } if (writeFragmentHeader) { tx_packet->buf[0]=(remaining+3 <= FLIGHTSIM_TX_SIZE) ? (byte) remaining+3 : FLIGHTSIM_TX_SIZE; tx_packet->buf[1]=0xff; tx_packet->buf[2]=fragmentCounter++; tx_packet->index=3; } if (!part2) { // we still need to send the first part uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen > remainingPart1) partLen=remainingPart1; memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); dataPtr += partLen; remainingPart1 -= partLen; tx_packet->index += partLen; remaining -= partLen; if (!remainingPart1) { part2=true; dataPtr = (const uint8_t*)p2; } } if (part2) { uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen) { if (partLen > remaining) partLen=remaining; memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); remaining -= partLen; tx_packet->index += partLen; dataPtr += partLen; } } writeFragmentHeader = true; if (tx_packet->index >= FLIGHTSIM_TX_SIZE) { // queue packet for sending tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; } } tx_noautoflush = 0; // data is ready to be transmitted on start of USB token }
/** * usb_sg_wait - synchronously execute scatter/gather request * @io: request block handle, as initialized with usb_sg_init(). * some fields become accessible when this call returns. * Context: !in_interrupt () * * This function blocks until the specified I/O operation completes. It * leverages the grouping of the related I/O requests to get good transfer * rates, by queueing the requests. At higher speeds, such queuing can * significantly improve USB throughput. * * There are three kinds of completion for this function. * (1) success, where io->status is zero. The number of io->bytes * transferred is as requested. * (2) error, where io->status is a negative errno value. The number * of io->bytes transferred before the error is usually less * than requested, and can be nonzero. * (3) cancellation, a type of error with status -ECONNRESET that * is initiated by usb_sg_cancel(). * * When this function returns, all memory allocated through usb_sg_init() or * this call will have been freed. The request block parameter may still be * passed to usb_sg_cancel(), or it may be freed. It could also be * reinitialized and then reused. * * Data Transfer Rates: * * Bulk transfers are valid for full or high speed endpoints. * The best full speed data rate is 19 packets of 64 bytes each * per frame, or 1216 bytes per millisecond. * The best high speed data rate is 13 packets of 512 bytes each * per microframe, or 52 KBytes per millisecond. * * The reason to use interrupt transfers through this API would most likely * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond * could be transferred. That capability is less useful for low or full * speed interrupt endpoints, which allow at most one packet per millisecond, * of at most 8 or 64 bytes (respectively). */ void usb_sg_wait (struct usb_sg_request *io) { int i, entries = io->entries; /* queue the urbs. */ spin_lock_irq (&io->lock); for (i = 0; i < entries && !io->status; i++) { int retval; io->urbs [i]->dev = io->dev; retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); /* after we submit, let completions or cancelations fire; * we handshake using io->status. */ spin_unlock_irq (&io->lock); switch (retval) { /* maybe we retrying will recover */ case -ENXIO: // hc didn't queue this one case -EAGAIN: case -ENOMEM: io->urbs[i]->dev = NULL; retval = 0; i--; yield (); break; /* no error? continue immediately. * * NOTE: to work better with UHCI (4K I/O buffer may * need 3K of TDs) it may be good to limit how many * URBs are queued at once; N milliseconds? */ case 0: cpu_relax (); break; /* fail any uncompleted urbs */ default: io->urbs [i]->dev = NULL; io->urbs [i]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } spin_lock_irq (&io->lock); if (retval && (io->status == 0 || io->status == -ECONNRESET)) io->status = retval; } io->count -= entries - i; if (io->count == 0) complete (&io->complete); spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. * So could the submit loop above ... but it's easier to * solve neither problem than to solve both! */ wait_for_completion (&io->complete); sg_clean (io); }
int infRecursion_cmd(int argc, char **argv) { yield(); infRecursion_cmd(argc, argv); return 0; }
int mypthread_yield() { yield(); }
/* * This routine is responsible for faulting in user pages. * It passes the work off to one of the appropriate routines. * It returns true if the fault was successfully handled. */ static int handle_page_fault(struct pt_regs *regs, int fault_num, int is_page_fault, unsigned long address, int write) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct *vma; unsigned long stack_offset; int fault; int si_code; int is_kernel_mode; pgd_t *pgd; /* on TILE, protection faults are always writes */ if (!is_page_fault) write = 1; is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL); tsk = validate_current(); /* * Check to see if we might be overwriting the stack, and bail * out if so. The page fault code is a relatively likely * place to get trapped in an infinite regress, and once we * overwrite the whole stack, it becomes very hard to recover. */ stack_offset = stack_pointer & (THREAD_SIZE-1); if (stack_offset < THREAD_SIZE / 8) { pr_alert("Potential stack overrun: sp %#lx\n", stack_pointer); show_regs(regs); pr_alert("Killing current process %d/%s\n", tsk->pid, tsk->comm); do_group_exit(SIGKILL); } /* * Early on, we need to check for migrating PTE entries; * see homecache.c. If we find a migrating PTE, we wait until * the backing page claims to be done migrating, then we procede. * For kernel PTEs, we rewrite the PTE and return and retry. * Otherwise, we treat the fault like a normal "no PTE" fault, * rather than trying to patch up the existing PTE. */ pgd = get_current_pgd(); if (handle_migrating_pte(pgd, fault_num, address, is_kernel_mode, write)) return 1; si_code = SEGV_MAPERR; /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. * * NOTE! We MUST NOT take any locks for this case. We may * be in an interrupt or a critical region, and should * only copy the information from the master page table, * nothing more. * * This verifies that the fault happens in kernel space * and that the fault was not a protection fault. */ if (unlikely(address >= TASK_SIZE && !is_arch_mappable_range(address, 0))) { if (is_kernel_mode && is_page_fault && vmalloc_fault(pgd, address) >= 0) return 1; /* * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. */ mm = NULL; /* happy compiler */ vma = NULL; goto bad_area_nosemaphore; } /* * If we're trying to touch user-space addresses, we must * be either at PL0, or else with interrupts enabled in the * kernel, so either way we can re-enable interrupts here. */ local_irq_enable(); mm = tsk->mm; /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault. */ if (in_atomic() || !mm) { vma = NULL; /* happy compiler */ goto bad_area_nosemaphore; } /* * When running in the kernel we expect faults to occur only to * addresses in user space. All other faults represent errors in the * kernel and should generate an OOPS. Unfortunately, in the case of an * erroneous fault occurring in a code path which already holds mmap_sem * we will deadlock attempting to validate the fault against the * address space. Luckily the kernel only validly references user * space from well defined areas of code, which are listed in the * exceptions table. * * As the vast majority of faults will be valid we will only perform * the source reference check when there is a possibility of a deadlock. * Attempt to lock the address space, if we cannot we then validate the * source. If this is invalid we can skip the address space check, * thus avoiding the deadlock. */ if (!down_read_trylock(&mm->mmap_sem)) { if (is_kernel_mode && !search_exception_tables(regs->pc)) { vma = NULL; /* happy compiler */ goto bad_area_nosemaphore; } down_read(&mm->mmap_sem); } vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; if (regs->sp < PAGE_OFFSET) { /* * accessing the stack below sp is always a bug. */ if (address < regs->sp) goto bad_area; } if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: si_code = SEGV_ACCERR; if (fault_num == INT_ITLB_MISS) { if (!(vma->vm_flags & VM_EXEC)) goto bad_area; } else if (write) { #ifdef TEST_VERIFY_AREA if (!is_page_fault && regs->cs == KERNEL_CS) pr_err("WP fault at "REGFMT"\n", regs->eip); #endif if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { if (!is_page_fault || !(vma->vm_flags & VM_READ)) goto bad_area; } survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ fault = handle_mm_fault(mm, vma, address, write); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; else if (fault & VM_FAULT_SIGBUS) goto do_sigbus; BUG(); } if (fault & VM_FAULT_MAJOR) tsk->maj_flt++; else tsk->min_flt++; #if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() /* * If this was an asynchronous fault, * restart the appropriate engine. */ switch (fault_num) { #if CHIP_HAS_TILE_DMA() case INT_DMATLB_MISS: case INT_DMATLB_MISS_DWNCL: case INT_DMATLB_ACCESS: case INT_DMATLB_ACCESS_DWNCL: __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__REQUEST_MASK); break; #endif #if CHIP_HAS_SN_PROC() case INT_SNITLB_MISS: case INT_SNITLB_MISS_DWNCL: __insn_mtspr(SPR_SNCTL, __insn_mfspr(SPR_SNCTL) & ~SPR_SNCTL__FRZPROC_MASK); break; #endif } #endif up_read(&mm->mmap_sem); return 1; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ bad_area: up_read(&mm->mmap_sem); bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (!is_kernel_mode) { /* * It's possible to have interrupts off here. */ local_irq_enable(); force_sig_info_fault(SIGSEGV, si_code, address, fault_num, tsk); return 0; } no_context: /* Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) return 0; /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ bust_spinlocks(1); /* FIXME: no lookup_address() yet */ #ifdef SUPPORT_LOOKUP_ADDRESS if (fault_num == INT_ITLB_MISS) { pte_t *pte = lookup_address(address); if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) pr_crit("kernel tried to execute" " non-executable page - exploit attempt?" " (uid: %d)\n", current->uid); } #endif if (address < PAGE_SIZE) pr_alert("Unable to handle kernel NULL pointer dereference\n"); else pr_alert("Unable to handle kernel paging request\n"); pr_alert(" at virtual address "REGFMT", pc "REGFMT"\n", address, regs->pc); show_regs(regs); if (unlikely(tsk->pid < 2)) { panic("Kernel page fault running %s!", tsk->pid ? "init" : "the idle task"); } /* * More FIXME: we should probably copy the i386 here and * implement a generic die() routine. Not today. */ #ifdef SUPPORT_DIE die("Oops", regs); #endif bust_spinlocks(1); do_group_exit(SIGKILL); /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ out_of_memory: up_read(&mm->mmap_sem); if (is_global_init(tsk)) { yield(); down_read(&mm->mmap_sem); goto survive; } pr_alert("VM: killing process %s\n", tsk->comm); if (!is_kernel_mode) do_group_exit(SIGKILL); goto no_context; do_sigbus: up_read(&mm->mmap_sem); /* Kernel mode? Handle exceptions or die */ if (is_kernel_mode) goto no_context; force_sig_info_fault(SIGBUS, BUS_ADRERR, address, fault_num, tsk); return 0; }
/** * ubi_io_read - read data from a physical eraseblock. * @ubi: UBI device description object * @buf: buffer where to store the read data * @pnum: physical eraseblock number to read from * @offset: offset within the physical eraseblock from where to read * @len: how many bytes to read * * This function reads data from offset @offset of physical eraseblock @pnum * and stores the read data in the @buf buffer. The following return codes are * possible: * * o %0 if all the requested data were successfully read; * o %UBI_IO_BITFLIPS if all the requested data were successfully read, but * correctable bit-flips were detected; this is harmless but may indicate * that this eraseblock may become bad soon (but do not have to); * o %-EBADMSG if the MTD subsystem reported about data integrity problems, for * example it can be an ECC error in case of NAND; this most probably means * that the data is corrupted; * o %-EIO if some I/O error occurred; * o other negative error codes in case of other errors. */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { int err, retries = 0; size_t read; loff_t addr; dbg_io("read %d bytes from PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(len > 0); err = paranoid_check_not_bad(ubi, pnum); if (err) return err > 0 ? -EINVAL : err; addr = (loff_t)pnum * ubi->peb_size + offset; retry: err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); if (err == -EUCLEAN) err = 0; //added by Elvis, for ignore EUCLEAN if (err) { if (err == -EUCLEAN) { /* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless. */ ubi_msg("fixable bit-flip detected at PEB %d", pnum); ubi_assert(len == read); return UBI_IO_BITFLIPS; } if (read != len && retries++ < UBI_IO_RETRIES) { dbg_io("error %d while reading %d bytes from PEB %d:%d, " "read only %zd bytes, retry", err, len, pnum, offset, read); yield(); goto retry; } ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); ubi_dbg_dump_stack(); /* * The driver should never return -EBADMSG if it failed to read * all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ if (read != len && err == -EBADMSG) { ubi_assert(0); printk("%s[%d] not here\n", __func__, __LINE__); /* err = -EIO; */ } } else { ubi_assert(len == read); if (ubi_dbg_is_bitflip()) { dbg_msg("bit-flip (emulated)"); err = UBI_IO_BITFLIPS; } } return err; }
/* * This routine handles page faults. It determines the problem, and * then passes it off to one of the appropriate routines. * * error_code: * bit 0 == 0 means no page found, 1 means protection fault * bit 1 == 0 means read, 1 means write * * If this routine detects a bad access, it returns 1, otherwise it * returns 0. */ int do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { struct mm_struct *mm = current->mm; struct vm_area_struct * vma; int write, fault; #ifdef DEBUG printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", regs->sr, regs->pc, address, error_code, current->mm->pgd); #endif /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_interrupt() || !mm) goto no_context; down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) goto map_err; if (vma->vm_flags & VM_IO) goto acc_err; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto map_err; if (user_mode(regs)) { /* Accessing the stack below usp is always a bug. The "+ 256" is there due to some instructions doing pre-decrement on the stack and that doesn't show up until later. */ if (address + 256 < rdusp()) goto map_err; } if (expand_stack(vma, address)) goto map_err; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: #ifdef DEBUG printk("do_page_fault: good_area\n"); #endif write = 0; switch (error_code & 3) { default: /* 3: write, present */ /* fall through */ case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) goto acc_err; write++; break; case 1: /* read, present */ goto acc_err; case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto acc_err; } /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ survive: fault = handle_mm_fault(mm, vma, address, write); #ifdef DEBUG printk("handle_mm_fault returns %d\n",fault); #endif switch (fault) { case VM_FAULT_MINOR: current->min_flt++; break; case VM_FAULT_MAJOR: current->maj_flt++; break; case VM_FAULT_SIGBUS: goto bus_err; default: goto out_of_memory; } up_read(&mm->mmap_sem); return 0; /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { yield(); down_read(&mm->mmap_sem); goto survive; } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); no_context: current->thread.signo = SIGBUS; current->thread.faddr = address; return send_fault_sig(regs); bus_err: current->thread.signo = SIGBUS; current->thread.code = BUS_ADRERR; current->thread.faddr = address; goto send_sig; map_err: current->thread.signo = SIGSEGV; current->thread.code = SEGV_MAPERR; current->thread.faddr = address; goto send_sig; acc_err: current->thread.signo = SIGSEGV; current->thread.code = SEGV_ACCERR; current->thread.faddr = address; send_sig: up_read(&mm->mmap_sem); return send_fault_sig(regs); }
void imx233_lradc_wait_channel(int channel) { /* wait for completion */ while(!(HW_LRADC_CTRL1 & HW_LRADC_CTRL1__LRADCx_IRQ(channel))) yield(); }
/** * do_sync_erase - synchronously erase a physical eraseblock. * @ubi: UBI device description object * @pnum: the physical eraseblock number to erase * * This function synchronously erases physical eraseblock @pnum and returns * zero in case of success and a negative error code in case of failure. If * %-EIO is returned, the physical eraseblock most probably went bad. */ static int do_sync_erase(struct ubi_device *ubi, int pnum) { int err, retries = 0; struct erase_info ei; wait_queue_head_t wq; dbg_io("erase PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); if (ubi->ro_mode) { ubi_err("read-only mode"); return -EROFS; } retry: init_waitqueue_head(&wq); memset(&ei, 0, sizeof(struct erase_info)); ei.mtd = ubi->mtd; ei.addr = (loff_t)pnum * ubi->peb_size; ei.len = ubi->peb_size; ei.callback = erase_callback; ei.priv = (unsigned long)&wq; err = mtd_erase(ubi->mtd, &ei); atomic_inc(&ubi->ec_count); //MTK if (err) { if (retries++ < UBI_IO_RETRIES) { ubi_warn("error %d while erasing PEB %d, retry", err, pnum); yield(); goto retry; } ubi_err("cannot erase PEB %d, error %d", pnum, err); dump_stack(); return err; } err = wait_event_interruptible(wq, ei.state == MTD_ERASE_DONE || ei.state == MTD_ERASE_FAILED); if (err) { ubi_err("interrupted PEB %d erasure", pnum); return -EINTR; } if (ei.state == MTD_ERASE_FAILED) { if (retries++ < UBI_IO_RETRIES) { ubi_warn("error while erasing PEB %d, retry", pnum); yield(); goto retry; } ubi_err("cannot erase PEB %d", pnum); dump_stack(); return -EIO; } err = ubi_self_check_all_ff(ubi, pnum, 0, ubi->peb_size); if (err) return err; if (ubi_dbg_is_erase_failure(ubi)) { ubi_err("cannot erase PEB %d (emulated)", pnum); return -EIO; } return 0; }
void TickerTask::kill(){ // end this task. clear all data in scheduler table clear(); yield(); };
/** * ubi_io_read - read data from a physical eraseblock. * @ubi: UBI device description object * @buf: buffer where to store the read data * @pnum: physical eraseblock number to read from * @offset: offset within the physical eraseblock from where to read * @len: how many bytes to read * * This function reads data from offset @offset of physical eraseblock @pnum * and stores the read data in the @buf buffer. The following return codes are * possible: * * o %0 if all the requested data were successfully read; * o %UBI_IO_BITFLIPS if all the requested data were successfully read, but * correctable bit-flips were detected; this is harmless but may indicate * that this eraseblock may become bad soon (but do not have to); * o %-EBADMSG if the MTD subsystem reported about data integrity problems, for * example it can be an ECC error in case of NAND; this most probably means * that the data is corrupted; * o %-EIO if some I/O error occurred; * o other negative error codes in case of other errors. */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { int err, retries = 0; size_t read; loff_t addr; dbg_io("read %d bytes from PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(len > 0); err = self_check_not_bad(ubi, pnum); if (err) return err; /* * Deliberately corrupt the buffer to improve robustness. Indeed, if we * do not do this, the following may happen: * 1. The buffer contains data from previous operation, e.g., read from * another PEB previously. The data looks like expected, e.g., if we * just do not read anything and return - the caller would not * notice this. E.g., if we are reading a VID header, the buffer may * contain a valid VID header from another PEB. * 2. The driver is buggy and returns us success or -EBADMSG or * -EUCLEAN, but it does not actually put any data to the buffer. * * This may confuse UBI or upper layers - they may think the buffer * contains valid data while in fact it is just old data. This is * especially possible because UBI (and UBIFS) relies on CRC, and * treats data as correct even in case of ECC errors if the CRC is * correct. * * Try to prevent this situation by changing the first byte of the * buffer. */ *((uint8_t *)buf) ^= 0xFF; addr = (loff_t)pnum * ubi->peb_size + offset; retry: err = mtd_read(ubi->mtd, addr, len, &read, buf); if (err) { const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : ""; if (mtd_is_bitflip(err)) { /* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless. * * We do not report about it here unless debugging is * enabled. A corresponding message will be printed * later, when it is has been scrubbed. */ ubi_msg("fixable bit-flip detected at PEB %d", pnum); ubi_assert(len == read); return UBI_IO_BITFLIPS; } if (retries++ < UBI_IO_RETRIES) { ubi_warn("error %d%s while reading %d bytes from PEB %d:%d, read only %zd bytes, retry", err, errstr, len, pnum, offset, read); yield(); goto retry; } ubi_err("error %d%s while reading %d bytes from PEB %d:%d, read %zd bytes", err, errstr, len, pnum, offset, read); dump_stack(); /* * The driver should never return -EBADMSG if it failed to read * all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ if (read != len && mtd_is_eccerr(err)) { ubi_assert(0); err = -EIO; } } else { ubi_assert(len == read); if (ubi_dbg_is_bitflip(ubi)) { dbg_gen("bit-flip (emulated)"); err = UBI_IO_BITFLIPS; } } return err; }
void adcInit(void) { GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; AQ_NOTICE("ADC init\n"); memset((void *)&adcData, 0, sizeof(adcData)); // energize mag's set/reset circuit adcData.magSetReset = digitalInit(GPIOE, GPIO_Pin_10, 1); // use auto-zero function of gyros adcData.rateAutoZero = digitalInit(GPIOE, GPIO_Pin_8, 0); // bring ACC's SELF TEST line low adcData.accST = digitalInit(GPIOE, GPIO_Pin_12, 0); // bring ACC's SCALE line low (ADXL3X5 requires this line be tied to GND or left floating) adcData.accScale = digitalInit(GPIOC, GPIO_Pin_15, 0); GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOC, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); adcData.sample = ADC_SAMPLES - 1; // Use STM32F4's Triple Regular Simultaneous Mode capable of ~ 6M samples per second DMA_DeInit(ADC_DMA_STREAM); DMA_InitStructure.DMA_Channel = ADC_DMA_CHANNEL; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)adcDMAData.adc123Raw1; DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)0x40012308); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = ADC_CHANNELS * 3 * 2; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(ADC_DMA_STREAM, &DMA_InitStructure); DMA_ITConfig(ADC_DMA_STREAM, DMA_IT_HT | DMA_IT_TC, ENABLE); DMA_ClearITPendingBit(ADC_DMA_STREAM, ADC_DMA_FLAGS); DMA_Cmd(ADC_DMA_STREAM, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = ADC_DMA_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // ADC Common Init ADC_CommonStructInit(&ADC_CommonInitStructure); ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; ADC_CommonInit(&ADC_CommonInitStructure); // ADC1 configuration ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 16; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGX, 1, ADC_SAMPLE_TIME); // magX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGX, 2, ADC_SAMPLE_TIME); // magX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGX, 3, ADC_SAMPLE_TIME); // magX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGX, 4, ADC_SAMPLE_TIME); // magX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGY, 5, ADC_SAMPLE_TIME); // magY ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGY, 6, ADC_SAMPLE_TIME); // magY ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGY, 7, ADC_SAMPLE_TIME); // magY ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGY, 8, ADC_SAMPLE_TIME); // magY ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGZ, 9, ADC_SAMPLE_TIME); // magZ ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGZ, 10, ADC_SAMPLE_TIME); // magZ ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGZ, 11, ADC_SAMPLE_TIME); // magZ ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_MAGZ, 12, ADC_SAMPLE_TIME); // magZ ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_RATEX, 13, ADC_SAMPLE_TIME); // rateX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_RATEX, 14, ADC_SAMPLE_TIME); // rateX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_RATEX, 15, ADC_SAMPLE_TIME); // rateX ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_RATEX, 16, ADC_SAMPLE_TIME); // rateX // Enable ADC1 DMA since ADC1 is the Master ADC_DMACmd(ADC1, ENABLE); // ADC2 configuration ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 16; ADC_Init(ADC2, &ADC_InitStructure); ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_RATEY, 1, ADC_SAMPLE_TIME); // rateY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_RATEY, 2, ADC_SAMPLE_TIME); // rateY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_RATEY, 3, ADC_SAMPLE_TIME); // rateY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_RATEY, 4, ADC_SAMPLE_TIME); // rateY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCX, 5, ADC_SAMPLE_TIME); // accX ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCX, 6, ADC_SAMPLE_TIME); // accX ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCX, 7, ADC_SAMPLE_TIME); // accX ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCX, 8, ADC_SAMPLE_TIME); // accX ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCY, 9, ADC_SAMPLE_TIME); // accY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCY, 10, ADC_SAMPLE_TIME); // accY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCY, 11, ADC_SAMPLE_TIME); // accY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCY, 12, ADC_SAMPLE_TIME); // accY ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCZ, 13, ADC_SAMPLE_TIME); // accZ ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCZ, 14, ADC_SAMPLE_TIME); // accZ ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCZ, 15, ADC_SAMPLE_TIME); // accZ ADC_RegularChannelConfig(ADC2, ADC_CHANNEL_ACCZ, 16, ADC_SAMPLE_TIME); // accZ // ADC3 configuration ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 16; ADC_Init(ADC3, &ADC_InitStructure); ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_RATEZ, 1, ADC_SAMPLE_TIME); // rateZ ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_RATEZ, 2, ADC_SAMPLE_TIME); // rateZ ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_RATEZ, 3, ADC_SAMPLE_TIME); // rateZ ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_RATEZ, 4, ADC_SAMPLE_TIME); // rateZ ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_TEMP1, 5, ADC_SAMPLE_TIME); // temp1 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_TEMP2, 6, ADC_SAMPLE_TIME); // temp2 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES1, 7, ADC_SAMPLE_TIME); // pressure1 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES1, 8, ADC_SAMPLE_TIME); // pressure1 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES1, 9, ADC_SAMPLE_TIME); // pressure1 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES1, 10, ADC_SAMPLE_TIME); // pressure1 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_VIN, 11, ADC_SAMPLE_TIME); // Vin ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_TEMP3, 12, ADC_SAMPLE_TIME); // temp3 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES2, 13, ADC_SAMPLE_TIME); // pressure2 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES2, 14, ADC_SAMPLE_TIME); // pressure2 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES2, 15, ADC_SAMPLE_TIME); // pressure2 ADC_RegularChannelConfig(ADC3, ADC_CHANNEL_PRES2, 16, ADC_SAMPLE_TIME); // pressure2 // Enable DMA request after last transfer (Multi-ADC mode) ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); // Enable ADC_Cmd(ADC1, ENABLE); ADC_Cmd(ADC2, ENABLE); ADC_Cmd(ADC3, ENABLE); adcData.adcFlag = CoCreateFlag(1, 0); adcTaskStack = aqStackInit(ADC_STACK_SIZE, "ADC"); adcData.adcTask = CoCreateTask(adcTaskCode, (void *)0, ADC_PRIORITY, &adcTaskStack[ADC_STACK_SIZE-1], ADC_STACK_SIZE); // Start ADC1 Software Conversion ADC_SoftwareStartConv(ADC1); yield(100); // set initial temperatures adcData.temp1 = adcIDGVoltsToTemp(adcData.voltages[ADC_VOLTS_TEMP1]); adcData.temp2 = adcIDGVoltsToTemp(adcData.voltages[ADC_VOLTS_TEMP2]); adcData.temp3 = adcT1VoltsToTemp(adcData.voltages[ADC_VOLTS_TEMP3]); analogData.vIn = adcVsenseToVin(adcData.voltages[ADC_VOLTS_VIN]); adcCalibOffsets(); }
void Console::wait_for_enter_keypress() { while (fgetc(stdin) != '\n') yield(); }
void Client::execute() { if ( DEBUG > 1 ) { printf( "Executing client...\n" ); } int choice; // Infinite execution loop while( true ) { //printf( "Client %d has %d/%d units in state %d.\n", id, allocated, requested, state ); yield(); if ( state == 1 ) { // Normal operation if ( crashed ) { mutex.lock(); crashed = false; mutex.unlock(); report( allocated ); continue; } if ( allocated ) { choice = randint(1,2); switch( choice ) { case 1: use(); break; case 2: release(); break; } } else { choice = randint(1,2); switch( choice ) { case 1: work(); break; case 2: request(randint(1,REQUEST_MAX)); break; } } } else if ( state == 2 ) { // Requesting units if ( crashed ) { mutex.lock(); crashed = false; mutex.unlock(); report( allocated ); if ( allocated ) { mutex.lock(); state = 3; mutex.unlock(); } else { request( requested ); } } } else if ( state == 3 ) { // Crash recovery if ( crashed ) { mutex.lock(); crashed = false; mutex.unlock(); report( allocated ); } if ( allocated ) { release(); } else { request(requested); } } } }
static void __init handle_initrd(void) { int error; int pid; real_root_dev = new_encode_dev(ROOT_DEV); create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); root_fd = sys_open("/", 0, 0); old_fd = sys_open("/old", 0, 0); /* move initrd over / and chdir/chroot in initrd root */ sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); /* * In case that a resume from disk is carried out by linuxrc or one of * its children, we need to tell the freezer not to wait for us. */ current->flags |= PF_FREEZER_SKIP; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) while (pid != sys_wait4(-1, NULL, 0, NULL)) yield(); current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ sys_fchdir(old_fd); sys_mount("/", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ sys_fchdir(root_fd); sys_chroot("."); sys_close(old_fd); sys_close(root_fd); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); return; } ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); if (!error) printk("okay\n"); else { int fd = sys_open("/dev/root.old", O_RDWR, 0); if (error == -ENOENT) printk("/initrd does not exist. Ignored.\n"); else printk("failed\n"); printk(KERN_NOTICE "Unmounting old root\n"); sys_umount("/old", MNT_DETACH); printk(KERN_NOTICE "Trying to free ramdisk memory ... "); if (fd < 0) { error = fd; } else { error = sys_ioctl(fd, BLKFLSBUF, 0); sys_close(fd); } printk(!error ? "okay\n" : "failed\n"); } }
int usb_serial_write(const void *buffer, uint32_t size) { #if 1 uint32_t len; uint32_t wait_count; const uint8_t *src = (const uint8_t *)buffer; uint8_t *dest; tx_noautoflush = 1; while (size > 0) { if (!tx_packet) { wait_count = 0; while (1) { if (!usb_configuration) { tx_noautoflush = 0; return -1; } if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_noautoflush = 1; tx_packet = usb_malloc(); if (tx_packet) break; tx_noautoflush = 0; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; return -1; } yield(); } } transmit_previous_timeout = 0; len = CDC_TX_SIZE - tx_packet->index; if (len > size) len = size; dest = tx_packet->buf + tx_packet->index; tx_packet->index += len; size -= len; while (len-- > 0) *dest++ = *src++; if (tx_packet->index < CDC_TX_SIZE) { usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; } else { tx_packet->len = CDC_TX_SIZE; usb_cdc_transmit_flush_timer = 0; usb_tx(CDC_TX_ENDPOINT, tx_packet); tx_packet = NULL; } } tx_noautoflush = 0; return 0; #endif #if 0 const uint8_t *p = (const uint8_t *)buffer; int r; while (size) { r = usb_serial_putchar(*p++); if (r < 0) return -1; size--; } return 0; #endif }
/* * VERY simple elf loader. * * Make stupid assumptions like linear allocation of segments, in order */ void elf_load(void *base, size_t size) { elf_file_header_t *f; elf_program_header_t *ph; void *alloc_to = (void *)0; int i; f = base; if (f->magic != ELF_MAGIC) { kprint("Bad ELF magic found"); return; } if (f->type != ELF_TYPE_EXEC && f->type != ELF_TYPE_DYN_EXEC) { kprintf("Unknown ELF executable type (%x)\n", f->type); return; } for (i=0; i<(f->ph_entry_count); i++) { ph = base + f->program_head_offset + (f->ph_entry_size * i); if (ph->segment_type == ELF_PROG_SEG_LOAD) { int pages_needed = ((ph->mem_size) / PAGE_SIZE) + 1; void * pages[pages_needed]; void *abase = ph->virtual_addr; int i; /* Show what we are loading if debugging */ if (ph->flags & ELF_PS_READ) kprint("R"); if (ph->flags & ELF_PS_WRITE) kprint("W"); if (ph->flags & ELF_PS_EXEC) kprint("X"); kprintf("elf:\t0x%x(0x%x), mem 0x%x, dsk 0x%x, aln 0x%x\n", ph->phys_addr, ph->virtual_addr, ph->mem_size, ph->file_size, ph->alignment); /* Don't double allocate pages, no matter how * stupid and broken the ELF header is */ while (abase < alloc_to) { pages_needed--; abase += PAGE_SIZE; } alloc_to = abase + (PAGE_SIZE * pages_needed) - 1; kgetpages(pages_needed, pages); for (i = 0; i < pages_needed; i++) { paging_add_to_dir(kernel_page_dir, abase, pages[i]); abase += PAGE_SIZE; } kmemcpy(ph->virtual_addr, base+(ph->offset), ph->file_size); if (ph->file_size < ph->mem_size) { kmemset((ph->virtual_addr)+(ph->file_size), 0, (ph->mem_size - ph->file_size)); } } } #if 0 /* 2008-07-15: THIS IS BAD! * tempstack should NOT be used by things outside of inth.S or mem.S! * even that is going to be phased out... * * new_kthread is a much more sane way to be doing this even to bootstrap * usermode... */ /* Splinter, but give the tempstack, so we have to yield to make * sure that it is freed again before we are called again in this * thread */ splinter(f->entry, tempstack+PAGE_SIZE); yield(); #endif new_kthread(f->entry); }
static int try_to_freeze_tasks(int freeze_user_space) { struct task_struct *g, *p; unsigned long end_time; unsigned int todo; struct timeval start, end; s64 elapsed_csecs64; unsigned int elapsed_csecs; do_gettimeofday(&start); end_time = jiffies + TIMEOUT; do { todo = 0; read_lock(&tasklist_lock); do_each_thread(g, p) { if (frozen(p) || !freezeable(p)) continue; if (!freeze_task(p, freeze_user_space)) continue; /* * Now that we've done set_freeze_flag, don't * perturb a task in TASK_STOPPED or TASK_TRACED. * It is "frozen enough". If the task does wake * up, it will immediately call try_to_freeze. */ if (!task_is_stopped_or_traced(p) && !freezer_should_skip(p)) todo++; } while_each_thread(g, p); read_unlock(&tasklist_lock); yield(); /* Yield is okay here */ if (time_after(jiffies, end_time)) break; } while (todo); do_gettimeofday(&end); elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); do_div(elapsed_csecs64, NSEC_PER_SEC / 100); elapsed_csecs = elapsed_csecs64; if (todo) { /* This does not unfreeze processes that are already frozen * (we have slightly ugly calling convention in that respect, * and caller must call thaw_processes() if something fails), * but it cleans up leftover PF_FREEZE requests. */ printk("\n"); printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " "(%d tasks refusing to freeze):\n", elapsed_csecs / 100, elapsed_csecs % 100, todo); show_state(); read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); if (freezing(p) && !freezer_should_skip(p)) printk(KERN_ERR " %s\n", p->comm); cancel_freezing(p); task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); } else {
void FawkesMainThread::loop() { if ( ! __thread_manager->timed_threads_exist() ) { __multi_logger->log_debug("FawkesMainThread", "No timed threads exist, waiting"); try { __thread_manager->wait_for_timed_threads(); __multi_logger->log_debug("FawkesMainThread", "Timed threads have been added, " "running main loop now"); } catch (InterruptedException &e) { __multi_logger->log_debug("FawkesMainThread", "Waiting for timed threads interrupted"); return; } } __plugin_manager->lock(); try { if ( __time_wait ) { __time_wait->mark_start(); } __loop_start->stamp_systime(); CancelState old_state; set_cancel_state(CANCEL_DISABLED, &old_state); __mainloop_mutex->lock(); if (unlikely(__mainloop_thread != NULL)) { try { if (likely(__mainloop_thread != NULL)) { __mainloop_thread->wakeup(__mainloop_barrier); __mainloop_barrier->wait(); } } catch (Exception &e) { __multi_logger->log_warn("FawkesMainThread", e); } } else { safe_wake(BlockedTimingAspect::WAKEUP_HOOK_PRE_LOOP, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_ACQUIRE, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PREPARE, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PROCESS, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_WORLDSTATE, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_THINK, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SKILL, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_ACT, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_ACT_EXEC, __max_thread_time_usec); safe_wake(BlockedTimingAspect::WAKEUP_HOOK_POST_LOOP, __max_thread_time_usec); } __mainloop_mutex->unlock(); set_cancel_state(old_state); test_cancel(); __thread_manager->try_recover(__recovered_threads); if ( ! __recovered_threads.empty() ) { // threads have been recovered! //__multi_logger->log_error(name(), "Threads recovered %zu", __recovered_threads.size()); if(__enable_looptime_warnings) { if ( __recovered_threads.size() == 1 ) { __multi_logger->log_warn("FawkesMainThread", "The thread %s could be " "recovered and resumes normal operation", __recovered_threads.front().c_str()); } else { std::string s; for (std::list<std::string>::iterator i = __recovered_threads.begin(); i != __recovered_threads.end(); ++i) { s += *i + " "; } __multi_logger->log_warn("FawkesMainThread", "The following threads could be " "recovered and resumed normal operation: %s", s.c_str()); } } __recovered_threads.clear(); } if (__desired_loop_time_sec > 0) { __loop_end->stamp_systime(); float loop_time = *__loop_end - __loop_start; if(__enable_looptime_warnings) { // give some extra 10% to eliminate frequent false warnings due to regular // time jitter (TimeWait might not be all that precise) if (loop_time > 1.1 * __desired_loop_time_sec) { __multi_logger->log_warn("FawkesMainThread", "Loop time exceeded, " "desired: %f sec (%u usec), actual: %f sec", __desired_loop_time_sec, __desired_loop_time_usec, loop_time); } } } __plugin_manager->unlock(); if ( __time_wait ) { __time_wait->wait_systime(); } else { yield(); } } catch (Exception &e) { __multi_logger->log_warn("FawkesMainThread", "Exception caught while executing default main " "loop, ignoring."); __multi_logger->log_warn("FawkesMainThread", e); } catch (std::exception &e) { __multi_logger->log_warn("FawkesMainThread", "STL Exception caught while executing default main " "loop, ignoring. (what: %s)", e.what()); } // catch ... is not a good idea, would catch cancellation exception // at least needs to be rethrown. }
void run(){ while(!threadShouldExit()){ loop(); yield(); } }
void do_work(s_coro<void>::yield_type & real_yield) { for (int i = 0; i < 10; ++ i) { std::cout << "zzz" << std::endl; yield(real_yield, 10); } }
ssize_t read_wrap(int fd, void * buf, size_t count) { // off_t offset; int status; int size = sizeof(buf); int bytes_read; struct aiocb *aiocbp = malloc(sizeof(struct aiocb)); // allocate structure if (aiocbp == NULL) { do { perror("malloc issue"); exit(EXIT_FAILURE); } while (0); } aiocbp->aio_fildes = fd; // set the file if (aiocbp->aio_fildes == -1){ do { perror("opened on file"); exit(EXIT_FAILURE); } while (0); } aiocbp->aio_buf = buf; //malloc(size); // allocate for the buffer if (aiocbp->aio_buf == NULL) { do { perror("malloc issue"); exit(EXIT_FAILURE); } while (0); } aiocbp->aio_nbytes = size; // number of bytes to read aiocbp->aio_reqprio = 0; // no additional priority set aiocbp->aio_offset = SEEK_CUR; // offset for the file aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE; // correct for polling status = aio_read(aiocbp); // start the read if (status == -1) { do { perror("aio_read issue"); exit(EXIT_FAILURE); } while (0); } while (status == EINPROGRESS) { printf("Async request still going. \n"); yield(); status = aio_error(aiocbp); } switch (status) { case 0: printf("I/O succeeded\n"); bytes_read = aio_return(aiocbp); //offset = lseek(fd, size, SEEK_CUR); // set the new offset after the read //strcpy(buf, aiocbp->aio_buf); break; case ECANCELED: printf("Canceled\n"); break; default: do { perror("aio_error"); exit(EXIT_FAILURE); } while (0); break; } return bytes_read; }
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct *vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; const int field = sizeof(unsigned long) * 2; siginfo_t info; int fault; info.si_code = SEGV_MAPERR; /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. * * NOTE! We MUST NOT take any locks for this case. We may * be in an interrupt or a critical region, and should * only copy the information from the master page table, * nothing more. */ if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END)) goto vmalloc_fault; #ifdef MODULE_START if (unlikely(address >= MODULE_START && address < MODULE_END)) goto vmalloc_fault; #endif /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_atomic() || !mm) goto bad_area_nosemaphore; down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: info.si_code = SEGV_ACCERR; if (write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) goto bad_area; } survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ fault = handle_mm_fault(mm, vma, address, write); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) goto out_of_memory; else if (fault & VM_FAULT_SIGBUS) goto do_sigbus; BUG(); } if (fault & VM_FAULT_MAJOR) tsk->maj_flt++; else tsk->min_flt++; up_read(&mm->mmap_sem); return; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ bad_area: up_read(&mm->mmap_sem); bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; info.si_signo = SIGSEGV; info.si_errno = 0; /* info.si_code has been set above */ info.si_addr = (void __user *) address; force_sig_info(SIGSEGV, &info, tsk); return; } no_context: /* Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) { current->thread.cp0_baduaddr = address; return; } /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ bust_spinlocks(1); printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", 0, field, address, field, regs->cp0_epc, field, regs->regs[3]); die("Oops", regs); /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ out_of_memory: up_read(&mm->mmap_sem); if (is_global_init(tsk)) { yield(); down_read(&mm->mmap_sem); goto survive; } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) do_group_exit(SIGKILL); goto no_context; do_sigbus: up_read(&mm->mmap_sem); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) goto no_context; else /* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ tsk->thread.cp0_badvaddr = address; info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; info.si_addr = (void __user *) address; force_sig_info(SIGBUS, &info, tsk); return; vmalloc_fault: { /* * Synchronize this task's top level page-table * with the 'reference' page table. * * Do _not_ use "tsk" here. We might be inside * an interrupt in the middle of a task switch.. */ int offset = __pgd_offset(address); pgd_t *pgd, *pgd_k; pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; pte_t *pte_k; pgd = (pgd_t *) pgd_current + offset; pgd_k = init_mm.pgd + offset; if (!pgd_present(*pgd_k)) goto no_context; set_pgd(pgd, *pgd_k); pud = pud_offset(pgd, address); pud_k = pud_offset(pgd_k, address); if (!pud_present(*pud_k)) goto no_context; pmd = pmd_offset(pud, address); pmd_k = pmd_offset(pud_k, address); if (!pmd_present(*pmd_k)) goto no_context; set_pmd(pmd, *pmd_k); pte_k = pte_offset_kernel(pmd_k, address); if (!pte_present(*pte_k)) goto no_context; return; } }
//PAGEBREAK: 41 void trap(struct trapframe *tf) { if (tf->trapno == T_SYSCALL) { if (proc->killed) { exit(); } proc->tf = tf; syscall(); if (proc->killed) { exit(); } return; } switch (tf->trapno) { case T_IRQ0 + IRQ_TIMER: if (cpu->id == 0) { acquire(&tickslock); ticks++; wakeup(&ticks); release(&tickslock); } lapiceoi(); break; case T_IRQ0 + IRQ_IDE: ideintr(); lapiceoi(); break; case T_IRQ0 + IRQ_IDE+1: // Bochs generates spurious IDE1 interrupts. break; case T_IRQ0 + IRQ_KBD: kbdintr(); lapiceoi(); break; case T_IRQ0 + IRQ_COM1: uartintr(); lapiceoi(); break; case T_IRQ0 + 7: case T_IRQ0 + IRQ_SPURIOUS: cprintf("cpu%d: spurious interrupt at %x:%x\n", cpu->id, tf->cs, tf->eip); lapiceoi(); break; //PAGEBREAK: 13 default: if (proc == 0 || (tf->cs & 3) == 0) { // In kernel, it must be our mistake. cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", tf->trapno, cpu->id, tf->eip, rcr2()); panic("trap"); } // In user space, assume process misbehaved. cprintf("pid %d %s: trap %d err %d on cpu %d " "eip 0x%x addr 0x%x--kill proc\n", proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, rcr2()); proc->killed = 1; } // Force process exit if it has been killed and is in user space. // (If it is still executing in the kernel, let it keep running // until it gets to the regular system call return.) if (proc && proc->killed && (tf->cs & 3) == DPL_USER) { exit(); } // Force process to give up CPU on clock tick. // If interrupts were on while locks held, would need to check nlock. if (proc && proc->state == RUNNING && tf->trapno == T_IRQ0 + IRQ_TIMER) { yield(); } // Check if the process has been killed since we yielded if (proc && proc->killed && (tf->cs & 3) == DPL_USER) { exit(); } }
void rtw_yield_os() { #ifdef PLATFORM_LINUX yield(); #endif }
/*Finally, recall from the first assignment that we need a way to prevent the main thread from terminating prematurely if there are other threads still running. Implement a solution to this problem in scheduler_end. (Hint: you may find the is_empty queue function useful).*/ void scheduler_end(){ while(is_empty(&ready_list) == 0){ yield(); } };
static int __ps2_command(int aux, int command, u8 *param) { int ret2; int receive = (command >> 8) & 0xf; int send = (command >> 12) & 0xf; // Disable interrupts and keyboard/mouse. u8 ps2ctr = GET_EBDA(ps2ctr); u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS) & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT)); dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr); int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); if (ret) return ret; // Flush any interrupts already pending. yield(); // Enable port command is being sent to. if (aux) newctr &= ~I8042_CTR_AUXDIS; else newctr &= ~I8042_CTR_KBDDIS; ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); if (ret) goto fail; if (command == ATKBD_CMD_RESET_BAT) { // Reset is special wrt timeouts and bytes received. // Send command. ret = ps2_sendbyte(aux, command, 1000); if (ret) goto fail; // Receive parameters. ret = ps2_recvbyte(aux, 0, 4000); if (ret < 0) goto fail; param[0] = ret; ret = ps2_recvbyte(aux, 0, 100); if (ret < 0) // Some devices only respond with one byte on reset. ret = 0; param[1] = ret; } else if (command == ATKBD_CMD_GETID) { // Getid is special wrt bytes received. // Send command. ret = ps2_sendbyte(aux, command, 200); if (ret) goto fail; // Receive parameters. ret = ps2_recvbyte(aux, 0, 500); if (ret < 0) goto fail; param[0] = ret; if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d || ret == 0x60 || ret == 0x47) { // These ids (keyboards) return two bytes. ret = ps2_recvbyte(aux, 0, 500); if (ret < 0) goto fail; param[1] = ret; } else { param[1] = 0; } } else { // Send command. ret = ps2_sendbyte(aux, command, 200); if (ret) goto fail; // Send parameters (if any). int i; for (i = 0; i < send; i++) { ret = ps2_sendbyte(aux, param[i], 200); if (ret) goto fail; } // Receive parameters (if any). for (i = 0; i < receive; i++) { ret = ps2_recvbyte(aux, 0, 500); if (ret < 0) goto fail; param[i] = ret; } } ret = 0; fail: // Restore interrupts and keyboard/mouse. ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr); if (ret2) return ret2; return ret; }
/* Voice thread entrypoint */ static void voice_thread(void) { struct voice_thread_data td; voice_data_init(&td); /* audio thread will only set this once after it finished the final * audio hardware init so this little construct is safe - even * cross-core. */ while (!audio_is_thread_ready()) sleep(0); goto message_wait; while (1) { td.state = TSTATE_DECODE; if (!queue_empty(&voice_queue)) { message_wait: queue_wait(&voice_queue, &td.ev); message_process: voice_message(&td); /* Branch to initial start point or branch back to previous * operation if interrupted by a message */ switch (td.state) { case TSTATE_DECODE: goto voice_decode; case TSTATE_BUFFER_INSERT: goto buffer_insert; default: goto message_wait; } } voice_decode: /* Decode the data */ if (speex_decode_int(td.st, &td.bits, voice_output_buf) < 0) { /* End of stream or error - get next clip */ td.vi.size = 0; if (td.vi.get_more != NULL) td.vi.get_more(&td.vi.start, &td.vi.size); if (td.vi.start != NULL && (ssize_t)td.vi.size > 0) { /* Make bit buffer use our own buffer */ speex_bits_set_bit_buffer(&td.bits, td.vi.start, td.vi.size); /* Don't skip any samples when we're stringing clips together */ td.lookahead = 0; /* Paranoid check - be sure never to somehow get stuck in a * loop without listening to the queue */ yield(); if (!queue_empty(&voice_queue)) goto message_wait; else goto voice_decode; } /* If all clips are done and not playing, force pcm playback. */ if (!pcm_is_playing()) pcmbuf_play_start(); /* Synthesize a stop request */ /* NOTE: We have no way to know when the pcm data placed in the * buffer is actually consumed and playback has reached the end * so until the info is available or inferred somehow, this will * not be accurate and the stopped signal will come too soon. * ie. You may not hear the "Shutting Down" splash even though * it waits for voice to stop. */ td.ev.id = Q_VOICE_STOP; td.ev.data = 0; /* Let PCM drain by itself */ yield(); goto message_process; } yield(); /* Output the decoded frame */ td.count = VOICE_FRAME_SIZE - td.lookahead; td.src[0] = (const char *)&voice_output_buf[td.lookahead]; td.src[1] = NULL; td.lookahead -= MIN(VOICE_FRAME_SIZE, td.lookahead); buffer_insert: /* Process the PCM samples in the DSP and send out for mixing */ td.state = TSTATE_BUFFER_INSERT; while (td.count > 0) { int out_count = dsp_output_count(td.dsp, td.count); int inp_count; char *dest; while (1) { if (!queue_empty(&voice_queue)) goto message_wait; if ((dest = pcmbuf_request_voice_buffer(&out_count)) != NULL) break; yield(); } /* Get the real input_size for output_size bytes, guarding * against resampling buffer overflows. */ inp_count = dsp_input_count(td.dsp, out_count); if (inp_count <= 0) break; /* Input size has grown, no error, just don't write more than * length */ if (inp_count > td.count) inp_count = td.count; out_count = dsp_process(td.dsp, dest, td.src, inp_count); if (out_count <= 0) break; pcmbuf_write_voice_complete(out_count); td.count -= inp_count; } yield(); } /* end while */ } /* voice_thread */
int raid_memchk(unsigned int *p1, unsigned int pattern, unsigned int bytes) { int status=0; RAID_DMA_STATUS_T dma_status; if(bytes > (1<<(SRAM_PAR_SIZE+11))){ printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); } status = ((pattern&0xFFFF)%bytes )/4; p1[status] = pattern; while(tp.status != COMPLETE){ DPRINTK("XOR yield\n"); //schedule(); yield(); } tp.status = RUNNING; // flush the cache to memory before H/W XOR touches them consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); tp.tx_desc = tp.tx_first_desc; if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ // prepare tx descript raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF); tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address tp.tx_desc->func_ctrl.bits.raid_ctrl_status = 0; tp.tx_desc->func_ctrl.bits.buffer_size = bytes ; /* total frame byte count */ tp.tx_desc->flg_status.bits32 = CMD_CHK; // only support memory FILL command tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ tp.tx_desc->next_desc_addr.bits32 = 0x0000000b; // tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base); } else{ /* no free tx descriptor */ printk("XOR:no free tx descript"); return -1; } // change status //tp.status = RUNNING; status = tp.busy = 1; // start tx DMA txdma_ctrl.bits.td_start = 1; raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); // raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); #ifdef SPIN_WAIT gemini_xor_isr(2); #else xor_queue_descriptor(); #endif // dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS); // if (dma_status.bits32 & (1<<15)) { if((tp.tx_first_desc->func_ctrl.bits.raid_ctrl_status & 0x2)) { status = 1; // raid_write_reg(RAID_DMA_STATUS,0x00008000,0x00080000); } else{ status = 0; } tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; tp.status = COMPLETE; // tp.rx_desc->func_ctrl.bits.own = DMA; return status ; }