static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp) { unsigned short csr = dregs->csr; dregs->csr &= ~CSR_DMA_ENABLE; #ifdef SUN3_SCSI_DEBUG printk("scsi_intr csr %x\n", csr); #endif if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { printk("scsi%d: bus error in dma\n", default_instance->host_no); #ifdef SUN3_SCSI_DEBUG printk("scsi: residual %x count %x addr %p dmaaddr %x\n", dregs->fifo_count, dregs->dma_count_lo | (dregs->dma_count_hi << 16), sun3_dma_orig_addr, dregs->dma_addr_lo | (dregs->dma_addr_hi << 16)); #endif } if(csr & CSR_DMA_CONFLICT) { printk("scsi%d: dma conflict\n", default_instance->host_no); } } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) NCR5380_intr(irq, dummy, fp); }
static irqreturn_t scsi_sun3_intr(int irq, void *dummy) { unsigned short csr = dregs->csr; int handled = 0; #ifdef SUN3_SCSI_VME dregs->csr &= ~CSR_DMA_ENABLE; #endif if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { printk("scsi%d: bus error in dma\n", default_instance->host_no); } if(csr & CSR_DMA_CONFLICT) { printk("scsi%d: dma conflict\n", default_instance->host_no); } handled = 1; } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { NCR5380_intr(irq, dummy); handled = 1; } return IRQ_RETVAL(handled); }
static irqreturn_t scsi_falcon_intr (int irq, void *dummy, struct pt_regs *fp) { #ifdef REAL_DMA int dma_stat; /* Turn off DMA and select sector counter register before * accessing the status register (Atari recommendation!) */ st_dma.dma_mode_status = 0x90; dma_stat = st_dma.dma_mode_status; /* Bit 0 indicates some error in the DMA process... don't know * what happened exactly (no further docu). */ if (!(dma_stat & 0x01)) { /* DMA error */ printk(KERN_CRIT "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR()); } /* If the DMA was active, but now bit 1 is not clear, it is some * other 5380 interrupt that finishes the DMA transfer. We have to * calculate the number of residual bytes and give a warning if * bytes are stuck in the ST-DMA fifo (there's no way to reach them!) */ if (atari_dma_active && (dma_stat & 0x02)) { unsigned long transferred; transferred = SCSI_DMA_GETADR() - atari_dma_startaddr; /* The ST-DMA address is incremented in 2-byte steps, but the * data are written only in 16-byte chunks. If the number of * transferred bytes is not divisible by 16, the remainder is * lost somewhere in outer space. */ if (transferred & 15) printk(KERN_ERR "SCSI DMA error: %ld bytes lost in " "ST-DMA fifo\n", transferred & 15); atari_dma_residual = HOSTDATA_DMALEN - transferred; DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", atari_dma_residual); } else atari_dma_residual = 0; atari_dma_active = 0; if (atari_dma_orig_addr) { /* If the dribble buffer was used on a read operation, copy the DMA-ed * data to the original destination address. */ memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr), HOSTDATA_DMALEN - atari_dma_residual); atari_dma_orig_addr = NULL; } #endif /* REAL_DMA */ NCR5380_intr (0, 0, 0); return IRQ_HANDLED; }
static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp) { unsigned short csr = dregs->csr; if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { printk("scsi%d: bus error in dma\n", default_instance->host_no); } if(csr & CSR_DMA_CONFLICT) { printk("scsi%d: dma conflict\n", default_instance->host_no); } } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) NCR5380_intr(irq, dummy, fp); }
static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp) { unsigned short csr = dregs->csr; int handled = 0; if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { printk("scsi%d: bus error in dma\n", default_instance->host_no); } if(csr & CSR_DMA_CONFLICT) { printk("scsi%d: dma conflict\n", default_instance->host_no); } handled = 1; } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { NCR5380_intr(irq, dummy, fp); handled = 1; } return IRQ_RETVAL(handled); }
static irqreturn_t scsi_sun3_intr(int irq, void *dummy) { unsigned short csr = dregs->csr; int handled = 0; if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { ; } if(csr & CSR_DMA_CONFLICT) { ; } handled = 1; } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { NCR5380_intr(irq, dummy); handled = 1; } return IRQ_RETVAL(handled); }
static irqreturn_t scsi_sun3_intr(int irq, void *dummy) { unsigned short csr = dregs->csr; int handled = 0; dregs->csr &= ~CSR_DMA_ENABLE; #ifdef SUN3_SCSI_DEBUG printk("scsi_intr csr %x\n", csr); #endif if(csr & ~CSR_GOOD) { if(csr & CSR_DMA_BUSERR) { printk("scsi%d: bus error in dma\n", default_instance->host_no); #ifdef SUN3_SCSI_DEBUG printk("scsi: residual %x count %x addr %p dmaaddr %x\n", dregs->fifo_count, dregs->dma_count_lo | (dregs->dma_count_hi << 16), sun3_dma_orig_addr, dregs->dma_addr_lo | (dregs->dma_addr_hi << 16)); #endif } if(csr & CSR_DMA_CONFLICT) { printk("scsi%d: dma conflict\n", default_instance->host_no); } handled = 1; } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { NCR5380_intr(irq, dummy); handled = 1; } return IRQ_RETVAL(handled); }
static irqreturn_t scsi_tt_intr (int irq, void *dummy, struct pt_regs *fp) { #ifdef REAL_DMA int dma_stat; dma_stat = tt_scsi_dma.dma_ctrl; INT_PRINTK("scsi%d: NCR5380 interrupt, DMA status = %02x\n", atari_scsi_host->host_no, dma_stat & 0xff); /* Look if it was the DMA that has interrupted: First possibility * is that a bus error occurred... */ if (dma_stat & 0x80) { if (!scsi_dma_is_ignored_buserr( dma_stat )) { printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", SCSI_DMA_READ_P(dma_addr)); printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); } } /* If the DMA is active but not finished, we have the case * that some other 5380 interrupt occurred within the DMA transfer. * This means we have residual bytes, if the desired end address * is not yet reached. Maybe we have to fetch some bytes from the * rest data register, too. The residual must be calculated from * the address pointer, not the counter register, because only the * addr reg counts bytes not yet written and pending in the rest * data reg! */ if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) - atari_dma_startaddr); DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", atari_dma_residual); if ((signed int)atari_dma_residual < 0) atari_dma_residual = 0; if ((dma_stat & 1) == 0) { /* After read operations, we maybe have to transport some rest bytes */ atari_scsi_fetch_restbytes(); } else { /* There seems to be a nasty bug in some SCSI-DMA/NCR combinations: If a target disconnects while a write operation is going on, the address register of the DMA may be a few bytes farer than it actually read. This is probably due to DMA prefetching and a delay between DMA and NCR. Experiments showed that the dma_addr is 9 bytes to high, but this could vary. The problem is, that the residual is thus calculated wrong and the next transfer will start behind where it should. So we round up the residual to the next multiple of a sector size, if it isn't already a multiple and the originally expected transfer size was. The latter condition is there to ensure that the correction is taken only for "real" data transfers and not for, e.g., the parameters of some other command. These shouldn't disconnect anyway. */ if (atari_dma_residual & 0x1ff) { DMA_PRINTK("SCSI DMA: DMA bug corrected, " "difference %ld bytes\n", 512 - (atari_dma_residual & 0x1ff)); atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff; } } tt_scsi_dma.dma_ctrl = 0; } /* If the DMA is finished, fetch the rest bytes and turn it off */ if (dma_stat & 0x40) { atari_dma_residual = 0; if ((dma_stat & 1) == 0) atari_scsi_fetch_restbytes(); tt_scsi_dma.dma_ctrl = 0; } #endif /* REAL_DMA */ NCR5380_intr (0, 0, 0); #if 0 /* To be sure the int is not masked */ atari_enable_irq( IRQ_TT_MFP_SCSI ); #endif return IRQ_HANDLED; }