Ejemplo n.º 1
0
/* be aware of: */
THIS_IS_REALMODE_CODE

static int __bootcode empty_8042(void)
{
	u8 status;
	int loops = MAX_8042_LOOPS;
	int ffs   = MAX_8042_FF;

	while (loops--) {
		io_delay();

		status = inb(0x64);
		if (status == 0xff) {
			/* FF is a plausible, but very unlikely status */
			if (!--ffs)
				return -1; /* Assume no KBC present */
		}
		if (status & 1) {
			/* Read and discard input data */
			io_delay();
			(void)inb(0x60);
		} else if (!(status & 2)) {
			/* Buffers empty, finished! */
			return 0;
		}
	}

	return -1;
}
Ejemplo n.º 2
0
//重置协处理器
static void reset_coprocess()
{
    outb(0xf0,0);
	io_delay();
	outb(0xf1,0);
	io_delay();
}
Ejemplo n.º 3
0
/****f* spin1_api.c/report_warns
*
* SUMMARY
*  This function reports warnings if requested
*  at compile time
*
* SYNOPSIS
*  void report_warns ()
*
* SOURCE
*/
void report_warns ()
{
#if API_WARN == TRUE	    // report warnings
  if (warnings & TASK_QUEUE_FULL)
    {
      io_printf (IO_API, "\t\t[api_warn] warning: task queue full (%u)\n",
                 fullq);
      io_delay (API_PRINT_DELAY);
    }
  if (warnings & DMA_QUEUE_FULL)
    {
      io_printf (IO_API, "\t\t[api_warn] warning: DMA queue full (%u)\n",
                 dfull);
      io_delay (API_PRINT_DELAY);
    }
  if (warnings & PACKET_QUEUE_FULL)
    {
      io_printf (IO_API, "\t\t[api_warn] warning: packet queue full (%u)\n",
                 pfull);
      io_delay (API_PRINT_DELAY);
    }
# if USE_WRITE_BUFFER == TRUE
  if (warnings & WRITE_BUFFER_ERROR)
    {
      io_printf (IO_API,
		 "\t\t[api_warn] warning: write buffer errors (%u)\n",
                   wberrors);
      io_delay (API_PRINT_DELAY);
    }
#endif
#endif
}
Ejemplo n.º 4
0
/****f* spin1_api.c/report_debug
*
* SUMMARY
*  This function reports warnings if requested
*  at compile time
*
* SYNOPSIS
*  void report_debug ()
*
* SOURCE
*/
void report_debug ()
{
  #if API_DEBUG == TRUE

    if (leadAp) // Only the leader appl. core reports router data
    {
      // Report router counters

      io_printf (IO_API, "\t\t[api_debug] RTR mc     packets: %d\n",
                 rtr[RTR_DGC0] + rtr[RTR_DGC1]);
      io_delay (API_PRINT_DELAY);

      io_printf (IO_API, "\t\t[api_debug] RTR dpd mc packets: %d\n",
                 rtr[RTR_DGC8]);
      io_delay (API_PRINT_DELAY);
    }

    io_printf (IO_API, "\t\t[api_debug] ISR thrown packets: %d\n", thrown);
    io_delay (API_PRINT_DELAY);

    // Report DMAC counters

    io_printf (IO_API, "\t\t[api_debug] DMA bursts:  %d\n", dma[DMA_STAT0]);
    io_delay (API_PRINT_DELAY);
  #endif
}
Ejemplo n.º 5
0
//在这里处理PIC芯片,将所有外部中断的端口屏蔽
static void mask_pic()
{
    outb(0x21,0xff);//屏蔽主PIC芯片
	io_delay();
	outb(0xf1,0);//屏蔽从PIC芯片
	io_delay();
}
Ejemplo n.º 6
0
void disable_8259A_irq(unsigned int irq)
{
       	int i;
        unsigned int mask = 1 << irq;
        irq_mask_8259A  |= mask;

        outb(PIC_MASTER_IMR,(char)irq_mask_8259A);
	io_delay();
        outb(PIC_SLAVE_IMR,(char)(irq_mask_8259A>>8));
	io_delay();
	
}
Ejemplo n.º 7
0
void irq_eoi()
{
	// OCW2: rse00xxx
	//   r: rotate
	//   s: specific
	//   e: end-of-interrupt
	// xxx: specific interrupt line
	
	outb(PIC_MASTER_CMD, 0x20);
	io_delay();
	outb(PIC_SLAVE_CMD, 0x20);
	io_delay();
}
Ejemplo n.º 8
0
void setmask_8259A_irq(uint16_t mask)
{
	int i;
	irq_mask_8259A = mask;
        outb(PIC_MASTER_IMR,(char)mask);
	io_delay();
        outb(PIC_SLAVE_IMR,(char)(mask>>8));
	io_delay();
	printk("enabled interrupts:");
	for (i = 0; i < 16; i++)
		if (~mask & (1<<i))
			printk(" %d", i);
	printk("\n");

}
Ejemplo n.º 9
0
	// note: synchronized
	// will be blocked until the data is recieved
	char read() const
	{
		while (!recieved()) {
			io_delay();
		}
		return inb(port_addr);
	}
