(2.6.34内核, 使用cf卡的IDE模式,PIO传输方式)
设备选择协议
============
设备选择协议请参考: http://wenku.baidu.com/view/40f58020aaea998fcc220e2e.html
在写设备寄存器之前需要确定BSY和DRQ这两位为0:
/* yll
* 根据设备选择协议,在往device寄存器中写入以前必须等待BSY和DRQ为0
*/
if (valid & IDE_VALID_DEVICE) {
for(i=10000; i; --i) {
tmp = ide_inb(io_ports->status_addr);
if (!( tmp & (1<<7 | 1<<3) )) //wait for BUSY==0,DRQ==0
break;
}
tf_outb(tf->device, io_ports->device_addr);
}
经过测试,如果没有等待BSY和DRQ这两位为0,则16G(133X)的金士顿CF卡和1G的工业卡无法正常挂载,虽然其扇区数等ID信息是可以被读出的.
忽略意外中断
============
采取措施
-------------
在driver/ide/ide-io.c的函数ide_intr中,将处理意外中断的函数unexpected_intr注释掉:
if (handler == NULL || hwif->polling) {
/*
* Not expecting an interrupt from this drive.
* That means this could be:
* (1) an interrupt from another PCI device
* sharing the same PCI INT# as us.
* or (2) a drive just entered sleep or standby mode,
* and is interrupting to let us know.
* or (3) a spurious interrupt of unknown origin.
*
* For PCI, we cannot tell the difference,
* so in that case we just ignore it and hope it goes away.
*/
if ((host->irq_flags & IRQF_SHARED) == 0) {
/*
* Probably not a shared PCI interrupt,
* so we can safely try to do something about it:
*/
#if 0//yll: do nothing ########## Look Here ################
unexpected_intr(irq, hwif);
#endif
} else {
/*
* Whack the status register, just in case
* we have a leftover pending IRQ.
*/
(void)hwif->tp_ops->read_status(hwif);
}
goto out;
}
错误信息和现象
---------------------
CF卡有时会产生一些意外的中断,如果不将unexpected_intr注释掉,会产生以下类似的错误:
ide0: unexpected interrupt, status=0x51, count=4
hda: task_pio_intr: status=0x51 { DriveReady SeekComplete Error }
hda: task_pio_intr: error=0x10 { SectorIdNotFound }, CHS=2/0/221, sector=733
hda: possibly failed opcode: 0x20
ide0: unexpected interrupt, status=0x51, count=16
或者:
--------
ide0: unexpected interrupt, status=0x51, count=3
ide0: unexpected interrupt, status=0x51, count=4
ide0: unexpected interrupt, status=0x51, count=5
ide0: unexpected interrupt, status=0x51, count=6
ide0: unexpected interrupt, status=0x51, count=7
ide0: unexpected interrupt, status=0x51, count=8
ide0: unexpected interrupt, status=0xd1, count=9
hda: status error: status=0x59 { DriveReady SeekComplete DataRequest Error }
hda: status error: error=0x00 { }
hda: possibly failed opcode: 0x30
hda: no DRQ after issuing WRITE
ide0: reset: master: ECC circuitry error
ide0: unexpected interrupt, status=0x51, count=11
ide0: unexpected interrupt, status=0x51, count=12
cp: write error: No space left on device
这些错误可能会引起读写操作的意外停止,或者使CF卡变成只读的,还可能破坏CF卡上的文件系统,损坏数据,让CF卡的可用空间变小,一些文件无法读写。
原因
-----------
ide_intr是中断上下文,如果调用了unexpected_intr,unexpected_intr会调用printk函数打印信息。
注释掉unexpected_intr之后测试表明,数据传输并不会出错(md5码验证),也不再有恼人的错误信息。