--- c/ar6000/hif/hif2.c 2009-03-30 01:20:20.000000000 +0400 +++ d/ar6000//hif/hif2.c 2009-03-30 01:11:04.000000000 +0400 @@ -121,14 +121,10 @@ struct hif_request { struct list_head list; struct sdio_func *func; - int (*read)(struct sdio_func *func, - void *dst, unsigned int addr, int count); - int (*write)(struct sdio_func *func, - unsigned int addr, void *src, int count); void *buf; - unsigned long addr; - int len; - A_STATUS (*completion)(void *context, A_STATUS status); + u32 addr; + u32 len; + u32 flags; void *context; }; @@ -144,36 +140,90 @@ /* ----- Request processing ------------------------------------------------ */ -static A_STATUS process_request(struct hif_request *req) +static A_STATUS \ +process_request(struct sdio_func *func, A_UCHAR *buff, A_UINT32 addr, + A_UINT32 len, A_UINT32 flags) { - int ret; - A_STATUS status; + u32 blksz, blocks, arg; + struct hif_device *hif; + struct mmc_card *card; + struct mmc_host *host; + struct { + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + struct scatterlist sg; + } req; - dev_dbg(&req->func->dev, "process_request(req %p)\n", req); - sdio_claim_host(req->func); - if (req->read) { -#ifdef _GTA02_ - while (!s3c2410_gpio_getpin(S3C2410_GPE7)) { - printk(KERN_INFO "READ WHILE BUSY !\n"); - yield(); - } -#endif /* end _GTA02_ */ - ret = req->read(req->func, req->buf, req->addr, req->len); + /* + * Next code based on: 'mmc_io_rw_extended' (mmc/core/sdio_ops.c), + * but have shorten path and send small blocks not in byte mode. + */ + + memset(&req, 0, sizeof(req)); + + req.mrq.cmd = &req.cmd; + req.mrq.data = &req.data; + + req.cmd.opcode = SD_IO_RW_EXTENDED; + + arg = (flags & HIF_WRITE) ? 0x80000000 : 0x00000000; + arg |= (func->num << 28); + arg |= (flags & HIF_INCREMENTAL_ADDRESS) ? 0x04000000 : 0x00000000; + arg |= (addr << 9); + + if (flags & HIF_BYTE_BASIS) { + /* byte mode */ + blksz = len; + blocks = 1; + arg |= blksz; } else { + /* block mode */ + blksz = HIF_MBOX_BLOCK_SIZE; + blocks = len / HIF_MBOX_BLOCK_SIZE; + arg |= blocks | 0x08000000; + } + + req.cmd.arg = arg; + req.cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + req.data.blksz = blksz; + req.data.blocks = blocks; + req.data.flags = (flags & HIF_WRITE) ? MMC_DATA_WRITE : MMC_DATA_READ; + req.data.sg = &req.sg; + req.data.sg_len = 1; + + sg_init_one(&req.sg, buff, blksz * blocks); + + card = func->card; + host = card->host; + + mmc_set_data_timeout(&req.data, card); + + hif = sdio_get_drvdata(func); + + sdio_claim_host(func); + #ifdef _GTA02_ - while (!s3c2410_gpio_getpin(S3C2410_GPE7)) { - printk(KERN_INFO "WRITE WHILE BUSY !\n"); - yield(); - } + while (!s3c2410_gpio_getpin(S3C2410_GPE7)) { + printk(KERN_INFO "READ/WRITE WHILE BUSY !\n"); + yield(); #endif /* end _GTA02_ */ - ret = req->write(req->func, req->addr, req->buf, req->len); + + mmc_wait_for_req(host, &req.mrq); + + sdio_release_host(func); + + if ((req.cmd.error) || (req.data.error)) + return A_ERROR; + + if (!(mmc_host_is_spi(host))) { + if (req.cmd.resp[0] & (R5_ERROR|R5_FUNCTION_NUMBER|R5_OUT_OF_RANGE)) { + return A_ERROR; + } } - sdio_release_host(req->func); - status = ret ? A_ERROR : A_OK; - if (req->completion) - req->completion(req->context, status); - kfree(req); - return status; + + return A_OK; } @@ -254,7 +304,18 @@ } finish_wait(&hif->wait, &wait); - (void) process_request(req); + { + A_STATUS status; + void *context; + + status = process_request(req->func, req->buf, req->addr, + req->len, req->flags); + context = req->context; + + kfree(req); + + htcCallbacks.rwCompletionHandler(context, status); + } } return 0; } @@ -283,38 +344,25 @@ address += HIF_MBOX_WIDTH-length; } - req = kzalloc(sizeof(*req), GFP_ATOMIC); - if (!req) { - if (request & HIF_ASYNCHRONOUS) - htcCallbacks.rwCompletionHandler(context, A_ERROR); - return A_ERROR; + if (!(request & HIF_ASYNCHRONOUS)) { + return process_request(hif->func, buffer, address, length, request); } - req->func = hif->func; - req->addr = address; - req->buf = buffer; - req->len = length; - - if (request & HIF_READ) { - if (request & HIF_FIXED_ADDRESS) - req->read = sdio_readsb; - else - req->read = sdio_memcpy_fromio; - } else { - if (request & HIF_FIXED_ADDRESS) - req->write = sdio_writesb; - else - req->write = sdio_memcpy_toio; - } + if ((req = kzalloc(sizeof(*req), GFP_ATOMIC))) { + req->func = hif->func; + req->buf = buffer; + req->addr = address; + req->len = length; + req->flags = request; + req->context = context; - if (!(request & HIF_ASYNCHRONOUS)) - return process_request(req); + enqueue_request(hif, req); - req->completion = htcCallbacks.rwCompletionHandler; - req->context = context; - enqueue_request(hif, req); + return A_OK; + } - return A_OK; + htcCallbacks.rwCompletionHandler(context, A_ERROR); + return A_ERROR; }