static int usb_stor_BBB_reset(struct us_data *us)
{
	int result;
	unsigned int pipe;

	/*
	 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
	 *
	 * For Reset Recovery the host shall issue in the following order:
	 * a) a Bulk-Only Mass Storage Reset
	 * b) a Clear Feature HALT to the Bulk-In endpoint
	 * c) a Clear Feature HALT to the Bulk-Out endpoint
	 *
	 * This is done in 3 steps.
	 *
	 * If the reset doesn't succeed, the device should be port reset.
	 *
	 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
	 */
	debug("BBB_reset\n");
	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
				 US_BBB_RESET,
				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
				 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);

	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
		debug("RESET:stall\n");
		return -1;
	}

	/* long wait for reset */
	_mdelay(150);
	debug("BBB_reset result %d: status %lX reset\n",
	      result, us->pusb_dev->status);
	pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
	result = usb_clear_halt(us->pusb_dev, pipe);
	/* long wait for reset */
	_mdelay(150);
	debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
	      result, us->pusb_dev->status);
	/* long wait for reset */
	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
	result = usb_clear_halt(us->pusb_dev, pipe);
	_mdelay(150);
	debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
	      result, us->pusb_dev->status);
	debug("BBB_reset done\n");
	return 0;
}
/* FIXME: this reset function doesn't really reset the port, and it
 * should. Actually it should probably do what it's doing here, and
 * reset the port physically
 */
static int usb_stor_CB_reset(struct us_data *us)
{
	unsigned char cmd[12];
	int result;

	debug("CB_reset\n");
	memset(cmd, 0xff, sizeof(cmd));
	cmd[0] = SCSI_SEND_DIAG;
	cmd[1] = 4;
	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
				 US_CBI_ADSC,
				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
				 0, us->ifnum, cmd, sizeof(cmd),
				 USB_CNTL_TIMEOUT * 5);

	/* long wait for reset */
	_mdelay(1500);
	debug("CB_reset result %d: status %lX clearing endpoint halt\n",
	      result, us->pusb_dev->status);
	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));

	debug("CB_reset done\n");
	return 0;
}
示例#3
0
文件: lib.c 项目: cyysu/AliOS-Things
void mdelay(uint32_t ms)
{
    if (ms == 0) {
        return;
    }

    while (ms--) {
        _mdelay();
    }
}
static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
{
	int timeout;

	us->ip_wanted = 1;
	submit_int_msg(us->pusb_dev, us->irqpipe,
			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
	timeout = 1000;
	while (timeout--) {
		if ((volatile int *)(unsigned long long)us->ip_wanted == NULL)
			break;
		_mdelay(10);
	}
	if (us->ip_wanted) {
		printf("	Did not get interrupt on CBI\n");
		us->ip_wanted = 0;
		return USB_STOR_TRANSPORT_ERROR;
	}
	debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
	      us->ip_data, us->pusb_dev->irq_act_len,
	      us->pusb_dev->irq_status);
	/* UFI gives us ASC and ASCQ, like a request sense */
	if (us->subclass == US_SC_UFI) {
		if (srb->cmd[0] == SCSI_REQ_SENSE ||
		    srb->cmd[0] == SCSI_INQUIRY)
			return USB_STOR_TRANSPORT_GOOD; /* Good */
		else if (us->ip_data)
			return USB_STOR_TRANSPORT_FAILED;
		else
			return USB_STOR_TRANSPORT_GOOD;
	}
	/* otherwise, we interpret the data normally */
	switch (us->ip_data) {
	case 0x0001:
		return USB_STOR_TRANSPORT_GOOD;
	case 0x0002:
		return USB_STOR_TRANSPORT_FAILED;
	default:
		return USB_STOR_TRANSPORT_ERROR;
	}			/* switch */
	return USB_STOR_TRANSPORT_ERROR;
}
示例#5
0
/**
 * Low level initialize the Octeon PCI controller
 *
 * @return
 */
