示例#1
0
bool uplink_packet( int port, byte *buffer )
{
    byte length;

	CALL_MSG("starting uplink_packet()", ++pclta_call_level);
	
    write_byte_wait( port, CMD_ACK );
    read_byte_wait( port ); // dummy
    *buffer++ = length = (read_byte_wait( port ));  //first byte is length 
    
    DEBUG_MSG( "in uplink_packet() length = %d", length );
    
    
    if( length == 0 ) {
    	RETURN_MSG("uplink_packet() LENGTH=0", pclta_call_level-- );
    	return false; // drop it
	}
	
    while( length-- ) {
        *buffer++ = read_byte_wait( port );
		#ifdef DEBUG
			if((int)(buffer-1)%8 == 0)  // formating debug output.. 
				DEBUG_MSG("                    " );
        	printk( "[%2x] ", *(buffer-1) );
		#endif	
		CALL_MSG("downlink_packet()", ++pclta_call_level );

    }
    
    RETURN_MSG("finishing uplink_packet()", pclta_call_level-- );
    return true;
}
示例#2
0
int close_pclta( struct inode *inode, struct file *file )
{
    struct pclta_device *device = pclta_device_table[MINOR(inode->i_rdev)];

	CALL_MSG("close_pclta()", ++pclta_call_level );
	
    if( device == NULL ) {
		RETURN_MSG("close_pclta() ENXIO", pclta_call_level-- );
    	return -ENXIO; // no such device
	}
    if( device->state == Offline ) {
		RETURN_MSG("close_pclta() already closed", pclta_call_level-- );
    	return 0; // device already closed
	}
// karl removed this for 2.4 kernel 30 July 2001
//    if( file->f_count >1 ) {
//		RETURN_MSG("close_pclta() EBUSY", pclta_call_level-- );
//    	return -EBUSY; // not the last process
//    }
    
    device->state = Offline;
    init_hw( device->base_address, 0x00, device->txcvr_clock );  // turn off interupts
    close_device( device );
    MOD_DEC_USE_COUNT;

	RETURN_MSG("close_pclta()", pclta_call_level-- );
	
    return 0;
}
示例#3
0
void cleanup_hw( struct pclta_device *device )
{
	int io;
	
	CALL_MSG("cleanup_hw()", ++pclta_call_level );
	
	// don't bother if device undefined
    if( device == NULL ) {
		RETURN_MSG("cleanup_hw() DEV=NULL", pclta_call_level-- );
    	return;
	}

	io = device->base_address;
	
	// reset internal interrupt register
    write_byte_wait( io, CMD_XFER );
    write_byte_wait( io, 2 );
    write_byte_wait( io, niIRQENA );
    write_byte_wait( io, IRQPLRTY );
 
	// release I/O region and interrupt
    release_region( io, 4 );
    
    DEBUG_MSG("Freeing up Interrupt %d", device->interrupt);
    free_irq( device->interrupt,device );
    
    // free up other resources
    remove_device( device );

	RETURN_MSG("cleanup_hw() CLEANED", pclta_call_level-- );
}
示例#4
0
bool open_device( struct pclta_device * device )
{
	CALL_MSG( "Starting open_device()", ++pclta_call_level );
	
	// allocate and initialize buffers
	device->rx = kmalloc( sizeof(struct pclta_packet_buffer), GFP_KERNEL );
	if( device->rx == NULL ) {
		RETURN_MSG( "open_device() ERROR= device->rx == NULL", pclta_call_level-- );
		return false;
	}
	device->tx = kmalloc( sizeof(struct pclta_packet_buffer), GFP_KERNEL );
	if( device->tx == NULL ) {
		kfree( device->rx );
		RETURN_MSG( "open_device() ERROR= device->tx == NULL", pclta_call_level-- );
		return false;
	}
	
	init_buffers( device->rx );
	DEBUG_MSG("RECEIVE BUFFER");
	print_buffer(device->rx);

	init_buffers( device->tx );
	DEBUG_MSG("TRANSMIT BUFFER");
	print_buffer(device->tx);

		
	// set initial state of device
	device->restart_uplink = false;
	device->pclta_wait_queue = NULL;
//    last_packet_read_complete=true;	 // for incomplete reads
    
	RETURN_MSG( "open_device() SUCCESS", pclta_call_level-- );
	return true;
}
示例#5
0
bool wait_uplink_buffer( int port, int sec100, byte *buffer )
{
	int count=0;

	CALL_MSG("wait_uplink_buffer()", ++pclta_call_level );
	
	
	// initialize timeout timer
    setup_timeout( sec100 );
    
    // wait for uplink buffer, or timeout
    while( !(inb_p(status_reg(port)) & ULREADY) && !pclta_timeout )
    {
    	count++;
	}
    
    // uplink buffer ready, kill timeout timer
    del_timer( &pclta_timer_list );
    
    // unsuccessful if timed out
    if( pclta_timeout ) {
		RETURN_MSG("wait_uplink_buffer() TIMEOUT", pclta_call_level-- );
    	return false;
	}
	
	// otherwise, ready to send packet to device
    uplink_packet( port, buffer );
    DEBUG_MSG("Count = %d",count);
	RETURN_MSG("wait_uplink_buffer()", pclta_call_level-- );
    return true;
}
示例#6
0
struct pclta_device * create_device( int port, int irq, byte txcvr_clock )
{
    struct pclta_device *device;

