--- libata-dev-2.6-reorg/drivers/scsi/pata_pdc2027x.c 2005-04-11 15:05:28.000000000 +0800 +++ libata-dev-2.6-pll-fix/drivers/scsi/pata_pdc2027x.c 2005-04-11 15:05:42.000000000 +0800 @@ -29,7 +29,7 @@ #include #define DRV_NAME "pata_pdc2027x" -#define DRV_VERSION "0.59" +#define DRV_VERSION "0.60" #undef PDC_DEBUG #ifdef PDC_DEBUG @@ -463,7 +463,10 @@ { u8 ctr0, ctr1, ctr2, ctr3; unsigned long counter; + u8 ctr0v, ctr1v, ctr2v, ctr3v; + int retry = 1; +retry: outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03); outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); @@ -473,10 +476,32 @@ outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03); + /* Read the counter values again for verification */ + outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); + ctr0v = inb(probe_ent->port[0].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); + ctr1v = inb(probe_ent->port[0].bmdma_addr + 0x03); + outb(0x20, probe_ent->port[1].bmdma_addr + 0x01); + ctr2v = inb(probe_ent->port[1].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); + ctr3v = inb(probe_ent->port[1].bmdma_addr + 0x03); + counter = (ctr3 << 23) | (ctr2 << 15) | (ctr1 << 8) | ctr0; PDPRINTK("ctr0[%X] ctr1[%X] ctr2[%X] ctr3[%X]\n", ctr0, ctr1, ctr2, ctr3); + PDPRINTK("ctr0[%X] ctr1[%X] ctr2[%X] ctr3[%X]\n", + ctr0v, ctr1v, ctr2v, ctr3v); + + /* + * The 30-bit decreasing counter are read by 4 pieces. + * Incorrect value may be read when ctr2 and ctr3 are changing. + */ + if (retry && !(ctr3 == ctr3v && ctr2 == ctr2v && ctr1 >= ctr1v)) { + retry--; + PDPRINTK("rereading counter\n"); + goto retry; + } return counter; } @@ -599,8 +624,8 @@ PDPRINTK("scr1[%X]\n", scr1); outb(scr1 | 0x40, probe_ent->port[0].bmdma_addr + 0x03); - /* Let the counter run for 1000 us. */ - udelay(1000); + /* Let the counter run for 100 ms. */ + mdelay(100); /* Read the counter values again */ end_count = pdc_read_counter(probe_ent); @@ -612,7 +637,7 @@ outb(scr1 & 0xBF, probe_ent->port[0].bmdma_addr + 0x03); /* calculate the input clock in Hz */ - pll_clock = (long) ((start_count - end_count) * 1000); + pll_clock = (long) ((start_count - end_count) * 10); PDPRINTK("start[%lu] end[%lu] \n", start_count, end_count); PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);