예제 #1
0
/**
* @brief 	Request service function.
* @param 	sd[in]: Card information.
* @param 	req[in]: Start sector.
* @return 	SUCCESS/ERROR_ID.
*/ 
static int gp_sdcard_xfer_request(gpSDInfo_t *sd, struct request *req)
{
	int ret = 1;

	while (ret) 
	{
		unsigned int ln;
		
		ln = blk_rq_map_sg(sd->queue, req, sd->sg);
		
		ret = gp_sdcard_transfer_scatter(sd, blk_rq_pos(req), sd->sg, ln, rq_data_dir(req));
		if(ret<0)
			goto out_error;
		/* ----- End of request ----- */
		spin_lock_irq(&sd->lock);
		ret = __blk_end_request(req, 0, ret<<9);
		spin_unlock_irq(&sd->lock);
	}
	return 1;
out_error:
	spin_lock_irq(&sd->lock);
	__blk_end_request_all(req, ret);;
	spin_unlock_irq(&sd->lock);
	return 0;
}
예제 #2
0
/**
* @brief 	SD read sector in app area. (only used for fast boot)
* @param 	sd_num[in]: SD device number.
* @param 	lba[in]: Sector address.
* @param 	sector_num[in]: Sector number.
* @param 	buf_addr[in]: Buffer address.
* @return 	SUCCESS/ERROR_ID.
*/
int gp_sdcard_app_read_sector(unsigned int sd_num, unsigned int lba, unsigned short sector_num, unsigned int buf_addr)
{
    gpSDInfo_t *sd;
    unsigned int app_start_sector;
    struct scatterlist sg;

    if (sd_num > 2)
    {
    	return -EINVAL;
    }

    sd = &sd_info[sd_num];
    app_start_sector = sd->partition.offset[MAX_SD_PART];

	sg_init_one(&sg, (char*)buf_addr, sector_num*512);

	if(gp_sdcard_transfer_scatter(sd, app_start_sector+lba, &sg, 1, 0)<0)
	{
		DEBUG("Read sector fail\n");
		return -EIO;
	}

    return 0;
}
예제 #3
0
/**
* @brief 	parse header,get the start sector of partition.
* @param 	sd[in]: Card information.
*/
static int gp_sdcard_parse_header(gpSDInfo_t * sd)
{
	struct scatterlist *sg;
	char *buf;
	unsigned int Tag1, Tag2;
	unsigned short part[8] = {292, 294, 300, 302, 52, 54, 60, 62};
	unsigned int mbr_offset = 0;
	unsigned int part_offset = 0;
	unsigned int RtCode;
	int ret = 0;
	int i=0;
	/* ----- Alloc buffer first ----- */
	buf = kmalloc(512, GFP_DMA);
	if(buf==NULL)
	{
		DERROR("No buf memory\n");
		return -ENOMEM;
	}
	/* ----- Alloc scatter list ----- */
	sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
	if(sg==NULL)
	{
		DERROR("No sg memory\n");
		ret = -ENOMEM;
		goto fail_mem;
	}
	sg_init_one(sg, buf, 512);
	/* ----- Read sector 0 to get table ----- */
	if(gp_sdcard_transfer_scatter(sd, 0, sg, 1, 0)<0)
	{
		DERROR("Read sector fail\n");
		ret = -EIO;
		goto fail_read;
	}
	Tag1 = *(unsigned int*)&buf[0];
	Tag2 = *(unsigned int*)&buf[0xc8];
	/* ----- GP MBR ----- */
	if( Tag2 == GP_TAG )
	{
		mbr_offset = *(unsigned short*)&buf[0xcc];
		part_offset = buf[0x1c9];
		part_offset = (part_offset<<8)|buf[0x1c8];
		part_offset = (part_offset<<8)|buf[0x1c7];
		part_offset = (part_offset<<8)|buf[0x1c6];
		/* ----- Read boot header ----- */
		if(gp_sdcard_transfer_scatter(sd, mbr_offset, sg, 1, 0)<0)
		{
			DERROR("Read sector fail\n");
			ret = -EIO;
			goto fail_read;
		}
	}
	/* ----- Sector 0 is boot header ----- */
	else if( Tag1 == GP_TAG )
	{
		goto decode_boot;
	}
	/* ----- No MBR ----- */
	else
		goto end;
decode_boot:

	if(buf[4] < 0x20 )  /* version 1.0 */
	{
    	RtCode = mbr_offset + *(unsigned short*)&buf[20];
    }
    else /* version 2.0 */
    {
    	RtCode = mbr_offset + *(unsigned int*)&buf[272];
    }
    /* ----- Get partition capacity ----- */
	for(i=0;i<MAX_SD_PART;i++)
		sd->partition.capacity[i]= *(unsigned short*)&buf[part[i]]*2048;		//Unit: 1MB
	/* ----- Read APP header ----- */
	if(gp_sdcard_transfer_scatter(sd, RtCode, sg, 1, 0)<0)
	{
		DERROR("Read sector fail\n");
		ret = -EIO;
		goto fail_read;
	}
	/* ----- Check APP header tag ----- */
	if(*(unsigned int*)&buf[0] != APP_TAG)
	{
		DERROR("APP header fail\n");
		ret = -EIO;
		goto end;
	}
	/* ----- Get Serial number ----- */
	sd->partition.sn = *(unsigned int*)&buf[16];
	/* ----- Get app area ----- */
	sd->partition.offset[MAX_SD_PART] = RtCode;
	sd->partition.capacity[MAX_SD_PART] = *(unsigned int*)&buf[8];
	/* ----- Get data area ----- */
	sd->partition.offset[0] = (part_offset)? part_offset : (RtCode + *(unsigned int*)&buf[8]);
	for(i=1;i<MAX_SD_PART;i++)
	{
		if(sd->partition.capacity[i]==0)
			continue;
		sd->partition.offset[i]= sd->partition.offset[i-1] + sd->partition.capacity[i-1];
		sd->partition.partition_num ++;
	}
	sd->partition.activity = 1;
	/* ----- For Old CodePacker Bug ----- */
	if(sd->partition.offset[MAX_SD_PART]&&(sd->partition.capacity[MAX_SD_PART]==0))
		sd->partition.capacity[MAX_SD_PART] = 0x10000 - sd->partition.offset[MAX_SD_PART];
	//for(i=0;i<MAX_SD_PART+1;i++)
	//	DEBUG("[%d] partition %d, start = 0x%x, capacity = 0x%x\n", sd->device_id, i, sd->partition.offset[i], sd->partition.capacity[i]);
end:
fail_read :
	kfree(sg);
fail_mem:
	kfree(buf);
	return ret;
}
예제 #4
0
/**
* @brief 	Request service function.
* @param 	sd[in]: Card information.
* @param 	req[in]: Start sector.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sdcard_xfer_request(gpSDInfo_t *sd, struct request *req)
{
	int ret = 1;

	while (ret)
	{
		unsigned int ln;
		unsigned int retry = 0;

		ln = blk_rq_map_sg(sd->queue, req, sd->sg);

#if 0	/* This is used for usb disk check */
		{
			bool do_sync = (rq_is_sync(req) && rq_data_dir(req) == WRITE);
			if (do_sync)
			{
				DEBUG("[Jerry] detect do write sync\n");
			}
		}
