Messages in this thread Patch in this message |  | | Subject | [PATCH] 53c700 update for 2.4.10-ac3 | Date | Tue, 02 Oct 2001 21:44:45 -0500 | From | James Bottomley <> |
| |
This updates the driver to version 2.6. The main changes are:
- Updated README describing better how to use the chip driver. - Now uses coherent pci memory on parisc. - 64 bit i/o mapping support should be complete (for 64 bit parisc).
It's been tested on a variety of parisc and x86 microchannel hardware. Richard Hirst is still running the 64 bit version of the driver through its paces, but it seems OK so far.
James Bottomley
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 <linux/config.h> #include <linux/version.h> @@ -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<<reselection_id)) { resume_offset = hostdata->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<<SCp->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, <irq flags>, <driver name>, 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. |  |