	CALL_MSG( "create_device()", ++pclta_call_level );
	
	// allocate descriptor space
    device = kmalloc( sizeof(struct pclta_device), GFP_KERNEL );
    if( device == NULL ) {
		RETURN_MSG( "create_device() kmalloc error", pclta_call_level-- );
    	return NULL;
	}
	else {
		device->interrupt_queue = kmalloc( sizeof( struct tq_struct ), GFP_KERNEL );
		if( device->interrupt_queue == NULL ) {
			kfree( device );
			RETURN_MSG( "create_device() kmalloc error", pclta_call_level-- );
			return NULL;
		}
	}
	
    device->base_address = port;
    device->interrupt = irq;
    device->state = Offline;
    device->rx = device->tx = NULL; // initialize these later
    device->txcvr_clock = txcvr_clock;

	// initialize interrupt task queue
    device->interrupt_queue->routine = (void *)pclta_service;
    device->interrupt_queue->sync = 0;
    
	RETURN_MSG( "create_device()", pclta_call_level-- );
    return device;
}
示例#7
0
void close_device( struct pclta_device * device )
{
	CALL_MSG( "close_device()", ++pclta_call_level );
	
    if( device->state == Offline ) {
    	RETURN_MSG( "close_device()", pclta_call_level-- );
    	return;
	}
	
    kfree( device->rx );
    kfree( device->tx );
    device->tx = device->rx = NULL;
    
//    wake_up_interruptible( &device->pclta_wait_queue ); //  karl thinks this not needed  removed 1 aug 2001

    RETURN_MSG( "close_device()", pclta_call_level-- );
}
示例#8
0
int open_pclta( struct inode *inode, struct file *file )
{
	struct pclta_device *device = pclta_device_table[MINOR(inode->i_rdev)];
	file->private_data = device;

//	file->f_op=&pclta_fops;  karl test 13/07/2000

	CALL_MSG("open_pclta()", ++pclta_call_level );
	
	if( device == NULL ) {
		RETURN_MSG("open_pclta() ENXIO", pclta_call_level-- );
		return -ENXIO; // no such device
	}
	
	if( device->state != Offline ) {
		RETURN_MSG("open_pclta() EBUSY", pclta_call_level-- );
		return -EBUSY; // device busy
	}
	
	if( !open_device( device ) ) {
		RETURN_MSG("open_pclta() ENOMEM", pclta_call_level-- );
		return -ENOMEM; // out of memory
	}
	
	// program interrupt request line
//	outb_p(irq_mask[device->interrupt], selirq_reg(device->base_address) );  //removed 07/07/200  karl. added init_hw below

    DEBUG_MSG("Base Addy=0x0%x ; IRQ=%d ; IRQ MASK = 0x0%x \n",device->base_address, device->interrupt ,pclta_irq_mask[device->interrupt]);
    init_hw( device->base_address, pclta_irq_mask[device->interrupt], device->txcvr_clock );

    if( ! wait_reset(device->base_address, 500 ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_LRESET.\n", PCLTA_LRESET );
        return -EBUSY;
    } // waiting to leave reset state
	
		
	device->state = Idle;
	
	//enable_irq( device->interrupt );  // karl's test  07/07/2000

	MOD_INC_USE_COUNT;
	
	RETURN_MSG("open_pclta() OK", pclta_call_level-- );
	return 0;
}
示例#9
0
bool wait_reset( unsigned int port, int sec100 )
{
	CALL_MSG("wait_reset()", ++pclta_call_level );
	
    setup_timeout( sec100 );
    
    while( ( inb_p(status_reg(port)) & RESET ) && !pclta_timeout );
    
    del_timer( &pclta_timer_list );
    
    if( pclta_timeout ) {
		RETURN_MSG("wait_reset() false", pclta_call_level-- );
    	return false;
	}
	
	RETURN_MSG("wait_reset() true", pclta_call_level-- );
    return true;
}
示例#10
0
bool write_byte_timeout( int port, byte data_byte, int sec100 )
{
	CALL_MSG("write_byte_timeout()", ++pclta_call_level );

    setup_timeout( sec100 );
    while( ( inb_p( status_reg(port) ) & _READY ) && ( ! pclta_timeout ) );
    
    if( ! pclta_timeout )
    	outb_p( data_byte, data_reg(port) );
	
    del_timer( &pclta_timer_list );
    
    if( pclta_timeout ) {
    	RETURN_MSG( "write_byte_timeout() false", pclta_call_level-- );
		return false;
	}
	
   	RETURN_MSG( "write_byte_timeout() true", pclta_call_level-- );
    return true;
}
示例#11
0
void cleanup_module( void )
{
    unsigned int i;

	CALL_MSG("cleanup_module()", ++pclta_call_level );
	
    for( i=0; i<MAX_DEVICES; i++ )
    	cleanup_hw( pclta_device_table[i] );
	
    unregister_chrdev( pclta_major, pclta_device_name );

	RETURN_MSG("cleanup_module()", pclta_call_level-- );
}
示例#12
0
//////////////////TEST FUNCTION
void print_buffer( struct pclta_packet_buffer * packet_buffer )
{
	unsigned int i;
	
	CALL_MSG( "print_buffer()\n", ++pclta_call_level );

    DEBUG_MSG("Buffer  head= %ud tail= %ud\n",(unsigned int) packet_buffer->head,(unsigned int) packet_buffer->tail);
	for( i=0; i<PACKETS_PER_BUFFER; i++ ) {
	
	    DEBUG_MSG("PB: %d ; Busy= %d ; L= %d ; d0= %x ; d1= %x ; d2= %x \n",i ,packet_buffer->buffer[i].busy,packet_buffer->buffer[i].length,packet_buffer->buffer[i].data[0],packet_buffer->buffer[i].data[1],packet_buffer->buffer[i].data[2]);
	}
	// start at beginning of buffer

	RETURN_MSG( "print_buffer()", pclta_call_level-- );
}
示例#13
0
void downlink_packet( int port, byte * buffer )
{
    byte length = *buffer;   //length is first byte in buffer.

	CALL_MSG("downlink_packet()", ++pclta_call_level );
	
	DEBUG_MSG("IN downlink_packet() LENGTH= %d",length);
	
    write_byte_wait( port, length );
    
    while( length-- )
    	write_byte_wait( port, *(++buffer) );
	
	RETURN_MSG("downlink_packet()", pclta_call_level-- );

}
示例#14
0
void pclta_start_downlink( struct pclta_device *dev )
{
    struct pclta_packet *packet_buffer;
    unsigned char ni_cmd, buff_p, status;

	CALL_MSG("Starting pclta_start_downlink()", ++pclta_call_level );
//	DEBUG_MSG
	
    if( dev->state == Idle ) {
        DEBUG_MSG("pclta_start_downlink () Device is idle.  checking if busy");

        packet_buffer = dev->tx->tail;
        if( packet_buffer->busy ) {
            ni_cmd = packet_buffer->data[0];
	        DEBUG_MSG("NICOMMAND = [0x%2x]",ni_cmd);
            if( ni_cmd == niSERVICE ) {
                buff_p = DLPBA;
                ni_cmd = niCOMM;
            }
	    	else {
                buff_p = ni_cmd & niPRIORITY ? DLPBA : DLBA;
                ni_cmd &= NI_Q_CMD;
            }
	    
            status = inb_p( status_reg(dev->base_address) );
	    
            if( ni_cmd == niCOMM || ni_cmd == niNETMGMT ) {
                if( status & buff_p )
                    dev->state = Transfer;
            }
	    	else
                dev->state = Transfer;
		
            if( dev->state == Transfer ) {
                if( status & RESET )
                    dev->state = Idle;
                else {
                    DEBUG_MSG( "xfer_start, " );
                    write_byte_wait( dev->base_address, CMD_XFER );
                    DEBUG_MSG( "xfer_done, base addy = 0x0%x ",dev->base_address );

                }
            }
        }
    }
	RETURN_MSG("Finishing pclta_start_downlink()", pclta_call_level-- );
}
示例#15
0
void init_buffers( struct pclta_packet_buffer * packet_buffer )
{
	unsigned int i;
	int buffer_index;
	
	CALL_MSG( "init_buffers()", ++pclta_call_level );
	
	for( i=0; i<PACKETS_PER_BUFFER; i++ ) {
		packet_buffer->buffer[i].next = & packet_buffer->buffer[(i+1)%PACKETS_PER_BUFFER];
		packet_buffer->buffer[i].busy = false;
		packet_buffer->buffer[i].length = 0;
		for (buffer_index=0; buffer_index < MAX_PACKET_SIZE; buffer_index++)  // default data to 0
		    packet_buffer->buffer[i].data[buffer_index] = 0;

	 
	
	}
	// start at beginning of buffer

	packet_buffer->head = packet_buffer->tail = &packet_buffer->buffer[0];

	RETURN_MSG( "init_buffers()", pclta_call_level-- );
}
示例#16
0
void init_hw( int port, byte irq, byte txcvr_clock )
{
	CALL_MSG("init_hw()", ++pclta_call_level );

	DEBUG_MSG("PROGRAM IRQ LINE Writing 0x0%x to 0x0%x",irq, selirq_reg(port));	
	// program interrupt request line
    outb_p( irq, selirq_reg(port) );
    
    // reset device
   	DEBUG_MSG("RESET device with txcvr_clock Writing 0x0%x to 0x0%x",txcvr_clock, clkrst_reg(port));	
    outb_p( txcvr_clock, clkrst_reg(port) );
   	DEBUG_MSG("UNREST Device Writing 0x0%x to 0x0%x", PCLTA_RESET | txcvr_clock, clkrst_reg(port) );
    outb_p( PCLTA_RESET | txcvr_clock, clkrst_reg(port) );


   	DEBUG_MSG("ACK IRQ hardware Writing 0x0%x to 0x0%x",~CLRIRQ, clrirq_reg(port) );
    
    // acknowledge IRQ hardware
    if( irq )
    	outb_p( ~CLRIRQ, clrirq_reg(port) );

	RETURN_MSG("init_hw()", pclta_call_level-- );
}
示例#17
0
int email_grammar_checker(char *string)
{
	int i=0,j=0;
	int val_start,val_end;
	int iteration_values[2][2]={{0,0},{0,0}};
	int len=0;			//length of string 
	int position_at=0;	//location of at
	int is_dot=0;		//found dot? //rule 3
	int count_at=0;
	int pass=SW_FAIL;	//pass variable (default:FAIL)
	int char_count;		//the number of letter
	char *p;
	char prev_ch=0;
	
/*
1) an email address has two parts, Local and Domain, separated by an '@' char
2) both the Local part and the Domain part consist of a sequence of Words, separated by '.' characters
3) the Local part has one or more Words; the Domain part has two or more Words (i.e. at least one '.')
4) each Word is a sequence of one or more characters, starting with a letter
5) each Word ends with a letter or a digit
6) between the starting and ending chars, there may be any number of letters, digits or hyphens ('-')
*/

//---------------------------------------------------------------------------------------
//RULE 1
//1) an email address has two parts, Local and Domain, separated by an '@' char
//String is not safisfied with rule 1( '@' should be located between Local and Domain.);
	p=string;
	len=0;
	count_at=0;
	pass=SW_FAIL;

	while(*p)
	{
		if(func_is_at(*p)== IS_TRUE)
		{
			pass=SW_PASS;				//this rule is valid because of the presence of @.
			position_at=(int)(p-string);//get position of '@'.
			count_at++;
		}
		p++;
		len++;
	}
	if(count_at>1) // abc@[email protected]
		pass=SW_FAIL;

	if(pass==SW_FAIL)
		RETURN_MSG("err:r1",RET_INVALID);
		

	//Local Checking scope
	iteration_values[0][0]=0;
	iteration_values[0][1]=position_at;
	//Domain Checking scope
	iteration_values[1][0]=position_at+1;
	iteration_values[1][1]=len;
	pass=SW_PASS;

//----------------------------------------------------------------------------------------
//RULE 2
//2) both the Local part and the Domain part consist of a sequence of Words, separated by '.' characters
//Words should be separated by '.'. So, ".." is not permitted.

	for(j=0;j<2;j++)
	{
		val_start=iteration_values[j][0];
		val_end=iteration_values[j][1];

		if(func_is_dot(string[val_start])== IS_TRUE)					// [email protected] =>FAIL
			pass=SW_FAIL;
		else if(func_is_dot(string[val_end-1])== IS_TRUE) // [email protected] =>FAIL
					pass=SW_FAIL;
	
		if(pass == SW_FAIL) 		
			RETURN_MSG("err:r2-0",RET_INVALID);


		prev_ch= string[val_start];
		for(i=val_start+1;i<val_end;i++)
		{
			if(prev_ch==string[i])
				if(func_is_dot(prev_ch)== IS_TRUE)			//  [email protected]
				{
					pass=SW_FAIL;
					break;
				}
	
			prev_ch=string[i];
		}

		if(pass == SW_FAIL)
			RETURN_MSG("err:r2-1",RET_INVALID);

	}

//----------------------------------------------------------------------------------------
//RULE 3	
//3) the Local part has one or more Words; the Domain part has two or more Words (i.e. at least one '.')

//Local Checking
	char_count=0;
	for(i=0;i<position_at;i++)
	{
		if(func_is_alphabet(string[i]) == IS_TRUE)
			char_count++;
	}
	if(char_count<1)
		pass=SW_FAIL;

	if(pass == SW_FAIL)
			RETURN_MSG("err:r3-1",RET_INVALID);


//Domail Checking
	char_count=0;
	is_dot=0;
	for(i=position_at+2;i<len;i++)
	{
		if(func_is_alphabet(string[i]) == IS_TRUE)
			char_count++;
		else if(func_is_dot(string[i]) == IS_TRUE) 
			is_dot=1; //[email protected] 
	}
	if(char_count<2 || is_dot==0) // haha@ad  
		pass=SW_FAIL;

	if(pass == SW_FAIL)
			RETURN_MSG("err:r3-2",RET_INVALID);

//----------------------------------------------------------------------------------------
//RULE 4	
//each Word is a sequence of one or more characters, starting with a letter
	
	for(j=0;j<2;j++)
	{
		val_start=iteration_values[j][0];
		val_end=iteration_values[j][1];

		prev_ch=string[val_start];
		if(func_is_alphabet(prev_ch) == IS_FALSE) //[email protected]
			pass=SW_FAIL;
		else 
		for(i=val_start+1;i<val_end;i++)
		{
			if(func_is_dot(prev_ch)== IS_TRUE)
			{
				if(func_is_alphabet(string[i]) == IS_FALSE) // [email protected]
				{
					pass=SW_FAIL;
					break;
				}
			}
		}

		if(pass == SW_FAIL)
			RETURN_MSG("err:r4",RET_INVALID);

	}


//----------------------------------------------------------------------------------------
//RULE 5
//5) each Word ends with a letter or a digit
	for(j=0;j<2;j++)
	{
		val_start=iteration_values[j][0];
		val_end=iteration_values[j][1];

		if(!((func_is_alphabet(string[val_end-1]) ==IS_TRUE) || (func_is_number(string[val_end-1])==IS_TRUE)))
		// abc [d]  @abc.com is a letter or a digit
			pass=SW_FAIL;
		else
		{
			prev_ch=string[val_start];
			for(i=val_start+1;i<val_end;i++)
			{
				if(func_is_dot(string[i]) == IS_TRUE) // abc[.]@abc.com
				{
					if(!((func_is_alphabet(prev_ch) == IS_TRUE) || (func_is_number(prev_ch) == IS_TRUE)))
					{
						pass=SW_FAIL;
						break;
					}
				}

				prev_ch=string[i];
			}
		}

		if(pass == SW_FAIL)
				RETURN_MSG("err:r5",RET_INVALID);
	}


//----------------------------------------------------------------------------------------
//RULE 6
//6) between the starting and ending chars, there may be any number of letters, digits or hyphens ('-')
	for(j=0;j<2;j++)
	{
		val_start=iteration_values[j][0];
		val_end=iteration_values[j][1];
	
		if(func_is_dash(string[val_start])== IS_TRUE || func_is_dash(string[val_end-1]) == IS_TRUE) // [email protected]
			pass=SW_FAIL;
		else
		{
			prev_ch=string[val_start];
			for(i=val_start+1;i<val_end;i++)
			{
				if(func_is_dot(prev_ch) == IS_TRUE)// [.][email protected]
				{
					if(func_is_dash(string[i]) == IS_TRUE) // .[-][email protected]
					{
						pass=SW_FAIL;
						break;
					}
				}
				else if(func_is_dot(string[i]) == IS_TRUE)	// abc-[.][email protected]
					{
						if(func_is_dash(prev_ch) == IS_TRUE) // ab[-][email protected]
						{
							pass=SW_FAIL;
							break;
						}
					}

				prev_ch=string[i];
			}
		}
	
		if(pass == SW_FAIL)
			RETURN_MSG("err:r6-1",RET_INVALID);
	}

//------------------------------------------------------------------------------------------
	return RET_VALID;
}
示例#18
0
//---------------------------------------------
// read_pclta()
ssize_t read_pclta( struct file *dev_file, char * buffer, size_t count, loff_t * offset )

//long read_pclta(struct inode* dev_inode, struct file *dev_file, char *buffer, unsigned long count)
//read_write_t read_pclta(struct inode*, struct file *dev_file, char * buffer, count_t count)

{
	struct pclta_device *device = dev_file->private_data;
	struct pclta_packet * packet_buffer;
	byte temp_swap=0;

	CALL_MSG("Starting read_pclta()", ++pclta_call_level );
		
	// verification
	if( device == NULL ) {
		RETURN_MSG("read_pclta() ENXIO", pclta_call_level-- );
		return -ENXIO;
	}
	
//	if (last_packet_read_complete==true)
	
    	// wait for uplink packet
	packet_buffer = device->rx->tail; // read from tail.
    print_buffer(device->rx);
	

	// no data available
	if( ! packet_buffer->busy && (dev_file->f_flags & O_NONBLOCK) ) {
		RETURN_MSG("read_pclta() EWOULDBLOCK", pclta_call_level-- );
		return -EWOULDBLOCK;
	}
	else
		if( ! packet_buffer->busy ) {
    		DEBUG_MSG( "in read_pclta() packet_buffer  ADDY(tail)=%ud", (unsigned int) &packet_buffer);
     		DEBUG_MSG("p_b->length= %d ;data0=; %x data1= %x ", packet_buffer->length,packet_buffer->data[0],packet_buffer->data[1]);

			RETURN_MSG("read_pclta() ENODATA", pclta_call_level-- );
			return -ENODATA;		// nothing available
		}
		
	// check if enough space available to read.
	if( count <= packet_buffer->length ) {
	    DEBUG_MSG("ERROR: count= %d    ;  packet_buffer->length= %d",(int) count, packet_buffer->length);
		RETURN_MSG("read_pclta() EINVAL;  count > packet_buffer->length", pclta_call_level-- );
		return -EINVAL;

	}

    //swap the first two bytes and subtract one from the length
    temp_swap=packet_buffer->data[0]-1;  // subtract one from length
    packet_buffer->data[0]=packet_buffer->data[1];
    packet_buffer->data[1]=temp_swap;
	
	// copy data from buffer to user space
	copy_to_user( buffer, &packet_buffer->data[0], packet_buffer->length+1 );

	// update buffer data
	packet_buffer->busy = false;
	device->rx->tail = packet_buffer->next;
	
	
//	restart uplink if backed off
	if( device->restart_uplink ) {
		disable_irq( device->interrupt );
		device->restart_uplink = false;
		if( device->state == Idle )
			pclta_service( device );
		enable_irq( device->interrupt );
	} // restart uplink, but only if device is in the Idle State

	RETURN_MSG("SUCCESS read_pclta() length = %d", pclta_call_level--, packet_buffer->length );
	
	return packet_buffer->length+1;
}
示例#19
0
//int write_pclta( struct file *file, const char *buffer, size_t count, loff_t * offset)						
ssize_t write_pclta( struct file *file, const char *buffer, size_t count, loff_t *offset )

{
    struct pclta_device *device = file->private_data;
    struct pclta_packet *packet_buffer;
    unsigned int length_of_msg;
    byte temp_swap=0;
    byte temp_buffer[512];
    int sum_sent=0;  // sum of bytes sent.
    byte *msg_ptr;    
	
	CALL_MSG("Starting write_pclta()", ++pclta_call_level);

	
	// verification
    if( device == NULL ) {
    	RETURN_MSG("write_pclta() ERROR device=NULL", pclta_call_level-- );
    	return -ENXIO;
	}
	
    if( 0 > verify_area( VERIFY_READ, buffer, count ) ) {
    	RETURN_MSG("write_pclta() ERROR= EFAULT verify area ", pclta_call_level-- );
    	return -EFAULT;
	}
	
    if( count < 2 ) {
    	RETURN_MSG("write_pclta() ERROR=EINVAL  count < 2 ", pclta_call_level-- );
    	return -EINVAL;
	}

	//    length=count; // karl

//    copy_from_user(&packet_buffer->length, buffer, count );  // reads NI command into the legth position

    copy_from_user(temp_buffer, buffer,count );  // reads NI command into the legth position
	msg_ptr=temp_buffer;
	while (sum_sent < count) // must send all data
	{
	
    	// wait for free buffer entry
        packet_buffer = device->tx->head;
    
    
        // no buffer available
        if( packet_buffer->busy && (file->f_flags & O_NONBLOCK) ) {
        	RETURN_MSG("write_pclta()  ERROR write_pclta()", pclta_call_level-- ); 
        	return -EWOULDBLOCK;
    	}
    	else
    		if( packet_buffer->busy ) {
    			RETURN_MSG("write_pclta() ERROR EAGAIN", pclta_call_level-- );
	    		return -EAGAIN;		// retry later
        	}


        length_of_msg=*(msg_ptr+1)+2;
        memcpy(&packet_buffer->length,msg_ptr,length_of_msg);
        

//	DEBUG_MSG("in write_pclta() Length=[%x] D0=[%x] ;D1=[%x] ;D2=[%x] ;D3=[%x] ;D4=[%x] ;D5=[%x] ;D6=[%x]",packet_buffer->length,packet_buffer->data[0],packet_buffer->data[1],packet_buffer->data[2],packet_buffer->data[3],packet_buffer->data[4],packet_buffer->data[5],packet_buffer->data[6]);

      //swap the first two bytes and subtract one from the length
        temp_swap=packet_buffer->data[0];  // [0] is the length
        packet_buffer->data[0]=packet_buffer->length;  // put the NI command at postion 0 
        packet_buffer->length=temp_swap + 1; 
//	DEBUG_MSG("write_pclta() FIX Length=[%x] D0=[%x] ;D1=[%x] ;D2=[%x] ;D3=[%x] ;D4=[%x] ;D5=[%x] ;D6=[%x]",packet_buffer->length,packet_buffer->data[0],packet_buffer->data[1],packet_buffer->data[2],packet_buffer->data[3],packet_buffer->data[4],packet_buffer->data[5],packet_buffer->data[6]);


    	// update output buffers and start downlink transfer
        device->tx->head = packet_buffer->next;
        packet_buffer->busy = true;
    
        sum_sent+=length_of_msg;
	    msg_ptr+=length_of_msg;
    }
    
    if( device->state == Idle ) {
        disable_irq( device->interrupt );
	    DEBUG_MSG("in write_pclta()  about to start_downlink  interupt= %d",device->interrupt);
        pclta_start_downlink( device );
        enable_irq( device->interrupt );
    }

       
    
	RETURN_MSG("write_pclta() finished. ", pclta_call_level-- );
    return count;
}