#endif
		while(1)
		{
			ret = gp_sdcard_transfer_scatter(sd, blk_rq_pos(req), sd->sg, ln, rq_data_dir(req));
			/* ----- Re-try procedure ----- */
			if(ret<0)
			{
				unsigned int cid[4];
				unsigned int capacity;
				if((retry>=SD_RETRY)||(gp_sdcard_ckinsert(sd)==0)||sd->fremove)
					goto out_error;
				/* ----- Re-initialize sd card ----- */
				memcpy(cid, sd->CID, sizeof(cid));
				capacity = sd->capacity;
				if(gp_sdcard_cardinit(sd)!=0)
				{
					DERROR("[%d]: Re-initialize fail\n",sd->device_id);
					goto out_error;
				}
				else if((cid[0]!=sd->CID[0])||(cid[1]!=sd->CID[1])||(cid[2]!=sd->CID[2])||(cid[3]!=sd->CID[3])||(capacity!=sd->capacity))
				{
					DERROR("[%d]: Different card insert\n",sd->device_id);
					goto out_error;
				}
				retry ++;
			}
			else
				break;
		}
		/* ----- End of request ----- */
		spin_lock_irq(&sd->lock);
		ret = __blk_end_request(req, 0, ret<<9);
		spin_unlock_irq(&sd->lock);
	}
	return 1;
out_error:
	spin_lock_irq(&sd->lock);
	DEBUG("[%d]: txrx fail %d\n", sd->device_id, ret);
	__blk_end_request_all(req, ret);;
	spin_unlock_irq(&sd->lock);
	return -ENXIO;
}