X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fblock%2Fxsysace.c;h=e5c5415eb45eb7a7e8f350427be29fcfe2fb3eec;hb=b4b90c659d88d09dcb4e34dce5123458cb1b5071;hp=9e7652dcde6cd46f1d1d19c2fa0462f8754d9536;hpb=d2bbf3da3759d04cd5836955cc59c8ae96092831;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 9e7652d..e5c5415 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #if defined(CONFIG_OF) @@ -194,7 +195,7 @@ struct ace_device { int in_irq; /* Details of hardware device */ - unsigned long physaddr; + resource_size_t physaddr; void __iomem *baseaddr; int irq; int bus_width; /* 0 := 8 bit; 1 := 16 bit */ @@ -208,7 +209,7 @@ struct ace_device { struct gendisk *gd; /* Inserted CF card parameters */ - struct hd_driveid cf_id; + u16 cf_id[ATA_ID_WORDS]; }; static int ace_major; @@ -389,7 +390,8 @@ static inline void ace_dump_mem(void *base, int len) static void ace_dump_regs(struct ace_device *ace) { - dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" + dev_info(ace->dev, + " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" " status:%.8x mpu_lba:%.8x busmode:%4x\n" " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", ace_in32(ace, ACE_CTRL), @@ -402,21 +404,14 @@ static void ace_dump_regs(struct ace_device *ace) ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT)); } -void ace_fix_driveid(struct hd_driveid *id) +void ace_fix_driveid(u16 *id) { #if defined(__BIG_ENDIAN) - u16 *buf = (void *)id; int i; /* All half words have wrong byte order; swap the bytes */ - for (i = 0; i < sizeof(struct hd_driveid); i += 2, buf++) - *buf = le16_to_cpu(*buf); - - /* Some of the data values are 32bit; swap the half words */ - id->lba_capacity = ((id->lba_capacity >> 16) & 0x0000FFFF) | - ((id->lba_capacity << 16) & 0xFFFF0000); - id->spg = ((id->spg >> 16) & 0x0000FFFF) | - ((id->spg << 16) & 0xFFFF0000); + for (i = 0; i < ATA_ID_WORDS; i++, id++) + *id = le16_to_cpu(*id); #endif } @@ -469,10 +464,11 @@ struct request *ace_get_next_request(struct request_queue * q) { struct request *req; - while ((req = elv_next_request(q)) != NULL) { + while ((req = blk_peek_request(q)) != NULL) { if (blk_fs_request(req)) break; - end_request(req, 0); + blk_start_request(req); + __blk_end_request_all(req, -EIO); } return req; } @@ -483,13 +479,38 @@ static void ace_fsm_dostate(struct ace_device *ace) u32 status; u16 val; int count; - int i; #if defined(DEBUG) dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n", ace->fsm_state, ace->id_req_count); #endif + /* Verify that there is actually a CF in the slot. If not, then + * bail out back to the idle state and wake up all the waiters */ + status = ace_in32(ace, ACE_STATUS); + if ((status & ACE_STATUS_CFDETECT) == 0) { + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->media_change = 1; + set_capacity(ace->gd, 0); + dev_info(ace->dev, "No CF in slot\n"); + + /* Drop all in-flight and pending requests */ + if (ace->req) { + __blk_end_request_all(ace->req, -EIO); + ace->req = NULL; + } + while ((req = blk_fetch_request(ace->queue)) != NULL) + __blk_end_request_all(req, -EIO); + + /* Drop back to IDLE state and notify waiters */ + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->id_result = -EIO; + while (ace->id_req_count) { + complete(&ace->id_completion); + ace->id_req_count--; + } + } + switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ @@ -548,7 +569,7 @@ static void ace_fsm_dostate(struct ace_device *ace) case ACE_FSM_STATE_IDENTIFY_PREPARE: /* Send identify command */ ace->fsm_task = ACE_TASK_IDENTIFY; - ace->data_ptr = &ace->cf_id; + ace->data_ptr = ace->cf_id; ace->data_count = ACE_BUF_PER_SECTOR; ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY); @@ -593,8 +614,8 @@ static void ace_fsm_dostate(struct ace_device *ace) break; case ACE_FSM_STATE_IDENTIFY_COMPLETE: - ace_fix_driveid(&ace->cf_id); - ace_dump_mem(&ace->cf_id, 512); /* Debug: Dump out disk ID */ + ace_fix_driveid(ace->cf_id); + ace_dump_mem(ace->cf_id, 512); /* Debug: Dump out disk ID */ if (ace->data_result) { /* Error occured, disable the disk */ @@ -606,9 +627,10 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->media_change = 0; /* Record disk parameters */ - set_capacity(ace->gd, ace->cf_id.lba_capacity); + set_capacity(ace->gd, + ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY)); dev_info(ace->dev, "capacity: %i sectors\n", - ace->cf_id.lba_capacity); + ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY)); } /* We're done, drop to IDLE state and notify waiters */ @@ -626,19 +648,21 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state = ACE_FSM_STATE_IDLE; break; } + blk_start_request(req); /* Okay, it's a data request, set it up for transfer */ dev_dbg(ace->dev, - "request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n", - req->sector, req->hard_nr_sectors, - req->current_nr_sectors, rq_data_dir(req)); + "request: sec=%llx hcnt=%x, ccnt=%x, dir=%i\n", + (unsigned long long)blk_rq_pos(req), + blk_rq_sectors(req), blk_rq_cur_sectors(req), + rq_data_dir(req)); ace->req = req; ace->data_ptr = req->buffer; - ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR; - ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF); + ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR; + ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF); - count = req->hard_nr_sectors; + count = blk_rq_sectors(req); if (rq_data_dir(req)) { /* Kick off write request */ dev_dbg(ace->dev, "write data\n"); @@ -672,7 +696,7 @@ static void ace_fsm_dostate(struct ace_device *ace) dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n", ace->fsm_task, ace->fsm_iter_num, - ace->req->current_nr_sectors * 16, + blk_rq_cur_sectors(ace->req) * 16, ace->data_count, ace->in_irq); ace_fsm_yield(ace); /* need to poll CFBSY bit */ break; @@ -681,14 +705,13 @@ static void ace_fsm_dostate(struct ace_device *ace) dev_dbg(ace->dev, "DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n", ace->fsm_task, ace->fsm_iter_num, - ace->req->current_nr_sectors * 16, + blk_rq_cur_sectors(ace->req) * 16, ace->data_count, ace->in_irq); ace_fsm_yieldirq(ace); break; } /* Transfer the next buffer */ - i = 16; if (ace->fsm_task == ACE_TASK_WRITE) ace->reg_ops->dataout(ace); else @@ -702,14 +725,13 @@ static void ace_fsm_dostate(struct ace_device *ace) } /* bio finished; is there another one? */ - i = ace->req->current_nr_sectors; - if (end_that_request_first(ace->req, 1, i)) { - /* dev_dbg(ace->dev, "next block; h=%li c=%i\n", - * ace->req->hard_nr_sectors, - * ace->req->current_nr_sectors); + if (__blk_end_request_cur(ace->req, 0)) { + /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", + * blk_rq_sectors(ace->req), + * blk_rq_cur_sectors(ace->req)); */ ace->data_ptr = ace->req->buffer; - ace->data_count = ace->req->current_nr_sectors * 16; + ace->data_count = blk_rq_cur_sectors(ace->req) * 16; ace_fsm_yieldirq(ace); break; } @@ -718,9 +740,6 @@ static void ace_fsm_dostate(struct ace_device *ace) break; case ACE_FSM_STATE_REQ_COMPLETE: - /* Complete the block request */ - blkdev_dequeue_request(ace->req); - end_that_request_last(ace->req, 1); ace->req = NULL; /* Finished request; go to idle state */ @@ -875,25 +894,24 @@ static int ace_revalidate_disk(struct gendisk *gd) return ace->id_result; } -static int ace_open(struct inode *inode, struct file *filp) +static int ace_open(struct block_device *bdev, fmode_t mode) { - struct ace_device *ace = inode->i_bdev->bd_disk->private_data; + struct ace_device *ace = bdev->bd_disk->private_data; unsigned long flags; dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1); - filp->private_data = ace; spin_lock_irqsave(&ace->lock, flags); ace->users++; spin_unlock_irqrestore(&ace->lock, flags); - check_disk_change(inode->i_bdev); + check_disk_change(bdev); return 0; } -static int ace_release(struct inode *inode, struct file *filp) +static int ace_release(struct gendisk *disk, fmode_t mode) { - struct ace_device *ace = inode->i_bdev->bd_disk->private_data; + struct ace_device *ace = disk->private_data; unsigned long flags; u16 val; @@ -912,17 +930,18 @@ static int ace_release(struct inode *inode, struct file *filp) static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo) { struct ace_device *ace = bdev->bd_disk->private_data; + u16 *cf_id = ace->cf_id; dev_dbg(ace->dev, "ace_getgeo()\n"); - geo->heads = ace->cf_id.heads; - geo->sectors = ace->cf_id.sectors; - geo->cylinders = ace->cf_id.cyls; + geo->heads = cf_id[ATA_ID_HEADS]; + geo->sectors = cf_id[ATA_ID_SECTORS]; + geo->cylinders = cf_id[ATA_ID_CYLS]; return 0; } -static struct block_device_operations ace_fops = { +static const struct block_device_operations ace_fops = { .owner = THIS_MODULE, .open = ace_open, .release = ace_release, @@ -941,7 +960,8 @@ static int __devinit ace_setup(struct ace_device *ace) int rc; dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace); - dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq); + dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n", + (unsigned long long)ace->physaddr, ace->irq); spin_lock_init(&ace->lock); init_completion(&ace->id_completion); @@ -965,7 +985,7 @@ static int __devinit ace_setup(struct ace_device *ace) ace->queue = blk_init_queue(ace_request, &ace->lock); if (ace->queue == NULL) goto err_blk_initq; - blk_queue_hardsect_size(ace->queue, 512); + blk_queue_logical_block_size(ace->queue, 512); /* * Allocate and initialize GD structure @@ -1023,8 +1043,8 @@ static int __devinit ace_setup(struct ace_device *ace) /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); - dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n", - ace->physaddr, ace->baseaddr, ace->irq); + dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n", + (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq); ace->media_change = 1; ace_revalidate_disk(ace->gd); @@ -1041,8 +1061,8 @@ err_alloc_disk: err_blk_initq: iounmap(ace->baseaddr); err_ioremap: - dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", - ace->physaddr); + dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n", + (unsigned long long) ace->physaddr); return -ENOMEM; } @@ -1065,7 +1085,7 @@ static void __devexit ace_teardown(struct ace_device *ace) } static int __devinit -ace_alloc(struct device *dev, int id, unsigned long physaddr, +ace_alloc(struct device *dev, int id, resource_size_t physaddr, int irq, int bus_width) { struct ace_device *ace; @@ -1125,7 +1145,7 @@ static void __devexit ace_free(struct device *dev) static int __devinit ace_probe(struct platform_device *dev) { - unsigned long physaddr = 0; + resource_size_t physaddr = 0; int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ int id = dev->id; int irq = NO_IRQ; @@ -1171,7 +1191,7 @@ static int __devinit ace_of_probe(struct of_device *op, const struct of_device_id *match) { struct resource res; - unsigned long physaddr; + resource_size_t physaddr; const u32 *id; int irq, bus_width, rc; @@ -1207,8 +1227,11 @@ static int __devexit ace_of_remove(struct of_device *op) } /* Match table for of_platform binding */ -static struct of_device_id __devinit ace_of_match[] = { - { .compatible = "xilinx,xsysace", }, +static struct of_device_id ace_of_match[] __devinitdata = { + { .compatible = "xlnx,opb-sysace-1.00.b", }, + { .compatible = "xlnx,opb-sysace-1.00.c", }, + { .compatible = "xlnx,xps-sysace-1.00.a", }, + { .compatible = "xlnx,sysace", }, {}, }; MODULE_DEVICE_TABLE(of, ace_of_match);