kernels/linux-2.4.0/drivers/ieee1394/aic5800.c
/* This must be called with the async_queue_lock held. */
This must be called with the async_queue_lock held.
This must be called with the async_queue_lock held .
static void send_next_async(struct aic5800 *aic)
{
    int i;
    struct hpsb_packet *packet = aic->async_queue;
    reg_write( aic, AT_ChannelControl, 0x80000000);
    packet->header[1] = (packet->header[1] & 0xFFFF) | 
	(packet->header[0] & 0xFFFF0000);
    packet->header[0] = (packet->header[0] & 0xFFFF);
#ifndef __BIG_ENDIAN
    { u32 i;
    for ( i = 0 ; i < packet->header_size/sizeof(u32) ; i++ ) 
	packet->header[i] = cpu_to_be32( packet->header[i] ); 
    for ( i = 0 ; i < packet->data_size/sizeof(u32) ; i++ ) 
	packet->data[i] = cpu_to_be32( packet->data[i] ); 
    }
#endif
    i = 0;
    while (reg_read(aic, AT_ChannelStatus) & 0x400) {
	i++;
	if (i>5000) {
	    PRINT(KERN_ERR, aic->id, 
		  "runaway loop 1 in send_next_async() - bailing out...");
	    break;
	};
    };
    memset(aic->AT_program, 0, MAX_AT_PROGRAM_SIZE * sizeof(struct dma_cmd));
    if (packet->data_size) {
	aic->AT_program[0].control = ( DMA_CMD_OUTPUTMORE | DMA_KEY_STREAM0 ) + 
	    packet -> header_size;
	aic->AT_program[0].address = virt_to_bus( packet->header );
	aic->AT_program[1].control = ( DMA_CMD_OUTPUTLAST | DMA_KEY_STREAM0 
				       | DMA_INTR_ALWAYS ) 
	    + packet -> data_size;
	aic->AT_program[1].address = virt_to_bus( packet->data );
	aic->AT_program[2].control = DMA_CMD_STOP;
    } else {
	aic->AT_program[0].control = ( DMA_CMD_OUTPUTLAST | DMA_INTR_ALWAYS | 
				       DMA_KEY_STREAM0 ) + 
	    packet -> header_size;
	aic->AT_program[0].address = virt_to_bus( packet->header );
	aic->AT_program[1].control = DMA_CMD_STOP;
    };
    reg_write(aic, AT_CommandPtr, (unsigned int) virt_to_bus(aic->AT_program));
    i = 0;
    while (reg_read(aic, AT_CommandPtr) != (unsigned int) 
	   virt_to_bus(aic->AT_program)) {
		i++;
	if (i>5000) {
	    PRINT(KERN_ERR, aic->id, 
		  "runaway loop 2 in send_next_async() - bailing out...");
	    break;
	};
    };
    reg_write( aic, AT_ChannelControl, 0x80008000);
}
static void send_next_async ( struct aic5800 * aic ) { int i ; struct hpsb_packet * packet = aic -> async_queue ; reg_write ( aic , AT_ChannelControl , 0x80000000 ) ; packet -> header [ 1 ] = ( packet -> header [ 1 ] & 0xFFFF ) | ( packet -> header [ 0 ] & 0xFFFF0000 ) ; packet -> header [ 0 ] = ( packet -> header [ 0 ] & 0xFFFF ) ; #ifndef __BIG_ENDIAN { u32 i ; for ( i = 0 ; i < packet -> header_size / sizeof ( u32 ) ; i ++ ) packet -> header [ i ] = cpu_to_be32 ( packet -> header [ i ] ) ; for ( i = 0 ; i < packet -> data_size / sizeof ( u32 ) ; i ++ ) packet -> data [ i ] = cpu_to_be32 ( packet -> data [ i ] ) ; } #endif i = 0 ; while ( reg_read ( aic , AT_ChannelStatus ) & 0x400 ) { i ++ ; if ( i > 5000 ) { PRINT ( KERN_ERR , aic -> id , " " ) ; break ; } ; } ; memset ( aic -> AT_program , 0 , MAX_AT_PROGRAM_SIZE * sizeof ( struct dma_cmd ) ) ; if ( packet -> data_size ) { aic -> AT_program [ 0 ] . control = ( DMA_CMD_OUTPUTMORE | DMA_KEY_STREAM0 ) + packet -> header_size ; aic -> AT_program [ 0 ] . address = virt_to_bus ( packet -> header ) ; aic -> AT_program [ 1 ] . control = ( DMA_CMD_OUTPUTLAST | DMA_KEY_STREAM0 | DMA_INTR_ALWAYS ) + packet -> data_size ; aic -> AT_program [ 1 ] . address = virt_to_bus ( packet -> data ) ; aic -> AT_program [ 2 ] . control = DMA_CMD_STOP ; } else { aic -> AT_program [ 0 ] . control = ( DMA_CMD_OUTPUTLAST | DMA_INTR_ALWAYS | DMA_KEY_STREAM0 ) + packet -> header_size ; aic -> AT_program [ 0 ] . address = virt_to_bus ( packet -> header ) ; aic -> AT_program [ 1 ] . control = DMA_CMD_STOP ; } ; reg_write ( aic , AT_CommandPtr , ( unsigned int ) virt_to_bus ( aic -> AT_program ) ) ; i = 0 ; while ( reg_read ( aic , AT_CommandPtr ) != ( unsigned int ) virt_to_bus ( aic -> AT_program ) ) { i ++ ; if ( i > 5000 ) { PRINT ( KERN_ERR , aic -> id , " " ) ; break ; } ; } ; reg_write ( aic , AT_ChannelControl , 0x80008000 ) ; }
This must be called with the async_queue_lock held.
This must be called with the async_queue_lock held .
/* stop the channel program if it's still running */ /* re-format packet header for AIC-5800 chip */ /* Packet must be byte-swapped in non-big-endian environments, 
     * see AIC-5800 specification...
     */ /* typically we use only a few iterations here */ /* set data buffer address and packet length */ /* set program start address */ /* typically we use only a few iterations here */ /* run program */