[parisc-linux-cvs] Re: 2.4.17-pa17 PDC_INITIATOR support
Grant Grundler
grundler@dsl2.external.hp.com
Wed, 30 Jan 2002 01:18:07 -0700
Grant Grundler wrote:
> Log message:
> 2.4.17-pa17 PDC_INITIATOR support
> Enables use of 50-pin SE port on C3000 and similar machines.
> WARNING: If you have a disk attached to the 50-pin SE port, the
> disk numbering will change! (hint: fixup /etc/fstab first)
> At least on the C3000, scsi0 is the SE SCSI port.
Index: Makefile
===================================================================
RCS file: /var/cvs/linux/Makefile,v
retrieving revision 1.254
diff -u -p -r1.254 Makefile
--- Makefile 2002/01/28 22:58:39 1.254
+++ Makefile 2002/01/30 08:01:50
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 17
-EXTRAVERSION = -pa16
+EXTRAVERSION = -pa17
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
Index: include/asm-parisc/hardware.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/hardware.h,v
retrieving revision 1.33
diff -u -p -r1.33 hardware.h
--- include/asm-parisc/hardware.h 2002/01/28 22:56:04 1.33
+++ include/asm-parisc/hardware.h 2002/01/30 08:01:51
@@ -147,6 +147,8 @@ extern void print_subdevices(struct pari
extern void print_parisc_devices(void);
extern char *print_pa_hwpath(struct parisc_device *dev, char *path);
extern char *print_pci_hwpath(struct pci_dev *dev, char *path);
+extern void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path);
+
/* inventory.c: */
extern void do_memory_inventory(void);
Index: include/asm-parisc/pdc.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/pdc.h,v
retrieving revision 1.39
diff -u -p -r1.39 pdc.h
--- include/asm-parisc/pdc.h 2002/01/06 16:24:18 1.39
+++ include/asm-parisc/pdc.h 2002/01/30 08:01:52
@@ -147,8 +147,14 @@
#define PDC_PCI_GET_INT_TBL_SIZE 13
#define PDC_PCI_GET_INT_TBL 14
+/* Get SCSI Interface Card info: SDTR, SCSI ID, mode (SE vs LVD) */
+#define PDC_INITIATOR 163UL
+#define PDC_GET_INITIATOR 0UL
+#define PDC_SET_INITIATOR 1UL
+#define PDC_DELETE_INITIATOR 2UL
+#define PDC_RETURN_TABLE_SIZE 3UL
+#define PDC_RETURN_TABLE 4UL
-
/* constants for OS (NVM...) */
#define OS_ID_NONE 0
#define OS_ID_HPUX 1
@@ -804,6 +810,7 @@ int pdc_lan_station_id(char *lan_addr, u
int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa);
int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl);
+int pdc_get_initiator(struct hardware_path *hwpath, unsigned char *scsi_id, unsigned long *period, char *width, char *mode);
int pdc_tod_read(struct pdc_tod *tod);
int pdc_tod_set(unsigned long sec, unsigned long usec);
Index: arch/parisc/kernel/firmware.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/firmware.c,v
retrieving revision 1.39
diff -u -p -r1.39 firmware.c
--- arch/parisc/kernel/firmware.c 2002/01/06 16:24:18 1.39
+++ arch/parisc/kernel/firmware.c 2002/01/30 08:01:52
@@ -45,10 +45,12 @@
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/page.h>
#include <asm/pdc.h>
#include <asm/system.h>
+#include <asm/processor.h> /* for boot_cpu_data */
#include <stdarg.h>
@@ -478,7 +480,84 @@ int pdc_lan_station_id(char *lan_addr, u
return retval;
}
+
/**
+ * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
+ * @hwpath: fully bc.mod style path to the device.
+ * @scsi_id: what someone told firmware the ID should be.
+ * @period: time in cycles
+ * @width: 8 or 16-bit wide bus
+ * @mode: 0,1,2 -> SE,HVD,LVD signalling mode
+ *
+ * Get the SCSI operational parameters from PDC.
+ * Needed since HPUX never used BIOS or symbios card NVRAM.
+ * Most ncr/sym cards won't have an entry and just use whatever
+ * capabilities of the card are (eg Ultra, LVD). But there are
+ * several cases where it's useful:
+ * o set SCSI id for Multi-initiator clusters,
+ * o cable too long (ie SE scsi 10Mhz won't support 6m length),
+ * o bus width exported is less than what the interface chip supports.
+ */
+int pdc_get_initiator( struct hardware_path *hwpath, unsigned char *scsi_id,
+ unsigned long *period, char *width, char *mode)
+{
+ int retval;
+
+ spin_lock_irq(&pdc_lock);
+
+/* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
+#define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
+ strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 9) == 0)
+
+ retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR,
+ __pa(pdc_result), __pa(hwpath));
+
+
+ if (retval >= PDC_OK) {
+ *scsi_id = (unsigned char) pdc_result[0];
+
+ /* convert Bus speed in Mhz to period (in 1/10 ns) */
+ switch(pdc_result[1]) {
+ /*
+ ** case 0: driver determines rate
+ ** case -1: Settings are uninitialized.
+ */
+ case 5: *period = 2000; break;
+ case 10: *period = 1000; break;
+ case 20: *period = 500; break;
+ case 40: *period = 250; break;
+ default: /* Do nothing */ break;
+ }
+
+ /*
+ ** pdc_result[2] PDC suggested SCSI id
+ ** pdc_result[3] PDC suggested SCSI rate
+ */
+
+ if (IS_SPROCKETS()) {
+ /*
+ ** Revisit: PAT PDC do the same thing?
+ ** A500 also exports 50-pin SE SCSI.
+ ** 0 == 8-bit
+ ** 1 == 16-bit
+ */
+ *width = (char) pdc_result[4];
+
+ /* ...in case someone needs it in the future.
+ ** sym53c8xx.c comments say it can't autodetect
+ ** for 825/825A/875 chips.
+ ** 0 == SE, 1 == HVD, 2 == LVD
+ */
+ *mode = (char) pdc_result[5];
+ }
+ }
+
+ spin_unlock_irq(&pdc_lock);
+ return retval >= PDC_OK;
+}
+
+
+/**
* pdc_pci_irt_size - Get the number of entries in the interrupt routing table.
* @num_entries: The return value.
* @hpa: The HPA for the device.
@@ -522,6 +601,7 @@ int pdc_pci_irt(unsigned long num_entrie
return retval;
}
+
/**
* pdc_tod_read - Read the Time-Of-Day clock.
Index: arch/parisc/kernel/parisc_ksyms.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/parisc_ksyms.c,v
retrieving revision 1.38
diff -u -p -r1.38 parisc_ksyms.c
--- arch/parisc/kernel/parisc_ksyms.c 2002/01/21 00:15:15 1.38
+++ arch/parisc/kernel/parisc_ksyms.c 2002/01/30 08:01:52
@@ -26,8 +26,10 @@ EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strstr);
#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+#include <asm/hardware.h> /* struct parisc_device for asm/pci.h */
#include <linux/pci.h>
EXPORT_SYMBOL(hppa_dma_ops);
+EXPORT_SYMBOL(get_pci_node_path);
#endif
#ifdef CONFIG_IOMMU_CCIO
@@ -146,6 +148,7 @@ EXPORT_SYMBOL(csum_partial_copy);
#include <asm/pdc.h>
EXPORT_SYMBOL(pdc_add_valid);
EXPORT_SYMBOL(pdc_lan_station_id);
+EXPORT_SYMBOL(pdc_get_initiator);
extern void $$divI(void);
extern void $$divU(void);
Index: drivers/scsi/sym53c8xx.c
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/sym53c8xx.c,v
retrieving revision 1.16
diff -u -p -r1.16 sym53c8xx.c
--- drivers/scsi/sym53c8xx.c 2002/01/03 22:37:18 1.16
+++ drivers/scsi/sym53c8xx.c 2002/01/30 08:01:59
@@ -4915,6 +4915,11 @@ static int __init ncr_prepare_setting(nc
u_long period;
int i;
+#ifdef CONFIG_PARISC
+ char scsi_mode = -1;
+ struct hardware_path hwpath;
+#endif
+
/*
** Wide ?
*/
@@ -4986,6 +4991,29 @@ static int __init ncr_prepare_setting(nc
*/
period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
+
+#if defined(CONFIG_PARISC)
+ /* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip
+ * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters
+ * to set the SCSI Initiator ID.
+ */
+ get_pci_node_path(np->pdev, &hwpath);
+ if (pdc_get_initiator(&hwpath, &np->myaddr, &period, &np->maxwide, &scsi_mode))
+ {
+ if (scsi_mode >= 0) {
+ /* C3000 PDC reports period/mode */
+ driver_setup.diff_support = 0;
+ switch(scsi_mode) {
+ case 0: np->scsi_mode = SMODE_SE; break;
+ case 1: np->scsi_mode = SMODE_HVD; break;
+ case 2: np->scsi_mode = SMODE_LVD; break;
+ default: break;
+ }
+ }
+ }
+#endif
+
if (period <= 250) np->minsync = 10;
else if (period <= 303) np->minsync = 11;
else if (period <= 500) np->minsync = 12;
@@ -5128,7 +5156,6 @@ static int __init ncr_prepare_setting(nc
np->rv_ctest4 |= MPEE; /* Master parity checking */
if (driver_setup.scsi_parity)
np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
-
#ifdef SCSI_NCR_NVRAM_SUPPORT
/*
** Get parity checking, host ID and verbose mode from NVRAM
@@ -5196,7 +5223,7 @@ static int __init ncr_prepare_setting(nc
if (np->sv_stest2 & 0x20)
np->scsi_mode = SMODE_HVD;
break;
- default:/* Don't care about HVD */
+ default: /* Don't care about HVD */
break;
}
}
@@ -5239,6 +5266,7 @@ static int __init ncr_prepare_setting(nc
tcb_p tp = &np->target[i];
tp->usrsync = 255;
+
#ifdef SCSI_NCR_NVRAM_SUPPORT
if (nvram) {
switch(nvram->type) {
@@ -5256,10 +5284,11 @@ static int __init ncr_prepare_setting(nc
if (driver_setup.use_nvram & 0x8)
tp->usrflag &= ~UF_NOSCAN;
}
- else {
+ else
#else
- if (1) {
+ if (1)
#endif
+ {
tp->usrsync = driver_setup.default_sync;
tp->usrwide = driver_setup.max_wide;
tp->usrtags = MAX_TAGS;
@@ -7074,7 +7103,11 @@ static int ncr_reset_scsi_bus(ncb_p np,
((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
+#ifdef CONFIG_PARISC
+ if (np->maxwide)
+#else
if (!(np->features & FE_WIDE))
+#endif
term &= 0x3ffff;
if (term != (2<<7)) {