예제 #1
0
/**
 * 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", 8) == 0)

	retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, 
			      __pa(pdc_result), __pa(hwpath));

	if (retval < PDC_OK)
		goto fail;

	*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;
		case 80:  *period = 125; break;
		default: /* Do nothing */ break;
	}

	/* 
	 * pdc_result[2]	PDC suggested SCSI id
	 * pdc_result[3]	PDC suggested SCSI rate
	 */

	if (IS_SPROCKETS()) {
		/* 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]; 
	}

 fail:
	spin_unlock_irq(&pdc_lock);
	return (retval >= PDC_OK);
}
예제 #2
0
/**
 * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
 * @hwpath: fully bc.mod style path to the device.
 * @initiator: the array to return the result into
 *
 * 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, struct pdc_initiator *initiator)
{
	int retval;
	unsigned long flags;

	spin_lock_irqsave(&pdc_lock, flags);

/* 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", 8) == 0)

	retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, 
			      __pa(pdc_result), __pa(hwpath));
	if (retval < PDC_OK)
		goto out;

	if (pdc_result[0] < 16) {
		initiator->host_id = pdc_result[0];
	} else {
		initiator->host_id = -1;
	}

	/*
	 * Sprockets and Piranha return 20 or 40 (MT/s).  Prelude returns
	 * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively
	 */
	switch (pdc_result[1]) {
		case  1: initiator->factor = 50; break;
		case  2: initiator->factor = 25; break;
		case  5: initiator->factor = 12; break;
		case 25: initiator->factor = 10; break;
		case 20: initiator->factor = 12; break;
		case 40: initiator->factor = 10; break;
		default: initiator->factor = -1; break;
	}

	if (IS_SPROCKETS()) {
		initiator->width = pdc_result[4];
		initiator->mode = pdc_result[5];
	} else {
		initiator->width = -1;
		initiator->mode = -1;
	}

 out:
	spin_unlock_irqrestore(&pdc_lock, flags);

	return (retval >= PDC_OK);
}