static inline void octeon_pci_initialize(void)
{
	int64_t stat;
	octeon_pci_cfg01_t cfg01;
	octeon_npi_ctl_status_t ctl_status;
	octeon_pci_ctl_status_2_t ctl_status_2;
	octeon_pci_cfg19_t cfg19;
	octeon_pci_cfg16_t cfg16;
	octeon_pci_cfg22_t cfg22;
	octeon_pci_cfg56_t cfg56;

	/* Reset the PCI Bus */
	octeon_write_csr(OCTEON_CIU_SOFT_PRST, 0x1);
	stat = octeon_read_csr(OCTEON_CIU_SOFT_PRST);

	_mdelay(2);		/* Hold  PCI reset for 2 ms */

	ctl_status.u64 = 0;
	ctl_status.s.max_word = 1;
	ctl_status.s.timer = 1;
	octeon_write_csr(OCTEON_NPI_CTL_STATUS, ctl_status.u64);

	/* Deassert PCI reset and advertize PCX Host Mode Device Capability (64b) */
	octeon_write_csr(OCTEON_CIU_SOFT_PRST, 0x4);
	stat = octeon_read_csr(OCTEON_CIU_SOFT_PRST);

	_mdelay(2);		/* Wait 2 ms after deasserting PCI reset */

	ctl_status_2.u32 = 0;
	ctl_status_2.s.bar2pres = 1;   /* bar2 present */
	ctl_status_2.s.bar2_enb = 1;   /* bar2 enable  */
	ctl_status_2.s.tsr_hwm = 1;	/* Initializes to 0.  Must be set before any PCI reads. */
	npi_write32(OCTEON_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32);
	_mdelay(4);		/* Wait 2 ms before doing PCI reads */

	ctl_status_2.u32 = npi_read32(OCTEON_NPI_PCI_CTL_STATUS_2);
	printk("PCI Status: %s %s-bit\n",
	       ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI",
	       ctl_status_2.s.ap_64ad ? "64" : "32");

	/*
	 ** TDOMC must be set to one in PCI mode. TDOMC should be set to 4
	 ** in PCI-X mode to allow four oustanding splits. Otherwise,
	 ** should not change from its reset value. Don't write PCI_CFG19
	 ** in PCI mode (0x82000001 reset value), write it to 0x82000004
	 ** after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero.
	 ** MRBCM -> must be one.
	 */
	if (ctl_status_2.s.ap_pcix) {
		cfg19.u32 = 0;
		cfg19.s.tdomc = 4;	/* Target Delayed/Split request
					   outstanding maximum count. [1..31]
					   and 0=32.  NOTE: If the user
					   programs these bits beyond the
					   Designed Maximum outstanding count,
					   then the designed maximum table
					   depth will be used instead.  No
					   additional Deferred/Split
					   transactions will be accepted if
					   this outstanding maximum count is
					   reached. Furthermore, no additional
					   deferred/split transactions will be
					   accepted if the I/O delay/ I/O
					   Split Request outstanding maximum
					   is reached. */
		cfg19.s.mdrrmc = 2;	/* Master Deferred Read Request Outstanding Max
					   Count (PCI only).
					   CR4C[26:24]  Max SAC cycles   MAX DAC cycles
					   000              8                4
					   001              1                0
					   010              2                1
					   011              3                1
					   100              4                2
					   101              5                2
					   110              6                3
					   111              7                3
					   For example, if these bits are programmed to
					   100, the core can support 2 DAC cycles, 4 SAC
					   cycles or a combination of 1 DAC and 2 SAC cycles.
					   NOTE: For the PCI-X maximum outstanding split
					   transactions, refer to CRE0[22:20]  */

		cfg19.s.mrbcm = 1;	/* Master Request (Memory Read) Byte Count/Byte
					   Enable select.
					   0 = Byte Enables valid. In PCI mode, a burst
					   transaction cannot be performed using
					   Memory Read command=4?h6.
					   1 = DWORD Byte Count valid (default). In PCI
					   Mode, the memory read byte enables are
					   automatically generated by the core.
					   Note: N3 Master Request transaction sizes are
					   always determined through the
					   am_attr[<35:32>|<7:0>] field.  */
		npi_write32(OCTEON_NPI_PCI_CFG19, cfg19.u32);
	}

	cfg01.u32 = 0;
	cfg01.s.msae = 1;	/* Memory Space Access Enable */
	cfg01.s.me = 1;		/* Master Enable */
	cfg01.s.pee = 1;	/* PERR# Enable */
	cfg01.s.see = 1;	/* System Error Enable */
	cfg01.s.fbbe = 1;	/* Fast Back to Back Transaction Enable */

	npi_write32(OCTEON_NPI_PCI_CFG01, cfg01.u32);
	npi_read32(OCTEON_NPI_PCI_CFG01);

#ifdef USE_OCTEON_INTERNAL_ARBITER
	/*
	 ** When OCTEON is a PCI host, most systems will use OCTEON's
	 ** internal arbiter, so must enable it before any PCI/PCI-X
	 ** traffic can occur.
	 */
	{
		octeon_npi_pci_int_arb_cfg_t pci_int_arb_cfg;

		pci_int_arb_cfg.u64 = 0;
		pci_int_arb_cfg.s.en = 1;	/* Internal arbiter enable */
		octeon_write_csr(OCTEON_NPI_PCI_INT_ARB_CFG,
				 pci_int_arb_cfg.u64);
	}
#endif				/* USE_OCTEON_INTERNAL_ARBITER */

	/*
	 ** Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
	 ** TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to
	 ** 1..7.
	 */
	cfg16.u32 = 0;
	cfg16.s.mltd = 1;	/* Master Latency Timer Disable */
	npi_write32(OCTEON_NPI_PCI_CFG16, cfg16.u32);

	/*
	 ** Should be written to 0x4ff00. MTTV -> must be zero.
	 ** FLUSH -> must be 1. MRV -> should be 0xFF.
	 */
	cfg22.u32 = 0;
	cfg22.s.mrv = 0xff;	/* Master Retry Value [1..255] and 0=infinite */
	cfg22.s.flush = 1;	/* AM_DO_FLUSH_I control NOTE: This
				   bit MUST BE ONE for proper N3K
				   operation */
	npi_write32(OCTEON_NPI_PCI_CFG22, cfg22.u32);

	/*
	 ** MOST Indicates the maximum number of outstanding splits (in -1
	 ** notation) when OCTEON is in PCI-X mode.  PCI-X performance is
	 ** affected by the MOST selection.  Should generally be written
	 ** with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807,
	 ** depending on the desired MOST of 3, 2, 1, or 0, respectively.
	 */
	cfg56.u32 = 0;
	cfg56.s.pxcid = 7;	/* RO - PCI-X Capability ID */
	cfg56.s.ncp = 0xe8;	/* RO - Next Capability Pointer */
	cfg56.s.dpere = 1;	/* Data Parity Error Recovery Enable */
	cfg56.s.roe = 1;	/* Relaxed Ordering Enable */
	cfg56.s.mmbc = 1;	/* Maximum Memory Byte Count [0=512B,1=1024B,2=2048B,3=4096B] */
	cfg56.s.most = 3;	/* Maximum outstanding Split transactions [0=1 .. 7=32] */

	npi_write32(OCTEON_NPI_PCI_CFG56, cfg56.u32);

	/*
	 ** Affects PCI performance when OCTEON services reads to its
	 ** BAR1/BAR2. Refer to Section 10.6.1.  The recommended values are
	 ** 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and
	 ** PCI_READ_CMD_E, respectively. Note that these values differ
	 ** from their reset values.
	 */
	npi_write32(OCTEON_NPI_PCI_READ_CMD_6, 0x22);
	npi_write32(OCTEON_NPI_PCI_READ_CMD_C, 0x33);
	npi_write32(OCTEON_NPI_PCI_READ_CMD_E, 0x33);
}
static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
{
	int result, retry;
	int dir_in;
	int actlen, data_actlen;
	unsigned int pipe, pipein, pipeout;
	ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
#ifdef BBB_XPORT_TRACE
	unsigned char *ptr;
	int index;
#endif
	if (us->pusb_dev->connect_status == 0)
		return -1;
	dir_in = US_DIRECTION(srb->cmd[0]);

	/* COMMAND phase */
	debug("COMMAND phase\n");
	result = usb_stor_BBB_comdat(srb, us);
	if (result < 0) {
		debug("failed to send CBW status %ld\n",
		      us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
	if (!(us->flags & USB_READY))
		_mdelay(5);
	pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
	pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
	/* DATA phase + error handling */
	data_actlen = 0;
	/* no data, go immediately to the STATUS phase */
	if (srb->datalen == 0)
		goto st;
	debug("DATA phase\n");
	if (dir_in)
		pipe = pipein;
	else
		pipe = pipeout;
	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
			      &data_actlen, USB_CNTL_TIMEOUT * 5);
	/* special handling of STALL in DATA phase */
	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
		debug("DATA:stall\n");
		/* clear the STALL on the endpoint */
		result = usb_stor_BBB_clear_endpt_stall(us,
					dir_in ? us->ep_in : us->ep_out);
		if (result >= 0)
			/* continue on to STATUS phase */
			goto st;
	}
	if (result < 0) {
		debug("usb_bulk_msg error status %ld\n",
		      us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
#ifdef BBB_XPORT_TRACE
	for (index = 0; index < data_actlen; index++)
		printf("pdata[%d] %#x ", index, srb->pdata[index]);
	printf("\n");
#endif
	/* STATUS phase + error handling */
st:
	retry = 0;
again:
	debug("STATUS phase\n");
	result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
				&actlen, USB_CNTL_TIMEOUT*5);

	/* special handling of STALL in STATUS phase */
	if ((result < 0) && (retry < 1) &&
	    (us->pusb_dev->status & USB_ST_STALLED)) {
		debug("STATUS:stall\n");
		/* clear the STALL on the endpoint */
		result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
		if (result >= 0 && (retry++ < 1))
			/* do a retry */
			goto again;
	}
	if (result < 0) {
		debug("usb_bulk_msg error status %ld\n",
		      us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
#ifdef BBB_XPORT_TRACE
	ptr = (unsigned char *)csw;
	for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
		printf("ptr[%d] %#x ", index, ptr[index]);
	printf("\n");
#endif
	/* misuse pipe to get the residue */
	pipe = le32_to_cpu(csw->dCSWDataResidue);
	if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
		pipe = srb->datalen - data_actlen;
	if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
		debug("!CSWSIGNATURE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
		debug("!Tag\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
		debug(">PHASE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
		debug("=PHASE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (data_actlen > srb->datalen) {
		debug("transferred %dB instead of %ldB\n",
		      data_actlen, srb->datalen);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
		debug("FAILED\n");
		return USB_STOR_TRANSPORT_FAILED;
	}

	return result;
}