📄 ncr53c406a.c
字号:
while (reqlen) { i = inb(PIO_STATUS); /* VDEB(printk("pio_status=%x\n", i)); */ if (i & 0x80) return 0; switch( i & 0x1e ) { default: case 0x10: len=0; break; case 0x0: len=1; break; case 0x8: len=42; break; case 0xc: len=84; break; case 0xe: len=128; break; } if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occurred */ return 0; } if (len) { if( len > reqlen ) len = reqlen; save_flags(flags); cli(); if( fast_pio && len > 3 ) { insl(PIO_FIFO,request,len>>2); request += len & 0xfc; reqlen -= len & 0xfc; } else { while(len--) { *request++ = inb(PIO_FIFO); reqlen--; } } restore_flags(flags); } } return 0;}static __inline__ int NCR53c406a_pio_write(unsigned char *request, unsigned int reqlen) { int i = 0; int len; /* current scsi fifo size */ unsigned long flags = 0; REG1; while (reqlen && !(i&0x40)) { i = inb(PIO_STATUS); /* VDEB(printk("pio_status=%x\n", i)); */ if (i & 0x80) /* error */ return 0; switch( i & 0x1e ) { case 0x10: len=128; break; case 0x0: len=84; break; case 0x8: len=42; break; case 0xc: len=1; break; default: case 0xe: len=0; break; } if (len) { if( len > reqlen ) len = reqlen; save_flags(flags); cli(); if( fast_pio && len > 3 ) { outsl(PIO_FIFO,request,len>>2); request += len & 0xfc; reqlen -= len & 0xfc; } else { while(len--) { outb(*request++, PIO_FIFO); reqlen--; } } restore_flags(flags); } } return 0;}#endif USE_PIO__initfunc(int NCR53c406a_detect(Scsi_Host_Template * tpnt)){ struct Scsi_Host *shpnt;#ifndef PORT_BASE int i;#endif #if USE_BIOS int ii, jj; bios_base = 0; /* look for a valid signature */ for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++) for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset, (void *) signatures[jj].signature, (int) signatures[jj].sig_length)) bios_base=addresses[ii]; if(!bios_base){ printk("NCR53c406a: BIOS signature not found\n"); return 0; } DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base););#endif USE_BIOS #ifdef PORT_BASE if (check_region(port_base, 0x10)) /* ports already snatched */ port_base = 0; #else /* autodetect */ if (port_base) { /* LILO override */ if (check_region(port_base, 0x10)) port_base = 0; } else { for(i=0; i<PORT_COUNT && !port_base; i++){ if(check_region(ports[i], 0x10)){ DEB(printk("NCR53c406a: port %x in use\n", ports[i])); } else { VDEB(printk("NCR53c406a: port %x available\n", ports[i])); outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */ if( (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 && (inb(ports[i] + 0x0e) & 0xf8) == 0x58 ) { VDEB(printk("NCR53c406a: Sig register valid\n")); VDEB(printk("port_base=%x\n", port_base)); port_base = ports[i]; } } } }#endif PORT_BASE if(!port_base){ /* no ports found */ printk("NCR53c406a: no available ports found\n"); return 0; } DEB(printk("NCR53c406a detected\n")); calc_port_addr(); chip_init(); #ifndef IRQ_LEV if (irq_level < 0) { /* LILO override if >= 0*/ irq_level=irq_probe(); if (irq_level < 0) { /* Trouble */ printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); return 0; } }#endif DEB(printk("NCR53c406a: using port_base %x\n", port_base)); request_region(port_base, 0x10, "NCR53c406a"); if(irq_level > 0) { if(request_irq(irq_level, do_NCR53c406a_intr, 0, "NCR53c406a", NULL)){ printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); return 0; } tpnt->can_queue = 1; DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); } else if (irq_level == 0) { tpnt->can_queue = 0; DEB(printk("NCR53c406a: No interrupts detected\n"));#if USE_DMA printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); return 0;#endif USE_DMA } else { DEB(printk("NCR53c406a: Shouldn't get here!\n")); return 0; } #if USE_DMA dma_chan = DMA_CHAN; if(request_dma(dma_chan, "NCR53c406a") != 0){ printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); return 0; } DEB(printk("Allocated DMA channel %d\n", dma_chan));#endif USE_DMA tpnt->present = 1; tpnt->proc_dir = &proc_scsi_NCR53c406a; shpnt = scsi_register(tpnt, 0); shpnt->irq = irq_level; shpnt->io_port = port_base; shpnt->n_io_port = 0x10;#if USE_DMA shpnt->dma = dma_chan;#endif #if USE_DMA sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", port_base, irq_level, dma_chan);#else sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", port_base, irq_level, fast_pio ? "fast" : "slow");#endif return (tpnt->present);}/* called from init/main.c */__initfunc(void NCR53c406a_setup(char *str, int *ints)){ static size_t setup_idx = 0; size_t i; DEB(printk("NCR53c406a: Setup called\n");); if (setup_idx >= PORT_COUNT - 1) { printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); return; } if (ints[0] < 1 || ints[0] > 3) { printk("NCR53c406a: Malformed command line\n"); printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n"); return; } for (i = 0; i < PORT_COUNT && !port_base; i++) if (ports[i] == ints[1]) { port_base = ints[1]; DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);) } if (!port_base) { printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]); return; } if (ints[0] > 1) { if (ints[2] == 0) { irq_level = 0; DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);) } else for (i = 0; i < INTR_COUNT && irq_level < 0; i++) if (intrs[i] == ints[2]) { irq_level = ints[2]; DEB(printk("NCR53c406a: Specified irq %d\n", port_base);) } if (irq_level < 0) printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); } if (ints[0] > 2) fast_pio = ints[3]; DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);)}const char* NCR53c406a_info(struct Scsi_Host *SChost){ DEB(printk("NCR53c406a_info called\n")); return (info_msg);}static void internal_done(Scsi_Cmnd *SCpnt) { internal_done_errcode = SCpnt->result; ++internal_done_flag;}static void wait_intr() { int i = jiffies + WATCHDOG; while(time_after(i,jiffies) && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ barrier(); if (time_before_eq(i,jiffies)) { /* Timed out */ rtrc(0); current_SC->result = DID_TIME_OUT << 16; current_SC->SCp.phase = idle; current_SC->scsi_done(current_SC); return; } NCR53c406a_intr(0, NULL, NULL);}int NCR53c406a_command(Scsi_Cmnd *SCpnt){ DEB(printk("NCR53c406a_command called\n")); NCR53c406a_queue(SCpnt, internal_done); if(irq_level) while (!internal_done_flag); else /* interrupts not supported */ while (!internal_done_flag) wait_intr(); internal_done_flag = 0; return internal_done_errcode;}int NCR53c406a_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){ int i; unsigned long flags = 0; VDEB(printk("NCR53c406a_queue called\n")); DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen)); #if 0 VDEB(for(i=0; i<SCpnt->cmd_len; i++) printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); VDEB(printk("\n"));#endif current_SC = SCpnt; current_SC->scsi_done = done; current_SC->SCp.phase = command_ph; current_SC->SCp.Status = 0; current_SC->SCp.Message = 0; save_flags(flags); cli(); REG0; outb(SCpnt->target, DEST_ID); /* set destination */ outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ for(i=0; i<SCpnt->cmd_len; i++){ outb(SCpnt->cmnd[i], SCSI_FIFO); } outb(SELECT_NO_ATN, CMD_REG); restore_flags(flags); rtrc(1); return 0;}int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -