Changeset ad6b881 in rtems


Ignore:
Timestamp:
Feb 9, 2011, 3:57:29 PM (9 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.11, master
Children:
ebebd71
Parents:
26c17377
Message:

2011-02-09 Jennifer Averett <jennifer.averett@…>

  • console/ps2_mouse.c: Formatting changes in preparation for making mouse parsing and serial mouse driver BSP independent.
Location:
c/src/lib/libbsp/i386/pc386
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/ChangeLog

    r26c17377 rad6b881  
     12011-02-09      Jennifer Averett <jennifer.averett@oarcorp.com>
     2
     3        * console/ps2_mouse.c: Formatting changes in preparation for making
     4        mouse parsing and serial mouse driver BSP independent.
     5
    162011-02-09      Ralf Corsépius <ralf.corsepius@rtems.org>
    27
  • c/src/lib/libbsp/i386/pc386/console/ps2_mouse.c

    r26c17377 rad6b881  
    6969void ps2_set_driver_handler( int port, void ( *handler )( void *,  unsigned char *, int ) )
    7070{
    71    driver_input_handler_ps2 = handler;
     71  driver_input_handler_ps2 = handler;
    7272}
    7373
     
    118118static void kb_wait(void)
    119119{
    120         unsigned long timeout = KBC_TIMEOUT;
    121 
    122         do {
    123                 /*
    124                 * "handle_kbd_event()" will handle any incoming events
    125                 * while we wait - keypresses or mouse movement.
    126                 */
    127                 unsigned char status = handle_kbd_event();
    128 
    129                 if (! (status & KBD_STAT_IBF))
    130                         return;
    131 
    132                 mdelay(1);
    133 
    134                 timeout--;
    135         } while (timeout);
    136 #ifdef KBD_REPORT_TIMEOUTS
    137         printk( "Keyboard timed out[1]\n");
    138 #endif
     120  unsigned long timeout = KBC_TIMEOUT;
     121
     122  do {
     123    /*
     124    * "handle_kbd_event()" will handle any incoming events
     125    * while we wait - keypresses or mouse movement.
     126    */
     127    unsigned char status = handle_kbd_event();
     128
     129    if (! (status & KBD_STAT_IBF))
     130      return;
     131
     132    mdelay(1);
     133    timeout--;
     134  } while (timeout);
     135
     136  #ifdef KBD_REPORT_TIMEOUTS
     137    printk( "Keyboard timed out[1]\n");
     138  #endif
    139139}
    140140
    141141static int do_acknowledge(unsigned char scancode)
    142142{
    143         if (reply_expected) {
    144           /* Unfortunately, we must recognise these codes only if we know they
    145            * are known to be valid (i.e., after sending a command), because there
    146            * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
    147            * keys with such codes :(
    148            */
    149                 if (scancode == KBD_REPLY_ACK) {
    150                         acknowledge = 1;
    151                         reply_expected = 0;
    152                         return 0;
    153                 } else if (scancode == KBD_REPLY_RESEND) {
    154                         resend = 1;
    155                         reply_expected = 0;
    156                         return 0;
    157                 }
    158                 /* Should not happen... */
    159 #if 0
    160                 printk( "keyboard reply expected - got %02x\n",
    161                        scancode);
    162 #endif
    163         }
    164         return 1;
     143  if (reply_expected) {
     144
     145    /* Unfortunately, we must recognise these codes only if we know they
     146     * are known to be valid (i.e., after sending a command), because there
     147     * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
     148     * keys with such codes :(
     149     */
     150    if (scancode == KBD_REPLY_ACK) {
     151      acknowledge = 1;
     152      reply_expected = 0;
     153      return 0;
     154    } else if (scancode == KBD_REPLY_RESEND) {
     155      resend = 1;
     156      reply_expected = 0;
     157      return 0;
     158    }
     159
     160    /* Should not happen... */
     161    #if 0
     162      printk( "keyboard reply expected - got %02x\n", scancode);
     163    #endif
     164  }
     165  return 1;
    165166}
    166167
    167168static inline void handle_mouse_event(unsigned char scancode)
    168169{
    169         if (mouse_reply_expected) {
    170                 if (scancode == AUX_ACK) {
    171                         mouse_reply_expected--;
    172                         return;
    173                 }
    174                 mouse_reply_expected = 0;
    175         }
    176 
    177         if (aux_count) {
    178                 int head = queue->head;
    179 
    180                 queue->buf[head] = scancode;
    181                 head = (head + 1) & (AUX_BUF_SIZE-1);
    182                 if (head != queue->tail) {
    183                         queue->head = head;
    184                 }
    185       /* if the input queue is active, add to it */
    186       if( driver_input_handler_ps2 )
    187       {
    188           driver_input_handler_ps2( NULL,  &scancode, 1 );
    189       }
    190       else
    191       {
    192          /* post this byte to termios */
    193               rtems_termios_enqueue_raw_characters( termios_ttyp_paux, (char *)&scancode, 1 );
    194       }
    195         }
     170  if (mouse_reply_expected) {
     171    if (scancode == AUX_ACK) {
     172      mouse_reply_expected--;
     173      return;
     174    }
     175    mouse_reply_expected = 0;
     176  }
     177
     178  if (aux_count) {
     179    int head = queue->head;
     180    queue->buf[head] = scancode;
     181    head = (head + 1) & (AUX_BUF_SIZE-1);
     182    if (head != queue->tail) {
     183      queue->head = head;
     184    }
     185
     186    /* if the input queue is active, add to it */
     187    if( driver_input_handler_ps2 ) {
     188      driver_input_handler_ps2( NULL,  &scancode, 1 );
     189    } else {
     190      /* post this byte to termios */
     191      rtems_termios_enqueue_raw_characters( termios_ttyp_paux, (char *)&scancode, 1 );
     192    }
     193  }
    196194}
    197195
     
    205203static unsigned char handle_kbd_event(void)
    206204{
    207         unsigned char status = kbd_read_status();
    208         unsigned int work = 10000;
    209 
    210         while (status & KBD_STAT_OBF) {
    211                 unsigned char scancode;
    212 
    213                 scancode = kbd_read_input();
    214 
    215                 if (status & KBD_STAT_MOUSE_OBF) {
    216                         handle_mouse_event(scancode);
    217                 } else {
    218                         do_acknowledge(scancode);
    219          printk("pc_keyb: %X ", scancode );
    220                 }
    221                 status = kbd_read_status();
    222                 if(!work--)
    223                 {
    224                         printk("pc_keyb: controller jammed (0x%02X).\n",
    225                                 status);
    226                         break;
    227                 }
    228         }
    229 
    230         return status;
     205  unsigned char status = kbd_read_status();
     206  unsigned int work = 10000;
     207
     208  while (status & KBD_STAT_OBF) {
     209    unsigned char scancode;
     210    scancode = kbd_read_input();
     211    if (status & KBD_STAT_MOUSE_OBF) {
     212      handle_mouse_event(scancode);
     213    } else {
     214      do_acknowledge(scancode);
     215      printk("pc_keyb: %X ", scancode );
     216    }
     217    status = kbd_read_status();
     218    if(!work--) {
     219      printk("pc_keyb: controller jammed (0x%02X).\n", status);
     220      break;
     221    }
     222  }
     223  return status;
    231224}
    232225
    233226static void ps2_mouse_interrupt(rtems_irq_hdl_param ignored)
    234227{
    235         handle_kbd_event();
    236 }
    237 
    238 /*
    239  * send_data sends a character to the keyboard and waits
    240  * for an acknowledge, possibly retrying if asked to. Returns
    241  * the success status.
    242  *
    243  * Don't use 'jiffies', so that we don't depend on interrupts
    244  */
    245 #if 0
    246 static int send_data(unsigned char data)
    247 {
    248         int retries = 3;
    249 
    250         do {
    251                 unsigned long timeout = KBD_TIMEOUT;
    252 
    253                 acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
    254                 resend = 0;
    255                 reply_expected = 1;
    256                 kbd_write_output_w(data);
    257                 for (;;) {
    258                         if (acknowledge)
    259                                 return 1;
    260                         if (resend)
    261                                 break;
    262                         mdelay(1);
    263                         if (!--timeout) {
    264 #ifdef KBD_REPORT_TIMEOUTS
    265                                 printk( "Keyboard timeout[2]\n");
    266 #endif
    267                                 return 0;
    268                         }
    269                 }
    270         } while (retries-- > 0);
    271 #ifdef KBD_REPORT_TIMEOUTS
    272         printk( "keyboard: Too many NACKs -- noisy kbd cable?\n");
    273 #endif
    274         return 0;
    275 }
    276 #endif
    277 
    278 #if 0
    279 #define KBD_NO_DATA     (-1)    /* No data */
    280 #define KBD_BAD_DATA    (-2)    /* Parity or other error */
    281 
    282 static int kbd_read_data(void)
    283 {
    284         int retval = KBD_NO_DATA;
    285         unsigned char status;
    286 
    287         status = kbd_read_status();
    288         if (status & KBD_STAT_OBF) {
    289                 unsigned char data = kbd_read_input();
    290 
    291                 retval = data;
    292                 if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
    293                         retval = KBD_BAD_DATA;
    294         }
    295         return retval;
    296 }
    297 
    298 static void kbd_clear_input(void)
    299 {
    300         int maxread = 100;      /* Random number */
    301 
    302         do {
    303                 if (kbd_read_data() == KBD_NO_DATA)
    304                         break;
    305         } while (--maxread);
    306 }
    307 
    308 static int kbd_wait_for_input(void)
    309 {
    310         long timeout = KBD_INIT_TIMEOUT;
    311 
    312         do {
    313                 int retval = kbd_read_data();
    314                 if (retval >= 0)
    315                         return retval;
    316                 mdelay(1);
    317         } while (--timeout);
    318         return -1;
    319 }
    320 #endif
     228  handle_kbd_event();
     229}
    321230
    322231static void kbd_write_command_w(int data)
    323232{
    324         kb_wait();
    325         kbd_write_command(data);
    326 }
    327 
    328 #if 0
    329 static void kbd_write_output_w(int data)
    330 {
    331         kb_wait();
    332         kbd_write_output(data);
    333 }
    334 #endif
     233  kb_wait();
     234  kbd_write_command(data);
     235}
    335236
    336237static void kbd_write_cmd(int cmd)
    337238{
    338         kb_wait();
    339         kbd_write_command(KBD_CCMD_WRITE_MODE);
    340         kb_wait();
    341         kbd_write_output(cmd);
     239  kb_wait();
     240  kbd_write_command(KBD_CCMD_WRITE_MODE);
     241  kb_wait();
     242  kbd_write_output(cmd);
    342243}
    343244
     
    347248static int detect_auxiliary_port(void)
    348249{
    349         int loops = 10;
    350         int retval = 0;
    351 
    352         /* Put the value 0x5A in the output buffer using the "Write
    353          * Auxiliary Device Output Buffer" command (0xD3). Poll the
    354          * Status Register for a while to see if the value really
    355          * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
    356          * bit is also set to 1 in the Status Register, we assume this
    357          * controller has an Auxiliary Port (a.k.a. Mouse Port).
    358          */
    359         kb_wait();
    360         kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
    361 
    362         kb_wait();
    363         kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
    364 
    365         do {
    366                 unsigned char status = kbd_read_status();
    367 
    368                 if (status & KBD_STAT_OBF) {
    369                         (void) kbd_read_input();
    370                         if (status & KBD_STAT_MOUSE_OBF) {
    371                                 printk( "Detected PS/2 Mouse Port.\n");
    372                                 retval = 1;
    373                         }
    374                         break;
    375                 }
    376                 mdelay(1);
    377         } while (--loops);
    378         return retval;
     250  int loops = 10;
     251  int retval = 0;
     252
     253  /* Put the value 0x5A in the output buffer using the "Write
     254   * Auxiliary Device Output Buffer" command (0xD3). Poll the
     255   * Status Register for a while to see if the value really
     256   * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
     257   * bit is also set to 1 in the Status Register, we assume this
     258   * controller has an Auxiliary Port (a.k.a. Mouse Port).
     259   */
     260  kb_wait();
     261  kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
     262
     263  kb_wait();
     264  kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
     265
     266  do {
     267    unsigned char status = kbd_read_status();
     268    if (status & KBD_STAT_OBF) {
     269      kbd_read_input();
     270      if (status & KBD_STAT_MOUSE_OBF) {
     271        printk( "Detected PS/2 Mouse Port.\n");
     272        retval = 1;
     273      }
     274      break;
     275    }
     276    mdelay(1);
     277  } while (--loops);
     278  return retval;
    379279}
    380280
     
    384284static void aux_write_dev(int val)
    385285{
    386         kb_wait();
    387         kbd_write_command(KBD_CCMD_WRITE_MOUSE);
    388         kb_wait();
    389         kbd_write_output(val);
     286  kb_wait();
     287  kbd_write_command(KBD_CCMD_WRITE_MOUSE);
     288  kb_wait();
     289  kbd_write_output(val);
    390290}
    391291
     
    395295static void aux_write_ack(int val)
    396296{
    397         kb_wait();
    398         kbd_write_command(KBD_CCMD_WRITE_MOUSE);
    399         kb_wait();
    400         kbd_write_output(val);
    401         /* we expect an ACK in response. */
    402         mouse_reply_expected++;
    403         kb_wait();
     297  kb_wait();
     298  kbd_write_command(KBD_CCMD_WRITE_MOUSE);
     299  kb_wait();
     300  kbd_write_output(val);
     301  /* we expect an ACK in response. */
     302  mouse_reply_expected++;
     303  kb_wait();
    404304}
    405305
    406306static unsigned char get_from_queue(void)
    407307{
    408         unsigned char result;
    409         result = queue->buf[queue->tail];
    410         queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
    411         return result;
     308  unsigned char result;
     309  result = queue->buf[queue->tail];
     310  queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
     311  return result;
    412312}
    413313
    414314static int queue_empty(void)
    415315{
    416         return queue->head == queue->tail;
     316  return queue->head == queue->tail;
    417317}
    418318
     
    424324static int release_aux(void)
    425325{
    426         if (--aux_count)
    427                 return 0;
    428         kbd_write_cmd(AUX_INTS_OFF);                        /* Disable controller ints */
    429         kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
    430 
    431    BSP_remove_rtems_irq_handler( &ps2_isr_data );
    432         return 0;
    433 }
     326  if (--aux_count)
     327    return 0;
     328  kbd_write_cmd(AUX_INTS_OFF);                      /* Disable controller ints */
     329  kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
     330  BSP_remove_rtems_irq_handler( &ps2_isr_data );
     331  return 0;
     332}
     333
    434334/*
    435335 * Install interrupt handler.
     
    464364size_t read_aux(char * buffer, size_t count )
    465365{
    466         size_t i = count;
    467         unsigned char c;
    468 
    469         if (queue_empty())
    470         {
    471                 return 0;
    472    }
    473         while (i > 0 && !queue_empty())
    474         {
    475                 c = get_from_queue();
    476                 *buffer++ = c;
    477                 i--;
    478         }
    479         return count-i;
     366  size_t i = count;
     367  unsigned char c;
     368
     369  if (queue_empty()) {
     370    return 0;
     371  }
     372  while (i > 0 && !queue_empty()) {
     373    c = get_from_queue();
     374    *buffer++ = c;
     375    i--;
     376  }
     377  return count-i;
    480378}
    481379
     
    483381 * Write to the aux device.
    484382 */
    485 
    486383static int write_aux( int minor, const char * buffer, int count )
    487384{
    488         int retval = 0;
    489 
    490         if (count) {
    491                 int written = 0;
    492 
    493                 if (count > 32)
    494                         count = 32; /* Limit to 32 bytes. */
    495                 do {
    496                         char c;
    497                         c = *buffer++;
    498                         aux_write_dev(c);
    499                         written++;
    500                 } while (--count);
    501                 retval = -EIO;
    502                 if (written) {
    503                         retval = written;
    504                 }
    505         }
    506         return retval;
    507 }
    508 
    509 #if 0
    510 static unsigned int aux_poll()
    511 {
    512         if( !queue_empty() )
    513                 return 1;
    514         return 0;
    515 }
    516 #endif
     385  int retval = 0;
     386
     387  if (count) {
     388    int written = 0;
     389    if (count > 32)
     390      count = 32; /* Limit to 32 bytes. */
     391    do {
     392      char c;
     393      c = *buffer++;
     394      aux_write_dev(c);
     395      written++;
     396    } while (--count);
     397    retval = -EIO;
     398    if (written) {
     399      retval = written;
     400    }
     401  }
     402  return retval;
     403}
    517404
    518405static int psaux_init( void )
    519406{
    520         if( !detect_auxiliary_port() )
    521    {
    522         printk( "PS/2 - mouse not found.\n" );
    523                 return -EIO;
    524    }
    525 
    526         queue = (struct aux_queue *)malloc( sizeof(*queue) );
    527    memset(queue, 0, sizeof(*queue));
    528         queue->head = queue->tail = 0;
    529         queue->proc_list = NULL;
    530 
    531 #ifdef INITIALIZE_MOUSE
    532         kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
    533         aux_write_ack(AUX_SET_SAMPLE);
    534         aux_write_ack(100);                           /* 100 samples/sec */
    535         aux_write_ack(AUX_SET_RES);
    536         aux_write_ack(3);                                /* 8 counts per mm */
    537         aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
    538 #endif /* INITIALIZE_MOUSE */
    539         kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
    540         kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
    541         return 0;
     407  if( !detect_auxiliary_port() ) {
     408    printk( "PS/2 - mouse not found.\n" );
     409    return -EIO;
     410  }
     411  queue = (struct aux_queue *)malloc( sizeof(*queue) );
     412  memset(queue, 0, sizeof(*queue));
     413  queue->head = queue->tail = 0;
     414  queue->proc_list = NULL;
     415
     416  #ifdef INITIALIZE_MOUSE
     417    kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
     418    aux_write_ack(AUX_SET_SAMPLE);
     419    aux_write_ack(100);                       /* 100 samples/sec */
     420    aux_write_ack(AUX_SET_RES);
     421    aux_write_ack(3);                            /* 8 counts per mm */
     422    aux_write_ack(AUX_SET_SCALE21);     /* 2:1 scaling */
     423  #endif /* INITIALIZE_MOUSE */
     424  kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
     425  kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
     426  return 0;
    542427}
    543428
     
    545430 * paux device driver INITIALIZE entry point.
    546431 */
    547 rtems_device_driver
    548 paux_initialize(  rtems_device_major_number major,
    549                    rtems_device_minor_number minor,
    550                    void                      *arg)
    551 {
    552    rtems_status_code status;
     432rtems_device_driver paux_initialize( 
     433  rtems_device_major_number major,
     434  rtems_device_minor_number minor,
     435  void                      *arg)
     436{
     437  rtems_status_code status;
    553438
    554439  /*
    555440   * Set up TERMIOS
    556441   */
    557    rtems_termios_initialize();
    558 
    559         printk( "PS/2 mouse probe.\n" );
    560    if( psaux_init() < 0 )
    561    {
    562       printk("Error detecting PS/2 mouse --\n");
    563 
    564       /* we might want to finish the application here !!! */
    565    }
    566    open_aux();
     442  rtems_termios_initialize();
     443
     444  printk( "PS/2 mouse probe.\n" );
     445  if( psaux_init() < 0 ) {
     446    printk("Error detecting PS/2 mouse --\n");
     447    /* we might want to finish the application here !!! */
     448  }
     449  open_aux();
    567450
    568451  /*
     
    570453   */
    571454  status = rtems_io_register_name ("/dev/mouse", major, 0);
    572   if (status != RTEMS_SUCCESSFUL)
    573   {
    574       printk("Error registering paux device!\n");
    575       rtems_fatal_error_occurred (status);
     455  if (status != RTEMS_SUCCESSFUL) {
     456    printk("Error registering paux device!\n");
     457    rtems_fatal_error_occurred (status);
    576458  }
    577459  return RTEMS_SUCCESSFUL;
     
    591473static ssize_t write_aux_echo( int minor, const char * buffer, size_t count )
    592474{
    593    return 0;
     475  return 0;
    594476}
    595477
     
    597479 * paux device driver OPEN entry point
    598480 */
    599 rtems_device_driver
    600 paux_open(rtems_device_major_number major,
    601                 rtems_device_minor_number minor,
    602                 void                      *arg)
     481rtems_device_driver paux_open(
     482  rtems_device_major_number major,
     483  rtems_device_minor_number minor,
     484  void                      *arg)
    603485{
    604486  rtems_status_code              status;
     
    623505 * paux device driver CLOSE entry point
    624506 */
    625 rtems_device_driver
    626 paux_close(rtems_device_major_number major,
    627            rtems_device_minor_number minor,
    628            void                      *arg)
     507rtems_device_driver paux_close(
     508  rtems_device_major_number major,
     509  rtems_device_minor_number minor,
     510  void                      *arg)
    629511{
    630512  return (rtems_termios_close (arg));
     
    635517 * Read characters from the PS/2 mouse.
    636518 */
    637 rtems_device_driver
    638 paux_read(rtems_device_major_number major,
    639           rtems_device_minor_number minor,
    640          void                      *arg)
     519rtems_device_driver paux_read(
     520  rtems_device_major_number major,
     521  rtems_device_minor_number minor,
     522  void                      *arg)
    641523{
    642524  return rtems_termios_read (arg);
     
    647529 * Write characters to the PS/2 mouse.
    648530 */
    649 rtems_device_driver
    650 paux_write(rtems_device_major_number major,
    651           rtems_device_minor_number minor,
    652           void                    * arg)
     531rtems_device_driver  paux_write(
     532  rtems_device_major_number major,
     533  rtems_device_minor_number minor,
     534  void                      *arg)
    653535{
    654536  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
     
    662544 * Handle ioctl request.
    663545 */
    664 rtems_device_driver
    665 paux_control(rtems_device_major_number major,
    666              rtems_device_minor_number minor,
    667              void                      * arg
     546rtems_device_driver paux_control(
     547  rtems_device_major_number major,
     548  rtems_device_minor_number minor,
     549  void                      *arg
    668550)
    669551{
    670         rtems_libio_ioctl_args_t *args = arg;
    671         switch( args->command )
    672         {
    673            default:
     552  rtems_libio_ioctl_args_t *args = arg;
     553
     554  switch( args->command ) {
     555    default:
    674556      return rtems_termios_ioctl (arg);
    675                 break;
    676 
    677       case MW_UID_REGISTER_DEVICE:
     557      break;
     558
     559    case MW_UID_REGISTER_DEVICE:
    678560      printk( "PS2 Mouse: reg=%s\n", args->buffer );
    679561      register_mou_msg_queue( args->buffer, -1 );
    680                 break;
    681 
    682       case MW_UID_UNREGISTER_DEVICE:
     562      break;
     563
     564    case MW_UID_UNREGISTER_DEVICE:
    683565      unregister_mou_msg_queue( -1 );
    684                 break;
    685    }
    686         args->ioctl_return = 0;
    687    return RTEMS_SUCCESSFUL;
    688 }
     566      break;
     567  }
     568  args->ioctl_return = 0;
     569  return RTEMS_SUCCESSFUL;
     570}
Note: See TracChangeset for help on using the changeset viewer.