Index: linux/2.4/Makefile diff -u linux/2.4/Makefile:1.1.1.30 linux/2.4/Makefile:1.1.1.30.2.1 --- linux/2.4/Makefile:1.1.1.30 Mon Oct 1 19:57:48 2001 +++ linux/2.4/Makefile Mon Oct 1 22:33:19 2001 @@ -211,7 +211,7 @@ drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \ drivers/scsi/aic7xxx/aicasm/y.tab.h \ drivers/scsi/aic7xxx/aicasm/aicasm \ - drivers/scsi/53c700-mem.c \ + drivers/scsi/53c700_d.h \ net/khttpd/make_times_h \ net/khttpd/times.h \ submenu* Index: linux/2.4/drivers/scsi/53c700.c diff -u linux/2.4/drivers/scsi/53c700.c:1.1.1.4 linux/2.4/drivers/scsi/53c700.c:1.1.1.4.2.2 --- linux/2.4/drivers/scsi/53c700.c:1.1.1.4 Tue Sep 25 18:58:28 2001 +++ linux/2.4/drivers/scsi/53c700.c Tue Oct 2 20:47:11 2001 @@ -51,6 +51,12 @@ /* CHANGELOG * + * Version 2.6 + * + * Following test of the 64 bit parisc kernel by Richard Hirst, + * several problems have now been corrected. Also adds support for + * consistent memory allocation. + * * Version 2.5 * * More Compatibility changes for 710 (now actually works). Enhanced @@ -90,7 +96,7 @@ * Initial modularisation from the D700. See NCR_D700.c for the rest of * the changelog. * */ -#define NCR_700_VERSION "2.5" +#define NCR_700_VERSION "2.6" #include #include @@ -217,18 +223,39 @@ NCR_700_detect(Scsi_Host_Template *tpnt, struct NCR_700_Host_Parameters *hostdata) { - dma_addr_t pScript, pSlots; + dma_addr_t pScript, pMemory, pSlots; + __u8 *memory; __u32 *script; struct Scsi_Host *host; static int banner = 0; int j; - /* This separation of pScript and script is not strictly - * necessay, but may be useful in architectures which can - * allocate consistent memory on which virt_to_bus will not - * work */ - script = kmalloc(sizeof(SCRIPT), GFP_KERNEL); - pScript = virt_to_bus(script); +#ifdef CONFIG_53C700_USE_CONSISTENT + memory = pci_alloc_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE, + &pMemory); + hostdata->consistent = 1; + if(memory == NULL ) { + printk(KERN_WARNING "53c700: consistent memory allocation failed\n"); +#endif + memory = kmalloc(TOTAL_MEM_SIZE, GFP_KERNEL); + if(memory == NULL) { + printk(KERN_ERR "53c700: Failed to allocate memory for driver, detatching\n"); + return NULL; + } + pMemory = pci_map_single(hostdata->pci_dev, memory, + TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL); +#ifdef CONFIG_53C700_USE_CONSISTENT + hostdata->consistent = 0; + } +#endif + script = (__u32 *)memory; + pScript = pMemory; + hostdata->msgin = memory + MSGIN_OFFSET; + hostdata->msgout = memory + MSGOUT_OFFSET; + hostdata->status = memory + STATUS_OFFSET; + hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); + + pSlots = pMemory + SLOTS_OFFSET; /* Fill in the missing routines from the host template */ tpnt->queuecommand = NCR_700_queuecommand; @@ -251,29 +278,6 @@ if((host = scsi_register(tpnt, 4)) == NULL) return NULL; - if(script == NULL) { - printk(KERN_ERR "53c700: Failed to allocate script, detatching\n"); - scsi_unregister(host); - return NULL; - } - - /* This separation of slots and pSlots may facilitate later - * migration to consistent memory on architectures which - * support it */ - hostdata->slots = kmalloc(sizeof(struct NCR_700_command_slot) - * NCR_700_COMMAND_SLOTS_PER_HOST, - GFP_KERNEL); - pSlots = virt_to_bus(hostdata->slots); - - hostdata->msgin = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL); - hostdata->msgout = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL); - hostdata->status = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL); - if(hostdata->slots == NULL || hostdata->msgin == NULL - || hostdata->msgout == NULL || hostdata->status==NULL) { - printk(KERN_ERR "53c700: Failed to allocate command slots or message buffers, detatching\n"); - scsi_unregister(host); - return NULL; - } memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { @@ -295,19 +299,17 @@ for(j = 0; j < PATCHES; j++) { script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); } - /* now patch up fixed addresses. - * NOTE: virt_to_bus may be wrong if consistent memory is used - * for these in the future */ + /* now patch up fixed addresses. */ script_patch_32(script, MessageLocation, - virt_to_bus(&hostdata->msgout[0])); + pScript + MSGOUT_OFFSET); script_patch_32(script, StatusAddress, - virt_to_bus(&hostdata->status[0])); + pScript + STATUS_OFFSET); script_patch_32(script, ReceiveMsgAddress, - virt_to_bus(&hostdata->msgin[0])); + pScript + MSGIN_OFFSET); hostdata->script = script; hostdata->pScript = pScript; - dma_cache_wback((unsigned long)script, sizeof(SCRIPT)); + NCR_700_dma_cache_wback((unsigned long)script, sizeof(SCRIPT)); hostdata->state = NCR_700_HOST_FREE; spin_lock_init(&hostdata->lock); hostdata->cmd = NULL; @@ -344,13 +346,18 @@ struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; - /* NOTE: these may be NULL if we weren't fully initialised before - * the scsi_unregister was called */ - kfree(hostdata->script); - kfree(hostdata->slots); - kfree(hostdata->msgin); - kfree(hostdata->msgout); - kfree(hostdata->status); +#ifdef CONFIG_53C700_USE_CONSISTENT + if(hostdata->consistent) { + pci_free_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE, + hostdata->script, hostdata->pScript); + } else { +#endif + pci_unmap_single(hostdata->pci_dev, hostdata->pScript, + TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL); + kfree(hostdata->script); +#ifdef CONFIG_53C700_USE_CONSISTENT + } +#endif return 1; } @@ -620,9 +627,27 @@ } return (offset & 0x0f) | (XFERP & 0x07)<<4; } - STATIC inline void +NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, + struct NCR_700_command_slot *slot) +{ + if(SCp->sc_data_direction != SCSI_DATA_NONE && + SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { + int pci_direction = scsi_to_pci_dma_dir(SCp->sc_data_direction); + if(SCp->use_sg) { + pci_unmap_sg(hostdata->pci_dev, SCp->buffer, + SCp->use_sg, pci_direction); + } else { + pci_unmap_single(hostdata->pci_dev, + slot->dma_handle, + SCp->request_bufflen, + pci_direction); + } + } +} + +STATIC inline void NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, int result) { @@ -632,31 +657,22 @@ if(SCp != NULL) { struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; - + + NCR_700_unmap(hostdata, SCp, slot); + pci_unmap_single(hostdata->pci_dev, slot->pCmd, + sizeof(SCp->cmnd), PCI_DMA_TODEVICE); if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); print_sense("53c700", SCp); + #endif + SCp->use_sg = SCp->cmnd[8]; if(result == 0) result = SCp->cmnd[7]; } - if(SCp->sc_data_direction != SCSI_DATA_NONE && - SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { - int pci_direction = scsi_to_pci_dma_dir(SCp->sc_data_direction); - if(SCp->use_sg) { - pci_unmap_sg(hostdata->pci_dev, SCp->buffer, - SCp->use_sg, pci_direction); - } else { - pci_unmap_single(hostdata->pci_dev, - slot->dma_handle, - SCp->request_bufflen, - pci_direction); - } - } - free_slot(slot, hostdata); SCp->host_scribble = NULL; @@ -850,7 +866,7 @@ printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n", host->host_no); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_wback((unsigned long)hostdata->msgout, 1); + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1); script_patch_16(hostdata->script, MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ @@ -862,7 +878,7 @@ printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", host->host_no, pun, lun); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_wback((unsigned long)hostdata->msgout, 1); + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1); script_patch_16(hostdata->script, MessageCount, 1); resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -876,7 +892,7 @@ printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_wback((unsigned long)hostdata->msgout, 1); + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1); script_patch_16(hostdata->script, MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ @@ -954,7 +970,7 @@ printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_wback((unsigned long)hostdata->msgout, 1); + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1); script_patch_16(hostdata->script, MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ @@ -964,7 +980,7 @@ } NCR_700_writel(temp, host, TEMP_REG); /* set us up to receive another message */ - dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); + NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); return resume_offset; } @@ -1002,10 +1018,15 @@ printk(" cmd %p has status %d, requesting sense\n", SCp, hostdata->status[0]); #endif - /* we can destroy the command here because the - * contingent allegiance condition will cause a - * retry which will re-copy the command from the - * saved data_cmnd */ + /* we can destroy the command here + * because the contingent allegiance + * condition will cause a retry which + * will re-copy the command from the + * saved data_cmnd. We also unmap any + * data associated with the command + * here */ + NCR_700_unmap(hostdata, SCp, slot); + SCp->cmnd[0] = REQUEST_SENSE; SCp->cmnd[1] = (SCp->lun & 0x7) << 5; SCp->cmnd[2] = 0; @@ -1013,21 +1034,29 @@ SCp->cmnd[4] = sizeof(SCp->sense_buffer); SCp->cmnd[5] = 0; SCp->cmd_len = 6; - /* Here's a quiet hack: the REQUEST_SENSE command is - * six bytes, so store a flag indicating that this - * was an internal sense request and the original - * status at the end of the command */ + /* Here's a quiet hack: the + * REQUEST_SENSE command is six bytes, + * so store a flag indicating that + * this was an internal sense request + * and the original status at the end + * of the command */ SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; SCp->cmnd[7] = hostdata->status[0]; + SCp->cmnd[8] = SCp->use_sg; + SCp->use_sg = 0; SCp->sc_data_direction = SCSI_DATA_READ; - dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len); + pci_dma_sync_single(hostdata->pci_dev, + slot->pCmd, + SCp->cmd_len, + PCI_DMA_TODEVICE); + slot->dma_handle = pci_map_single(hostdata->pci_dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), PCI_DMA_FROMDEVICE); slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); - slot->SG[0].pAddr = bS_to_host(virt_to_bus(SCp->sense_buffer)); + slot->SG[0].pAddr = bS_to_host(slot->dma_handle); slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); slot->SG[1].pAddr = 0; slot->resume_offset = hostdata->pScript; - dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2); - dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer)); + NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2); + NCR_700_dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer)); /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; @@ -1136,7 +1165,7 @@ /* re-patch for this command */ script_patch_32_abs(hostdata->script, CommandAddress, - virt_to_bus(slot->cmnd->cmnd)); + slot->pCmd); script_patch_16(hostdata->script, CommandCount, slot->cmnd->cmd_len); script_patch_32_abs(hostdata->script, SGScriptStartAddress, @@ -1149,13 +1178,13 @@ * should therefore always clear ACK */ NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), host, SXFER_REG); - dma_cache_inv((unsigned long)hostdata->msgin, + NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); - dma_cache_wback((unsigned long)hostdata->msgout, + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, MSG_ARRAY_SIZE); /* I'm just being paranoid here, the command should * already have been flushed from the cache */ - dma_cache_wback((unsigned long)slot->cmnd->cmnd, + NCR_700_dma_cache_wback((unsigned long)slot->cmnd->cmnd, slot->cmnd->cmd_len); @@ -1219,7 +1248,8 @@ hostdata->reselection_id = reselection_id; /* just in case we have a stale simple tag message, clear it */ hostdata->msgin[1] = 0; - dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); + NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin, + MSG_ARRAY_SIZE); if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; } else { @@ -1334,7 +1364,7 @@ hostdata->cmd = NULL; /* clear any stale simple tag message */ hostdata->msgin[1] = 0; - dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); + NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); if(id == 0xff) { /* Selected as target, Ignore */ @@ -1404,7 +1434,7 @@ * set up so we cannot take a selection interrupt */ hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, - SCp->lun); + SCp->lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ @@ -1437,7 +1467,7 @@ Device_ID, 1<target); script_patch_32_abs(hostdata->script, CommandAddress, - virt_to_bus(SCp->cmnd)); + slot->pCmd); script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); /* finally plumb the beginning of the SG list into the script * */ @@ -1448,10 +1478,10 @@ if(slot->resume_offset == 0) slot->resume_offset = hostdata->pScript; /* now perform all the writebacks and invalidates */ - dma_cache_wback((unsigned long)hostdata->msgout, count); - dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); - dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len); - dma_cache_inv((unsigned long)hostdata->status, 1); + NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, count); + NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE); + NCR_700_dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len); + NCR_700_dma_cache_inv((unsigned long)hostdata->status, 1); /* set the synchronous period/offset */ NCR_700_writeb(NCR_700_get_SXFER(SCp->device), @@ -1519,7 +1549,7 @@ DEBUG(("scsi%d: istat %02x sstat0 %02x dstat %02x dsp %04x[%08x] dsps 0x%x\n", host->host_no, istat, sstat0, dstat, - (dsp - (__u32)virt_to_bus(hostdata->script))/4, + (dsp - (__u32)(hostdata->pScript))/4, dsp, dsps)); if(SCp != NULL) { @@ -1632,7 +1662,7 @@ slot->SG[i].ins = bS_to_host(SCRIPT_NOP); slot->SG[i].pAddr = 0; } - dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); /* and pretend we disconnected after * the command phase */ resume_offset = hostdata->pScript + Ent_MsgInDuringData; @@ -1847,7 +1877,13 @@ #endif if(old != NULL && old->tag == SCp->device->current_tag) { - printk(KERN_WARNING "scsi%d (%d:%d) Tag clock back to current, queueing\n", SCp->host->host_no, SCp->target, SCp->lun); + /* On some badly starving drives, this can be + * a frequent occurance, so print the message + * only once */ + if(NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED)) { + printk(KERN_WARNING "scsi%d (%d:%d) Target is suffering from tag starvation.\n", SCp->host->host_no, SCp->target, SCp->lun); + NCR_700_set_flag(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED); + } return 1; } slot->tag = SCp->device->current_tag++; @@ -1900,6 +1936,18 @@ hostdata->ITL_Hash_back[hash] = slot; slot->ITL_back = NULL; + /* sanity check: some of the commands generated by the mid-layer + * have an eccentric idea of their sc_data_direction */ + if(!SCp->use_sg && !SCp->request_bufflen + && SCp->sc_data_direction != SCSI_DATA_NONE) { +#ifdef NCR_700_DEBUG + printk("53c700: Command"); + print_command(SCp->cmnd); + printk("Has wrong data direction %d\n", SCp->sc_data_direction); +#endif + SCp->sc_data_direction = SCSI_DATA_NONE; + } + switch (SCp->cmnd[0]) { case REQUEST_SENSE: /* clear the internal sense magic */ @@ -1965,12 +2013,14 @@ } slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); slot->SG[i].pAddr = 0; - dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); DEBUG((" SETTING %08lx to %x\n", - virt_to_bus(&slot->SG[i].ins), + (&slot->pSG[i].ins), slot->SG[i].ins)); } slot->resume_offset = 0; + slot->pCmd = pci_map_single(hostdata->pci_dev, SCp->cmnd, + sizeof(SCp->cmnd), PCI_DMA_TODEVICE); NCR_700_start_command(SCp); return 0; } Index: linux/2.4/drivers/scsi/53c700.h diff -u linux/2.4/drivers/scsi/53c700.h:1.1.1.3 linux/2.4/drivers/scsi/53c700.h:1.1.1.3.2.2 --- linux/2.4/drivers/scsi/53c700.h:1.1.1.3 Tue Sep 25 18:58:28 2001 +++ linux/2.4/drivers/scsi/53c700.h Tue Oct 2 20:47:11 2001 @@ -40,7 +40,25 @@ #error "Config.in must define either CONFIG_53C700_IO_MAPPED or CONFIG_53C700_MEM_MAPPED to use this scsi core." #endif +/* macros for consistent memory allocation */ +#ifdef CONFIG_53C700_USE_CONSISTENT +#define NCR_700_dma_cache_wback(mem, size) \ + if(!hostdata->consistent) \ + dma_cache_wback(mem, size) +#define NCR_700_dma_cache_inv(mem, size) \ + if(!hostdata->consistent) \ + dma_cache_inv(mem, size) +#define NCR_700_dma_cache_wback_inv(mem, size) \ + if(!hostdata->consistent) \ + dma_cache_wback_inv(mem, size) +#else +#define NCR_700_dma_cache_wback(mem, size) dma_cache_wback(mem,size) +#define NCR_700_dma_cache_inv(mem, size) dma_cache_inv(mem,size) +#define NCR_700_dma_cache_wback_inv(mem, size) dma_cache_wback_inv(mem,size) +#endif + + struct NCR_700_Host_Parameters; /* These are the externally used routines */ @@ -86,6 +104,7 @@ #define NCR_700_DEV_NEGOTIATED_SYNC (1<<16) #define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17) #define NCR_700_DEV_BEGIN_TAG_QUEUEING (1<<18) +#define NCR_700_DEV_TAG_STARVATION_WARNED (1<<19) static inline void NCR_700_set_SXFER(Scsi_Device *SDp, __u8 sxfer) @@ -174,6 +193,8 @@ __u16 tag; __u32 resume_offset; Scsi_Cmnd *cmnd; + /* The pci_mapped address of the actual command in cmnd */ + dma_addr_t pCmd; __u32 temp; /* if this command is a pci_single mapping, holds the dma address * for later unmapping in the done routine */ @@ -191,19 +212,22 @@ int clock; /* board clock speed in MHz */ __u32 base; /* the base for the port (copied to host) */ struct pci_dev *pci_dev; - __u8 dmode_extra; /* adjustable bus settings */ - __u8 differential:1; /* if we are differential */ + __u32 dmode_extra; /* adjustable bus settings */ + __u32 differential:1; /* if we are differential */ #ifdef CONFIG_53C700_LE_ON_BE /* This option is for HP only. Set it if your chip is wired for * little endian on this platform (which is big endian) */ - __u8 force_le_on_be:1; + __u32 force_le_on_be:1; #endif - __u8 chip710:1; /* set if really a 710 not 700 */ - __u8 burst_disable:1; /* set to 1 to disable 710 bursting */ + __u32 chip710:1; /* set if really a 710 not 700 */ + __u32 burst_disable:1; /* set to 1 to disable 710 bursting */ /* NOTHING BELOW HERE NEEDS ALTERING */ - __u8 fast:1; /* if we can alter the SCSI bus clock + __u32 fast:1; /* if we can alter the SCSI bus clock speed (so can negiotiate sync) */ +#ifdef CONFIG_53C700_USE_CONSISTENT + __u32 consistent:1; +#endif int sync_clock; /* The speed of the SYNC core */ @@ -216,15 +240,23 @@ spinlock_t lock; enum NCR_700_Host_State state; /* protected by state lock */ Scsi_Cmnd *cmd; - + /* Note: pScript contains the single consistent block of + * memory. All the msgin, msgout and status are allocated in + * this memory too (at separate cache lines). TOTAL_MEM_SIZE + * represents the total size of this area */ +#define MSG_ARRAY_SIZE 8 +#define MSGOUT_OFFSET (L1_CACHE_ALIGN(sizeof(SCRIPT))) __u8 *msgout; -#define MSG_ARRAY_SIZE 16 - __u8 tag_negotiated; - __u8 *status; +#define MSGIN_OFFSET (MSGOUT_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE)) __u8 *msgin; +#define STATUS_OFFSET (MSGIN_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE)) + __u8 *status; +#define SLOTS_OFFSET (STATUS_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE)) struct NCR_700_command_slot *slots; +#define TOTAL_MEM_SIZE (SLOTS_OFFSET + L1_CACHE_ALIGN(sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST)) int saved_slot_position; int command_slot_count; /* protected by state lock */ + __u8 tag_negotiated; __u8 rev; __u8 reselection_id; /* flags for the host */ Index: linux/2.4/drivers/scsi/Config.in diff -u linux/2.4/drivers/scsi/Config.in:1.1.1.19 linux/2.4/drivers/scsi/Config.in:1.1.1.19.2.2 --- linux/2.4/drivers/scsi/Config.in:1.1.1.19 Tue Sep 25 18:58:12 2001 +++ linux/2.4/drivers/scsi/Config.in Tue Oct 2 20:47:11 2001 @@ -122,10 +122,11 @@ fi fi if [ "$CONFIG_PARISC" = "y" ]; then - dep_tristate 'HP LASI SCSI support for 53c700' CONFIG_SCSI_LASI700 $CONFIG_SCSI + dep_tristate 'HP LASI SCSI support for 53c700/710' CONFIG_SCSI_LASI700 $CONFIG_SCSI if [ "$CONFIG_SCSI_LASI700" != "n" ]; then define_bool CONFIG_53C700_MEM_MAPPED y define_bool CONFIG_53C700_LE_ON_BE y + define_bool CONFIG_53C700_USE_CONSISTENT y fi fi dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI $CONFIG_PCI Index: linux/2.4/drivers/scsi/README.53c700 diff -u linux/2.4/drivers/scsi/README.53c700:1.1.1.1 linux/2.4/drivers/scsi/README.53c700:1.1.1.1.22.1 --- linux/2.4/drivers/scsi/README.53c700:1.1.1.1 Mon May 14 18:48:23 2001 +++ linux/2.4/drivers/scsi/README.53c700 Mon Oct 1 22:26:31 2001 @@ -1,17 +1,154 @@ -This driver supports the 53c700 and 53c700-66 chips only. It is full -featured and does sync (-66 only), disconnects and tag command -queueing. +General Description +=================== +This driver supports the 53c700 and 53c700-66 chips. It also supports +the 53c710 but only in 53c700 emulation mode. It is full featured and +does sync (-66 and 710 only), disconnects and tag command queueing. + Since the 53c700 must be interfaced to a bus, you need to wrapper the card detector around this driver. For an example, see the -NCR_D700.[ch] files. +NCR_D700.[ch] or lasi700.[ch] files. The comments in the 53c700.[ch] files tell you which parts you need to fill in to get the driver working. + + +Compile Time Flags +================== + +The driver may be either io mapped or memory mapped. This is +selectable by configuration flags: + +CONFIG_53C700_MEM_MAPPED + +define if the driver is memory mapped. + +CONFIG_53C700_IO_MAPPED + +define if the driver is to be io mapped. + +One or other of the above flags *must* be defined. + +Other flags are: + +CONFIG_53C700_LE_ON_BE + +define if the chipset must be supported in little endian mode on a big +endian architecture (used for the 700 on parisc). + +CONFIG_53C700_USE_CONSISTENT + +allocate consistent memory (should only be used if your architecture +has a mixture of consistent and inconsistent memory). Fully +consistent or fully inconsistent architectures should not define this. + + +Using the Chip Core Driver +========================== + +In order to plumb the 53c700 chip core driver into a working SCSI +driver, you need to know three things about the way the chip is wired +into your system (or expansion card). + +1. The clock speed of the SCSI core +2. The interrupt line used +3. The memory (or io space) location of the 53c700 registers. + +Optionally, you may also need to know other things, like how to read +the SCSI Id from the card bios or whether the chip is wired for +differential operation. + +Usually you can find items 2. and 3. from general spec. documents or +even by examining the configuration of a working driver under another +operating system. + +The clock speed is usually buried deep in the technical literature. +It is required because it is used to set up both the synchronous and +asynchronous dividers for the chip. As a general rule of thumb, +manufacturers set the clock speed at the lowest possible setting +consistent with the best operation of the chip (although some choose +to drive it off the CPU or bus clock rather than going to the expense +of an extra clock chip). The best operation clock speeds are: + +53c700 - 25MHz +53c700-66 - 50MHz +53c710 - 40Mhz + +Writing Your Glue Driver +======================== + +This will be a standard SCSI driver (I don't know of a good document +describing this, just copy from some other driver) with at least a +detect and release entry. + +In the detect routine, you need to allocate a struct +NCR_700_Host_Parameters sized memory area and clear it (so that the +default values for everything are 0). Then you must fill in the +parameters that matter to you (see below), plumb the NCR_700_intr +routine into the interrupt line and call NCR_700_detect with the host +template and the new parameters as arguments. You should also call +the relevant request_*_region function and place the register base +address into the `base' pointer of the host parameters. + +In the release routine, you must free the NCR_700_Host_Parameters that +you allocated, call the corresponding release_*_region and free the +interrupt. + +Handling Interrupts +------------------- + +In general, you should just plumb the card's interrupt line in with + +request_irq(irq, NCR_700_intr, , , host); + +where host is the return from the relevant NCR_700_detect() routine. + +You may also write your own interrupt handling routine which calls +NCR_700_intr() directly. However, you should only really do this if +you have a card with more than one chip on it and you can read a +register to tell which set of chips wants the interrupt. + +Settable NCR_700_Host_Parameters +-------------------------------- + +The following are a list of the user settable parameters: + +clock: (MANDATORY) + +Set to the clock speed of the chip in MHz. + +base: (MANDATORY) + +set to the base of the io or mem region for the register set. On 64 +bit architectures this is only 32 bits wide, so the registers must be +mapped into the low 32 bits of memory. + +pci_dev: (OPTIONAL) + +set to the PCI board device. Leave NULL for a non-pci board. This is +used for the pci_alloc_consistent() and pci_map_*() functions. + +dmode_extra: (OPTIONAL, 53c710 only) + +extra flags for the DMODE register. These are used to control bus +output pins on the 710. The settings should be a combination of +DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up +to the board designer. Usually it is safe to ignore this setting. + +differential: (OPTIONAL) + +set to 1 if the chip drives a differential bus. + +force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set) + +set to 1 if the chip is operating in little endian mode on a big +endian architecture. + +chip710: (OPTIONAL) + +set to 1 if the chip is a 53c710. + +burst_disable: (OPTIONAL, 53c710 only) -The driver is currently I/O mapped only, but it should be easy enough -to memory map (just make the port reads #defines with MEM_MAPPED for -memory mapping or nothing for I/O mapping, specify an extra rule for -53c700-mem.o with the -DMEM_MAPPED flag and make your driver use it, -that way the make rules will generate the correct version). +disable 8 byte bursting for DMA transfers.