文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Driver Writer如何读DATASHEET(总结BBS文章)

Driver Writer如何读DATASHEET(总结BBS文章)

时间:2009-06-01  来源:bingqi17

首先明确, 我们写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<<4

ehci_err (ehci, "fatal error
"); //will print "ehci_hcd 00:01.2: fatal error"

...........................................

// ----------------------------------STS_FATAL Define

-----------------------------------

/* USBSTS: offset 0x04 */

u32 status;

#define STS_ASS (1<<15) /* Async Schedule Status */

#define STS_PSS (1<<14) /* Periodic Schedule Status */

#define STS_RECL (1<<13) /* Reclamation */

#define STS_HALT (1<<12) /* Not running (any reason) */

/* some bits reserved */

/* these STS_* flags are also intr_enable bits (USBINTR) */

#define STS_IAA (1<<5) /* Interrupted on async advance */

#define STS_FATAL (1<<4) /* such as some PCI access errors */

#define STS_FLR (1<<3) /* frame list rolled over */

#define STS_PCD (1<<2) /* port change detect */

#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */

#define STS_INT (1<<0) /* "normal" completion (short, ...) */

//

--------------------------------------------------------------------------------------

I find EHCI 1.0 datasheet(VT6212L declare that he is compliant with Enhanced Host

Controller Interface Specification Revision 1.0)

there is some info about STS_FATAL in 2.3.2 USBSTS USB Status Register of Page 31

bit 4

Host System Error . R/WC. The Host Controller sets this bit to 1 when a serious

error

occurs during a host system access involving the Host Controller module. In a PCI

system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort,

and

PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit

in

the Command register to prevent further execution of the scheduled TDs.

这样的话, 我们基本可以定位问题, 知道问题出在了哪里 。、
相关阅读 更多 +
排行榜 更多 +
PvZ戴夫的时空冒险重置

PvZ戴夫的时空冒险重置

策略塔防 下载
PVZTV雪版阳光加50

PVZTV雪版阳光加50

策略塔防 下载
双刃战士雪姐

双刃战士雪姐

冒险解谜 下载