⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ahci.c

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	fis[12] = __ilog2(probe_ent->udma_mask + 1) + 0x40 - 0x01;	memcpy((unsigned char *)pp->cmd_tbl, fis, 20);	ahci_fill_cmd_slot(pp, cmd_fis_len);	writel(1, port_mmio + PORT_CMD_ISSUE);	readl(port_mmio + PORT_CMD_ISSUE);	if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 150, 0x1)) {		printf("set feature error!\n");	}}static int ahci_port_start(u8 port){	struct ahci_ioports *pp = &(probe_ent->port[port]);	volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;	u32 port_status;	u32 mem;	debug("Enter start port: %d\n", port);	port_status = readl(port_mmio + PORT_SCR_STAT);	debug("Port %d status: %x\n", port, port_status);	if ((port_status & 0xf) != 0x03) {		printf("No Link on this port!\n");		return -1;	}	mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);	if (!mem) {		free(pp);		printf("No mem for table!\n");		return -ENOMEM;	}	mem = (mem + 0x800) & (~0x7ff);	/* Aligned to 2048-bytes */	memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ);	/*	 * First item in chunk of DMA memory: 32-slot command table,	 * 32 bytes each in size	 */	pp->cmd_slot = (struct ahci_cmd_hdr *)mem;	debug("cmd_slot = 0x%x\n", pp->cmd_slot);	mem += (AHCI_CMD_SLOT_SZ + 224);	/*	 * Second item: Received-FIS area	 */	pp->rx_fis = mem;	mem += AHCI_RX_FIS_SZ;	/*	 * Third item: data area for storing a single command	 * and its scatter-gather table	 */	pp->cmd_tbl = mem;	debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);	mem += AHCI_CMD_TBL_HDR;	pp->cmd_tbl_sg = (struct ahci_sg *)mem;	writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR);	writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);	writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |			  PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |			  PORT_CMD_START, port_mmio + PORT_CMD);	debug("Exit start port %d\n", port);	return 0;}static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf,				int buf_len){	struct ahci_ioports *pp = &(probe_ent->port[port]);	volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;	u32 opts;	u32 port_status;	int sg_count;	debug("Enter get_ahci_device_data: for port %d\n", port);	if (port > probe_ent->n_ports) {		printf("Invaild port number %d\n", port);		return -1;	}	port_status = readl(port_mmio + PORT_SCR_STAT);	if ((port_status & 0xf) != 0x03) {		debug("No Link on port %d!\n", port);		return -1;	}	memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len);	sg_count = ahci_fill_sg(port, buf, buf_len);	opts = (fis_len >> 2) | (sg_count << 16);	ahci_fill_cmd_slot(pp, opts);	writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);	if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 150, 0x1)) {		printf("timeout exit!\n");		return -1;	}	debug("get_ahci_device_data: %d byte transferred.\n",	      pp->cmd_slot->status);	return 0;}static char *ata_id_strcpy(u16 *target, u16 *src, int len){	int i;	for (i = 0; i < len / 2; i++)		target[i] = le16_to_cpu(src[i]);	return (char *)target;}static void dump_ataid(hd_driveid_t *ataid){	debug("(49)ataid->capability = 0x%x\n", ataid->capability);	debug("(53)ataid->field_valid =0x%x\n", ataid->field_valid);	debug("(63)ataid->dma_mword = 0x%x\n", ataid->dma_mword);	debug("(64)ataid->eide_pio_modes = 0x%x\n", ataid->eide_pio_modes);	debug("(75)ataid->queue_depth = 0x%x\n", ataid->queue_depth);	debug("(80)ataid->major_rev_num = 0x%x\n", ataid->major_rev_num);	debug("(81)ataid->minor_rev_num = 0x%x\n", ataid->minor_rev_num);	debug("(82)ataid->command_set_1 = 0x%x\n", ataid->command_set_1);	debug("(83)ataid->command_set_2 = 0x%x\n", ataid->command_set_2);	debug("(84)ataid->cfsse = 0x%x\n", ataid->cfsse);	debug("(85)ataid->cfs_enable_1 = 0x%x\n", ataid->cfs_enable_1);	debug("(86)ataid->cfs_enable_2 = 0x%x\n", ataid->cfs_enable_2);	debug("(87)ataid->csf_default = 0x%x\n", ataid->csf_default);	debug("(88)ataid->dma_ultra = 0x%x\n", ataid->dma_ultra);	debug("(93)ataid->hw_config = 0x%x\n", ataid->hw_config);}/* * SCSI INQUIRY command operation. */static int ata_scsiop_inquiry(ccb *pccb){	u8 hdr[] = {		0,		0,		0x5,		/* claim SPC-3 version compatibility */		2,		95 - 4,	};	u8 fis[20];	u8 *tmpid;	u8 port;	/* Clean ccb data buffer */	memset(pccb->pdata, 0, pccb->datalen);	memcpy(pccb->pdata, hdr, sizeof(hdr));	if (pccb->datalen <= 35)		return 0;	memset(fis, 0, 20);	/* Construct the FIS */	fis[0] = 0x27;		/* Host to device FIS. */	fis[1] = 1 << 7;	/* Command FIS. */	fis[2] = ATA_CMD_IDENT;	/* Command byte. */	/* Read id from sata */	port = pccb->target;	if (!(tmpid = malloc(sizeof(hd_driveid_t))))		return -ENOMEM;	if (get_ahci_device_data(port, (u8 *) & fis, 20,				 tmpid, sizeof(hd_driveid_t))) {		debug("scsi_ahci: SCSI inquiry command failure.\n");		return -EIO;	}	if (ataid[port])		free(ataid[port]);	ataid[port] = (hd_driveid_t *) tmpid;	memcpy(&pccb->pdata[8], "ATA     ", 8);	ata_id_strcpy((u16 *) &pccb->pdata[16], (u16 *)ataid[port]->model, 16);	ata_id_strcpy((u16 *) &pccb->pdata[32], (u16 *)ataid[port]->fw_rev, 4);	dump_ataid(ataid[port]);	return 0;}/* * SCSI READ10 command operation. */static int ata_scsiop_read10(ccb * pccb){	u64 lba = 0;	u32 len = 0;	u8 fis[20];	lba = (((u64) pccb->cmd[2]) << 24) | (((u64) pccb->cmd[3]) << 16)	    | (((u64) pccb->cmd[4]) << 8) | ((u64) pccb->cmd[5]);	len = (((u32) pccb->cmd[7]) << 8) | ((u32) pccb->cmd[8]);	/* For 10-byte and 16-byte SCSI R/W commands, transfer	 * length 0 means transfer 0 block of data.	 * However, for ATA R/W commands, sector count 0 means	 * 256 or 65536 sectors, not 0 sectors as in SCSI.	 *	 * WARNING: one or two older ATA drives treat 0 as 0...	 */	if (!len)		return 0;	memset(fis, 0, 20);	/* Construct the FIS */	fis[0] = 0x27;		/* Host to device FIS. */	fis[1] = 1 << 7;	/* Command FIS. */	fis[2] = ATA_CMD_RD_DMA;	/* Command byte. */	/* LBA address, only support LBA28 in this driver */	fis[4] = pccb->cmd[5];	fis[5] = pccb->cmd[4];	fis[6] = pccb->cmd[3];	fis[7] = (pccb->cmd[2] & 0x0f) | 0xe0;	/* Sector Count */	fis[12] = pccb->cmd[8];	fis[13] = pccb->cmd[7];	/* Read from ahci */	if (get_ahci_device_data(pccb->target, (u8 *) & fis, 20,				 pccb->pdata, pccb->datalen)) {		debug("scsi_ahci: SCSI READ10 command failure.\n");		return -EIO;	}	return 0;}/* * SCSI READ CAPACITY10 command operation. */static int ata_scsiop_read_capacity10(ccb *pccb){	u8 buf[8];	if (!ataid[pccb->target]) {		printf("scsi_ahci: SCSI READ CAPACITY10 command failure. "		       "\tNo ATA info!\n"		       "\tPlease run SCSI commmand INQUIRY firstly!\n");		return -EPERM;	}	memset(buf, 0, 8);	*(u32 *) buf = le32_to_cpu(ataid[pccb->target]->lba_capacity);	buf[6] = 512 >> 8;	buf[7] = 512 & 0xff;	memcpy(pccb->pdata, buf, 8);	return 0;}/* * SCSI TEST UNIT READY command operation. */static int ata_scsiop_test_unit_ready(ccb *pccb){	return (ataid[pccb->target]) ? 0 : -EPERM;}int scsi_exec(ccb *pccb){	int ret;	switch (pccb->cmd[0]) {	case SCSI_READ10:		ret = ata_scsiop_read10(pccb);		break;	case SCSI_RD_CAPAC:		ret = ata_scsiop_read_capacity10(pccb);		break;	case SCSI_TST_U_RDY:		ret = ata_scsiop_test_unit_ready(pccb);		break;	case SCSI_INQUIRY:		ret = ata_scsiop_inquiry(pccb);		break;	default:		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);		return FALSE;	}	if (ret) {		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);		return FALSE;	}	return TRUE;}void scsi_low_level_init(int busdevfunc){	int i;	u32 linkmap;	ahci_init_one(busdevfunc);	linkmap = probe_ent->link_port_map;	for (i = 0; i < CFG_SCSI_MAX_SCSI_ID; i++) {		if (((linkmap >> i) & 0x01)) {			if (ahci_port_start((u8) i)) {				printf("Can not start port %d\n", i);				continue;			}			ahci_set_feature((u8) i);		}	}}void scsi_bus_reset(void){	/*Not implement*/}void scsi_print_error(ccb * pccb){	/*The ahci error info can be read in the ahci driver*/}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -