Changeset 04c5ac7 in rtems


Ignore:
Timestamp:
Jul 25, 1998, 4:20:14 PM (23 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
dfb16ce
Parents:
c1da250
Message:

Removed z85c30_flush().

Reworked transmit interrupt processing to remove ring buffer and
to mask the TX empty interrupt when it was not expected. This code
now uses termios to buffer TX output.

Location:
c/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libchip/serial/z85c30.c

    rc1da250 r04c5ac7  
    6464  libchip_serial_default_probe,  /* deviceProbe */
    6565  z85c30_open,                   /* deviceFirstOpen */
    66   z85c30_flush,                  /* deviceLastClose */
     66  NULL,                          /* deviceLastClose */
    6767  NULL,                          /* deviceRead */
    6868  z85c30_write_support_int,      /* deviceWrite */
     
    216216)
    217217{
     218
     219  z85c30_initialize_port(minor);
     220
    218221  /*
    219222   * Assert DTR
     
    288291    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
    289292  }
    290 
    291   z85c30_initialize_port(minor);
    292293}
    293294
     
    550551   * Deal with any received characters
    551552   */
     553
    552554  while (ucIntPend&SCC_RR3_B_RX_IP)
    553555  {
     
    570572  }
    571573
    572   while (TRUE)
    573   {
     574  /*
     575   *  There could be a race condition here if there is not yet a TX
     576   *  interrupt pending but the buffer is empty.  This condition has
     577   *  been seen before on other z8530 drivers but has not been seen
     578   *  with this one.  The typical solution is to use "vector includes
     579   *  status" or to only look at the interrupts actually pending
     580   *  in RR3.
     581   */
     582
     583  while (TRUE) {
    574584    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
    575585    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
     
    582592    }
    583593 
     594#if 0
    584595    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
    585596      /*
     
    592603      break;
    593604    }
     605#endif
    594606 
    595     if (Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    596       Console_Port_Data[minor].bActive=FALSE;
    597       if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
     607    if (!rtems_termios_dequeue_characters(
     608                Console_Port_Data[minor].termios_data, 1)) {
     609      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
    598610        z85c30_negate_RTS(minor);
    599611      }
    600       /*
    601        * There is no data to transmit
    602        */
     612      Console_Port_Data[minor].bActive = FALSE;
     613      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
    603614      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
    604615      break;
    605616    }
    606617
    607     Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
    608 
    609     /*
    610      * transmit character
    611      */
    612     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, cChar);
    613 
    614     /*
    615      * Interrupt once FIFO has room
    616       */
    617     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
    618     break;
    619   }
    620 
    621   if (ucIntPend&SCC_RR3_B_EXT_IP) {
     618  }
     619
     620  if (ucIntPend & SCC_RR3_B_EXT_IP) {
    622621    /*
    623622     * Clear the external status interrupt
     
    671670
    672671/*
    673  *  z85c30_flush
    674  */
    675 
    676 Z85C30_STATIC int z85c30_flush(
    677   int major,
     672 *  z85c30_enable_interrupts
     673 *
     674 *  This routine enables the specified interrupts for this minor.
     675 */
     676
     677Z85C30_STATIC void z85c30_enable_interrupts(
    678678  int minor,
    679   void *arg
    680 )
    681 {
    682   while (!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    683     /*
    684      * Yield while we wait
    685      */
    686     if (_System_state_Is_up(_System_state_Get())) {
    687       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    688     }
    689   }
    690 
    691   z85c30_close(major, minor, arg);
    692 
    693   return(RTEMS_SUCCESSFUL);
    694 }
    695 
    696 /*
    697  *  z85c30_initialize_interrupts
    698  *
    699  *  This routine initializes the console's receive and transmit
    700  *  ring buffers and loads the appropriate vectors to handle the interrupts.
    701  *
    702  *  Input parameters:  NONE
    703  *
    704  *  Output parameters: NONE
    705  *
    706  *  Return values:     NONE
    707  */
    708 
    709 Z85C30_STATIC void z85c30_enable_interrupts(
    710   int minor
     679  int interrupt_mask
    711680)
    712681{
     
    717686  setReg     = Console_Port_Tbl[minor].setRegister;
    718687
    719   /*
    720    * Enable interrupts
    721    */
    722   (*setReg)(
    723     ulCtrlPort,
    724     SCC_WR0_SEL_WR1,
    725     SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX
    726   );
    727   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR2, 0);
    728   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
    729 
    730   /*
    731    * Reset interrupts
    732    */
    733   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
    734 }
     688  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
     689}
     690
     691/*
     692 *  z85c30_initialize_interrupts
     693 *
     694 *  This routine initializes the port to use interrupts.
     695 */
    735696
    736697Z85C30_STATIC void z85c30_initialize_interrupts(
     
    738699)
    739700{
     701  unsigned32     ulCtrlPort1;
     702  unsigned32     ulCtrlPort2;
     703  setRegister_f  setReg;
     704
     705  ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
     706  ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
     707  setReg      = Console_Port_Tbl[minor].setRegister;
     708
     709
    740710  z85c30_init(minor);
    741711
    742   Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
    743 
    744712  Console_Port_Data[minor].bActive=FALSE;
    745   if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
     713
     714  z85c30_initialize_port( minor );
     715
     716  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
    746717    z85c30_negate_RTS(minor);
    747718  }
    748719
    749   if (Console_Port_Tbl[minor].ulCtrlPort1== Console_Port_Tbl[minor].ulCtrlPort2) {
    750     /*
    751      * Only do this for Channel A
    752      */
    753 
    754     set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
    755   }
    756 
    757   z85c30_enable_interrupts(minor);
     720  set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
     721
     722  z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
     723
     724  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */
     725  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
     726
     727  /*
     728   * Reset interrupts
     729   */
     730
     731  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
    758732}
    759733
     
    770744  int   len)
    771745{
    772   int i;
    773   unsigned32 Irql;
    774 
    775   for (i=0; i<len;) {
    776     if (Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
    777       if (!Console_Port_Data[minor].bActive) {
    778         /*
    779          * Wake up the device
    780          */
    781         if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
    782           z85c30_assert_RTS(minor);
    783         }
    784         rtems_interrupt_disable(Irql);
    785         Console_Port_Data[minor].bActive=TRUE;
    786         z85c30_process(minor, SCC_RR3_B_TX_IP);
    787         rtems_interrupt_enable(Irql);
    788       } else {
    789         /*
    790          * Yield while we await an interrupt
    791          */
    792         rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    793       }
    794 
    795       /*
    796        * Wait for ring buffer to empty
    797        */
    798       continue;
    799     } else {
    800       Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
    801       i++;
     746  unsigned32     Irql;
     747  unsigned32     ulCtrlPort;
     748  setRegister_f  setReg;
     749
     750  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
     751  setReg     = Console_Port_Tbl[minor].setRegister;
     752
     753  /*
     754   *  We are using interrupt driven output and termios only sends us
     755   *  one character at a time.
     756   */
     757
     758  if ( !len )
     759    return 0;
     760
     761  /*
     762   *  Put the character out and enable interrupts if necessary.
     763   */
     764
     765  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
     766    z85c30_assert_RTS(minor);
     767  }
     768  rtems_interrupt_disable(Irql);
     769    if ( Console_Port_Data[minor].bActive == FALSE) {
     770      Console_Port_Data[minor].bActive = TRUE;
     771      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
    802772    }
    803   }
    804 
    805   /*
    806    * Ensure that characters are on the way
    807    */
    808   if (!Console_Port_Data[minor].bActive) {
    809     /*
    810      * Wake up the device
    811      */
    812     if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
    813             z85c30_assert_RTS(minor);
    814     }
    815     rtems_interrupt_disable(Irql);
    816     Console_Port_Data[minor].bActive=TRUE;
    817     z85c30_process(minor, SCC_RR3_B_TX_IP);
    818     rtems_interrupt_enable(Irql);
    819   }
    820 
    821   return (len);
     773    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
     774  rtems_interrupt_enable(Irql);
     775
     776  return 1;
    822777}
    823778
  • c/src/libchip/serial/z85c30.c

    rc1da250 r04c5ac7  
    6464  libchip_serial_default_probe,  /* deviceProbe */
    6565  z85c30_open,                   /* deviceFirstOpen */
    66   z85c30_flush,                  /* deviceLastClose */
     66  NULL,                          /* deviceLastClose */
    6767  NULL,                          /* deviceRead */
    6868  z85c30_write_support_int,      /* deviceWrite */
     
    216216)
    217217{
     218
     219  z85c30_initialize_port(minor);
     220
    218221  /*
    219222   * Assert DTR
     
    288291    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
    289292  }
    290 
    291   z85c30_initialize_port(minor);
    292293}
    293294
     
    550551   * Deal with any received characters
    551552   */
     553
    552554  while (ucIntPend&SCC_RR3_B_RX_IP)
    553555  {
     
    570572  }
    571573
    572   while (TRUE)
    573   {
     574  /*
     575   *  There could be a race condition here if there is not yet a TX
     576   *  interrupt pending but the buffer is empty.  This condition has
     577   *  been seen before on other z8530 drivers but has not been seen
     578   *  with this one.  The typical solution is to use "vector includes
     579   *  status" or to only look at the interrupts actually pending
     580   *  in RR3.
     581   */
     582
     583  while (TRUE) {
    574584    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
    575585    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
     
    582592    }
    583593 
     594#if 0
    584595    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
    585596      /*
     
    592603      break;
    593604    }
     605#endif
    594606 
    595     if (Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    596       Console_Port_Data[minor].bActive=FALSE;
    597       if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
     607    if (!rtems_termios_dequeue_characters(
     608                Console_Port_Data[minor].termios_data, 1)) {
     609      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
    598610        z85c30_negate_RTS(minor);
    599611      }
    600       /*
    601        * There is no data to transmit
    602        */
     612      Console_Port_Data[minor].bActive = FALSE;
     613      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
    603614      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
    604615      break;
    605616    }
    606617
    607     Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
    608 
    609     /*
    610      * transmit character
    611      */
    612     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, cChar);
    613 
    614     /*
    615      * Interrupt once FIFO has room
    616       */
    617     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
    618     break;
    619   }
    620 
    621   if (ucIntPend&SCC_RR3_B_EXT_IP) {
     618  }
     619
     620  if (ucIntPend & SCC_RR3_B_EXT_IP) {
    622621    /*
    623622     * Clear the external status interrupt
     
    671670
    672671/*
    673  *  z85c30_flush
    674  */
    675 
    676 Z85C30_STATIC int z85c30_flush(
    677   int major,
     672 *  z85c30_enable_interrupts
     673 *
     674 *  This routine enables the specified interrupts for this minor.
     675 */
     676
     677Z85C30_STATIC void z85c30_enable_interrupts(
    678678  int minor,
    679   void *arg
    680 )
    681 {
    682   while (!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    683     /*
    684      * Yield while we wait
    685      */
    686     if (_System_state_Is_up(_System_state_Get())) {
    687       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    688     }
    689   }
    690 
    691   z85c30_close(major, minor, arg);
    692 
    693   return(RTEMS_SUCCESSFUL);
    694 }
    695 
    696 /*
    697  *  z85c30_initialize_interrupts
    698  *
    699  *  This routine initializes the console's receive and transmit
    700  *  ring buffers and loads the appropriate vectors to handle the interrupts.
    701  *
    702  *  Input parameters:  NONE
    703  *
    704  *  Output parameters: NONE
    705  *
    706  *  Return values:     NONE
    707  */
    708 
    709 Z85C30_STATIC void z85c30_enable_interrupts(
    710   int minor
     679  int interrupt_mask
    711680)
    712681{
     
    717686  setReg     = Console_Port_Tbl[minor].setRegister;
    718687
    719   /*
    720    * Enable interrupts
    721    */
    722   (*setReg)(
    723     ulCtrlPort,
    724     SCC_WR0_SEL_WR1,
    725     SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX
    726   );
    727   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR2, 0);
    728   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
    729 
    730   /*
    731    * Reset interrupts
    732    */
    733   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
    734 }
     688  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
     689}
     690
     691/*
     692 *  z85c30_initialize_interrupts
     693 *
     694 *  This routine initializes the port to use interrupts.
     695 */
    735696
    736697Z85C30_STATIC void z85c30_initialize_interrupts(
     
    738699)
    739700{
     701  unsigned32     ulCtrlPort1;
     702  unsigned32     ulCtrlPort2;
     703  setRegister_f  setReg;
     704
     705  ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
     706  ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
     707  setReg      = Console_Port_Tbl[minor].setRegister;
     708
     709
    740710  z85c30_init(minor);
    741711
    742   Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
    743 
    744712  Console_Port_Data[minor].bActive=FALSE;
    745   if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
     713
     714  z85c30_initialize_port( minor );
     715
     716  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
    746717    z85c30_negate_RTS(minor);
    747718  }
    748719
    749   if (Console_Port_Tbl[minor].ulCtrlPort1== Console_Port_Tbl[minor].ulCtrlPort2) {
    750     /*
    751      * Only do this for Channel A
    752      */
    753 
    754     set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
    755   }
    756 
    757   z85c30_enable_interrupts(minor);
     720  set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
     721
     722  z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
     723
     724  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */
     725  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
     726
     727  /*
     728   * Reset interrupts
     729   */
     730
     731  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
    758732}
    759733
     
    770744  int   len)
    771745{
    772   int i;
    773   unsigned32 Irql;
    774 
    775   for (i=0; i<len;) {
    776     if (Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
    777       if (!Console_Port_Data[minor].bActive) {
    778         /*
    779          * Wake up the device
    780          */
    781         if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
    782           z85c30_assert_RTS(minor);
    783         }
    784         rtems_interrupt_disable(Irql);
    785         Console_Port_Data[minor].bActive=TRUE;
    786         z85c30_process(minor, SCC_RR3_B_TX_IP);
    787         rtems_interrupt_enable(Irql);
    788       } else {
    789         /*
    790          * Yield while we await an interrupt
    791          */
    792         rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    793       }
    794 
    795       /*
    796        * Wait for ring buffer to empty
    797        */
    798       continue;
    799     } else {
    800       Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
    801       i++;
     746  unsigned32     Irql;
     747  unsigned32     ulCtrlPort;
     748  setRegister_f  setReg;
     749
     750  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
     751  setReg     = Console_Port_Tbl[minor].setRegister;
     752
     753  /*
     754   *  We are using interrupt driven output and termios only sends us
     755   *  one character at a time.
     756   */
     757
     758  if ( !len )
     759    return 0;
     760
     761  /*
     762   *  Put the character out and enable interrupts if necessary.
     763   */
     764
     765  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
     766    z85c30_assert_RTS(minor);
     767  }
     768  rtems_interrupt_disable(Irql);
     769    if ( Console_Port_Data[minor].bActive == FALSE) {
     770      Console_Port_Data[minor].bActive = TRUE;
     771      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
    802772    }
    803   }
    804 
    805   /*
    806    * Ensure that characters are on the way
    807    */
    808   if (!Console_Port_Data[minor].bActive) {
    809     /*
    810      * Wake up the device
    811      */
    812     if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_RTSCTS) {
    813             z85c30_assert_RTS(minor);
    814     }
    815     rtems_interrupt_disable(Irql);
    816     Console_Port_Data[minor].bActive=TRUE;
    817     z85c30_process(minor, SCC_RR3_B_TX_IP);
    818     rtems_interrupt_enable(Irql);
    819   }
    820 
    821   return (len);
     773    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
     774  rtems_interrupt_enable(Irql);
     775
     776  return 1;
    822777}
    823778
Note: See TracChangeset for help on using the changeset viewer.