📄 mac_ncr5380.c
字号:
}/* Mark the tag of command 'cmd' as free, or in case of an untagged command, * unlock the LUN. */static void cmd_free_tag( Scsi_Cmnd *cmd ){ SETUP_HOSTDATA(cmd->host); if (cmd->tag == TAG_NONE) { hostdata->busy[cmd->target] &= ~(1 << cmd->lun); TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n", H_NO(cmd), cmd->target, cmd->lun ); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag ); } else { TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; clear_bit( cmd->tag, &ta->allocated ); ta->nr_allocated--; TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n", H_NO(cmd), cmd->tag, cmd->target, cmd->lun ); }}static void free_all_tags( void ){ int target, lun; TAG_ALLOC *ta; if (!setup_use_tagged_queuing) return; for( target = 0; target < 8; ++target ) { for( lun = 0; lun < 8; ++lun ) { ta = &TagAlloc[target][lun]; memset( &ta->allocated, 0, MAX_TAGS/8 ); ta->nr_allocated = 0; } }}#endif /* SUPPORT_TAGS *//* * Function: void merge_contiguous_buffers( Scsi_Cmnd *cmd ) * * Purpose: Try to merge several scatter-gather requests into one DMA * transfer. This is possible if the scatter buffers lie on * physical contiguous addresses. * * Parameters: Scsi_Cmnd *cmd * The command to work on. The first scatter buffer's data are * assumed to be already transfered into ptr/this_residual. */static void merge_contiguous_buffers( Scsi_Cmnd *cmd ){ unsigned long endaddr;#if (NDEBUG & NDEBUG_MERGING) unsigned long oldlen = cmd->SCp.this_residual; int cnt = 1;#endif for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; cmd->SCp.buffers_residual && virt_to_phys(cmd->SCp.buffer[1].address) == endaddr; ) { MER_PRINTK("VTOP(%p) == %08lx -> merging\n", cmd->SCp.buffer[1].address, endaddr);#if (NDEBUG & NDEBUG_MERGING) ++cnt;#endif ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual += cmd->SCp.buffer->length; endaddr += cmd->SCp.buffer->length; }#if (NDEBUG & NDEBUG_MERGING) if (oldlen != cmd->SCp.this_residual) MER_PRINTK("merged %d buffers from %p, new length %08x\n", cnt, cmd->SCp.ptr, cmd->SCp.this_residual);#endif}/* * Function : void initialize_SCp(Scsi_Cmnd *cmd) * * Purpose : initialize the saved data pointers for cmd to point to the * start of the buffer. * * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. */static __inline__ void initialize_SCp(Scsi_Cmnd *cmd){ /* * Initialize the Scsi Pointer field so that all of the commands in the * various queues are valid. */ if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = (char *) cmd->SCp.buffer->address; cmd->SCp.this_residual = cmd->SCp.buffer->length; /* ++roman: Try to merge some scatter-buffers if they are at * contiguous physical addresses. */ merge_contiguous_buffers( cmd ); } else { cmd->SCp.buffer = NULL; cmd->SCp.buffers_residual = 0; cmd->SCp.ptr = (char *) cmd->request_buffer; cmd->SCp.this_residual = cmd->request_bufflen; }}#include <linux/config.h>#include <linux/delay.h>#if 1static struct { unsigned char mask; const char * name;} signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" }, { SR_SEL, "SEL" }, {0, NULL}}, basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"}, {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, {0, NULL}},mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"}, {MR_MONITOR_BSY, "MODE MONITOR BSY"}, {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, {0, NULL}};/* * Function : void NCR5380_print(struct Scsi_Host *instance) * * Purpose : print the SCSI bus signals for debugging purposes * * Input : instance - which NCR5380 */static void NCR5380_print(struct Scsi_Host *instance) { unsigned char status, data, basr, mr, icr, i; unsigned long flags; save_flags(flags); cli(); data = NCR5380_read(CURRENT_SCSI_DATA_REG); status = NCR5380_read(STATUS_REG); mr = NCR5380_read(MODE_REG); icr = NCR5380_read(INITIATOR_COMMAND_REG); basr = NCR5380_read(BUS_AND_STATUS_REG); restore_flags(flags); printk("STATUS_REG: %02x ", status); for (i = 0; signals[i].mask ; ++i) if (status & signals[i].mask) printk(",%s", signals[i].name); printk("\nBASR: %02x ", basr); for (i = 0; basrs[i].mask ; ++i) if (basr & basrs[i].mask) printk(",%s", basrs[i].name); printk("\nICR: %02x ", icr); for (i = 0; icrs[i].mask; ++i) if (icr & icrs[i].mask) printk(",%s", icrs[i].name); printk("\nMODE: %02x ", mr); for (i = 0; mrs[i].mask; ++i) if (mr & mrs[i].mask) printk(",%s", mrs[i].name); printk("\n");}static struct { unsigned char value; const char *name;} phases[] = { {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, {PHASE_UNKNOWN, "UNKNOWN"}};/* * Function : void NCR5380_print_phase(struct Scsi_Host *instance) * * Purpose : print the current SCSI phase for debugging purposes * * Input : instance - which NCR5380 */static void NCR5380_print_phase(struct Scsi_Host *instance){ unsigned char status; int i; status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); else { for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i); printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name); }}#else /* !NDEBUG *//* dummies... */__inline__ void NCR5380_print(struct Scsi_Host *instance) { };__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };#endif/* * ++roman: New scheme of calling NCR5380_main() * * If we're not in an interrupt, we can call our main directly, it cannot be * already running. Else, we queue it on a task queue, if not 'main_running' * tells us that a lower level is already executing it. This way, * 'main_running' needs not be protected in a special way. * * queue_main() is a utility function for putting our main onto the task * queue, if main_running is false. It should be called only from a * interrupt or bottom half. */#include <linux/tqueue.h>#include <linux/interrupt.h>static volatile int main_running = 0;static struct tq_struct NCR5380_tqueue = { NULL, /* next */ 0, /* sync */ (void (*)(void*))NCR5380_main, /* routine, must have (void *) arg... */ NULL /* data */};static __inline__ void queue_main(void){ if (!main_running) { /* If in interrupt and NCR5380_main() not already running, queue it on the 'immediate' task queue, to be processed immediately after the current interrupt processing has finished. */ queue_task(&NCR5380_tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); } /* else: nothing to do: the running NCR5380_main() will pick up any newly queued command. */}static void NCR5380_all_init (void){ static int done = 0; if (!done) { INI_PRINTK("scsi : NCR5380_all_init()\n"); done = 1; }} /* * Function : void NCR58380_print_options (struct Scsi_Host *instance) * * Purpose : called by probe code indicating the NCR5380 driver * options that were selected. * * Inputs : instance, pointer to this instance. Unused. */static void NCR5380_print_options (struct Scsi_Host *instance){ printk(" generic options"#ifdef AUTOSENSE " AUTOSENSE"#endif#ifdef REAL_DMA " REAL DMA"#endif#ifdef PSEUDO_DMA " PSEUDO DMA"#endif#ifdef PARITY " PARITY"#endif#ifdef SUPPORT_TAGS " SCSI-2 TAGGED QUEUING"#endif ); printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);}/* * Function : void NCR5380_print_status (struct Scsi_Host *instance) * * Purpose : print commands in the various queues, called from * NCR5380_abort and NCR5380_debug to aid debugging. * * Inputs : instance, pointer to this instance. */static void NCR5380_print_status (struct Scsi_Host *instance){ char *pr_bfr; char *start; int len; NCR_PRINT(NDEBUG_ANY); NCR_PRINT_PHASE(NDEBUG_ANY); pr_bfr = (char *) __get_free_page(GFP_ATOMIC); if (!pr_bfr) { printk("NCR5380_print_status: no memory for print buffer\n"); return; } len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0); pr_bfr[len] = 0; printk("\n%s\n", pr_bfr); free_page((unsigned long) pr_bfr);}/******************************************//* * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED] * * *buffer: I/O buffer * **start: if inout == FALSE pointer into buffer where user read should start * offset: current offset * length: length of buffer * hostno: Scsi_Host host_no * inout: TRUE - user is writing; FALSE - user is reading * * Return the number of bytes read from or written*/#undef SPRINTF#define SPRINTF(fmt,args...) \ do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \ pos += sprintf(pos, fmt , ## args); } while(0)staticchar *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);#ifndef NCR5380_proc_infostatic#endifint NCR5380_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout){ char *pos = buffer; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; Scsi_Cmnd *ptr; unsigned long flags; off_t begin = 0;#define check_offset() \ do { \ if (pos - buffer < offset - begin) { \ begin += pos - buffer; \ pos = buffer; \ } \ } while (0) for (instance = first_instance; instance && HOSTNO != hostno; instance = instance->next) ; if (!instance) return(-ESRCH); hostdata = (struct NCR5380_hostdata *)instance->hostdata; if (inout) { /* Has data been written to the file ? */ return(-ENOSYS); /* Currently this is a no-op */ } SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE); check_offset(); save_flags(flags); cli(); SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't"); check_offset(); if (!hostdata->connected) SPRINTF("scsi%d: no currently connected command\n", HOSTNO); else pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected, pos, buffer, length); SPRINTF("scsi%d: issue_queue\n", HOSTNO); check_offset(); for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) { pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); check_offset(); } SPRINTF("scsi%d: disconnected_queue\n", HOSTNO); check_offset(); for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = NEXT(ptr)) { pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); check_offset(); } restore_flags(flags); *start = buffer + (offset - begin); if (pos - buffer < offset - begin) return 0; else if (pos - buffer - (offset - begin) < length) return pos - buffer - (offset - begin); return length;}static char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -