void delete_list_item(play_item_t* play_item) { dbg1("deleting list item at %p with ID %llu between (prev) %p and (next) %p\n", play_item, play_item->play_id, play_item->prev_item, play_item->next_item); if (play_item->next_item != NULL) { play_item->next_item->prev_item = play_item->prev_item; } if (play_item->prev_item != NULL) { play_item->prev_item->next_item = play_item->next_item; } destroy_mutex(play_item->mutex); PyMem_Free(play_item); }
static unsigned lpc_poll( struct file *file, struct poll_table_struct *wait) { DEV *dev = file->private_data; unsigned mask = 0; dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev); // DbgFlush(); poll_wait( file, &dev->rd_wait, wait); if(dev->inhead != dev->intail) mask |= POLLIN | POLLRDNORM; return mask; }
int wkm_cfg_to_opts(struct wkman *wkman, struct cfg *cfg) { HDF *base_hdf = (HDF*)cfg; HDF *hdf; int rval = 0; dbg1("%s %s()", wkman->dev->serial, __func__); for(hdf = hdf_obj_child(base_hdf); hdf; hdf = hdf_obj_next(hdf)) { const char *key = hdf_obj_name(hdf); const char *val_str = hdf_obj_value(hdf); int val = atoi(val_str); rval += wkm_set_value(wkman, key, val); } return rval; }
/* --------------------------------------------------------------------- */ static int hdshm_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret=0; struct hdshm_file *bsf=(struct hdshm_file*)file->private_data; switch(cmd) { case IOCTL_HDSHM_GET_AREA: ret=hdshm_get_area(bsf,arg); break; case IOCTL_HDSHM_SET_ID: ret=hdshm_set_id(bsf,arg); break; case IOCTL_HDSHM_CREATE_AREA: ret=hdshm_create_area(bsf,arg); break; case IOCTL_HDSHM_DESTROY_AREA: ret=hdshm_destroy_area(bsf,arg); break; case IOCTL_HDSHM_GET_STATUS: ret=hdshm_get_status(bsf,arg); break; case IOCTL_HDSHM_RESET: ret=hdshm_reset(bsf,arg); break; case IOCTL_HDSHM_UNMAP_AREA: ret=hdshm_unmap_area(bsf,arg); break; case IOCTL_HDSHM_GET_ROOT: ret=(int)hdd.hd_root; // HACK FIXME break; case IOCTL_HDSHM_FLUSH: break; case IOCTL_HDSHM_PCIBAR1: return (int)hdd.bar1; // HACK FIXME break; case IOCTL_HDSHM_SHUTDOWN: hdd.hd_root->booted=arg; break; #ifdef CONFIG_MIPS case IOCTL_HDSHM_DMA: ret=hdshm_dma(bsf,arg); break; #endif default: break; } dbg1("usage h %i b %i",hdd.hd_root->host_usage,hdd.hd_root->hd_usage); return ret; }
inline static void remove_free_block(void* bp) { #else static void remove_free_block(void* bp) { #endif /* get specific segregated free list */ size_t free_list_num = get_list_num(GET_SIZE(HDRP(bp))); dbg1("[IN ] : remove_free_block()\n"); /* remove block */ if ((void*)NEXT_FREE_BLKP(bp) == NULL) { /* if next pointer is null */ if ((void*)PREV_FREE_BLKP(bp) == NULL) { /* if prev pointer is null, make list empty */ PUT8(FREE_LISTP(free_list_num), NULL); PUT8(FREE_LISTP_T(free_list_num), NULL); dbg1("[OUT] : remove_free_block() : list is empty\n"); return; } /* remove from tail */ PUT8(NEXT_FREEP(PREV_FREE_BLKP(bp)), NULL); PUT8(FREE_LISTP_T(free_list_num), PREV_FREE_BLKP(bp)); } else if ((void*)PREV_FREE_BLKP(bp) == NULL) { /* if prev pointer is null, remove from head */ PUT8(FREE_LISTP(free_list_num), NEXT_FREE_BLKP(bp)); PUT8(PREV_FREEP(GET_FREE_LISTP(free_list_num)), NULL); } else { /* just remove from middle of list */ PUT8(PREV_FREEP(NEXT_FREE_BLKP(bp)), PREV_FREE_BLKP(bp)); PUT8(NEXT_FREEP(PREV_FREE_BLKP(bp)), NEXT_FREE_BLKP(bp)); } dbg1("[OUT] : remove_free_block()\n"); }
void destroy_audio_blob(audio_blob_t* audio_blob) { PyGILState_STATE gstate; dbg1("destroying audio blob at %p\n", audio_blob); /* release the buffer view so Python can decrement it's reference count*/ gstate = PyGILState_Ensure(); PyBuffer_Release(&audio_blob->buffer_obj); PyGILState_Release(gstate); grab_mutex(audio_blob->list_mutex); delete_list_item(audio_blob->play_list_item); release_mutex(audio_blob->list_mutex); PyMem_Free(audio_blob); }
int wkm_reset(struct wkman *wkman) { const uint8_t cmd[] = { 0x00, 0x01 }; int len = sizeof(cmd); dbg1("%s %s()", wkman->dev->serial, __func__); if(!mhc_is_online(wkman->dev->ctl)) return WKM_RESULT_DEVICE_OFFLINE; if(len != mhr_send(wkman->dev->router, cmd, len, MH_CHANNEL_WINKEY)) return WKM_RESULT_IO_ERROR; wkman->state = WKM_STATE_HOST_CLOSED; return WKM_RESULT_OK; }
inline static size_t get_nonempty_list_num(size_t size) { #else static size_t get_nonempty_list_num(size_t size) { #endif dbg1("[IN ] : get_nonempty_list_num() - class2\n"); if(size <= BLKSIZE && GET_FREE_LISTP(0) != NULL) return 0; if(size <= (BLKSIZE << 1) && GET_FREE_LISTP(1) != NULL) return 1; if(size <= (BLKSIZE << 2) && GET_FREE_LISTP(2) != NULL) return 2; if(size <= (BLKSIZE << 3) && GET_FREE_LISTP(3) != NULL) return 3; if(size <= (BLKSIZE << 4) && GET_FREE_LISTP(4) != NULL) return 4; if(size <= (BLKSIZE << 5) && GET_FREE_LISTP(5) != NULL) return 5; if(size <= (BLKSIZE << 6) && GET_FREE_LISTP(6) != NULL) return 6; if(size <= (BLKSIZE << 7) && GET_FREE_LISTP(7) != NULL) return 7; return 8; }
/* --------------------------------------------------------------------- */ int hdshm_destroy_area(struct hdshm_file *bsf, unsigned long arg) { int id=(int)arg; int retval; dbg1("destroy_area id=%x",id); if (id==0) return -ENOENT; if (hdshm_lock_table()) return -ETIMEDOUT; retval=hdshm_destroy_area_sub(id); hdshm_unlock_table(); return retval; }
static int __init module_lpc_init(void) { int i, val, ret; char c; // if (!DbgInit()) return -ENOMEM; info(DRIVER_DESC " " DRIVER_VERSION); ret = register_chrdev(major, DRIVER_DEV_NAME, &lpc_fops); if (ret < 0) { err("register_chrdev(major=%d, \"" DRIVER_DEV_NAME "\")=%d -> failed", major, ret); // DbgExit(); return ret; } if (major == 0) major = ret; // dynamic major #ifdef CONFIG_DEVFS_FS #warning CONFIG_DEVFS_FS not tested ret = devfs_mk_dir("lpc"); dbg1("major=%d devfs_mk_dir()=%08X", major, ret); #else #warning Info: CONFIG_DEVFS_FS not used #endif ret = pci_module_init(&lpp_driver); if( isa ) { i = 0; while( *isa && (i < MAX_LPCS*4) ) { c = *isa++; val = -1; if((c >= '0') && (c <= '9')) val = c - '0'; if((c >= 'A') && (c <= 'F')) val = c + 10 - 'A'; if((c >= 'a') && (c <= 'f')) val = c + 10 - 'a'; if(val >= 0) { lpcs[i >> 2] = (lpcs[i >> 2] << 4) | val; i++; } } }
int wkm_write_cfg(struct wkman *wkman) { uint8_t cmd[1 + sizeof(wkman->cfg)] = { 0x0f }; int len = sizeof(cmd); dbg1("%s %s()", wkman->dev->serial, __func__); if(!mhc_is_online(wkman->dev->ctl)) return WKM_RESULT_DEVICE_OFFLINE; if(wkman->state != WKM_STATE_HOST_OPEN && wkman->state != WKM_STATE_HOST_CLOSED) { return WKM_RESULT_BUSY; } memcpy(cmd + 1, wkman->cfg, sizeof(wkman->cfg)); if(len != mhr_send(wkman->dev->router, cmd, len, MH_CHANNEL_WINKEY)) return WKM_RESULT_IO_ERROR; return WKM_RESULT_OK; }
PyMODINIT_FUNC PyInit__simpleaudio(void) { PyObject *m; m = PyModule_Create(&_simpleaudio_module); if (m == NULL) return NULL; sa_python_error = PyErr_NewException("_simpleaudio.SimpleaudioError", NULL, NULL); Py_INCREF(sa_python_error); PyModule_AddObject(m, "SimpleaudioError", sa_python_error); /* initialize the list head mutex */ play_list_head.mutex = create_mutex(); dbg1("init'd list head at %p\n", &play_list_head); return m; }
// Needs table_lock int hdshm_destroy_area_sub(int id) { int num_entry; hdshm_entry_t *bse; bse=hdshm_find_area(id,&num_entry); if (!bse) return -ENOENT; if (bse->usage || bse->flags&HDSHM_MEM_HD) return -EBUSY; dbg1("destroy_area bse=%p",bse); dbg("free %x %p %p", bse->length, (void*)bse->kernel, (void*)bse->phys); hdshm_free_memory(&hdd, bse->phys, bse->length); hdd.hd_root->ids[num_entry]=0; hdd.num_areas--; return 0; }
play_item_t* new_list_item(play_item_t* list_head) { play_item_t* new_item; play_item_t* old_tail; new_item = PyMem_Malloc(sizeof(play_item_t)); new_item->next_item = NULL; old_tail = list_head; while(old_tail->next_item != NULL) { old_tail = old_tail->next_item; } old_tail->next_item = new_item; new_item->prev_item = old_tail; new_item->mutex = create_mutex(); new_item->play_id = (list_head->play_id)++; new_item->stop_flag = SA_CLEAR; dbg1("new list item at %p with ID %llu attached to %p\n", new_item, new_item->play_id, old_tail); return new_item; }
/* --------------------------------------------------------------------- */ int hdshm_set_id(struct hdshm_file *bsf, unsigned long arg) { hdshm_entry_t *bse; int id=(int)arg; dbg1("IOCTL_HDSHM_SET_ID %x",id); if (!id) { bsf->id=id; return 0; } if (hdshm_lock_table()) return -ETIMEDOUT; bse=hdshm_find_area(id,NULL); hdshm_unlock_table(); if (!bse) return -ENOENT; bsf->id=id; return 0; }
int wkm_host_open(struct wkman *wkman) { const uint8_t cmd[] = { 0x00, 0x02 }; int len = sizeof(cmd); dbg1("%s %s()", wkman->dev->serial, __func__); if(!mhc_is_online(wkman->dev->ctl)) return WKM_RESULT_DEVICE_OFFLINE; if(wkman->state != WKM_STATE_HOST_CLOSED && wkman->state != WKM_STATE_HOST_OPEN) { return WKM_RESULT_BUSY; } if(len != mhr_send(wkman->dev->router, cmd, len, MH_CHANNEL_WINKEY)) return WKM_RESULT_IO_ERROR; ev_timer_start(wkman->loop, &wkman->timeout_timer); wkman->state = WKM_STATE_HOST_OPEN_SENT; return WKM_RESULT_OK; }
/* --------------------------------------------------------------------- */ int hdshm_get_area(struct hdshm_file *bsf, unsigned long arg) { hdshm_area_t bsa; hdshm_entry_t *bse; int ret=0; if (!hdd.hd_root->booted) return -ENODEV; if (copy_from_user(&bsa,(void*)arg,sizeof(hdshm_area_t))) return -EFAULT; dbg1("get_area %x",bsa.id); if (hdshm_lock_table()) return -ETIMEDOUT; bse=hdshm_find_area(bsa.id, NULL); if (!bse) { hdshm_unlock_table(); return -ENOENT; } { // int* z=(int*)bse; // printk("XX %08x %08x %08x %08x %08x\n",*z,*(z+1),*(z+2),*(z+3),*(z+4)); } bsa.physical=bse->phys; bsa.length=bse->length; bsa.flags=bse->flags; bsa.usage=bse->usage; bsa.kernel_mem=(char*)hdd.start +((long)bse->phys-(long)hdd.start_phys); if (copy_to_user((void*)arg,&bsa,sizeof(hdshm_area_t))) ret=-EFAULT; hdshm_unlock_table(); return ret; }
void read_cb(struct mh_router *router, unsigned const char *data , int len, int channel, void *user_data) { (void)router; (void)channel; struct wkman *wkman = user_data; int err; dbg1("%s %s() %d", wkman->dev->serial, __func__, len); dbg1_h(wkman->dev->serial, "fm k", data, len); switch(wkman->state) { case WKM_STATE_HOST_OPEN_SENT: wkman->version = *data; wkman->state = WKM_STATE_HOST_OPEN; ev_timer_stop(wkman->loop, &wkman->timeout_timer); err = wkm_write_cfg(wkman); if(err != WKM_RESULT_OK) err("(wkman) could not send config to winkey (%s)!", wkm_err_string(err)); #if 0 err = wkm_host_close(wkman); if(err != WKM_RESULT_OK) err("(wkman) could not send HOST CLOSE to winkey (%s)!", wkm_err_string(err)); #endif break; } }
static int initialize_pcicard( DEV *dev, int index ) { dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev); { #if 0 u32 PlxIntCsrPort, cport, rport, wtcport, rtr; int irq; char bus, function; if( !pcibios_present() ) { err( "PCI bios not present\n" ); return -ENODEV; } if( pcibios_find_device( VENDOR_ID, DEVICE_ID, index, &bus, &function ) ) { err( "PCI device not found\n" ); return -ENODEV; } pcibios_read_config_dword( bus, function, 0x14, (int *)&rtr ); pcibios_read_config_dword( bus, function, 0x18, (int *)&cport ); pcibios_read_config_dword( bus, function, 0x1C, (int *)&rport ); pcibios_read_config_dword( bus, function, 0x24, (int *)&wtcport ); pcibios_read_config_dword( bus, function, 0x3C, &irq ); PlxIntCsrPort = (rtr & 0xFFF0) + P9050_INTCSR; cport &= 0xFFF0; rport &= 0xFFF0; irq &= 0x0F; outw( 0, PlxIntCsrPort ); if( check_region(cport, 4) ) { err( "unable to register port 0x%X\n", cport ); return -ENODEV; } if( check_region(rport, 4) ) { err( "unable to register port 0x%X\n", rport ); return -ENODEV; } request_region( cport, 4, DRIVER_DEV_NAME ); request_region( rport, 4, DRIVER_DEV_NAME ); dev->cport = cport; dev->rport = rport; dev->wport = rport; dev->wtcport = wtcport; dev->irq = irq; dev->PlxIntCsrPort = PlxIntCsrPort; #else u32 cport; u16 IntCsr; cport = dev->cport; #endif dev->ctl = 0x0D; SETCTL; SETCTL; dev->ctl = 0x16; SETCTL; SETCTL; dev->ctl = 0x02; SETCTL; SETCTL; dev->ctl = 0x16; SETCTL; IntCsr = inw(dev->PlxIntCsrPort); dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr); IntCsr |= PLX_9050_INTR_ENABLE | PLX_9050_LINT1_ENABLE; // | PLX_9050_LINT2_ENABLE; outw(IntCsr, dev->PlxIntCsrPort); dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr); if( request_irq(dev->irq, lpc_pci_interrupt, SA_SHIRQ, DRIVER_DEV_NAME, dev) ) { err("unable to register IRQ%d\n", dev->irq); #if 0 release_region(rport, 4); release_region(cport, 4); #endif return -ENODEV; } return 0; } }
/* --------------------------------------------------------------------- */ int hdshm_mmap(struct file * file, struct vm_area_struct * vma) { struct hdshm_file *bsf=(struct hdshm_file*)file->private_data; hdshm_entry_t *bse; int n,uncached=1; dma_addr_t phys_start; int length; dbg1("mmap id %x flags %x",bsf->id,(int)vma->vm_flags); if (!bsf->id) return -EINVAL; if (hdshm_lock_table()) return -ETIMEDOUT; // Only one mapping per id per process for(n=0;n<MAPPED_IDS_PER_FILE;n++) { int id=bsf->bsm[n].id; if (id!=0 && bsf->id==id) { hdshm_unlock_table(); return -EEXIST; } } dbg1("mmap find"); bse=hdshm_find_area(bsf->id,NULL); if (!bse) { dbg("mmap not found"); hdshm_unlock_table(); return -ENOENT; } dbg1("mmap bse=%p user %x phys=%x size %x offset %x", bse, (int)vma->vm_start, (int)bse->phys, (int)(vma->vm_end - vma->vm_start), (int)vma->vm_pgoff); if (bse->flags&HDSHM_MEM_CACHEABLE) uncached=0; if (uncached) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); dbg1("uncached %x pgprot %x",uncached,(int)pgprot_val(vma->vm_page_prot)); vma->vm_private_data=bse; vma->vm_flags |= VM_RESERVED|VM_SHARED; if (bse->flags&HDSHM_MEM_HD) { hdd.hd_root->hd_usage++; } else { hdd.hd_root->host_usage++; } #ifdef IS_HD if (bse->flags&HDSHM_MEM_HD) { phys_start = (dma_addr_t)(bse->phys&~4095); } else { phys_start = (dma_addr_t)bse->kernel; } #else if (bse->flags&HDSHM_MEM_HD) { phys_start = (dma_addr_t)(hdd.start_phys-MAP_START)+(bse->phys&~4095); // FIXME -MAP! } else { phys_start = (dma_addr_t)bse->kernel; // FIXME CHECK } #endif length=vma->vm_end-vma->vm_start; dbg1("MAP PHYSICAL: %p, length %x\n",(void*)phys_start, length); remap_pfn_range(vma, vma->vm_start, phys_start>>PAGE_SHIFT, length, vma->vm_page_prot); bse->usage++; for(n=0;n<MAPPED_IDS_PER_FILE;n++) { int id=bsf->bsm[n].id; if (!id) { bsf->bsm[n].id=bsf->id; break; } } hdshm_unlock_table(); return 0; }
/* --------------------------------------------------------------------- */ int hdshm_create_area(struct hdshm_file *bsf, unsigned long arg) { hdshm_area_t bsa; hdshm_entry_t *bse; int found; if (!hdd.hd_root->booted) return -ENODEV; if (copy_from_user(&bsa,(void*)arg,sizeof(bsa))) return -EFAULT; dbg1("create_area id=%x, flags %x",bsa.id,bsa.flags); #ifdef CONFIG_MIPS // Only HD based maps allowed if (!(bsa.flags&HDSHM_MEM_HD) || !bsa.id) return -EINVAL; #else /* Host can allocate host and HDE memory Host memory mus be explicitely flagged with HDSHM_MEM_DMA! DMA-flagged areas cannot be mmaped but must be accessed with IOCTL_HDSHM_DMA on HDE */ if (!bsa.id || (!(bsa.flags&HDSHM_MEM_HD) && !(bsa.flags&HDSHM_MEM_DMA)) || ((bsa.flags&HDSHM_MEM_HD) && (bsa.flags&HDSHM_MEM_DMA)) ) return EINVAL; #endif if (hdshm_lock_table()) return -ETIMEDOUT; bse=hdshm_find_area(bsa.id,NULL); if (bse) { hdshm_unlock_table(); return -EEXIST; } found=hdshm_find_free_entry(); if (found==-1) { hdshm_unlock_table(); return -ENFILE; } bse=&(hdd.hd_root->entries[found]); #ifdef CONFIG_MIPS bse->kernel=(int)hdshm_allocate_memory(&hdd, bsa.length, &bse->phys); #else if (bsa.flags&HDSHM_MEM_HD) bse->kernel=(int)hdshm_allocate_memory(&hdd, bsa.length, &bse->phys); else bse->kernel=pci_alloc_consistent (hdd.hd_pci, bsa.length, &bse->phys); #endif dbg("create_area id %x bse %p, physical %p, kernel %p length %x", bsa.id, bse, (void*)bse->phys, (void*)bse->kernel, bsa.length); if (!bse->kernel) { hdshm_unlock_table(); return -ENOMEM; } bse->usage=0; bse->length= bsa.length; bse->flags=bsa.flags; hdd.hd_root->ids[found]=bsa.id; hdd.num_areas++; hdshm_unlock_table(); return 0; }
static int initialize_isacard( DEV *dev, int index ) { u32 cport, rport; int irq; dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev); /* if( !lpcs[index] ) { err( "invalid minor number %d\n", index ); return -ENODEV; } iobase = lpcs[index] & 0x0FFF; irq = lpcs[index] >> 12; cport = iobase+1; rport = iobase+2; */ cport = dev->cport; rport = dev->rport; irq = dev->irq; #ifndef CHECK_ISA_AT_LOAD_TIME { int hwfail = 0; if( ((u8)irq > 15) || !irq_table[irq] ) { err("IRQ%d not supported\n", irq ); return -ENODEV; } if( check_region(iobase, 4) ) { err( "unable to register port 0x%X\n", iobase); return -ENODEV; } outb(0x5F, cport); outb(0, rport); outb(0, rport); outb(0, rport); if( (inb(cport) & 0xF0) != 0x50 ) hwfail = 1; outb(0x0F, cport); outb(0, rport); outb(0, rport); outb(0, rport); if( inb(cport) & 0xF0 ) hwfail = 1; if( hwfail ) { err("interface card not responding at port 0x%X\n", iobase); return -ENODEV; } request_region( iobase, 4, DRIVER_DEV_NAME ); } #endif /* dev->cport = iobase+1; dev->rport = iobase+2; dev->wport = iobase+3; dev->wtcport = iobase+0; dev->irq = irq; dev->PlxIntCsrPort = 0; */ dev->ctl = 0x0F; SETCTL; SETCTL; dev->ctl = 0x0D; SETCTL; SETCTL; dev->ctl |= irq_table[dev->irq]; SETCTL; SETCTL; dev->ctl &= 0xF6; SETCTL; if( request_irq(irq, lpc_isa_interrupt, SA_SHIRQ, DRIVER_DEV_NAME, dev) ) { err("unable to register IRQ%d\n", irq); #ifndef CHECK_ISA_AT_LOAD_TIME release_region(iobase, 4); #endif return -ENODEV; } return 0; }
static ssize_t lpc_read( struct file *file, char *buf, size_t count, loff_t *off ) { // int flags; int idx; int len; u8 *p; register DEV *dev = (DEV *)(file->private_data); if(count < 0) return -EINVAL; dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev); // DbgFlush(); idx = dev->inhead; #if 0 CLI; if( idx == dev->intail ) { if(file->f_flags & O_NONBLOCK) { STI; return -EWOULDBLOCK; } interruptible_sleep_on( &dev->rd_wait ); /* The next line produces compiling errors, so I use a workaround if( current->signal & ~current->blocked ) return -ERESTARTSYS; */ if( idx == dev->intail ) return -ERESTARTSYS; } STI; #else // if (qempty(&dev->ReadBufferQueue)) if (idx == dev->intail) { dbg1("%s(): qempty", __FUNCTION__); // up (&dev->sem); if (file->f_flags & O_NONBLOCK) { dbg1("%s()=-EAGAIN !!!", __FUNCTION__); return -EAGAIN; // -EWOULDBLOCK; } // if (wait_event_interruptible(dev->rd_wait, qhasdata(&dev->ReadBufferQueue))) if (wait_event_interruptible(dev->rd_wait, (idx != dev->intail) )) { dbg1("%s(): dev=%08X return -ERESTARTSYS", __FUNCTION__, (uint)dev); return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ } dbg8("%s(): nach wait_event_interruptible(rd_wait)", __FUNCTION__); // if (down_interruptible(&dev->sem)) // return -ERESTARTSYS; } #endif p = dev->inbuf[idx]; #if 0 // link layer -> app layer len = p[0]; p[0] = p[1]; p[1] = (u8)(len - 1); if( count > len + 1 ) count = len + 1; #else len = p[1]+2; if (count > len) count = len; #endif if (debug & DEBUG_DUMP1) DumpBuffer("< ", p, count); if (copy_to_user(buf, p, count)) return -EFAULT; idx++; if(idx >= NUM_INBUF) idx = 0; dev->inhead = idx; dbg1("%s(): dev=%08X return %d", __FUNCTION__, (uint)dev, count); return count; }
static int lpc_open(struct inode *inode, struct file *file) { int minor; // u32 cport; int idx; register DEV *dev; dbg1("%s(): MINOR=%d", __FUNCTION__, MINOR (inode->i_rdev)); /* DbgFlush(); struct timeval tv; do { do_gettimeofday(&tv); } while ( (tv.tv_sec % 10) != 0); */ minor = iminor(inode); if( minor > MAX_DEVICES ) { err("%s - invalid minor number %d", __FUNCTION__, minor); return -ENODEV; } dev = minor_table[minor]; if( !dev ) { err ("%s - error, can't find device for minor %d", __FUNCTION__, minor); return -ENODEV; } /* increment our usage count for the driver */ if (++dev->open_count == 1) { dev->active = 1; if( minor < MAX_LPCS ) { if( initialize_isacard(dev, minor) ) { /* decrement our usage count for the device */ --dev->open_count; return -ENODEV; } } else { #ifndef NO_PCI if( initialize_pcicard(dev, minor - MAX_LPCS) ) #endif { /* decrement our usage count for the device */ --dev->open_count; return -ENODEV; } } // dev->PciIntCount = dev->PciIntCountPlus = dev->PciIntCountMinus = 0; // dev->TimerCountPlus = dev->TimerCountMinus = 0; #if LINUX_VERSION_CODE < 0x020400 dev->rd_wait = NULL; // dev->wr_wait = NULL; #else // #ifdef DECLARE_WAITQUEUE init_waitqueue_head(&dev->rd_wait); // dbg8("%s(): init_waitqueue_head()", __FUNCTION__); // init_waitqueue_head(&dev->wr_wait); // #endif #endif dev->inhead = dev->intail = 0; dev->outhead = dev->outtail = 0; dev->state = ST_RESYNC; dev->active = 0; dev->wtc_exist = 0; init_timer( &dev->drvtimer ); dev->drvtimer.function = lpc_timer; dev->drvtimer.data = (unsigned long)dev; // cport = dev->cport; #if LINUX_VERSION_CODE < 0x020500 MOD_INC_USE_COUNT; #endif dbg1("%s(): before sm_stub()", __FUNCTION__); sm_stub( dev ); // Start state machine #if 01 #if 0 dbg8("%s(): before interruptible_sleep_on()", __FUNCTION__); interruptible_sleep_on( &dev->rd_wait ); // and read 1st reset msg dbg8("%s(): after interruptible_sleep_on()", __FUNCTION__); idx = dev->inhead; #else idx = dev->inhead; // if (qempty(&dev->ReadBufferQueue)) if (idx == dev->intail) { dbg1("%s(): qempty", __FUNCTION__); // up (&dev->sem); // if (wait_event_interruptible(dev->rd_wait, qhasdata(&dev->ReadBufferQueue))) if (wait_event_interruptible(dev->rd_wait, (idx != dev->intail) )) { /* decrement our usage count for the device */ --dev->open_count; return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ } dbg8("%s(): nach wait_event_interruptible(rd_wait)", __FUNCTION__); // if (down_interruptible(&dev->sem)) // return -ERESTARTSYS; } #endif idx++; if(idx >= NUM_INBUF) idx = 0; dev->inhead = idx; #endif } /* save our object in the file's private structure */ file->private_data = dev; dbg1("%s(): return 0", __FUNCTION__); return 0; }
inline static size_t get_list_num(size_t size) { #else static size_t get_list_num(size_t size) { #endif if(size <= BLKSIZE) return 0; if(size <= (BLKSIZE << 1)) return 1; if(size <= (BLKSIZE << 2)) return 2; if(size <= (BLKSIZE << 3)) return 3; if(size <= (BLKSIZE << 4)) return 4; if(size <= (BLKSIZE << 5)) return 5; if(size <= (BLKSIZE << 6)) return 6; if(size <= (BLKSIZE << 7)) return 7; return 8; } #endif #ifdef CLASS1 #ifdef INLINE inline static size_t get_nonempty_list_num(size_t size) { #else static size_t get_nonempty_list_num(size_t size) { #endif dbg1("[IN ] : get_nonempty_list_num():request[%ld] - class1\n", size); if(size <= BLKSIZE && GET_FREE_LISTP(0) != NULL) return 0; if((size <= 40) && GET_FREE_LISTP(1) != NULL) return 1; if((size <= 48) && GET_FREE_LISTP(2) != NULL) return 2; if((size <= 56) && GET_FREE_LISTP(3) != NULL) return 3; if(size <= (BLKSIZE << 1) && GET_FREE_LISTP(4) != NULL) return 4; if(size <= (BLKSIZE << 2) && GET_FREE_LISTP(5) != NULL) return 5; if(size <= (BLKSIZE << 3) && GET_FREE_LISTP(6) != NULL) return 6; if(size <= (BLKSIZE << 4) && GET_FREE_LISTP(7) != NULL) return 7; if(size <= (BLKSIZE << 5) && GET_FREE_LISTP(8) != NULL) return 8; if(size <= (BLKSIZE << 6) && GET_FREE_LISTP(9) != NULL) return 9; if(size <= (BLKSIZE << 7) && GET_FREE_LISTP(10) != NULL) return 10; return 11; } #ifdef INLINE inline static size_t get_list_num(size_t size) { #else static size_t get_list_num(size_t size) { #endif if(size <= BLKSIZE) return 0; if(size <= 40) return 1; if(size <= 48) return 2; if(size <= 56) return 3; if(size <= (BLKSIZE << 1)) return 4; if(size <= (BLKSIZE << 2)) return 5; if(size <= (BLKSIZE << 3)) return 6; if(size <= (BLKSIZE << 4)) return 7; if(size <= (BLKSIZE << 5)) return 8; if(size <= (BLKSIZE << 6)) return 9; if(size <= (BLKSIZE << 7)) return 10; return 11; } #endif /* debugging routines */ /* * mm_checkheap - called by mdriver for each operation in the trace file * */ void mm_checkheap(int v) { verbose = v; checkheap(); } #ifdef CHECKHEAP static void printblock(void *bp) { size_t hsize, halloc, hpalloc, fsize, falloc, fpalloc; hsize = GET_SIZE(HDRP(bp)); halloc = GET_ALLOC(HDRP(bp)); hpalloc = GET_PREV_ALLOC(HDRP(bp)); fsize = GET_SIZE(FTRP(bp)); falloc = GET_ALLOC(FTRP(bp)); fpalloc = GET_PREV_ALLOC(HDRP(bp)); if (hsize == 0) { printf("%p: EOL (size=0): header: [%ld:%c:%c]\n", bp, hsize, (hpalloc ? 'a' : 'f'), (halloc ? 'a' : 'f')); return; } printf("%p: header: [%ld:%c:%c] footer: [%ld:%c:%c]\n", bp, hsize, (hpalloc ? 'a' : 'f'), (halloc ? 'a' : 'f'), fsize, (fpalloc ? 'a' : 'f'), (falloc ? 'a' : 'f')); }
static int lpc_release(struct inode *inode, struct file *file) { register DEV *dev = (DEV *)(file->private_data); if (dev == NULL) { dbg1("%s() dev=NULL", __FUNCTION__); return -ENODEV; } dbg1("%s(): minor=%d open_count=%d", __FUNCTION__, dev->minor, dev->open_count); /* dbg("PciIntCount=%5d PciIntCountPlus=%5d PciIntCountMinus=%5d" "\nTimerCountPlus=%5d TimerCountMinus=%5d", dev->PciIntCount, dev->PciIntCountPlus, dev->PciIntCountMinus, dev->TimerCountPlus, dev->TimerCountMinus); DbgFlush(); */ if (dev->open_count <= 0) { dbg1("%s() device not opened", __FUNCTION__); return -ENODEV; } /* decrement our usage count for the device */ if (--dev->open_count <= 0) { u32 cport = dev->cport; dev->active = 1; dbg8("%s(): before del_timer()", __FUNCTION__); del_timer( &dev->drvtimer ); free_irq(dev->irq, dev); dbg8("%s(): after free_irq()", __FUNCTION__); dev->ctl = 0x0D; SETCTL; if (dev->PlxIntCsrPort) { u16 IntCsr = inw(dev->PlxIntCsrPort); dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr); IntCsr &= ~PLX_9050_INTR_ENABLE; outw(IntCsr, dev->PlxIntCsrPort); dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr); // release_region(dev->cport, 4); // release_region(dev->rport, 4); } else { outw( 0, dev->rport ); #ifndef CHECK_ISA_AT_LOAD_TIME release_region(cport-1, 4); #endif } // devs[minor] = NULL; // kfree( dev ); dev->open_count = 0; } file->private_data = 0; #if LINUX_VERSION_CODE < 0x020500 MOD_DEC_USE_COUNT; #endif dbg1("%s(): return 0", __FUNCTION__); // DbgFlush(); return 0; }
/* * coalesce - boundary tag coalescing. return ptr to coalesced block * */ static void* coalesce(void* bp) { size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp)); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); dbg1("[IN ] : coalesce()\n"); switch (prev_alloc | next_alloc) { case 3: /* neither of the adjacent blocks are free */ insert_free_block(bp); dbg1("[OUT] : coalesce() : neither of the adjacent blocks are free.\n"); return bp; case 2: /* next block is free */ size += GET_SIZE(HDRP(NEXT_BLKP(bp))); /* remove next block from free list */ remove_free_block(NEXT_BLKP(bp)); /* update header and footer pointers */ PUT(HDRP(bp), PACK(size, prev_alloc)); PUT(FTRP(bp), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(bp); dbg1("[OUT] : coalesce() : next block is free - merged \n"); return(bp); case 1: /* prev block is free */ size += GET_SIZE(HDRP(PREV_BLKP(bp))); /* remove this block from free list */ remove_free_block(PREV_BLKP(bp)); /* update header and footer pointers */ prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); PUT(FTRP(bp), PACK(size, prev_alloc)); PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(PREV_BLKP(bp)); dbg1("[OUT] : coalesce() : previous block is free - merged \n"); return(PREV_BLKP(bp)); default: /* both previous and next blocks are free */ size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp))); /* remove next block from free list */ remove_free_block(NEXT_BLKP(bp)); /* remove this block from free list */ remove_free_block(PREV_BLKP(bp)); /* update header and footer pointers */ prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc)); PUT(FTRP(NEXT_BLKP(bp)), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(PREV_BLKP(bp)); dbg1("[OUT] : coalesce() : both previous and next blocks are free - merged \n"); return(PREV_BLKP(bp)); } }
/* * malloc - allocates a block with requested size * (implementation issue: adjust size, extend size) * */ void *malloc(size_t size) { size_t asize = 0; size_t extendsize; char* bp; #ifdef TWEAK int k; #endif dbg1("[IN ] : malloc() - malloc(%ld)\n", size); checkheap(); if (!mm_initialized) mm_init(); /* Ignore spurious requests */ if (size <= 0) return NULL; #ifdef TWEAK /* * [Optimization for binary*.rep trace files] * if requested size is larger than 2^4=16 bytes, and close to power of two * (when the difference between requested size and its closest larger power of two * is smaller than one eighth of closest power of two) round up to power of two */ k = ceil_log_2(size); if( k >= 4 && ((1 << k) - size) <= (unsigned)(1 << (k -3))) { size = 1 << k; } dbg1("intermediate size : %ld\n", size); #endif #ifdef PUTBUG if (size <= MINBLKSIZE) { asize = MINBLKSIZE + WSIZE; } else { asize = DSIZE * ((size + DSIZE-1)/DSIZE); } #endif #ifdef ASIZE1 /* Adjust block size to include overhead and alignment reqs */ /* Block should at least have space for Header, Footer, Pred, Succ Pointers */ if (size <= MINBLKSIZE) { asize = MINBLKSIZE + WSIZE; } else { asize = DSIZE * ((size + WSIZE + DSIZE-1)/DSIZE); } #endif #ifdef ASIZE2 if (size <= 2*DSIZE+OVERHEAD) { asize = 2*DSIZE+OVERHEAD+OVERHEAD; } else { /* round up to the nearest order of 16 */ asize = 2*DSIZE * ((size + (OVERHEAD - WSIZE) + 2*DSIZE-1)/(2*DSIZE)); } #endif #ifdef ASIZE3 if (size <= DDSIZE){ asize = DDSIZE + DSIZE; } else { asize = DDSIZE*((size + (DSIZE - WSIZE) + (DDSIZE-1)) / DDSIZE); } #endif dbg("malloc: adjusted size %ld, class %ld\n", asize, get_list_num(asize)); /* Search the free list for a fit */ if ((bp = find_fit(asize)) != NULL) { place(bp, asize); dbg1("[OUT] : malloc() - found fit\n"); return bp; } /* No fit found. Get more memory and place the block */ extendsize = MAX(asize, CHUNKSIZE); if((bp = extend_heap(extendsize/WSIZE)) == NULL) return NULL; place(bp, asize); dbg1("[OUT] : malloc() - found fit failed, extended the heap\n"); return bp; }
/* * mm_init - initialize the malloc package. */ int mm_init(void) { int i; dbg1("[IN ] : mm_init()\n"); /* create the initial empty heap */ // if ((heap_listp = mem_sbrk(18*DSIZE + 4 * WSIZE)) == NULL) if ((heap_listp = mem_sbrk((MAXCLASS+1)*2*DSIZE + 4 * WSIZE)) == NULL) return -1; /* free_list_ptrs points to starting point of free list pointers */ free_list_ptrs = heap_listp; for (i=0; i<= MAXCLASS; i++) { PUT8(heap_listp+DSIZE*(i*2), NULL); PUT8(heap_listp+DSIZE*(i*2+1), NULL); } /* heap starting point is set right after the free list pointers */ heap_listp = heap_listp+DSIZE*2*(MAXCLASS+1); #if 0 /* set up segregated free list pointers */ PUT8(heap_listp, NULL); /* free list 0 head */ PUT8(heap_listp+DSIZE, NULL); /* free list 0 tail */ PUT8(heap_listp+DSIZE*2, NULL); /* free list 1 head */ PUT8(heap_listp+DSIZE*3, NULL); /* free list 1 tail */ PUT8(heap_listp+DSIZE*4, NULL); /* free list 2 head */ PUT8(heap_listp+DSIZE*5, NULL); /* free list 2 tail */ PUT8(heap_listp+DSIZE*6, NULL); /* free list 3 head */ PUT8(heap_listp+DSIZE*7, NULL); /* free list 3 tail */ PUT8(heap_listp+DSIZE*8, NULL); /* free list 4 head */ PUT8(heap_listp+DSIZE*9, NULL); /* free list 4 tail */ PUT8(heap_listp+DSIZE*10, NULL); /* free list 5 head */ PUT8(heap_listp+DSIZE*11, NULL); /* free list 5 tail */ PUT8(heap_listp+DSIZE*12, NULL); /* free list 6 head */ PUT8(heap_listp+DSIZE*13, NULL); /* free list 6 tail */ PUT8(heap_listp+DSIZE*14, NULL); /* free list 7 head */ PUT8(heap_listp+DSIZE*15, NULL); /* free list 7 tail */ PUT8(heap_listp+DSIZE*16, NULL); /* free list 8 head */ PUT8(heap_listp+DSIZE*17, NULL); /* free list 8 tail */ /* free_list_ptrs points to starting point of free list pointers */ free_list_ptrs = heap_listp; /* heap starting point is set right after the free list pointers */ heap_listp = heap_listp+DSIZE*18; #endif PUT(heap_listp, 0); /* alignment padding */ PUT(heap_listp+WSIZE, PACK(OVERHEAD, 3)); /* prologue header */ PUT(heap_listp+2*WSIZE, PACK(OVERHEAD, 3)); /* prologue footer */ PUT(heap_listp+3*WSIZE, PACK(0, 3)); /* epilogue header */ epilogue = (unsigned *)(heap_listp+3*WSIZE); /* update epilogue pointer */ heap_listp += 2*WSIZE; /* extends heap only on demand */ mm_initialized = 1; dbg1("[OUT] : mm_init()\n"); return 0; }
int lpc_watcher( DEV* dev, u8* buf ) { u32 cport, wtcport; u8 *s, *d; s16 count, i; u8 xcvr, cmd, tmp; int t; dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev); cport = dev->cport; wtcport = dev->wtcport; s = d = buf; #if 01 __get_user(count, s++); // Get the length __get_user(tmp, s++); count = (count << 8) + tmp; __get_user(cmd, s++); cmd &= 0x7F; #else count = *s++; // Get the length count = (count << 8) + *s++; cmd = *s++ & 0x7F; #endif if( cmd ) { // Normal case: request watcher firmware if(!dev->wtc_exist) return -ENODEV; t = jiffies + HZ/2; WTCHS; WOUT((u8)(count >> 8)); // Send the length WTCHS; WOUT((u8)(count & 0xFF)); WTCHS; WOUT(cmd); count--; while( count > 0 ) { WTCHS; #if 01 __get_user(tmp, s++); WOUT(tmp); // Send the data bytes #else WOUT(*s++); // Send the data bytes #endif count--; } WTCHS; WOUT(0); // EOM WTCHS; count = WIN; // Receive the length #if 01 __put_user(count & 0xFF, d++); WTCHS; count = (count << 8) + WIN; __put_user(count & 0xFF, d++); #else *d++ = count & 0xFF; WTCHS; count = (count << 8) + WIN; *d++ = count & 0xFF; #endif i = count; while( i > 0 ) { WTCHS; #if 01 tmp = WIN; __put_user(tmp, d++); #else *d++ = WIN; #endif i--; } } else { // Special case: firmware download