/* $Revision: 1.2 $ */

#include <cpu.h>
#include <common.h>
#include <kern.h>
#include <sem.h>
#include <bsp.h>
#include <qsm.h>
#include <sim.h>
#include <beep.h>
#include <stdio.h>
#include <intr.h>
#include <locore.h>
#include <malloc.h>



volatile char  *tty;
volatile char  *tty0;

int             timer_ticks, timer_secs;
int             tty_rx_err;

static volatile qsmstruct * qsm = (qsmstruct *) 0xFFFC00 ;  

void tty_init(void) {
  unsigned short dummy ;
  qsm->SCCR0=0 ;
  qsm->SCCR1=0 ;
  dummy=qsm->SCSR ;
  qsm->QMCR=0x4001 ;
  qsm->QIVR=0x42 ;/* qspi odd Vector SCI even Vector */

  qsm->SCCR0=0x0009 ; /* =16,77 MHz /(32*57600 Baud)*/

/*   vec_set( 0x42 << 2 , tty_isr ) ; */
  qsm->QILR=0x5 ;
  qsm->SCCR1=TE|RE|RIE ; /*Tansmit und Receiv enable 8N1 Receive &Transmit Interrupt enable*/ 
  kputs( __PRETTY_FUNCTION__  ": Serial Line Configured\n") ;
}

void tty_tx_handle(void){
}

int tty_handle(int dummy){
  UWORD scsr = qsm->SCSR ;
  if( scsr & RDRF ){
    record_char( qsm->SCDR ) ;
  }
  if( scsr & TDRE ){
    qsm->SCCR1=qsm->SCCR1&(~(TIE)) ;
  }
  if( scsr & TC ){
    qsm->SCCR1=qsm->SCCR1&(~(TIE)) ;
  }
  return 0 ;
}

void tty_rx_handle(void){
}

void tty_rxerr_handle(void){
}

void tty_write(volatile char *tty, char ch){
  /* FIXME this is polling */
  while( !(qsm->SCSR & TDRE) ) /*trasmit Busy*/
    ;
  qsm->SCDR=ch ;
}


void tty_poll_write(volatile char *tty, char ch){
  while( !(qsm->SCSR & TDRE) ) /*trasmit Busy*/
    ;
  qsm->SCDR=ch ;
}

#ifdef MV134_TIMER_TEST
/* XXX for testing only */
extern sem_t    timer_sem;
#endif

void timer_handle(){
  timer_ticks++;
  check_sleep_queue() ;
  if ((timer_ticks % TICKS_PER_SECOND) == 0) {
    timer_secs++;
#ifdef MV134_TIMER_TEST
    /* XXX for testing only */
    sem_v(&timer_sem);
#endif
  }
}

volatile static simstruct * sim = (simstruct *) 0xFFFA00 ; 

/*       ori.w   #$000f,simmcr
 *       move.w  #$0640,picr
 *       move.w  #$0008,pitr
 *       andi.w  #$f8ff,sr 
 */
/* PITM = ( 32768 * 1/60 sec )/4*(Prescaler=1) ) = 136 */
void timer_init(void){
  trap_connect( 0x40 , timer_handle , 0 ) ;
  /* PITR = Periode * EXTAL /(4*Prescaler)
   * z.B.   16,67ms * 32768*1/s / (4*1)=0x88 oder
   *        1ms*32768*1/s/ 4=0x08 = Periode 0,977 ms
   */
  sim->PITR=(UBYTE)(1.0/TICKS_PER_SECOND*32768.0/4);

  sim->PICR=0x640 ; /* Level 6 Vector 40 */

  timer_ticks = 0;
  timer_secs = 0;
}


/* |
 * | first_bit() used for scanning 32bit integer for a bit set to 1.
 * | the postion of the first bit set from the right-most position is returned.
 * | used in pick() for scheduling. useful for other selection type work.
 * |
 *
 * .globl	first_bit		| find first bit set in an integer
 * bfffo	sp@(4){#0:#0},d1
 * movel	#MAX_PRIORITY_GROUPS-1,d0
 * subl	d1,d0
 * rts				| return index to the first set bit
*/

int first_bit( int a ){
  register unsigned int i  ;
  register unsigned int j ;
  i=1<<31 ;   
  for( j=0; j<MAX_PRIORITY_GROUPS ; j++ ){
    if( a & i )
      return (MAX_PRIORITY_GROUPS-1)-j ;
    i=i>>1 ;
  }
  return (MAX_PRIORITY_GROUPS-1)-j ;
}

/* These had been defined as int functions. Hmmm ... */
extern void *  _start, _end;

void mem_init(void){
/*   __free_hook = NULL ; */
/*   __malloc_hook = NULL ; */
/*   __realloc_hook = NULL ; */
/*   __morecore = __default_morecore; */
/*   __malloc_initialized = 0; */
}
