u16 rd_ptr; u16 wr_ptr; 
u32 rd_ptr; u32 wr_ptr; 
static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {  unsigned short idle_channels;  short tx_channel = -1;  unsigned int spin_count;  PRINTD (DBG_FLOW|DBG_TX, "setup_idle_tx_channel %p", dev);    // better would be to fail immediately, the caller can then decide whether  // to wait or drop (depending on whether this is UBR etc.)  spin_count = 0;  while (!(idle_channels = rd_regw (dev, TX_STATUS_OFF) & IDLE_CHANNELS_MASK)) {    PRINTD (DBG_TX|DBG_WARN, "waiting for idle TX channel");    // delay a bit here    if (++spin_count > 100) {      PRINTD (DBG_TX|DBG_ERR, "spun out waiting for idle TX channel");      return -EBUSY;    }  }    // got an idle channel  {    // tx_idle ensures we look for idle channels in RR order    int chan = dev->tx_idle;        int keep_going = 1;    while (keep_going) {      if (idle_channels & (1<<chan)) {	tx_channel = chan;	keep_going = 0;      }      ++chan;      if (chan == TX_CHANS)	chan = 0;    }        dev->tx_idle = chan;  }    // set up the channel we found  {    // Initialise the cell header in the transmit channel descriptor    // a.k.a. prepare the channel and remember that we have done so.        tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel];    u16 rd_ptr;    u16 wr_ptr;    u16 channel = vcc->channel;        unsigned long flags;    spin_lock_irqsave (&dev->mem_lock, flags);        // Update the transmit channel record.    dev->tx_channel_record[tx_channel] = channel;        // xBR channel    update_tx_channel_config (dev, tx_channel, RATE_TYPE_ACCESS,			      vcc->tx_xbr_bits);        // Update the PCR counter preload value etc.    update_tx_channel_config (dev, tx_channel, PCR_TIMER_ACCESS,			      vcc->tx_pcr_bits);#if 0    if (vcc->tx_xbr_bits == VBR_RATE_TYPE) {      // SCR timer      update_tx_channel_config (dev, tx_channel, SCR_TIMER_ACCESS,				vcc->tx_scr_bits);            // Bucket size...      update_tx_channel_config (dev, tx_channel, BUCKET_CAPACITY_ACCESS,				vcc->tx_bucket_bits);            // ... and fullness      update_tx_channel_config (dev, tx_channel, BUCKET_FULLNESS_ACCESS,				vcc->tx_bucket_bits);    }#endif    // Initialise the read and write buffer pointers    rd_ptr = rd_mem (dev, &tx_desc->rd_buf_type) & BUFFER_PTR_MASK;    wr_ptr = rd_mem (dev, &tx_desc->wr_buf_type) & BUFFER_PTR_MASK;        // idle TX channels should have identical pointers    if (rd_ptr != wr_ptr) {      PRINTD (DBG_TX|DBG_ERR, "TX buffer pointers are broken!");      // spin_unlock... return -E...      // I wonder if gcc would get rid of one of the pointer aliases    }    PRINTD (DBG_TX, "TX buffer pointers are: rd %x, wr %x.",	    rd_ptr, wr_ptr);        switch (vcc->aal) {      case aal0:	PRINTD (DBG_QOS|DBG_TX, "tx_channel: aal0");	rd_ptr |= CHANNEL_TYPE_RAW_CELLS;	wr_ptr |= CHANNEL_TYPE_RAW_CELLS;	break;      case aal34:	PRINTD (DBG_QOS|DBG_TX, "tx_channel: aal34");	rd_ptr |= CHANNEL_TYPE_AAL3_4;	wr_ptr |= CHANNEL_TYPE_AAL3_4;	break;      case aal5:	rd_ptr |= CHANNEL_TYPE_AAL5;	wr_ptr |= CHANNEL_TYPE_AAL5;	// Initialise the CRC	wr_mem (dev, &tx_desc->partial_crc, INITIAL_CRC);	break;    }        wr_mem (dev, &tx_desc->rd_buf_type, rd_ptr);    wr_mem (dev, &tx_desc->wr_buf_type, wr_ptr);        // Write the Cell Header    // Payload Type, CLP and GFC would go here if non-zero    wr_mem (dev, &tx_desc->cell_header, channel);        spin_unlock_irqrestore (&dev->mem_lock, flags);  }    return tx_channel;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/b925556cc9e82b32ab68a7620b247f47193501a7/horizon.c/buggy/drivers/atm/horizon.c