zhangnengjun 发表于 2008-7-14 00:04:00

谁帮详细解释所有发给ec的60/64命令号码和意义

bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。

amty.wang 发表于 2008-7-14 12:09:38

转个别人发的,不知道LZ能不能用上:)

4.2.7 Command

通过8042芯片,可以:
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
读取Status Register的内容(通过64h);
向8048发布命令(通过60h);
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。

再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。



    * 64h端口(读操作)


对64h端口进行读操作,会读取Status Register的内容。

inb %0x64
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。

    * 64h端口(写操作)

向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
Ÿ
写入的字节将会被存放在Input Register中;
Ÿ
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;
Ÿ
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;
Ÿ
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。

void wait_input_empty(void)
{
   char __b;

   do{
   __b = inb(0x64);
   }while(!(__b&0x02));
}

void disable_keyboard(void)
{
   wait_input_empty();
   outb(0x64, 0xAD);
}

    * 60h端口(读操作)

对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
Ÿ         来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
Ÿ         通过64h端口对8042发布的命令的返回结果。

在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
void wait_output_full(void)
{
   char __b;

   do{
   __b = inb(0x64);
   }while(__b&0x01);
}

unsigned char read_output(void)
{
   wait_output_full();
   return inb(0x60);
}

    * 60h端口(写操作)

向60h端口写入的字节,有两种可能:
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;
2.否则,此字节被认为是发送给8048的命令。

在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。


4.2.7.1 发给8042的命令

    * 20h

准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。


unsigned char read_command_byte(void)
{
   wait_input_empty();
   outb(0x64,0x20);
   wait_output_full();
   return inb(0x60);   
}

    * 60h

准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。


void write_command_byte(unsigned char command_byte)
{
   wait_input_empty();
   outb(0x64,0x60);
   wait_input_empty();
   outb(0x60,command_byte);
}


    * A4h

测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
bool is_set_password(void)
{
   wait_input_empty();
   outb(0x64,0xA4);
   wait_output_full();
   return inb(0x60)==0xFA?true:false;   
}

    * A5h

设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
void set_password(unsigned char* password)
{
   char* p = password;

   if(p == NULL)
      return;

   wait_input_empty();
   outb(0x64,0xA5);

   do{
      wait_input_empty();
      outb(0x60, *p);
   }while(*p++ != 0);
}

    * A6h

让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
void enable_password(void)
{
   if(!is_set_password())
      return;

   wait_input_empty();
   outb(0x64,0xA6);   
}

    * AAh

自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。


bool is_test_ok(void)
{
   wait_input_empty();
   outb(0x64,0xAA);


   wait_output_full();
   return inb(0x60)==0x55?true:false;   
}


    * ADh

禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
void disable_keyboard(void)
{
   wait_input_empty();
   outb(0x64,0xAD);

}

    * AEh

打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
void enable_keyboard(void)
{
   wait_input_empty();
   outb(0x64,0xAE);

}

    * C0h

准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
unsigned char read_input_port(void)
{
   wait_input_empty();
   outb(0x64,0xC0);

   wait_output_full();

   return inb(0x60);
}

    * D0h

准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
unsigned char read_output_port(void)
{
   wait_input_empty();
   outb(0x64,0xD0);

   wait_output_full();

   return inb(0x60);
}

    * D1h

准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
void write_output_port(unsigned char __c)
{
   wait_input_empty();
   outb(0x64,0xD1);

   wait_input_empty();
   outb(0x60,__c);

}


    * D2h

准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
void put_data_to_output_register(unsigned char __data)
{
   wait_input_empty();
   outb(0x64,0xD2);

   wait_input_empty();
   outb(0x60,__c);
}

4.2.7.2 发给8048的命令


    * EDh

设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。

    * EEh

诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。

    * F0h

选择Scan code set。Keyboard系统共可能有3个Scan code set。当Keyboard收到此命令后,将回复一个ACK,然后等待一个来自于60h端口的Scan code set代码。系统必须在此命令之后发送给Keyboard一个Scan code set代码。当Keyboard收到此代码后,将再次回复一个ACK,然后将Scan code set设置为收到的Scan code set代码所要求的。

    * F2

读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。

    * F3h

设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。

    * F4h

清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。

    * F5h

设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。

    * F6h

设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。

    * FEh

Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。

    * FFh

Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。

daway 发表于 2009-1-14 13:49:16

好贴!
非常详细!
谢谢!

ak756 发表于 2009-2-25 17:37:28

2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。

我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑:(
页: [1]
查看完整版本: 谁帮详细解释所有发给ec的60/64命令号码和意义