Ejemplo n.º 10
0
/*
 * write_serial: If serial output is enabled, write character on
 * serial port.
 */
__export void write_serial(char data)
{
	if (!SerialPort)
		return;

	if (!(DisplayMask & 0x04))
		return;

	while (1) {
		char ch;

		ch = inb(SerialPort + 5); /* LSR */

		/* Wait for space in transmit register */
		if (!(ch & 0x20))
			continue;

		/* Wait for input flow control */
		ch = inb(SerialPort + 6);
		ch &= FlowInput;
		if (ch != FlowInput)
			continue;

		break;
	}

	outb(data, SerialPort);	/* Send data */
	io_delay();
}
Ejemplo n.º 11
0
	void write(char data)
	{
		while (!transimit_is_empty()) {
			io_delay();
		}
		outb(port_addr, data);
	}
Ejemplo n.º 12
0
/* Queue up some data to send.  This is only called when uart_hw_poll_tx
returns true, which means that there is some space in the UART to hold some
data.  Therefore, this routine does not need to check the uart to see if data
can be written, because uart_hw_poll_tx has been called. */
void uart_hw_tx(PUART_INFO uinfo, byte data)
{
#if (UART_16550)
    OUTBYTE(uinfo->port_base + THR, data); io_delay();

#else
#error: Implement sending data over uart
#endif
}
Ejemplo n.º 13
0
/* Temporarily disable the transmit interrupt.  Called when there is not
any more data queued up to send.*/
void uart_hw_disable_tx_int(PUART_INFO uinfo)
{
#if (UART_16550)
    OUTBYTE(uinfo->port_base + IER, THRE_OFF); io_delay();

#else
#error: Implement disabling uart tx interrupts
#endif
}
Ejemplo n.º 14
0
static inline unsigned char crtc_read(unsigned char index) {

    volatile unsigned char v;

    outb(CRTC_ADDRESS_PORT, index);
    io_delay();
    inb(CRTC_DATA_PORT, v);
    return v;
}
Ejemplo n.º 15
0
/* Enable the transmit interrupt.  Called when data is ready to be sent.
   This routine should be ISR safe. */
