- 论坛徽章:
- 0
|
首先明确, 我们写driver 一个主要的动作就是 control register , 所以怎么样在driver
里面control register 这个时候就要查datasheet 了,我们写driver 的人只要严格按照
datasheet的steps就好了,
比如我举个例子: 对于intel 的 8255x lan controller (就是网卡控制芯片,也就是
微机原理书上的接口电路,用来连接总线和实际的网卡设备) ,kernel里面的code 就是
drivers/net/e100
比如对于这个功能: 如何determine EEPROM size , 我们要在driver里面实现 ,
就必须到datasheet里面查 , 下面就是 如何determine EEPROM size 的 描述:
6.3.4.2 Software Determination of EEPROM Size
To determine the size of the EEPROM, software may use the following steps.
Note: This algorithm will only work if the EEPROM drives a dummy zero to EEDO after
receiving the
complete address field.
1. Activate the EEPROM by writing a 1 to the EECS bit.
2. Write the read opcode, including the start bit (110b), one bit at a time starting
with the most
significant bit (1):
a. Write the opcode bit to the EEDI bit.
b. Write a 1 to EESK bit and wait the minimum SK high time.
c. Write a 0 to EESK bit and wait the minimum SK low time.
d. Repeat steps 2.a through 2.c for the next two opcode bits.
3. Write the address field, one bit at a time, keeping track of the number of bits
shifted in, starting
with the most significant bit.
a. Write the address bit to the EEDI bit.
b. Write a 1 to the EESK bit and wait the minimum SK high time.
c. Write a 0 to the EESK bit and wait the minimum SK low time.
d. Read the EEDO bit, looking for the dummy 0 bit.
e. Repeat steps 3.a through 3.d until the EEDO bit equals 0. The number of loop
iterations
performed is the number of bits in the address field.
4. Read a 16-bit word from the EEPROM one bit at a time, starting with the most
significant bit,
to complete the transaction (but discard the output).
a. Write a 1 to the EESK bit then wait the minimum SK high time.
b. Read a data bit from the EEDO bit.
c. Write a 0 to the EESK bit then wait the minimum SK low time.
d. Repeat steps 4.a through 4.c an additional 15 times.
e. De-activate the EEPROM by writing a 0 to the EECS bit.
然后我们才可以实现我们的driver , 仔细对照 才可以成功control register
e100_eeprom.c 里面的一个函数:
//------------------------------------------------------------------------------------
----
// Procedure: e100_eeprom_size
//
// Description: This routine determines the size of the EEPROM. This value should be
// checked for validity - ie. is it too big or too small. The size
returned
// is then passed to the read/write functions.
//
// Returns:
// Size of the eeprom, or zero if an error occurred
//------------------------------------------------------------------------------------
----
u16
e100_eeprom_size(struct e100_private *adapter)
{
u16 x, size = 1; // must be one to accumulate a product
// if we've already stored this data, read from memory
if (adapter->eeprom_size) {
return adapter->eeprom_size;
}
// otherwise, read from the eeprom
// Set EEPROM semaphore.
if (adapter->rev_id >= D102_REV_ID) {
if (!eeprom_set_semaphore(adapter))
return 0;
}
// enable the eeprom by setting EECS.
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
// write the read opcode
shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
// experiment to discover the size of the eeprom. request register zero
// and wait for the eeprom to tell us it has accepted the entire address.
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
do {
size *= 2; // each bit of address doubles eeprom size
x |= EEDO; // set bit to detect "dummy zero"
x &= ~EEDI; // address consists of all zeros
writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
readw(&(adapter->scb->scb_status));
udelay(EEPROM_STALL_TIME);//udaly (4)
raise_clock(adapter, &x);
lower_clock(adapter, &x);
// check for "dummy zero"
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
if (size > EEPROM_MAX_WORD_SIZE) {
size = 0;
break;
}
} while (x & EEDO);
// read in the value requested
(void) shift_in_bits(adapter);
e100_eeprom_cleanup(adapter);
// Clear EEPROM Semaphore.
if (adapter->rev_id >= D102_REV_ID) {
eeprom_reset_semaphore(adapter);
}
return size;
}
另外 ,你要control EEPROM的寄存器, 就要找到 register的地址 ,
找datasheet 有这样的一段:(不好意思 ,粘贴pdf 上的表格不行啊)
Upper Word (D31:D16) Lower Word (D15:D0) Offset
SCB Command Word SCB Status Word Base + 0h
SCB General Pointer Base + 4h
PORT Base + 8h
EEPROM Control Register Reserved Base + Ch
在datasheet中 :是这样定义的:
Figure 12. EEPROM Control Register
23 22 21 20 19 18 17 16
X X X X EEDO EEDI EECS EESK
当我们在学习 别人的driver的时候, 发现 在定义寄存器地址的时候都是这样定义的:
比如:
#define EN_TRNF 0x10 /* Enable turnoff */
#define EEDO 0x08 /* EEPROM data out */
#define EEDI 0x04 /* EEPROM data in (set for writing data) */
#define EECS 0x02 /* EEPROM chip select (1=hi, 0=lo) */
#define EESK 0x01 /* EEPROM shift clock (1=hi, 0=lo) */
我们看出来 , 如果从0开始排 , EEDO EEDI EECS EESK
0x08 0x04 0x02 0x01
所以就对应上了 。
// enable the eeprom by setting EECS. 把EECS 置为1
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
x &= ~(EEDI | EEDO | EESK); //把这三位都置为 0 ,EECS不动 ,
//0x8 | 0x4 | 0x1 , 1101 ,
x |= EECS; // 把EECS的位置为 1
writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
从上面可以看出 , kernel里面的driver 写的多好啊 ! 一目了然 。
读datasheet 还是要针对一个你目前正在作的案子 , 死盯住一个datasheet ,把它看懂 。
我现在就一直在看 usb方面的, uhci ehci , 这些在debug的时候都要用到,还有就是
GL880和VT6212L的datasheet ,
比如:
在我们的板子上原来有个 bug , 只要插上usb harddisk ,往里面copy file ,
console就输入出 fatal error , 然后file system read-only 的错误
It looks that PCI has problems . I doubt that whether the usb chip has been attached
tightly to the PCI bus or not , maybe ,their connection is loose,result in transaction
error .
FYI ,
when copy the file into USB Harddisk , some error messages will pop up ,
ehci_hcd 00:01.2: fatal error
Unable to handle kernel NULL pointer dereference at virtual address 00000000
it is printed by a sheet of code
/* unrequested/ignored: Port Change Detect, Frame List Rollover */
dbg_status (ehci, "irq", status); // print the status of USBSTS Register
....................................
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) { //STS_FATAL : 1
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/58463/showart_1951134.html |
|