Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
    }
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
/* --------------------------------------------------------------------- */
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;
}
Exemplo n.º 5
0
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");
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
/* --------------------------------------------------------------------- */
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;	
}
Exemplo n.º 10
0
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++;
                }
            }
        }
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
// 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;		
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
/* --------------------------------------------------------------------- */
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;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
/* --------------------------------------------------------------------- */
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;
}
Exemplo n.º 18
0
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;
	}
}
Exemplo n.º 19
0
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;
        }
    }
Exemplo n.º 20
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;
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
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;
    }
Exemplo n.º 23
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;
    }
Exemplo n.º 24
0
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;
    }
Exemplo n.º 25
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'));
}
Exemplo n.º 26
0
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;
    }
Exemplo n.º 27
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));
	}
}
Exemplo n.º 28
0
/* 
 * 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;
}
Exemplo n.º 29
0
/* 
 * 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;
}
Exemplo n.º 30
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