void uart_hw_enable_tx_int(PUART_INFO uinfo)
{
#if (UART_16550)
    if (!uinfo->is_16550 || !uinfo->xmit_on)
    {
#if (DEBUG_XMIT)
        DEBUG_ERROR("uart_hw_enable_tx_int: start xmit", NOVAR, 0, 0);
#endif

        /* Start tranmitting by toggling xmit reg empty in interrupt enable reg   */
        OUTBYTE(uinfo->port_base + IER, THRE_OFF);  /* THRE off */
        io_delay();
        OUTBYTE(uinfo->port_base + IER, THRE_ON);  /* THRE on */
        io_delay();
    }
#else
#error: Implement uart enable tx interrupts
#endif
}
Ejemplo n.º 16
0
/* 16550 is done with a macro in uartport.h   */
void uart_hw_resume_sender(PUART_INFO uinfo)
{
#if (UART_16550)
    if (uinfo->handshake_mask)
    {
        OUTBYTE(uinfo->port_base + MCR, INBYTE(uinfo->port_base + MCR) | uinfo->resume_mask); 
        io_delay();
    }
#else
#error Implement hw handshaking, rx enable, or turn off SUPPORTS_HANDSHAKING
#endif
}
Ejemplo n.º 17
0
void uart_hw_hold_off_sender(PUART_INFO uinfo)
{
#if (UART_16550)
    if (uinfo->handshake_mask) 
    {
DEBUG_ERROR("HOLD OFF SENDER", NOVAR, 0, 0);
        OUTBYTE(uinfo->port_base + MCR, INBYTE(uinfo->port_base + MCR) & uinfo->holdoff_mask ); 
        io_delay();
    }
#else
#error Implement hw handshaking, rx enable, or turn off SUPPORTS_HANDSHAKING
#endif
}
Ejemplo n.º 18
0
static int 
kbd_handler (excp_entry_t * excp, excp_vec_t vec)
{

    uint8_t status;
    uint8_t scan;
    uint8_t key;
    uint8_t flag;

    status = inb(KBD_CMD_REG);

    io_delay();

    if ((status & STATUS_OUTPUT_FULL) != 0) {
      scan  = inb(KBD_DATA_REG);
      DEBUG_PRINT("Keyboard: status=0x%x, scancode=0x%x\n", status, scan);
      io_delay();

      if (!(scan & KBD_RELEASE)) {
          goto out;
      }

#if NAUT_CONFIG_THREAD_EXIT_KEYCODE == 0xc4
      /* this is a key release */
      if (scan == 0xc4) {
          void * ret = NULL;
          IRQ_HANDLER_END();
          nk_thread_exit(ret);
      }
#endif
      
    }


out:
    IRQ_HANDLER_END();
    return 0;
}
Ejemplo n.º 19
0
void init_8259A()
{

	outb(PIC_MASTER_IMR, 0xff);     	/* mask all of 8259A-1 */
	io_delay();
	outb(PIC_SLAVE_IMR,  0xff);      	/* mask all of 8259A-2 */
	io_delay();


	outb(PIC_MASTER_CMD,0x11); 		/* ICW1: select 8259A-1 init */
	io_delay();
	
	outb(PIC_MASTER_IMR, IRQ0_VECTOR);	/* ICW2: 8259A-1 IR0-7 mapped to to 0x20-0x27*/
	io_delay();

	/* 8259A-1 (the master) has a slave on IR2 */
	outb(PIC_MASTER_IMR,1U << PIC_CASCADE_IR);/*ICM3*/
	io_delay();
	outb(PIC_MASTER_IMR,0x1);		/* ICW4 */
	io_delay();

	//set up slave

	outb(PIC_SLAVE_CMD,0x11); 		/* ICW1: select 8259A-1 init */
	io_delay();
	outb(PIC_SLAVE_IMR, IRQ8_VECTOR);	/* ICW2: 8259A-1 IR0-7 mapped to to 0x28-0x2F*/
	io_delay();

	/* 8259A-2 (the slave) has a slave on IR2 */
	outb(PIC_SLAVE_IMR,PIC_CASCADE_IR);/*ICM3*/
	io_delay();
	outb(PIC_SLAVE_IMR,0x1);		/* ICW4 */
	io_delay();
	
	if (irq_mask_8259A != 0xFFFF)
		setmask_8259A_irq(irq_mask_8259A);
	
}
Ejemplo n.º 20
0
static void beep(unsigned int hz)
{
	u8 enable;

	if (!hz) {
		enable = 0x00;		
	} else {
		u16 div = 1193181/hz;

		outb(0xb6, 0x43);	
		io_delay();
		outb(div, 0x42);	
		io_delay();
		outb(div >> 8, 0x42);	
		io_delay();

		enable = 0x03;		
	}
	inb(0x61);		
	io_delay();
	outb(enable, 0x61);	
	io_delay();
}
Ejemplo n.º 21
0
static void beep(unsigned int hz)
{
	u8 enable;

	if (!hz) {
		enable = 0x00;		/* Turn off speaker */
	} else {
		u16 div = 1193181/hz;

		outb(0xb6, 0x43);	/* Ctr 2, squarewave, load, binary */
		io_delay();
		outb(div, 0x42);	/* LSB of counter */
		io_delay();
		outb(div >> 8, 0x42);	/* MSB of counter */
		io_delay();

		enable = 0x03;		/* Turn on speaker */
	}
	inb(0x61);		/* Dummy read of System Control Port B */
	io_delay();
	outb(enable, 0x61);	/* Enable timer 2 output to speaker */
	io_delay();
}
Ejemplo n.º 22
0
/*
 * note: char in some C compiled is 'unsigned"
 */
void lcd_scroll(signed char steps)
{
   char cmd = (steps>0)?0x1c:0x18;
   short ssteps= (steps>0)?steps:(-steps);
   /* get negetive is unsafe, char range: -128 to +127, 
    * so -128 get negtive is overflow
	*/

   while(ssteps--)
   {
    	send_cmd((unsigned char)cmd);
		io_delay();  
   }
}
Ejemplo n.º 23
0
int uart_hw_check_error(PUART_INFO uinfo)
{
#if (UART_16550)
byte err_flag = (byte)(INBYTE(uinfo->port_base + LSR) & 0x1eu);

    if (err_flag)
    {
        if (err_flag & LS_OVRRUN_ERR)   return 0;
        if (err_flag & LS_PARITY_ERR)   return 1;
        if (err_flag & LS_FRAME_ERR)    return 2;
    }
    io_delay();
    return -1;
#else
#error: Implement checking error status 
#endif
}
Ejemplo n.º 24
0
static int __bootcode a20_test(int loops)
{
	int ok = 0;
	int saved, ctr;

	set_fs(0x0000);
	set_gs(0xffff);

	saved = ctr = rdfs32(A20_TEST_ADDR);

	while (loops--) {
		wrfs32(++ctr, A20_TEST_ADDR);
		io_delay();	/* Serialize and make delay constant */
		ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
		if (ok)
			break;
	}

	wrfs32(saved, A20_TEST_ADDR);
	return ok;
}
Ejemplo n.º 25
0
static void hd44870_send(unsigned char data, char is_cmd) 
{
  io_delay();
  
  bus4w &=~(_EN|_RW);       
  _rswe();
  //io_delay();
  
  if(is_cmd)
  	 bus4w&=~_RS;  //RS=0,command
  else
  	 bus4w|=_RS;  //RS=1, data
  _rswe();
  io_delay();
  
  /* 4 MSB*/
  bus4w &= ~(_DATA);    
  bus4w |= data&_DATA; 
  _data();
  
  io_delay();
  bus4w |=_EN;  
  _rswe();
  io_delay(); 
  bus4w &=~_EN;   
  _rswe();

  io_delay();
  
  /*send low 4 lsb*/
  bus4w&=~_DATA;         
  bus4w|=(data<<4)&_DATA; 
  _data();
  io_delay();

  bus4w |=_EN;  
  _rswe();
  io_delay(); 
  bus4w &=~_EN;   
  _rswe();
  
  
}
Ejemplo n.º 26
0
static void udelay(int loops)
{
	while (loops--)
		io_delay();	/* Approximately 1 us */
}
Ejemplo n.º 27
0
uint spin1_start (sync_bool sync)
{
  sark_cpu_state (CPU_STATE_RUN);

  // Initialise hardware

  configure_communications_controller();
  configure_dma_controller();
  configure_timer1 (timer_tick);
  configure_vic();

#if (API_WARN == TRUE) || (API_DIAGNOSTICS == TRUE)
  warnings = NO_ERROR;
  dfull = 0;
  fullq = 0;
  pfull = 0;
#if USE_WRITE_BUFFER == TRUE
  wberrors = 0;
#endif
#endif

  // synchronise with other application cores

  if (sync == SYNC_WAIT)
    event_wait ();

  // initialise counter and ticks for simulation
  // 32-bit, periodic counter, interrupts enabled

  if (timer_tick)
    tc[T1_CONTROL] = 0xe2;

  ticks = 0;
  run = 1;

  // simulate!
  dispatch ();

  // simulation finished - clean up before returning to c_main
  clean_up ();

  // re-enable interrupts for sark
  // only CPU_INT enabled in the VIC
  spin1_int_enable ();

  // provide diagnostics data to application
  #if (API_DIAGNOSTICS == TRUE)
    diagnostics.exit_code            = exit_val;
    diagnostics.warnings             = warnings;
    diagnostics.total_mc_packets     = rtr[RTR_DGC0] + rtr[RTR_DGC1];
    diagnostics.dumped_mc_packets    = rtr[RTR_DGC8];
    diagnostics.discarded_mc_packets = thrown;
    diagnostics.dma_transfers        = dma_id - 1;
    diagnostics.dma_bursts           = dma[DMA_STAT0];
    diagnostics.dma_queue_full       = dfull;
    diagnostics.task_queue_full      = fullq;
    diagnostics.tx_packet_queue_full = pfull;
    #if USE_WRITE_BUFFER == TRUE
      diagnostics.writeBack_errors     = wberrors;
    #endif
  #endif

  // report problems if requested!
  #if (API_DEBUG == TRUE) || (API_WARN == TRUE)
    // avoid sending output at the same time as other chips!
    io_delay (10000 * my_chip);

    #if API_DEBUG == TRUE	// report debug information
      report_debug();
    #endif

    #if API_WARN == TRUE       	// report warnings
      report_warns ();
    #endif
  #endif

  return exit_val;
}
Ejemplo n.º 28
0
/* ********************************************************************   */
RTIP_BOOLEAN uart_hw_init(PUART_INFO uinfo)
{
#if (UART_16550)
byte baud_rate_divisor;
word port_base;
byte comm_irq;
byte temp_iir;
#if (DONT_OPEN_UART)
    return(TRUE);
#endif

#if (UART_SUPPORTS_HANDSHAKING)
    if (uinfo->handshake_type == 'R')
    {
#if (DEBUG_HANDSHAKING)
        DEBUG_ERROR("DOING R HANDSHAKING", NOVAR, 0, 0);
#endif
         uinfo->handshake_mask = UART_CTS;
         uinfo->holdoff_mask = (byte)(~UART_RTS);
         uinfo->resume_mask = UART_RTS;
    }
    else if (uinfo->handshake_type == 'D')
    {
       uinfo->handshake_mask = UART_DSR;
       uinfo->holdoff_mask = (byte)(~UART_DTR);
       uinfo->resume_mask = UART_DTR;
    }
    else
    {
       uinfo->handshake_mask = 0;
       uinfo->holdoff_mask = (byte)(~UART_DTR);
       uinfo->resume_mask = UART_DTR;
    }
#endif /* UART_SUPPORTS_HANDSHAKING */

    switch (uinfo->comm_port)
    {
    case 1 :
        port_base = 0x3F8;   /* I/O address for COM1  */
        comm_irq  =     4;   /* IRQ for COM1  */
        break;
    case 2 :
        port_base = 0x2F8;   /* I/O address for COM2  */
        comm_irq  =     3;   /* IRQ for COM2  */
        break;
    case 3 :
        port_base = 0x3E8;   /* I/O address for COM3  */
        comm_irq  =     4;   /* IRQ for COM3  */
        break;
    case 4 :
        port_base = 0x2E8;   /* I/O address for COM4  */
        comm_irq  =     3;   /* IRQ for COM4  */
        break;
    default:
        DEBUG_ERROR("uart_hw_init: illegal comm port: ", EBS_INT1, uinfo->comm_port, 0);
        return(FALSE);
    }

    /* ******                                                       */
    /* convert baud rate to divisor and check if baud rate is valid */
    switch (uinfo->baud_rate)
    {
    case 1152:
        baud_rate_divisor = 1;
        break;
    case 560:
        baud_rate_divisor = 2;
        break;
    case 384:
        baud_rate_divisor = 3;
        break;
    case 192:
        baud_rate_divisor = 6;
        break;
    case 96:
        baud_rate_divisor = 12;
        break;
    case 24:
        baud_rate_divisor = 48;
        break;
    case 12:
        baud_rate_divisor = 96;
        break;
    default:
        DEBUG_ERROR("uart_hw_init - bad baud rate = ", EBS_INT1, uinfo->baud_rate, 0);
        return(FALSE); /*  set_errno(EBADBAUD); */
    }

    /* Initialize UART                                   */
    /* interrupts were disabled already by the caller    */

    /* Set communication rate and parameters   */
    OUTBYTE(port_base + LCR, 0x80);   /* divisor access */
    io_delay();
    OUTBYTE(port_base + BRDL, baud_rate_divisor);
    io_delay();
    OUTBYTE(port_base + BRDH, 0);
    io_delay();
    OUTBYTE(port_base + LCR, 0x03);   /* divisor off, no parity, 1 stop bit, 8 bits */
    io_delay();

    /* Clear existing interrupts   */
    INBYTE(port_base + LSR);
    io_delay();
    INBYTE(port_base + MSR);
    io_delay();
    INBYTE(port_base + RBR);
    io_delay();

    /* Enable FIFO with receive interrupt after 8 char   */
    OUTBYTE(port_base + FCR, 0x87);
    io_delay();

    uinfo->xmit_fifo_size = 1;
    temp_iir = (byte)(INBYTE(port_base + IIR) & 0xf0);
    if (temp_iir == 0xc0)
    {
        DEBUG_ERROR("UART: 16550A", NOVAR, 0, 0);
        uinfo->is_16550=TRUE;
        uinfo->xmit_fifo_size = 16;
    }

    /* Enable read buffer full and receiver line status interrupts   */
    /* but not TX ints. Also enable modem status change INTS.        */
    
    OUTBYTE(port_base + IER, THRE_OFF);
    io_delay();

    /* cause uart_interrupt to execute when interrupt occurs and   */
    /* uart_receive to be called by the interrupt task             */
    ks_hook_interrupt(comm_irq, (PFVOID) 0, 
                      (RTIPINTFN_POINTER)uart_interrupt, 
                      (RTIPINTFN_POINTER) 0, uinfo->minor_number);
    io_delay();

    /* Enable interrupt signal and DTR    */
    OUTBYTE(port_base + MCR, 0x0b);   
    io_delay();

    uinfo->port_base=port_base;
    uinfo->comm_irq=comm_irq;
#else
#error: Set up any hardware dependent driver info here, and put it in UART_INFO
#endif
    return(TRUE);
}
Ejemplo n.º 29
0
static inline void crtc_write(unsigned char index, unsigned char val) {

    outb(CRTC_ADDRESS_PORT, index);
    io_delay();
    outb(CRTC_DATA_PORT, val);
}
Ejemplo n.º 30
0
void badapple_main(void)
{
  int i;
  
  // initialize the global flags.
  sched_next_buffer = 0;
  sched_skip_frames = 0;
  
  // Detect data disk.
  if (badapple_detect_disk() != 0)
    return;
  
  // Open VGA display.
  va = va_first();
  va_switch_mode(va, VM_VGA_CG640);
  va_set_palette(va, &kDefault16GrayPalette);
  va_clear_output(va);
  
  // Initialize the buffers.
  for (i=0; i<2; ++i) {
    atomic_set(&(buffers[i].ready), 0);
    buffers[i].data = kmalloc(PIC_GROUP_SIZE);
  }
  
  // Display loading image.
  uint8_t *badapple_loading_data = badapple_loading_image;
  do {
    int compress_size = *(int*)badapple_loading_data;
    int size = 
      LZ4_decompress_safe(
        (const char*)badapple_loading_data + sizeof(int),
        (char*)buffers[0].data, compress_size, PIC_FRAME_SIZE
      );
    if (size != PIC_FRAME_SIZE) {
      panic("[badapple] Error decoding image: got %d bytes instead of %d.\n", 
            size, PIC_FRAME_SIZE);
    }
    
    va_video_write(va, buffers[0].data, 0, 0, DST_WIDTH, DST_HEIGHT);
  } while (0);
  
  // Create video data memory jar.
  uint8_t* video_compressed_data = 
    (uint8_t*)kmalloc(BADAPPLE_VIDEO_DATA_SIZE * SECTSIZE);

  // Load video data from external disk.
  if (kdisk_read_secs(ideno, 
                      video_compressed_data, 
                      BADAPPLE_VIDEO_DATA_SIZE, 
                      BADAPPLE_VIDEO_DATA_OFFSET + ideoff) != 0) {
    panic("[badapple] Cannot load video data from disk.\n");
  }
  printf("[badapple] Video data already loaded from disk.\n");
  
  // Loop and decode data.
  do {
    int group = 0;
    uint8_t *p = video_compressed_data;
    i = 0; sched_inited = 1;
    for (;;) {
      // wait for buffer to be used up.
      while (atomic_read(&(buffers[i].ready)) != 0) 
        io_delay();
      // get next group compressed size.
      int compress_size = *(int*)p;
      p += sizeof(int); ++group;
      if (compress_size == 0) {
        va_clear_output(va);
        printf("[badapple] All frames decoded, badapple_main exit.\n");
        break;
      }
      
      // decompress this group.
      int size = LZ4_decompress_safe((const char*)p, (char*)buffers[i].data, 
                                     compress_size, PIC_GROUP_SIZE);
      if (size != PIC_GROUP_SIZE) {
        printf("[badapple] Error decoding %d sec (offset 0x%08x): "
               "got %d bytes instead of %d; compress size is %d.\n", 
               group, p - video_compressed_data, size, PIC_GROUP_SIZE,
               compress_size
              );
      }
      
#if 0
      else {
        printf("[badapple] Decoded %d sec on buffer[%d].\n", group, i);
      }
#endif

      p += compress_size;
      // Set the ready flag.
      atomic_set(&(buffers[i].ready), 1);
      i = 1 - i;
    }
  } while (0);
  
  // Free all resources.
  kfree(video_compressed_data);
}