Changeset 198d851 in rtems


Ignore:
Timestamp:
Jul 15, 1998, 11:20:33 PM (22 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
49370cd
Parents:
27a66bd
Message:

Switched from driver's own buffering to using termios. This eliminated
the need for the ringbuffer manipulation in this driver. It should
also allow the removal of mc68681_flush. This greatly simplified the
interrupt processing.

Reworked Interrupt Mask Register handling. Added imr field to the device
context. This handling makes sure that the IMR accurately reflects the
state of the port in use and its mate. This required the reworking of
the mc68681_enable_interrupts() routine to allow for the specification
of which interrupt sources were being enabled/disabled.

Reworked initialization to reset using port address rather than chip
base address. Basically we were always resetting port 0.

Added deviceType field which allows for multiple chips of the same
class to have the same vector number.

Location:
c/src
Files:
2 edited

Legend:

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

    r27a66bd r198d851  
    3636  libchip_serial_default_probe,   /* deviceProbe */
    3737  mc68681_open,                   /* deviceFirstOpen */
    38   mc68681_flush,                  /* deviceLastClose */
     38  NULL,                           /* deviceLastClose */
    3939  NULL,                           /* deviceRead */
    4040  mc68681_write_support_int,      /* deviceWrite */
     
    294294         Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) {
    295295      pmc68681Context->mate = port;
     296      pmc68681Context->imr  = 0;
    296297      break;
    297298    }
     
    329330   */
    330331
    331   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
    332   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
    333   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
    334   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
    335   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
    336   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
    337   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
    338 
    339 
    340   (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 );
    341   (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 );
     332  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
     333  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
     334  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
     335  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
     336  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
     337  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
     338  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
     339
     340
     341  (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );
     342  (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );
    342343
    343344  /*
     
    345346   */
    346347
    347   (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0));
     348  mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );
    348349}
    349350
     
    499500
    500501  for(minor=0 ; minor<Console_Port_Count ; minor++) {
    501     if(vector == Console_Port_Tbl[minor].ulIntVector) {
     502    if(Console_Port_Tbl[minor].ulIntVector == vector &&
     503       Console_Port_Tbl[minor].deviceType == SERIAL_MC68681 ) {
    502504      mc68681_process(minor);
    503505    }
     
    514516 */
    515517
     518/* XXX remove me */
    516519MC68681_STATIC int mc68681_flush(int major, int minor, void *arg)
    517520{
     521#if 0
    518522  while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    519523    /*
     
    527531  mc68681_close(major, minor, arg);
    528532
     533#endif
    529534  return(RTEMS_SUCCESSFUL);
    530 }
    531 
    532 /*
    533  *  mc68681_enable_interrupts
    534  *
    535  *  This function initializes the hardware for this port to use interrupts.
    536  */
    537 
    538 MC68681_STATIC void mc68681_enable_interrupts(
    539   int minor
    540 )
    541 {
    542   unsigned32            pMC68681;
    543   setRegister_f         setReg;
    544 
    545   pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
    546   setReg   = Console_Port_Tbl[minor].setRegister;
    547 
    548   /*
    549    *  Enable interrupts on RX and TX -- not break
    550    */
    551 
    552   (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 1));
    553535}
    554536
     
    564546  mc68681_init(minor);
    565547
    566   Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
    567 
    568548  Console_Port_Data[minor].bActive = FALSE;
    569549
    570550  set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
    571551
    572   mc68681_enable_interrupts(minor);
     552  mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
    573553}
    574554
     
    585565)
    586566{
    587   int i;
    588   unsigned32 Irql;
    589 
    590   for(i=0 ; i<len ;) {
    591     if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
    592       if(!Console_Port_Data[minor].bActive) {
    593         /*
    594          * Wake up the device
    595          */
    596         rtems_interrupt_disable(Irql);
    597         Console_Port_Data[minor].bActive = TRUE;
    598         mc68681_process(minor);
    599         rtems_interrupt_enable(Irql);
    600       } else {
    601         /*
    602          * Yield
    603          */
    604         rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    605       }
    606 
    607       /*
    608        * Wait for ring buffer to empty
    609        */
    610       continue;
    611     }
    612     else {
    613       Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
    614       i++;
    615     }
    616   }
    617 
    618   /*
    619    * Ensure that characters are on the way
    620    */
    621 
    622   if(!Console_Port_Data[minor].bActive) {
    623     /*
    624      * Wake up the device
    625      */
    626     rtems_interrupt_disable(Irql);
     567  unsigned32      Irql;
     568  unsigned32      pMC68681_port;
     569  setRegister_f   setReg;
     570
     571  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
     572  setReg        = Console_Port_Tbl[minor].setRegister;
     573
     574  /*
     575   *  We are using interrupt driven output and termios only sends us one character
     576   *  at a time.
     577   */
     578
     579  if ( !len )
     580    return 0;
     581
     582  /*
     583   * Wake up the device
     584   */
     585  rtems_interrupt_disable(Irql);
    627586    Console_Port_Data[minor].bActive = TRUE;
    628     mc68681_process(minor);
    629     rtems_interrupt_enable(Irql);
    630   }
    631 
    632   return (len);
     587    (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf);
     588    mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL);
     589  rtems_interrupt_enable(Irql);
     590  return 1;
    633591}
    634592
     
    808766   */
    809767
    810   while(TRUE) {
    811     if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    812       Console_Port_Data[minor].bActive = FALSE;
    813 
    814       /*
    815        * There is no data to transmit
    816        */
    817       break;
    818     }
    819 
    820     ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
    821     if(!(ucLineStatus & (MC68681_TX_EMPTY|MC68681_TX_READY))) {
    822       /*
    823        *  We'll get another interrupt when the TX can take another character.
    824        */
    825       break;
    826     }
    827 
    828     Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
    829     /*
    830      * transmit character
    831      */
    832     (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
     768  ucLineStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
     769  if (pMC68681 != pMC68681_port)
     770    ucLineStatus >>= 4;
     771
     772  if(ucLineStatus & MC68681_IR_TX_READY) {
     773    mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
     774    rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
    833775  }
    834776
     
    849791{
    850792  int              mate;
     793  int              is_a;
    851794  unsigned int     mask;
    852795  unsigned int     mate_mask;
     
    854797  unsigned int     pMC68681_port;
    855798  mc68681_context *pmc68681Context;
     799  mc68681_context *mateContext;
    856800 
    857801  pMC68681        = Console_Port_Tbl[minor].ulCtrlPort1;
     
    860804  mate            = pmc68681Context->mate;
    861805
     806  mask = 0;
    862807  mate_mask = 0;
    863808
    864   /*
    865    *  Decide if the other port on this DUART is using interrupts
     809  is_a = (pMC68681 == pMC68681_port);
     810 
     811  /*
     812   *  If there is a mate for this port, get its IMR mask.
    866813   */
    867814
    868815  if ( mate != -1 ) {
    869     if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts )
    870       mate_mask = 0x03;
    871 
    872     /*
    873      *  If equal, then minor is A so the mate must be B
    874      */
    875 
    876     if ( pMC68681 == pMC68681_port )
    877       mate_mask <<= 4;
    878   }
    879 
    880   /*
    881    *  Add in minor's mask
    882    */
    883 
    884   mask = 0;
    885   if ( enable_flag ) {
    886     if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) {
    887       if ( pMC68681 == pMC68681_port )
    888          mask = 0x03;
    889       else
    890          mask = 0x30;
    891     }
    892   }
    893 
    894   return mask | mate_mask;
    895 }
    896 
     816    mateContext = Console_Port_Data[mate].pDeviceContext;
     817   
     818    if (mateContext)
     819      mate_mask = mateContext->imr;
     820  }
     821
     822  /*
     823   *  Calculate this port's IMR mask and save it in the context area.
     824   */
     825
     826  if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts )
     827    mask = enable_flag;
     828
     829  pmc68681Context->imr = mask;
     830
     831  /*
     832   *  Now return the full IMR value
     833   */
     834
     835  if (is_a)
     836    return (mate_mask << 4) | mask;
     837
     838  return (mask << 4) | mate_mask;
     839}
     840
     841/*
     842 *  mc68681_enable_interrupts
     843 *
     844 *  This function initializes the hardware for this port to use interrupts.
     845 */
     846
     847MC68681_STATIC void mc68681_enable_interrupts(
     848  int minor,
     849  int imr_mask
     850)
     851{
     852  unsigned32            pMC68681;
     853  setRegister_f         setReg;
     854
     855  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
     856  setReg   = Console_Port_Tbl[minor].setRegister;
     857
     858  /*
     859   *  Enable interrupts on RX and TX -- not break
     860   */
     861
     862  (*setReg)(
     863     pMC68681,
     864     MC68681_INTERRUPT_MASK_REG,
     865     mc68681_build_imr(minor, imr_mask)
     866  );
     867}
     868
  • c/src/libchip/serial/mc68681.c

    r27a66bd r198d851  
    3636  libchip_serial_default_probe,   /* deviceProbe */
    3737  mc68681_open,                   /* deviceFirstOpen */
    38   mc68681_flush,                  /* deviceLastClose */
     38  NULL,                           /* deviceLastClose */
    3939  NULL,                           /* deviceRead */
    4040  mc68681_write_support_int,      /* deviceWrite */
     
    294294         Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) {
    295295      pmc68681Context->mate = port;
     296      pmc68681Context->imr  = 0;
    296297      break;
    297298    }
     
    329330   */
    330331
    331   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
    332   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
    333   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
    334   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
    335   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
    336   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
    337   (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
    338 
    339 
    340   (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 );
    341   (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 );
     332  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
     333  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
     334  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
     335  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
     336  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
     337  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
     338  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
     339
     340
     341  (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );
     342  (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );
    342343
    343344  /*
     
    345346   */
    346347
    347   (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0));
     348  mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );
    348349}
    349350
     
    499500
    500501  for(minor=0 ; minor<Console_Port_Count ; minor++) {
    501     if(vector == Console_Port_Tbl[minor].ulIntVector) {
     502    if(Console_Port_Tbl[minor].ulIntVector == vector &&
     503       Console_Port_Tbl[minor].deviceType == SERIAL_MC68681 ) {
    502504      mc68681_process(minor);
    503505    }
     
    514516 */
    515517
     518/* XXX remove me */
    516519MC68681_STATIC int mc68681_flush(int major, int minor, void *arg)
    517520{
     521#if 0
    518522  while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    519523    /*
     
    527531  mc68681_close(major, minor, arg);
    528532
     533#endif
    529534  return(RTEMS_SUCCESSFUL);
    530 }
    531 
    532 /*
    533  *  mc68681_enable_interrupts
    534  *
    535  *  This function initializes the hardware for this port to use interrupts.
    536  */
    537 
    538 MC68681_STATIC void mc68681_enable_interrupts(
    539   int minor
    540 )
    541 {
    542   unsigned32            pMC68681;
    543   setRegister_f         setReg;
    544 
    545   pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
    546   setReg   = Console_Port_Tbl[minor].setRegister;
    547 
    548   /*
    549    *  Enable interrupts on RX and TX -- not break
    550    */
    551 
    552   (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 1));
    553535}
    554536
     
    564546  mc68681_init(minor);
    565547
    566   Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer);
    567 
    568548  Console_Port_Data[minor].bActive = FALSE;
    569549
    570550  set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
    571551
    572   mc68681_enable_interrupts(minor);
     552  mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
    573553}
    574554
     
    585565)
    586566{
    587   int i;
    588   unsigned32 Irql;
    589 
    590   for(i=0 ; i<len ;) {
    591     if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) {
    592       if(!Console_Port_Data[minor].bActive) {
    593         /*
    594          * Wake up the device
    595          */
    596         rtems_interrupt_disable(Irql);
    597         Console_Port_Data[minor].bActive = TRUE;
    598         mc68681_process(minor);
    599         rtems_interrupt_enable(Irql);
    600       } else {
    601         /*
    602          * Yield
    603          */
    604         rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
    605       }
    606 
    607       /*
    608        * Wait for ring buffer to empty
    609        */
    610       continue;
    611     }
    612     else {
    613       Ring_buffer_Add_character( &Console_Port_Data[minor].TxBuffer, buf[i]);
    614       i++;
    615     }
    616   }
    617 
    618   /*
    619    * Ensure that characters are on the way
    620    */
    621 
    622   if(!Console_Port_Data[minor].bActive) {
    623     /*
    624      * Wake up the device
    625      */
    626     rtems_interrupt_disable(Irql);
     567  unsigned32      Irql;
     568  unsigned32      pMC68681_port;
     569  setRegister_f   setReg;
     570
     571  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
     572  setReg        = Console_Port_Tbl[minor].setRegister;
     573
     574  /*
     575   *  We are using interrupt driven output and termios only sends us one character
     576   *  at a time.
     577   */
     578
     579  if ( !len )
     580    return 0;
     581
     582  /*
     583   * Wake up the device
     584   */
     585  rtems_interrupt_disable(Irql);
    627586    Console_Port_Data[minor].bActive = TRUE;
    628     mc68681_process(minor);
    629     rtems_interrupt_enable(Irql);
    630   }
    631 
    632   return (len);
     587    (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf);
     588    mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL);
     589  rtems_interrupt_enable(Irql);
     590  return 1;
    633591}
    634592
     
    808766   */
    809767
    810   while(TRUE) {
    811     if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) {
    812       Console_Port_Data[minor].bActive = FALSE;
    813 
    814       /*
    815        * There is no data to transmit
    816        */
    817       break;
    818     }
    819 
    820     ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
    821     if(!(ucLineStatus & (MC68681_TX_EMPTY|MC68681_TX_READY))) {
    822       /*
    823        *  We'll get another interrupt when the TX can take another character.
    824        */
    825       break;
    826     }
    827 
    828     Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar);
    829     /*
    830      * transmit character
    831      */
    832     (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
     768  ucLineStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
     769  if (pMC68681 != pMC68681_port)
     770    ucLineStatus >>= 4;
     771
     772  if(ucLineStatus & MC68681_IR_TX_READY) {
     773    mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
     774    rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
    833775  }
    834776
     
    849791{
    850792  int              mate;
     793  int              is_a;
    851794  unsigned int     mask;
    852795  unsigned int     mate_mask;
     
    854797  unsigned int     pMC68681_port;
    855798  mc68681_context *pmc68681Context;
     799  mc68681_context *mateContext;
    856800 
    857801  pMC68681        = Console_Port_Tbl[minor].ulCtrlPort1;
     
    860804  mate            = pmc68681Context->mate;
    861805
     806  mask = 0;
    862807  mate_mask = 0;
    863808
    864   /*
    865    *  Decide if the other port on this DUART is using interrupts
     809  is_a = (pMC68681 == pMC68681_port);
     810 
     811  /*
     812   *  If there is a mate for this port, get its IMR mask.
    866813   */
    867814
    868815  if ( mate != -1 ) {
    869     if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts )
    870       mate_mask = 0x03;
    871 
    872     /*
    873      *  If equal, then minor is A so the mate must be B
    874      */
    875 
    876     if ( pMC68681 == pMC68681_port )
    877       mate_mask <<= 4;
    878   }
    879 
    880   /*
    881    *  Add in minor's mask
    882    */
    883 
    884   mask = 0;
    885   if ( enable_flag ) {
    886     if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) {
    887       if ( pMC68681 == pMC68681_port )
    888          mask = 0x03;
    889       else
    890          mask = 0x30;
    891     }
    892   }
    893 
    894   return mask | mate_mask;
    895 }
    896 
     816    mateContext = Console_Port_Data[mate].pDeviceContext;
     817   
     818    if (mateContext)
     819      mate_mask = mateContext->imr;
     820  }
     821
     822  /*
     823   *  Calculate this port's IMR mask and save it in the context area.
     824   */
     825
     826  if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts )
     827    mask = enable_flag;
     828
     829  pmc68681Context->imr = mask;
     830
     831  /*
     832   *  Now return the full IMR value
     833   */
     834
     835  if (is_a)
     836    return (mate_mask << 4) | mask;
     837
     838  return (mask << 4) | mate_mask;
     839}
     840
     841/*
     842 *  mc68681_enable_interrupts
     843 *
     844 *  This function initializes the hardware for this port to use interrupts.
     845 */
     846
     847MC68681_STATIC void mc68681_enable_interrupts(
     848  int minor,
     849  int imr_mask
     850)
     851{
     852  unsigned32            pMC68681;
     853  setRegister_f         setReg;
     854
     855  pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
     856  setReg   = Console_Port_Tbl[minor].setRegister;
     857
     858  /*
     859   *  Enable interrupts on RX and TX -- not break
     860   */
     861
     862  (*setReg)(
     863     pMC68681,
     864     MC68681_INTERRUPT_MASK_REG,
     865     mc68681_build_imr(minor, imr_mask)
     866  );
     867}
     868
Note: See TracChangeset for help on using the changeset viewer.