Workaround for VIA chipset+ATAPI ZIP 100 problem
Hi, all.
I've seen a couple of mails telling about the probelem with some via chipsets and atapa floppy disks.
I experienced the same problem lately and decided to investigate this matter a bit.
The problem symtops were ide bus lockup and the following messages:
hdd: lost interrupt
ide-floppy: CoD != 0 in idefloppy_pc_intr
hdd: ATAPI reset complete
After extensive tracing the look seemed to change from 100% sure to random ones and they only followed after a large write packet command. I decided to try a small delay before every command (the hardware might busy after the write and ignoring new requests). This seemed to cure my atapi zip floppy.
I'm not a kernel or an ide expert, but I created a little patch which works on my system quite stably. Any feedback on the solution
appreciated: eg. if it works for others or not and is the chipset stuff I added okay. Also I'm not sure which versions of the via chipset are the buggy ones so it enables the workaround whenever a via chipset is found.
Regards,
Timo Teräs
PS. Please send mails directly or Cc me, since I haven't subscribed to this list.
drivers/ide/ide-floppy.c +18 -0
@@ -238,6 +238,8 @@int wp;/* Write protect */ unsigned int flags;/* Status/Action flags */ + +unsigned long via_kludge; } idefloppy_floppy_t;/*
@@ -1034,11 +1036,19 @@static void idefloppy_rw_callback (ide_drive_t *drive) { +idefloppy_floppy_t *floppy = drive->driver_data; +#if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n" );#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_end_request (1 ,HWGROUP (drive)); + +if (HWIF (drive)->chipset == ide_via82cxxx && + (floppy->pc->c[0 ] ==IDEFLOPPY_WRITE10_CMD || + floppy->pc->c[0 ] ==IDEFLOPPY_WRITE12_CMD )) { + floppy->via_kludge = jiffies +HZ /40 ; + }return ; }
@@ -1153,6 +1163,13 @@idefloppy_end_request (0 ,HWGROUP (drive));return ide_stopped; } +if (floppy->via_kludge) { +long wait = floppy->via_kludge - jiffies; +if (wait >0 ) { +mdelay (wait*1000 /HZ ); + } + floppy->via_kludge =0 ; + }switch (rq->cmd) {case READ :case WRITE :
@@ -1541,6 +1558,7 @@memset (floppy,0 ,sizeof (idefloppy_floppy_t)); floppy->drive = drive; floppy->pc = floppy->pc_stack; + floppy->via_kludge =0 ;if (gcw.drq_type ==1 )set_bit (IDEFLOPPY_DRQ_INTERRUPT , &floppy->flags);/*
drivers/ide/via82cxxx.c +1 -0
@@ -494,6 +494,7 @@ hwif->tuneproc = &via82cxxx_tune_drive; hwif->speedproc = &via_set_drive; hwif->autodma =0 ; + hwif->chipset = ide_via82cxxx;for (i =0 ; i <2 ; i++) { hwif->drives[i].io_32bit =1 ;
include/linux/ide.h +1 -1
@@ -405,7 +405,7 @@ ide_qd6580, ide_umc8672, ide_ht6560b, ide_pdc4030, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, - ide_pmac + ide_pmac, ide_via82cxxx } hwif_chipset_t;#ifdef CONFIG_BLK_DEV_IDEPCI
drivers/ide/ide-floppy.c line 1167
Quoted 2 lines
drivers/ide/ide-floppy.c +2
-0+if (floppy->via_kludge) { +long wait = floppy->via_kludge - jiffies;
that will do strange things when the timer wraps. Use unsigned and "time_before"
As to the rest perhaps Andre can comment