/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }