⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 horizon.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
    dev->tx_last = tx_channel;  }    PRINTD (DBG_TX, "using channel %u", tx_channel);    YELLOW_LED_OFF(dev);    // TX start transfer    {    unsigned int tx_len = skb->len;    unsigned int tx_iovcnt = ATM_SKB(skb)->iovcnt;    // remember this so we can free it later    dev->tx_skb = skb;        if (tx_iovcnt) {      // scatter gather transfer      dev->tx_regions = tx_iovcnt;      dev->tx_iovec = (struct iovec *) skb->data;      dev->tx_bytes = 0;      PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)",	      skb->data, tx_len);    } else {      // simple transfer      dev->tx_regions = 0;      dev->tx_iovec = 0;      dev->tx_bytes = tx_len;      dev->tx_addr = skb->data;      PRINTD (DBG_TX|DBG_BUS, "TX start simple transfer (addr %p, len %d)",	      skb->data, tx_len);    }        // and do the business    tx_schedule (dev, 0);      }    return 0;}/********** reset a card **********/static void __init hrz_reset (const hrz_dev * dev) {  u32 control_0_reg = rd_regl (dev, CONTROL_0_REG);    // why not set RESET_HORIZON to one and wait for the card to  // reassert that bit as zero? Like so:  control_0_reg = control_0_reg & RESET_HORIZON;  wr_regl (dev, CONTROL_0_REG, control_0_reg);  while (control_0_reg & RESET_HORIZON)    control_0_reg = rd_regl (dev, CONTROL_0_REG);    // old reset code retained:  wr_regl (dev, CONTROL_0_REG, control_0_reg |	   RESET_ATM | RESET_RX | RESET_TX | RESET_HOST);  // just guessing here  udelay (1000);    wr_regl (dev, CONTROL_0_REG, control_0_reg);}/********** read the burnt in address **********/static u16 __init read_bia (const hrz_dev * dev, u16 addr) {    u32 ctrl = rd_regl (dev, CONTROL_0_REG);    void WRITE_IT_WAIT (void) {    wr_regl (dev, CONTROL_0_REG, ctrl);    udelay (5);  }    void CLOCK_IT (void) {    // DI must be valid around rising SK edge    ctrl &= ~SEEPROM_SK;    WRITE_IT_WAIT();    ctrl |= SEEPROM_SK;    WRITE_IT_WAIT();  }    const unsigned int addr_bits = 6;  const unsigned int data_bits = 16;    unsigned int i;    u16 res;    ctrl &= ~(SEEPROM_CS | SEEPROM_SK | SEEPROM_DI);  WRITE_IT_WAIT();    // wake Serial EEPROM and send 110 (READ) command  ctrl |=  (SEEPROM_CS | SEEPROM_DI);  CLOCK_IT();    ctrl |= SEEPROM_DI;  CLOCK_IT();    ctrl &= ~SEEPROM_DI;  CLOCK_IT();    for (i=0; i<addr_bits; i++) {    if (addr & (1 << (addr_bits-1)))      ctrl |= SEEPROM_DI;    else      ctrl &= ~SEEPROM_DI;        CLOCK_IT();        addr = addr << 1;  }    // we could check that we have DO = 0 here  ctrl &= ~SEEPROM_DI;    res = 0;  for (i=0;i<data_bits;i++) {    res = res >> 1;        CLOCK_IT();        if (rd_regl (dev, CONTROL_0_REG) & SEEPROM_DO)      res |= (1 << (data_bits-1));  }    ctrl &= ~(SEEPROM_SK | SEEPROM_CS);  WRITE_IT_WAIT();    return res;}/********** initialise a card **********/static int __init hrz_init (hrz_dev * dev) {  int onefivefive;    u16 chan;    int buff_count;    HDW * mem;    cell_buf * tx_desc;  cell_buf * rx_desc;    u32 ctrl;    ctrl = rd_regl (dev, CONTROL_0_REG);  PRINTD (DBG_INFO, "ctrl0reg is %#x", ctrl);  onefivefive = ctrl & ATM_LAYER_STATUS;    if (onefivefive)    printk (DEV_LABEL ": Horizon Ultra (at 155.52 MBps)");  else    printk (DEV_LABEL ": Horizon (at 25 MBps)");    printk (":");  // Reset the card to get everything in a known state    printk (" reset");  hrz_reset (dev);    // Clear all the buffer memory    printk (" clearing memory");    for (mem = (HDW *) memmap; mem < (HDW *) (memmap + 1); ++mem)    wr_mem (dev, mem, 0);    printk (" tx channels");    // All transmit eight channels are set up as AAL5 ABR channels with  // a 16us cell spacing. Why?    // Channel 0 gets the free buffer at 100h, channel 1 gets the free  // buffer at 110h etc.    for (chan = 0; chan < TX_CHANS; ++chan) {    tx_ch_desc * tx_desc = &memmap->tx_descs[chan];    cell_buf * buf = &memmap->inittxbufs[chan];        // initialise the read and write buffer pointers    wr_mem (dev, &tx_desc->rd_buf_type, BUF_PTR(buf));    wr_mem (dev, &tx_desc->wr_buf_type, BUF_PTR(buf));        // set the status of the initial buffers to empty    wr_mem (dev, &buf->next, BUFF_STATUS_EMPTY);  }    // Use space bufn3 at the moment for tx buffers    printk (" tx buffers");    tx_desc = memmap->bufn3;    wr_mem (dev, &memmap->txfreebufstart.next, BUF_PTR(tx_desc) | BUFF_STATUS_EMPTY);    for (buff_count = 0; buff_count < BUFN3_SIZE-1; buff_count++) {    wr_mem (dev, &tx_desc->next, BUF_PTR(tx_desc+1) | BUFF_STATUS_EMPTY);    tx_desc++;  }    wr_mem (dev, &tx_desc->next, BUF_PTR(&memmap->txfreebufend) | BUFF_STATUS_EMPTY);    // Initialise the transmit free buffer count  wr_regw (dev, TX_FREE_BUFFER_COUNT_OFF, BUFN3_SIZE);    printk (" rx channels");    // Initialise all of the receive channels to be AAL5 disabled with  // an interrupt threshold of 0    for (chan = 0; chan < RX_CHANS; ++chan) {    rx_ch_desc * rx_desc = &memmap->rx_descs[chan];        wr_mem (dev, &rx_desc->wr_buf_type, CHANNEL_TYPE_AAL5 | RX_CHANNEL_DISABLED);  }    printk (" rx buffers");    // Use space bufn4 at the moment for rx buffers    rx_desc = memmap->bufn4;    wr_mem (dev, &memmap->rxfreebufstart.next, BUF_PTR(rx_desc) | BUFF_STATUS_EMPTY);    for (buff_count = 0; buff_count < BUFN4_SIZE-1; buff_count++) {    wr_mem (dev, &rx_desc->next, BUF_PTR(rx_desc+1) | BUFF_STATUS_EMPTY);        rx_desc++;  }    wr_mem (dev, &rx_desc->next, BUF_PTR(&memmap->rxfreebufend) | BUFF_STATUS_EMPTY);    // Initialise the receive free buffer count  wr_regw (dev, RX_FREE_BUFFER_COUNT_OFF, BUFN4_SIZE);    // Initialize Horizons registers    // TX config  wr_regw (dev, TX_CONFIG_OFF,	   ABR_ROUND_ROBIN | TX_NORMAL_OPERATION | DRVR_DRVRBAR_ENABLE);    // RX config. Use 10-x VC bits, x VP bits, non user cells in channel 0.  wr_regw (dev, RX_CONFIG_OFF,	   DISCARD_UNUSED_VPI_VCI_BITS_SET | NON_USER_CELLS_IN_ONE_CHANNEL | vpi_bits);    // RX line config  wr_regw (dev, RX_LINE_CONFIG_OFF,	   LOCK_DETECT_ENABLE | FREQUENCY_DETECT_ENABLE | GXTALOUT_SELECT_DIV4);    // Set the max AAL5 cell count to be just enough to contain the  // largest AAL5 frame that the user wants to receive  wr_regw (dev, MAX_AAL5_CELL_COUNT_OFF,	   (max_rx_size + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD);    // Enable receive  wr_regw (dev, RX_CONFIG_OFF, rd_regw (dev, RX_CONFIG_OFF) | RX_ENABLE);    printk (" control");    // Drive the OE of the LEDs then turn the green LED on  ctrl |= GREEN_LED_OE | YELLOW_LED_OE | GREEN_LED | YELLOW_LED;  wr_regl (dev, CONTROL_0_REG, ctrl);    // Test for a 155-capable card    if (onefivefive) {    // Select 155 mode... make this a choice (or: how do we detect    // external line speed and switch?)    ctrl |= ATM_LAYER_SELECT;    wr_regl (dev, CONTROL_0_REG, ctrl);        // test SUNI-lite vs SAMBA        // Register 0x00 in the SUNI will have some of bits 3-7 set, and    // they will always be zero for the SAMBA.  Ha!  Bloody hardware    // engineers.  It'll never work.        if (rd_framer (dev, 0) & 0x00f0) {      // SUNI      printk (" SUNI");            // Reset, just in case      wr_framer (dev, 0x00, 0x0080);      wr_framer (dev, 0x00, 0x0000);            // Configure transmit FIFO      wr_framer (dev, 0x63, rd_framer (dev, 0x63) | 0x0002);            // Set line timed mode      wr_framer (dev, 0x05, rd_framer (dev, 0x05) | 0x0001);    } else {      // SAMBA      printk (" SAMBA");            // Reset, just in case      wr_framer (dev, 0, rd_framer (dev, 0) | 0x0001);      wr_framer (dev, 0, rd_framer (dev, 0) &~ 0x0001);            // Turn off diagnostic loopback and enable line-timed mode      wr_framer (dev, 0, 0x0002);            // Turn on transmit outputs      wr_framer (dev, 2, 0x0B80);    }  } else {    // Select 25 mode    ctrl &= ~ATM_LAYER_SELECT;        // Madge B154 setup    // none required?  }    printk (" LEDs");    GREEN_LED_ON(dev);  YELLOW_LED_ON(dev);    printk (" ESI=");    {    u16 b = 0;    int i;    u8 * esi = dev->atm_dev->esi;        // in the card I have, EEPROM    // addresses 0, 1, 2 contain 0    // addresess 5, 6 etc. contain ffff    // NB: Madge prefix is 00 00 f6 (which is 00 00 6f in Ethernet bit order)    // the read_bia routine gets the BIA in Ethernet bit order        for (i=0; i < ESI_LEN; ++i) {      if (i % 2 == 0)	b = read_bia (dev, i/2 + 2);      else	b = b >> 8;      esi[i] = b & 0xFF;      printk ("%02x", esi[i]);    }  }    // Enable RX_Q and ?X_COMPLETE interrupts only  wr_regl (dev, INT_ENABLE_REG_OFF, INTERESTING_INTERRUPTS);  printk (" IRQ on");    printk (".\n");    return onefivefive;}/********** check max_sdu **********/static int check_max_sdu (hrz_aal aal, struct atm_trafprm * tp, unsigned int max_frame_size) {  PRINTD (DBG_FLOW|DBG_QOS, "check_max_sdu");    switch (aal) {    case aal0:      if (!(tp->max_sdu)) {	PRINTD (DBG_QOS, "defaulting max_sdu");	tp->max_sdu = ATM_AAL0_SDU;      } else if (tp->max_sdu != ATM_AAL0_SDU) {	PRINTD (DBG_QOS|DBG_ERR, "rejecting max_sdu");	return -EINVAL;      }      break;    case aal34:      if (tp->max_sdu == 0 || tp->max_sdu > ATM_MAX_AAL34_PDU) {	PRINTD (DBG_QOS, "%sing max_sdu", tp->max_sdu ? "capp" : "default");	tp->max_sdu = ATM_MAX_AAL34_PDU;      }      break;    case aal5:      if (tp->max_sdu == 0 || tp->max_sdu > max_frame_size) {	PRINTD (DBG_QOS, "%sing max_sdu", tp->max_sdu ? "capp" : "default");	tp->max_sdu = max_frame_size;      }      break;  }  return 0;}/********** check pcr **********/// something like this should be part of ATM Linuxstatic int atm_pcr_check (struct atm_trafprm * tp, unsigned int pcr) {  // we are assuming non-UBR, and non-special values of pcr  if (tp->min_pcr == ATM_MAX_PCR)    PRINTD (DBG_QOS, "luser gave min_pcr = ATM_MAX_PCR");  else if (tp->min_pcr < 0)    PRINTD (DBG_QOS, "luser gave negative min_pcr");  else if (tp->min_pcr && tp->min_pcr > pcr)    PRINTD (DBG_QOS, "pcr less than min_pcr");  else    // !! max_pcr = UNSPEC (0) is equivalent to max_pcr = MAX (-1)    // easier to #define ATM_MAX_PCR 0 and have all rates unsigned?    // [this would get rid of next two conditionals]    if ((0) && tp->max_pcr == ATM_MAX_PCR)      PRINTD (DBG_QOS, "luser gave max_pcr = ATM_MAX_PCR");    else if ((tp->max_pcr != ATM_MAX_PCR) && tp->max_pcr < 0)      PRINTD (DBG_QOS, "luser gave negative max_pcr");    else if (tp->max_pcr && tp->max_pcr != ATM_MAX_PCR && tp->max_pcr < pcr)      PRINTD (DBG_QOS, "pcr greater than max_pcr");    else {      // each limit unspecified or not violated      PRINTD (DBG_QOS, "xBR(pcr) OK");      return 0;    }  PRINTD (DBG_QOS, "pcr=%u, tp: min_pcr=%d, pcr=%d, max_pcr=%d",	  pcr, tp->min_pcr, tp->pcr, tp->max_pcr);  return -EINVAL;}/********** open VC **********/static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {  int error;  u16 channel;    struct atm_qos * qos;  struct atm_trafprm * txtp;  struct atm_trafprm * rxtp;    hrz_dev * dev = HRZ_DEV(atm_vcc->dev);  hrz_vcc vcc;  hrz_vcc * vccp; // allocated late  PRINTD (DBG_FLOW|DBG_VCC, "hrz_open %x %x", vpi, vci);  #ifdef ATM_VPI_UNSPEC  // UNSPEC is deprecated, remove this code eventually  if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) {    PRINTK (KERN_WARNING, "rejecting open with unspecified VPI/VCI (deprecated)");    return -EINVAL;  }#endif    // deal with possibly wildcarded VCs  error = atm_find_ci (atm_vcc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -