示例#1
0
文件: ps2.c 项目: PyroOS/Pyro
/* Initializes the controller and the keyboard part */
static status_t ps2_keyboard_init()
{
	int nError = 0;
	g_nKbdLedStatus = 0;
	
	memset( &g_sKbdPort, 0, sizeof( g_sKbdPort ) );
	
	/* Flush buffer */
	ps2_flush();
	
	/* Read control register */
	uint8 nControl = 0;
	nError = ps2_read_command( PS2_CMD_RCTR, &nControl );
	
	if( nError < 0 ) {
		printk( "PS2 I/O error\n" );
		return( -EIO );
	}
	
	/* TODO: Disable keyboard */
	nControl |= PS2_CTR_KBDDIS;
	nControl &= ~PS2_CTR_KBDINT;
	
	/* Check if translated mode is enabled */
	if( !( nControl & PS2_CTR_XLATE ) )
	{
		printk( "Keyboard is in non-translated mode. This is not supported\n" );
		return( -ENOENT );
	}
	
	/* Write control register */
	nError = ps2_write_command( PS2_CMD_WCTR, nControl );
	if( nError < 0 ) {
		printk( "PS2 I/O error\n" );
		return( -EIO );
	}
	
	g_sKbdPort.bPresent = true;
	g_sKbdPort.hWait = create_semaphore( "ps2_wait", 0, 0 );
	g_sKbdPort.nIrq = 1;
	g_sKbdPort.nDevHandle = register_device( "", "isa" );
	claim_device( g_nDevNum, g_sKbdPort.nDevHandle, "PS/2 or AT keyboard", DEVICE_INPUT );
	set_device_data( g_sKbdPort.nDevHandle, &g_sKbdPort );
	nError = create_device_node( g_nDevNum, g_sKbdPort.nDevHandle, "keybd", &g_sOperations, &g_sKbdPort );
	
	printk( "PS2 or AT Keyboard detected\n" );
	return( 0 );
}
示例#2
0
文件: ps2.c 项目: PyroOS/Pyro
status_t ps2_open( void* pNode, uint32 nFlags, void **pCookie )
{
    uint8 nControl;
    uint32 nFlg;
    PS2_Port_s* psPort = (PS2_Port_s*)pNode;
    
    printk( "ps2_open()\n" );
  
    if ( atomic_inc_and_read( &psPort->nOpenCount ) > 0 ) {
    	atomic_dec( &psPort->nOpenCount );
		return( -EBUSY );
    }
	ps2_flush();
	
    psPort->nIrqHandle = request_irq( psPort->nIrq, ps2_interrupt, NULL, 0, "ps2", psPort );
    if ( psPort->nIrqHandle < 0 ) {
    	printk( "PS2: Could not get irq %i\n", psPort->nIrq );
		atomic_dec( &psPort->nOpenCount );
		return( -EBUSY );
    }
    
    /* Enable device */
    if( psPort->bIsAux )
		ps2_command( PS2_CMD_AUX_ENABLE );
	nFlg = spinlock_disable( &g_sLock );
	ps2_read_command( PS2_CMD_RCTR, &nControl );
    
	if( psPort->bIsAux ) {
    	nControl &= ~PS2_CTR_AUXDIS;
    	nControl |= PS2_CTR_AUXINT;
    } else {
    	nControl &= ~PS2_CTR_KBDDIS;
    	nControl |= PS2_CTR_KBDINT;
    }
	ps2_write_command( PS2_CMD_WCTR, nControl );
    spinunlock_enable( &g_sLock, nFlg );
  
    atomic_set( &psPort->nBytesReceived, 0 );
    atomic_set( &psPort->nInPos, 0 );
    atomic_set( &psPort->nOutPos, 0 );
    
 
    return( 0 );
}
示例#3
0
  void KBM::init()
  {
    // disable ports
    ctl_send(CMD_DISABLE_PORT1);
    ctl_send(CMD_DISABLE_PORT2);
    ps2_flush();

    // configure controller
    ctl_send(0x20);
    uint8_t config = read_data();
    bool second_port = config & (1 << 5);
    (void) second_port;

    config |= 0x1 | 0x2; // enable interrupts
    config &= ~(1 << 6);

    // write config
    ctl_send(0x60);
    send_data(config);

    ps2_flush();

    // enable port1
    ctl_send(CMD_ENABLE_PORT1);

    ps2_flush();

    // self-test (port1)
    write_port1(0xFF);
    uint8_t selftest = read_data();
    assert(selftest == 0xAA);

    write_port1(DEV_IDENTIFY);
    uint8_t id1 = read_data();

    if (id1 == 0xAA || id1 == 0xAB) {
      // port1 is the keyboard
      debug("keyboard on port1\n");
      keyboard_write = write_port1;
      mouse_write    = write_port2;
    }
    else {
      // port2 is the keyboard
      debug("keyboard on port2\n");
      mouse_write    = write_port1;
      keyboard_write = write_port2;
    }

    // enable keyboard
    keyboard_write(0xF4);

    // get and set scancode
    keyboard_write(0xF0);
    send_data(0x01);
    keyboard_write(0xF0);
    send_data(0x00);
    uint8_t scanset = 0xFA;
    while (scanset == 0xFA) scanset = read_data();

    // route and enable interrupt handlers
    const uint8_t KEYB_IRQ = (keyboard_write == write_port1) ? PORT1_IRQ : PORT2_IRQ;
    const uint8_t MOUS_IRQ = (KEYB_IRQ == PORT1_IRQ) ? PORT2_IRQ : PORT1_IRQ;
    assert(KEYB_IRQ != MOUS_IRQ);

    // need to route IRQs from IO APIC to BSP LAPIC
    IRQ_manager::get().enable_irq(KEYB_IRQ);
    IRQ_manager::get().enable_irq(MOUS_IRQ);

    IRQ_manager::get().subscribe(KEYB_IRQ,
    [KEYB_IRQ] {
      //IRQ_manager::eoi(KEYB_IRQ);
      uint8_t byte = read_fast();
      // transform to virtual key
      int key = get().transform_vk(byte);
      // call handler
      get().on_virtualkey(key);
    });

    IRQ_manager::get().subscribe(MOUS_IRQ,
    [MOUS_IRQ] {
      //IRQ_manager::eoi(MOUS_IRQ);
      get().handle_mouse(read_fast());
    });

    /*
    // reset and enable keyboard
    send_data(0xF6);

    // enable keyboard scancodes
    send_data(0xF4);

    // enable interrupts
    //ctl_send(0x60, ctl_read(0x20) | 0x1 | 0x2);
    */
  }
示例#4
0
文件: ps2.c 项目: PyroOS/Pyro
static status_t ps2_aux_init()
{
	int nError = 0;
	struct RMREGS rm;

	/* TODO: Do this without calling the bios */
	memset( &rm, 0, sizeof( struct RMREGS ) );
	realint( 0x11, &rm );

	if( ( rm.EAX & 0x04 ) == 0 ) {
		printk( "No PS2 mouse present\n" );
		return( -EIO );
    }
	
	memset( &g_sAuxPort, 0, sizeof( g_sAuxPort ) );
	g_sAuxPort.bIsAux = true;
	
	/* Flush buffer */
	ps2_flush();
	
	/* Test loop command */
	uint8 nData = 0x5a;
	
	nError = ps2_write_read_command( PS2_CMD_AUX_LOOP, &nData );
	
	if( nError < 0 || nData != 0x5a )
	{
		/* According to linux driver the loop test fails on some chipsets */
		printk( "PS2 Aux loop test failed (error = %i, data = %x)! Trying test command...\n", nError, (uint)nData );
		if( ps2_read_command( PS2_CMD_AUX_TEST, &nData ) < 0 )
		{
			printk( "Failed -> Aux port not present!\n" );
			return( -ENOENT );
		}
		printk( "Test command returned %x\n", (uint)nData );
		if( nData && nData != 0xfa && nData != 0xff )
		{
			printk( "Invalid return code!\n" );
			return( -ENOENT );
		}
	}
	
	/* Disable and then enable the auxport */
	if( ps2_command( PS2_CMD_AUX_DISABLE ) < 0 )
		return( -ENOENT );
	if( ps2_command( PS2_CMD_AUX_ENABLE ) < 0 )
		return( -ENOENT );
	if( ps2_read_command( PS2_CMD_RCTR, &nData ) < 0 || ( nData & PS2_CTR_AUXDIS ) )
		return( -EIO );
		
	/* Disable aux port */
	nData |= PS2_CTR_AUXDIS;
	nData &= ~PS2_CTR_AUXINT;
	
	/* Write control register */
	nError = ps2_write_command( PS2_CMD_WCTR, nData );
	if( nError < 0 ) {
		printk( "PS2 I/O error\n" );
		return( -EIO );
	}

	printk( "PS2 AUX port detected\n" );
	
	/* Register device */
	
	g_sAuxPort.bPresent = true;
	g_sAuxPort.hWait = create_semaphore( "ps2_wait", 0, 0 );
	g_sAuxPort.nDevHandle = register_device( "", "isa" );
	g_sAuxPort.nIrq = 12;
	claim_device( g_nDevNum, g_sAuxPort.nDevHandle, "PS/2 Aux port", DEVICE_PORT );
	set_device_data( g_sAuxPort.nDevHandle, &g_sAuxPort );
	nError = create_device_node( g_nDevNum, g_sAuxPort.nDevHandle, "misc/ps2aux", &g_sOperations, &g_sAuxPort );
	
	if( nError < 0 )
		return( -EIO );
	
	return( 0 );
}