📄 aha152x.c
字号:
setup[setup_count].debug = aha152x1[8];#endif if(aha152x_checksetup(&setup[setup_count])) setup_count++; else printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n", setup[setup_count].io_port, setup[setup_count].irq, setup[setup_count].scsiid, setup[setup_count].reconnect, setup[setup_count].parity, setup[setup_count].synchronous, setup[setup_count].delay, setup[setup_count].ext_trans); }#endif #if defined(AUTOCONF) if(setup_count<2) {#if !defined(SKIP_BIOSTEST) ok=0; for(i=0; i < ADDRESS_COUNT && !ok; i++) for(j=0; (j < SIGNATURE_COUNT) && !ok; j++) ok=!memcmp((void *) addresses[i]+signatures[j].sig_offset, (void *) signatures[j].signature, (int) signatures[j].sig_length); if(!ok && setup_count==0) return 0; printk("aha152x: BIOS test: passed, ");#else printk("aha152x: ");#endif /* !SKIP_BIOSTEST */ ok=0; for(i=0; i<PORT_COUNT && setup_count<2; i++) { if((setup_count==1) && (setup[0].io_port == ports[i])) continue; if(aha152x_porttest(ports[i])) { ok++; setup[setup_count].io_port = ports[i]; conf.cf_port = (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB); setup[setup_count].irq = IRQ_MIN + conf.cf_irq; setup[setup_count].scsiid = conf.cf_id; setup[setup_count].reconnect = conf.cf_tardisc; setup[setup_count].parity = !conf.cf_parity; setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */; setup[setup_count].delay = DELAY_DEFAULT; setup[setup_count].ext_trans = 0;#ifdef DEBUG_AHA152X setup[setup_count].debug = DEBUG_DEFAULT;#endif setup_count++; } } if(ok) printk("auto configuration: ok, "); }#endif printk("detected %d controller(s)\n", setup_count); for(i=0; i<setup_count; i++) { struct Scsi_Host *shpnt; unsigned long int the_time; shpnt = aha152x_host[setup[i].irq-IRQ_MIN] = scsi_register(tpnt, sizeof(struct aha152x_hostdata)); shpnt->io_port = setup[i].io_port; shpnt->n_io_port = IO_RANGE; shpnt->irq = setup[i].irq; ISSUE_SC = (Scsi_Cmnd *) NULL; CURRENT_SC = (Scsi_Cmnd *) NULL; DISCONNECTED_SC = (Scsi_Cmnd *) NULL; HOSTDATA(shpnt)->reconnect = setup[i].reconnect; HOSTDATA(shpnt)->parity = setup[i].parity; HOSTDATA(shpnt)->synchronous = setup[i].synchronous; HOSTDATA(shpnt)->delay = setup[i].delay; HOSTDATA(shpnt)->ext_trans = setup[i].ext_trans;#ifdef DEBUG_AHA152X HOSTDATA(shpnt)->debug = setup[i].debug;#endif HOSTDATA(shpnt)->aborting = 0; HOSTDATA(shpnt)->abortion_complete = 0; HOSTDATA(shpnt)->abort_result = 0; HOSTDATA(shpnt)->commands = 0; HOSTDATA(shpnt)->message_len = 0; for(j=0; j<8; j++) HOSTDATA(shpnt)->syncrate[j] = 0; SETPORT(SCSIID, setup[i].scsiid << 4); shpnt->this_id=setup[i].scsiid; if(setup[i].reconnect) shpnt->can_queue=AHA152X_MAXQUEUE; /* RESET OUT */ SETBITS(SCSISEQ, SCSIRSTO); do_pause(30); CLRBITS(SCSISEQ, SCSIRSTO); do_pause(setup[i].delay); aha152x_reset_ports(shpnt); printk("aha152x%d: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d," " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n", i, shpnt->io_port, shpnt->irq, shpnt->this_id, HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled", HOSTDATA(shpnt)->parity ? "enabled" : "disabled", HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled", HOSTDATA(shpnt)->delay, HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled"); request_region(shpnt->io_port, IO_RANGE, "aha152x"); /* Register */ /* not expecting any interrupts */ SETPORT(SIMODE0, 0); SETPORT(SIMODE1, 0); SETBITS(DMACNTRL0, INTEN); ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", NULL); if(ok<0) { if(ok == -EINVAL) printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq); else if(ok == -EBUSY) printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq); else printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n", i, ok, shpnt->irq); printk("aha152x: driver needs an IRQ.\n"); scsi_unregister(shpnt); shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0; continue; } HOSTDATA(shpnt)->swint=0; printk("aha152x: trying software interrupt, "); SETBITS(DMACNTRL0, SWINT); the_time=jiffies+100; while(!HOSTDATA(shpnt)->swint && jiffies<the_time) barrier(); free_irq(shpnt->irq,0); if(!HOSTDATA(shpnt)->swint) { if(TESTHI(DMASTAT, INTSTAT)) { printk("lost.\n"); } else { printk("failed.\n"); } printk("aha152x: IRQ %d possibly wrong. Please verify.\n", shpnt->irq); scsi_unregister(shpnt); shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0; continue; } printk("ok.\n"); CLRBITS(DMACNTRL0, SWINT); /* clear interrupts */ SETPORT(SSTAT0, 0x7f); SETPORT(SSTAT1, 0xef); if(request_irq(shpnt->irq,aha152x_intr,SA_INTERRUPT,"aha152x",NULL)<0) { printk("aha152x: failed to reassign interrupt.\n"); } } return (setup_count>0);}/* * Queue a command and setup interrupts for a free bus. */int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){ struct Scsi_Host *shpnt = SCpnt->host; unsigned long flags;#if defined(DEBUG_RACE) enter_driver("queue");#else#if defined(DEBUG_QUEUE) if(HOSTDATA(shpnt)->debug & debug_queue) printk("aha152x: queue(), ");#endif#endif#if defined(DEBUG_QUEUE) if(HOSTDATA(shpnt)->debug & debug_queue) { printk("SCpnt (target = %d lun = %d cmnd = ", SCpnt->target, SCpnt->lun); print_command(SCpnt->cmnd); printk(", cmd_len=%d, pieces = %d size = %u), ", SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); disp_ports(shpnt); }#endif SCpnt->scsi_done = done; /* setup scratch area SCp.ptr : buffer pointer SCp.this_residual : buffer length SCp.buffer : next buffer SCp.buffers_residual : left buffers in list SCp.phase : current state of the command */ SCpnt->SCp.phase = not_issued; if (SCpnt->use_sg) { SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; SCpnt->SCp.ptr = SCpnt->SCp.buffer->address; SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; } else { SCpnt->SCp.ptr = (char *)SCpnt->request_buffer; SCpnt->SCp.this_residual = SCpnt->request_bufflen; SCpnt->SCp.buffer = NULL; SCpnt->SCp.buffers_residual = 0; } SCpnt->SCp.Status = CHECK_CONDITION; SCpnt->SCp.Message = 0; SCpnt->SCp.have_data_in = 0; SCpnt->SCp.sent_command = 0; /* Turn led on, when this is the first command. */ save_flags(flags); cli(); HOSTDATA(shpnt)->commands++; if(HOSTDATA(shpnt)->commands==1) SETPORT(PORTA, 1);#if defined(DEBUG_QUEUES) if(HOSTDATA(shpnt)->debug & debug_queues) printk("i+ (%d), ", HOSTDATA(shpnt)->commands);#endif append_SC(&ISSUE_SC, SCpnt); /* Enable bus free interrupt, when we aren't currently on the bus */ if(!CURRENT_SC) { SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); } restore_flags(flags);#if defined(DEBUG_RACE) leave_driver("queue");#endif return 0;}/* * We only support commands in interrupt-driven fashion */int aha152x_command(Scsi_Cmnd *SCpnt){ printk("aha152x: interrupt driven driver; use aha152x_queue()\n"); return -1;}/* * Abort a queued command * (commands that are on the bus can't be aborted easily) */int aha152x_abort(Scsi_Cmnd *SCpnt){ struct Scsi_Host *shpnt = SCpnt->host; unsigned long flags; Scsi_Cmnd *ptr, *prev; save_flags(flags); cli();#if defined(DEBUG_ABORT) if(HOSTDATA(shpnt)->debug & debug_abort) { printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt); show_queues(shpnt); }#endif /* look for command in issue queue */ for(ptr=ISSUE_SC, prev=NULL; ptr && ptr!=SCpnt; prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) ; if(ptr) { /* dequeue */ if(prev) prev->host_scribble = ptr->host_scribble; else ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble; HOSTDATA(shpnt)->commands--; restore_flags(flags); ptr->host_scribble = NULL; ptr->result = DID_ABORT << 16; ptr->scsi_done(ptr); return SCSI_ABORT_SUCCESS; } /* if the bus is busy or a command is currently processed, we can't do anything more */ if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt)) { /* fail abortion, if bus is busy */ if(!CURRENT_SC) printk("bus busy w/o current command, "); restore_flags(flags); return SCSI_ABORT_BUSY; } /* bus is free */ if(CURRENT_SC) { HOSTDATA(shpnt)->commands--; /* target entered bus free before COMMAND COMPLETE, nothing to abort */ restore_flags(flags); CURRENT_SC->result = DID_ERROR << 16; CURRENT_SC->scsi_done(CURRENT_SC); CURRENT_SC = (Scsi_Cmnd *) NULL; return SCSI_ABORT_SUCCESS; } /* look for command in disconnected queue */ for(ptr=DISCONNECTED_SC, prev=NULL; ptr && ptr!=SCpnt; prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) ; if(!ptr) { /* command wasn't found */ printk("command not found\n"); restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } if(!HOSTDATA(shpnt)->aborting) { /* dequeue */ if(prev) prev->host_scribble = ptr->host_scribble; else DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; HOSTDATA(shpnt)->commands--; /* set command current and initiate selection, let the interrupt routine take care of the abortion */ CURRENT_SC = ptr; ptr->SCp.phase = in_selection|aborted; SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); ADDMSG(ABORT); /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); SETPORT(SIMODE1, ENSELTIMO); /* Enable SELECTION OUT sequence */ SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); SETBITS(DMACNTRL0, INTEN); HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS; HOSTDATA(shpnt)->aborting++; HOSTDATA(shpnt)->abortion_complete=0; sti(); /* Hi Eric, guess what ;-) */ /* sleep until the abortion is complete */ while(!HOSTDATA(shpnt)->abortion_complete) barrier(); HOSTDATA(shpnt)->aborting=0; return HOSTDATA(shpnt)->abort_result; } else { /* we're already aborting a command */ restore_flags(flags); return SCSI_ABORT_BUSY; }}/* * Restore default values to the AIC-6260 registers and reset the fifos */static void aha152x_reset_ports(struct Scsi_Host *shpnt){ /* disable interrupts */ SETPORT(DMACNTRL0, RSTFIFO); SETPORT(SCSISEQ, 0); SETPORT(SXFRCTL1, 0); SETPORT(SCSISIG, 0); SETPORT(SCSIRATE, 0); /* clear all interrupt conditions */ SETPORT(SSTAT0, 0x7f); SETPORT(SSTAT1, 0xef); SETPORT(SSTAT4, SYNCERR|FWERR|FRERR); SETPORT(DMACNTRL0, 0); SETPORT(DMACNTRL1, 0); SETPORT(BRSTCNTRL, 0xf1); /* clear SCSI fifo and transfer count */ SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); SETPORT(SXFRCTL0, CH1); /* enable interrupts */ SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);}/* * Reset registers, reset a hanging bus and * kill active and disconnected commands for target w/o soft reset */int aha152x_reset(Scsi_Cmnd *SCpnt, unsigned int unused){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -