?? aha152x.c
字號:
return 0; SETPORT( DMACNTRL1, 0 ); /* reset stack pointer */ for(i=0; i<16; i++) SETPORT( STACK, i ); SETPORT( DMACNTRL1, 0 ); /* reset stack pointer */ for(i=0; i<16 && GETPORT(STACK)==i; i++) ; return(i==16);}int aha152x_detect(int hostno){ int i, j, ok; aha152x_config conf; struct sigaction sa; int interrupt_level; #if defined(DEBUG_RACE) enter_driver("detect");#endif printk("aha152x: Probing: "); if(setup_called) { printk("processing commandline: "); if(setup_called!=4) { printk("\naha152x: %s\n", setup_str ); printk("aha152x: usage: aha152x=<PORTBASE>,<IRQ>,<SCSI ID>,<RECONNECT>\n"); panic("aha152x panics in line %d", __LINE__); } port_base = setup_portbase; interrupt_level = setup_irq; this_host = setup_scsiid; can_disconnect = setup_reconnect; for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++) ; if(i==PORT_COUNT) { printk("unknown portbase 0x%03x\n", port_base); panic("aha152x panics in line %d", __LINE__); } if(!aha152x_porttest(port_base)) { printk("portbase 0x%03x fails probe\n", port_base); panic("aha152x panics in line %d", __LINE__); } i=0; while(ints[i] && (interrupt_level!=ints[i])) i++; if(!ints[i]) { printk("illegal IRQ %d\n", interrupt_level); panic("aha152x panics in line %d", __LINE__); } if( (this_host < 0) || (this_host > 7) ) { printk("illegal SCSI ID %d\n", this_host); panic("aha152x panics in line %d", __LINE__); } if( (can_disconnect < 0) || (can_disconnect > 1) ) { printk("reconnect %d should be 0 or 1\n", can_disconnect); panic("aha152x panics in line %d", __LINE__); } printk("ok, "); } else {#if !defined(SKIP_BIOSTEST) printk("BIOS test: "); 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) {#if defined(DEBUG_RACE) leave_driver("(1) detect");#endif printk("failed\n"); return 0; } printk("ok, ");#endif /* !SKIP_BIOSTEST */ #if !defined(PORTBASE) printk("porttest: "); for( i=0; i<PORT_COUNT && !aha152x_porttest(ports[i]); i++) ; if(i==PORT_COUNT) { printk("failed\n");#if defined(DEBUG_RACE) leave_driver("(2) detect");#endif return 0; } else port_base=ports[i]; printk("ok, ");#else port_base=PORTBASE;#endif /* !PORTBASE */#if defined(AUTOCONF) conf.cf_port = (GETPORT(PORTA)<<8) + GETPORT(PORTB); interrupt_level = ints[conf.cf_irq]; this_host = conf.cf_id; can_disconnect = conf.cf_tardisc; printk("auto configuration: ok, ");#endif /* AUTOCONF */#if defined(IRQ) interrupt_level = IRQ; #endif#if defined(SCSI_ID) this_host = SCSI_ID;#endif#if defined(RECONNECT) can_disconnect=RECONNECT;#endif } printk("detection complete\n"); sa.sa_handler = aha152x_intr; sa.sa_flags = SA_INTERRUPT; sa.sa_mask = 0; sa.sa_restorer = NULL; ok = irqaction( interrupt_level, &sa); if(ok<0) { if(ok == -EINVAL) { printk("aha152x: bad IRQ %d.\n", interrupt_level); printk(" Contact author.\n"); } else if( ok == -EBUSY) printk( "aha152x: IRQ %d already in use. Configure another.\n", interrupt_level); else { printk( "\naha152x: Unexpected error code on requesting IRQ %d.\n", interrupt_level); printk(" Contact author.\n"); } panic("aha152x: driver needs an IRQ.\n"); } SETPORT( SCSIID, this_host << 4 ); scsi_hosts[hostno].this_id=this_host; if(can_disconnect) scsi_hosts[hostno].can_queue=AHA152X_MAXQUEUE; /* RESET OUT */ SETBITS(SCSISEQ, SCSIRSTO ); do_pause(5); CLRBITS(SCSISEQ, SCSIRSTO ); do_pause(10); aha152x_reset(NULL); printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=enabled\n", port_base, interrupt_level, this_host, can_disconnect ? "enabled" : "disabled" ); snarf_region(port_base, TEST-SCSISEQ); /* Register */ /* not expecting any interrupts */ SETPORT(SIMODE0, 0); SETPORT(SIMODE1, 0);#if defined(DEBUG_RACE) leave_driver("(3) detect");#endif SETBITS( DMACNTRL0, INTEN); return 1;}/* * return the name of the thing */const char *aha152x_info(void){#if defined(DEBUG_RACE) enter_driver("info"); leave_driver("info");#else#if defined(DEBUG_INFO) printk("\naha152x: info()\n");#endif#endif return(aha152x_id);}/* * Queue a command and setup interrupts for a free bus. */int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){#if defined(DEBUG_RACE) enter_driver("queue");#else#if defined(DEBUG_QUEUE) printk("aha152x: queue(), ");#endif#endif#if defined(DEBUG_QUEUE) printk( "SCpnt (target = %d lun = %d cmnd = 0x%02x pieces = %d size = %u), ", SCpnt->target, SCpnt->lun, *(unsigned char *)SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen ); disp_ports();#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. */ cli(); commands++; if(commands==1) SETPORT( PORTA, 1 );#if defined(DEBUG_QUEUES) printk("i+ (%d), ", 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); } sti(); return 0;}/* * We only support command 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, int code ){ Scsi_Cmnd *ptr, *prev; cli();#if defined(DEBUG_ABORT) printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned long) SCpnt );#endif show_queues(); /* 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; sti(); ptr->host_scribble = NULL; ptr->result = (code ? code : DID_ABORT ) << 16; ptr->done(ptr); return 0; } /* Fail abortion, if we're on the bus */ if (current_SC) { sti(); return -1; } /* 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 && TESTLO(SSTAT1, BUSFREE) ) printk("bus busy but no current command, "); if(ptr && TESTHI(SSTAT1, BUSFREE) ) { /* dequeue */ if(prev) prev->host_scribble = ptr->host_scribble; else issue_SC = (Scsi_Cmnd *) ptr->host_scribble; /* 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, (this_host << OID_) | current_SC->target ); /* 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 ); abort_result=0; sti(); /* sleep until the abortion is complete */ sleep_on( &abortion_complete ); return abort_result; } else printk("aha152x: bus busy but no current command\n"); /* command wasn't found */ sti(); return 0;}/* * Restore default values to the AIC-6260 registers and reset the fifos */static void aha152x_reset_ports(void){ /* 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 */int aha152x_reset(Scsi_Cmnd * __unused){ Scsi_Cmnd *ptr; aha152x_reset_ports(); /* Reset, if bus hangs */ if( TESTLO( SSTAT1, BUSFREE ) ) { CLRBITS( DMACNTRL0, INTEN );#if defined( DEBUG_RESET ) printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");#endif show_queues(); if(current_SC) { current_SC->host_scribble = NULL; current_SC->result = DID_RESET << 16; current_SC->done(current_SC); current_SC=NULL; } while(disconnected_SC) { ptr = disconnected_SC; disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble; ptr->host_scribble = NULL; ptr->result = DID_RESET << 16; ptr->done(ptr); } /* RESET OUT */ SETPORT(SCSISEQ, SCSIRSTO); do_pause(5); SETPORT(SCSISEQ, 0); do_pause(10); SETPORT(SIMODE0, 0 ); SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -