/************************************************************************* Author: Josiah Snarr Date: April 11, 2015 stepperHome finds the stepper limits on the platform, and centers the stepper at the midpoint between them *************************************************************************/ void stepperHome(void) { unsigned int midpoint; //Delay stops it from going "ttttttzzzhhggggghhghhzzzzzttttt" msDelay(25); //Go fully left while(IS_CLR(STEP_SWI_PORT, SWI_LEFT)) { stepperStep(); msDelay(2); } //All the way left, 0-position, switch direction currStep = 0; SWI_DIR(direction); //Go all the way right while(IS_CLR(STEP_SWI_PORT, SWI_RIGHT)) { stepperStep(); msDelay(2); } //All the way right, number of steps is current step, find midpoint and switch direction numSteps = currStep; midpoint = currStep/2; SWI_DIR(direction); //Move to midpoint while(currStep != midpoint) { stepperStep(); msDelay(2); } }
void MBC2::control(uint8_t value, uint16_t addr) { if (addr >= 0x0000 && addr <= 0x1FFF) { // least significant bit of upper byte in address must be zero if (IS_CLR(addr, 0x0100)) { xram_enable_ = ((value & 0x0F) == 0x0A); } } else if (addr >= 0x2000 && addr <= 0x3FFF) { // least significant bit of upper byte in address must be one if (IS_SET(addr, 0x0100)) { rom_bank_ = value & 0x0F; } } }
void Agc_sweep(SEGCTLPTR *heap_segments) { SEGCTLPTR segctlp, *segctlpp; ELPTR elp; CODEDPTR *elpp; GC_SWEEP(); for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; ) /* At end of loop so it can be skipped by continue: segctlpp = &((segctlp)->next ) */ { PTR elstart, elend; BITMAPPTR bitmap = segctlp->bitmap; PTR old_elend; ASSERT_DECL( PTR last_freestart ) REPORT6(5,"Agc_collect{free list reconstruct}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n", (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp)); /* ** First, clear bitmap (to indicate unused) from free list. ** This is essential for the freelist reconstruction algorithm to work. ** It ensures that all free list elements are enclosed in an unused heap area ** as identified by the bitmap. */ /* ** Note that sweeping algorithm relies on the fact that the free list elements are ** in ascending address order, and there is some allocated space between elements. */ ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear); ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear); elpp = &segctlp->free; elp = DECODEPTR(*elpp); old_elend = SEGSTART( segctlp ); ASSERT_INIT( last_freestart = SEGSTART(segctlp) - 1 ); if ( elp != NIL ) { elstart = (PTR)elp; elend = (PTR)ELEND( elp, segctlp ); CHECK_EL( segctlp, elp, elend ); } else { elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } for (;;) { PTR freestart, freeend; SIZE freed_bytes; ASSERT(elp == DECODEPTR(*elpp),Agc_collect,elpp and elp out of step); ASSERT(elp == NIL || ((PTR)elp >= (PTR)SEGSTART(segctlp) && (PTR)elp < (PTR)SEGEND(segctlp)) ,Agc_collect,elp not within segment); ASSERT(elp == NIL || ((PTR)ELEND(elp,segctlp) <= (PTR)SEGEND(segctlp)) ,Agc_collect,elp end not within segment); ASSERT(elp == NIL || elend > elstart,Agc_collect,empty free list element); /* ** First, set 'freestart' to be the start of either the next: ** ** free space starting outside a free list element ** or ** free space starting at the start of a free list element ** but finishing beyond the end of that element ** or ** an adress beyond the end of the segment */ SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart ); ASSERT( freestart > last_freestart,Agc_collect,not progressing in sweep); ASSERT_INIT( last_freestart = freestart ); if ( freestart >= SEGEND( segctlp ) ) break; while ( freestart == elstart && TSTMARK( bitmap, ELNUM( elend, segctlp ) ) ) { /* ** Freespace is identical to free list element. ** Skip on to next free list element. */ ASSERT(freestart <= SEGEND(segctlp),Agc_collect,freestart beyond segend); /* step on to next free list element */ ASSERT(elp != NIL,Agc_collect,elp nil at elpp update); elpp = &elp->next; elp = DECODEPTR(*elpp); old_elend = elend; if ( elp != NIL ) { elstart = (PTR)elp; elend = (PTR)ELEND( elp, segctlp ); CHECK_EL( segctlp, elp, elend ); ASSERT(elend > elstart,Agc_collect,empty free list element); } else { elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } ASSERT(old_elend < elstart,Agc_collect,free list not in order); SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart ); } if ( freestart >= SEGEND( segctlp ) ) break; ASSERT(freestart == (PTR)SEGSTART( segctlp ) || freestart > old_elend,Agc_collect,freestart before old_elend); ASSERT(freestart <= elstart,Agc_collect,freestart > elstart); ASSERT(elp == NIL || elstart == (PTR)DECODEPTR(*elpp),Agc_collect,elstart != *elpp); /* ** Secondly, set 'freeend' to be the end of the freespace */ if ( freestart < elstart ) { SCAN_TO_SET( freeend, segctlp, bitmap, freestart, elstart ); freed_bytes = (char *)freeend - (char *)freestart; CLR_AT_FREE( freestart, SEGELSIZE(segctlp), freed_bytes ); } else { ASSERT(freestart == elstart,Agc_collect,freestart == elstart); freed_bytes = 0; freeend = freestart; } while ( freeend == elstart ) { /* step on to next free list element */ ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); elp = DECODEPTR(elp->next); old_elend = elend; if ( elp != NIL ) { elend = (PTR)ELEND( elp, segctlp ); CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) ); elstart = (PTR)elp; CHECK_EL( segctlp, elp, elend ); ASSERT(elend > elstart,Agc_collect,empty free list element); } else { CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) ); elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } ASSERT(old_elend < elstart,Agc_collect,free list not in order); ASSERT(freeend < elstart,Agc_collect,freeend not less than elstart); SCAN_TO_SET( freeend, segctlp, bitmap, old_elend, elstart ); ASSERT(freeend >= old_elend,Agc_collect,freeend before old_elend); ASSERT(freeend <= elstart,Agc_collect,freeend beyond elstart limit); ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); if ( freeend != old_elend ) { freed_bytes += (char *)freeend - (char *)old_elend; CLR_AT_FREE( old_elend, SEGELSIZE(segctlp), (char *)freeend-(char *)old_elend ); } } ASSERT(freeend < elstart,Agc_collect,freeend beyond elstart); /* freestart -> freeend is the new element */ /* elp is freelist element beyond freeend, or NIL */ /* elpp points to el pointer before freestart */ ASSERT(freeend > freestart,Agc_collect,empty bitmap area); ASSERT(elp == NIL || (PTR)elp > freeend,Agc_collect,elp before freeend); ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); ASSERT((PTR)elpp < freestart,Agc_collect,elpp beyond freestart); ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear); ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear); if ( freestart == SEGSTART( segctlp ) && freeend == SEGEND( segctlp ) ) { /* Whole segment is free */ /* +++ put segment at end of list rather than freeing */ REPORT1(3,"Agc_collect: freeing seg=0x%p\n",(void *)segctlp); ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 ); ASSERT_INIT( segctlp->bitmap = bitmap = NIL ); *segctlpp = segctlp->next; /* remove segctlp from list */ Agc_b_allocated -= freed_bytes; Agc_s_grabbed--; Agc_b_grabbed -= SEGSIZE(segctlp); REP_DO(Agc_s_freed++); FREE_SEG( segctlp ); ASSERT_INIT( segctlp = NIL ); goto sweep_next_seg; } else if ( ELPTRENOUGH( freestart, freeend ) ) { #define freeelp ((ELPTR)freestart) /* care needed because of possible overlap between new and old element header */ REPORT5(6,"Agc_collect: adding free list element (0x%p -> 0x%p : size %d) after elpp 0x%p, before 0x%p\n", (void *)freestart,(void *)freeend,(char *)freeend-(char *)freestart,(void *)elpp,(void *)elp); ASSERT( IS_CLR(freestart,SEGELSIZE(segctlp),(char *)freeend-(char *)freestart) ,Agc_collect,recreated free list element not clear); ASSERT( ((char *)freeend - (char *)freestart) % SEGELSIZE( segctlp ) == 0,Agc_collect,space recovered not multiple of elsize); freeelp->next = ENCODEPTR( elp ); freeelp->elements = ((char *)freeend - (char *)freestart) / SEGELSIZE( segctlp ); ASSERT(DECODEPTR(*elpp) == NIL || (PTR)DECODEPTR(*elpp) >= freestart,Agc_collect,discarding space already in free list); *elpp = ENCODEPTR( freestart ); /* elp is still correct as next element, we have just inserted preceding it */ /* however elpp now needs to point at new element */ elpp = &freeelp->next; Agc_b_allocated -= freed_bytes; ASSERT( freeend == (PTR)ELEND(freeelp,segctlp) ,Agc_collect,freeend not ELEND); ASSERT( freeelp->next == CODEDNIL || DECODEPTR(freeelp->next) > ELEND(freeelp,segctlp) ,Agc_collect,free list elements overlap); ASSERT( freeelp->next == CODEDNIL || (PTR)DECODEPTR(freeelp->next) > freeend ,Agc_collect,freeelp->next not past freeend); #undef freeelp } /* else ( ! ELPTRENOUGH( freestart, freeend ) ) */ /* do nothing, forget the few bytes of free space we found */ old_elend = freeend; } #ifdef A_DEBUG if ( ELPTRENOUGH( (PTR)NIL, (char *)NIL+SEGELSIZE(segctlp) ) ) /* if ( SEGELSIZE(segctlp) >= sizeof( EL ) ) */ { SIZE i; elp = DECODEPTR( segctlp->free ); for ( i = 0; i < SEGELS(segctlp); i++ ) { if ( !TSTMARK(bitmap,i) ) { while ( i > ELNUM( ELEND( elp, segctlp ), segctlp ) ) { elp = DECODEPTR( elp->next ); ASSERT( elp != NIL,Agc_collect,free element beyond free list end at end of sweep); } ASSERT( i >= ELNUM( elp, segctlp ) && i < ELNUM( ELEND( elp, segctlp ), segctlp ),Agc_collect,free element not in free list at end of sweep); } } } #endif ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 ); ASSERT_INIT( segctlp->bitmap = bitmap = NIL ); segctlpp = &((segctlp)->next); sweep_next_seg: ; } }
char sci_read() { while(IS_CLR(SCISR1, SCISR1_RDRF_MASK)); return SCIDRL; }
void sci_write(char c) { while(IS_CLR(SCISR1, SCISR1_TDRE_MASK)); SCIDRL = c; }
loff_t btp_llseek( struct file *file_p, loff_t offset, int which ) { FUNCTION("btp_llseek"); LOG_DEVID(file_p); bt_dev_t type = GET_LDEV_TYPE(file_p); bt_unit_t *unit_p = GET_UNIT_PTR(file_p); loff_t retval = 0; loff_t f_pos, end_pos; FENTRY; /* Determine where the end of the various logical devices are */ switch(type) { case BT_DEV_RDP: if (IS_CLR(unit_p->bt_status, BT_PCI2PCI)) { end_pos = 8 * SIZE_1MB; } else if (IS_SET(unit_p->bt_status, BT_NEXT_GEN)) { end_pos = 192 * SIZE_1KB; } else { end_pos = 0; } break; case BT_DEV_LDP: if (IS_CLR(unit_p->bt_status, BT_NEXT_GEN)) { end_pos = 0; } else { end_pos = 192 * SIZE_1KB; } break; case BT_DEV_A24: /* 24 address bits */ end_pos = 16 * SIZE_1MB; break; case BT_DEV_IO: /* 16 address bits */ end_pos = 64 * SIZE_1KB; break; case BT_DEV_A32: /* 32 address bits */ end_pos = ((loff_t) 1)<<32; break; case BT_DEV_RE: /* 31 address bits, only provided for compatibility */ end_pos = ((loff_t) 1)<<31; break; case BT_DEV_LM: /* User determined when device was loaded */ end_pos = unit_p->lm_size; if (0 == end_pos) { INFO_STR("Local Memory device not enabled.\n"); retval = -ENXIO; goto llseek_end; } break; default: TRC_MSG(BT_TRC_RD_WR, (LOG_FMT "Unrecognized device type: %d.\n", LOG_ARG, type)); retval = -ENXIO; goto llseek_end; } /* Determine what the new address would be */ switch(which) { case SEEK_SET: f_pos = offset; break; case SEEK_CUR: f_pos = file_p->f_pos + offset; break; case SEEK_END: f_pos = end_pos + offset; /* Better be a negative offset */ break; default: /* Should never happen */ INFO_STR("Invalid SEEK type.\n"); retval = -EINVAL; goto llseek_end; } if (f_pos >= end_pos) { INFO_STR("Seek past end of logical device.\n"); retval = -EINVAL; goto llseek_end; } file_p->f_pos = f_pos; retval = f_pos; llseek_end: FEXIT(retval); return retval; }
static int btp_xfer( bt_unit_t *unit_p, bt_dev_t type, bt_accessflag_t dir, void * usr_data_p, unsigned long dest_addr, size_t length, size_t *xferred_bytes_p ) { FUNCTION("btp_xfer"); LOG_UNIT(unit_p->unit_number); void *data_p; int dma_flag; int data_width; size_t length_remaining = length; unsigned int start, need; bt_data32_t mreg_value; bt_error_t retval = BT_SUCCESS; unsigned int inx; unsigned long pci_addr; bt_data32_t ldma_addr; struct page **pages; int ret, i, write; bt_data32_t usr_curr_offset; caddr_t kbuf_p; unsigned int nr_pages; FENTRY; /* ** Haven't transferred any data yet */ *xferred_bytes_p = 0; /* ** Adjust for the extended remote ram window. */ if (type == BT_AXSRE) { dest_addr |= RE_ADJUST; } /* ** Normally you would have the while loop in the read and write routines. ** ** Since both would require the same loop, I've decided to just put it ** in this routine instead. */ while ((length_remaining > 0) && (BT_SUCCESS == retval)) { int xferred_length = 0; int requested_length = length_remaining; /* ** Setup direction and current offset */ if (dir == BT_WR) { write = 1; } else { write = 0; } usr_curr_offset = (bt_data32_t) ((bt_devaddr_t) usr_data_p & (PAGE_SIZE -1)); /* ** Malloc a scatter/gather list */ nr_pages = (usr_curr_offset + requested_length + ~PAGE_MASK) >> PAGE_SHIFT; pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); if (!pages) { WARN_STR("Failed to kmalloc scatter/gather list.\n"); retval = BT_EIO; goto btp_xfer_end; } /* ** Translate the user pages to physical addresses ** store in scatter/gather list */ down_read(¤t->mm->mmap_sem); ret = get_user_pages(current, current->mm, (unsigned long) usr_data_p, nr_pages, write, 1, pages, NULL); up_read(¤t->mm->mmap_sem); if (ret < nr_pages) { WARN_STR("Failed to create scatter/gather list for user buffer.\n"); for (i = 0; i < ret; i++) { page_cache_release(pages[i]); } kfree(pages); retval = BT_EIO; goto btp_xfer_end; } /* ** Determine whether we do DMA or PIO */ btk_dma_pio(unit_p, type, (bt_devaddr_t) usr_data_p, dest_addr, &requested_length, &dma_flag, &data_width, &start, &need); #define BTP_FREE_MREG if (dma_flag) { \ btk_mutex_enter(&unit_p->mreg_mutex); \ (void) btk_bit_free(unit_p->sdma_aval_p, start, need); \ btk_mutex_exit(&unit_p->mreg_mutex); \ btk_mutex_exit(&unit_p->dma_mutex); \ } \ for (i = 0; i < nr_pages; i++) { \ if (BT_RD == dir) { \ set_page_dirty_lock(pages[i]); \ } \ page_cache_release(pages[i]); \ } \ kfree(pages); /* ** Can't let PIO go past one page */ if (!dma_flag) { if ((usr_curr_offset + requested_length) > PAGE_SIZE) { requested_length = PAGE_SIZE - usr_curr_offset; } need = 1; } TRC_MSG(BT_TRC_RD_WR, (LOG_FMT "Transferring %d bytes data to 0x%lx using %s.\n", LOG_ARG, requested_length, dest_addr, ((dma_flag) ? "DMA" : "PIO"))); if (dma_flag) { /* ** Setup vme address, address modifier, and function code */ mreg_value = 0; btk_setup_mreg(unit_p, type, &mreg_value, BT_OP_DMA); /* ** Program up mapping RAM */ for (inx = start, i = 0; inx < (start + need); inx++, i++) { pci_addr = (unsigned long) page_to_phys(pages[i]); if (0 == pci_addr) { WARN_STR("Kernel to PCI address translation failed.\n"); retval = BT_EIO; goto end_xfer_loop; } mreg_value &= ~BT_MREG_ADDR_MASK; mreg_value |= (pci_addr & BT_MREG_ADDR_MASK); btk_put_mreg(unit_p, inx, BT_LMREG_DMA_2_PCI, mreg_value); if ( (btk_get_mreg(unit_p, inx, BT_LMREG_DMA_2_PCI)) != mreg_value ) { WARN_MSG((LOG_FMT "Verify Write BT_LMREG_DMA_2_PCI mapping register mr_idx = 0x%.1X failed.\n", LOG_ARG, inx)); retval = BT_EIO; goto end_xfer_loop; } } /* ** Now we need to get the DMA semaphore ** Note this routines does nothing in a single driver situtation */ retval = btk_take_drv_sema(unit_p); if (retval != BT_SUCCESS) { goto end_xfer_loop; } /* ** If old Nanobus card, we must stop PIO from occuring */ if (IS_CLR(unit_p->bt_status, BT_NEXT_GEN)) { btk_rwlock_wr_enter(&unit_p->hw_rwlock); } /* ** Do the DMA */ ldma_addr = (bt_data32_t) ((start * BT_PAGE_SIZE) + usr_curr_offset); xferred_length = requested_length; retval = btk_dma_xfer(unit_p, type, ldma_addr, (bt_data32_t) dest_addr, &xferred_length, (dir == BT_RD) ? BT_READ : BT_WRITE, data_width); if (IS_CLR(unit_p->bt_status, BT_NEXT_GEN)) { btk_rwlock_wr_exit(&unit_p->hw_rwlock); } btk_give_drv_sema(unit_p); /* ** Do a PIO */ } else { /* ** Perform the proper direction PIO data transfer */ kbuf_p = kmap(pages[0]); if (kbuf_p == NULL) { INFO_STR("Failed to get kernel pointer to PIO user buffer"); retval = BT_EIO; } else { data_p = (void *) (kbuf_p + usr_curr_offset); xferred_length = requested_length; retval = btk_pio_xfer(unit_p, type, data_p, (unsigned long) dest_addr, &xferred_length, (dir == BT_RD) ? BT_READ : BT_WRITE); kunmap(pages[0]); } } end_xfer_loop: BTP_FREE_MREG; TRC_MSG(BT_TRC_RD_WR, (LOG_FMT "%s transfer done 0x%x bytes transferred, retval %d\n", LOG_ARG, ((dma_flag) ? "DMA" : "PIO"), xferred_length, retval)); usr_data_p = (caddr_t) usr_data_p + xferred_length; dest_addr += xferred_length; length_remaining -= xferred_length; } btp_xfer_end: *xferred_bytes_p = length - length_remaining; FEXIT(retval); return retval; }