📄 ncr53c406a.c
字号:
NCR53c406a_abort(Scsi_Cmnd *SCpnt){ DEB(printk("NCR53c406a_abort called\n")); return SCSI_ABORT_SNOOZE; /* Don't know how to abort */}int NCR53c406a_reset(Scsi_Cmnd *SCpnt, unsigned int ignored){ DEB(printk("NCR53c406a_reset called\n")); outb(C4_IMG, CONFIG4); /* Select reg set 0 */ outb(CHIP_RESET, CMD_REG); outb(SCSI_NOP, CMD_REG); /* required after reset */ outb(SCSI_RESET, CMD_REG); chip_init(); rtrc(2); if (irq_level) return SCSI_RESET_PENDING; /* should get an interrupt */ else return SCSI_RESET_WAKEUP; /* won't get any interrupts */}int NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){ int size; DEB(printk("NCR53c406a_biosparm called\n")); size = disk->capacity; info_array[0] = 64; /* heads */ info_array[1] = 32; /* sectors */ info_array[2] = size>>11; /* cylinders */ if (info_array[2] > 1024) { /* big disk */ info_array[0] = 255; info_array[1] = 63; info_array[2] = size / (255*63); } return 0; } static voiddo_NCR53c406a_intr(int unused, void *dev_id, struct pt_regs *regs){ unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); NCR53c406a_intr(0, dev_id, regs); spin_unlock_irqrestore(&io_request_lock, flags);} static voidNCR53c406a_intr(int unused, void *dev_id, struct pt_regs *regs){ DEB(unsigned char fifo_size;) DEB(unsigned char seq_reg;) unsigned char status, int_reg; unsigned long flags = 0;#if USE_PIO unsigned char pio_status; struct scatterlist *sglist; unsigned int sgcount;#endif VDEB(printk("NCR53c406a_intr called\n")); save_flags(flags); cli();#if USE_PIO REG1; pio_status = inb(PIO_STATUS);#endif REG0; status = inb(STAT_REG); DEB(seq_reg = inb(SEQ_REG)); int_reg = inb(INT_REG); DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); restore_flags(flags); #if NCR53C406A_DEBUG printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", status, seq_reg, int_reg, fifo_size);#if (USE_DMA) printk("\n");#else printk(", pio=%02x\n", pio_status);#endif USE_DMA#endif NCR53C406A_DEBUG if(int_reg & 0x80){ /* SCSI reset intr */ rtrc(3); DEB(printk("NCR53c406a: reset intr received\n")); current_SC->SCp.phase = idle; current_SC->result = DID_RESET << 16; current_SC->scsi_done(current_SC); return; } #if USE_PIO if(pio_status & 0x80) { printk("NCR53C406A: Warning: PIO error!\n"); current_SC->SCp.phase = idle; current_SC->result = DID_ERROR << 16; current_SC->scsi_done(current_SC); return; }#endif USE_PIO if(status & 0x20) { /* Parity error */ printk("NCR53c406a: Warning: parity error!\n"); current_SC->SCp.phase = idle; current_SC->result = DID_PARITY << 16; current_SC->scsi_done(current_SC); return; } if(status & 0x40) { /* Gross error */ printk("NCR53c406a: Warning: gross error!\n"); current_SC->SCp.phase = idle; current_SC->result = DID_ERROR << 16; current_SC->scsi_done(current_SC); return; } if(int_reg & 0x20){ /* Disconnect */ DEB(printk("NCR53c406a: disconnect intr received\n")); if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */ current_SC->result = DID_NO_CONNECT << 16; } else{ /* Command complete, return status and message */ current_SC->result = (current_SC->SCp.Status & 0xff) | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); } rtrc(0); current_SC->SCp.phase = idle; current_SC->scsi_done( current_SC ); return; } switch(status & 0x07){ /* scsi phase */ case 0x00: /* DATA-OUT */ if(int_reg & 0x10){ /* Target requesting info transfer */ rtrc(5); current_SC->SCp.phase = data_out; VDEB(printk("NCR53c406a: Data-Out phase\n")); outb(FLUSH_FIFO, CMD_REG); LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */#if USE_DMA /* No s/g support for DMA */ NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen);#endif USE_DMA outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO if (!current_SC->use_sg) /* Don't use scatter-gather */ NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen); else { /* use scatter-gather */ sgcount = current_SC->use_sg; sglist = current_SC->request_buffer; while( sgcount-- ) { NCR53c406a_pio_write(sglist->address, sglist->length); sglist++; } } REG0;#endif USE_PIO } break; case 0x01: /* DATA-IN */ if(int_reg & 0x10){ /* Target requesting info transfer */ rtrc(6); current_SC->SCp.phase = data_in; VDEB(printk("NCR53c406a: Data-In phase\n")); outb(FLUSH_FIFO, CMD_REG); LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */#if USE_DMA /* No s/g support for DMA */ NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen);#endif USE_DMA outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO if (!current_SC->use_sg) /* Don't use scatter-gather */ NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen); else { /* Use scatter-gather */ sgcount = current_SC->use_sg; sglist = current_SC->request_buffer; while( sgcount-- ) { NCR53c406a_pio_read(sglist->address, sglist->length); sglist++; } } REG0;#endif USE_PIO } break; case 0x02: /* COMMAND */ current_SC->SCp.phase = command_ph; printk("NCR53c406a: Warning: Unknown interrupt occurred in command phase!\n"); break; case 0x03: /* STATUS */ rtrc(7); current_SC->SCp.phase = status_ph; VDEB(printk("NCR53c406a: Status phase\n")); outb(FLUSH_FIFO, CMD_REG); outb(INIT_CMD_COMPLETE, CMD_REG); break; case 0x04: /* Reserved */ case 0x05: /* Reserved */ printk("NCR53c406a: WARNING: Reserved phase!!!\n"); break; case 0x06: /* MESSAGE-OUT */ DEB(printk("NCR53c406a: Message-Out phase\n")); current_SC->SCp.phase = message_out; outb(SET_ATN, CMD_REG); /* Reject the message */ outb(MSG_ACCEPT, CMD_REG); break; case 0x07: /* MESSAGE-IN */ rtrc(4); VDEB(printk("NCR53c406a: Message-In phase\n")); current_SC->SCp.phase = message_in; current_SC->SCp.Status = inb(SCSI_FIFO); current_SC->SCp.Message = inb(SCSI_FIFO); VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); DEB(printk("Status = %02x Message = %02x\n", current_SC->SCp.Status, current_SC->SCp.Message)); if(current_SC->SCp.Message == SAVE_POINTERS || current_SC->SCp.Message == DISCONNECT) { outb(SET_ATN, CMD_REG); /* Reject message */ DEB(printk("Discarding SAVE_POINTERS message\n")); } outb(MSG_ACCEPT, CMD_REG); break; }}#ifndef IRQ_LEVstatic int irq_probe(){ int irqs, irq; int i; inb(INT_REG); /* clear the interrupt register */ irqs = probe_irq_on(); /* Invalid command will cause an interrupt */ REG0; outb(0xff, CMD_REG); /* Wait for the interrupt to occur */ i = jiffies + WATCHDOG; while(time_after(i, jiffies) && !(inb(STAT_REG) & 0x80)) barrier(); if (time_before_eq(i, jiffies)) { /* Timed out, must be hardware trouble */ probe_irq_off(irqs); return -1; } irq = probe_irq_off(irqs); /* Kick the chip */ outb(CHIP_RESET, CMD_REG); outb(SCSI_NOP, CMD_REG); chip_init(); return irq;}#endif IRQ_LEVstatic void chip_init(){ REG1;#if USE_DMA outb(0x00, PIO_STATUS);#else /* USE_PIO */ outb(0x01, PIO_STATUS);#endif outb(0x00, PIO_FLAG); outb(C4_IMG, CONFIG4); /* REG0; */ outb(C3_IMG, CONFIG3); outb(C2_IMG, CONFIG2); outb(C1_IMG, CONFIG1); outb(0x05, CLKCONV); /* clock conversion factor */ outb(0x9C, SRTIMOUT); /* Selection timeout */ outb(0x05, SYNCPRD); /* Synchronous transfer period */ outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ }__initfunc(void calc_port_addr(void)){ /* Control Register Set 0 */ TC_LSB = (port_base+0x00); TC_MSB = (port_base+0x01); SCSI_FIFO = (port_base+0x02); CMD_REG = (port_base+0x03); STAT_REG = (port_base+0x04); DEST_ID = (port_base+0x04); INT_REG = (port_base+0x05); SRTIMOUT = (port_base+0x05); SEQ_REG = (port_base+0x06); SYNCPRD = (port_base+0x06); FIFO_FLAGS = (port_base+0x07); SYNCOFF = (port_base+0x07); CONFIG1 = (port_base+0x08); CLKCONV = (port_base+0x09); /* TESTREG = (port_base+0x0A); */ CONFIG2 = (port_base+0x0B); CONFIG3 = (port_base+0x0C); CONFIG4 = (port_base+0x0D); TC_HIGH = (port_base+0x0E); /* FIFO_BOTTOM = (port_base+0x0F); */ /* Control Register Set 1 */ /* JUMPER_SENSE = (port_base+0x00);*/ /* SRAM_PTR = (port_base+0x01);*/ /* SRAM_DATA = (port_base+0x02);*/ PIO_FIFO = (port_base+0x04); /* PIO_FIFO1 = (port_base+0x05);*/ /* PIO_FIFO2 = (port_base+0x06);*/ /* PIO_FIFO3 = (port_base+0x07);*/ PIO_STATUS = (port_base+0x08); /* ATA_CMD = (port_base+0x09);*/ /* ATA_ERR = (port_base+0x0A);*/ PIO_FLAG = (port_base+0x0B); CONFIG5 = (port_base+0x0D); /* SIGNATURE = (port_base+0x0E);*/ /* CONFIG6 = (port_base+0x0F);*/}#ifdef MODULE/* Eventually this will go into an include file, but this will be later */Scsi_Host_Template driver_template = NCR53c406a;#include "scsi_module.c"#endif/* * Overrides for Emacs so that we get a uniform tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -