ostream& AmaPerishable::write(ostream& ostr, bool linear)const{ AmaProduct::write(ostr, linear); if (err_.isClear() && !isEmpty()){ linear ? ostr << expiry() : ostr << "Expiry date: " << expiry() << endl; } return ostr; }
fstream& AmaPerishable::store(fstream& file, bool addNewLine)const{ AmaProduct::store(file, false); file << "," << expiry(); if (addNewLine){ file << endl; } return file; }
/* * HACKITY HACK * * This is a workaround for the limitation 5 of the TC86C001 IDE controller: * if a DMA transfer terminates prematurely, the controller leaves the device's * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or * set the interrupt bit in the DMA status register), thus no PCI interrupt * will occur until a DMA transfer has been successfully completed. * * We work around this by initiating dummy, zero-length DMA transfer on * a DMA timeout expiration. I found no better way to do this with the current * IDE core than to temporarily replace a higher level driver's timer expiry * handler with our own backing up to that handler in case our recovery fails. */ static int tc86c001_timer_expiry(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); ide_expiry_t *expiry = ide_get_hwifdata(hwif); ide_hwgroup_t *hwgroup = HWGROUP(drive); u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); /* Restore a higher level driver's expiry handler first. */ hwgroup->expiry = expiry; if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */ unsigned long sc_base = hwif->config_data; unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " "attempting recovery...\n", drive->name); /* Stop DMA */ outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD); /* Setup the dummy DMA transfer */ outw(0, sc_base + 0x0a); /* Sector Count */ outw(0, twcr_port); /* Transfer Word Count 1 or 2 */ /* Start the dummy DMA transfer */ /* clear R_OR_WCTR for write */ outb(0x00, hwif->dma_base + ATA_DMA_CMD); /* set START_STOPBM */ outb(0x01, hwif->dma_base + ATA_DMA_CMD); /* * If an interrupt was pending, it should come thru shortly. * If not, a higher level driver's expiry handler should * eventually cause some kind of recovery from the DMA stall. */ return WAIT_MIN_SLEEP; } /* Chain to the restored expiry handler if DMA wasn't active. */ if (likely(expiry != NULL)) return expiry(drive); /* If there was no handler, "emulate" that for ide_timer_expiry()... */ return -1; }
void ide_timer_expiry (unsigned long data) { ide_hwif_t *hwif = (ide_hwif_t *)data; ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; unsigned long flags; unsigned long wait = -1; int plug_device = 0; spin_lock_irqsave(&hwif->lock, flags); handler = hwif->handler; if (handler == NULL || hwif->req_gen != hwif->req_gen_timer) { /* * Either a marginal timeout occurred * (got the interrupt just as timer expired), * or we were "sleeping" to give other devices a chance. * Either way, we don't really want to complain about anything. */ } else { ide_expiry_t *expiry = hwif->expiry; ide_startstop_t startstop = ide_stopped; drive = hwif->cur_dev; if (expiry) { wait = expiry(drive); if (wait > 0) { /* continue */ /* reset timer */ hwif->timer.expires = jiffies + wait; hwif->req_gen_timer = hwif->req_gen; add_timer(&hwif->timer); spin_unlock_irqrestore(&hwif->lock, flags); return; } } hwif->handler = NULL; /* * We need to simulate a real interrupt when invoking * the handler() function, which means we need to * globally mask the specific IRQ: */ spin_unlock(&hwif->lock); /* disable_irq_nosync ?? */ disable_irq(hwif->irq); /* local CPU only, as if we were handling an interrupt */ local_irq_disable(); if (hwif->polling) { startstop = handler(drive); } else if (drive_is_ready(drive)) { if (drive->waiting_for_dma) hwif->dma_ops->dma_lost_irq(drive); (void)ide_ack_intr(hwif); printk(KERN_WARNING "%s: lost interrupt\n", drive->name); startstop = handler(drive); } else { if (drive->waiting_for_dma) startstop = ide_dma_timeout_retry(drive, wait); else startstop = ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); } spin_lock_irq(&hwif->lock); enable_irq(hwif->irq); if (startstop == ide_stopped) { ide_unlock_port(hwif); plug_device = 1; } } spin_unlock_irqrestore(&hwif->lock, flags); if (plug_device) { ide_unlock_host(hwif->host); ide_plug_device(drive); } }