From 4c31a781144c1f556dfcda3277dafecd4e107d95 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 3 Nov 2009 15:58:40 +0000 Subject: xenbus: do not hold transaction_mutex when returning to userspace ================================================ [ BUG: lock held when returning to user space! ] ------------------------------------------------ xenstore-list/3522 is leaving the kernel with locks still held! 1 lock held by xenstore-list/3522: #0: (&xs_state.transaction_mutex){......}, at: [] xenbus_dev_request_and_reply+0x8f/0xa0 The canonical fix for this type of issue appears to be to maintain a count manually rather than using an rwsem so do that here. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge --- drivers/xen/xenbus/xenbus_xs.c | 57 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index eab33f1dbdf7..6f91e8c8b932 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -76,6 +76,14 @@ struct xs_handle { /* * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex. * response_mutex is never taken simultaneously with the other three. + * + * transaction_mutex must be held before incrementing + * transaction_count. The mutex is held when a suspend is in + * progress to prevent new transactions starting. + * + * When decrementing transaction_count to zero the wait queue + * should be woken up, the suspend code waits for count to + * reach zero. */ /* One request at a time. */ @@ -85,7 +93,9 @@ struct xs_handle { struct mutex response_mutex; /* Protect transactions against save/restore. */ - struct rw_semaphore transaction_mutex; + struct mutex transaction_mutex; + atomic_t transaction_count; + wait_queue_head_t transaction_wq; /* Protect watch (de)register against save/restore. */ struct rw_semaphore watch_mutex; @@ -157,6 +167,31 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) return body; } +static void transaction_start(void) +{ + mutex_lock(&xs_state.transaction_mutex); + atomic_inc(&xs_state.transaction_count); + mutex_unlock(&xs_state.transaction_mutex); +} + +static void transaction_end(void) +{ + if (atomic_dec_and_test(&xs_state.transaction_count)) + wake_up(&xs_state.transaction_wq); +} + +static void transaction_suspend(void) +{ + mutex_lock(&xs_state.transaction_mutex); + wait_event(xs_state.transaction_wq, + atomic_read(&xs_state.transaction_count) == 0); +} + +static void transaction_resume(void) +{ + mutex_unlock(&xs_state.transaction_mutex); +} + void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) { void *ret; @@ -164,7 +199,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) int err; if (req_msg.type == XS_TRANSACTION_START) - down_read(&xs_state.transaction_mutex); + transaction_start(); mutex_lock(&xs_state.request_mutex); @@ -180,7 +215,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) if ((msg->type == XS_TRANSACTION_END) || ((req_msg.type == XS_TRANSACTION_START) && (msg->type == XS_ERROR))) - up_read(&xs_state.transaction_mutex); + transaction_end(); return ret; } @@ -432,11 +467,11 @@ int xenbus_transaction_start(struct xenbus_transaction *t) { char *id_str; - down_read(&xs_state.transaction_mutex); + transaction_start(); id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); if (IS_ERR(id_str)) { - up_read(&xs_state.transaction_mutex); + transaction_end(); return PTR_ERR(id_str); } @@ -461,7 +496,7 @@ int xenbus_transaction_end(struct xenbus_transaction t, int abort) err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); - up_read(&xs_state.transaction_mutex); + transaction_end(); return err; } @@ -662,7 +697,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch); void xs_suspend(void) { - down_write(&xs_state.transaction_mutex); + transaction_suspend(); down_write(&xs_state.watch_mutex); mutex_lock(&xs_state.request_mutex); mutex_lock(&xs_state.response_mutex); @@ -677,7 +712,7 @@ void xs_resume(void) mutex_unlock(&xs_state.response_mutex); mutex_unlock(&xs_state.request_mutex); - up_write(&xs_state.transaction_mutex); + transaction_resume(); /* No need for watches_lock: the watch_mutex is sufficient. */ list_for_each_entry(watch, &watches, list) { @@ -693,7 +728,7 @@ void xs_suspend_cancel(void) mutex_unlock(&xs_state.response_mutex); mutex_unlock(&xs_state.request_mutex); up_write(&xs_state.watch_mutex); - up_write(&xs_state.transaction_mutex); + mutex_unlock(&xs_state.transaction_mutex); } static int xenwatch_thread(void *unused) @@ -843,8 +878,10 @@ int xs_init(void) mutex_init(&xs_state.request_mutex); mutex_init(&xs_state.response_mutex); - init_rwsem(&xs_state.transaction_mutex); + mutex_init(&xs_state.transaction_mutex); init_rwsem(&xs_state.watch_mutex); + atomic_set(&xs_state.transaction_count, 0); + init_waitqueue_head(&xs_state.transaction_wq); /* Initialize the shared memory rings to talk to xenstored */ err = xb_init_comms(); -- cgit v1.2.3 From d8c1fa4af0f311363d9f9cf1014b11d31a99ff10 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 22 May 2010 10:22:00 +0200 Subject: ieee1394: video1394: Use memdup_user ...when user data is immediately copied into the allocated region. Signed-off-by: Julia Lawall Signed-off-by: Stefan Richter (changelog) --- drivers/ieee1394/video1394.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index a42bd6893bcf..a77483befcda 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1045,14 +1045,9 @@ static long video1394_ioctl(struct file *file, if (get_user(qv, &p->packet_sizes)) return -EFAULT; - psizes = kmalloc(buf_size, GFP_KERNEL); - if (!psizes) - return -ENOMEM; - - if (copy_from_user(psizes, qv, buf_size)) { - kfree(psizes); - return -EFAULT; - } + psizes = memdup_user(qv, buf_size); + if (IS_ERR(psizes)) + return PTR_ERR(psizes); } spin_lock_irqsave(&d->lock,flags); -- cgit v1.2.3 From 01d73a6967f12fe6c4bbde1834a9fe662264a2eb Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:24 -0600 Subject: drm: Remove drm_resource wrappers Remove the drm_resource wrappers and directly use the actual PCI and/or platform functions in their place. [airlied: fixup nouveau properly to build] Signed-off-by: Jordan Crouse Reviewed-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 13 ------------- drivers/gpu/drm/i915/i915_dma.c | 6 +++--- drivers/gpu/drm/mga/mga_dma.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/nouveau/nouveau_channel.c | 3 ++- drivers/gpu/drm/nouveau/nouveau_mem.c | 16 +++++++++------- drivers/gpu/drm/nouveau/nv20_graph.c | 4 ++-- drivers/gpu/drm/nouveau/nv40_graph.c | 2 +- drivers/gpu/drm/nouveau/nv50_instmem.c | 2 +- drivers/gpu/drm/radeon/evergreen.c | 4 ++-- drivers/gpu/drm/radeon/r100.c | 4 ++-- drivers/gpu/drm/radeon/r600.c | 4 ++-- drivers/gpu/drm/radeon/radeon_bios.c | 2 +- drivers/gpu/drm/radeon/radeon_cp.c | 8 ++++---- drivers/gpu/drm/radeon/radeon_device.c | 4 ++-- drivers/gpu/drm/radeon/rs600.c | 4 ++-- drivers/gpu/drm/radeon/rs690.c | 4 ++-- drivers/gpu/drm/radeon/rv770.c | 4 ++-- drivers/gpu/drm/savage/savage_bci.c | 24 +++++++++++++----------- include/drm/drmP.h | 4 ---- 20 files changed, 53 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index f7ba82ebf65a..7783035871e9 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -39,19 +39,6 @@ #include #include "drmP.h" -resource_size_t drm_get_resource_start(struct drm_device *dev, unsigned int resource) -{ - return pci_resource_start(dev->pdev, resource); -} -EXPORT_SYMBOL(drm_get_resource_start); - -resource_size_t drm_get_resource_len(struct drm_device *dev, unsigned int resource) -{ - return pci_resource_len(dev->pdev, resource); -} - -EXPORT_SYMBOL(drm_get_resource_len); - static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, struct drm_local_map *map) { diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2a6b5de5ae5d..9fe2d08d9e9d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1429,7 +1429,7 @@ static int i915_load_modeset_init(struct drm_device *dev, int fb_bar = IS_I9XX(dev) ? 2 : 0; int ret = 0; - dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & + dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) & 0xff000000; /* Basic memrange allocator for stolen space (aka vram) */ @@ -1612,8 +1612,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) /* Add register map (needed for suspend/resume) */ mmio_bar = IS_I9XX(dev) ? 0 : 1; - base = drm_get_resource_start(dev, mmio_bar); - size = drm_get_resource_len(dev, mmio_bar); + base = pci_resource_start(dev->pdev, mmio_bar); + size = pci_resource_len(dev->pdev, mmio_bar); if (i915_get_bridge_dev(dev)) { ret = -EIO; diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 3c917fb3a60b..ccc129c328a4 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -405,8 +405,8 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags) dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; dev_priv->chipset = flags; - dev_priv->mmio_base = drm_get_resource_start(dev, 1); - dev_priv->mmio_size = drm_get_resource_len(dev, 1); + dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); + dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); dev->counters += 3; dev->types[6] = _DRM_STAT_IRQ; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 6f3c19522377..9f5ab4677758 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -783,7 +783,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) break; case TTM_PL_VRAM: mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; - mem->bus.base = drm_get_resource_start(dev, 1); + mem->bus.base = pci_resource_start(dev->pdev, 1); mem->bus.is_iomem = true; break; default: diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 1fc57ef58295..06555c7cde50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -62,7 +62,8 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) * VRAM. */ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - drm_get_resource_start(dev, 1), + pci_resource_start(dev->pdev, + 1), dev_priv->fb_available_size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI, &pushbuf); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 775a7017af64..37c7bf8e8296 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -471,8 +471,9 @@ void nouveau_mem_close(struct drm_device *dev) } if (dev_priv->fb_mtrr) { - drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1), - drm_get_resource_len(dev, 1), DRM_MTRR_WC); + drm_mtrr_del(dev_priv->fb_mtrr, + pci_resource_start(dev->pdev, 1), + pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); dev_priv->fb_mtrr = 0; } } @@ -632,7 +633,7 @@ nouveau_mem_init(struct drm_device *dev) struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; int ret, dma_bits = 32; - dev_priv->fb_phys = drm_get_resource_start(dev, 1); + dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); dev_priv->gart_info.type = NOUVEAU_GART_NONE; if (dev_priv->card_type >= NV_50 && @@ -664,8 +665,9 @@ nouveau_mem_init(struct drm_device *dev) dev_priv->fb_available_size = dev_priv->vram_size; dev_priv->fb_mappable_pages = dev_priv->fb_available_size; - if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1)) - dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1); + if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) + dev_priv->fb_mappable_pages = + pci_resource_len(dev->pdev, 1); dev_priv->fb_mappable_pages >>= PAGE_SHIFT; /* remove reserved space at end of vram from available amount */ @@ -717,8 +719,8 @@ nouveau_mem_init(struct drm_device *dev) return ret; } - dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), - drm_get_resource_len(dev, 1), + dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), + pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); return 0; diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index d6fc0a82f03d..fe2349b115f0 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c @@ -616,7 +616,7 @@ nv20_graph_init(struct drm_device *dev) nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); /* begin RAM config */ - vramsz = drm_get_resource_len(dev, 0) - 1; + vramsz = pci_resource_len(dev->pdev, 0) - 1; nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); @@ -717,7 +717,7 @@ nv30_graph_init(struct drm_device *dev) nv_wr32(dev, 0x0040075c , 0x00000001); /* begin RAM config */ - /* vramsz = drm_get_resource_len(dev, 0) - 1; */ + /* vramsz = pci_resource_len(dev->pdev, 0) - 1; */ nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); if (dev_priv->chipset != 0x34) { diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 704a25d04ac9..65b13b54c5ae 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -367,7 +367,7 @@ nv40_graph_init(struct drm_device *dev) nv40_graph_set_region_tiling(dev, i, 0, 0, 0); /* begin RAM config */ - vramsz = drm_get_resource_len(dev, 0) - 1; + vramsz = pci_resource_len(dev->pdev, 0) - 1; switch (dev_priv->chipset) { case 0x40: nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 5f21df31f3aa..71c01b6e5731 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -241,7 +241,7 @@ nv50_instmem_init(struct drm_device *dev) return ret; BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + - drm_get_resource_len(dev, 1) - 1); + pci_resource_len(dev->pdev, 1) - 1); BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 8c8e4d3cbaa3..a4745e49ecf1 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1300,8 +1300,8 @@ int evergreen_mc_init(struct radeon_device *rdev) } rdev->mc.vram_width = numchan * chansize; /* Could aper size report 0 ? */ - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* Setup GPU memory space */ /* size in MB on evergreen */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index cc004b05d63e..c485c2cec4da 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2284,8 +2284,8 @@ void r100_vram_init_sizes(struct radeon_device *rdev) u64 config_aper_size; /* work out accessible VRAM */ - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev); /* FIXME we don't use the second aperture yet when we could use it */ if (rdev->mc.visible_vram_size > rdev->mc.aper_size) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 44e96a2ae25a..4959619f8851 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1118,8 +1118,8 @@ int r600_mc_init(struct radeon_device *rdev) } rdev->mc.vram_width = numchan * chansize; /* Could aper size report 0 ? */ - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* Setup GPU memory space */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index fbba938f8048..91f5b5a29a9f 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -49,7 +49,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) resource_size_t size = 256 * 1024; /* ??? */ rdev->bios = NULL; - vram_base = drm_get_resource_start(rdev->ddev, 0); + vram_base = pci_resource_start(rdev->pdev, 0); bios = ioremap(vram_base, size); if (!bios) { return false; diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 2f042a3c0e62..eb6b9eed7349 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2120,8 +2120,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) else dev_priv->flags |= RADEON_IS_PCI; - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), _DRM_REGISTERS, + ret = drm_addmap(dev, pci_resource_start(dev->pdev, 2), + pci_resource_len(dev->pdev, 2), _DRM_REGISTERS, _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); if (ret != 0) return ret; @@ -2194,9 +2194,9 @@ int radeon_driver_firstopen(struct drm_device *dev) dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); + dev_priv->fb_aper_offset = pci_resource_start(dev->pdev, 0); ret = drm_addmap(dev, dev_priv->fb_aper_offset, - drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, + pci_resource_len(dev->pdev, 0), _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &map); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index fdc3fdf78acb..2a897a7ca26f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -648,8 +648,8 @@ int radeon_device_init(struct radeon_device *rdev, /* Registers mapping */ /* TODO: block userspace mapping of io register */ - rdev->rmmio_base = drm_get_resource_start(rdev->ddev, 2); - rdev->rmmio_size = drm_get_resource_len(rdev->ddev, 2); + rdev->rmmio_base = pci_resource_start(rdev->pdev, 2); + rdev->rmmio_size = pci_resource_len(rdev->pdev, 2); rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); if (rdev->rmmio == NULL) { return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 79887cac5b54..340c7611f2ac 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -685,8 +685,8 @@ void rs600_mc_init(struct radeon_device *rdev) { u64 base; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index bcc33195ebc2..a18ba98885f3 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -151,8 +151,8 @@ void rs690_mc_init(struct radeon_device *rdev) rdev->mc.vram_width = 128; rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = rdev->mc.aper_size; base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 253f24aec031..5c7f0b97c6aa 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -908,8 +908,8 @@ int rv770_mc_init(struct radeon_device *rdev) } rdev->mc.vram_width = numchan * chansize; /* Could aper size report 0 ? */ - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* Setup GPU memory space */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 2d0c9ca484c5..f576232846c3 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -573,13 +573,13 @@ int savage_driver_firstopen(struct drm_device *dev) dev_priv->mtrr[2].handle = -1; if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { fb_rsrc = 0; - fb_base = drm_get_resource_start(dev, 0); + fb_base = pci_resource_start(dev->pdev, 0); fb_size = SAVAGE_FB_SIZE_S3; mmio_base = fb_base + SAVAGE_FB_SIZE_S3; aper_rsrc = 0; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; /* this should always be true */ - if (drm_get_resource_len(dev, 0) == 0x08000000) { + if (pci_resource_len(dev->pdev, 0) == 0x08000000) { /* Don't make MMIO write-cobining! We need 3 * MTRRs. */ dev_priv->mtrr[0].base = fb_base; @@ -599,18 +599,19 @@ int savage_driver_firstopen(struct drm_device *dev) dev_priv->mtrr[2].size, DRM_MTRR_WC); } else { DRM_ERROR("strange pci_resource_len %08llx\n", - (unsigned long long)drm_get_resource_len(dev, 0)); + (unsigned long long) + pci_resource_len(dev->pdev, 0)); } } else if (dev_priv->chipset != S3_SUPERSAVAGE && dev_priv->chipset != S3_SAVAGE2000) { - mmio_base = drm_get_resource_start(dev, 0); + mmio_base = pci_resource_start(dev->pdev, 0); fb_rsrc = 1; - fb_base = drm_get_resource_start(dev, 1); + fb_base = pci_resource_start(dev->pdev, 1); fb_size = SAVAGE_FB_SIZE_S4; aper_rsrc = 1; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; /* this should always be true */ - if (drm_get_resource_len(dev, 1) == 0x08000000) { + if (pci_resource_len(dev->pdev, 1) == 0x08000000) { /* Can use one MTRR to cover both fb and * aperture. */ dev_priv->mtrr[0].base = fb_base; @@ -620,15 +621,16 @@ int savage_driver_firstopen(struct drm_device *dev) dev_priv->mtrr[0].size, DRM_MTRR_WC); } else { DRM_ERROR("strange pci_resource_len %08llx\n", - (unsigned long long)drm_get_resource_len(dev, 1)); + (unsigned long long) + pci_resource_len(dev->pdev, 1)); } } else { - mmio_base = drm_get_resource_start(dev, 0); + mmio_base = pci_resource_start(dev->pdev, 0); fb_rsrc = 1; - fb_base = drm_get_resource_start(dev, 1); - fb_size = drm_get_resource_len(dev, 1); + fb_base = pci_resource_start(dev->pdev, 1); + fb_size = pci_resource_len(dev->pdev, 1); aper_rsrc = 2; - aperture_base = drm_get_resource_start(dev, 2); + aperture_base = pci_resource_start(dev->pdev, 2); /* Automatic MTRR setup will do the right thing. */ } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c1b987158dfa..8f7f5cb4a86d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1273,10 +1273,6 @@ extern int drm_freebufs(struct drm_device *dev, void *data, extern int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_order(unsigned long size); -extern resource_size_t drm_get_resource_start(struct drm_device *dev, - unsigned int resource); -extern resource_size_t drm_get_resource_len(struct drm_device *dev, - unsigned int resource); /* DMA support (drm_dma.h) */ extern int drm_dma_setup(struct drm_device *dev); -- cgit v1.2.3 From dcdb167402cbdca1d021bdfa5f63995ee0a79317 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:25 -0600 Subject: drm: Add support for platform devices to register as DRM devices Allow platform devices without PCI resources to be DRM devices. [airlied: fixup warnings with dev pointers] Signed-off-by: Jordan Crouse Signed-off-by: Dave Airlie --- drivers/gpu/drm/Kconfig | 4 +- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_drv.c | 37 ++------- drivers/gpu/drm/drm_edid.c | 4 +- drivers/gpu/drm/drm_info.c | 23 ++++-- drivers/gpu/drm/drm_ioctl.c | 71 +++++++++++------ drivers/gpu/drm/drm_irq.c | 15 ++-- drivers/gpu/drm/drm_pci.c | 143 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_platform.c | 122 +++++++++++++++++++++++++++++ drivers/gpu/drm/drm_stub.c | 89 +-------------------- drivers/gpu/drm/drm_sysfs.c | 3 +- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +- drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- include/drm/drmP.h | 52 +++++++++++-- 17 files changed, 402 insertions(+), 172 deletions(-) create mode 100644 drivers/gpu/drm/drm_platform.c (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 88910e5a2c77..520ab23d8a3f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -6,7 +6,7 @@ # menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" - depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU + depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU select I2C select I2C_ALGOBIT select SLOW_WORK @@ -17,7 +17,7 @@ menuconfig DRM These modules provide support for synchronization, security, and DMA transfers. Please see for more details. You should also select and configure AGP - (/dev/agpgart) support. + (/dev/agpgart) support if it is available for your platform. config DRM_KMS_HELPER tristate diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index abe3f446ca48..b4b2b480d0ce 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ - drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ + drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 4a66201edaec..510bc87d98f6 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -243,47 +243,20 @@ int drm_lastclose(struct drm_device * dev) * * Initializes an array of drm_device structures, and attempts to * initialize all available devices, using consecutive minors, registering the - * stubs and initializing the AGP device. + * stubs and initializing the device. * * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and * after the initialization for driver customization. */ int drm_init(struct drm_driver *driver) { - struct pci_dev *pdev = NULL; - const struct pci_device_id *pid; - int i; - DRM_DEBUG("\n"); - INIT_LIST_HEAD(&driver->device_list); - if (driver->driver_features & DRIVER_MODESET) - return pci_register_driver(&driver->pci_driver); - - /* If not using KMS, fall back to stealth mode manual scanning. */ - for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { - pid = &driver->pci_driver.id_table[i]; - - /* Loop around setting up a DRM device for each PCI device - * matching our ID and device class. If we had the internal - * function that pci_get_subsys and pci_get_class used, we'd - * be able to just pass pid in instead of doing a two-stage - * thing. - */ - pdev = NULL; - while ((pdev = - pci_get_subsys(pid->vendor, pid->device, pid->subvendor, - pid->subdevice, pdev)) != NULL) { - if ((pdev->class & pid->class_mask) != pid->class) - continue; - - /* stealth mode requires a manual probe */ - pci_dev_get(pdev); - drm_get_dev(pdev, pid, driver); - } - } - return 0; + if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE) + return drm_platform_init(driver); + else + return drm_pci_init(driver); } EXPORT_SYMBOL(drm_init); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c1981861bbbd..83d8072066cb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -282,7 +282,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) return block; carp: - dev_warn(&connector->dev->pdev->dev, "%s: EDID block %d invalid.\n", + dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", drm_get_connector_name(connector), j); out: @@ -1626,7 +1626,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) return 0; } if (!drm_edid_is_valid(edid)) { - dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", + dev_warn(connector->dev->dev, "%s: EDID invalid.\n", drm_get_connector_name(connector)); return 0; } diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index f0f6c6b93f3a..2ef2c7827243 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -51,13 +51,24 @@ int drm_name_info(struct seq_file *m, void *data) if (!master) return 0; - if (master->unique) { - seq_printf(m, "%s %s %s\n", - dev->driver->pci_driver.name, - pci_name(dev->pdev), master->unique); + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { + if (master->unique) { + seq_printf(m, "%s %s %s\n", + dev->driver->platform_device->name, + dev_name(dev->dev), master->unique); + } else { + seq_printf(m, "%s\n", + dev->driver->platform_device->name); + } } else { - seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, - pci_name(dev->pdev)); + if (master->unique) { + seq_printf(m, "%s %s %s\n", + dev->driver->pci_driver.name, + dev_name(dev->dev), master->unique); + } else { + seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, + dev_name(dev->dev)); + } } return 0; diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 9b9ff46c2378..76d3d18056dd 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -132,32 +132,57 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) struct drm_master *master = file_priv->master; int len; - if (master->unique != NULL) - return -EBUSY; - - master->unique_len = 40; - master->unique_size = master->unique_len; - master->unique = kmalloc(master->unique_size, GFP_KERNEL); - if (master->unique == NULL) - return -ENOMEM; + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { + master->unique_len = 10 + strlen(dev->platformdev->name); + master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL); + + if (master->unique == NULL) + return -ENOMEM; + + len = snprintf(master->unique, master->unique_len, + "platform:%s", dev->platformdev->name); + + if (len > master->unique_len) + DRM_ERROR("Unique buffer overflowed\n"); + + dev->devname = + kmalloc(strlen(dev->platformdev->name) + + master->unique_len + 2, GFP_KERNEL); + + if (dev->devname == NULL) + return -ENOMEM; + + sprintf(dev->devname, "%s@%s", dev->platformdev->name, + master->unique); + + } else { + master->unique_len = 40; + master->unique_size = master->unique_len; + master->unique = kmalloc(master->unique_size, GFP_KERNEL); + if (master->unique == NULL) + return -ENOMEM; + + len = snprintf(master->unique, master->unique_len, + "pci:%04x:%02x:%02x.%d", + drm_get_pci_domain(dev), + dev->pdev->bus->number, + PCI_SLOT(dev->pdev->devfn), + PCI_FUNC(dev->pdev->devfn)); + if (len >= master->unique_len) + DRM_ERROR("buffer overflow"); + else + master->unique_len = len; - len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d", - drm_get_pci_domain(dev), - dev->pdev->bus->number, - PCI_SLOT(dev->pdev->devfn), - PCI_FUNC(dev->pdev->devfn)); - if (len >= master->unique_len) - DRM_ERROR("buffer overflow"); - else - master->unique_len = len; + dev->devname = + kmalloc(strlen(dev->driver->pci_driver.name) + + master->unique_len + 2, GFP_KERNEL); - dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) + - master->unique_len + 2, GFP_KERNEL); - if (dev->devname == NULL) - return -ENOMEM; + if (dev->devname == NULL) + return -ENOMEM; - sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, - master->unique); + sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, + master->unique); + } return 0; } diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index a263b7070fc6..6353b625e099 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -57,6 +57,9 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, { struct drm_irq_busid *p = data; + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return -EINVAL; + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; @@ -211,7 +214,7 @@ int drm_irq_install(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - if (dev->pdev->irq == 0) + if (drm_dev_to_irq(dev) == 0) return -EINVAL; mutex_lock(&dev->struct_mutex); @@ -229,7 +232,7 @@ int drm_irq_install(struct drm_device *dev) dev->irq_enabled = 1; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("irq=%d\n", dev->pdev->irq); + DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); /* Before installing handler */ dev->driver->irq_preinstall(dev); @@ -302,14 +305,14 @@ int drm_irq_uninstall(struct drm_device * dev) if (!irq_enabled) return -EINVAL; - DRM_DEBUG("irq=%d\n", dev->pdev->irq); + DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); if (!drm_core_check_feature(dev, DRIVER_MODESET)) vga_client_register(dev->pdev, NULL, NULL, NULL); dev->driver->irq_uninstall(dev); - free_irq(dev->pdev->irq, dev); + free_irq(drm_dev_to_irq(dev), dev); return 0; } @@ -341,7 +344,7 @@ int drm_control(struct drm_device *dev, void *data, if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && - ctl->irq != dev->pdev->irq) + ctl->irq != drm_dev_to_irq(dev)) return -EINVAL; return drm_irq_install(dev); case DRM_UNINST_HANDLER: @@ -651,7 +654,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, int ret = 0; unsigned int flags, seq, crtc; - if ((!dev->pdev->irq) || (!dev->irq_enabled)) + if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled)) return -EINVAL; if (vblwait->request.type & _DRM_VBLANK_SIGNAL) diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 2ea9ad4a8d69..e20f78b542a7 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -124,4 +124,147 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) EXPORT_SYMBOL(drm_pci_free); +#ifdef CONFIG_PCI +/** + * Register. + * + * \param pdev - PCI device structure + * \param ent entry from the PCI ID table with device type flags + * \return zero on success or a negative number on failure. + * + * Attempt to gets inter module "drm" information. If we are first + * then register the character device and inter module information. + * Try and register, if we fail to register, backout previous work. + */ +int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + struct drm_driver *driver) +{ + struct drm_device *dev; + int ret; + + DRM_DEBUG("\n"); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + ret = pci_enable_device(pdev); + if (ret) + goto err_g1; + + pci_set_master(pdev); + + dev->pdev = pdev; + dev->dev = &pdev->dev; + + dev->pci_device = pdev->device; + dev->pci_vendor = pdev->vendor; + +#ifdef __alpha__ + dev->hose = pdev->sysdata; +#endif + + if ((ret = drm_fill_in_dev(dev, ent, driver))) { + printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); + goto err_g2; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + pci_set_drvdata(pdev, dev); + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret) + goto err_g2; + } + + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) + goto err_g3; + + if (dev->driver->load) { + ret = dev->driver->load(dev, ent->driver_data); + if (ret) + goto err_g4; + } + + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, + &dev->primary->mode_group); + if (ret) + goto err_g4; + } + + list_add_tail(&dev->driver_item, &driver->device_list); + + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, pci_name(pdev), dev->primary->index); + + return 0; + +err_g4: + drm_put_minor(&dev->primary); +err_g3: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); +err_g2: + pci_disable_device(pdev); +err_g1: + kfree(dev); + return ret; +} +EXPORT_SYMBOL(drm_get_pci_dev); + +/** + * PCI device initialization. Called via drm_init at module load time, + * + * \return zero on success or a negative number on failure. + * + * Initializes a drm_device structures,registering the + * stubs and initializing the AGP device. + * + * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and + * after the initialization for driver customization. + */ +int drm_pci_init(struct drm_driver *driver) +{ + struct pci_dev *pdev = NULL; + const struct pci_device_id *pid; + int i; + + if (driver->driver_features & DRIVER_MODESET) + return pci_register_driver(&driver->pci_driver); + + /* If not using KMS, fall back to stealth mode manual scanning. */ + for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { + pid = &driver->pci_driver.id_table[i]; + + /* Loop around setting up a DRM device for each PCI device + * matching our ID and device class. If we had the internal + * function that pci_get_subsys and pci_get_class used, we'd + * be able to just pass pid in instead of doing a two-stage + * thing. + */ + pdev = NULL; + while ((pdev = + pci_get_subsys(pid->vendor, pid->device, pid->subvendor, + pid->subdevice, pdev)) != NULL) { + if ((pdev->class & pid->class_mask) != pid->class) + continue; + + /* stealth mode requires a manual probe */ + pci_dev_get(pdev); + drm_get_pci_dev(pdev, pid, driver); + } + } + return 0; +} + +#else + +int drm_pci_init(struct drm_driver *driver) +{ + return -1; +} + +#endif /*@}*/ diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c new file mode 100644 index 000000000000..460e9a3afa8d --- /dev/null +++ b/drivers/gpu/drm/drm_platform.c @@ -0,0 +1,122 @@ +/* + * Derived from drm_pci.c + * + * Copyright 2003 José Fonseca. + * Copyright 2003 Leif Delgass. + * Copyright (c) 2009, Code Aurora Forum. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" + +/** + * Register. + * + * \param platdev - Platform device struture + * \return zero on success or a negative number on failure. + * + * Attempt to gets inter module "drm" information. If we are first + * then register the character device and inter module information. + * Try and register, if we fail to register, backout previous work. + */ + +int drm_get_platform_dev(struct platform_device *platdev, + struct drm_driver *driver) +{ + struct drm_device *dev; + int ret; + + DRM_DEBUG("\n"); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->platformdev = platdev; + dev->dev = &platdev->dev; + + ret = drm_fill_in_dev(dev, NULL, driver); + + if (ret) { + printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); + goto err_g1; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + dev_set_drvdata(&platdev->dev, dev); + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret) + goto err_g1; + } + + ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); + if (ret) + goto err_g2; + + if (dev->driver->load) { + ret = dev->driver->load(dev, 0); + if (ret) + goto err_g3; + } + + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, + &dev->primary->mode_group); + if (ret) + goto err_g3; + } + + list_add_tail(&dev->driver_item, &driver->device_list); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, dev->primary->index); + + return 0; + +err_g3: + drm_put_minor(&dev->primary); +err_g2: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); +err_g1: + kfree(dev); + return ret; +} +EXPORT_SYMBOL(drm_get_platform_dev); + +/** + * Platform device initialization. Called via drm_init at module load time, + * + * \return zero on success or a negative number on failure. + * + * Initializes a drm_device structures,registering the + * stubs + * + * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and + * after the initialization for driver customization. + */ + +int drm_platform_init(struct drm_driver *driver) +{ + return drm_get_platform_dev(driver->platform_device, driver); +} diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index a0c365f2e521..63575e2fa882 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -224,7 +224,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, return 0; } -static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, +int drm_fill_in_dev(struct drm_device *dev, const struct pci_device_id *ent, struct drm_driver *driver) { @@ -245,14 +245,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, idr_init(&dev->drw_idr); - dev->pdev = pdev; - dev->pci_device = pdev->device; - dev->pci_vendor = pdev->vendor; - -#ifdef __alpha__ - dev->hose = pdev->sysdata; -#endif - if (drm_ht_create(&dev->map_hash, 12)) { return -ENOMEM; } @@ -321,7 +313,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) +int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) { struct drm_minor *new_minor; int ret; @@ -387,83 +379,6 @@ err_idr: return ret; } -/** - * Register. - * - * \param pdev - PCI device structure - * \param ent entry from the PCI ID table with device type flags - * \return zero on success or a negative number on failure. - * - * Attempt to gets inter module "drm" information. If we are first - * then register the character device and inter module information. - * Try and register, if we fail to register, backout previous work. - */ -int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, - struct drm_driver *driver) -{ - struct drm_device *dev; - int ret; - - DRM_DEBUG("\n"); - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - ret = pci_enable_device(pdev); - if (ret) - goto err_g1; - - pci_set_master(pdev); - if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { - printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); - goto err_g2; - } - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - pci_set_drvdata(pdev, dev); - ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); - if (ret) - goto err_g2; - } - - if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) - goto err_g3; - - if (dev->driver->load) { - ret = dev->driver->load(dev, ent->driver_data); - if (ret) - goto err_g4; - } - - /* setup the grouping for the legacy output */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); - if (ret) - goto err_g4; - } - - list_add_tail(&dev->driver_item, &driver->device_list); - - DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", - driver->name, driver->major, driver->minor, driver->patchlevel, - driver->date, pci_name(pdev), dev->primary->index); - - return 0; - -err_g4: - drm_put_minor(&dev->primary); -err_g3: - if (drm_core_check_feature(dev, DRIVER_MODESET)) - drm_put_minor(&dev->control); -err_g2: - pci_disable_device(pdev); -err_g1: - kfree(dev); - return ret; -} -EXPORT_SYMBOL(drm_get_dev); - /** * Put a secondary minor number. * diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 3a3a451d0bf8..14d9d829ef27 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -488,7 +488,8 @@ int drm_sysfs_device_add(struct drm_minor *minor) int err; char *minor_str; - minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.parent = minor->dev->dev; + minor->kdev.class = drm_class; minor->kdev.release = drm_sysfs_device_release; minor->kdev.devt = minor->device; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9fe2d08d9e9d..9bed5617e0ea 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -34,6 +34,7 @@ #include "i915_drm.h" #include "i915_drv.h" #include "i915_trace.h" +#include #include #include #include diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5c51e45ab68d..b7aecf5ea1fc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -435,7 +435,7 @@ int i965_reset(struct drm_device *dev, u8 flags) static int __devinit i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index c6079e36669d..f60a2b2ae445 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -132,7 +132,7 @@ static struct drm_driver driver; static int __devinit nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static void diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4afba1eca2a7..683e281b4092 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -236,7 +236,7 @@ static struct drm_driver kms_driver; static int __devinit radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &kms_driver); + return drm_get_pci_dev(pdev, ent, &kms_driver); } static void diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0c9c0811f42d..f7f248dbff58 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -758,7 +758,7 @@ static struct drm_driver driver = { static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static int __init vmwgfx_init(void) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8f7f5cb4a86d..6235169d5950 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -9,6 +9,7 @@ /* * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright (c) 2009-2010, Code Aurora Forum. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include /* For (un)lock_kernel */ @@ -144,6 +146,7 @@ extern void drm_ut_debug_printk(unsigned int request_level, #define DRIVER_IRQ_VBL2 0x800 #define DRIVER_GEM 0x1000 #define DRIVER_MODESET 0x2000 +#define DRIVER_USE_PLATFORM_DEVICE 0x4000 /***********************************************************************/ /** \name Begin the DRM... */ @@ -823,6 +826,7 @@ struct drm_driver { int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; + struct platform_device *platform_device; /* List of devices hanging off this driver */ struct list_head device_list; }; @@ -1015,12 +1019,16 @@ struct drm_device { struct drm_agp_head *agp; /**< AGP data */ + struct device *dev; /**< Device structure */ struct pci_dev *pdev; /**< PCI device structure */ int pci_vendor; /**< PCI vendor id */ int pci_device; /**< PCI device id */ #ifdef __alpha__ struct pci_controller *hose; #endif + + struct platform_device *platformdev; /**< Platform device struture */ + struct drm_sg_mem *sg; /**< Scatter gather memory */ int num_crtcs; /**< Number of CRTCs on this device */ void *dev_private; /**< device private data */ @@ -1060,17 +1068,21 @@ struct drm_device { }; -static inline int drm_dev_to_irq(struct drm_device *dev) -{ - return dev->pdev->irq; -} - static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature) { return ((dev->driver->driver_features & feature) ? 1 : 0); } + +static inline int drm_dev_to_irq(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return platform_get_irq(dev->platformdev, 0); + else + return dev->pdev->irq; +} + #ifdef __alpha__ #define drm_get_pci_domain(dev) dev->hose->index #else @@ -1347,8 +1359,11 @@ extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_master *drm_master_create(struct drm_minor *minor); extern struct drm_master *drm_master_get(struct drm_master *master); extern void drm_master_put(struct drm_master **master); -extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, - struct drm_driver *driver); +extern int drm_get_pci_dev(struct pci_dev *pdev, + const struct pci_device_id *ent, + struct drm_driver *driver); +extern int drm_get_platform_dev(struct platform_device *pdev, + struct drm_driver *driver); extern void drm_put_dev(struct drm_device *dev); extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; @@ -1525,6 +1540,9 @@ static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, static __inline__ int drm_device_is_agp(struct drm_device *dev) { + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return 0; + if (dev->driver->device_is_agp != NULL) { int err = (*dev->driver->device_is_agp) (dev); @@ -1538,7 +1556,10 @@ static __inline__ int drm_device_is_agp(struct drm_device *dev) static __inline__ int drm_device_is_pcie(struct drm_device *dev) { - return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return 0; + else + return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); } static __inline__ void drm_core_dropmap(struct drm_local_map *map) @@ -1546,6 +1567,21 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map) } #include "drm_mem_util.h" + +static inline void *drm_get_device(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return dev->platformdev; + else + return dev->pdev; +} + +extern int drm_platform_init(struct drm_driver *driver); +extern int drm_pci_init(struct drm_driver *driver); +extern int drm_fill_in_dev(struct drm_device *dev, + const struct pci_device_id *ent, + struct drm_driver *driver); +int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type); /*@}*/ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 4b7fb9b5746554d460e7bc986341d4b2db01e0b6 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:26 -0600 Subject: drm: Add __arm defines to DRM Add __arm defines to specify behavior specific for an ARM processor. Signed-off-by: Jordan Crouse Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 2 +- drivers/gpu/drm/drm_vm.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 7783035871e9..4fcbc445a8e5 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -176,7 +176,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) +#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__) if (map->offset + (map->size-1) < map->offset || map->offset < virt_to_phys(high_memory)) { kfree(map); diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index c3b13fb41d0c..3778360eceea 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -61,7 +61,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) tmp = pgprot_writecombine(tmp); else tmp = pgprot_noncached(tmp); -#elif defined(__sparc__) +#elif defined(__sparc__) || defined(__arm__) tmp = pgprot_noncached(tmp); #endif return tmp; @@ -601,6 +601,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) } switch (map->type) { +#if !defined(__arm__) case _DRM_AGP: if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) { /* @@ -615,20 +616,31 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) break; } /* fall through to _DRM_FRAME_BUFFER... */ +#endif case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: offset = dev->driver->get_reg_ofs(dev); vma->vm_flags |= VM_IO; /* not in core dump */ vma->vm_page_prot = drm_io_prot(map->type, vma); +#if !defined(__arm__) if (io_remap_pfn_range(vma, vma->vm_start, (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; +#else + if (remap_pfn_range(vma, vma->vm_start, + (map->offset + offset) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; +#endif + DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," " offset = 0x%llx\n", map->type, vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset)); + vma->vm_ops = &drm_vm_ops; break; case _DRM_CONSISTENT: -- cgit v1.2.3 From 05269a3a5a78bb074413de495105d7a2686c4529 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:27 -0600 Subject: drm: Make sure the DRM offset matches the CPU The pgoff option in mmap() is defined as an unsigned long so the offset generated by DRM needs to fit into BITS_PER_LONG for the CPU in question. Signed-off-by: Jordan Crouse Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_gem.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 33dad3fa6043..8601b72b6f26 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -68,8 +68,18 @@ * We make up offsets for buffer objects so we can recognize them at * mmap time. */ + +/* pgoff in mmap is an unsigned long, so we need to make sure that + * the faked up offset will fit + */ + +#if BITS_PER_LONG == 64 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) +#else +#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1) +#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) +#endif /** * Initialize the GEM device fields -- cgit v1.2.3 From 867e359b97c970a60626d5d76bbe2a8fadbf38fb Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 28 May 2010 23:09:12 -0400 Subject: arch/tile: core support for Tilera 32-bit chips. This change is the core kernel support for TILEPro and TILE64 chips. No driver support (except the console driver) is included yet. This includes the relevant Linux headers in asm/; the low-level low-level "Tile architecture" headers in arch/, which are shared with the hypervisor, etc., and are build-system agnostic; and the relevant hypervisor headers in hv/. Signed-off-by: Chris Metcalf Acked-by: Arnd Bergmann Acked-by: FUJITA Tomonori Reviewed-by: Paul Mundt --- MAINTAINERS | 6 + arch/tile/Kbuild | 3 + arch/tile/Kconfig | 352 + arch/tile/Kconfig.debug | 43 + arch/tile/Makefile | 52 + arch/tile/configs/tile_defconfig | 1289 +++ arch/tile/include/arch/abi.h | 93 + arch/tile/include/arch/chip.h | 23 + arch/tile/include/arch/chip_tile64.h | 252 + arch/tile/include/arch/chip_tilepro.h | 252 + arch/tile/include/arch/interrupts.h | 19 + arch/tile/include/arch/interrupts_32.h | 304 + arch/tile/include/arch/sim_def.h | 512 + arch/tile/include/arch/spr_def.h | 19 + arch/tile/include/arch/spr_def_32.h | 162 + arch/tile/include/asm/Kbuild | 3 + arch/tile/include/asm/asm-offsets.h | 1 + arch/tile/include/asm/atomic.h | 159 + arch/tile/include/asm/atomic_32.h | 353 + arch/tile/include/asm/auxvec.h | 20 + arch/tile/include/asm/backtrace.h | 193 + arch/tile/include/asm/bitops.h | 126 + arch/tile/include/asm/bitops_32.h | 132 + arch/tile/include/asm/bitsperlong.h | 26 + arch/tile/include/asm/bug.h | 1 + arch/tile/include/asm/bugs.h | 1 + arch/tile/include/asm/byteorder.h | 1 + arch/tile/include/asm/cache.h | 50 + arch/tile/include/asm/cacheflush.h | 145 + arch/tile/include/asm/checksum.h | 24 + arch/tile/include/asm/compat.h | 308 + arch/tile/include/asm/cputime.h | 1 + arch/tile/include/asm/current.h | 31 + arch/tile/include/asm/delay.h | 34 + arch/tile/include/asm/device.h | 1 + arch/tile/include/asm/div64.h | 1 + arch/tile/include/asm/dma-mapping.h | 102 + arch/tile/include/asm/dma.h | 25 + arch/tile/include/asm/elf.h | 169 + arch/tile/include/asm/emergency-restart.h | 1 + arch/tile/include/asm/errno.h | 1 + arch/tile/include/asm/fcntl.h | 1 + arch/tile/include/asm/fixmap.h | 124 + arch/tile/include/asm/ftrace.h | 20 + arch/tile/include/asm/futex.h | 136 + arch/tile/include/asm/hardirq.h | 47 + arch/tile/include/asm/highmem.h | 73 + arch/tile/include/asm/homecache.h | 125 + arch/tile/include/asm/hugetlb.h | 109 + arch/tile/include/asm/hv_driver.h | 60 + arch/tile/include/asm/hw_irq.h | 18 + arch/tile/include/asm/ide.h | 25 + arch/tile/include/asm/io.h | 279 + arch/tile/include/asm/ioctl.h | 1 + arch/tile/include/asm/ioctls.h | 1 + arch/tile/include/asm/ipc.h | 1 + arch/tile/include/asm/ipcbuf.h | 1 + arch/tile/include/asm/irq.h | 37 + arch/tile/include/asm/irq_regs.h | 1 + arch/tile/include/asm/irqflags.h | 267 + arch/tile/include/asm/kdebug.h | 1 + arch/tile/include/asm/kexec.h | 53 + arch/tile/include/asm/kmap_types.h | 43 + arch/tile/include/asm/linkage.h | 51 + arch/tile/include/asm/local.h | 1 + arch/tile/include/asm/memprof.h | 33 + arch/tile/include/asm/mman.h | 40 + arch/tile/include/asm/mmu.h | 31 + arch/tile/include/asm/mmu_context.h | 131 + arch/tile/include/asm/mmzone.h | 81 + arch/tile/include/asm/module.h | 1 + arch/tile/include/asm/msgbuf.h | 1 + arch/tile/include/asm/mutex.h | 1 + arch/tile/include/asm/opcode-tile.h | 30 + arch/tile/include/asm/opcode-tile_32.h | 1597 +++ arch/tile/include/asm/opcode-tile_64.h | 1597 +++ arch/tile/include/asm/opcode_constants.h | 26 + arch/tile/include/asm/opcode_constants_32.h | 480 + arch/tile/include/asm/opcode_constants_64.h | 480 + arch/tile/include/asm/page.h | 334 + arch/tile/include/asm/param.h | 1 + arch/tile/include/asm/pci-bridge.h | 117 + arch/tile/include/asm/pci.h | 128 + arch/tile/include/asm/percpu.h | 24 + arch/tile/include/asm/pgalloc.h | 119 + arch/tile/include/asm/pgtable.h | 475 + arch/tile/include/asm/pgtable_32.h | 117 + arch/tile/include/asm/poll.h | 1 + arch/tile/include/asm/posix_types.h | 1 + arch/tile/include/asm/processor.h | 339 + arch/tile/include/asm/ptrace.h | 163 + arch/tile/include/asm/resource.h | 1 + arch/tile/include/asm/scatterlist.h | 22 + arch/tile/include/asm/sections.h | 37 + arch/tile/include/asm/sembuf.h | 1 + arch/tile/include/asm/setup.h | 32 + arch/tile/include/asm/shmbuf.h | 1 + arch/tile/include/asm/shmparam.h | 1 + arch/tile/include/asm/sigcontext.h | 27 + arch/tile/include/asm/sigframe.h | 33 + arch/tile/include/asm/siginfo.h | 30 + arch/tile/include/asm/signal.h | 31 + arch/tile/include/asm/smp.h | 126 + arch/tile/include/asm/socket.h | 1 + arch/tile/include/asm/sockios.h | 1 + arch/tile/include/asm/spinlock.h | 24 + arch/tile/include/asm/spinlock_32.h | 200 + arch/tile/include/asm/spinlock_types.h | 60 + arch/tile/include/asm/stack.h | 68 + arch/tile/include/asm/stat.h | 1 + arch/tile/include/asm/statfs.h | 1 + arch/tile/include/asm/string.h | 32 + arch/tile/include/asm/swab.h | 29 + arch/tile/include/asm/syscall.h | 79 + arch/tile/include/asm/syscalls.h | 60 + arch/tile/include/asm/system.h | 220 + arch/tile/include/asm/termbits.h | 1 + arch/tile/include/asm/termios.h | 1 + arch/tile/include/asm/thread_info.h | 165 + arch/tile/include/asm/timex.h | 47 + arch/tile/include/asm/tlb.h | 25 + arch/tile/include/asm/tlbflush.h | 128 + arch/tile/include/asm/topology.h | 85 + arch/tile/include/asm/traps.h | 36 + arch/tile/include/asm/types.h | 1 + arch/tile/include/asm/uaccess.h | 578 ++ arch/tile/include/asm/ucontext.h | 1 + arch/tile/include/asm/unaligned.h | 24 + arch/tile/include/asm/unistd.h | 47 + arch/tile/include/asm/user.h | 21 + arch/tile/include/asm/xor.h | 1 + arch/tile/include/hv/drv_pcie_rc_intf.h | 38 + arch/tile/include/hv/hypervisor.h | 2366 +++++ arch/tile/include/hv/syscall_public.h | 42 + arch/tile/kernel/Makefile | 16 + arch/tile/kernel/asm-offsets.c | 76 + arch/tile/kernel/backtrace.c | 634 ++ arch/tile/kernel/compat.c | 183 + arch/tile/kernel/compat_signal.c | 433 + arch/tile/kernel/early_printk.c | 109 + arch/tile/kernel/entry.S | 141 + arch/tile/kernel/head_32.S | 180 + arch/tile/kernel/hvglue.lds | 56 + arch/tile/kernel/init_task.c | 59 + arch/tile/kernel/intvec_32.S | 2006 ++++ arch/tile/kernel/irq.c | 227 + arch/tile/kernel/machine_kexec.c | 291 + arch/tile/kernel/messaging.c | 115 + arch/tile/kernel/module.c | 257 + arch/tile/kernel/pci-dma.c | 252 + arch/tile/kernel/proc.c | 91 + arch/tile/kernel/process.c | 647 ++ arch/tile/kernel/ptrace.c | 203 + arch/tile/kernel/reboot.c | 52 + arch/tile/kernel/regs_32.S | 145 + arch/tile/kernel/relocate_kernel.S | 280 + arch/tile/kernel/setup.c | 1497 +++ arch/tile/kernel/signal.c | 359 + arch/tile/kernel/single_step.c | 656 ++ arch/tile/kernel/smp.c | 202 + arch/tile/kernel/smpboot.c | 293 + arch/tile/kernel/stack.c | 485 + arch/tile/kernel/sys.c | 122 + arch/tile/kernel/tile-desc_32.c | 13826 ++++++++++++++++++++++++++ arch/tile/kernel/time.c | 220 + arch/tile/kernel/tlb.c | 97 + arch/tile/kernel/traps.c | 237 + arch/tile/kernel/vmlinux.lds.S | 98 + arch/tile/lib/Makefile | 16 + arch/tile/lib/__invalidate_icache.S | 106 + arch/tile/lib/atomic_32.c | 347 + arch/tile/lib/atomic_asm_32.S | 197 + arch/tile/lib/checksum.c | 102 + arch/tile/lib/cpumask.c | 51 + arch/tile/lib/delay.c | 34 + arch/tile/lib/exports.c | 78 + arch/tile/lib/mb_incoherent.S | 34 + arch/tile/lib/memchr_32.c | 68 + arch/tile/lib/memcpy_32.S | 628 ++ arch/tile/lib/memcpy_tile64.c | 271 + arch/tile/lib/memmove_32.c | 63 + arch/tile/lib/memset_32.c | 274 + arch/tile/lib/spinlock_32.c | 221 + arch/tile/lib/spinlock_common.h | 64 + arch/tile/lib/strchr_32.c | 66 + arch/tile/lib/strlen_32.c | 36 + arch/tile/lib/uaccess.c | 31 + arch/tile/lib/usercopy_32.S | 223 + arch/tile/mm/Makefile | 9 + arch/tile/mm/elf.c | 164 + arch/tile/mm/extable.c | 30 + arch/tile/mm/fault.c | 905 ++ arch/tile/mm/highmem.c | 328 + arch/tile/mm/homecache.c | 445 + arch/tile/mm/hugetlbpage.c | 343 + arch/tile/mm/init.c | 1082 ++ arch/tile/mm/migrate.h | 50 + arch/tile/mm/migrate_32.S | 211 + arch/tile/mm/mmap.c | 75 + arch/tile/mm/pgtable.c | 566 ++ drivers/char/Makefile | 1 + drivers/char/hvc_tile.c | 67 + 202 files changed, 49569 insertions(+) create mode 100644 arch/tile/Kbuild create mode 100644 arch/tile/Kconfig create mode 100644 arch/tile/Kconfig.debug create mode 100644 arch/tile/Makefile create mode 100644 arch/tile/configs/tile_defconfig create mode 100644 arch/tile/include/arch/abi.h create mode 100644 arch/tile/include/arch/chip.h create mode 100644 arch/tile/include/arch/chip_tile64.h create mode 100644 arch/tile/include/arch/chip_tilepro.h create mode 100644 arch/tile/include/arch/interrupts.h create mode 100644 arch/tile/include/arch/interrupts_32.h create mode 100644 arch/tile/include/arch/sim_def.h create mode 100644 arch/tile/include/arch/spr_def.h create mode 100644 arch/tile/include/arch/spr_def_32.h create mode 100644 arch/tile/include/asm/Kbuild create mode 100644 arch/tile/include/asm/asm-offsets.h create mode 100644 arch/tile/include/asm/atomic.h create mode 100644 arch/tile/include/asm/atomic_32.h create mode 100644 arch/tile/include/asm/auxvec.h create mode 100644 arch/tile/include/asm/backtrace.h create mode 100644 arch/tile/include/asm/bitops.h create mode 100644 arch/tile/include/asm/bitops_32.h create mode 100644 arch/tile/include/asm/bitsperlong.h create mode 100644 arch/tile/include/asm/bug.h create mode 100644 arch/tile/include/asm/bugs.h create mode 100644 arch/tile/include/asm/byteorder.h create mode 100644 arch/tile/include/asm/cache.h create mode 100644 arch/tile/include/asm/cacheflush.h create mode 100644 arch/tile/include/asm/checksum.h create mode 100644 arch/tile/include/asm/compat.h create mode 100644 arch/tile/include/asm/cputime.h create mode 100644 arch/tile/include/asm/current.h create mode 100644 arch/tile/include/asm/delay.h create mode 100644 arch/tile/include/asm/device.h create mode 100644 arch/tile/include/asm/div64.h create mode 100644 arch/tile/include/asm/dma-mapping.h create mode 100644 arch/tile/include/asm/dma.h create mode 100644 arch/tile/include/asm/elf.h create mode 100644 arch/tile/include/asm/emergency-restart.h create mode 100644 arch/tile/include/asm/errno.h create mode 100644 arch/tile/include/asm/fcntl.h create mode 100644 arch/tile/include/asm/fixmap.h create mode 100644 arch/tile/include/asm/ftrace.h create mode 100644 arch/tile/include/asm/futex.h create mode 100644 arch/tile/include/asm/hardirq.h create mode 100644 arch/tile/include/asm/highmem.h create mode 100644 arch/tile/include/asm/homecache.h create mode 100644 arch/tile/include/asm/hugetlb.h create mode 100644 arch/tile/include/asm/hv_driver.h create mode 100644 arch/tile/include/asm/hw_irq.h create mode 100644 arch/tile/include/asm/ide.h create mode 100644 arch/tile/include/asm/io.h create mode 100644 arch/tile/include/asm/ioctl.h create mode 100644 arch/tile/include/asm/ioctls.h create mode 100644 arch/tile/include/asm/ipc.h create mode 100644 arch/tile/include/asm/ipcbuf.h create mode 100644 arch/tile/include/asm/irq.h create mode 100644 arch/tile/include/asm/irq_regs.h create mode 100644 arch/tile/include/asm/irqflags.h create mode 100644 arch/tile/include/asm/kdebug.h create mode 100644 arch/tile/include/asm/kexec.h create mode 100644 arch/tile/include/asm/kmap_types.h create mode 100644 arch/tile/include/asm/linkage.h create mode 100644 arch/tile/include/asm/local.h create mode 100644 arch/tile/include/asm/memprof.h create mode 100644 arch/tile/include/asm/mman.h create mode 100644 arch/tile/include/asm/mmu.h create mode 100644 arch/tile/include/asm/mmu_context.h create mode 100644 arch/tile/include/asm/mmzone.h create mode 100644 arch/tile/include/asm/module.h create mode 100644 arch/tile/include/asm/msgbuf.h create mode 100644 arch/tile/include/asm/mutex.h create mode 100644 arch/tile/include/asm/opcode-tile.h create mode 100644 arch/tile/include/asm/opcode-tile_32.h create mode 100644 arch/tile/include/asm/opcode-tile_64.h create mode 100644 arch/tile/include/asm/opcode_constants.h create mode 100644 arch/tile/include/asm/opcode_constants_32.h create mode 100644 arch/tile/include/asm/opcode_constants_64.h create mode 100644 arch/tile/include/asm/page.h create mode 100644 arch/tile/include/asm/param.h create mode 100644 arch/tile/include/asm/pci-bridge.h create mode 100644 arch/tile/include/asm/pci.h create mode 100644 arch/tile/include/asm/percpu.h create mode 100644 arch/tile/include/asm/pgalloc.h create mode 100644 arch/tile/include/asm/pgtable.h create mode 100644 arch/tile/include/asm/pgtable_32.h create mode 100644 arch/tile/include/asm/poll.h create mode 100644 arch/tile/include/asm/posix_types.h create mode 100644 arch/tile/include/asm/processor.h create mode 100644 arch/tile/include/asm/ptrace.h create mode 100644 arch/tile/include/asm/resource.h create mode 100644 arch/tile/include/asm/scatterlist.h create mode 100644 arch/tile/include/asm/sections.h create mode 100644 arch/tile/include/asm/sembuf.h create mode 100644 arch/tile/include/asm/setup.h create mode 100644 arch/tile/include/asm/shmbuf.h create mode 100644 arch/tile/include/asm/shmparam.h create mode 100644 arch/tile/include/asm/sigcontext.h create mode 100644 arch/tile/include/asm/sigframe.h create mode 100644 arch/tile/include/asm/siginfo.h create mode 100644 arch/tile/include/asm/signal.h create mode 100644 arch/tile/include/asm/smp.h create mode 100644 arch/tile/include/asm/socket.h create mode 100644 arch/tile/include/asm/sockios.h create mode 100644 arch/tile/include/asm/spinlock.h create mode 100644 arch/tile/include/asm/spinlock_32.h create mode 100644 arch/tile/include/asm/spinlock_types.h create mode 100644 arch/tile/include/asm/stack.h create mode 100644 arch/tile/include/asm/stat.h create mode 100644 arch/tile/include/asm/statfs.h create mode 100644 arch/tile/include/asm/string.h create mode 100644 arch/tile/include/asm/swab.h create mode 100644 arch/tile/include/asm/syscall.h create mode 100644 arch/tile/include/asm/syscalls.h create mode 100644 arch/tile/include/asm/system.h create mode 100644 arch/tile/include/asm/termbits.h create mode 100644 arch/tile/include/asm/termios.h create mode 100644 arch/tile/include/asm/thread_info.h create mode 100644 arch/tile/include/asm/timex.h create mode 100644 arch/tile/include/asm/tlb.h create mode 100644 arch/tile/include/asm/tlbflush.h create mode 100644 arch/tile/include/asm/topology.h create mode 100644 arch/tile/include/asm/traps.h create mode 100644 arch/tile/include/asm/types.h create mode 100644 arch/tile/include/asm/uaccess.h create mode 100644 arch/tile/include/asm/ucontext.h create mode 100644 arch/tile/include/asm/unaligned.h create mode 100644 arch/tile/include/asm/unistd.h create mode 100644 arch/tile/include/asm/user.h create mode 100644 arch/tile/include/asm/xor.h create mode 100644 arch/tile/include/hv/drv_pcie_rc_intf.h create mode 100644 arch/tile/include/hv/hypervisor.h create mode 100644 arch/tile/include/hv/syscall_public.h create mode 100644 arch/tile/kernel/Makefile create mode 100644 arch/tile/kernel/asm-offsets.c create mode 100644 arch/tile/kernel/backtrace.c create mode 100644 arch/tile/kernel/compat.c create mode 100644 arch/tile/kernel/compat_signal.c create mode 100644 arch/tile/kernel/early_printk.c create mode 100644 arch/tile/kernel/entry.S create mode 100644 arch/tile/kernel/head_32.S create mode 100644 arch/tile/kernel/hvglue.lds create mode 100644 arch/tile/kernel/init_task.c create mode 100644 arch/tile/kernel/intvec_32.S create mode 100644 arch/tile/kernel/irq.c create mode 100644 arch/tile/kernel/machine_kexec.c create mode 100644 arch/tile/kernel/messaging.c create mode 100644 arch/tile/kernel/module.c create mode 100644 arch/tile/kernel/pci-dma.c create mode 100644 arch/tile/kernel/proc.c create mode 100644 arch/tile/kernel/process.c create mode 100644 arch/tile/kernel/ptrace.c create mode 100644 arch/tile/kernel/reboot.c create mode 100644 arch/tile/kernel/regs_32.S create mode 100644 arch/tile/kernel/relocate_kernel.S create mode 100644 arch/tile/kernel/setup.c create mode 100644 arch/tile/kernel/signal.c create mode 100644 arch/tile/kernel/single_step.c create mode 100644 arch/tile/kernel/smp.c create mode 100644 arch/tile/kernel/smpboot.c create mode 100644 arch/tile/kernel/stack.c create mode 100644 arch/tile/kernel/sys.c create mode 100644 arch/tile/kernel/tile-desc_32.c create mode 100644 arch/tile/kernel/time.c create mode 100644 arch/tile/kernel/tlb.c create mode 100644 arch/tile/kernel/traps.c create mode 100644 arch/tile/kernel/vmlinux.lds.S create mode 100644 arch/tile/lib/Makefile create mode 100644 arch/tile/lib/__invalidate_icache.S create mode 100644 arch/tile/lib/atomic_32.c create mode 100644 arch/tile/lib/atomic_asm_32.S create mode 100644 arch/tile/lib/checksum.c create mode 100644 arch/tile/lib/cpumask.c create mode 100644 arch/tile/lib/delay.c create mode 100644 arch/tile/lib/exports.c create mode 100644 arch/tile/lib/mb_incoherent.S create mode 100644 arch/tile/lib/memchr_32.c create mode 100644 arch/tile/lib/memcpy_32.S create mode 100644 arch/tile/lib/memcpy_tile64.c create mode 100644 arch/tile/lib/memmove_32.c create mode 100644 arch/tile/lib/memset_32.c create mode 100644 arch/tile/lib/spinlock_32.c create mode 100644 arch/tile/lib/spinlock_common.h create mode 100644 arch/tile/lib/strchr_32.c create mode 100644 arch/tile/lib/strlen_32.c create mode 100644 arch/tile/lib/uaccess.c create mode 100644 arch/tile/lib/usercopy_32.S create mode 100644 arch/tile/mm/Makefile create mode 100644 arch/tile/mm/elf.c create mode 100644 arch/tile/mm/extable.c create mode 100644 arch/tile/mm/fault.c create mode 100644 arch/tile/mm/highmem.c create mode 100644 arch/tile/mm/homecache.c create mode 100644 arch/tile/mm/hugetlbpage.c create mode 100644 arch/tile/mm/init.c create mode 100644 arch/tile/mm/migrate.h create mode 100644 arch/tile/mm/migrate_32.S create mode 100644 arch/tile/mm/mmap.c create mode 100644 arch/tile/mm/pgtable.c create mode 100644 drivers/char/hvc_tile.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index a73dd8030afa..7a0baf8fd18c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5572,6 +5572,12 @@ F: include/linux/tipc*.h F: include/net/tipc/ F: net/tipc/ +TILE ARCHITECTURE +M: Chris Metcalf +W: http://www.tilera.com/scm/ +S: Supported +F: arch/tile/ + TLAN NETWORK DRIVER M: Samuel Chessman L: tlan-devel@lists.sourceforge.net (subscribers-only) diff --git a/arch/tile/Kbuild b/arch/tile/Kbuild new file mode 100644 index 000000000000..a9b922716092 --- /dev/null +++ b/arch/tile/Kbuild @@ -0,0 +1,3 @@ + +obj-y += kernel/ +obj-y += mm/ diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig new file mode 100644 index 000000000000..290ef4161939 --- /dev/null +++ b/arch/tile/Kconfig @@ -0,0 +1,352 @@ +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/config-language.txt. + +config MMU + def_bool y + +config GENERIC_CSUM + def_bool y + +config GENERIC_HARDIRQS + def_bool y + +config GENERIC_HARDIRQS_NO__DO_IRQ + def_bool y + +config GENERIC_IRQ_PROBE + def_bool y + +config GENERIC_PENDING_IRQ + def_bool y + depends on GENERIC_HARDIRQS && SMP + +config SEMAPHORE_SLEEPERS + def_bool y + +config HAVE_ARCH_ALLOC_REMAP + def_bool y + +config HAVE_SETUP_PER_CPU_AREA + def_bool y + +config NEED_PER_CPU_PAGE_FIRST_CHUNK + def_bool y + +config SYS_SUPPORTS_HUGETLBFS + def_bool y + +config GENERIC_TIME + def_bool y + +config GENERIC_CLOCKEVENTS + def_bool y + +# FIXME: tilegx can implement a more efficent rwsem. +config RWSEM_GENERIC_SPINLOCK + def_bool y + +# We have a very flat architecture from a migration point of view, +# so save boot time by presetting this (particularly useful on tile-sim). +config DEFAULT_MIGRATION_COST + int + default "10000000" + +# We only support gcc 4.4 and above, so this should work. +config ARCH_SUPPORTS_OPTIMIZED_INLINING + def_bool y + +config ARCH_PHYS_ADDR_T_64BIT + def_bool y + +config LOCKDEP_SUPPORT + def_bool y + +config STACKTRACE_SUPPORT + def_bool y + select STACKTRACE + +# We use discontigmem for now; at some point we may want to switch +# to sparsemem (Tilera bug 7996). +config ARCH_DISCONTIGMEM_ENABLE + def_bool y + +config ARCH_DISCONTIGMEM_DEFAULT + def_bool y + +config TRACE_IRQFLAGS_SUPPORT + def_bool y + +config STRICT_DEVMEM + def_bool y + +# SMP is required for Tilera Linux. +config SMP + def_bool y + +# Allow checking for compile-time determined overflow errors in +# copy_from_user(). There are still unprovable places in the +# generic code as of 2.6.34, so this option is not really compatible +# with -Werror, which is more useful in general. +config DEBUG_COPY_FROM_USER + def_bool n + +config HVC_TILE + select HVC_DRIVER + def_bool y + +config TILE + def_bool y + select GENERIC_FIND_FIRST_BIT + select GENERIC_FIND_NEXT_BIT + select USE_GENERIC_SMP_HELPERS + select CC_OPTIMIZE_FOR_SIZE + +# FIXME: investigate whether we need/want these options. +# select HAVE_IOREMAP_PROT +# select HAVE_OPTPROBES +# select HAVE_REGS_AND_STACK_ACCESS_API +# select HAVE_HW_BREAKPOINT +# select PERF_EVENTS +# select HAVE_USER_RETURN_NOTIFIER +# config NO_BOOTMEM +# config ARCH_SUPPORTS_DEBUG_PAGEALLOC +# config HUGETLB_PAGE_SIZE_VARIABLE + + +mainmenu "Linux/TILE Kernel Configuration" + +# Please note: TILE-Gx support is not yet finalized; this is +# the preliminary support. TILE-Gx drivers are only provided +# with the alpha or beta test versions for Tilera customers. +config TILEGX + depends on EXPERIMENTAL + bool "Building with TILE-Gx (64-bit) compiler and toolchain" + +config 64BIT + depends on TILEGX + def_bool y + +config ARCH_DEFCONFIG + string + default "arch/tile/configs/tile_defconfig" if !TILEGX + default "arch/tile/configs/tilegx_defconfig" if TILEGX + +source "init/Kconfig" + +menu "Tilera-specific configuration" + +config NR_CPUS + int "Maximum number of tiles (2-255)" + range 2 255 + depends on SMP + default "64" + ---help--- + Building with 64 is the recommended value, but a slightly + smaller kernel memory footprint results from using a smaller + value on chips with fewer tiles. + +source "kernel/time/Kconfig" + +source "kernel/Kconfig.hz" + +config KEXEC + bool "kexec system call" + ---help--- + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is independent of the system firmware. It is used + to implement the "mboot" Tilera booter. + + The name comes from the similarity to the exec system call. + +config COMPAT + bool "Support 32-bit TILE-Gx binaries in addition to 64-bit" + depends on TILEGX + select COMPAT_BINFMT_ELF + default y + ---help--- + If enabled, the kernel will support running TILE-Gx binaries + that were built with the -m32 option. + +config SYSVIPC_COMPAT + def_bool y + depends on COMPAT && SYSVIPC + +# We do not currently support disabling HIGHMEM on tile64 and tilepro. +config HIGHMEM + bool # "Support for more than 512 MB of RAM" + default !TILEGX + ---help--- + Linux can use the full amount of RAM in the system by + default. However, the address space of TILE processors is + only 4 Gigabytes large. That means that, if you have a large + amount of physical memory, not all of it can be "permanently + mapped" by the kernel. The physical memory that's not + permanently mapped is called "high memory". + + If you are compiling a kernel which will never run on a + machine with more than 512 MB total physical RAM, answer + "false" here. This will result in the kernel mapping all of + physical memory into the top 1 GB of virtual memory space. + + If unsure, say "true". + +# We do not currently support disabling NUMA. +config NUMA + bool # "NUMA Memory Allocation and Scheduler Support" + depends on SMP && DISCONTIGMEM + default y + ---help--- + NUMA memory allocation is required for TILE processors + unless booting with memory striping enabled in the + hypervisor, or with only a single memory controller. + It is recommended that this option always be enabled. + +config NODES_SHIFT + int "Log base 2 of the max number of memory controllers" + default 2 + depends on NEED_MULTIPLE_NODES + ---help--- + By default, 2, i.e. 2^2 == 4 DDR2 controllers. + In a system with more controllers, this value should be raised. + +# Need 16MB areas to enable hugetlb +# See build-time check in arch/tile/mm/init.c. +config FORCE_MAX_ZONEORDER + int + default 9 + +choice + depends on !TILEGX + prompt "Memory split" if EMBEDDED + default VMSPLIT_3G + ---help--- + Select the desired split between kernel and user memory. + + If the address range available to the kernel is less than the + physical memory installed, the remaining memory will be available + as "high memory". Accessing high memory is a little more costly + than low memory, as it needs to be mapped into the kernel first. + Note that increasing the kernel address space limits the range + available to user programs, making the address space there + tighter. Selecting anything other than the default 3G/1G split + will also likely make your kernel incompatible with binary-only + kernel modules. + + If you are not absolutely sure what you are doing, leave this + option alone! + + config VMSPLIT_375G + bool "3.75G/0.25G user/kernel split (no kernel networking)" + config VMSPLIT_35G + bool "3.5G/0.5G user/kernel split" + config VMSPLIT_3G + bool "3G/1G user/kernel split" + config VMSPLIT_3G_OPT + bool "3G/1G user/kernel split (for full 1G low memory)" + config VMSPLIT_2G + bool "2G/2G user/kernel split" + config VMSPLIT_1G + bool "1G/3G user/kernel split" +endchoice + +config PAGE_OFFSET + hex + default 0xF0000000 if VMSPLIT_375G + default 0xE0000000 if VMSPLIT_35G + default 0xB0000000 if VMSPLIT_3G_OPT + default 0x80000000 if VMSPLIT_2G + default 0x40000000 if VMSPLIT_1G + default 0xC0000000 + +source "mm/Kconfig" + +config CMDLINE_BOOL + bool "Built-in kernel command line" + default n + ---help--- + Allow for specifying boot arguments to the kernel at + build time. On some systems (e.g. embedded ones), it is + necessary or convenient to provide some or all of the + kernel boot arguments with the kernel itself (that is, + to not rely on the boot loader to provide them.) + + To compile command line arguments into the kernel, + set this option to 'Y', then fill in the + the boot arguments in CONFIG_CMDLINE. + + Systems with fully functional boot loaders (e.g. mboot, or + if booting over PCI) should leave this option set to 'N'. + +config CMDLINE + string "Built-in kernel command string" + depends on CMDLINE_BOOL + default "" + ---help--- + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, it is appended to this string to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_OVERRIDE + bool "Built-in command line overrides boot loader arguments" + default n + depends on CMDLINE_BOOL + ---help--- + Set this option to 'Y' to have the kernel ignore the boot loader + command line, and use ONLY the built-in command line. + + This is used to work around broken boot loaders. This should + be set to 'N' under normal conditions. + +config VMALLOC_RESERVE + hex + default 0x1000000 + +endmenu # Tilera-specific configuration + +menu "Bus options" + +config NO_IOMEM + def_bool !PCI + +config NO_IOPORT + def_bool !PCI + +source "drivers/pci/Kconfig" + +source "drivers/pci/hotplug/Kconfig" + +endmenu + +menu "Executable file formats" + +# only elf supported +config KCORE_ELF + def_bool y + depends on PROC_FS + +source "fs/Kconfig.binfmt" + +endmenu + +source "net/Kconfig" + +source "drivers/Kconfig" + +source "fs/Kconfig" + +source "arch/tile/Kconfig.debug" + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" diff --git a/arch/tile/Kconfig.debug b/arch/tile/Kconfig.debug new file mode 100644 index 000000000000..a81f0fbf7e60 --- /dev/null +++ b/arch/tile/Kconfig.debug @@ -0,0 +1,43 @@ +menu "Kernel hacking" + +source "lib/Kconfig.debug" + +config EARLY_PRINTK + bool "Early printk" if EMBEDDED && DEBUG_KERNEL + default y + help + Write kernel log output directly via the hypervisor console. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd. You should normally N here, + unless you want to debug such a crash. + +config DEBUG_STACKOVERFLOW + bool "Check for stack overflows" + depends on DEBUG_KERNEL + help + This option will cause messages to be printed if free stack space + drops below a certain limit. + +config DEBUG_STACK_USAGE + bool "Stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. + +config DEBUG_EXTRA_FLAGS + string "Additional compiler arguments when building with '-g'" + depends on DEBUG_INFO + default "" + help + Debug info can be large, and flags like + `-femit-struct-debug-baseonly' can reduce the kernel file + size and build time noticeably. Such flags are often + helpful if the main use of debug info is line number info. + +endmenu diff --git a/arch/tile/Makefile b/arch/tile/Makefile new file mode 100644 index 000000000000..07c4318c0629 --- /dev/null +++ b/arch/tile/Makefile @@ -0,0 +1,52 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture + +ifeq ($(CROSS_COMPILE),) +# If building with TILERA_ROOT set (i.e. using the Tilera Multicore +# Development Environment) we can set CROSS_COMPILE based on that. +ifdef TILERA_ROOT +CROSS_COMPILE = $(TILERA_ROOT)/bin/tile- +endif +endif + +# If we're not cross-compiling, make sure we're on the right architecture. +ifeq ($(CROSS_COMPILE),) +HOST_ARCH = $(shell uname -m) +ifneq ($(HOST_ARCH),$(ARCH)) +$(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH)) +endif +endif + + +KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) + +LIBGCC_PATH := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) + +# Provide the path to use for "make defconfig". +KBUILD_DEFCONFIG := $(ARCH)_defconfig + +# Used as a file extension when useful, e.g. head_$(BITS).o +# Not needed for (e.g.) "$(CC) -m32" since the compiler automatically +# uses the right default anyway. +export BITS +ifeq ($(CONFIG_TILEGX),y) +BITS := 64 +else +BITS := 32 +endif + +head-y := arch/tile/kernel/head_$(BITS).o + +libs-y += arch/tile/lib/ +libs-y += $(LIBGCC_PATH) + + +# See arch/tile/Kbuild for content of core part of the kernel +core-y += arch/tile/ diff --git a/arch/tile/configs/tile_defconfig b/arch/tile/configs/tile_defconfig new file mode 100644 index 000000000000..74a5be39e8f2 --- /dev/null +++ b/arch/tile/configs/tile_defconfig @@ -0,0 +1,1289 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.34 +# Fri May 28 17:51:43 2010 +# +CONFIG_MMU=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_ZONE_DMA=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_HAVE_ARCH_ALLOC_REMAP=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_DEFAULT_MIGRATION_COST=10000000 +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_STRICT_DEVMEM=y +CONFIG_SMP=y +CONFIG_WERROR=y +# CONFIG_DEBUG_COPY_FROM_USER is not set +CONFIG_SERIAL_CONSOLE=y +CONFIG_HVC_TILE=y +CONFIG_TILE=y +# CONFIG_TILEGX is not set +CONFIG_ARCH_DEFCONFIG="arch/tile/configs/tile_defconfig" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="usr/contents.txt" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set +# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set +# CONFIG_INITRAMFS_COMPRESSION_LZO is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +CONFIG_USE_GENERIC_SMP_HELPERS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y + +# +# Tilera-specific configuration +# +CONFIG_NR_CPUS=64 +CONFIG_HOMECACHE=y +CONFIG_DATAPLANE=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +CONFIG_HIGHMEM=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=2 +CONFIG_FORCE_MAX_ZONEORDER=9 +# CONFIG_VMSPLIT_375G is not set +# CONFIG_VMSPLIT_35G is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_3G_OPT is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_DISCONTIGMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_FEEDBACK_COLLECT is not set +CONFIG_FEEDBACK_USE="" +# CONFIG_HUGEVMAP is not set +CONFIG_VMALLOC_RESERVE=0x1000000 +CONFIG_HARDWALL=y +CONFIG_MEMPROF=y +CONFIG_XGBE_MAIN=y +CONFIG_NET_TILE=y +CONFIG_PSEUDO_NAPI=y +CONFIG_TILEPCI_ENDP=y +CONFIG_TILE_IDE_GPIO=y +CONFIG_TILE_SOFTUART=y + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_DEBUG=y +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_DS1682 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set +CONFIG_HAVE_IDE=y +CONFIG_IDE=y + +# +# Please see Documentation/ide/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_PLATFORM is not set + +# +# PCI IDE chipsets support +# +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8172 is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_IDEDMA is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y +# CONFIG_SATA_AHCI is not set +CONFIG_SATA_SIL24=y +CONFIG_ATA_SFF=y +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_SCH is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# You can enable one or both FireWire driver stacks. +# + +# +# The newer stack is recommended. +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_NET_ETHERNET is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +CONFIG_E1000E=y +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_HVC_DRIVER=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +# CONFIG_RTC_INTF_SYSFS is not set +# CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_SAMPLES is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_EXTRA_FLAGS="-femit-struct-debug-baseonly" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/tile/include/arch/abi.h b/arch/tile/include/arch/abi.h new file mode 100644 index 000000000000..7cdc47b3e02a --- /dev/null +++ b/arch/tile/include/arch/abi.h @@ -0,0 +1,93 @@ +// Copyright 2010 Tilera Corporation. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, version 2. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or +// NON INFRINGEMENT. See the GNU General Public License for +// more details. + +//! @file +//! +//! ABI-related register definitions helpful when writing assembly code. +//! + +#ifndef __ARCH_ABI_H__ +#define __ARCH_ABI_H__ + +#include + +// Registers 0 - 55 are "normal", but some perform special roles. + +#define TREG_FP 52 /**< Frame pointer. */ +#define TREG_TP 53 /**< Thread pointer. */ +#define TREG_SP 54 /**< Stack pointer. */ +#define TREG_LR 55 /**< Link to calling function PC. */ + +/** Index of last normal general-purpose register. */ +#define TREG_LAST_GPR 55 + +// Registers 56 - 62 are "special" network registers. + +#define TREG_SN 56 /**< Static network access. */ +#define TREG_IDN0 57 /**< IDN demux 0 access. */ +#define TREG_IDN1 58 /**< IDN demux 1 access. */ +#define TREG_UDN0 59 /**< UDN demux 0 access. */ +#define TREG_UDN1 60 /**< UDN demux 1 access. */ +#define TREG_UDN2 61 /**< UDN demux 2 access. */ +#define TREG_UDN3 62 /**< UDN demux 3 access. */ + +// Register 63 is the "special" zero register. + +#define TREG_ZERO 63 /**< "Zero" register; always reads as "0". */ + + +/** By convention, this register is used to hold the syscall number. */ +#define TREG_SYSCALL_NR 10 + +/** Name of register that holds the syscall number, for use in assembly. */ +#define TREG_SYSCALL_NR_NAME r10 + + +//! The ABI requires callers to allocate a caller state save area of +//! this many bytes at the bottom of each stack frame. +//! +#ifdef __tile__ +#define C_ABI_SAVE_AREA_SIZE (2 * __SIZEOF_POINTER__) +#endif + +//! The operand to an 'info' opcode directing the backtracer to not +//! try to find the calling frame. +//! +#define INFO_OP_CANNOT_BACKTRACE 2 + +#ifndef __ASSEMBLER__ +#if CHIP_WORD_SIZE() > 32 + +//! Unsigned type that can hold a register. +typedef unsigned long long uint_reg_t; + +//! Signed type that can hold a register. +typedef long long int_reg_t; + +//! String prefix to use for printf(). +#define INT_REG_FMT "ll" + +#elif !defined(__LP64__) /* avoid confusion with LP64 cross-build tools */ + +//! Unsigned type that can hold a register. +typedef unsigned long uint_reg_t; + +//! Signed type that can hold a register. +typedef long int_reg_t; + +//! String prefix to use for printf(). +#define INT_REG_FMT "l" + +#endif +#endif /* __ASSEMBLER__ */ + +#endif // !__ARCH_ABI_H__ diff --git a/arch/tile/include/arch/chip.h b/arch/tile/include/arch/chip.h new file mode 100644 index 000000000000..926d3db0e91e --- /dev/null +++ b/arch/tile/include/arch/chip.h @@ -0,0 +1,23 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#if __tile_chip__ == 0 +#include +#elif __tile_chip__ == 1 +#include +#elif defined(__tilegx__) +#include +#else +#error Unexpected Tilera chip type +#endif diff --git a/arch/tile/include/arch/chip_tile64.h b/arch/tile/include/arch/chip_tile64.h new file mode 100644 index 000000000000..18b5bc8e563f --- /dev/null +++ b/arch/tile/include/arch/chip_tile64.h @@ -0,0 +1,252 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* + * @file + * Global header file. + * This header file specifies defines for TILE64. + */ + +#ifndef __ARCH_CHIP_H__ +#define __ARCH_CHIP_H__ + +/** Specify chip version. + * When possible, prefer the CHIP_xxx symbols below for future-proofing. + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip__ symbol. + */ +#define TILE_CHIP 0 + +/** Specify chip revision. + * This provides for the case of a respin of a particular chip type; + * the normal value for this symbol is "0". + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip_rev__ symbol. + */ +#define TILE_CHIP_REV 0 + +/** The name of this architecture. */ +#define CHIP_ARCH_NAME "tile64" + +/** The ELF e_machine type for binaries for this chip. */ +#define CHIP_ELF_TYPE() EM_TILE64 + +/** The alternate ELF e_machine type for binaries for this chip. */ +#define CHIP_COMPAT_ELF_TYPE() 0x2506 + +/** What is the native word size of the machine? */ +#define CHIP_WORD_SIZE() 32 + +/** How many bits of a virtual address are used. Extra bits must be + * the sign extension of the low bits. + */ +#define CHIP_VA_WIDTH() 32 + +/** How many bits are in a physical address? */ +#define CHIP_PA_WIDTH() 36 + +/** Size of the L2 cache, in bytes. */ +#define CHIP_L2_CACHE_SIZE() 65536 + +/** Log size of an L2 cache line in bytes. */ +#define CHIP_L2_LOG_LINE_SIZE() 6 + +/** Size of an L2 cache line, in bytes. */ +#define CHIP_L2_LINE_SIZE() (1 << CHIP_L2_LOG_LINE_SIZE()) + +/** Associativity of the L2 cache. */ +#define CHIP_L2_ASSOC() 2 + +/** Size of the L1 data cache, in bytes. */ +#define CHIP_L1D_CACHE_SIZE() 8192 + +/** Log size of an L1 data cache line in bytes. */ +#define CHIP_L1D_LOG_LINE_SIZE() 4 + +/** Size of an L1 data cache line, in bytes. */ +#define CHIP_L1D_LINE_SIZE() (1 << CHIP_L1D_LOG_LINE_SIZE()) + +/** Associativity of the L1 data cache. */ +#define CHIP_L1D_ASSOC() 2 + +/** Size of the L1 instruction cache, in bytes. */ +#define CHIP_L1I_CACHE_SIZE() 8192 + +/** Log size of an L1 instruction cache line in bytes. */ +#define CHIP_L1I_LOG_LINE_SIZE() 6 + +/** Size of an L1 instruction cache line, in bytes. */ +#define CHIP_L1I_LINE_SIZE() (1 << CHIP_L1I_LOG_LINE_SIZE()) + +/** Associativity of the L1 instruction cache. */ +#define CHIP_L1I_ASSOC() 1 + +/** Stride with which flush instructions must be issued. */ +#define CHIP_FLUSH_STRIDE() CHIP_L2_LINE_SIZE() + +/** Stride with which inv instructions must be issued. */ +#define CHIP_INV_STRIDE() CHIP_L1D_LINE_SIZE() + +/** Stride with which finv instructions must be issued. */ +#define CHIP_FINV_STRIDE() CHIP_L1D_LINE_SIZE() + +/** Can the local cache coherently cache data that is homed elsewhere? */ +#define CHIP_HAS_COHERENT_LOCAL_CACHE() 0 + +/** How many simultaneous outstanding victims can the L2 cache have? */ +#define CHIP_MAX_OUTSTANDING_VICTIMS() 2 + +/** Does the TLB support the NC and NOALLOC bits? */ +#define CHIP_HAS_NC_AND_NOALLOC_BITS() 0 + +/** Does the chip support hash-for-home caching? */ +#define CHIP_HAS_CBOX_HOME_MAP() 0 + +/** Number of entries in the chip's home map tables. */ +/* #define CHIP_CBOX_HOME_MAP_SIZE() -- does not apply to chip 0 */ + +/** Do uncacheable requests miss in the cache regardless of whether + * there is matching data? */ +#define CHIP_HAS_ENFORCED_UNCACHEABLE_REQUESTS() 0 + +/** Does the mf instruction wait for victims? */ +#define CHIP_HAS_MF_WAITS_FOR_VICTIMS() 1 + +/** Does the chip have an "inv" instruction that doesn't also flush? */ +#define CHIP_HAS_INV() 0 + +/** Does the chip have a "wh64" instruction? */ +#define CHIP_HAS_WH64() 0 + +/** Does this chip have a 'dword_align' instruction? */ +#define CHIP_HAS_DWORD_ALIGN() 0 + +/** Number of performance counters. */ +#define CHIP_PERFORMANCE_COUNTERS() 2 + +/** Does this chip have auxiliary performance counters? */ +#define CHIP_HAS_AUX_PERF_COUNTERS() 0 + +/** Is the CBOX_MSR1 SPR supported? */ +#define CHIP_HAS_CBOX_MSR1() 0 + +/** Is the TILE_RTF_HWM SPR supported? */ +#define CHIP_HAS_TILE_RTF_HWM() 0 + +/** Is the TILE_WRITE_PENDING SPR supported? */ +#define CHIP_HAS_TILE_WRITE_PENDING() 0 + +/** Is the PROC_STATUS SPR supported? */ +#define CHIP_HAS_PROC_STATUS_SPR() 0 + +/** Log of the number of mshims we have. */ +#define CHIP_LOG_NUM_MSHIMS() 2 + +/** Are the bases of the interrupt vector areas fixed? */ +#define CHIP_HAS_FIXED_INTVEC_BASE() 1 + +/** Are the interrupt masks split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_INTR_MASK() 1 + +/** Is the cycle count split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_CYCLE() 1 + +/** Does the chip have a static network? */ +#define CHIP_HAS_SN() 1 + +/** Does the chip have a static network processor? */ +#define CHIP_HAS_SN_PROC() 1 + +/** Size of the L1 static network processor instruction cache, in bytes. */ +#define CHIP_L1SNI_CACHE_SIZE() 2048 + +/** Does the chip have DMA support in each tile? */ +#define CHIP_HAS_TILE_DMA() 1 + +/** Does the chip have the second revision of the directly accessible + * dynamic networks? This encapsulates a number of characteristics, + * including the absence of the catch-all, the absence of inline message + * tags, the absence of support for network context-switching, and so on. + */ +#define CHIP_HAS_REV1_XDN() 0 + +/** Does the chip have cmpexch and similar (fetchadd, exch, etc.)? */ +#define CHIP_HAS_CMPEXCH() 0 + +/** Does the chip have memory-mapped I/O support? */ +#define CHIP_HAS_MMIO() 0 + +/** Does the chip have post-completion interrupts? */ +#define CHIP_HAS_POST_COMPLETION_INTERRUPTS() 0 + +/** Does the chip have native single step support? */ +#define CHIP_HAS_SINGLE_STEP() 0 + +#ifndef __OPEN_SOURCE__ /* features only relevant to hypervisor-level code */ + +/** How many entries are present in the instruction TLB? */ +#define CHIP_ITLB_ENTRIES() 8 + +/** How many entries are present in the data TLB? */ +#define CHIP_DTLB_ENTRIES() 16 + +/** How many MAF entries does the XAUI shim have? */ +#define CHIP_XAUI_MAF_ENTRIES() 16 + +/** Does the memory shim have a source-id table? */ +#define CHIP_HAS_MSHIM_SRCID_TABLE() 1 + +/** Does the L1 instruction cache clear on reset? */ +#define CHIP_HAS_L1I_CLEAR_ON_RESET() 0 + +/** Does the chip come out of reset with valid coordinates on all tiles? + * Note that if defined, this also implies that the upper left is 1,1. + */ +#define CHIP_HAS_VALID_TILE_COORD_RESET() 0 + +/** Does the chip have unified packet formats? */ +#define CHIP_HAS_UNIFIED_PACKET_FORMATS() 0 + +/** Does the chip support write reordering? */ +#define CHIP_HAS_WRITE_REORDERING() 0 + +/** Does the chip support Y-X routing as well as X-Y? */ +#define CHIP_HAS_Y_X_ROUTING() 0 + +/** Is INTCTRL_3 managed with the correct MPL? */ +#define CHIP_HAS_INTCTRL_3_STATUS_FIX() 0 + +/** Is it possible to configure the chip to be big-endian? */ +#define CHIP_HAS_BIG_ENDIAN_CONFIG() 0 + +/** Is the CACHE_RED_WAY_OVERRIDDEN SPR supported? */ +#define CHIP_HAS_CACHE_RED_WAY_OVERRIDDEN() 0 + +/** Is the DIAG_TRACE_WAY SPR supported? */ +#define CHIP_HAS_DIAG_TRACE_WAY() 0 + +/** Is the MEM_STRIPE_CONFIG SPR supported? */ +#define CHIP_HAS_MEM_STRIPE_CONFIG() 0 + +/** Are the TLB_PERF SPRs supported? */ +#define CHIP_HAS_TLB_PERF() 0 + +/** Is the VDN_SNOOP_SHIM_CTL SPR supported? */ +#define CHIP_HAS_VDN_SNOOP_SHIM_CTL() 0 + +/** Does the chip support rev1 DMA packets? */ +#define CHIP_HAS_REV1_DMA_PACKETS() 0 + +#endif /* !__OPEN_SOURCE__ */ +#endif /* __ARCH_CHIP_H__ */ diff --git a/arch/tile/include/arch/chip_tilepro.h b/arch/tile/include/arch/chip_tilepro.h new file mode 100644 index 000000000000..9852af163862 --- /dev/null +++ b/arch/tile/include/arch/chip_tilepro.h @@ -0,0 +1,252 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* + * @file + * Global header file. + * This header file specifies defines for TILEPro. + */ + +#ifndef __ARCH_CHIP_H__ +#define __ARCH_CHIP_H__ + +/** Specify chip version. + * When possible, prefer the CHIP_xxx symbols below for future-proofing. + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip__ symbol. + */ +#define TILE_CHIP 1 + +/** Specify chip revision. + * This provides for the case of a respin of a particular chip type; + * the normal value for this symbol is "0". + * This is intended for cross-compiling; native compilation should + * use the predefined __tile_chip_rev__ symbol. + */ +#define TILE_CHIP_REV 0 + +/** The name of this architecture. */ +#define CHIP_ARCH_NAME "tilepro" + +/** The ELF e_machine type for binaries for this chip. */ +#define CHIP_ELF_TYPE() EM_TILEPRO + +/** The alternate ELF e_machine type for binaries for this chip. */ +#define CHIP_COMPAT_ELF_TYPE() 0x2507 + +/** What is the native word size of the machine? */ +#define CHIP_WORD_SIZE() 32 + +/** How many bits of a virtual address are used. Extra bits must be + * the sign extension of the low bits. + */ +#define CHIP_VA_WIDTH() 32 + +/** How many bits are in a physical address? */ +#define CHIP_PA_WIDTH() 36 + +/** Size of the L2 cache, in bytes. */ +#define CHIP_L2_CACHE_SIZE() 65536 + +/** Log size of an L2 cache line in bytes. */ +#define CHIP_L2_LOG_LINE_SIZE() 6 + +/** Size of an L2 cache line, in bytes. */ +#define CHIP_L2_LINE_SIZE() (1 << CHIP_L2_LOG_LINE_SIZE()) + +/** Associativity of the L2 cache. */ +#define CHIP_L2_ASSOC() 4 + +/** Size of the L1 data cache, in bytes. */ +#define CHIP_L1D_CACHE_SIZE() 8192 + +/** Log size of an L1 data cache line in bytes. */ +#define CHIP_L1D_LOG_LINE_SIZE() 4 + +/** Size of an L1 data cache line, in bytes. */ +#define CHIP_L1D_LINE_SIZE() (1 << CHIP_L1D_LOG_LINE_SIZE()) + +/** Associativity of the L1 data cache. */ +#define CHIP_L1D_ASSOC() 2 + +/** Size of the L1 instruction cache, in bytes. */ +#define CHIP_L1I_CACHE_SIZE() 16384 + +/** Log size of an L1 instruction cache line in bytes. */ +#define CHIP_L1I_LOG_LINE_SIZE() 6 + +/** Size of an L1 instruction cache line, in bytes. */ +#define CHIP_L1I_LINE_SIZE() (1 << CHIP_L1I_LOG_LINE_SIZE()) + +/** Associativity of the L1 instruction cache. */ +#define CHIP_L1I_ASSOC() 1 + +/** Stride with which flush instructions must be issued. */ +#define CHIP_FLUSH_STRIDE() CHIP_L2_LINE_SIZE() + +/** Stride with which inv instructions must be issued. */ +#define CHIP_INV_STRIDE() CHIP_L2_LINE_SIZE() + +/** Stride with which finv instructions must be issued. */ +#define CHIP_FINV_STRIDE() CHIP_L2_LINE_SIZE() + +/** Can the local cache coherently cache data that is homed elsewhere? */ +#define CHIP_HAS_COHERENT_LOCAL_CACHE() 1 + +/** How many simultaneous outstanding victims can the L2 cache have? */ +#define CHIP_MAX_OUTSTANDING_VICTIMS() 4 + +/** Does the TLB support the NC and NOALLOC bits? */ +#define CHIP_HAS_NC_AND_NOALLOC_BITS() 1 + +/** Does the chip support hash-for-home caching? */ +#define CHIP_HAS_CBOX_HOME_MAP() 1 + +/** Number of entries in the chip's home map tables. */ +#define CHIP_CBOX_HOME_MAP_SIZE() 64 + +/** Do uncacheable requests miss in the cache regardless of whether + * there is matching data? */ +#define CHIP_HAS_ENFORCED_UNCACHEABLE_REQUESTS() 1 + +/** Does the mf instruction wait for victims? */ +#define CHIP_HAS_MF_WAITS_FOR_VICTIMS() 0 + +/** Does the chip have an "inv" instruction that doesn't also flush? */ +#define CHIP_HAS_INV() 1 + +/** Does the chip have a "wh64" instruction? */ +#define CHIP_HAS_WH64() 1 + +/** Does this chip have a 'dword_align' instruction? */ +#define CHIP_HAS_DWORD_ALIGN() 1 + +/** Number of performance counters. */ +#define CHIP_PERFORMANCE_COUNTERS() 4 + +/** Does this chip have auxiliary performance counters? */ +#define CHIP_HAS_AUX_PERF_COUNTERS() 1 + +/** Is the CBOX_MSR1 SPR supported? */ +#define CHIP_HAS_CBOX_MSR1() 1 + +/** Is the TILE_RTF_HWM SPR supported? */ +#define CHIP_HAS_TILE_RTF_HWM() 1 + +/** Is the TILE_WRITE_PENDING SPR supported? */ +#define CHIP_HAS_TILE_WRITE_PENDING() 1 + +/** Is the PROC_STATUS SPR supported? */ +#define CHIP_HAS_PROC_STATUS_SPR() 1 + +/** Log of the number of mshims we have. */ +#define CHIP_LOG_NUM_MSHIMS() 2 + +/** Are the bases of the interrupt vector areas fixed? */ +#define CHIP_HAS_FIXED_INTVEC_BASE() 1 + +/** Are the interrupt masks split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_INTR_MASK() 1 + +/** Is the cycle count split up into 2 SPRs? */ +#define CHIP_HAS_SPLIT_CYCLE() 1 + +/** Does the chip have a static network? */ +#define CHIP_HAS_SN() 1 + +/** Does the chip have a static network processor? */ +#define CHIP_HAS_SN_PROC() 0 + +/** Size of the L1 static network processor instruction cache, in bytes. */ +/* #define CHIP_L1SNI_CACHE_SIZE() -- does not apply to chip 1 */ + +/** Does the chip have DMA support in each tile? */ +#define CHIP_HAS_TILE_DMA() 1 + +/** Does the chip have the second revision of the directly accessible + * dynamic networks? This encapsulates a number of characteristics, + * including the absence of the catch-all, the absence of inline message + * tags, the absence of support for network context-switching, and so on. + */ +#define CHIP_HAS_REV1_XDN() 0 + +/** Does the chip have cmpexch and similar (fetchadd, exch, etc.)? */ +#define CHIP_HAS_CMPEXCH() 0 + +/** Does the chip have memory-mapped I/O support? */ +#define CHIP_HAS_MMIO() 0 + +/** Does the chip have post-completion interrupts? */ +#define CHIP_HAS_POST_COMPLETION_INTERRUPTS() 0 + +/** Does the chip have native single step support? */ +#define CHIP_HAS_SINGLE_STEP() 0 + +#ifndef __OPEN_SOURCE__ /* features only relevant to hypervisor-level code */ + +/** How many entries are present in the instruction TLB? */ +#define CHIP_ITLB_ENTRIES() 16 + +/** How many entries are present in the data TLB? */ +#define CHIP_DTLB_ENTRIES() 16 + +/** How many MAF entries does the XAUI shim have? */ +#define CHIP_XAUI_MAF_ENTRIES() 32 + +/** Does the memory shim have a source-id table? */ +#define CHIP_HAS_MSHIM_SRCID_TABLE() 0 + +/** Does the L1 instruction cache clear on reset? */ +#define CHIP_HAS_L1I_CLEAR_ON_RESET() 1 + +/** Does the chip come out of reset with valid coordinates on all tiles? + * Note that if defined, this also implies that the upper left is 1,1. + */ +#define CHIP_HAS_VALID_TILE_COORD_RESET() 1 + +/** Does the chip have unified packet formats? */ +#define CHIP_HAS_UNIFIED_PACKET_FORMATS() 1 + +/** Does the chip support write reordering? */ +#define CHIP_HAS_WRITE_REORDERING() 1 + +/** Does the chip support Y-X routing as well as X-Y? */ +#define CHIP_HAS_Y_X_ROUTING() 1 + +/** Is INTCTRL_3 managed with the correct MPL? */ +#define CHIP_HAS_INTCTRL_3_STATUS_FIX() 1 + +/** Is it possible to configure the chip to be big-endian? */ +#define CHIP_HAS_BIG_ENDIAN_CONFIG() 1 + +/** Is the CACHE_RED_WAY_OVERRIDDEN SPR supported? */ +#define CHIP_HAS_CACHE_RED_WAY_OVERRIDDEN() 1 + +/** Is the DIAG_TRACE_WAY SPR supported? */ +#define CHIP_HAS_DIAG_TRACE_WAY() 1 + +/** Is the MEM_STRIPE_CONFIG SPR supported? */ +#define CHIP_HAS_MEM_STRIPE_CONFIG() 1 + +/** Are the TLB_PERF SPRs supported? */ +#define CHIP_HAS_TLB_PERF() 1 + +/** Is the VDN_SNOOP_SHIM_CTL SPR supported? */ +#define CHIP_HAS_VDN_SNOOP_SHIM_CTL() 1 + +/** Does the chip support rev1 DMA packets? */ +#define CHIP_HAS_REV1_DMA_PACKETS() 1 + +#endif /* !__OPEN_SOURCE__ */ +#endif /* __ARCH_CHIP_H__ */ diff --git a/arch/tile/include/arch/interrupts.h b/arch/tile/include/arch/interrupts.h new file mode 100644 index 000000000000..20f8f07d2de9 --- /dev/null +++ b/arch/tile/include/arch/interrupts.h @@ -0,0 +1,19 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifdef __tilegx__ +#include +#else +#include +#endif diff --git a/arch/tile/include/arch/interrupts_32.h b/arch/tile/include/arch/interrupts_32.h new file mode 100644 index 000000000000..feffada705f0 --- /dev/null +++ b/arch/tile/include/arch/interrupts_32.h @@ -0,0 +1,304 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef __ARCH_INTERRUPTS_H__ +#define __ARCH_INTERRUPTS_H__ + +/** Mask for an interrupt. */ +#ifdef __ASSEMBLER__ +/* Note: must handle breaking interrupts into high and low words manually. */ +#define INT_MASK(intno) (1 << (intno)) +#else +#define INT_MASK(intno) (1ULL << (intno)) +#endif + + +/** Where a given interrupt executes */ +#define INTERRUPT_VECTOR(i, pl) (0xFC000000 + ((pl) << 24) + ((i) << 8)) + +/** Where to store a vector for a given interrupt. */ +#define USER_INTERRUPT_VECTOR(i) INTERRUPT_VECTOR(i, 0) + +/** The base address of user-level interrupts. */ +#define USER_INTERRUPT_VECTOR_BASE INTERRUPT_VECTOR(0, 0) + + +/** Additional synthetic interrupt. */ +#define INT_BREAKPOINT (63) + +#define INT_ITLB_MISS 0 +#define INT_MEM_ERROR 1 +#define INT_ILL 2 +#define INT_GPV 3 +#define INT_SN_ACCESS 4 +#define INT_IDN_ACCESS 5 +#define INT_UDN_ACCESS 6 +#define INT_IDN_REFILL 7 +#define INT_UDN_REFILL 8 +#define INT_IDN_COMPLETE 9 +#define INT_UDN_COMPLETE 10 +#define INT_SWINT_3 11 +#define INT_SWINT_2 12 +#define INT_SWINT_1 13 +#define INT_SWINT_0 14 +#define INT_UNALIGN_DATA 15 +#define INT_DTLB_MISS 16 +#define INT_DTLB_ACCESS 17 +#define INT_DMATLB_MISS 18 +#define INT_DMATLB_ACCESS 19 +#define INT_SNITLB_MISS 20 +#define INT_SN_NOTIFY 21 +#define INT_SN_FIREWALL 22 +#define INT_IDN_FIREWALL 23 +#define INT_UDN_FIREWALL 24 +#define INT_TILE_TIMER 25 +#define INT_IDN_TIMER 26 +#define INT_UDN_TIMER 27 +#define INT_DMA_NOTIFY 28 +#define INT_IDN_CA 29 +#define INT_UDN_CA 30 +#define INT_IDN_AVAIL 31 +#define INT_UDN_AVAIL 32 +#define INT_PERF_COUNT 33 +#define INT_INTCTRL_3 34 +#define INT_INTCTRL_2 35 +#define INT_INTCTRL_1 36 +#define INT_INTCTRL_0 37 +#define INT_BOOT_ACCESS 38 +#define INT_WORLD_ACCESS 39 +#define INT_I_ASID 40 +#define INT_D_ASID 41 +#define INT_DMA_ASID 42 +#define INT_SNI_ASID 43 +#define INT_DMA_CPL 44 +#define INT_SN_CPL 45 +#define INT_DOUBLE_FAULT 46 +#define INT_SN_STATIC_ACCESS 47 +#define INT_AUX_PERF_COUNT 48 + +#define NUM_INTERRUPTS 49 + +#define QUEUED_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_DMATLB_MISS) | \ + INT_MASK(INT_DMATLB_ACCESS) | \ + INT_MASK(INT_SNITLB_MISS) | \ + INT_MASK(INT_SN_NOTIFY) | \ + INT_MASK(INT_SN_FIREWALL) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_DMA_NOTIFY) | \ + INT_MASK(INT_IDN_CA) | \ + INT_MASK(INT_UDN_CA) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DMA_ASID) | \ + INT_MASK(INT_SNI_ASID) | \ + INT_MASK(INT_DMA_CPL) | \ + INT_MASK(INT_SN_CPL) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + 0) +#define NONQUEUED_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_SN_ACCESS) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_IDN_REFILL) | \ + INT_MASK(INT_UDN_REFILL) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_SN_STATIC_ACCESS) | \ + 0) +#define CRITICAL_MASKED_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_DMATLB_MISS) | \ + INT_MASK(INT_DMATLB_ACCESS) | \ + INT_MASK(INT_SNITLB_MISS) | \ + INT_MASK(INT_SN_NOTIFY) | \ + INT_MASK(INT_SN_FIREWALL) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_DMA_NOTIFY) | \ + INT_MASK(INT_IDN_CA) | \ + INT_MASK(INT_UDN_CA) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + 0) +#define CRITICAL_UNMASKED_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_SN_ACCESS) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_IDN_REFILL) | \ + INT_MASK(INT_UDN_REFILL) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DMA_ASID) | \ + INT_MASK(INT_SNI_ASID) | \ + INT_MASK(INT_DMA_CPL) | \ + INT_MASK(INT_SN_CPL) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + INT_MASK(INT_SN_STATIC_ACCESS) | \ + 0) +#define MASKABLE_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_IDN_REFILL) | \ + INT_MASK(INT_UDN_REFILL) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_DMATLB_MISS) | \ + INT_MASK(INT_DMATLB_ACCESS) | \ + INT_MASK(INT_SNITLB_MISS) | \ + INT_MASK(INT_SN_NOTIFY) | \ + INT_MASK(INT_SN_FIREWALL) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_DMA_NOTIFY) | \ + INT_MASK(INT_IDN_CA) | \ + INT_MASK(INT_UDN_CA) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + 0) +#define UNMASKABLE_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_SN_ACCESS) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DMA_ASID) | \ + INT_MASK(INT_SNI_ASID) | \ + INT_MASK(INT_DMA_CPL) | \ + INT_MASK(INT_SN_CPL) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + INT_MASK(INT_SN_STATIC_ACCESS) | \ + 0) +#define SYNC_INTERRUPTS ( \ + INT_MASK(INT_ITLB_MISS) | \ + INT_MASK(INT_ILL) | \ + INT_MASK(INT_GPV) | \ + INT_MASK(INT_SN_ACCESS) | \ + INT_MASK(INT_IDN_ACCESS) | \ + INT_MASK(INT_UDN_ACCESS) | \ + INT_MASK(INT_IDN_REFILL) | \ + INT_MASK(INT_UDN_REFILL) | \ + INT_MASK(INT_IDN_COMPLETE) | \ + INT_MASK(INT_UDN_COMPLETE) | \ + INT_MASK(INT_SWINT_3) | \ + INT_MASK(INT_SWINT_2) | \ + INT_MASK(INT_SWINT_1) | \ + INT_MASK(INT_SWINT_0) | \ + INT_MASK(INT_UNALIGN_DATA) | \ + INT_MASK(INT_DTLB_MISS) | \ + INT_MASK(INT_DTLB_ACCESS) | \ + INT_MASK(INT_SN_STATIC_ACCESS) | \ + 0) +#define NON_SYNC_INTERRUPTS ( \ + INT_MASK(INT_MEM_ERROR) | \ + INT_MASK(INT_DMATLB_MISS) | \ + INT_MASK(INT_DMATLB_ACCESS) | \ + INT_MASK(INT_SNITLB_MISS) | \ + INT_MASK(INT_SN_NOTIFY) | \ + INT_MASK(INT_SN_FIREWALL) | \ + INT_MASK(INT_IDN_FIREWALL) | \ + INT_MASK(INT_UDN_FIREWALL) | \ + INT_MASK(INT_TILE_TIMER) | \ + INT_MASK(INT_IDN_TIMER) | \ + INT_MASK(INT_UDN_TIMER) | \ + INT_MASK(INT_DMA_NOTIFY) | \ + INT_MASK(INT_IDN_CA) | \ + INT_MASK(INT_UDN_CA) | \ + INT_MASK(INT_IDN_AVAIL) | \ + INT_MASK(INT_UDN_AVAIL) | \ + INT_MASK(INT_PERF_COUNT) | \ + INT_MASK(INT_INTCTRL_3) | \ + INT_MASK(INT_INTCTRL_2) | \ + INT_MASK(INT_INTCTRL_1) | \ + INT_MASK(INT_INTCTRL_0) | \ + INT_MASK(INT_BOOT_ACCESS) | \ + INT_MASK(INT_WORLD_ACCESS) | \ + INT_MASK(INT_I_ASID) | \ + INT_MASK(INT_D_ASID) | \ + INT_MASK(INT_DMA_ASID) | \ + INT_MASK(INT_SNI_ASID) | \ + INT_MASK(INT_DMA_CPL) | \ + INT_MASK(INT_SN_CPL) | \ + INT_MASK(INT_DOUBLE_FAULT) | \ + INT_MASK(INT_AUX_PERF_COUNT) | \ + 0) +#endif // !__ARCH_INTERRUPTS_H__ diff --git a/arch/tile/include/arch/sim_def.h b/arch/tile/include/arch/sim_def.h new file mode 100644 index 000000000000..6418fbde063e --- /dev/null +++ b/arch/tile/include/arch/sim_def.h @@ -0,0 +1,512 @@ +// Copyright 2010 Tilera Corporation. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, version 2. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or +// NON INFRINGEMENT. See the GNU General Public License for +// more details. + +//! @file +//! +//! Some low-level simulator definitions. +//! + +#ifndef __ARCH_SIM_DEF_H__ +#define __ARCH_SIM_DEF_H__ + + +//! Internal: the low bits of the SIM_CONTROL_* SPR values specify +//! the operation to perform, and the remaining bits are +//! an operation-specific parameter (often unused). +//! +#define _SIM_CONTROL_OPERATOR_BITS 8 + + +//== Values which can be written to SPR_SIM_CONTROL. + +//! If written to SPR_SIM_CONTROL, stops profiling. +//! +#define SIM_CONTROL_PROFILER_DISABLE 0 + +//! If written to SPR_SIM_CONTROL, starts profiling. +//! +#define SIM_CONTROL_PROFILER_ENABLE 1 + +//! If written to SPR_SIM_CONTROL, clears profiling counters. +//! +#define SIM_CONTROL_PROFILER_CLEAR 2 + +//! If written to SPR_SIM_CONTROL, checkpoints the simulator. +//! +#define SIM_CONTROL_CHECKPOINT 3 + +//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8), +//! sets the tracing mask to the given mask. See "sim_set_tracing()". +//! +#define SIM_CONTROL_SET_TRACING 4 + +//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8), +//! dumps the requested items of machine state to the log. +//! +#define SIM_CONTROL_DUMP 5 + +//! If written to SPR_SIM_CONTROL, clears chip-level profiling counters. +//! +#define SIM_CONTROL_PROFILER_CHIP_CLEAR 6 + +//! If written to SPR_SIM_CONTROL, disables chip-level profiling. +//! +#define SIM_CONTROL_PROFILER_CHIP_DISABLE 7 + +//! If written to SPR_SIM_CONTROL, enables chip-level profiling. +//! +#define SIM_CONTROL_PROFILER_CHIP_ENABLE 8 + +//! If written to SPR_SIM_CONTROL, enables chip-level functional mode +//! +#define SIM_CONTROL_ENABLE_FUNCTIONAL 9 + +//! If written to SPR_SIM_CONTROL, disables chip-level functional mode. +//! +#define SIM_CONTROL_DISABLE_FUNCTIONAL 10 + +//! If written to SPR_SIM_CONTROL, enables chip-level functional mode. +//! All tiles must perform this write for functional mode to be enabled. +//! Ignored in naked boot mode unless --functional is specified. +//! WARNING: Only the hypervisor startup code should use this! +//! +#define SIM_CONTROL_ENABLE_FUNCTIONAL_BARRIER 11 + +//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8), +//! writes a string directly to the simulator output. Written to once for +//! each character in the string, plus a final NUL. Instead of NUL, +//! you can also use "SIM_PUTC_FLUSH_STRING" or "SIM_PUTC_FLUSH_BINARY". +//! +// ISSUE: Document the meaning of "newline", and the handling of NUL. +// +#define SIM_CONTROL_PUTC 12 + +//! If written to SPR_SIM_CONTROL, clears the --grind-coherence state for +//! this core. This is intended to be used before a loop that will +//! invalidate the cache by loading new data and evicting all current data. +//! Generally speaking, this API should only be used by system code. +//! +#define SIM_CONTROL_GRINDER_CLEAR 13 + +//! If written to SPR_SIM_CONTROL, shuts down the simulator. +//! +#define SIM_CONTROL_SHUTDOWN 14 + +//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8), +//! indicates that a fork syscall just created the given process. +//! +#define SIM_CONTROL_OS_FORK 15 + +//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8), +//! indicates that an exit syscall was just executed by the given process. +//! +#define SIM_CONTROL_OS_EXIT 16 + +//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8), +//! indicates that the OS just switched to the given process. +//! +#define SIM_CONTROL_OS_SWITCH 17 + +//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8), +//! indicates that an exec syscall was just executed. Written to once for +//! each character in the executable name, plus a final NUL. +//! +#define SIM_CONTROL_OS_EXEC 18 + +//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8), +//! indicates that an interpreter (PT_INTERP) was loaded. Written to once +//! for each character in "ADDR:PATH", plus a final NUL, where "ADDR" is a +//! hex load address starting with "0x", and "PATH" is the executable name. +//! +#define SIM_CONTROL_OS_INTERP 19 + +//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8), +//! indicates that a dll was loaded. Written to once for each character +//! in "ADDR:PATH", plus a final NUL, where "ADDR" is a hexadecimal load +//! address starting with "0x", and "PATH" is the executable name. +//! +#define SIM_CONTROL_DLOPEN 20 + +//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8), +//! indicates that a dll was unloaded. Written to once for each character +//! in "ADDR", plus a final NUL, where "ADDR" is a hexadecimal load +//! address starting with "0x". +//! +#define SIM_CONTROL_DLCLOSE 21 + +//! If written to SPR_SIM_CONTROL, combined with a flag (shifted by 8), +//! indicates whether to allow data reads to remotely-cached +//! dirty cache lines to be cached locally without grinder warnings or +//! assertions (used by Linux kernel fast memcpy). +//! +#define SIM_CONTROL_ALLOW_MULTIPLE_CACHING 22 + +//! If written to SPR_SIM_CONTROL, enables memory tracing. +//! +#define SIM_CONTROL_ENABLE_MEM_LOGGING 23 + +//! If written to SPR_SIM_CONTROL, disables memory tracing. +//! +#define SIM_CONTROL_DISABLE_MEM_LOGGING 24 + +//! If written to SPR_SIM_CONTROL, changes the shaping parameters of one of +//! the gbe or xgbe shims. Must specify the shim id, the type, the units, and +//! the rate, as defined in SIM_SHAPING_SPR_ARG. +//! +#define SIM_CONTROL_SHAPING 25 + +//! If written to SPR_SIM_CONTROL, combined with character (shifted by 8), +//! requests that a simulator command be executed. Written to once for each +//! character in the command, plus a final NUL. +//! +#define SIM_CONTROL_COMMAND 26 + +//! If written to SPR_SIM_CONTROL, indicates that the simulated system +//! is panicking, to allow debugging via --debug-on-panic. +//! +#define SIM_CONTROL_PANIC 27 + +//! If written to SPR_SIM_CONTROL, triggers a simulator syscall. +//! See "sim_syscall()" for more info. +//! +#define SIM_CONTROL_SYSCALL 32 + +//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8), +//! provides the pid that subsequent SIM_CONTROL_OS_FORK writes should +//! use as the pid, rather than the default previous SIM_CONTROL_OS_SWITCH. +//! +#define SIM_CONTROL_OS_FORK_PARENT 33 + +//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number +//! (shifted by 8), clears the pending magic data section. The cleared +//! pending magic data section and any subsequently appended magic bytes +//! will only take effect when the classifier blast programmer is run. +#define SIM_CONTROL_CLEAR_MPIPE_MAGIC_BYTES 34 + +//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number +//! (shifted by 8) and a byte of data (shifted by 16), appends that byte +//! to the shim's pending magic data section. The pending magic data +//! section takes effect when the classifier blast programmer is run. +#define SIM_CONTROL_APPEND_MPIPE_MAGIC_BYTE 35 + +//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number +//! (shifted by 8), an enable=1/disable=0 bit (shifted by 16), and a +//! mask of links (shifted by 32), enable or disable the corresponding +//! mPIPE links. +#define SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE 36 + +//== Syscall numbers for use with "sim_syscall()". + +//! Syscall number for sim_add_watchpoint(). +//! +#define SIM_SYSCALL_ADD_WATCHPOINT 2 + +//! Syscall number for sim_remove_watchpoint(). +//! +#define SIM_SYSCALL_REMOVE_WATCHPOINT 3 + +//! Syscall number for sim_query_watchpoint(). +//! +#define SIM_SYSCALL_QUERY_WATCHPOINT 4 + +//! Syscall number that asserts that the cache lines whose 64-bit PA +//! is passed as the second argument to sim_syscall(), and over a +//! range passed as the third argument, are no longer in cache. +//! The simulator raises an error if this is not the case. +//! +#define SIM_SYSCALL_VALIDATE_LINES_EVICTED 5 + + +//== Bit masks which can be shifted by 8, combined with +//== SIM_CONTROL_SET_TRACING, and written to SPR_SIM_CONTROL. + +//! @addtogroup arch_sim +//! @{ + +//! Enable --trace-cycle when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_CYCLES 0x01 + +//! Enable --trace-router when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_ROUTER 0x02 + +//! Enable --trace-register-writes when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_REGISTER_WRITES 0x04 + +//! Enable --trace-disasm when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_DISASM 0x08 + +//! Enable --trace-stall-info when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_STALL_INFO 0x10 + +//! Enable --trace-memory-controller when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_MEMORY_CONTROLLER 0x20 + +//! Enable --trace-l2 when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_L2_CACHE 0x40 + +//! Enable --trace-lines when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_LINES 0x80 + +//! Turn off all tracing when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_NONE 0 + +//! Turn on all tracing when passed to simulator_set_tracing(). +//! +#define SIM_TRACE_ALL (-1) + +//! @} + +//! Computes the value to write to SPR_SIM_CONTROL to set tracing flags. +//! +#define SIM_TRACE_SPR_ARG(mask) \ + (SIM_CONTROL_SET_TRACING | ((mask) << _SIM_CONTROL_OPERATOR_BITS)) + + +//== Bit masks which can be shifted by 8, combined with +//== SIM_CONTROL_DUMP, and written to SPR_SIM_CONTROL. + +//! @addtogroup arch_sim +//! @{ + +//! Dump the general-purpose registers. +//! +#define SIM_DUMP_REGS 0x001 + +//! Dump the SPRs. +//! +#define SIM_DUMP_SPRS 0x002 + +//! Dump the ITLB. +//! +#define SIM_DUMP_ITLB 0x004 + +//! Dump the DTLB. +//! +#define SIM_DUMP_DTLB 0x008 + +//! Dump the L1 I-cache. +//! +#define SIM_DUMP_L1I 0x010 + +//! Dump the L1 D-cache. +//! +#define SIM_DUMP_L1D 0x020 + +//! Dump the L2 cache. +//! +#define SIM_DUMP_L2 0x040 + +//! Dump the switch registers. +//! +#define SIM_DUMP_SNREGS 0x080 + +//! Dump the switch ITLB. +//! +#define SIM_DUMP_SNITLB 0x100 + +//! Dump the switch L1 I-cache. +//! +#define SIM_DUMP_SNL1I 0x200 + +//! Dump the current backtrace. +//! +#define SIM_DUMP_BACKTRACE 0x400 + +//! Only dump valid lines in caches. +//! +#define SIM_DUMP_VALID_LINES 0x800 + +//! Dump everything that is dumpable. +//! +#define SIM_DUMP_ALL (-1 & ~SIM_DUMP_VALID_LINES) + +// @} + +//! Computes the value to write to SPR_SIM_CONTROL to dump machine state. +//! +#define SIM_DUMP_SPR_ARG(mask) \ + (SIM_CONTROL_DUMP | ((mask) << _SIM_CONTROL_OPERATOR_BITS)) + + +//== Bit masks which can be shifted by 8, combined with +//== SIM_CONTROL_PROFILER_CHIP_xxx, and written to SPR_SIM_CONTROL. + +//! @addtogroup arch_sim +//! @{ + +//! Use with with SIM_PROFILER_CHIP_xxx to control the memory controllers. +//! +#define SIM_CHIP_MEMCTL 0x001 + +//! Use with with SIM_PROFILER_CHIP_xxx to control the XAUI interface. +//! +#define SIM_CHIP_XAUI 0x002 + +//! Use with with SIM_PROFILER_CHIP_xxx to control the PCIe interface. +//! +#define SIM_CHIP_PCIE 0x004 + +//! Use with with SIM_PROFILER_CHIP_xxx to control the MPIPE interface. +//! +#define SIM_CHIP_MPIPE 0x008 + +//! Reference all chip devices. +//! +#define SIM_CHIP_ALL (-1) + +//! @} + +//! Computes the value to write to SPR_SIM_CONTROL to clear chip statistics. +//! +#define SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask) \ + (SIM_CONTROL_PROFILER_CHIP_CLEAR | ((mask) << _SIM_CONTROL_OPERATOR_BITS)) + +//! Computes the value to write to SPR_SIM_CONTROL to disable chip statistics. +//! +#define SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask) \ + (SIM_CONTROL_PROFILER_CHIP_DISABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS)) + +//! Computes the value to write to SPR_SIM_CONTROL to enable chip statistics. +//! +#define SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask) \ + (SIM_CONTROL_PROFILER_CHIP_ENABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS)) + + + +// Shim bitrate controls. + +//! The number of bits used to store the shim id. +//! +#define SIM_CONTROL_SHAPING_SHIM_ID_BITS 3 + +//! @addtogroup arch_sim +//! @{ + +//! Change the gbe 0 bitrate. +//! +#define SIM_CONTROL_SHAPING_GBE_0 0x0 + +//! Change the gbe 1 bitrate. +//! +#define SIM_CONTROL_SHAPING_GBE_1 0x1 + +//! Change the gbe 2 bitrate. +//! +#define SIM_CONTROL_SHAPING_GBE_2 0x2 + +//! Change the gbe 3 bitrate. +//! +#define SIM_CONTROL_SHAPING_GBE_3 0x3 + +//! Change the xgbe 0 bitrate. +//! +#define SIM_CONTROL_SHAPING_XGBE_0 0x4 + +//! Change the xgbe 1 bitrate. +//! +#define SIM_CONTROL_SHAPING_XGBE_1 0x5 + +//! The type of shaping to do. +//! +#define SIM_CONTROL_SHAPING_TYPE_BITS 2 + +//! Control the multiplier. +//! +#define SIM_CONTROL_SHAPING_MULTIPLIER 0 + +//! Control the PPS. +//! +#define SIM_CONTROL_SHAPING_PPS 1 + +//! Control the BPS. +//! +#define SIM_CONTROL_SHAPING_BPS 2 + +//! The number of bits for the units for the shaping parameter. +//! +#define SIM_CONTROL_SHAPING_UNITS_BITS 2 + +//! Provide a number in single units. +//! +#define SIM_CONTROL_SHAPING_UNITS_SINGLE 0 + +//! Provide a number in kilo units. +//! +#define SIM_CONTROL_SHAPING_UNITS_KILO 1 + +//! Provide a number in mega units. +//! +#define SIM_CONTROL_SHAPING_UNITS_MEGA 2 + +//! Provide a number in giga units. +//! +#define SIM_CONTROL_SHAPING_UNITS_GIGA 3 + +// @} + +//! How many bits are available for the rate. +//! +#define SIM_CONTROL_SHAPING_RATE_BITS \ + (32 - (_SIM_CONTROL_OPERATOR_BITS + \ + SIM_CONTROL_SHAPING_SHIM_ID_BITS + \ + SIM_CONTROL_SHAPING_TYPE_BITS + \ + SIM_CONTROL_SHAPING_UNITS_BITS)) + +//! Computes the value to write to SPR_SIM_CONTROL to change a bitrate. +//! +#define SIM_SHAPING_SPR_ARG(shim, type, units, rate) \ + (SIM_CONTROL_SHAPING | \ + ((shim) | \ + ((type) << (SIM_CONTROL_SHAPING_SHIM_ID_BITS)) | \ + ((units) << (SIM_CONTROL_SHAPING_SHIM_ID_BITS + \ + SIM_CONTROL_SHAPING_TYPE_BITS)) | \ + ((rate) << (SIM_CONTROL_SHAPING_SHIM_ID_BITS + \ + SIM_CONTROL_SHAPING_TYPE_BITS + \ + SIM_CONTROL_SHAPING_UNITS_BITS))) << _SIM_CONTROL_OPERATOR_BITS) + + +//== Values returned when reading SPR_SIM_CONTROL. +// ISSUE: These names should share a longer common prefix. + +//! When reading SPR_SIM_CONTROL, the mask of simulator tracing bits +//! (SIM_TRACE_xxx values). +//! +#define SIM_TRACE_FLAG_MASK 0xFFFF + +//! When reading SPR_SIM_CONTROL, the mask for whether profiling is enabled. +//! +#define SIM_PROFILER_ENABLED_MASK 0x10000 + + +//== Special arguments for "SIM_CONTROL_PUTC". + +//! Flag value for forcing a PUTC string-flush, including +//! coordinate/cycle prefix and newline. +//! +#define SIM_PUTC_FLUSH_STRING 0x100 + +//! Flag value for forcing a PUTC binary-data-flush, which skips the +//! prefix and does not append a newline. +//! +#define SIM_PUTC_FLUSH_BINARY 0x101 + + +#endif //__ARCH_SIM_DEF_H__ diff --git a/arch/tile/include/arch/spr_def.h b/arch/tile/include/arch/spr_def.h new file mode 100644 index 000000000000..c8fdbd9a45e6 --- /dev/null +++ b/arch/tile/include/arch/spr_def.h @@ -0,0 +1,19 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifdef __tilegx__ +#include +#else +#include +#endif diff --git a/arch/tile/include/arch/spr_def_32.h b/arch/tile/include/arch/spr_def_32.h new file mode 100644 index 000000000000..b4fc06864df6 --- /dev/null +++ b/arch/tile/include/arch/spr_def_32.h @@ -0,0 +1,162 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef __DOXYGEN__ + +#ifndef __ARCH_SPR_DEF_H__ +#define __ARCH_SPR_DEF_H__ + +#define SPR_AUX_PERF_COUNT_0 0x6005 +#define SPR_AUX_PERF_COUNT_1 0x6006 +#define SPR_AUX_PERF_COUNT_CTL 0x6007 +#define SPR_AUX_PERF_COUNT_STS 0x6008 +#define SPR_CYCLE_HIGH 0x4e06 +#define SPR_CYCLE_LOW 0x4e07 +#define SPR_DMA_BYTE 0x3900 +#define SPR_DMA_CHUNK_SIZE 0x3901 +#define SPR_DMA_CTR 0x3902 +#define SPR_DMA_CTR__REQUEST_MASK 0x1 +#define SPR_DMA_CTR__SUSPEND_MASK 0x2 +#define SPR_DMA_DST_ADDR 0x3903 +#define SPR_DMA_DST_CHUNK_ADDR 0x3904 +#define SPR_DMA_SRC_ADDR 0x3905 +#define SPR_DMA_SRC_CHUNK_ADDR 0x3906 +#define SPR_DMA_STATUS__DONE_MASK 0x1 +#define SPR_DMA_STATUS__BUSY_MASK 0x2 +#define SPR_DMA_STATUS__RUNNING_MASK 0x10 +#define SPR_DMA_STRIDE 0x3907 +#define SPR_DMA_USER_STATUS 0x3908 +#define SPR_DONE 0x4e08 +#define SPR_EVENT_BEGIN 0x4e0d +#define SPR_EVENT_END 0x4e0e +#define SPR_EX_CONTEXT_0_0 0x4a05 +#define SPR_EX_CONTEXT_0_1 0x4a06 +#define SPR_EX_CONTEXT_0_1__PL_SHIFT 0 +#define SPR_EX_CONTEXT_0_1__PL_RMASK 0x3 +#define SPR_EX_CONTEXT_0_1__PL_MASK 0x3 +#define SPR_EX_CONTEXT_0_1__ICS_SHIFT 2 +#define SPR_EX_CONTEXT_0_1__ICS_RMASK 0x1 +#define SPR_EX_CONTEXT_0_1__ICS_MASK 0x4 +#define SPR_EX_CONTEXT_1_0 0x4805 +#define SPR_EX_CONTEXT_1_1 0x4806 +#define SPR_EX_CONTEXT_1_1__PL_SHIFT 0 +#define SPR_EX_CONTEXT_1_1__PL_RMASK 0x3 +#define SPR_EX_CONTEXT_1_1__PL_MASK 0x3 +#define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2 +#define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1 +#define SPR_EX_CONTEXT_1_1__ICS_MASK 0x4 +#define SPR_FAIL 0x4e09 +#define SPR_INTCTRL_0_STATUS 0x4a07 +#define SPR_INTCTRL_1_STATUS 0x4807 +#define SPR_INTERRUPT_CRITICAL_SECTION 0x4e0a +#define SPR_INTERRUPT_MASK_0_0 0x4a08 +#define SPR_INTERRUPT_MASK_0_1 0x4a09 +#define SPR_INTERRUPT_MASK_1_0 0x4809 +#define SPR_INTERRUPT_MASK_1_1 0x480a +#define SPR_INTERRUPT_MASK_RESET_0_0 0x4a0a +#define SPR_INTERRUPT_MASK_RESET_0_1 0x4a0b +#define SPR_INTERRUPT_MASK_RESET_1_0 0x480b +#define SPR_INTERRUPT_MASK_RESET_1_1 0x480c +#define SPR_INTERRUPT_MASK_SET_0_0 0x4a0c +#define SPR_INTERRUPT_MASK_SET_0_1 0x4a0d +#define SPR_INTERRUPT_MASK_SET_1_0 0x480d +#define SPR_INTERRUPT_MASK_SET_1_1 0x480e +#define SPR_MPL_DMA_CPL_SET_0 0x5800 +#define SPR_MPL_DMA_CPL_SET_1 0x5801 +#define SPR_MPL_DMA_NOTIFY_SET_0 0x3800 +#define SPR_MPL_DMA_NOTIFY_SET_1 0x3801 +#define SPR_MPL_INTCTRL_0_SET_0 0x4a00 +#define SPR_MPL_INTCTRL_0_SET_1 0x4a01 +#define SPR_MPL_INTCTRL_1_SET_0 0x4800 +#define SPR_MPL_INTCTRL_1_SET_1 0x4801 +#define SPR_MPL_SN_ACCESS_SET_0 0x0800 +#define SPR_MPL_SN_ACCESS_SET_1 0x0801 +#define SPR_MPL_SN_CPL_SET_0 0x5a00 +#define SPR_MPL_SN_CPL_SET_1 0x5a01 +#define SPR_MPL_SN_FIREWALL_SET_0 0x2c00 +#define SPR_MPL_SN_FIREWALL_SET_1 0x2c01 +#define SPR_MPL_SN_NOTIFY_SET_0 0x2a00 +#define SPR_MPL_SN_NOTIFY_SET_1 0x2a01 +#define SPR_MPL_UDN_ACCESS_SET_0 0x0c00 +#define SPR_MPL_UDN_ACCESS_SET_1 0x0c01 +#define SPR_MPL_UDN_AVAIL_SET_0 0x4000 +#define SPR_MPL_UDN_AVAIL_SET_1 0x4001 +#define SPR_MPL_UDN_CA_SET_0 0x3c00 +#define SPR_MPL_UDN_CA_SET_1 0x3c01 +#define SPR_MPL_UDN_COMPLETE_SET_0 0x1400 +#define SPR_MPL_UDN_COMPLETE_SET_1 0x1401 +#define SPR_MPL_UDN_FIREWALL_SET_0 0x3000 +#define SPR_MPL_UDN_FIREWALL_SET_1 0x3001 +#define SPR_MPL_UDN_REFILL_SET_0 0x1000 +#define SPR_MPL_UDN_REFILL_SET_1 0x1001 +#define SPR_MPL_UDN_TIMER_SET_0 0x3600 +#define SPR_MPL_UDN_TIMER_SET_1 0x3601 +#define SPR_MPL_WORLD_ACCESS_SET_0 0x4e00 +#define SPR_MPL_WORLD_ACCESS_SET_1 0x4e01 +#define SPR_PASS 0x4e0b +#define SPR_PERF_COUNT_0 0x4205 +#define SPR_PERF_COUNT_1 0x4206 +#define SPR_PERF_COUNT_CTL 0x4207 +#define SPR_PERF_COUNT_STS 0x4208 +#define SPR_PROC_STATUS 0x4f00 +#define SPR_SIM_CONTROL 0x4e0c +#define SPR_SNCTL 0x0805 +#define SPR_SNCTL__FRZFABRIC_MASK 0x1 +#define SPR_SNCTL__FRZPROC_MASK 0x2 +#define SPR_SNPC 0x080b +#define SPR_SNSTATIC 0x080c +#define SPR_SYSTEM_SAVE_0_0 0x4b00 +#define SPR_SYSTEM_SAVE_0_1 0x4b01 +#define SPR_SYSTEM_SAVE_0_2 0x4b02 +#define SPR_SYSTEM_SAVE_0_3 0x4b03 +#define SPR_SYSTEM_SAVE_1_0 0x4900 +#define SPR_SYSTEM_SAVE_1_1 0x4901 +#define SPR_SYSTEM_SAVE_1_2 0x4902 +#define SPR_SYSTEM_SAVE_1_3 0x4903 +#define SPR_TILE_COORD 0x4c17 +#define SPR_TILE_RTF_HWM 0x4e10 +#define SPR_TILE_TIMER_CONTROL 0x3205 +#define SPR_TILE_WRITE_PENDING 0x4e0f +#define SPR_UDN_AVAIL_EN 0x4005 +#define SPR_UDN_CA_DATA 0x0d00 +#define SPR_UDN_DATA_AVAIL 0x0d03 +#define SPR_UDN_DEADLOCK_TIMEOUT 0x3606 +#define SPR_UDN_DEMUX_CA_COUNT 0x0c05 +#define SPR_UDN_DEMUX_COUNT_0 0x0c06 +#define SPR_UDN_DEMUX_COUNT_1 0x0c07 +#define SPR_UDN_DEMUX_COUNT_2 0x0c08 +#define SPR_UDN_DEMUX_COUNT_3 0x0c09 +#define SPR_UDN_DEMUX_CTL 0x0c0a +#define SPR_UDN_DEMUX_QUEUE_SEL 0x0c0c +#define SPR_UDN_DEMUX_STATUS 0x0c0d +#define SPR_UDN_DEMUX_WRITE_FIFO 0x0c0e +#define SPR_UDN_DIRECTION_PROTECT 0x3005 +#define SPR_UDN_REFILL_EN 0x1005 +#define SPR_UDN_SP_FIFO_DATA 0x0c11 +#define SPR_UDN_SP_FIFO_SEL 0x0c12 +#define SPR_UDN_SP_FREEZE 0x0c13 +#define SPR_UDN_SP_FREEZE__SP_FRZ_MASK 0x1 +#define SPR_UDN_SP_FREEZE__DEMUX_FRZ_MASK 0x2 +#define SPR_UDN_SP_FREEZE__NON_DEST_EXT_MASK 0x4 +#define SPR_UDN_SP_STATE 0x0c14 +#define SPR_UDN_TAG_0 0x0c15 +#define SPR_UDN_TAG_1 0x0c16 +#define SPR_UDN_TAG_2 0x0c17 +#define SPR_UDN_TAG_3 0x0c18 +#define SPR_UDN_TAG_VALID 0x0c19 +#define SPR_UDN_TILE_COORD 0x0c1a + +#endif /* !defined(__ARCH_SPR_DEF_H__) */ + +#endif /* !defined(__DOXYGEN__) */ diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild new file mode 100644 index 000000000000..3b8f55b82dee --- /dev/null +++ b/arch/tile/include/asm/Kbuild @@ -0,0 +1,3 @@ +include include/asm-generic/Kbuild.asm + +header-y += ucontext.h diff --git a/arch/tile/include/asm/asm-offsets.h b/arch/tile/include/asm/asm-offsets.h new file mode 100644 index 000000000000..d370ee36a182 --- /dev/null +++ b/arch/tile/include/asm/asm-offsets.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h new file mode 100644 index 000000000000..b8c49f98a44c --- /dev/null +++ b/arch/tile/include/asm/atomic.h @@ -0,0 +1,159 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Atomic primitives. + */ + +#ifndef _ASM_TILE_ATOMIC_H +#define _ASM_TILE_ATOMIC_H + +#ifndef __ASSEMBLY__ + +#include +#include + +#define ATOMIC_INIT(i) { (i) } + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. + */ +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} + +/** + * atomic_sub_return - subtract integer and return + * @v: pointer of type atomic_t + * @i: integer value to subtract + * + * Atomically subtracts @i from @v and returns @v - @i + */ +#define atomic_sub_return(i, v) atomic_add_return((int)(-(i)), (v)) + +/** + * atomic_sub - subtract integer from atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. + */ +#define atomic_sub(i, v) atomic_add((int)(-(i)), (v)) + +/** + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns true if the result is + * zero, or false for all other cases. + */ +#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) + +/** + * atomic_inc_return - increment memory and return + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 and returns the new value. + */ +#define atomic_inc_return(v) atomic_add_return(1, (v)) + +/** + * atomic_dec_return - decrement memory and return + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and returns the new value. + */ +#define atomic_dec_return(v) atomic_sub_return(1, (v)) + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. + */ +#define atomic_inc(v) atomic_add(1, (v)) + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. + */ +#define atomic_dec(v) atomic_sub(1, (v)) + +/** + * atomic_dec_and_test - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and returns true if the result is 0. + */ +#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) + +/** + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 and returns true if the result is 0. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +/** + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true if the result is + * negative, or false when result is greater than or equal to zero. + */ +#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) + +/** + * atomic_inc_not_zero - increment unless the number is zero + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1, so long as @v is non-zero. + * Returns non-zero if @v was non-zero, and zero otherwise. + */ +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) + + +/* + * We define xchg() and cmpxchg() in the included headers. + * Note that we do not define __HAVE_ARCH_CMPXCHG, since that would imply + * that cmpxchg() is an efficient operation, which is not particularly true. + */ + +/* Nonexistent functions intended to cause link errors. */ +extern unsigned long __xchg_called_with_bad_pointer(void); +extern unsigned long __cmpxchg_called_with_bad_pointer(void); + +#define tas(ptr) (xchg((ptr), 1)) + +#endif /* __ASSEMBLY__ */ + +#ifndef __tilegx__ +#include +#else +#include +#endif + +/* Provide the appropriate atomic_long_t definitions. */ +#ifndef __ASSEMBLY__ +#include +#endif + +#endif /* _ASM_TILE_ATOMIC_H */ diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h new file mode 100644 index 000000000000..e4f8b4f04895 --- /dev/null +++ b/arch/tile/include/asm/atomic_32.h @@ -0,0 +1,353 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Do not include directly; use . + */ + +#ifndef _ASM_TILE_ATOMIC_32_H +#define _ASM_TILE_ATOMIC_32_H + +#include + +#ifndef __ASSEMBLY__ + +/* Tile-specific routines to support . */ +int _atomic_xchg(atomic_t *v, int n); +int _atomic_xchg_add(atomic_t *v, int i); +int _atomic_xchg_add_unless(atomic_t *v, int a, int u); +int _atomic_cmpxchg(atomic_t *v, int o, int n); + +/** + * atomic_xchg - atomically exchange contents of memory with a new value + * @v: pointer of type atomic_t + * @i: integer value to store in memory + * + * Atomically sets @v to @i and returns old @v + */ +static inline int atomic_xchg(atomic_t *v, int n) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic_xchg(v, n); +} + +/** + * atomic_cmpxchg - atomically exchange contents of memory if it matches + * @v: pointer of type atomic_t + * @o: old value that memory should have + * @n: new value to write to memory if it matches + * + * Atomically checks if @v holds @o and replaces it with @n if so. + * Returns the old value at @v. + */ +static inline int atomic_cmpxchg(atomic_t *v, int o, int n) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic_cmpxchg(v, o, n); +} + +/** + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. + */ +static inline void atomic_add(int i, atomic_t *v) +{ + _atomic_xchg_add(v, i); +} + +/** + * atomic_add_return - add integer and return + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline int atomic_add_return(int i, atomic_t *v) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic_xchg_add(v, i) + i; +} + +/** + * atomic_add_unless - add unless the number is already a given value + * @v: pointer of type atomic_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as @v was not already @u. + * Returns non-zero if @v was not @u, and zero otherwise. + */ +static inline int atomic_add_unless(atomic_t *v, int a, int u) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic_xchg_add_unless(v, a, u) != u; +} + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. + * + * atomic_set() can't be just a raw store, since it would be lost if it + * fell between the load and store of one of the other atomic ops. + */ +static inline void atomic_set(atomic_t *v, int n) +{ + _atomic_xchg(v, n); +} + +#define xchg(ptr, x) ((typeof(*(ptr))) \ + ((sizeof(*(ptr)) == sizeof(atomic_t)) ? \ + atomic_xchg((atomic_t *)(ptr), (long)(x)) : \ + __xchg_called_with_bad_pointer())) + +#define cmpxchg(ptr, o, n) ((typeof(*(ptr))) \ + ((sizeof(*(ptr)) == sizeof(atomic_t)) ? \ + atomic_cmpxchg((atomic_t *)(ptr), (long)(o), (long)(n)) : \ + __cmpxchg_called_with_bad_pointer())) + +/* A 64bit atomic type */ + +typedef struct { + u64 __aligned(8) counter; +} atomic64_t; + +#define ATOMIC64_INIT(val) { (val) } + +u64 _atomic64_xchg(atomic64_t *v, u64 n); +u64 _atomic64_xchg_add(atomic64_t *v, u64 i); +u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u); +u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n); + +/** + * atomic64_read - read atomic variable + * @v: pointer of type atomic64_t + * + * Atomically reads the value of @v. + */ +static inline u64 atomic64_read(const atomic64_t *v) +{ + /* + * Requires an atomic op to read both 32-bit parts consistently. + * Casting away const is safe since the atomic support routines + * do not write to memory if the value has not been modified. + */ + return _atomic64_xchg_add((atomic64_t *)v, 0); +} + +/** + * atomic64_xchg - atomically exchange contents of memory with a new value + * @v: pointer of type atomic64_t + * @i: integer value to store in memory + * + * Atomically sets @v to @i and returns old @v + */ +static inline u64 atomic64_xchg(atomic64_t *v, u64 n) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic64_xchg(v, n); +} + +/** + * atomic64_cmpxchg - atomically exchange contents of memory if it matches + * @v: pointer of type atomic64_t + * @o: old value that memory should have + * @n: new value to write to memory if it matches + * + * Atomically checks if @v holds @o and replaces it with @n if so. + * Returns the old value at @v. + */ +static inline u64 atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic64_cmpxchg(v, o, n); +} + +/** + * atomic64_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic64_t + * + * Atomically adds @i to @v. + */ +static inline void atomic64_add(u64 i, atomic64_t *v) +{ + _atomic64_xchg_add(v, i); +} + +/** + * atomic64_add_return - add integer and return + * @v: pointer of type atomic64_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline u64 atomic64_add_return(u64 i, atomic64_t *v) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic64_xchg_add(v, i) + i; +} + +/** + * atomic64_add_unless - add unless the number is already a given value + * @v: pointer of type atomic64_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as @v was not already @u. + * Returns non-zero if @v was not @u, and zero otherwise. + */ +static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u) +{ + smp_mb(); /* barrier for proper semantics */ + return _atomic64_xchg_add_unless(v, a, u) != u; +} + +/** + * atomic64_set - set atomic variable + * @v: pointer of type atomic64_t + * @i: required value + * + * Atomically sets the value of @v to @i. + * + * atomic64_set() can't be just a raw store, since it would be lost if it + * fell between the load and store of one of the other atomic ops. + */ +static inline void atomic64_set(atomic64_t *v, u64 n) +{ + _atomic64_xchg(v, n); +} + +#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) +#define atomic64_inc(v) atomic64_add(1LL, (v)) +#define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) +#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) +#define atomic64_sub_return(i, v) atomic64_add_return(-(i), (v)) +#define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) +#define atomic64_sub(i, v) atomic64_add(-(i), (v)) +#define atomic64_dec(v) atomic64_sub(1LL, (v)) +#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) +#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) + +/* + * We need to barrier before modifying the word, since the _atomic_xxx() + * routines just tns the lock and then read/modify/write of the word. + * But after the word is updated, the routine issues an "mf" before returning, + * and since it's a function call, we don't even need a compiler barrier. + */ +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_dec() do { } while (0) +#define smp_mb__after_atomic_inc() do { } while (0) + + +/* + * Support "tns" atomic integers. These are atomic integers that can + * hold any value but "1". They are more efficient than regular atomic + * operations because the "lock" (aka acquire) step is a single "tns" + * in the uncontended case, and the "unlock" (aka release) step is a + * single "store" without an mf. (However, note that on tilepro the + * "tns" will evict the local cache line, so it's not all upside.) + * + * Note that you can ONLY observe the value stored in the pointer + * using these operations; a direct read of the value may confusingly + * return the special value "1". + */ + +int __tns_atomic_acquire(atomic_t *); +void __tns_atomic_release(atomic_t *p, int v); + +static inline void tns_atomic_set(atomic_t *v, int i) +{ + __tns_atomic_acquire(v); + __tns_atomic_release(v, i); +} + +static inline int tns_atomic_cmpxchg(atomic_t *v, int o, int n) +{ + int ret = __tns_atomic_acquire(v); + __tns_atomic_release(v, (ret == o) ? n : ret); + return ret; +} + +static inline int tns_atomic_xchg(atomic_t *v, int n) +{ + int ret = __tns_atomic_acquire(v); + __tns_atomic_release(v, n); + return ret; +} + +#endif /* !__ASSEMBLY__ */ + +/* + * Internal definitions only beyond this point. + */ + +#define ATOMIC_LOCKS_FOUND_VIA_TABLE() \ + (!CHIP_HAS_CBOX_HOME_MAP() && defined(CONFIG_SMP)) + +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + +/* Number of entries in atomic_lock_ptr[]. */ +#define ATOMIC_HASH_L1_SHIFT 6 +#define ATOMIC_HASH_L1_SIZE (1 << ATOMIC_HASH_L1_SHIFT) + +/* Number of locks in each struct pointed to by atomic_lock_ptr[]. */ +#define ATOMIC_HASH_L2_SHIFT (CHIP_L2_LOG_LINE_SIZE() - 2) +#define ATOMIC_HASH_L2_SIZE (1 << ATOMIC_HASH_L2_SHIFT) + +#else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + +/* + * Number of atomic locks in atomic_locks[]. Must be a power of two. + * There is no reason for more than PAGE_SIZE / 8 entries, since that + * is the maximum number of pointer bits we can use to index this. + * And we cannot have more than PAGE_SIZE / 4, since this has to + * fit on a single page and each entry takes 4 bytes. + */ +#define ATOMIC_HASH_SHIFT (PAGE_SHIFT - 3) +#define ATOMIC_HASH_SIZE (1 << ATOMIC_HASH_SHIFT) + +#ifndef __ASSEMBLY__ +extern int atomic_locks[]; +#endif + +#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + +/* + * All the code that may fault while holding an atomic lock must + * place the pointer to the lock in ATOMIC_LOCK_REG so the fault code + * can correctly release and reacquire the lock. Note that we + * mention the register number in a comment in "lib/atomic_asm.S" to help + * assembly coders from using this register by mistake, so if it + * is changed here, change that comment as well. + */ +#define ATOMIC_LOCK_REG 20 +#define ATOMIC_LOCK_REG_NAME r20 + +#ifndef __ASSEMBLY__ +/* Called from setup to initialize a hash table to point to per_cpu locks. */ +void __init_atomic_per_cpu(void); + +#ifdef CONFIG_SMP +/* Support releasing the atomic lock in do_page_fault_ics(). */ +void __atomic_fault_unlock(int *lock_ptr); +#endif +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_ATOMIC_32_H */ diff --git a/arch/tile/include/asm/auxvec.h b/arch/tile/include/asm/auxvec.h new file mode 100644 index 000000000000..1d393edb0641 --- /dev/null +++ b/arch/tile/include/asm/auxvec.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_AUXVEC_H +#define _ASM_TILE_AUXVEC_H + +/* No extensions to auxvec */ + +#endif /* _ASM_TILE_AUXVEC_H */ diff --git a/arch/tile/include/asm/backtrace.h b/arch/tile/include/asm/backtrace.h new file mode 100644 index 000000000000..6970bfcad549 --- /dev/null +++ b/arch/tile/include/asm/backtrace.h @@ -0,0 +1,193 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _TILE_BACKTRACE_H +#define _TILE_BACKTRACE_H + + + +#include + +#include + +#if CHIP_VA_WIDTH() > 32 +typedef unsigned long long VirtualAddress; +#else +typedef unsigned int VirtualAddress; +#endif + + +/** Reads 'size' bytes from 'address' and writes the data to 'result'. + * Returns true if successful, else false (e.g. memory not readable). + */ +typedef bool (*BacktraceMemoryReader)(void *result, + VirtualAddress address, + unsigned int size, + void *extra); + +typedef struct { + /** Current PC. */ + VirtualAddress pc; + + /** Current stack pointer value. */ + VirtualAddress sp; + + /** Current frame pointer value (i.e. caller's stack pointer) */ + VirtualAddress fp; + + /** Internal use only: caller's PC for first frame. */ + VirtualAddress initial_frame_caller_pc; + + /** Internal use only: callback to read memory. */ + BacktraceMemoryReader read_memory_func; + + /** Internal use only: arbitrary argument to read_memory_func. */ + void *read_memory_func_extra; + +} BacktraceIterator; + + +/** Initializes a backtracer to start from the given location. + * + * If the frame pointer cannot be determined it is set to -1. + * + * @param state The state to be filled in. + * @param read_memory_func A callback that reads memory. If NULL, a default + * value is provided. + * @param read_memory_func_extra An arbitrary argument to read_memory_func. + * @param pc The current PC. + * @param lr The current value of the 'lr' register. + * @param sp The current value of the 'sp' register. + * @param r52 The current value of the 'r52' register. + */ +extern void backtrace_init(BacktraceIterator *state, + BacktraceMemoryReader read_memory_func, + void *read_memory_func_extra, + VirtualAddress pc, VirtualAddress lr, + VirtualAddress sp, VirtualAddress r52); + + +/** Advances the backtracing state to the calling frame, returning + * true iff successful. + */ +extern bool backtrace_next(BacktraceIterator *state); + + +typedef enum { + + /* We have no idea what the caller's pc is. */ + PC_LOC_UNKNOWN, + + /* The caller's pc is currently in lr. */ + PC_LOC_IN_LR, + + /* The caller's pc can be found by dereferencing the caller's sp. */ + PC_LOC_ON_STACK + +} CallerPCLocation; + + +typedef enum { + + /* We have no idea what the caller's sp is. */ + SP_LOC_UNKNOWN, + + /* The caller's sp is currently in r52. */ + SP_LOC_IN_R52, + + /* The caller's sp can be found by adding a certain constant + * to the current value of sp. + */ + SP_LOC_OFFSET + +} CallerSPLocation; + + +/* Bit values ORed into CALLER_* values for info ops. */ +enum { + /* Setting the low bit on any of these values means the info op + * applies only to one bundle ago. + */ + ONE_BUNDLE_AGO_FLAG = 1, + + /* Setting this bit on a CALLER_SP_* value means the PC is in LR. + * If not set, PC is on the stack. + */ + PC_IN_LR_FLAG = 2, + + /* This many of the low bits of a CALLER_SP_* value are for the + * flag bits above. + */ + NUM_INFO_OP_FLAGS = 2, + + /* We cannot have one in the memory pipe so this is the maximum. */ + MAX_INFO_OPS_PER_BUNDLE = 2 +}; + + +/** Internal constants used to define 'info' operands. */ +enum { + /* 0 and 1 are reserved, as are all negative numbers. */ + + CALLER_UNKNOWN_BASE = 2, + + CALLER_SP_IN_R52_BASE = 4, + + CALLER_SP_OFFSET_BASE = 8 +}; + + +/** Current backtracer state describing where it thinks the caller is. */ +typedef struct { + /* + * Public fields + */ + + /* How do we find the caller's PC? */ + CallerPCLocation pc_location : 8; + + /* How do we find the caller's SP? */ + CallerSPLocation sp_location : 8; + + /* If sp_location == SP_LOC_OFFSET, then caller_sp == sp + + * loc->sp_offset. Else this field is undefined. + */ + uint16_t sp_offset; + + /* In the most recently visited bundle a terminating bundle? */ + bool at_terminating_bundle; + + /* + * Private fields + */ + + /* Will the forward scanner see someone clobbering sp + * (i.e. changing it with something other than addi sp, sp, N?) + */ + bool sp_clobber_follows; + + /* Operand to next "visible" info op (no more than one bundle past + * the next terminating bundle), or -32768 if none. + */ + int16_t next_info_operand; + + /* Is the info of in next_info_op in the very next bundle? */ + bool is_next_info_operand_adjacent; + +} CallerLocation; + + + + +#endif /* _TILE_BACKTRACE_H */ diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h new file mode 100644 index 000000000000..84600f3514da --- /dev/null +++ b/arch/tile/include/asm/bitops.h @@ -0,0 +1,126 @@ +/* + * Copyright 1992, Linus Torvalds. + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_BITOPS_H +#define _ASM_TILE_BITOPS_H + +#include + +#ifndef _LINUX_BITOPS_H +#error only can be included directly +#endif + +#ifdef __tilegx__ +#include +#else +#include +#endif + +/** + * __ffs - find first set bit in word + * @word: The word to search + * + * Undefined if no set bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + return __builtin_ctzl(word); +} + +/** + * ffz - find first zero bit in word + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +static inline unsigned long ffz(unsigned long word) +{ + return __builtin_ctzl(~word); +} + +/** + * __fls - find last set bit in word + * @word: The word to search + * + * Undefined if no set bit exists, so code should check against 0 first. + */ +static inline unsigned long __fls(unsigned long word) +{ + return (sizeof(word) * 8) - 1 - __builtin_clzl(word); +} + +/** + * ffs - find first set bit in word + * @x: the word to search + * + * This is defined the same way as the libc and compiler builtin ffs + * routines, therefore differs in spirit from the other bitops. + * + * ffs(value) returns 0 if value is 0 or the position of the first + * set bit if value is nonzero. The first (least significant) bit + * is at position 1. + */ +static inline int ffs(int x) +{ + return __builtin_ffs(x); +} + +/** + * fls - find last set bit in word + * @x: the word to search + * + * This is defined in a similar way as the libc and compiler builtin + * ffs, but returns the position of the most significant set bit. + * + * fls(value) returns 0 if value is 0 or the position of the last + * set bit if value is nonzero. The last (most significant) bit is + * at position 32. + */ +static inline int fls(int x) +{ + return (sizeof(int) * 8) - __builtin_clz(x); +} + +static inline int fls64(__u64 w) +{ + return (sizeof(__u64) * 8) - __builtin_clzll(w); +} + +static inline unsigned int hweight32(unsigned int w) +{ + return __builtin_popcount(w); +} + +static inline unsigned int hweight16(unsigned int w) +{ + return __builtin_popcount(w & 0xffff); +} + +static inline unsigned int hweight8(unsigned int w) +{ + return __builtin_popcount(w & 0xff); +} + +static inline unsigned long hweight64(__u64 w) +{ + return __builtin_popcountll(w); +} + +#include +#include +#include +#include + +#endif /* _ASM_TILE_BITOPS_H */ diff --git a/arch/tile/include/asm/bitops_32.h b/arch/tile/include/asm/bitops_32.h new file mode 100644 index 000000000000..7a93c001ac19 --- /dev/null +++ b/arch/tile/include/asm/bitops_32.h @@ -0,0 +1,132 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_BITOPS_32_H +#define _ASM_TILE_BITOPS_32_H + +#include +#include +#include + +/* Tile-specific routines to support . */ +unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask); +unsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask); +unsigned long _atomic_xor(volatile unsigned long *p, unsigned long mask); + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. + * See __set_bit() if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void set_bit(unsigned nr, volatile unsigned long *addr) +{ + _atomic_or(addr + BIT_WORD(nr), BIT_MASK(nr)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. + * See __clear_bit() if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + * + * clear_bit() may not contain a memory barrier, so if it is used for + * locking purposes, you should call smp_mb__before_clear_bit() and/or + * smp_mb__after_clear_bit() to ensure changes are visible on other cpus. + */ +static inline void clear_bit(unsigned nr, volatile unsigned long *addr) +{ + _atomic_andn(addr + BIT_WORD(nr), BIT_MASK(nr)); +} + +/** + * change_bit - Toggle a bit in memory + * @nr: Bit to change + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * See __change_bit() if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void change_bit(unsigned nr, volatile unsigned long *addr) +{ + _atomic_xor(addr + BIT_WORD(nr), BIT_MASK(nr)); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_set_bit(unsigned nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + addr += BIT_WORD(nr); + smp_mb(); /* barrier for proper semantics */ + return (_atomic_or(addr, mask) & mask) != 0; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_clear_bit(unsigned nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + addr += BIT_WORD(nr); + smp_mb(); /* barrier for proper semantics */ + return (_atomic_andn(addr, mask) & mask) != 0; +} + +/** + * test_and_change_bit - Change a bit and return its old value + * @nr: Bit to change + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_change_bit(unsigned nr, + volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + addr += BIT_WORD(nr); + smp_mb(); /* barrier for proper semantics */ + return (_atomic_xor(addr, mask) & mask) != 0; +} + +/* See discussion at smp_mb__before_atomic_dec() in . */ +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() do {} while (0) + +#include +#include + +#endif /* _ASM_TILE_BITOPS_32_H */ diff --git a/arch/tile/include/asm/bitsperlong.h b/arch/tile/include/asm/bitsperlong.h new file mode 100644 index 000000000000..58c771f2af2f --- /dev/null +++ b/arch/tile/include/asm/bitsperlong.h @@ -0,0 +1,26 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_BITSPERLONG_H +#define _ASM_TILE_BITSPERLONG_H + +#ifdef __LP64__ +# define __BITS_PER_LONG 64 +#else +# define __BITS_PER_LONG 32 +#endif + +#include + +#endif /* _ASM_TILE_BITSPERLONG_H */ diff --git a/arch/tile/include/asm/bug.h b/arch/tile/include/asm/bug.h new file mode 100644 index 000000000000..b12fd89e42e9 --- /dev/null +++ b/arch/tile/include/asm/bug.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/bugs.h b/arch/tile/include/asm/bugs.h new file mode 100644 index 000000000000..61791e1ad9f5 --- /dev/null +++ b/arch/tile/include/asm/bugs.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/byteorder.h b/arch/tile/include/asm/byteorder.h new file mode 100644 index 000000000000..9558416d578b --- /dev/null +++ b/arch/tile/include/asm/byteorder.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/cache.h b/arch/tile/include/asm/cache.h new file mode 100644 index 000000000000..c2b7dcfe5327 --- /dev/null +++ b/arch/tile/include/asm/cache.h @@ -0,0 +1,50 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_CACHE_H +#define _ASM_TILE_CACHE_H + +#include + +/* bytes per L1 data cache line */ +#define L1_CACHE_SHIFT CHIP_L1D_LOG_LINE_SIZE() +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1)) & -L1_CACHE_BYTES) + +/* bytes per L1 instruction cache line */ +#define L1I_CACHE_SHIFT CHIP_L1I_LOG_LINE_SIZE() +#define L1I_CACHE_BYTES (1 << L1I_CACHE_SHIFT) +#define L1I_CACHE_ALIGN(x) (((x)+(L1I_CACHE_BYTES-1)) & -L1I_CACHE_BYTES) + +/* bytes per L2 cache line */ +#define L2_CACHE_SHIFT CHIP_L2_LOG_LINE_SIZE() +#define L2_CACHE_BYTES (1 << L2_CACHE_SHIFT) +#define L2_CACHE_ALIGN(x) (((x)+(L2_CACHE_BYTES-1)) & -L2_CACHE_BYTES) + +/* use the cache line size for the L2, which is where it counts */ +#define SMP_CACHE_BYTES_SHIFT L2_CACHE_SHIFT +#define SMP_CACHE_BYTES L2_CACHE_BYTES +#define INTERNODE_CACHE_SHIFT L2_CACHE_SHIFT +#define INTERNODE_CACHE_BYTES L2_CACHE_BYTES + +/* Group together read-mostly things to avoid cache false sharing */ +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + +/* + * Attribute for data that is kept read/write coherent until the end of + * initialization, then bumped to read/only incoherent for performance. + */ +#define __write_once __attribute__((__section__(".w1data"))) + +#endif /* _ASM_TILE_CACHE_H */ diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h new file mode 100644 index 000000000000..7e2096a4ef7d --- /dev/null +++ b/arch/tile/include/asm/cacheflush.h @@ -0,0 +1,145 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_CACHEFLUSH_H +#define _ASM_TILE_CACHEFLUSH_H + +#include + +/* Keep includes the same across arches. */ +#include +#include +#include + +/* Caches are physically-indexed and so don't need special treatment */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) +#define flush_cache_range(vma, start, end) do { } while (0) +#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 +#define flush_dcache_page(page) do { } while (0) +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) +#define flush_icache_page(vma, pg) do { } while (0) +#define flush_icache_user_range(vma, pg, adr, len) do { } while (0) + +/* See "arch/tile/lib/__invalidate_icache.S". */ +extern void __invalidate_icache(unsigned long start, unsigned long size); + +/* Flush the icache just on this cpu */ +static inline void __flush_icache_range(unsigned long start, unsigned long end) +{ + __invalidate_icache(start, end - start); +} + +/* Flush the entire icache on this cpu. */ +#define __flush_icache() __flush_icache_range(0, CHIP_L1I_CACHE_SIZE()) + +#ifdef CONFIG_SMP +/* + * When the kernel writes to its own text we need to do an SMP + * broadcast to make the L1I coherent everywhere. This includes + * module load and single step. + */ +extern void flush_icache_range(unsigned long start, unsigned long end); +#else +#define flush_icache_range __flush_icache_range +#endif + +/* + * An update to an executable user page requires icache flushing. + * We could carefully update only tiles that are running this process, + * and rely on the fact that we flush the icache on every context + * switch to avoid doing extra work here. But for now, I'll be + * conservative and just do a global icache flush. + */ +static inline void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, + void *dst, void *src, int len) +{ + memcpy(dst, src, len); + if (vma->vm_flags & VM_EXEC) { + flush_icache_range((unsigned long) dst, + (unsigned long) dst + len); + } +} + +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ + memcpy((dst), (src), (len)) + +/* + * Invalidate a VA range; pads to L2 cacheline boundaries. + * + * Note that on TILE64, __inv_buffer() actually flushes modified + * cache lines in addition to invalidating them, i.e., it's the + * same as __finv_buffer(). + */ +static inline void __inv_buffer(void *buffer, size_t size) +{ + char *next = (char *)((long)buffer & -L2_CACHE_BYTES); + char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); + while (next < finish) { + __insn_inv(next); + next += CHIP_INV_STRIDE(); + } +} + +/* Flush a VA range; pads to L2 cacheline boundaries. */ +static inline void __flush_buffer(void *buffer, size_t size) +{ + char *next = (char *)((long)buffer & -L2_CACHE_BYTES); + char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); + while (next < finish) { + __insn_flush(next); + next += CHIP_FLUSH_STRIDE(); + } +} + +/* Flush & invalidate a VA range; pads to L2 cacheline boundaries. */ +static inline void __finv_buffer(void *buffer, size_t size) +{ + char *next = (char *)((long)buffer & -L2_CACHE_BYTES); + char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); + while (next < finish) { + __insn_finv(next); + next += CHIP_FINV_STRIDE(); + } +} + + +/* Invalidate a VA range, then memory fence. */ +static inline void inv_buffer(void *buffer, size_t size) +{ + __inv_buffer(buffer, size); + mb_incoherent(); +} + +/* Flush a VA range, then memory fence. */ +static inline void flush_buffer(void *buffer, size_t size) +{ + __flush_buffer(buffer, size); + mb_incoherent(); +} + +/* Flush & invalidate a VA range, then memory fence. */ +static inline void finv_buffer(void *buffer, size_t size) +{ + __finv_buffer(buffer, size); + mb_incoherent(); +} + +#endif /* _ASM_TILE_CACHEFLUSH_H */ diff --git a/arch/tile/include/asm/checksum.h b/arch/tile/include/asm/checksum.h new file mode 100644 index 000000000000..a120766c7264 --- /dev/null +++ b/arch/tile/include/asm/checksum.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_CHECKSUM_H +#define _ASM_TILE_CHECKSUM_H + +#include + +/* Allow us to provide a more optimized do_csum(). */ +__wsum do_csum(const unsigned char *buff, int len); +#define do_csum do_csum + +#endif /* _ASM_TILE_CHECKSUM_H */ diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h new file mode 100644 index 000000000000..e133c53f6c4f --- /dev/null +++ b/arch/tile/include/asm/compat.h @@ -0,0 +1,308 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_COMPAT_H +#define _ASM_TILE_COMPAT_H + +/* + * Architecture specific compatibility types + */ +#include +#include + +#define COMPAT_USER_HZ 100 + +/* "long" and pointer-based types are different. */ +typedef s32 compat_long_t; +typedef u32 compat_ulong_t; +typedef u32 compat_size_t; +typedef s32 compat_ssize_t; +typedef s32 compat_off_t; +typedef s32 compat_time_t; +typedef s32 compat_clock_t; +typedef u32 compat_ino_t; +typedef u32 compat_caddr_t; +typedef u32 compat_uptr_t; + +/* Many types are "int" or otherwise the same. */ +typedef __kernel_pid_t compat_pid_t; +typedef __kernel_uid_t __compat_uid_t; +typedef __kernel_gid_t __compat_gid_t; +typedef __kernel_uid32_t __compat_uid32_t; +typedef __kernel_uid32_t __compat_gid32_t; +typedef __kernel_mode_t compat_mode_t; +typedef __kernel_dev_t compat_dev_t; +typedef __kernel_loff_t compat_loff_t; +typedef __kernel_nlink_t compat_nlink_t; +typedef __kernel_ipc_pid_t compat_ipc_pid_t; +typedef __kernel_daddr_t compat_daddr_t; +typedef __kernel_fsid_t compat_fsid_t; +typedef __kernel_timer_t compat_timer_t; +typedef __kernel_key_t compat_key_t; +typedef int compat_int_t; +typedef s64 compat_s64; +typedef uint compat_uint_t; +typedef u64 compat_u64; + +/* We use the same register dump format in 32-bit images. */ +typedef unsigned long compat_elf_greg_t; +#define COMPAT_ELF_NGREG (sizeof(struct pt_regs) / sizeof(compat_elf_greg_t)) +typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; + +struct compat_timespec { + compat_time_t tv_sec; + s32 tv_nsec; +}; + +struct compat_timeval { + compat_time_t tv_sec; + s32 tv_usec; +}; + +struct compat_stat { + unsigned int st_dev; + unsigned int st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + unsigned int __pad1; + int st_size; + int st_blksize; + int __pad2; + int st_blocks; + int st_atime; + unsigned int st_atime_nsec; + int st_mtime; + unsigned int st_mtime_nsec; + int st_ctime; + unsigned int st_ctime_nsec; + unsigned int __unused[2]; +}; + +struct compat_stat64 { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + long st_size; + unsigned int st_blksize; + unsigned long st_blocks __attribute__((packed)); + unsigned int st_atime; + unsigned int st_atime_nsec; + unsigned int st_mtime; + unsigned int st_mtime_nsec; + unsigned int st_ctime; + unsigned int st_ctime_nsec; + unsigned int __unused8; +}; + +#define compat_statfs statfs + +struct compat_sysctl { + unsigned int name; + int nlen; + unsigned int oldval; + unsigned int oldlenp; + unsigned int newval; + unsigned int newlen; + unsigned int __unused[4]; +}; + + +struct compat_flock { + short l_type; + short l_whence; + compat_off_t l_start; + compat_off_t l_len; + compat_pid_t l_pid; +}; + +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +struct compat_flock64 { + short l_type; + short l_whence; + compat_loff_t l_start; + compat_loff_t l_len; + compat_pid_t l_pid; +}; + +#define COMPAT_RLIM_INFINITY 0xffffffff + +#define _COMPAT_NSIG 64 +#define _COMPAT_NSIG_BPW 32 + +typedef u32 compat_sigset_word; + +#define COMPAT_OFF_T_MAX 0x7fffffff +#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL + +struct compat_ipc64_perm { + compat_key_t key; + __compat_uid32_t uid; + __compat_gid32_t gid; + __compat_uid32_t cuid; + __compat_gid32_t cgid; + unsigned short mode; + unsigned short __pad1; + unsigned short seq; + unsigned short __pad2; + compat_ulong_t unused1; + compat_ulong_t unused2; +}; + +struct compat_semid64_ds { + struct compat_ipc64_perm sem_perm; + compat_time_t sem_otime; + compat_ulong_t __unused1; + compat_time_t sem_ctime; + compat_ulong_t __unused2; + compat_ulong_t sem_nsems; + compat_ulong_t __unused3; + compat_ulong_t __unused4; +}; + +struct compat_msqid64_ds { + struct compat_ipc64_perm msg_perm; + compat_time_t msg_stime; + compat_ulong_t __unused1; + compat_time_t msg_rtime; + compat_ulong_t __unused2; + compat_time_t msg_ctime; + compat_ulong_t __unused3; + compat_ulong_t msg_cbytes; + compat_ulong_t msg_qnum; + compat_ulong_t msg_qbytes; + compat_pid_t msg_lspid; + compat_pid_t msg_lrpid; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; + +struct compat_shmid64_ds { + struct compat_ipc64_perm shm_perm; + compat_size_t shm_segsz; + compat_time_t shm_atime; + compat_ulong_t __unused1; + compat_time_t shm_dtime; + compat_ulong_t __unused2; + compat_time_t shm_ctime; + compat_ulong_t __unused3; + compat_pid_t shm_cpid; + compat_pid_t shm_lpid; + compat_ulong_t shm_nattch; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; + +/* + * A pointer passed in from user mode. This should not + * be used for syscall parameters, just declare them + * as pointers because the syscall entry code will have + * appropriately converted them already. + */ + +static inline void __user *compat_ptr(compat_uptr_t uptr) +{ + return (void __user *)(unsigned long)uptr; +} + +static inline compat_uptr_t ptr_to_compat(void __user *uptr) +{ + return (u32)(unsigned long)uptr; +} + +/* Sign-extend when storing a kernel pointer to a user's ptregs. */ +static inline unsigned long ptr_to_compat_reg(void __user *uptr) +{ + return (long)(int)(long)uptr; +} + +static inline void __user *compat_alloc_user_space(long len) +{ + struct pt_regs *regs = task_pt_regs(current); + return (void __user *)regs->sp - len; +} + +static inline int is_compat_task(void) +{ + return current_thread_info()->status & TS_COMPAT; +} + +extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *set, + struct pt_regs *regs); + +/* Compat syscalls. */ +struct compat_sigaction; +struct compat_siginfo; +struct compat_sigaltstack; +long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, + compat_uptr_t __user *envp); +long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, + struct compat_sigaction __user *oact, + size_t sigsetsize); +long compat_sys_rt_sigqueueinfo(int pid, int sig, + struct compat_siginfo __user *uinfo); +long compat_sys_rt_sigreturn(void); +long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, + struct compat_sigaltstack __user *uoss_ptr); +long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); +long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); +long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, + u32 dummy, u32 low, u32 high); +long compat_sys_pwrite64(unsigned int fd, char __user *ubuf, size_t count, + u32 dummy, u32 low, u32 high); +long compat_sys_lookup_dcookie(u32 low, u32 high, char __user *buf, size_t len); +long compat_sys_sync_file_range2(int fd, unsigned int flags, + u32 offset_lo, u32 offset_hi, + u32 nbytes_lo, u32 nbytes_hi); +long compat_sys_fallocate(int fd, int mode, + u32 offset_lo, u32 offset_hi, + u32 len_lo, u32 len_hi); +long compat_sys_stat64(char __user *filename, + struct compat_stat64 __user *statbuf); +long compat_sys_lstat64(char __user *filename, + struct compat_stat64 __user *statbuf); +long compat_sys_fstat64(unsigned int fd, struct compat_stat64 __user *statbuf); +long compat_sys_fstatat64(int dfd, char __user *filename, + struct compat_stat64 __user *statbuf, int flag); +long compat_sys_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval); +ssize_t compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, + size_t count); + +/* Versions of compat functions that differ from generic Linux. */ +struct compat_msgbuf; +long tile_compat_sys_msgsnd(int msqid, + struct compat_msgbuf __user *msgp, + size_t msgsz, int msgflg); +long tile_compat_sys_msgrcv(int msqid, + struct compat_msgbuf __user *msgp, + size_t msgsz, long msgtyp, int msgflg); +long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data); + +/* Tilera Linux syscalls that don't have "compat" versions. */ +#define compat_sys_raise_fpe sys_raise_fpe +#define compat_sys_flush_cache sys_flush_cache + +#endif /* _ASM_TILE_COMPAT_H */ diff --git a/arch/tile/include/asm/cputime.h b/arch/tile/include/asm/cputime.h new file mode 100644 index 000000000000..6d68ad7e0ea3 --- /dev/null +++ b/arch/tile/include/asm/cputime.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/current.h b/arch/tile/include/asm/current.h new file mode 100644 index 000000000000..da21acf020d3 --- /dev/null +++ b/arch/tile/include/asm/current.h @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_CURRENT_H +#define _ASM_TILE_CURRENT_H + +#include + +struct task_struct; + +static inline struct task_struct *get_current(void) +{ + return current_thread_info()->task; +} +#define current get_current() + +/* Return a usable "task_struct" pointer even if the real one is corrupt. */ +struct task_struct *validate_current(void); + +#endif /* _ASM_TILE_CURRENT_H */ diff --git a/arch/tile/include/asm/delay.h b/arch/tile/include/asm/delay.h new file mode 100644 index 000000000000..97b0e69e704e --- /dev/null +++ b/arch/tile/include/asm/delay.h @@ -0,0 +1,34 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_DELAY_H +#define _ASM_TILE_DELAY_H + +/* Undefined functions to get compile-time errors. */ +extern void __bad_udelay(void); +extern void __bad_ndelay(void); + +extern void __udelay(unsigned long usecs); +extern void __ndelay(unsigned long nsecs); +extern void __delay(unsigned long loops); + +#define udelay(n) (__builtin_constant_p(n) ? \ + ((n) > 20000 ? __bad_udelay() : __ndelay((n) * 1000)) : \ + __udelay(n)) + +#define ndelay(n) (__builtin_constant_p(n) ? \ + ((n) > 20000 ? __bad_ndelay() : __ndelay(n)) : \ + __ndelay(n)) + +#endif /* _ASM_TILE_DELAY_H */ diff --git a/arch/tile/include/asm/device.h b/arch/tile/include/asm/device.h new file mode 100644 index 000000000000..f0a4c256403b --- /dev/null +++ b/arch/tile/include/asm/device.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/div64.h b/arch/tile/include/asm/div64.h new file mode 100644 index 000000000000..6cd978cefb28 --- /dev/null +++ b/arch/tile/include/asm/div64.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h new file mode 100644 index 000000000000..cf466b39aa13 --- /dev/null +++ b/arch/tile/include/asm/dma-mapping.h @@ -0,0 +1,102 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_DMA_MAPPING_H +#define _ASM_TILE_DMA_MAPPING_H + +#include +#include +#include +#include + +/* + * Note that on x86 and powerpc, there is a "struct dma_mapping_ops" + * that is used for all the DMA operations. For now, we don't have an + * equivalent on tile, because we only have a single way of doing DMA. + * (Tilera bug 7994 to use dma_mapping_ops.) + */ + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) + +extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction); +extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction); +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction); +extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nhwentries, enum dma_data_direction); +extern dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction); +extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction); +extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction); +extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction); + + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); + +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +extern void dma_sync_single_for_cpu(struct device *, dma_addr_t, size_t, + enum dma_data_direction); +extern void dma_sync_single_for_device(struct device *, dma_addr_t, + size_t, enum dma_data_direction); +extern void dma_sync_single_range_for_cpu(struct device *, dma_addr_t, + unsigned long offset, size_t, + enum dma_data_direction); +extern void dma_sync_single_range_for_device(struct device *, dma_addr_t, + unsigned long offset, size_t, + enum dma_data_direction); +extern void dma_cache_sync(void *vaddr, size_t, enum dma_data_direction); + +static inline int +dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} + +static inline int +dma_supported(struct device *dev, u64 mask) +{ + return 1; +} + +static inline int +dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} + +static inline int +dma_get_cache_alignment(void) +{ + return L2_CACHE_BYTES; +} + +#define dma_is_consistent(d, h) (1) + + +#endif /* _ASM_TILE_DMA_MAPPING_H */ diff --git a/arch/tile/include/asm/dma.h b/arch/tile/include/asm/dma.h new file mode 100644 index 000000000000..12a7ca16d164 --- /dev/null +++ b/arch/tile/include/asm/dma.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_DMA_H +#define _ASM_TILE_DMA_H + +#include + +/* Needed by drivers/pci/quirks.c */ +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#endif + +#endif /* _ASM_TILE_DMA_H */ diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h new file mode 100644 index 000000000000..1bca0debdb0f --- /dev/null +++ b/arch/tile/include/asm/elf.h @@ -0,0 +1,169 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_ELF_H +#define _ASM_TILE_ELF_H + +/* + * ELF register definitions. + */ + +#include + +#include +#include +#include + +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#define EM_TILE64 187 +#define EM_TILEPRO 188 +#define EM_TILEGX 191 + +/* Provide a nominal data structure. */ +#define ELF_NFPREG 0 +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +#ifdef __tilegx__ +#define ELF_CLASS ELFCLASS64 +#else +#define ELF_CLASS ELFCLASS32 +#endif +#define ELF_DATA ELFDATA2LSB + +/* + * There seems to be a bug in how compat_binfmt_elf.c works: it + * #undefs ELF_ARCH, but it is then used in binfmt_elf.c for fill_note_info(). + * Hack around this by providing an enum value of ELF_ARCH. + */ +enum { ELF_ARCH = CHIP_ELF_TYPE() }; +#define ELF_ARCH ELF_ARCH + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) \ + ((x)->e_ident[EI_CLASS] == ELF_CLASS && \ + ((x)->e_machine == CHIP_ELF_TYPE() || \ + (x)->e_machine == CHIP_COMPAT_ELF_TYPE())) + +/* The module loader only handles a few relocation types. */ +#ifndef __tilegx__ +#define R_TILE_32 1 +#define R_TILE_JOFFLONG_X1 15 +#define R_TILE_IMM16_X0_LO 25 +#define R_TILE_IMM16_X1_LO 26 +#define R_TILE_IMM16_X0_HA 29 +#define R_TILE_IMM16_X1_HA 30 +#else +#define R_TILEGX_64 1 +#define R_TILEGX_JUMPOFF_X1 21 +#define R_TILEGX_IMM16_X0_HW0 36 +#define R_TILEGX_IMM16_X1_HW0 37 +#define R_TILEGX_IMM16_X0_HW1 38 +#define R_TILEGX_IMM16_X1_HW1 39 +#define R_TILEGX_IMM16_X0_HW2_LAST 48 +#define R_TILEGX_IMM16_X1_HW2_LAST 49 +#endif + +/* Use standard page size for core dumps. */ +#define ELF_EXEC_PAGESIZE PAGE_SIZE + +/* + * This is the location that an ET_DYN program is loaded if exec'ed. Typical + * use of this is to invoke "./ld.so someprog" to test out a new version of + * the loader. We need to make sure that it is out of the way of the program + * that it will "exec", and that there is sufficient room for the brk. + */ +#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + +#define ELF_CORE_COPY_REGS(_dest, _regs) \ + memcpy((char *) &_dest, (char *) _regs, \ + sizeof(struct pt_regs)); + +/* No additional FP registers to copy. */ +#define ELF_CORE_COPY_FPREGS(t, fpu) 0 + +/* + * This yields a mask that user programs can use to figure out what + * instruction set this CPU supports. This could be done in user space, + * but it's not easy, and we've already done it here. + */ +#define ELF_HWCAP (0) + +/* + * This yields a string that ld.so will use to load implementation + * specific libraries for optimization. This is more specific in + * intent than poking at uname or /proc/cpuinfo. + */ +#define ELF_PLATFORM (NULL) + +extern void elf_plat_init(struct pt_regs *regs, unsigned long load_addr); + +#define ELF_PLAT_INIT(_r, load_addr) elf_plat_init(_r, load_addr) + +extern int dump_task_regs(struct task_struct *, elf_gregset_t *); +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) + +/* Tilera Linux has no personalities currently, so no need to do anything. */ +#define SET_PERSONALITY(ex) do { } while (0) + +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES +/* Support auto-mapping of the user interrupt vectors. */ +struct linux_binprm; +extern int arch_setup_additional_pages(struct linux_binprm *bprm, + int executable_stack); +#ifdef CONFIG_COMPAT + +#define COMPAT_ELF_PLATFORM "tilegx-m32" + +/* + * "Compat" binaries have the same machine type, but 32-bit class, + * since they're not a separate machine type, but just a 32-bit + * variant of the standard 64-bit architecture. + */ +#define compat_elf_check_arch(x) \ + ((x)->e_ident[EI_CLASS] == ELFCLASS32 && \ + ((x)->e_machine == CHIP_ELF_TYPE() || \ + (x)->e_machine == CHIP_COMPAT_ELF_TYPE())) + +#define compat_start_thread(regs, ip, usp) do { \ + regs->pc = ptr_to_compat_reg((void *)(ip)); \ + regs->sp = ptr_to_compat_reg((void *)(usp)); \ + } while (0) + +/* + * Use SET_PERSONALITY to indicate compatibility via TS_COMPAT. + */ +#undef SET_PERSONALITY +#define SET_PERSONALITY(ex) \ +do { \ + current->personality = PER_LINUX; \ + current_thread_info()->status &= ~TS_COMPAT; \ +} while (0) +#define COMPAT_SET_PERSONALITY(ex) \ +do { \ + current->personality = PER_LINUX_32BIT; \ + current_thread_info()->status |= TS_COMPAT; \ +} while (0) + +#define COMPAT_ELF_ET_DYN_BASE (0xffffffff / 3 * 2) + +#endif /* CONFIG_COMPAT */ + +#endif /* _ASM_TILE_ELF_H */ diff --git a/arch/tile/include/asm/emergency-restart.h b/arch/tile/include/asm/emergency-restart.h new file mode 100644 index 000000000000..3711bd9d50bd --- /dev/null +++ b/arch/tile/include/asm/emergency-restart.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/errno.h b/arch/tile/include/asm/errno.h new file mode 100644 index 000000000000..4c82b503d92f --- /dev/null +++ b/arch/tile/include/asm/errno.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/fcntl.h b/arch/tile/include/asm/fcntl.h new file mode 100644 index 000000000000..46ab12db5739 --- /dev/null +++ b/arch/tile/include/asm/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/fixmap.h b/arch/tile/include/asm/fixmap.h new file mode 100644 index 000000000000..51537ff9265a --- /dev/null +++ b/arch/tile/include/asm/fixmap.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 1998 Ingo Molnar + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_FIXMAP_H +#define _ASM_TILE_FIXMAP_H + +#include + +#ifndef __ASSEMBLY__ +#include +#ifdef CONFIG_HIGHMEM +#include +#include +#endif + +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) +#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) + +/* + * Here we define all the compile-time 'special' virtual + * addresses. The point is to have a constant address at + * compile time, but to set the physical address only + * in the boot process. We allocate these special addresses + * from the end of supervisor virtual memory backwards. + * Also this lets us do fail-safe vmalloc(), we + * can guarantee that these special addresses and + * vmalloc()-ed addresses never overlap. + * + * these 'compile-time allocated' memory buffers are + * fixed-size 4k pages. (or larger if used with an increment + * higher than 1) use fixmap_set(idx,phys) to associate + * physical memory with fixmap indices. + * + * TLB entries of such buffers will not be flushed across + * task switches. + * + * We don't bother with a FIX_HOLE since above the fixmaps + * is unmapped memory in any case. + */ +enum fixed_addresses { +#ifdef CONFIG_HIGHMEM + FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ + FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, +#endif + __end_of_permanent_fixed_addresses, + + /* + * Temporary boot-time mappings, used before ioremap() is functional. + * Not currently needed by the Tile architecture. + */ +#define NR_FIX_BTMAPS 0 +#if NR_FIX_BTMAPS + FIX_BTMAP_END = __end_of_permanent_fixed_addresses, + FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1, + __end_of_fixed_addresses +#else + __end_of_fixed_addresses = __end_of_permanent_fixed_addresses +#endif +}; + +extern void __set_fixmap(enum fixed_addresses idx, + unsigned long phys, pgprot_t flags); + +#define set_fixmap(idx, phys) \ + __set_fixmap(idx, phys, PAGE_KERNEL) +/* + * Some hardware wants to get fixmapped without caching. + */ +#define set_fixmap_nocache(idx, phys) \ + __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) + +#define clear_fixmap(idx) \ + __set_fixmap(idx, 0, __pgprot(0)) + +#define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) +#define __FIXADDR_BOOT_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) +#define FIXADDR_START (FIXADDR_TOP + PAGE_SIZE - __FIXADDR_SIZE) +#define FIXADDR_BOOT_START (FIXADDR_TOP + PAGE_SIZE - __FIXADDR_BOOT_SIZE) + +extern void __this_fixmap_does_not_exist(void); + +/* + * 'index to address' translation. If anyone tries to use the idx + * directly without tranlation, we catch the bug with a NULL-deference + * kernel oops. Illegal ranges of incoming indices are caught too. + */ +static __always_inline unsigned long fix_to_virt(const unsigned int idx) +{ + /* + * this branch gets completely eliminated after inlining, + * except when someone tries to use fixaddr indices in an + * illegal way. (such as mixing up address types or using + * out-of-range indices). + * + * If it doesn't get removed, the linker will complain + * loudly with a reasonably clear error message.. + */ + if (idx >= __end_of_fixed_addresses) + __this_fixmap_does_not_exist(); + + return __fix_to_virt(idx); +} + +static inline unsigned long virt_to_fix(const unsigned long vaddr) +{ + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); + return __virt_to_fix(vaddr); +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_FIXMAP_H */ diff --git a/arch/tile/include/asm/ftrace.h b/arch/tile/include/asm/ftrace.h new file mode 100644 index 000000000000..461459b06d98 --- /dev/null +++ b/arch/tile/include/asm/ftrace.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_FTRACE_H +#define _ASM_TILE_FTRACE_H + +/* empty */ + +#endif /* _ASM_TILE_FTRACE_H */ diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h new file mode 100644 index 000000000000..9eaeb3c08786 --- /dev/null +++ b/arch/tile/include/asm/futex.h @@ -0,0 +1,136 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * These routines make two important assumptions: + * + * 1. atomic_t is really an int and can be freely cast back and forth + * (validated in __init_atomic_per_cpu). + * + * 2. userspace uses sys_cmpxchg() for all atomic operations, thus using + * the same locking convention that all the kernel atomic routines use. + */ + +#ifndef _ASM_TILE_FUTEX_H +#define _ASM_TILE_FUTEX_H + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +extern struct __get_user futex_set(int *v, int i); +extern struct __get_user futex_add(int *v, int n); +extern struct __get_user futex_or(int *v, int n); +extern struct __get_user futex_andn(int *v, int n); +extern struct __get_user futex_cmpxchg(int *v, int o, int n); + +#ifndef __tilegx__ +extern struct __get_user futex_xor(int *v, int n); +#else +static inline struct __get_user futex_xor(int __user *uaddr, int n) +{ + struct __get_user asm_ret = __get_user_4(uaddr); + if (!asm_ret.err) { + int oldval, newval; + do { + oldval = asm_ret.val; + newval = oldval ^ n; + asm_ret = futex_cmpxchg(uaddr, oldval, newval); + } while (asm_ret.err == 0 && oldval != asm_ret.val); + } + return asm_ret; +} +#endif + +static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int ret; + struct __get_user asm_ret; + + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + pagefault_disable(); + switch (op) { + case FUTEX_OP_SET: + asm_ret = futex_set(uaddr, oparg); + break; + case FUTEX_OP_ADD: + asm_ret = futex_add(uaddr, oparg); + break; + case FUTEX_OP_OR: + asm_ret = futex_or(uaddr, oparg); + break; + case FUTEX_OP_ANDN: + asm_ret = futex_andn(uaddr, oparg); + break; + case FUTEX_OP_XOR: + asm_ret = futex_xor(uaddr, oparg); + break; + default: + asm_ret.err = -ENOSYS; + } + pagefault_enable(); + + ret = asm_ret.err; + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: + ret = (asm_ret.val == cmparg); + break; + case FUTEX_OP_CMP_NE: + ret = (asm_ret.val != cmparg); + break; + case FUTEX_OP_CMP_LT: + ret = (asm_ret.val < cmparg); + break; + case FUTEX_OP_CMP_GE: + ret = (asm_ret.val >= cmparg); + break; + case FUTEX_OP_CMP_LE: + ret = (asm_ret.val <= cmparg); + break; + case FUTEX_OP_CMP_GT: + ret = (asm_ret.val > cmparg); + break; + default: + ret = -ENOSYS; + } + } + return ret; +} + +static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, + int newval) +{ + struct __get_user asm_ret; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + asm_ret = futex_cmpxchg(uaddr, oldval, newval); + return asm_ret.err ? asm_ret.err : asm_ret.val; +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_FUTEX_H */ diff --git a/arch/tile/include/asm/hardirq.h b/arch/tile/include/asm/hardirq.h new file mode 100644 index 000000000000..822390f9a154 --- /dev/null +++ b/arch/tile/include/asm/hardirq.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_HARDIRQ_H +#define _ASM_TILE_HARDIRQ_H + +#include +#include + +#include + +typedef struct { + unsigned int __softirq_pending; + long idle_timestamp; + + /* Hard interrupt statistics. */ + unsigned int irq_timer_count; + unsigned int irq_syscall_count; + unsigned int irq_resched_count; + unsigned int irq_hv_flush_count; + unsigned int irq_call_count; + unsigned int irq_hv_msg_count; + unsigned int irq_dev_intr_count; + +} ____cacheline_aligned irq_cpustat_t; + +DECLARE_PER_CPU(irq_cpustat_t, irq_stat); + +#define __ARCH_IRQ_STAT +#define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member) + +#include /* Standard mappings for irq_cpustat_t above */ + +#define HARDIRQ_BITS 8 + +#endif /* _ASM_TILE_HARDIRQ_H */ diff --git a/arch/tile/include/asm/highmem.h b/arch/tile/include/asm/highmem.h new file mode 100644 index 000000000000..efdd12e91020 --- /dev/null +++ b/arch/tile/include/asm/highmem.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual addresses. + * + */ + +#ifndef _ASM_TILE_HIGHMEM_H +#define _ASM_TILE_HIGHMEM_H + +#include +#include +#include +#include +#include + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *pkmap_page_table; + +/* + * Ordering is: + * + * FIXADDR_TOP + * fixed_addresses + * FIXADDR_START + * temp fixed addresses + * FIXADDR_BOOT_START + * Persistent kmap area + * PKMAP_BASE + * VMALLOC_END + * Vmalloc area + * VMALLOC_START + * high_memory + */ +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +void *kmap_high(struct page *page); +void kunmap_high(struct page *page); +void *kmap(struct page *page); +void kunmap(struct page *page); +void *kmap_fix_kpte(struct page *page, int finished); + +/* This macro is used only in map_new_virtual() to map "page". */ +#define kmap_prot page_to_kpgprot(page) + +void kunmap_atomic(void *kvaddr, enum km_type type); +void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); +void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); +struct page *kmap_atomic_to_page(void *ptr); +void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot); +void *kmap_atomic(struct page *page, enum km_type type); +void kmap_atomic_fix_kpte(struct page *page, int finished); + +#define flush_cache_kmaps() do { } while (0) + +#endif /* _ASM_TILE_HIGHMEM_H */ diff --git a/arch/tile/include/asm/homecache.h b/arch/tile/include/asm/homecache.h new file mode 100644 index 000000000000..a8243865d49e --- /dev/null +++ b/arch/tile/include/asm/homecache.h @@ -0,0 +1,125 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Handle issues around the Tile "home cache" model of coherence. + */ + +#ifndef _ASM_TILE_HOMECACHE_H +#define _ASM_TILE_HOMECACHE_H + +#include +#include + +struct page; +struct task_struct; +struct vm_area_struct; +struct zone; + +/* + * Coherence point for the page is its memory controller. + * It is not present in any cache (L1 or L2). + */ +#define PAGE_HOME_UNCACHED -1 + +/* + * Is this page immutable (unwritable) and thus able to be cached more + * widely than would otherwise be possible? On tile64 this means we + * mark the PTE to cache locally; on tilepro it means we have "nc" set. + */ +#define PAGE_HOME_IMMUTABLE -2 + +/* + * Each cpu considers its own cache to be the home for the page, + * which makes it incoherent. + */ +#define PAGE_HOME_INCOHERENT -3 + +#if CHIP_HAS_CBOX_HOME_MAP() +/* Home for the page is distributed via hash-for-home. */ +#define PAGE_HOME_HASH -4 +#endif + +/* Homing is unknown or unspecified. Not valid for page_home(). */ +#define PAGE_HOME_UNKNOWN -5 + +/* Home on the current cpu. Not valid for page_home(). */ +#define PAGE_HOME_HERE -6 + +/* Support wrapper to use instead of explicit hv_flush_remote(). */ +extern void flush_remote(unsigned long cache_pfn, unsigned long cache_length, + const struct cpumask *cache_cpumask, + HV_VirtAddr tlb_va, unsigned long tlb_length, + unsigned long tlb_pgsize, + const struct cpumask *tlb_cpumask, + HV_Remote_ASID *asids, int asidcount); + +/* Set homing-related bits in a PTE (can also pass a pgprot_t). */ +extern pte_t pte_set_home(pte_t pte, int home); + +/* Do a cache eviction on the specified cpus. */ +extern void homecache_evict(const struct cpumask *mask); + +/* + * Change a kernel page's homecache. It must not be mapped in user space. + * If !CONFIG_HOMECACHE, only usable on LOWMEM, and can only be called when + * no other cpu can reference the page, and causes a full-chip cache/TLB flush. + */ +extern void homecache_change_page_home(struct page *, int order, int home); + +/* + * Flush a page out of whatever cache(s) it is in. + * This is more than just finv, since it properly handles waiting + * for the data to reach memory on tilepro, but it can be quite + * heavyweight, particularly on hash-for-home memory. + */ +extern void homecache_flush_cache(struct page *, int order); + +/* + * Allocate a page with the given GFP flags, home, and optionally + * node. These routines are actually just wrappers around the normal + * alloc_pages() / alloc_pages_node() functions, which set and clear + * a per-cpu variable to communicate with homecache_new_kernel_page(). + * If !CONFIG_HOMECACHE, uses homecache_change_page_home(). + */ +extern struct page *homecache_alloc_pages(gfp_t gfp_mask, + unsigned int order, int home); +extern struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask, + unsigned int order, int home); +#define homecache_alloc_page(gfp_mask, home) \ + homecache_alloc_pages(gfp_mask, 0, home) + +/* + * These routines are just pass-throughs to free_pages() when + * we support full homecaching. If !CONFIG_HOMECACHE, then these + * routines use homecache_change_page_home() to reset the home + * back to the default before returning the page to the allocator. + */ +void homecache_free_pages(unsigned long addr, unsigned int order); +#define homecache_free_page(page) \ + homecache_free_pages((page), 0) + + + +/* + * Report the page home for LOWMEM pages by examining their kernel PTE, + * or for highmem pages as the default home. + */ +extern int page_home(struct page *); + +#define homecache_migrate_kthread() do {} while (0) + +#define homecache_kpte_lock() 0 +#define homecache_kpte_unlock(flags) do {} while (0) + + +#endif /* _ASM_TILE_HOMECACHE_H */ diff --git a/arch/tile/include/asm/hugetlb.h b/arch/tile/include/asm/hugetlb.h new file mode 100644 index 000000000000..0521c277bbde --- /dev/null +++ b/arch/tile/include/asm/hugetlb.h @@ -0,0 +1,109 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_HUGETLB_H +#define _ASM_TILE_HUGETLB_H + +#include + + +static inline int is_hugepage_only_range(struct mm_struct *mm, + unsigned long addr, + unsigned long len) { + return 0; +} + +/* + * If the arch doesn't supply something else, assume that hugepage + * size aligned regions are ok without further preparation. + */ +static inline int prepare_hugepage_range(struct file *file, + unsigned long addr, unsigned long len) +{ + struct hstate *h = hstate_file(file); + if (len & ~huge_page_mask(h)) + return -EINVAL; + if (addr & ~huge_page_mask(h)) + return -EINVAL; + return 0; +} + +static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) +{ +} + +static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, + unsigned long addr, unsigned long end, + unsigned long floor, + unsigned long ceiling) +{ + free_pgd_range(tlb, addr, end, floor, ceiling); +} + +static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) +{ + set_pte_order(ptep, pte, HUGETLB_PAGE_ORDER); +} + +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + return ptep_get_and_clear(mm, addr, ptep); +} + +static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) +{ + ptep_clear_flush(vma, addr, ptep); +} + +static inline int huge_pte_none(pte_t pte) +{ + return pte_none(pte); +} + +static inline pte_t huge_pte_wrprotect(pte_t pte) +{ + return pte_wrprotect(pte); +} + +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + ptep_set_wrprotect(mm, addr, ptep); +} + +static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep, + pte_t pte, int dirty) +{ + return ptep_set_access_flags(vma, addr, ptep, pte, dirty); +} + +static inline pte_t huge_ptep_get(pte_t *ptep) +{ + return *ptep; +} + +static inline int arch_prepare_hugepage(struct page *page) +{ + return 0; +} + +static inline void arch_release_hugepage(struct page *page) +{ +} + +#endif /* _ASM_TILE_HUGETLB_H */ diff --git a/arch/tile/include/asm/hv_driver.h b/arch/tile/include/asm/hv_driver.h new file mode 100644 index 000000000000..ad614de899b3 --- /dev/null +++ b/arch/tile/include/asm/hv_driver.h @@ -0,0 +1,60 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This header defines a wrapper interface for managing hypervisor + * device calls that will result in an interrupt at some later time. + * In particular, this provides wrappers for hv_preada() and + * hv_pwritea(). + */ + +#ifndef _ASM_TILE_HV_DRIVER_H +#define _ASM_TILE_HV_DRIVER_H + +#include + +struct hv_driver_cb; + +/* A callback to be invoked when an operation completes. */ +typedef void hv_driver_callback_t(struct hv_driver_cb *cb, __hv32 result); + +/* + * A structure to hold information about an outstanding call. + * The driver must allocate a separate structure for each call. + */ +struct hv_driver_cb { + hv_driver_callback_t *callback; /* Function to call on interrupt. */ + void *dev; /* Driver-specific state variable. */ +}; + +/* Wrapper for invoking hv_dev_preada(). */ +static inline int +tile_hv_dev_preada(int devhdl, __hv32 flags, __hv32 sgl_len, + HV_SGL sgl[/* sgl_len */], __hv64 offset, + struct hv_driver_cb *callback) +{ + return hv_dev_preada(devhdl, flags, sgl_len, sgl, + offset, (HV_IntArg)callback); +} + +/* Wrapper for invoking hv_dev_pwritea(). */ +static inline int +tile_hv_dev_pwritea(int devhdl, __hv32 flags, __hv32 sgl_len, + HV_SGL sgl[/* sgl_len */], __hv64 offset, + struct hv_driver_cb *callback) +{ + return hv_dev_pwritea(devhdl, flags, sgl_len, sgl, + offset, (HV_IntArg)callback); +} + + +#endif /* _ASM_TILE_HV_DRIVER_H */ diff --git a/arch/tile/include/asm/hw_irq.h b/arch/tile/include/asm/hw_irq.h new file mode 100644 index 000000000000..4fac5fbf333e --- /dev/null +++ b/arch/tile/include/asm/hw_irq.h @@ -0,0 +1,18 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_HW_IRQ_H +#define _ASM_TILE_HW_IRQ_H + +#endif /* _ASM_TILE_HW_IRQ_H */ diff --git a/arch/tile/include/asm/ide.h b/arch/tile/include/asm/ide.h new file mode 100644 index 000000000000..3c6f2ed894ce --- /dev/null +++ b/arch/tile/include/asm/ide.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_IDE_H +#define _ASM_TILE_IDE_H + +/* For IDE on PCI */ +#define MAX_HWIFS 10 + +#define ide_default_io_ctl(base) (0) + +#include + +#endif /* _ASM_TILE_IDE_H */ diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h new file mode 100644 index 000000000000..8c95bef3fa45 --- /dev/null +++ b/arch/tile/include/asm/io.h @@ -0,0 +1,279 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_IO_H +#define _ASM_TILE_IO_H + +#include +#include +#include + +#define IO_SPACE_LIMIT 0xfffffffful + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access. + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer. + */ +#define xlate_dev_kmem_ptr(p) p + +/* + * Change "struct page" to physical address. + */ +#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) + +/* + * Some places try to pass in an loff_t for PHYSADDR (?!), so we cast it to + * long before casting it to a pointer to avoid compiler warnings. + */ +#if CHIP_HAS_MMIO() +extern void __iomem *ioremap(resource_size_t offset, unsigned long size); +extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, + pgprot_t pgprot); +extern void iounmap(volatile void __iomem *addr); +#else +#define ioremap(physaddr, size) ((void __iomem *)(unsigned long)(physaddr)) +#define iounmap(addr) ((void)0) +#endif + +#define ioremap_nocache(physaddr, size) ioremap(physaddr, size) +#define ioremap_writethrough(physaddr, size) ioremap(physaddr, size) +#define ioremap_fullcache(physaddr, size) ioremap(physaddr, size) + +void __iomem *ioport_map(unsigned long port, unsigned int len); +extern inline void ioport_unmap(void __iomem *addr) {} + +#define mmiowb() + +/* Conversion between virtual and physical mappings. */ +#define mm_ptov(addr) ((void *)phys_to_virt(addr)) +#define mm_vtop(addr) ((unsigned long)virt_to_phys(addr)) + +#ifdef CONFIG_PCI + +extern u8 _tile_readb(unsigned long addr); +extern u16 _tile_readw(unsigned long addr); +extern u32 _tile_readl(unsigned long addr); +extern u64 _tile_readq(unsigned long addr); +extern void _tile_writeb(u8 val, unsigned long addr); +extern void _tile_writew(u16 val, unsigned long addr); +extern void _tile_writel(u32 val, unsigned long addr); +extern void _tile_writeq(u64 val, unsigned long addr); + +#else + +/* + * The Tile architecture does not support IOMEM unless PCI is enabled. + * Unfortunately we can't yet simply not declare these methods, + * since some generic code that compiles into the kernel, but + * we never run, uses them unconditionally. + */ + +static inline int iomem_panic(void) +{ + panic("readb/writeb and friends do not exist on tile without PCI"); + return 0; +} + +static inline u8 _tile_readb(unsigned long addr) +{ + return iomem_panic(); +} + +static inline u16 _tile_readw(unsigned long addr) +{ + return iomem_panic(); +} + +static inline u32 _tile_readl(unsigned long addr) +{ + return iomem_panic(); +} + +static inline u64 _tile_readq(unsigned long addr) +{ + return iomem_panic(); +} + +static inline void _tile_writeb(u8 val, unsigned long addr) +{ + iomem_panic(); +} + +static inline void _tile_writew(u16 val, unsigned long addr) +{ + iomem_panic(); +} + +static inline void _tile_writel(u32 val, unsigned long addr) +{ + iomem_panic(); +} + +static inline void _tile_writeq(u64 val, unsigned long addr) +{ + iomem_panic(); +} + +#endif + +#define readb(addr) _tile_readb((unsigned long)addr) +#define readw(addr) _tile_readw((unsigned long)addr) +#define readl(addr) _tile_readl((unsigned long)addr) +#define readq(addr) _tile_readq((unsigned long)addr) +#define writeb(val, addr) _tile_writeb(val, (unsigned long)addr) +#define writew(val, addr) _tile_writew(val, (unsigned long)addr) +#define writel(val, addr) _tile_writel(val, (unsigned long)addr) +#define writeq(val, addr) _tile_writeq(val, (unsigned long)addr) + +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl +#define __raw_readq readq +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel +#define __raw_writeq writeq + +#define readb_relaxed readb +#define readw_relaxed readw +#define readl_relaxed readl +#define readq_relaxed readq + +#define ioread8 readb +#define ioread16 readw +#define ioread32 readl +#define ioread64 readq +#define iowrite8 writeb +#define iowrite16 writew +#define iowrite32 writel +#define iowrite64 writeq + +static inline void *memcpy_fromio(void *dst, void *src, int len) +{ + int x; + BUG_ON((unsigned long)src & 0x3); + for (x = 0; x < len; x += 4) + *(u32 *)(dst + x) = readl(src + x); + return dst; +} + +static inline void *memcpy_toio(void *dst, void *src, int len) +{ + int x; + BUG_ON((unsigned long)dst & 0x3); + for (x = 0; x < len; x += 4) + writel(*(u32 *)(src + x), dst + x); + return dst; +} + +/* + * The Tile architecture does not support IOPORT, even with PCI. + * Unfortunately we can't yet simply not declare these methods, + * since some generic code that compiles into the kernel, but + * we never run, uses them unconditionally. + */ + +static inline int ioport_panic(void) +{ + panic("inb/outb and friends do not exist on tile"); + return 0; +} + +static inline u8 inb(unsigned long addr) +{ + return ioport_panic(); +} + +static inline u16 inw(unsigned long addr) +{ + return ioport_panic(); +} + +static inline u32 inl(unsigned long addr) +{ + return ioport_panic(); +} + +static inline void outb(u8 b, unsigned long addr) +{ + ioport_panic(); +} + +static inline void outw(u16 b, unsigned long addr) +{ + ioport_panic(); +} + +static inline void outl(u32 b, unsigned long addr) +{ + ioport_panic(); +} + +#define inb_p(addr) inb(addr) +#define inw_p(addr) inw(addr) +#define inl_p(addr) inl(addr) +#define outb_p(x, addr) outb((x), (addr)) +#define outw_p(x, addr) outw((x), (addr)) +#define outl_p(x, addr) outl((x), (addr)) + +static inline void insb(unsigned long addr, void *buffer, int count) +{ + ioport_panic(); +} + +static inline void insw(unsigned long addr, void *buffer, int count) +{ + ioport_panic(); +} + +static inline void insl(unsigned long addr, void *buffer, int count) +{ + ioport_panic(); +} + +static inline void outsb(unsigned long addr, const void *buffer, int count) +{ + ioport_panic(); +} + +static inline void outsw(unsigned long addr, const void *buffer, int count) +{ + ioport_panic(); +} + +static inline void outsl(unsigned long addr, const void *buffer, int count) +{ + ioport_panic(); +} + +#define ioread8_rep(p, dst, count) \ + insb((unsigned long) (p), (dst), (count)) +#define ioread16_rep(p, dst, count) \ + insw((unsigned long) (p), (dst), (count)) +#define ioread32_rep(p, dst, count) \ + insl((unsigned long) (p), (dst), (count)) + +#define iowrite8_rep(p, src, count) \ + outsb((unsigned long) (p), (src), (count)) +#define iowrite16_rep(p, src, count) \ + outsw((unsigned long) (p), (src), (count)) +#define iowrite32_rep(p, src, count) \ + outsl((unsigned long) (p), (src), (count)) + +#endif /* _ASM_TILE_IO_H */ diff --git a/arch/tile/include/asm/ioctl.h b/arch/tile/include/asm/ioctl.h new file mode 100644 index 000000000000..b279fe06dfe5 --- /dev/null +++ b/arch/tile/include/asm/ioctl.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/ioctls.h b/arch/tile/include/asm/ioctls.h new file mode 100644 index 000000000000..ec34c760665e --- /dev/null +++ b/arch/tile/include/asm/ioctls.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/ipc.h b/arch/tile/include/asm/ipc.h new file mode 100644 index 000000000000..a46e3d9c2a3f --- /dev/null +++ b/arch/tile/include/asm/ipc.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/ipcbuf.h b/arch/tile/include/asm/ipcbuf.h new file mode 100644 index 000000000000..84c7e51cb6d0 --- /dev/null +++ b/arch/tile/include/asm/ipcbuf.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/irq.h b/arch/tile/include/asm/irq.h new file mode 100644 index 000000000000..9be1f849fac9 --- /dev/null +++ b/arch/tile/include/asm/irq.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_IRQ_H +#define _ASM_TILE_IRQ_H + +#include + +/* The hypervisor interface provides 32 IRQs. */ +#define NR_IRQS 32 + +/* IRQ numbers used for linux IPIs. */ +#define IRQ_RESCHEDULE 1 + +/* The HV interrupt state object. */ +DECLARE_PER_CPU(HV_IntrState, dev_intr_state); + +void ack_bad_irq(unsigned int irq); + +/* + * Paravirtualized drivers should call this when their init calls + * discover a valid HV IRQ. + */ +void tile_irq_activate(unsigned int irq); + +#endif /* _ASM_TILE_IRQ_H */ diff --git a/arch/tile/include/asm/irq_regs.h b/arch/tile/include/asm/irq_regs.h new file mode 100644 index 000000000000..3dd9c0b70270 --- /dev/null +++ b/arch/tile/include/asm/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h new file mode 100644 index 000000000000..cf5bffd00fef --- /dev/null +++ b/arch/tile/include/asm/irqflags.h @@ -0,0 +1,267 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_IRQFLAGS_H +#define _ASM_TILE_IRQFLAGS_H + +#include +#include +#include + +/* + * The set of interrupts we want to allow when interrupts are nominally + * disabled. The remainder are effectively "NMI" interrupts from + * the point of view of the generic Linux code. Note that synchronous + * interrupts (aka "non-queued") are not blocked by the mask in any case. + */ +#if CHIP_HAS_AUX_PERF_COUNTERS() +#define LINUX_MASKABLE_INTERRUPTS \ + (~(INT_MASK(INT_PERF_COUNT) | INT_MASK(INT_AUX_PERF_COUNT))) +#else +#define LINUX_MASKABLE_INTERRUPTS \ + (~(INT_MASK(INT_PERF_COUNT))) +#endif + +#ifndef __ASSEMBLY__ + +/* NOTE: we can't include due to #include dependencies. */ +#include +#include + +/* Set and clear kernel interrupt masks. */ +#if CHIP_HAS_SPLIT_INTR_MASK() +#if INT_PERF_COUNT < 32 || INT_AUX_PERF_COUNT < 32 || INT_MEM_ERROR >= 32 +# error Fix assumptions about which word various interrupts are in +#endif +#define interrupt_mask_set(n) do { \ + int __n = (n); \ + int __mask = 1 << (__n & 0x1f); \ + if (__n < 32) \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, __mask); \ + else \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, __mask); \ +} while (0) +#define interrupt_mask_reset(n) do { \ + int __n = (n); \ + int __mask = 1 << (__n & 0x1f); \ + if (__n < 32) \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, __mask); \ + else \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, __mask); \ +} while (0) +#define interrupt_mask_check(n) ({ \ + int __n = (n); \ + (((__n < 32) ? \ + __insn_mfspr(SPR_INTERRUPT_MASK_1_0) : \ + __insn_mfspr(SPR_INTERRUPT_MASK_1_1)) \ + >> (__n & 0x1f)) & 1; \ +}) +#define interrupt_mask_set_mask(mask) do { \ + unsigned long long __m = (mask); \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, (unsigned long)(__m)); \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, (unsigned long)(__m>>32)); \ +} while (0) +#define interrupt_mask_reset_mask(mask) do { \ + unsigned long long __m = (mask); \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, (unsigned long)(__m)); \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, (unsigned long)(__m>>32)); \ +} while (0) +#else +#define interrupt_mask_set(n) \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (1UL << (n))) +#define interrupt_mask_reset(n) \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (1UL << (n))) +#define interrupt_mask_check(n) \ + ((__insn_mfspr(SPR_INTERRUPT_MASK_1) >> (n)) & 1) +#define interrupt_mask_set_mask(mask) \ + __insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (mask)) +#define interrupt_mask_reset_mask(mask) \ + __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (mask)) +#endif + +/* + * The set of interrupts we want active if irqs are enabled. + * Note that in particular, the tile timer interrupt comes and goes + * from this set, since we have no other way to turn off the timer. + * Likewise, INTCTRL_1 is removed and re-added during device + * interrupts, as is the the hardwall UDN_FIREWALL interrupt. + * We use a low bit (MEM_ERROR) as our sentinel value and make sure it + * is always claimed as an "active interrupt" so we can query that bit + * to know our current state. + */ +DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask); +#define INITIAL_INTERRUPTS_ENABLED INT_MASK(INT_MEM_ERROR) + +/* Disable interrupts. */ +#define raw_local_irq_disable() \ + interrupt_mask_set_mask(LINUX_MASKABLE_INTERRUPTS) + +/* Disable all interrupts, including NMIs. */ +#define raw_local_irq_disable_all() \ + interrupt_mask_set_mask(-1UL) + +/* Re-enable all maskable interrupts. */ +#define raw_local_irq_enable() \ + interrupt_mask_reset_mask(__get_cpu_var(interrupts_enabled_mask)) + +/* Disable or enable interrupts based on flag argument. */ +#define raw_local_irq_restore(disabled) do { \ + if (disabled) \ + raw_local_irq_disable(); \ + else \ + raw_local_irq_enable(); \ +} while (0) + +/* Return true if "flags" argument means interrupts are disabled. */ +#define raw_irqs_disabled_flags(flags) ((flags) != 0) + +/* Return true if interrupts are currently disabled. */ +#define raw_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR) + +/* Save whether interrupts are currently disabled. */ +#define raw_local_save_flags(flags) ((flags) = raw_irqs_disabled()) + +/* Save whether interrupts are currently disabled, then disable them. */ +#define raw_local_irq_save(flags) \ + do { raw_local_save_flags(flags); raw_local_irq_disable(); } while (0) + +/* Prevent the given interrupt from being enabled next time we enable irqs. */ +#define raw_local_irq_mask(interrupt) \ + (__get_cpu_var(interrupts_enabled_mask) &= ~INT_MASK(interrupt)) + +/* Prevent the given interrupt from being enabled immediately. */ +#define raw_local_irq_mask_now(interrupt) do { \ + raw_local_irq_mask(interrupt); \ + interrupt_mask_set(interrupt); \ +} while (0) + +/* Allow the given interrupt to be enabled next time we enable irqs. */ +#define raw_local_irq_unmask(interrupt) \ + (__get_cpu_var(interrupts_enabled_mask) |= INT_MASK(interrupt)) + +/* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */ +#define raw_local_irq_unmask_now(interrupt) do { \ + raw_local_irq_unmask(interrupt); \ + if (!irqs_disabled()) \ + interrupt_mask_reset(interrupt); \ +} while (0) + +#else /* __ASSEMBLY__ */ + +/* We provide a somewhat more restricted set for assembly. */ + +#ifdef __tilegx__ + +#if INT_MEM_ERROR != 0 +# error Fix IRQ_DISABLED() macro +#endif + +/* Return 0 or 1 to indicate whether interrupts are currently disabled. */ +#define IRQS_DISABLED(tmp) \ + mfspr tmp, INTERRUPT_MASK_1; \ + andi tmp, tmp, 1 + +/* Load up a pointer to &interrupts_enabled_mask. */ +#define GET_INTERRUPTS_ENABLED_MASK_PTR(reg) \ + moveli reg, hw2_last(interrupts_enabled_mask); \ + shl16insli reg, reg, hw1(interrupts_enabled_mask); \ + shl16insli reg, reg, hw0(interrupts_enabled_mask); \ + add reg, reg, tp + +/* Disable interrupts. */ +#define IRQ_DISABLE(tmp0, tmp1) \ + moveli tmp0, hw2_last(LINUX_MASKABLE_INTERRUPTS); \ + shl16insli tmp0, tmp0, hw1(LINUX_MASKABLE_INTERRUPTS); \ + shl16insli tmp0, tmp0, hw0(LINUX_MASKABLE_INTERRUPTS); \ + mtspr INTERRUPT_MASK_SET_1, tmp0 + +/* Disable ALL synchronous interrupts (used by NMI entry). */ +#define IRQ_DISABLE_ALL(tmp) \ + movei tmp, -1; \ + mtspr INTERRUPT_MASK_SET_1, tmp + +/* Enable interrupts. */ +#define IRQ_ENABLE(tmp0, tmp1) \ + GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ + ld tmp0, tmp0; \ + mtspr INTERRUPT_MASK_RESET_1, tmp0 + +#else /* !__tilegx__ */ + +/* + * Return 0 or 1 to indicate whether interrupts are currently disabled. + * Note that it's important that we use a bit from the "low" mask word, + * since when we are enabling, that is the word we write first, so if we + * are interrupted after only writing half of the mask, the interrupt + * handler will correctly observe that we have interrupts enabled, and + * will enable interrupts itself on return from the interrupt handler + * (making the original code's write of the "high" mask word idempotent). + */ +#define IRQS_DISABLED(tmp) \ + mfspr tmp, INTERRUPT_MASK_1_0; \ + shri tmp, tmp, INT_MEM_ERROR; \ + andi tmp, tmp, 1 + +/* Load up a pointer to &interrupts_enabled_mask. */ +#define GET_INTERRUPTS_ENABLED_MASK_PTR(reg) \ + moveli reg, lo16(interrupts_enabled_mask); \ + auli reg, reg, ha16(interrupts_enabled_mask);\ + add reg, reg, tp + +/* Disable interrupts. */ +#define IRQ_DISABLE(tmp0, tmp1) \ + { \ + movei tmp0, -1; \ + moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS) \ + }; \ + { \ + mtspr INTERRUPT_MASK_SET_1_0, tmp0; \ + auli tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS) \ + }; \ + mtspr INTERRUPT_MASK_SET_1_1, tmp1 + +/* Disable ALL synchronous interrupts (used by NMI entry). */ +#define IRQ_DISABLE_ALL(tmp) \ + movei tmp, -1; \ + mtspr INTERRUPT_MASK_SET_1_0, tmp; \ + mtspr INTERRUPT_MASK_SET_1_1, tmp + +/* Enable interrupts. */ +#define IRQ_ENABLE(tmp0, tmp1) \ + GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ + { \ + lw tmp0, tmp0; \ + addi tmp1, tmp0, 4 \ + }; \ + lw tmp1, tmp1; \ + mtspr INTERRUPT_MASK_RESET_1_0, tmp0; \ + mtspr INTERRUPT_MASK_RESET_1_1, tmp1 +#endif + +/* + * Do the CPU's IRQ-state tracing from assembly code. We call a + * C function, but almost everywhere we do, we don't mind clobbering + * all the caller-saved registers. + */ +#ifdef CONFIG_TRACE_IRQFLAGS +# define TRACE_IRQS_ON jal trace_hardirqs_on +# define TRACE_IRQS_OFF jal trace_hardirqs_off +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_TILE_IRQFLAGS_H */ diff --git a/arch/tile/include/asm/kdebug.h b/arch/tile/include/asm/kdebug.h new file mode 100644 index 000000000000..6ece1b037665 --- /dev/null +++ b/arch/tile/include/asm/kdebug.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/kexec.h b/arch/tile/include/asm/kexec.h new file mode 100644 index 000000000000..c11a6cc73bb8 --- /dev/null +++ b/arch/tile/include/asm/kexec.h @@ -0,0 +1,53 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * based on kexec.h from other architectures in linux-2.6.18 + */ + +#ifndef _ASM_TILE_KEXEC_H +#define _ASM_TILE_KEXEC_H + +#include + +/* Maximum physical address we can use pages from. */ +#define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE +/* Maximum address we can reach in physical address mode. */ +#define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE +/* Maximum address we can use for the control code buffer. */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE + +#define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE + +/* + * We don't bother to provide a unique identifier, since we can only + * reboot with a single type of kernel image anyway. + */ +#define KEXEC_ARCH KEXEC_ARCH_DEFAULT + +/* Use the tile override for the page allocator. */ +struct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order); +#define kimage_alloc_pages_arch kimage_alloc_pages_arch + +#define MAX_NOTE_BYTES 1024 + +/* Defined in arch/tile/kernel/relocate_kernel.S */ +extern const unsigned char relocate_new_kernel[]; +extern const unsigned long relocate_new_kernel_size; +extern void relocate_new_kernel_end(void); + +/* Provide a dummy definition to avoid build failures. */ +static inline void crash_setup_regs(struct pt_regs *n, struct pt_regs *o) +{ +} + +#endif /* _ASM_TILE_KEXEC_H */ diff --git a/arch/tile/include/asm/kmap_types.h b/arch/tile/include/asm/kmap_types.h new file mode 100644 index 000000000000..1480106d1c05 --- /dev/null +++ b/arch/tile/include/asm/kmap_types.h @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_KMAP_TYPES_H +#define _ASM_TILE_KMAP_TYPES_H + +/* + * In TILE Linux each set of four of these uses another 16MB chunk of + * address space, given 64 tiles and 64KB pages, so we only enable + * ones that are required by the kernel configuration. + */ +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_MEMCPY0, + KM_MEMCPY1, +#if defined(CONFIG_HIGHPTE) + KM_PTE0, + KM_PTE1, +#endif + KM_TYPE_NR +}; + +#endif /* _ASM_TILE_KMAP_TYPES_H */ diff --git a/arch/tile/include/asm/linkage.h b/arch/tile/include/asm/linkage.h new file mode 100644 index 000000000000..e121c39751a7 --- /dev/null +++ b/arch/tile/include/asm/linkage.h @@ -0,0 +1,51 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_LINKAGE_H +#define _ASM_TILE_LINKAGE_H + +#include + +#define __ALIGN .align 8 + +/* + * The STD_ENTRY and STD_ENDPROC macros put the function in a + * self-named .text.foo section, and if linker feedback collection + * is enabled, add a suitable call to the feedback collection code. + * STD_ENTRY_SECTION lets you specify a non-standard section name. + */ + +#define STD_ENTRY(name) \ + .pushsection .text.##name, "ax"; \ + ENTRY(name); \ + FEEDBACK_ENTER(name) + +#define STD_ENTRY_SECTION(name, section) \ + .pushsection section, "ax"; \ + ENTRY(name); \ + FEEDBACK_ENTER_EXPLICIT(name, section, .Lend_##name - name) + +#define STD_ENDPROC(name) \ + ENDPROC(name); \ + .Lend_##name:; \ + .popsection + +/* Create a file-static function entry set up for feedback gathering. */ +#define STD_ENTRY_LOCAL(name) \ + .pushsection .text.##name, "ax"; \ + ALIGN; \ + name:; \ + FEEDBACK_ENTER(name) + +#endif /* _ASM_TILE_LINKAGE_H */ diff --git a/arch/tile/include/asm/local.h b/arch/tile/include/asm/local.h new file mode 100644 index 000000000000..c11c530f74d0 --- /dev/null +++ b/arch/tile/include/asm/local.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/memprof.h b/arch/tile/include/asm/memprof.h new file mode 100644 index 000000000000..359949be28c1 --- /dev/null +++ b/arch/tile/include/asm/memprof.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * The hypervisor's memory controller profiling infrastructure allows + * the programmer to find out what fraction of the available memory + * bandwidth is being consumed at each memory controller. The + * profiler provides start, stop, and clear operations to allows + * profiling over a specific time window, as well as an interface for + * reading the most recent profile values. + * + * This header declares IOCTL codes necessary to control memprof. + */ +#ifndef _ASM_TILE_MEMPROF_H +#define _ASM_TILE_MEMPROF_H + +#include + +#define MEMPROF_IOCTL_TYPE 0xB4 +#define MEMPROF_IOCTL_START _IO(MEMPROF_IOCTL_TYPE, 0) +#define MEMPROF_IOCTL_STOP _IO(MEMPROF_IOCTL_TYPE, 1) +#define MEMPROF_IOCTL_CLEAR _IO(MEMPROF_IOCTL_TYPE, 2) + +#endif /* _ASM_TILE_MEMPROF_H */ diff --git a/arch/tile/include/asm/mman.h b/arch/tile/include/asm/mman.h new file mode 100644 index 000000000000..4c6811e3e8dc --- /dev/null +++ b/arch/tile/include/asm/mman.h @@ -0,0 +1,40 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_MMAN_H +#define _ASM_TILE_MMAN_H + +#include +#include + +/* Standard Linux flags */ + +#define MAP_POPULATE 0x0040 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x0080 /* do not block on IO */ +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_LOCKED 0x0200 /* pages are locked */ +#define MAP_NORESERVE 0x0400 /* don't check for reservations */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +#define MAP_HUGETLB 0x4000 /* create a huge page mapping */ + + +/* + * Flags for mlockall + */ +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + + +#endif /* _ASM_TILE_MMAN_H */ diff --git a/arch/tile/include/asm/mmu.h b/arch/tile/include/asm/mmu.h new file mode 100644 index 000000000000..92f94c77b6e4 --- /dev/null +++ b/arch/tile/include/asm/mmu.h @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_MMU_H +#define _ASM_TILE_MMU_H + +/* Capture any arch- and mm-specific information. */ +struct mm_context { + /* + * Written under the mmap_sem semaphore; read without the + * semaphore but atomically, but it is conservatively set. + */ + unsigned int priority_cached; +}; + +typedef struct mm_context mm_context_t; + +void leave_mm(int cpu); + +#endif /* _ASM_TILE_MMU_H */ diff --git a/arch/tile/include/asm/mmu_context.h b/arch/tile/include/asm/mmu_context.h new file mode 100644 index 000000000000..9bc0d0725c28 --- /dev/null +++ b/arch/tile/include/asm/mmu_context.h @@ -0,0 +1,131 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_MMU_CONTEXT_H +#define _ASM_TILE_MMU_CONTEXT_H + +#include +#include +#include +#include +#include +#include +#include +#include + +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + return 0; +} + +/* Note that arch/tile/kernel/head.S also calls hv_install_context() */ +static inline void __install_page_table(pgd_t *pgdir, int asid, pgprot_t prot) +{ + /* FIXME: DIRECTIO should not always be set. FIXME. */ + int rc = hv_install_context(__pa(pgdir), prot, asid, HV_CTX_DIRECTIO); + if (rc < 0) + panic("hv_install_context failed: %d", rc); +} + +static inline void install_page_table(pgd_t *pgdir, int asid) +{ + pte_t *ptep = virt_to_pte(NULL, (unsigned long)pgdir); + __install_page_table(pgdir, asid, *ptep); +} + +/* + * "Lazy" TLB mode is entered when we are switching to a kernel task, + * which borrows the mm of the previous task. The goal of this + * optimization is to avoid having to install a new page table. On + * early x86 machines (where the concept originated) you couldn't do + * anything short of a full page table install for invalidation, so + * handling a remote TLB invalidate required doing a page table + * re-install. Someone clearly decided that it was silly to keep + * doing this while in "lazy" TLB mode, so the optimization involves + * installing the swapper page table instead the first time one + * occurs, and clearing the cpu out of cpu_vm_mask, so the cpu running + * the kernel task doesn't need to take any more interrupts. At that + * point it's then necessary to explicitly reinstall it when context + * switching back to the original mm. + * + * On Tile, we have to do a page-table install whenever DMA is enabled, + * so in that case lazy mode doesn't help anyway. And more generally, + * we have efficient per-page TLB shootdown, and don't expect to spend + * that much time in kernel tasks in general, so just leaving the + * kernel task borrowing the old page table, but handling TLB + * shootdowns, is a reasonable thing to do. And importantly, this + * lets us use the hypervisor's internal APIs for TLB shootdown, which + * means we don't have to worry about having TLB shootdowns blocked + * when Linux is disabling interrupts; see the page migration code for + * an example of where it's important for TLB shootdowns to complete + * even when interrupts are disabled at the Linux level. + */ +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *t) +{ +#if CHIP_HAS_TILE_DMA() + /* + * We have to do an "identity" page table switch in order to + * clear any pending DMA interrupts. + */ + if (current->thread.tile_dma_state.enabled) + install_page_table(mm->pgd, __get_cpu_var(current_asid)); +#endif +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + if (likely(prev != next)) { + + int cpu = smp_processor_id(); + + /* Pick new ASID. */ + int asid = __get_cpu_var(current_asid) + 1; + if (asid > max_asid) { + asid = min_asid; + local_flush_tlb(); + } + __get_cpu_var(current_asid) = asid; + + /* Clear cpu from the old mm, and set it in the new one. */ + cpumask_clear_cpu(cpu, &prev->cpu_vm_mask); + cpumask_set_cpu(cpu, &next->cpu_vm_mask); + + /* Re-load page tables */ + install_page_table(next->pgd, asid); + + /* See how we should set the red/black cache info */ + check_mm_caching(prev, next); + + /* + * Since we're changing to a new mm, we have to flush + * the icache in case some physical page now being mapped + * has subsequently been repurposed and has new code. + */ + __flush_icache(); + + } +} + +static inline void activate_mm(struct mm_struct *prev_mm, + struct mm_struct *next_mm) +{ + switch_mm(prev_mm, next_mm, NULL); +} + +#define destroy_context(mm) do { } while (0) +#define deactivate_mm(tsk, mm) do { } while (0) + +#endif /* _ASM_TILE_MMU_CONTEXT_H */ diff --git a/arch/tile/include/asm/mmzone.h b/arch/tile/include/asm/mmzone.h new file mode 100644 index 000000000000..c6344c4f32ac --- /dev/null +++ b/arch/tile/include/asm/mmzone.h @@ -0,0 +1,81 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_MMZONE_H +#define _ASM_TILE_MMZONE_H + +extern struct pglist_data node_data[]; +#define NODE_DATA(nid) (&node_data[nid]) + +extern void get_memcfg_numa(void); + +#ifdef CONFIG_DISCONTIGMEM + +#include + +/* + * Generally, memory ranges are always doled out by the hypervisor in + * fixed-size, power-of-two increments. That would make computing the node + * very easy. We could just take a couple high bits of the PA, which + * denote the memory shim, and we'd be done. However, when we're doing + * memory striping, this may not be true; PAs with different high bit + * values might be in the same node. Thus, we keep a lookup table to + * translate the high bits of the PFN to the node number. + */ +extern int highbits_to_node[]; + +static inline int pfn_to_nid(unsigned long pfn) +{ + return highbits_to_node[__pfn_to_highbits(pfn)]; +} + +/* + * Following are macros that each numa implmentation must define. + */ + +#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) +#define node_end_pfn(nid) \ +({ \ + pg_data_t *__pgdat = NODE_DATA(nid); \ + __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ +}) + +#define kern_addr_valid(kaddr) virt_addr_valid((void *)kaddr) + +static inline int pfn_valid(int pfn) +{ + int nid = pfn_to_nid(pfn); + + if (nid >= 0) + return (pfn < node_end_pfn(nid)); + return 0; +} + +/* Information on the NUMA nodes that we compute early */ +extern unsigned long node_start_pfn[]; +extern unsigned long node_end_pfn[]; +extern unsigned long node_memmap_pfn[]; +extern unsigned long node_percpu_pfn[]; +extern unsigned long node_free_pfn[]; +#ifdef CONFIG_HIGHMEM +extern unsigned long node_lowmem_end_pfn[]; +#endif +#ifdef CONFIG_PCI +extern unsigned long pci_reserve_start_pfn; +extern unsigned long pci_reserve_end_pfn; +#endif + +#endif /* CONFIG_DISCONTIGMEM */ + +#endif /* _ASM_TILE_MMZONE_H */ diff --git a/arch/tile/include/asm/module.h b/arch/tile/include/asm/module.h new file mode 100644 index 000000000000..1e4b79fe8584 --- /dev/null +++ b/arch/tile/include/asm/module.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/msgbuf.h b/arch/tile/include/asm/msgbuf.h new file mode 100644 index 000000000000..809134c644a6 --- /dev/null +++ b/arch/tile/include/asm/msgbuf.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/mutex.h b/arch/tile/include/asm/mutex.h new file mode 100644 index 000000000000..ff6101aa2c71 --- /dev/null +++ b/arch/tile/include/asm/mutex.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/opcode-tile.h b/arch/tile/include/asm/opcode-tile.h new file mode 100644 index 000000000000..ba38959137d7 --- /dev/null +++ b/arch/tile/include/asm/opcode-tile.h @@ -0,0 +1,30 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_OPCODE_TILE_H +#define _ASM_TILE_OPCODE_TILE_H + +#include + +#if CHIP_WORD_SIZE() == 64 +#include +#else +#include +#endif + +/* These definitions are not correct for TILE64, so just avoid them. */ +#undef TILE_ELF_MACHINE_CODE +#undef TILE_ELF_NAME + +#endif /* _ASM_TILE_OPCODE_TILE_H */ diff --git a/arch/tile/include/asm/opcode-tile_32.h b/arch/tile/include/asm/opcode-tile_32.h new file mode 100644 index 000000000000..90f8dd372531 --- /dev/null +++ b/arch/tile/include/asm/opcode-tile_32.h @@ -0,0 +1,1597 @@ +/* tile.h -- Header file for TILE opcode table + Copyright (C) 2005 Free Software Foundation, Inc. + Contributed by Tilera Corp. */ + +#ifndef opcode_tile_h +#define opcode_tile_h + +typedef unsigned long long tile_bundle_bits; + + +enum +{ + TILE_MAX_OPERANDS = 5 /* mm */ +}; + +typedef enum +{ + TILE_OPC_BPT, + TILE_OPC_INFO, + TILE_OPC_INFOL, + TILE_OPC_J, + TILE_OPC_JAL, + TILE_OPC_MOVE, + TILE_OPC_MOVE_SN, + TILE_OPC_MOVEI, + TILE_OPC_MOVEI_SN, + TILE_OPC_MOVELI, + TILE_OPC_MOVELI_SN, + TILE_OPC_MOVELIS, + TILE_OPC_PREFETCH, + TILE_OPC_ADD, + TILE_OPC_ADD_SN, + TILE_OPC_ADDB, + TILE_OPC_ADDB_SN, + TILE_OPC_ADDBS_U, + TILE_OPC_ADDBS_U_SN, + TILE_OPC_ADDH, + TILE_OPC_ADDH_SN, + TILE_OPC_ADDHS, + TILE_OPC_ADDHS_SN, + TILE_OPC_ADDI, + TILE_OPC_ADDI_SN, + TILE_OPC_ADDIB, + TILE_OPC_ADDIB_SN, + TILE_OPC_ADDIH, + TILE_OPC_ADDIH_SN, + TILE_OPC_ADDLI, + TILE_OPC_ADDLI_SN, + TILE_OPC_ADDLIS, + TILE_OPC_ADDS, + TILE_OPC_ADDS_SN, + TILE_OPC_ADIFFB_U, + TILE_OPC_ADIFFB_U_SN, + TILE_OPC_ADIFFH, + TILE_OPC_ADIFFH_SN, + TILE_OPC_AND, + TILE_OPC_AND_SN, + TILE_OPC_ANDI, + TILE_OPC_ANDI_SN, + TILE_OPC_AULI, + TILE_OPC_AVGB_U, + TILE_OPC_AVGB_U_SN, + TILE_OPC_AVGH, + TILE_OPC_AVGH_SN, + TILE_OPC_BBNS, + TILE_OPC_BBNS_SN, + TILE_OPC_BBNST, + TILE_OPC_BBNST_SN, + TILE_OPC_BBS, + TILE_OPC_BBS_SN, + TILE_OPC_BBST, + TILE_OPC_BBST_SN, + TILE_OPC_BGEZ, + TILE_OPC_BGEZ_SN, + TILE_OPC_BGEZT, + TILE_OPC_BGEZT_SN, + TILE_OPC_BGZ, + TILE_OPC_BGZ_SN, + TILE_OPC_BGZT, + TILE_OPC_BGZT_SN, + TILE_OPC_BITX, + TILE_OPC_BITX_SN, + TILE_OPC_BLEZ, + TILE_OPC_BLEZ_SN, + TILE_OPC_BLEZT, + TILE_OPC_BLEZT_SN, + TILE_OPC_BLZ, + TILE_OPC_BLZ_SN, + TILE_OPC_BLZT, + TILE_OPC_BLZT_SN, + TILE_OPC_BNZ, + TILE_OPC_BNZ_SN, + TILE_OPC_BNZT, + TILE_OPC_BNZT_SN, + TILE_OPC_BYTEX, + TILE_OPC_BYTEX_SN, + TILE_OPC_BZ, + TILE_OPC_BZ_SN, + TILE_OPC_BZT, + TILE_OPC_BZT_SN, + TILE_OPC_CLZ, + TILE_OPC_CLZ_SN, + TILE_OPC_CRC32_32, + TILE_OPC_CRC32_32_SN, + TILE_OPC_CRC32_8, + TILE_OPC_CRC32_8_SN, + TILE_OPC_CTZ, + TILE_OPC_CTZ_SN, + TILE_OPC_DRAIN, + TILE_OPC_DTLBPR, + TILE_OPC_DWORD_ALIGN, + TILE_OPC_DWORD_ALIGN_SN, + TILE_OPC_FINV, + TILE_OPC_FLUSH, + TILE_OPC_FNOP, + TILE_OPC_ICOH, + TILE_OPC_ILL, + TILE_OPC_INTHB, + TILE_OPC_INTHB_SN, + TILE_OPC_INTHH, + TILE_OPC_INTHH_SN, + TILE_OPC_INTLB, + TILE_OPC_INTLB_SN, + TILE_OPC_INTLH, + TILE_OPC_INTLH_SN, + TILE_OPC_INV, + TILE_OPC_IRET, + TILE_OPC_JALB, + TILE_OPC_JALF, + TILE_OPC_JALR, + TILE_OPC_JALRP, + TILE_OPC_JB, + TILE_OPC_JF, + TILE_OPC_JR, + TILE_OPC_JRP, + TILE_OPC_LB, + TILE_OPC_LB_SN, + TILE_OPC_LB_U, + TILE_OPC_LB_U_SN, + TILE_OPC_LBADD, + TILE_OPC_LBADD_SN, + TILE_OPC_LBADD_U, + TILE_OPC_LBADD_U_SN, + TILE_OPC_LH, + TILE_OPC_LH_SN, + TILE_OPC_LH_U, + TILE_OPC_LH_U_SN, + TILE_OPC_LHADD, + TILE_OPC_LHADD_SN, + TILE_OPC_LHADD_U, + TILE_OPC_LHADD_U_SN, + TILE_OPC_LNK, + TILE_OPC_LNK_SN, + TILE_OPC_LW, + TILE_OPC_LW_SN, + TILE_OPC_LW_NA, + TILE_OPC_LW_NA_SN, + TILE_OPC_LWADD, + TILE_OPC_LWADD_SN, + TILE_OPC_LWADD_NA, + TILE_OPC_LWADD_NA_SN, + TILE_OPC_MAXB_U, + TILE_OPC_MAXB_U_SN, + TILE_OPC_MAXH, + TILE_OPC_MAXH_SN, + TILE_OPC_MAXIB_U, + TILE_OPC_MAXIB_U_SN, + TILE_OPC_MAXIH, + TILE_OPC_MAXIH_SN, + TILE_OPC_MF, + TILE_OPC_MFSPR, + TILE_OPC_MINB_U, + TILE_OPC_MINB_U_SN, + TILE_OPC_MINH, + TILE_OPC_MINH_SN, + TILE_OPC_MINIB_U, + TILE_OPC_MINIB_U_SN, + TILE_OPC_MINIH, + TILE_OPC_MINIH_SN, + TILE_OPC_MM, + TILE_OPC_MNZ, + TILE_OPC_MNZ_SN, + TILE_OPC_MNZB, + TILE_OPC_MNZB_SN, + TILE_OPC_MNZH, + TILE_OPC_MNZH_SN, + TILE_OPC_MTSPR, + TILE_OPC_MULHH_SS, + TILE_OPC_MULHH_SS_SN, + TILE_OPC_MULHH_SU, + TILE_OPC_MULHH_SU_SN, + TILE_OPC_MULHH_UU, + TILE_OPC_MULHH_UU_SN, + TILE_OPC_MULHHA_SS, + TILE_OPC_MULHHA_SS_SN, + TILE_OPC_MULHHA_SU, + TILE_OPC_MULHHA_SU_SN, + TILE_OPC_MULHHA_UU, + TILE_OPC_MULHHA_UU_SN, + TILE_OPC_MULHHSA_UU, + TILE_OPC_MULHHSA_UU_SN, + TILE_OPC_MULHL_SS, + TILE_OPC_MULHL_SS_SN, + TILE_OPC_MULHL_SU, + TILE_OPC_MULHL_SU_SN, + TILE_OPC_MULHL_US, + TILE_OPC_MULHL_US_SN, + TILE_OPC_MULHL_UU, + TILE_OPC_MULHL_UU_SN, + TILE_OPC_MULHLA_SS, + TILE_OPC_MULHLA_SS_SN, + TILE_OPC_MULHLA_SU, + TILE_OPC_MULHLA_SU_SN, + TILE_OPC_MULHLA_US, + TILE_OPC_MULHLA_US_SN, + TILE_OPC_MULHLA_UU, + TILE_OPC_MULHLA_UU_SN, + TILE_OPC_MULHLSA_UU, + TILE_OPC_MULHLSA_UU_SN, + TILE_OPC_MULLL_SS, + TILE_OPC_MULLL_SS_SN, + TILE_OPC_MULLL_SU, + TILE_OPC_MULLL_SU_SN, + TILE_OPC_MULLL_UU, + TILE_OPC_MULLL_UU_SN, + TILE_OPC_MULLLA_SS, + TILE_OPC_MULLLA_SS_SN, + TILE_OPC_MULLLA_SU, + TILE_OPC_MULLLA_SU_SN, + TILE_OPC_MULLLA_UU, + TILE_OPC_MULLLA_UU_SN, + TILE_OPC_MULLLSA_UU, + TILE_OPC_MULLLSA_UU_SN, + TILE_OPC_MVNZ, + TILE_OPC_MVNZ_SN, + TILE_OPC_MVZ, + TILE_OPC_MVZ_SN, + TILE_OPC_MZ, + TILE_OPC_MZ_SN, + TILE_OPC_MZB, + TILE_OPC_MZB_SN, + TILE_OPC_MZH, + TILE_OPC_MZH_SN, + TILE_OPC_NAP, + TILE_OPC_NOP, + TILE_OPC_NOR, + TILE_OPC_NOR_SN, + TILE_OPC_OR, + TILE_OPC_OR_SN, + TILE_OPC_ORI, + TILE_OPC_ORI_SN, + TILE_OPC_PACKBS_U, + TILE_OPC_PACKBS_U_SN, + TILE_OPC_PACKHB, + TILE_OPC_PACKHB_SN, + TILE_OPC_PACKHS, + TILE_OPC_PACKHS_SN, + TILE_OPC_PACKLB, + TILE_OPC_PACKLB_SN, + TILE_OPC_PCNT, + TILE_OPC_PCNT_SN, + TILE_OPC_RL, + TILE_OPC_RL_SN, + TILE_OPC_RLI, + TILE_OPC_RLI_SN, + TILE_OPC_S1A, + TILE_OPC_S1A_SN, + TILE_OPC_S2A, + TILE_OPC_S2A_SN, + TILE_OPC_S3A, + TILE_OPC_S3A_SN, + TILE_OPC_SADAB_U, + TILE_OPC_SADAB_U_SN, + TILE_OPC_SADAH, + TILE_OPC_SADAH_SN, + TILE_OPC_SADAH_U, + TILE_OPC_SADAH_U_SN, + TILE_OPC_SADB_U, + TILE_OPC_SADB_U_SN, + TILE_OPC_SADH, + TILE_OPC_SADH_SN, + TILE_OPC_SADH_U, + TILE_OPC_SADH_U_SN, + TILE_OPC_SB, + TILE_OPC_SBADD, + TILE_OPC_SEQ, + TILE_OPC_SEQ_SN, + TILE_OPC_SEQB, + TILE_OPC_SEQB_SN, + TILE_OPC_SEQH, + TILE_OPC_SEQH_SN, + TILE_OPC_SEQI, + TILE_OPC_SEQI_SN, + TILE_OPC_SEQIB, + TILE_OPC_SEQIB_SN, + TILE_OPC_SEQIH, + TILE_OPC_SEQIH_SN, + TILE_OPC_SH, + TILE_OPC_SHADD, + TILE_OPC_SHL, + TILE_OPC_SHL_SN, + TILE_OPC_SHLB, + TILE_OPC_SHLB_SN, + TILE_OPC_SHLH, + TILE_OPC_SHLH_SN, + TILE_OPC_SHLI, + TILE_OPC_SHLI_SN, + TILE_OPC_SHLIB, + TILE_OPC_SHLIB_SN, + TILE_OPC_SHLIH, + TILE_OPC_SHLIH_SN, + TILE_OPC_SHR, + TILE_OPC_SHR_SN, + TILE_OPC_SHRB, + TILE_OPC_SHRB_SN, + TILE_OPC_SHRH, + TILE_OPC_SHRH_SN, + TILE_OPC_SHRI, + TILE_OPC_SHRI_SN, + TILE_OPC_SHRIB, + TILE_OPC_SHRIB_SN, + TILE_OPC_SHRIH, + TILE_OPC_SHRIH_SN, + TILE_OPC_SLT, + TILE_OPC_SLT_SN, + TILE_OPC_SLT_U, + TILE_OPC_SLT_U_SN, + TILE_OPC_SLTB, + TILE_OPC_SLTB_SN, + TILE_OPC_SLTB_U, + TILE_OPC_SLTB_U_SN, + TILE_OPC_SLTE, + TILE_OPC_SLTE_SN, + TILE_OPC_SLTE_U, + TILE_OPC_SLTE_U_SN, + TILE_OPC_SLTEB, + TILE_OPC_SLTEB_SN, + TILE_OPC_SLTEB_U, + TILE_OPC_SLTEB_U_SN, + TILE_OPC_SLTEH, + TILE_OPC_SLTEH_SN, + TILE_OPC_SLTEH_U, + TILE_OPC_SLTEH_U_SN, + TILE_OPC_SLTH, + TILE_OPC_SLTH_SN, + TILE_OPC_SLTH_U, + TILE_OPC_SLTH_U_SN, + TILE_OPC_SLTI, + TILE_OPC_SLTI_SN, + TILE_OPC_SLTI_U, + TILE_OPC_SLTI_U_SN, + TILE_OPC_SLTIB, + TILE_OPC_SLTIB_SN, + TILE_OPC_SLTIB_U, + TILE_OPC_SLTIB_U_SN, + TILE_OPC_SLTIH, + TILE_OPC_SLTIH_SN, + TILE_OPC_SLTIH_U, + TILE_OPC_SLTIH_U_SN, + TILE_OPC_SNE, + TILE_OPC_SNE_SN, + TILE_OPC_SNEB, + TILE_OPC_SNEB_SN, + TILE_OPC_SNEH, + TILE_OPC_SNEH_SN, + TILE_OPC_SRA, + TILE_OPC_SRA_SN, + TILE_OPC_SRAB, + TILE_OPC_SRAB_SN, + TILE_OPC_SRAH, + TILE_OPC_SRAH_SN, + TILE_OPC_SRAI, + TILE_OPC_SRAI_SN, + TILE_OPC_SRAIB, + TILE_OPC_SRAIB_SN, + TILE_OPC_SRAIH, + TILE_OPC_SRAIH_SN, + TILE_OPC_SUB, + TILE_OPC_SUB_SN, + TILE_OPC_SUBB, + TILE_OPC_SUBB_SN, + TILE_OPC_SUBBS_U, + TILE_OPC_SUBBS_U_SN, + TILE_OPC_SUBH, + TILE_OPC_SUBH_SN, + TILE_OPC_SUBHS, + TILE_OPC_SUBHS_SN, + TILE_OPC_SUBS, + TILE_OPC_SUBS_SN, + TILE_OPC_SW, + TILE_OPC_SWADD, + TILE_OPC_SWINT0, + TILE_OPC_SWINT1, + TILE_OPC_SWINT2, + TILE_OPC_SWINT3, + TILE_OPC_TBLIDXB0, + TILE_OPC_TBLIDXB0_SN, + TILE_OPC_TBLIDXB1, + TILE_OPC_TBLIDXB1_SN, + TILE_OPC_TBLIDXB2, + TILE_OPC_TBLIDXB2_SN, + TILE_OPC_TBLIDXB3, + TILE_OPC_TBLIDXB3_SN, + TILE_OPC_TNS, + TILE_OPC_TNS_SN, + TILE_OPC_WH64, + TILE_OPC_XOR, + TILE_OPC_XOR_SN, + TILE_OPC_XORI, + TILE_OPC_XORI_SN, + TILE_OPC_NONE +} tile_mnemonic; + +/* 64-bit pattern for a { bpt ; nop } bundle. */ +#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL + + +#define TILE_ELF_MACHINE_CODE EM_TILEPRO + +#define TILE_ELF_NAME "elf32-tilepro" + +enum +{ + TILE_SN_MAX_OPERANDS = 6 /* route */ +}; + +typedef enum +{ + TILE_SN_OPC_BZ, + TILE_SN_OPC_BNZ, + TILE_SN_OPC_JRR, + TILE_SN_OPC_FNOP, + TILE_SN_OPC_BLZ, + TILE_SN_OPC_NOP, + TILE_SN_OPC_MOVEI, + TILE_SN_OPC_MOVE, + TILE_SN_OPC_BGEZ, + TILE_SN_OPC_JR, + TILE_SN_OPC_BLEZ, + TILE_SN_OPC_BBNS, + TILE_SN_OPC_JALRR, + TILE_SN_OPC_BPT, + TILE_SN_OPC_JALR, + TILE_SN_OPC_SHR1, + TILE_SN_OPC_BGZ, + TILE_SN_OPC_BBS, + TILE_SN_OPC_SHL8II, + TILE_SN_OPC_ADDI, + TILE_SN_OPC_HALT, + TILE_SN_OPC_ROUTE, + TILE_SN_OPC_NONE +} tile_sn_mnemonic; + +extern const unsigned char tile_sn_route_encode[6 * 6 * 6]; +extern const signed char tile_sn_route_decode[256][3]; +extern const char tile_sn_direction_names[6][5]; +extern const signed char tile_sn_dest_map[6][6]; + + +static __inline unsigned int +get_BrOff_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3ff); +} + +static __inline unsigned int +get_BrOff_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000); +} + +static __inline unsigned int +get_BrType_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0xf); +} + +static __inline unsigned int +get_Dest_Imm8_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x0000003f) | + (((unsigned int)(n >> 43)) & 0x000000c0); +} + +static __inline unsigned int +get_Dest_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 2)) & 0x3); +} + +static __inline unsigned int +get_Dest_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3f); +} + +static __inline unsigned int +get_Dest_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x3f); +} + +static __inline unsigned int +get_Dest_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3f); +} + +static __inline unsigned int +get_Dest_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x3f); +} + +static __inline unsigned int +get_Imm16_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xffff); +} + +static __inline unsigned int +get_Imm16_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xffff); +} + +static __inline unsigned int +get_Imm8_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0xff); +} + +static __inline unsigned int +get_Imm8_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xff); +} + +static __inline unsigned int +get_Imm8_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xff); +} + +static __inline unsigned int +get_Imm8_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xff); +} + +static __inline unsigned int +get_Imm8_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xff); +} + +static __inline unsigned int +get_ImmOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 20)) & 0x7f); +} + +static __inline unsigned int +get_ImmOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 51)) & 0x7f); +} + +static __inline unsigned int +get_ImmRROpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 8)) & 0x3); +} + +static __inline unsigned int +get_JOffLong_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000) | + (((unsigned int)(n >> 14)) & 0x001e0000) | + (((unsigned int)(n >> 16)) & 0x07e00000) | + (((unsigned int)(n >> 31)) & 0x18000000); +} + +static __inline unsigned int +get_JOff_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000) | + (((unsigned int)(n >> 14)) & 0x001e0000) | + (((unsigned int)(n >> 16)) & 0x07e00000) | + (((unsigned int)(n >> 31)) & 0x08000000); +} + +static __inline unsigned int +get_MF_Imm15_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x00003fff) | + (((unsigned int)(n >> 44)) & 0x00004000); +} + +static __inline unsigned int +get_MMEnd_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x1f); +} + +static __inline unsigned int +get_MMEnd_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x1f); +} + +static __inline unsigned int +get_MMStart_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 23)) & 0x1f); +} + +static __inline unsigned int +get_MMStart_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 54)) & 0x1f); +} + +static __inline unsigned int +get_MT_Imm15_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x0000003f) | + (((unsigned int)(n >> 37)) & 0x00003fc0) | + (((unsigned int)(n >> 44)) & 0x00004000); +} + +static __inline unsigned int +get_Mode(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 63)) & 0x1); +} + +static __inline unsigned int +get_NoRegOpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0xf); +} + +static __inline unsigned int +get_Opcode_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 10)) & 0x3f); +} + +static __inline unsigned int +get_Opcode_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 28)) & 0x7); +} + +static __inline unsigned int +get_Opcode_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 59)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 27)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 59)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y2(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 56)) & 0x7); +} + +static __inline unsigned int +get_RROpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 4)) & 0xf); +} + +static __inline unsigned int +get_RRROpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x1ff); +} + +static __inline unsigned int +get_RRROpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x1ff); +} + +static __inline unsigned int +get_RRROpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x3); +} + +static __inline unsigned int +get_RRROpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x3); +} + +static __inline unsigned int +get_RouteOpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3ff); +} + +static __inline unsigned int +get_S_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 27)) & 0x1); +} + +static __inline unsigned int +get_S_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 58)) & 0x1); +} + +static __inline unsigned int +get_ShAmt_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_SrcA_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 6)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 6)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y2(tile_bundle_bits n) +{ + return (((n >> 26)) & 0x00000001) | + (((unsigned int)(n >> 50)) & 0x0000003e); +} + +static __inline unsigned int +get_SrcBDest_Y2(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 20)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x3f); +} + +static __inline unsigned int +get_Src_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3); +} + +static __inline unsigned int +get_UnOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_UnShOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 17)) & 0x3ff); +} + +static __inline unsigned int +get_UnShOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 48)) & 0x3ff); +} + +static __inline unsigned int +get_UnShOpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 17)) & 0x7); +} + +static __inline unsigned int +get_UnShOpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 48)) & 0x7); +} + + +static __inline int +sign_extend(int n, int num_bits) +{ + int shift = (int)(sizeof(int) * 8 - num_bits); + return (n << shift) >> shift; +} + + + +static __inline tile_bundle_bits +create_BrOff_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 0); +} + +static __inline tile_bundle_bits +create_BrOff_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20); +} + +static __inline tile_bundle_bits +create_BrType_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 31); +} + +static __inline tile_bundle_bits +create_Dest_Imm8_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | + (((tile_bundle_bits)(n & 0x000000c0)) << 43); +} + +static __inline tile_bundle_bits +create_Dest_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 2); +} + +static __inline tile_bundle_bits +create_Dest_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 0); +} + +static __inline tile_bundle_bits +create_Dest_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 31); +} + +static __inline tile_bundle_bits +create_Dest_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 0); +} + +static __inline tile_bundle_bits +create_Dest_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 31); +} + +static __inline tile_bundle_bits +create_Imm16_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xffff) << 12); +} + +static __inline tile_bundle_bits +create_Imm16_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xffff)) << 43); +} + +static __inline tile_bundle_bits +create_Imm8_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 0); +} + +static __inline tile_bundle_bits +create_Imm8_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 12); +} + +static __inline tile_bundle_bits +create_Imm8_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xff)) << 43); +} + +static __inline tile_bundle_bits +create_Imm8_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 12); +} + +static __inline tile_bundle_bits +create_Imm8_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xff)) << 43); +} + +static __inline tile_bundle_bits +create_ImmOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7f) << 20); +} + +static __inline tile_bundle_bits +create_ImmOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7f)) << 51); +} + +static __inline tile_bundle_bits +create_ImmRROpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 8); +} + +static __inline tile_bundle_bits +create_JOffLong_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20) | + (((tile_bundle_bits)(n & 0x001e0000)) << 14) | + (((tile_bundle_bits)(n & 0x07e00000)) << 16) | + (((tile_bundle_bits)(n & 0x18000000)) << 31); +} + +static __inline tile_bundle_bits +create_JOff_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20) | + (((tile_bundle_bits)(n & 0x001e0000)) << 14) | + (((tile_bundle_bits)(n & 0x07e00000)) << 16) | + (((tile_bundle_bits)(n & 0x08000000)) << 31); +} + +static __inline tile_bundle_bits +create_MF_Imm15_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00003fff)) << 37) | + (((tile_bundle_bits)(n & 0x00004000)) << 44); +} + +static __inline tile_bundle_bits +create_MMEnd_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 18); +} + +static __inline tile_bundle_bits +create_MMEnd_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 49); +} + +static __inline tile_bundle_bits +create_MMStart_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 23); +} + +static __inline tile_bundle_bits +create_MMStart_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 54); +} + +static __inline tile_bundle_bits +create_MT_Imm15_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | + (((tile_bundle_bits)(n & 0x00003fc0)) << 37) | + (((tile_bundle_bits)(n & 0x00004000)) << 44); +} + +static __inline tile_bundle_bits +create_Mode(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1)) << 63); +} + +static __inline tile_bundle_bits +create_NoRegOpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 0); +} + +static __inline tile_bundle_bits +create_Opcode_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 10); +} + +static __inline tile_bundle_bits +create_Opcode_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7) << 28); +} + +static __inline tile_bundle_bits +create_Opcode_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 59); +} + +static __inline tile_bundle_bits +create_Opcode_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 27); +} + +static __inline tile_bundle_bits +create_Opcode_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 59); +} + +static __inline tile_bundle_bits +create_Opcode_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7)) << 56); +} + +static __inline tile_bundle_bits +create_RROpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 4); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1ff) << 18); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1ff)) << 49); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 18); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3)) << 49); +} + +static __inline tile_bundle_bits +create_RouteOpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 0); +} + +static __inline tile_bundle_bits +create_S_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1) << 27); +} + +static __inline tile_bundle_bits +create_S_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1)) << 58); +} + +static __inline tile_bundle_bits +create_ShAmt_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_ShAmt_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_ShAmt_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_ShAmt_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_SrcA_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 6); +} + +static __inline tile_bundle_bits +create_SrcA_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 37); +} + +static __inline tile_bundle_bits +create_SrcA_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 6); +} + +static __inline tile_bundle_bits +create_SrcA_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 37); +} + +static __inline tile_bundle_bits +create_SrcA_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x00000001) << 26) | + (((tile_bundle_bits)(n & 0x0000003e)) << 50); +} + +static __inline tile_bundle_bits +create_SrcBDest_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 20); +} + +static __inline tile_bundle_bits +create_SrcB_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 12); +} + +static __inline tile_bundle_bits +create_SrcB_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 43); +} + +static __inline tile_bundle_bits +create_SrcB_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 12); +} + +static __inline tile_bundle_bits +create_SrcB_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 43); +} + +static __inline tile_bundle_bits +create_Src_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 0); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 17); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3ff)) << 48); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7) << 17); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7)) << 48); +} + + +typedef unsigned short tile_sn_instruction_bits; + + +typedef enum +{ + TILE_PIPELINE_X0, + TILE_PIPELINE_X1, + TILE_PIPELINE_Y0, + TILE_PIPELINE_Y1, + TILE_PIPELINE_Y2, +} tile_pipeline; + +#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1) + +typedef enum +{ + TILE_OP_TYPE_REGISTER, + TILE_OP_TYPE_IMMEDIATE, + TILE_OP_TYPE_ADDRESS, + TILE_OP_TYPE_SPR +} tile_operand_type; + +/* This is the bit that determines if a bundle is in the Y encoding. */ +#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63) + +enum +{ + /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */ + TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3, + + /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */ + TILE_NUM_PIPELINE_ENCODINGS = 5, + + /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */ + TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3, + + /* Instructions take this many bytes. */ + TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES, + + /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */ + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, + + /* Bundles should be aligned modulo this number of bytes. */ + TILE_BUNDLE_ALIGNMENT_IN_BYTES = + (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), + + /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */ + TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1, + + /* Static network instructions take this many bytes. */ + TILE_SN_INSTRUCTION_SIZE_IN_BYTES = + (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES), + + /* Number of registers (some are magic, such as network I/O). */ + TILE_NUM_REGISTERS = 64, + + /* Number of static network registers. */ + TILE_NUM_SN_REGISTERS = 4 +}; + + +struct tile_operand +{ + /* Is this operand a register, immediate or address? */ + tile_operand_type type; + + /* The default relocation type for this operand. */ + signed int default_reloc : 16; + + /* How many bits is this value? (used for range checking) */ + unsigned int num_bits : 5; + + /* Is the value signed? (used for range checking) */ + unsigned int is_signed : 1; + + /* Is this operand a source register? */ + unsigned int is_src_reg : 1; + + /* Is this operand written? (i.e. is it a destination register) */ + unsigned int is_dest_reg : 1; + + /* Is this operand PC-relative? */ + unsigned int is_pc_relative : 1; + + /* By how many bits do we right shift the value before inserting? */ + unsigned int rightshift : 2; + + /* Return the bits for this operand to be ORed into an existing bundle. */ + tile_bundle_bits (*insert) (int op); + + /* Extract this operand and return it. */ + unsigned int (*extract) (tile_bundle_bits bundle); +}; + + +extern const struct tile_operand tile_operands[]; + +/* One finite-state machine per pipe for rapid instruction decoding. */ +extern const unsigned short * const +tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS]; + + +struct tile_opcode +{ + /* The opcode mnemonic, e.g. "add" */ + const char *name; + + /* The enum value for this mnemonic. */ + tile_mnemonic mnemonic; + + /* A bit mask of which of the five pipes this instruction + is compatible with: + X0 0x01 + X1 0x02 + Y0 0x04 + Y1 0x08 + Y2 0x10 */ + unsigned char pipes; + + /* How many operands are there? */ + unsigned char num_operands; + + /* Which register does this write implicitly, or TREG_ZERO if none? */ + unsigned char implicitly_written_register; + + /* Can this be bundled with other instructions (almost always true). */ + unsigned char can_bundle; + + /* The description of the operands. Each of these is an + * index into the tile_operands[] table. */ + unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS]; + + /* A mask of which bits have predefined values for each pipeline. + * This is useful for disassembly. */ + tile_bundle_bits fixed_bit_masks[TILE_NUM_PIPELINE_ENCODINGS]; + + /* For each bit set in fixed_bit_masks, what the value is for this + * instruction. */ + tile_bundle_bits fixed_bit_values[TILE_NUM_PIPELINE_ENCODINGS]; +}; + +extern const struct tile_opcode tile_opcodes[]; + +struct tile_sn_opcode +{ + /* The opcode mnemonic, e.g. "add" */ + const char *name; + + /* The enum value for this mnemonic. */ + tile_sn_mnemonic mnemonic; + + /* How many operands are there? */ + unsigned char num_operands; + + /* The description of the operands. Each of these is an + * index into the tile_operands[] table. */ + unsigned char operands[TILE_SN_MAX_OPERANDS]; + + /* A mask of which bits have predefined values. + * This is useful for disassembly. */ + tile_sn_instruction_bits fixed_bit_mask; + + /* For each bit set in fixed_bit_masks, what its value is. */ + tile_sn_instruction_bits fixed_bit_values; +}; + +extern const struct tile_sn_opcode tile_sn_opcodes[]; + +/* Used for non-textual disassembly into structs. */ +struct tile_decoded_instruction +{ + const struct tile_opcode *opcode; + const struct tile_operand *operands[TILE_MAX_OPERANDS]; + int operand_values[TILE_MAX_OPERANDS]; +}; + + +/* Disassemble a bundle into a struct for machine processing. */ +extern int parse_insn_tile(tile_bundle_bits bits, + unsigned int pc, + struct tile_decoded_instruction + decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]); + + +/* Canonical names of all the registers. */ +/* ISSUE: This table lives in "tile-dis.c" */ +extern const char * const tile_register_names[]; + +/* Descriptor for a special-purpose register. */ +struct tile_spr +{ + /* The number */ + int number; + + /* The name */ + const char *name; +}; + +/* List of all the SPRs; ordered by increasing number. */ +extern const struct tile_spr tile_sprs[]; + +/* Number of special-purpose registers. */ +extern const int tile_num_sprs; + +extern const char * +get_tile_spr_name (int num); + +#endif /* opcode_tile_h */ diff --git a/arch/tile/include/asm/opcode-tile_64.h b/arch/tile/include/asm/opcode-tile_64.h new file mode 100644 index 000000000000..90f8dd372531 --- /dev/null +++ b/arch/tile/include/asm/opcode-tile_64.h @@ -0,0 +1,1597 @@ +/* tile.h -- Header file for TILE opcode table + Copyright (C) 2005 Free Software Foundation, Inc. + Contributed by Tilera Corp. */ + +#ifndef opcode_tile_h +#define opcode_tile_h + +typedef unsigned long long tile_bundle_bits; + + +enum +{ + TILE_MAX_OPERANDS = 5 /* mm */ +}; + +typedef enum +{ + TILE_OPC_BPT, + TILE_OPC_INFO, + TILE_OPC_INFOL, + TILE_OPC_J, + TILE_OPC_JAL, + TILE_OPC_MOVE, + TILE_OPC_MOVE_SN, + TILE_OPC_MOVEI, + TILE_OPC_MOVEI_SN, + TILE_OPC_MOVELI, + TILE_OPC_MOVELI_SN, + TILE_OPC_MOVELIS, + TILE_OPC_PREFETCH, + TILE_OPC_ADD, + TILE_OPC_ADD_SN, + TILE_OPC_ADDB, + TILE_OPC_ADDB_SN, + TILE_OPC_ADDBS_U, + TILE_OPC_ADDBS_U_SN, + TILE_OPC_ADDH, + TILE_OPC_ADDH_SN, + TILE_OPC_ADDHS, + TILE_OPC_ADDHS_SN, + TILE_OPC_ADDI, + TILE_OPC_ADDI_SN, + TILE_OPC_ADDIB, + TILE_OPC_ADDIB_SN, + TILE_OPC_ADDIH, + TILE_OPC_ADDIH_SN, + TILE_OPC_ADDLI, + TILE_OPC_ADDLI_SN, + TILE_OPC_ADDLIS, + TILE_OPC_ADDS, + TILE_OPC_ADDS_SN, + TILE_OPC_ADIFFB_U, + TILE_OPC_ADIFFB_U_SN, + TILE_OPC_ADIFFH, + TILE_OPC_ADIFFH_SN, + TILE_OPC_AND, + TILE_OPC_AND_SN, + TILE_OPC_ANDI, + TILE_OPC_ANDI_SN, + TILE_OPC_AULI, + TILE_OPC_AVGB_U, + TILE_OPC_AVGB_U_SN, + TILE_OPC_AVGH, + TILE_OPC_AVGH_SN, + TILE_OPC_BBNS, + TILE_OPC_BBNS_SN, + TILE_OPC_BBNST, + TILE_OPC_BBNST_SN, + TILE_OPC_BBS, + TILE_OPC_BBS_SN, + TILE_OPC_BBST, + TILE_OPC_BBST_SN, + TILE_OPC_BGEZ, + TILE_OPC_BGEZ_SN, + TILE_OPC_BGEZT, + TILE_OPC_BGEZT_SN, + TILE_OPC_BGZ, + TILE_OPC_BGZ_SN, + TILE_OPC_BGZT, + TILE_OPC_BGZT_SN, + TILE_OPC_BITX, + TILE_OPC_BITX_SN, + TILE_OPC_BLEZ, + TILE_OPC_BLEZ_SN, + TILE_OPC_BLEZT, + TILE_OPC_BLEZT_SN, + TILE_OPC_BLZ, + TILE_OPC_BLZ_SN, + TILE_OPC_BLZT, + TILE_OPC_BLZT_SN, + TILE_OPC_BNZ, + TILE_OPC_BNZ_SN, + TILE_OPC_BNZT, + TILE_OPC_BNZT_SN, + TILE_OPC_BYTEX, + TILE_OPC_BYTEX_SN, + TILE_OPC_BZ, + TILE_OPC_BZ_SN, + TILE_OPC_BZT, + TILE_OPC_BZT_SN, + TILE_OPC_CLZ, + TILE_OPC_CLZ_SN, + TILE_OPC_CRC32_32, + TILE_OPC_CRC32_32_SN, + TILE_OPC_CRC32_8, + TILE_OPC_CRC32_8_SN, + TILE_OPC_CTZ, + TILE_OPC_CTZ_SN, + TILE_OPC_DRAIN, + TILE_OPC_DTLBPR, + TILE_OPC_DWORD_ALIGN, + TILE_OPC_DWORD_ALIGN_SN, + TILE_OPC_FINV, + TILE_OPC_FLUSH, + TILE_OPC_FNOP, + TILE_OPC_ICOH, + TILE_OPC_ILL, + TILE_OPC_INTHB, + TILE_OPC_INTHB_SN, + TILE_OPC_INTHH, + TILE_OPC_INTHH_SN, + TILE_OPC_INTLB, + TILE_OPC_INTLB_SN, + TILE_OPC_INTLH, + TILE_OPC_INTLH_SN, + TILE_OPC_INV, + TILE_OPC_IRET, + TILE_OPC_JALB, + TILE_OPC_JALF, + TILE_OPC_JALR, + TILE_OPC_JALRP, + TILE_OPC_JB, + TILE_OPC_JF, + TILE_OPC_JR, + TILE_OPC_JRP, + TILE_OPC_LB, + TILE_OPC_LB_SN, + TILE_OPC_LB_U, + TILE_OPC_LB_U_SN, + TILE_OPC_LBADD, + TILE_OPC_LBADD_SN, + TILE_OPC_LBADD_U, + TILE_OPC_LBADD_U_SN, + TILE_OPC_LH, + TILE_OPC_LH_SN, + TILE_OPC_LH_U, + TILE_OPC_LH_U_SN, + TILE_OPC_LHADD, + TILE_OPC_LHADD_SN, + TILE_OPC_LHADD_U, + TILE_OPC_LHADD_U_SN, + TILE_OPC_LNK, + TILE_OPC_LNK_SN, + TILE_OPC_LW, + TILE_OPC_LW_SN, + TILE_OPC_LW_NA, + TILE_OPC_LW_NA_SN, + TILE_OPC_LWADD, + TILE_OPC_LWADD_SN, + TILE_OPC_LWADD_NA, + TILE_OPC_LWADD_NA_SN, + TILE_OPC_MAXB_U, + TILE_OPC_MAXB_U_SN, + TILE_OPC_MAXH, + TILE_OPC_MAXH_SN, + TILE_OPC_MAXIB_U, + TILE_OPC_MAXIB_U_SN, + TILE_OPC_MAXIH, + TILE_OPC_MAXIH_SN, + TILE_OPC_MF, + TILE_OPC_MFSPR, + TILE_OPC_MINB_U, + TILE_OPC_MINB_U_SN, + TILE_OPC_MINH, + TILE_OPC_MINH_SN, + TILE_OPC_MINIB_U, + TILE_OPC_MINIB_U_SN, + TILE_OPC_MINIH, + TILE_OPC_MINIH_SN, + TILE_OPC_MM, + TILE_OPC_MNZ, + TILE_OPC_MNZ_SN, + TILE_OPC_MNZB, + TILE_OPC_MNZB_SN, + TILE_OPC_MNZH, + TILE_OPC_MNZH_SN, + TILE_OPC_MTSPR, + TILE_OPC_MULHH_SS, + TILE_OPC_MULHH_SS_SN, + TILE_OPC_MULHH_SU, + TILE_OPC_MULHH_SU_SN, + TILE_OPC_MULHH_UU, + TILE_OPC_MULHH_UU_SN, + TILE_OPC_MULHHA_SS, + TILE_OPC_MULHHA_SS_SN, + TILE_OPC_MULHHA_SU, + TILE_OPC_MULHHA_SU_SN, + TILE_OPC_MULHHA_UU, + TILE_OPC_MULHHA_UU_SN, + TILE_OPC_MULHHSA_UU, + TILE_OPC_MULHHSA_UU_SN, + TILE_OPC_MULHL_SS, + TILE_OPC_MULHL_SS_SN, + TILE_OPC_MULHL_SU, + TILE_OPC_MULHL_SU_SN, + TILE_OPC_MULHL_US, + TILE_OPC_MULHL_US_SN, + TILE_OPC_MULHL_UU, + TILE_OPC_MULHL_UU_SN, + TILE_OPC_MULHLA_SS, + TILE_OPC_MULHLA_SS_SN, + TILE_OPC_MULHLA_SU, + TILE_OPC_MULHLA_SU_SN, + TILE_OPC_MULHLA_US, + TILE_OPC_MULHLA_US_SN, + TILE_OPC_MULHLA_UU, + TILE_OPC_MULHLA_UU_SN, + TILE_OPC_MULHLSA_UU, + TILE_OPC_MULHLSA_UU_SN, + TILE_OPC_MULLL_SS, + TILE_OPC_MULLL_SS_SN, + TILE_OPC_MULLL_SU, + TILE_OPC_MULLL_SU_SN, + TILE_OPC_MULLL_UU, + TILE_OPC_MULLL_UU_SN, + TILE_OPC_MULLLA_SS, + TILE_OPC_MULLLA_SS_SN, + TILE_OPC_MULLLA_SU, + TILE_OPC_MULLLA_SU_SN, + TILE_OPC_MULLLA_UU, + TILE_OPC_MULLLA_UU_SN, + TILE_OPC_MULLLSA_UU, + TILE_OPC_MULLLSA_UU_SN, + TILE_OPC_MVNZ, + TILE_OPC_MVNZ_SN, + TILE_OPC_MVZ, + TILE_OPC_MVZ_SN, + TILE_OPC_MZ, + TILE_OPC_MZ_SN, + TILE_OPC_MZB, + TILE_OPC_MZB_SN, + TILE_OPC_MZH, + TILE_OPC_MZH_SN, + TILE_OPC_NAP, + TILE_OPC_NOP, + TILE_OPC_NOR, + TILE_OPC_NOR_SN, + TILE_OPC_OR, + TILE_OPC_OR_SN, + TILE_OPC_ORI, + TILE_OPC_ORI_SN, + TILE_OPC_PACKBS_U, + TILE_OPC_PACKBS_U_SN, + TILE_OPC_PACKHB, + TILE_OPC_PACKHB_SN, + TILE_OPC_PACKHS, + TILE_OPC_PACKHS_SN, + TILE_OPC_PACKLB, + TILE_OPC_PACKLB_SN, + TILE_OPC_PCNT, + TILE_OPC_PCNT_SN, + TILE_OPC_RL, + TILE_OPC_RL_SN, + TILE_OPC_RLI, + TILE_OPC_RLI_SN, + TILE_OPC_S1A, + TILE_OPC_S1A_SN, + TILE_OPC_S2A, + TILE_OPC_S2A_SN, + TILE_OPC_S3A, + TILE_OPC_S3A_SN, + TILE_OPC_SADAB_U, + TILE_OPC_SADAB_U_SN, + TILE_OPC_SADAH, + TILE_OPC_SADAH_SN, + TILE_OPC_SADAH_U, + TILE_OPC_SADAH_U_SN, + TILE_OPC_SADB_U, + TILE_OPC_SADB_U_SN, + TILE_OPC_SADH, + TILE_OPC_SADH_SN, + TILE_OPC_SADH_U, + TILE_OPC_SADH_U_SN, + TILE_OPC_SB, + TILE_OPC_SBADD, + TILE_OPC_SEQ, + TILE_OPC_SEQ_SN, + TILE_OPC_SEQB, + TILE_OPC_SEQB_SN, + TILE_OPC_SEQH, + TILE_OPC_SEQH_SN, + TILE_OPC_SEQI, + TILE_OPC_SEQI_SN, + TILE_OPC_SEQIB, + TILE_OPC_SEQIB_SN, + TILE_OPC_SEQIH, + TILE_OPC_SEQIH_SN, + TILE_OPC_SH, + TILE_OPC_SHADD, + TILE_OPC_SHL, + TILE_OPC_SHL_SN, + TILE_OPC_SHLB, + TILE_OPC_SHLB_SN, + TILE_OPC_SHLH, + TILE_OPC_SHLH_SN, + TILE_OPC_SHLI, + TILE_OPC_SHLI_SN, + TILE_OPC_SHLIB, + TILE_OPC_SHLIB_SN, + TILE_OPC_SHLIH, + TILE_OPC_SHLIH_SN, + TILE_OPC_SHR, + TILE_OPC_SHR_SN, + TILE_OPC_SHRB, + TILE_OPC_SHRB_SN, + TILE_OPC_SHRH, + TILE_OPC_SHRH_SN, + TILE_OPC_SHRI, + TILE_OPC_SHRI_SN, + TILE_OPC_SHRIB, + TILE_OPC_SHRIB_SN, + TILE_OPC_SHRIH, + TILE_OPC_SHRIH_SN, + TILE_OPC_SLT, + TILE_OPC_SLT_SN, + TILE_OPC_SLT_U, + TILE_OPC_SLT_U_SN, + TILE_OPC_SLTB, + TILE_OPC_SLTB_SN, + TILE_OPC_SLTB_U, + TILE_OPC_SLTB_U_SN, + TILE_OPC_SLTE, + TILE_OPC_SLTE_SN, + TILE_OPC_SLTE_U, + TILE_OPC_SLTE_U_SN, + TILE_OPC_SLTEB, + TILE_OPC_SLTEB_SN, + TILE_OPC_SLTEB_U, + TILE_OPC_SLTEB_U_SN, + TILE_OPC_SLTEH, + TILE_OPC_SLTEH_SN, + TILE_OPC_SLTEH_U, + TILE_OPC_SLTEH_U_SN, + TILE_OPC_SLTH, + TILE_OPC_SLTH_SN, + TILE_OPC_SLTH_U, + TILE_OPC_SLTH_U_SN, + TILE_OPC_SLTI, + TILE_OPC_SLTI_SN, + TILE_OPC_SLTI_U, + TILE_OPC_SLTI_U_SN, + TILE_OPC_SLTIB, + TILE_OPC_SLTIB_SN, + TILE_OPC_SLTIB_U, + TILE_OPC_SLTIB_U_SN, + TILE_OPC_SLTIH, + TILE_OPC_SLTIH_SN, + TILE_OPC_SLTIH_U, + TILE_OPC_SLTIH_U_SN, + TILE_OPC_SNE, + TILE_OPC_SNE_SN, + TILE_OPC_SNEB, + TILE_OPC_SNEB_SN, + TILE_OPC_SNEH, + TILE_OPC_SNEH_SN, + TILE_OPC_SRA, + TILE_OPC_SRA_SN, + TILE_OPC_SRAB, + TILE_OPC_SRAB_SN, + TILE_OPC_SRAH, + TILE_OPC_SRAH_SN, + TILE_OPC_SRAI, + TILE_OPC_SRAI_SN, + TILE_OPC_SRAIB, + TILE_OPC_SRAIB_SN, + TILE_OPC_SRAIH, + TILE_OPC_SRAIH_SN, + TILE_OPC_SUB, + TILE_OPC_SUB_SN, + TILE_OPC_SUBB, + TILE_OPC_SUBB_SN, + TILE_OPC_SUBBS_U, + TILE_OPC_SUBBS_U_SN, + TILE_OPC_SUBH, + TILE_OPC_SUBH_SN, + TILE_OPC_SUBHS, + TILE_OPC_SUBHS_SN, + TILE_OPC_SUBS, + TILE_OPC_SUBS_SN, + TILE_OPC_SW, + TILE_OPC_SWADD, + TILE_OPC_SWINT0, + TILE_OPC_SWINT1, + TILE_OPC_SWINT2, + TILE_OPC_SWINT3, + TILE_OPC_TBLIDXB0, + TILE_OPC_TBLIDXB0_SN, + TILE_OPC_TBLIDXB1, + TILE_OPC_TBLIDXB1_SN, + TILE_OPC_TBLIDXB2, + TILE_OPC_TBLIDXB2_SN, + TILE_OPC_TBLIDXB3, + TILE_OPC_TBLIDXB3_SN, + TILE_OPC_TNS, + TILE_OPC_TNS_SN, + TILE_OPC_WH64, + TILE_OPC_XOR, + TILE_OPC_XOR_SN, + TILE_OPC_XORI, + TILE_OPC_XORI_SN, + TILE_OPC_NONE +} tile_mnemonic; + +/* 64-bit pattern for a { bpt ; nop } bundle. */ +#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL + + +#define TILE_ELF_MACHINE_CODE EM_TILEPRO + +#define TILE_ELF_NAME "elf32-tilepro" + +enum +{ + TILE_SN_MAX_OPERANDS = 6 /* route */ +}; + +typedef enum +{ + TILE_SN_OPC_BZ, + TILE_SN_OPC_BNZ, + TILE_SN_OPC_JRR, + TILE_SN_OPC_FNOP, + TILE_SN_OPC_BLZ, + TILE_SN_OPC_NOP, + TILE_SN_OPC_MOVEI, + TILE_SN_OPC_MOVE, + TILE_SN_OPC_BGEZ, + TILE_SN_OPC_JR, + TILE_SN_OPC_BLEZ, + TILE_SN_OPC_BBNS, + TILE_SN_OPC_JALRR, + TILE_SN_OPC_BPT, + TILE_SN_OPC_JALR, + TILE_SN_OPC_SHR1, + TILE_SN_OPC_BGZ, + TILE_SN_OPC_BBS, + TILE_SN_OPC_SHL8II, + TILE_SN_OPC_ADDI, + TILE_SN_OPC_HALT, + TILE_SN_OPC_ROUTE, + TILE_SN_OPC_NONE +} tile_sn_mnemonic; + +extern const unsigned char tile_sn_route_encode[6 * 6 * 6]; +extern const signed char tile_sn_route_decode[256][3]; +extern const char tile_sn_direction_names[6][5]; +extern const signed char tile_sn_dest_map[6][6]; + + +static __inline unsigned int +get_BrOff_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3ff); +} + +static __inline unsigned int +get_BrOff_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000); +} + +static __inline unsigned int +get_BrType_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0xf); +} + +static __inline unsigned int +get_Dest_Imm8_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x0000003f) | + (((unsigned int)(n >> 43)) & 0x000000c0); +} + +static __inline unsigned int +get_Dest_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 2)) & 0x3); +} + +static __inline unsigned int +get_Dest_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3f); +} + +static __inline unsigned int +get_Dest_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x3f); +} + +static __inline unsigned int +get_Dest_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3f); +} + +static __inline unsigned int +get_Dest_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x3f); +} + +static __inline unsigned int +get_Imm16_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xffff); +} + +static __inline unsigned int +get_Imm16_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xffff); +} + +static __inline unsigned int +get_Imm8_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0xff); +} + +static __inline unsigned int +get_Imm8_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xff); +} + +static __inline unsigned int +get_Imm8_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xff); +} + +static __inline unsigned int +get_Imm8_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0xff); +} + +static __inline unsigned int +get_Imm8_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0xff); +} + +static __inline unsigned int +get_ImmOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 20)) & 0x7f); +} + +static __inline unsigned int +get_ImmOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 51)) & 0x7f); +} + +static __inline unsigned int +get_ImmRROpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 8)) & 0x3); +} + +static __inline unsigned int +get_JOffLong_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000) | + (((unsigned int)(n >> 14)) & 0x001e0000) | + (((unsigned int)(n >> 16)) & 0x07e00000) | + (((unsigned int)(n >> 31)) & 0x18000000); +} + +static __inline unsigned int +get_JOff_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x00007fff) | + (((unsigned int)(n >> 20)) & 0x00018000) | + (((unsigned int)(n >> 14)) & 0x001e0000) | + (((unsigned int)(n >> 16)) & 0x07e00000) | + (((unsigned int)(n >> 31)) & 0x08000000); +} + +static __inline unsigned int +get_MF_Imm15_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x00003fff) | + (((unsigned int)(n >> 44)) & 0x00004000); +} + +static __inline unsigned int +get_MMEnd_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x1f); +} + +static __inline unsigned int +get_MMEnd_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x1f); +} + +static __inline unsigned int +get_MMStart_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 23)) & 0x1f); +} + +static __inline unsigned int +get_MMStart_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 54)) & 0x1f); +} + +static __inline unsigned int +get_MT_Imm15_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 31)) & 0x0000003f) | + (((unsigned int)(n >> 37)) & 0x00003fc0) | + (((unsigned int)(n >> 44)) & 0x00004000); +} + +static __inline unsigned int +get_Mode(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 63)) & 0x1); +} + +static __inline unsigned int +get_NoRegOpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0xf); +} + +static __inline unsigned int +get_Opcode_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 10)) & 0x3f); +} + +static __inline unsigned int +get_Opcode_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 28)) & 0x7); +} + +static __inline unsigned int +get_Opcode_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 59)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 27)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 59)) & 0xf); +} + +static __inline unsigned int +get_Opcode_Y2(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 56)) & 0x7); +} + +static __inline unsigned int +get_RROpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 4)) & 0xf); +} + +static __inline unsigned int +get_RRROpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x1ff); +} + +static __inline unsigned int +get_RRROpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x1ff); +} + +static __inline unsigned int +get_RRROpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 18)) & 0x3); +} + +static __inline unsigned int +get_RRROpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 49)) & 0x3); +} + +static __inline unsigned int +get_RouteOpcodeExtension_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3ff); +} + +static __inline unsigned int +get_S_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 27)) & 0x1); +} + +static __inline unsigned int +get_S_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 58)) & 0x1); +} + +static __inline unsigned int +get_ShAmt_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_ShAmt_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_SrcA_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 6)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 6)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 37)) & 0x3f); +} + +static __inline unsigned int +get_SrcA_Y2(tile_bundle_bits n) +{ + return (((n >> 26)) & 0x00000001) | + (((unsigned int)(n >> 50)) & 0x0000003e); +} + +static __inline unsigned int +get_SrcBDest_Y2(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 20)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x3f); +} + +static __inline unsigned int +get_SrcB_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x3f); +} + +static __inline unsigned int +get_Src_SN(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 0)) & 0x3); +} + +static __inline unsigned int +get_UnOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 12)) & 0x1f); +} + +static __inline unsigned int +get_UnOpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 43)) & 0x1f); +} + +static __inline unsigned int +get_UnShOpcodeExtension_X0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 17)) & 0x3ff); +} + +static __inline unsigned int +get_UnShOpcodeExtension_X1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 48)) & 0x3ff); +} + +static __inline unsigned int +get_UnShOpcodeExtension_Y0(tile_bundle_bits num) +{ + const unsigned int n = (unsigned int)num; + return (((n >> 17)) & 0x7); +} + +static __inline unsigned int +get_UnShOpcodeExtension_Y1(tile_bundle_bits n) +{ + return (((unsigned int)(n >> 48)) & 0x7); +} + + +static __inline int +sign_extend(int n, int num_bits) +{ + int shift = (int)(sizeof(int) * 8 - num_bits); + return (n << shift) >> shift; +} + + + +static __inline tile_bundle_bits +create_BrOff_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 0); +} + +static __inline tile_bundle_bits +create_BrOff_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20); +} + +static __inline tile_bundle_bits +create_BrType_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 31); +} + +static __inline tile_bundle_bits +create_Dest_Imm8_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | + (((tile_bundle_bits)(n & 0x000000c0)) << 43); +} + +static __inline tile_bundle_bits +create_Dest_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 2); +} + +static __inline tile_bundle_bits +create_Dest_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 0); +} + +static __inline tile_bundle_bits +create_Dest_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 31); +} + +static __inline tile_bundle_bits +create_Dest_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 0); +} + +static __inline tile_bundle_bits +create_Dest_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 31); +} + +static __inline tile_bundle_bits +create_Imm16_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xffff) << 12); +} + +static __inline tile_bundle_bits +create_Imm16_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xffff)) << 43); +} + +static __inline tile_bundle_bits +create_Imm8_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 0); +} + +static __inline tile_bundle_bits +create_Imm8_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 12); +} + +static __inline tile_bundle_bits +create_Imm8_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xff)) << 43); +} + +static __inline tile_bundle_bits +create_Imm8_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xff) << 12); +} + +static __inline tile_bundle_bits +create_Imm8_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xff)) << 43); +} + +static __inline tile_bundle_bits +create_ImmOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7f) << 20); +} + +static __inline tile_bundle_bits +create_ImmOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7f)) << 51); +} + +static __inline tile_bundle_bits +create_ImmRROpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 8); +} + +static __inline tile_bundle_bits +create_JOffLong_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20) | + (((tile_bundle_bits)(n & 0x001e0000)) << 14) | + (((tile_bundle_bits)(n & 0x07e00000)) << 16) | + (((tile_bundle_bits)(n & 0x18000000)) << 31); +} + +static __inline tile_bundle_bits +create_JOff_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00007fff)) << 43) | + (((tile_bundle_bits)(n & 0x00018000)) << 20) | + (((tile_bundle_bits)(n & 0x001e0000)) << 14) | + (((tile_bundle_bits)(n & 0x07e00000)) << 16) | + (((tile_bundle_bits)(n & 0x08000000)) << 31); +} + +static __inline tile_bundle_bits +create_MF_Imm15_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x00003fff)) << 37) | + (((tile_bundle_bits)(n & 0x00004000)) << 44); +} + +static __inline tile_bundle_bits +create_MMEnd_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 18); +} + +static __inline tile_bundle_bits +create_MMEnd_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 49); +} + +static __inline tile_bundle_bits +create_MMStart_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 23); +} + +static __inline tile_bundle_bits +create_MMStart_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 54); +} + +static __inline tile_bundle_bits +create_MT_Imm15_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x0000003f)) << 31) | + (((tile_bundle_bits)(n & 0x00003fc0)) << 37) | + (((tile_bundle_bits)(n & 0x00004000)) << 44); +} + +static __inline tile_bundle_bits +create_Mode(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1)) << 63); +} + +static __inline tile_bundle_bits +create_NoRegOpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 0); +} + +static __inline tile_bundle_bits +create_Opcode_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 10); +} + +static __inline tile_bundle_bits +create_Opcode_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7) << 28); +} + +static __inline tile_bundle_bits +create_Opcode_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 59); +} + +static __inline tile_bundle_bits +create_Opcode_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 27); +} + +static __inline tile_bundle_bits +create_Opcode_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0xf)) << 59); +} + +static __inline tile_bundle_bits +create_Opcode_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7)) << 56); +} + +static __inline tile_bundle_bits +create_RROpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0xf) << 4); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1ff) << 18); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1ff)) << 49); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 18); +} + +static __inline tile_bundle_bits +create_RRROpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3)) << 49); +} + +static __inline tile_bundle_bits +create_RouteOpcodeExtension_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 0); +} + +static __inline tile_bundle_bits +create_S_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1) << 27); +} + +static __inline tile_bundle_bits +create_S_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1)) << 58); +} + +static __inline tile_bundle_bits +create_ShAmt_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_ShAmt_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_ShAmt_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_ShAmt_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_SrcA_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 6); +} + +static __inline tile_bundle_bits +create_SrcA_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 37); +} + +static __inline tile_bundle_bits +create_SrcA_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 6); +} + +static __inline tile_bundle_bits +create_SrcA_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 37); +} + +static __inline tile_bundle_bits +create_SrcA_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x00000001) << 26) | + (((tile_bundle_bits)(n & 0x0000003e)) << 50); +} + +static __inline tile_bundle_bits +create_SrcBDest_Y2(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 20); +} + +static __inline tile_bundle_bits +create_SrcB_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 12); +} + +static __inline tile_bundle_bits +create_SrcB_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 43); +} + +static __inline tile_bundle_bits +create_SrcB_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3f) << 12); +} + +static __inline tile_bundle_bits +create_SrcB_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3f)) << 43); +} + +static __inline tile_bundle_bits +create_Src_SN(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3) << 0); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x1f) << 12); +} + +static __inline tile_bundle_bits +create_UnOpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x1f)) << 43); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_X0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x3ff) << 17); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_X1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x3ff)) << 48); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_Y0(int num) +{ + const unsigned int n = (unsigned int)num; + return ((n & 0x7) << 17); +} + +static __inline tile_bundle_bits +create_UnShOpcodeExtension_Y1(int num) +{ + const unsigned int n = (unsigned int)num; + return (((tile_bundle_bits)(n & 0x7)) << 48); +} + + +typedef unsigned short tile_sn_instruction_bits; + + +typedef enum +{ + TILE_PIPELINE_X0, + TILE_PIPELINE_X1, + TILE_PIPELINE_Y0, + TILE_PIPELINE_Y1, + TILE_PIPELINE_Y2, +} tile_pipeline; + +#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1) + +typedef enum +{ + TILE_OP_TYPE_REGISTER, + TILE_OP_TYPE_IMMEDIATE, + TILE_OP_TYPE_ADDRESS, + TILE_OP_TYPE_SPR +} tile_operand_type; + +/* This is the bit that determines if a bundle is in the Y encoding. */ +#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63) + +enum +{ + /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */ + TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3, + + /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */ + TILE_NUM_PIPELINE_ENCODINGS = 5, + + /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */ + TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3, + + /* Instructions take this many bytes. */ + TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES, + + /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */ + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, + + /* Bundles should be aligned modulo this number of bytes. */ + TILE_BUNDLE_ALIGNMENT_IN_BYTES = + (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), + + /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */ + TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1, + + /* Static network instructions take this many bytes. */ + TILE_SN_INSTRUCTION_SIZE_IN_BYTES = + (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES), + + /* Number of registers (some are magic, such as network I/O). */ + TILE_NUM_REGISTERS = 64, + + /* Number of static network registers. */ + TILE_NUM_SN_REGISTERS = 4 +}; + + +struct tile_operand +{ + /* Is this operand a register, immediate or address? */ + tile_operand_type type; + + /* The default relocation type for this operand. */ + signed int default_reloc : 16; + + /* How many bits is this value? (used for range checking) */ + unsigned int num_bits : 5; + + /* Is the value signed? (used for range checking) */ + unsigned int is_signed : 1; + + /* Is this operand a source register? */ + unsigned int is_src_reg : 1; + + /* Is this operand written? (i.e. is it a destination register) */ + unsigned int is_dest_reg : 1; + + /* Is this operand PC-relative? */ + unsigned int is_pc_relative : 1; + + /* By how many bits do we right shift the value before inserting? */ + unsigned int rightshift : 2; + + /* Return the bits for this operand to be ORed into an existing bundle. */ + tile_bundle_bits (*insert) (int op); + + /* Extract this operand and return it. */ + unsigned int (*extract) (tile_bundle_bits bundle); +}; + + +extern const struct tile_operand tile_operands[]; + +/* One finite-state machine per pipe for rapid instruction decoding. */ +extern const unsigned short * const +tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS]; + + +struct tile_opcode +{ + /* The opcode mnemonic, e.g. "add" */ + const char *name; + + /* The enum value for this mnemonic. */ + tile_mnemonic mnemonic; + + /* A bit mask of which of the five pipes this instruction + is compatible with: + X0 0x01 + X1 0x02 + Y0 0x04 + Y1 0x08 + Y2 0x10 */ + unsigned char pipes; + + /* How many operands are there? */ + unsigned char num_operands; + + /* Which register does this write implicitly, or TREG_ZERO if none? */ + unsigned char implicitly_written_register; + + /* Can this be bundled with other instructions (almost always true). */ + unsigned char can_bundle; + + /* The description of the operands. Each of these is an + * index into the tile_operands[] table. */ + unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS]; + + /* A mask of which bits have predefined values for each pipeline. + * This is useful for disassembly. */ + tile_bundle_bits fixed_bit_masks[TILE_NUM_PIPELINE_ENCODINGS]; + + /* For each bit set in fixed_bit_masks, what the value is for this + * instruction. */ + tile_bundle_bits fixed_bit_values[TILE_NUM_PIPELINE_ENCODINGS]; +}; + +extern const struct tile_opcode tile_opcodes[]; + +struct tile_sn_opcode +{ + /* The opcode mnemonic, e.g. "add" */ + const char *name; + + /* The enum value for this mnemonic. */ + tile_sn_mnemonic mnemonic; + + /* How many operands are there? */ + unsigned char num_operands; + + /* The description of the operands. Each of these is an + * index into the tile_operands[] table. */ + unsigned char operands[TILE_SN_MAX_OPERANDS]; + + /* A mask of which bits have predefined values. + * This is useful for disassembly. */ + tile_sn_instruction_bits fixed_bit_mask; + + /* For each bit set in fixed_bit_masks, what its value is. */ + tile_sn_instruction_bits fixed_bit_values; +}; + +extern const struct tile_sn_opcode tile_sn_opcodes[]; + +/* Used for non-textual disassembly into structs. */ +struct tile_decoded_instruction +{ + const struct tile_opcode *opcode; + const struct tile_operand *operands[TILE_MAX_OPERANDS]; + int operand_values[TILE_MAX_OPERANDS]; +}; + + +/* Disassemble a bundle into a struct for machine processing. */ +extern int parse_insn_tile(tile_bundle_bits bits, + unsigned int pc, + struct tile_decoded_instruction + decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]); + + +/* Canonical names of all the registers. */ +/* ISSUE: This table lives in "tile-dis.c" */ +extern const char * const tile_register_names[]; + +/* Descriptor for a special-purpose register. */ +struct tile_spr +{ + /* The number */ + int number; + + /* The name */ + const char *name; +}; + +/* List of all the SPRs; ordered by increasing number. */ +extern const struct tile_spr tile_sprs[]; + +/* Number of special-purpose registers. */ +extern const int tile_num_sprs; + +extern const char * +get_tile_spr_name (int num); + +#endif /* opcode_tile_h */ diff --git a/arch/tile/include/asm/opcode_constants.h b/arch/tile/include/asm/opcode_constants.h new file mode 100644 index 000000000000..37a9f2958cb1 --- /dev/null +++ b/arch/tile/include/asm/opcode_constants.h @@ -0,0 +1,26 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_OPCODE_CONSTANTS_H +#define _ASM_TILE_OPCODE_CONSTANTS_H + +#include + +#if CHIP_WORD_SIZE() == 64 +#include +#else +#include +#endif + +#endif /* _ASM_TILE_OPCODE_CONSTANTS_H */ diff --git a/arch/tile/include/asm/opcode_constants_32.h b/arch/tile/include/asm/opcode_constants_32.h new file mode 100644 index 000000000000..227d033b180c --- /dev/null +++ b/arch/tile/include/asm/opcode_constants_32.h @@ -0,0 +1,480 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* This file is machine-generated; DO NOT EDIT! */ + + +#ifndef _TILE_OPCODE_CONSTANTS_H +#define _TILE_OPCODE_CONSTANTS_H +enum +{ + ADDBS_U_SPECIAL_0_OPCODE_X0 = 98, + ADDBS_U_SPECIAL_0_OPCODE_X1 = 68, + ADDB_SPECIAL_0_OPCODE_X0 = 1, + ADDB_SPECIAL_0_OPCODE_X1 = 1, + ADDHS_SPECIAL_0_OPCODE_X0 = 99, + ADDHS_SPECIAL_0_OPCODE_X1 = 69, + ADDH_SPECIAL_0_OPCODE_X0 = 2, + ADDH_SPECIAL_0_OPCODE_X1 = 2, + ADDIB_IMM_0_OPCODE_X0 = 1, + ADDIB_IMM_0_OPCODE_X1 = 1, + ADDIH_IMM_0_OPCODE_X0 = 2, + ADDIH_IMM_0_OPCODE_X1 = 2, + ADDI_IMM_0_OPCODE_X0 = 3, + ADDI_IMM_0_OPCODE_X1 = 3, + ADDI_IMM_1_OPCODE_SN = 1, + ADDI_OPCODE_Y0 = 9, + ADDI_OPCODE_Y1 = 7, + ADDLIS_OPCODE_X0 = 1, + ADDLIS_OPCODE_X1 = 2, + ADDLI_OPCODE_X0 = 2, + ADDLI_OPCODE_X1 = 3, + ADDS_SPECIAL_0_OPCODE_X0 = 96, + ADDS_SPECIAL_0_OPCODE_X1 = 66, + ADD_SPECIAL_0_OPCODE_X0 = 3, + ADD_SPECIAL_0_OPCODE_X1 = 3, + ADD_SPECIAL_0_OPCODE_Y0 = 0, + ADD_SPECIAL_0_OPCODE_Y1 = 0, + ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4, + ADIFFH_SPECIAL_0_OPCODE_X0 = 5, + ANDI_IMM_0_OPCODE_X0 = 1, + ANDI_IMM_0_OPCODE_X1 = 4, + ANDI_OPCODE_Y0 = 10, + ANDI_OPCODE_Y1 = 8, + AND_SPECIAL_0_OPCODE_X0 = 6, + AND_SPECIAL_0_OPCODE_X1 = 4, + AND_SPECIAL_2_OPCODE_Y0 = 0, + AND_SPECIAL_2_OPCODE_Y1 = 0, + AULI_OPCODE_X0 = 3, + AULI_OPCODE_X1 = 4, + AVGB_U_SPECIAL_0_OPCODE_X0 = 7, + AVGH_SPECIAL_0_OPCODE_X0 = 8, + BBNST_BRANCH_OPCODE_X1 = 15, + BBNS_BRANCH_OPCODE_X1 = 14, + BBNS_OPCODE_SN = 63, + BBST_BRANCH_OPCODE_X1 = 13, + BBS_BRANCH_OPCODE_X1 = 12, + BBS_OPCODE_SN = 62, + BGEZT_BRANCH_OPCODE_X1 = 7, + BGEZ_BRANCH_OPCODE_X1 = 6, + BGEZ_OPCODE_SN = 61, + BGZT_BRANCH_OPCODE_X1 = 5, + BGZ_BRANCH_OPCODE_X1 = 4, + BGZ_OPCODE_SN = 58, + BITX_UN_0_SHUN_0_OPCODE_X0 = 1, + BITX_UN_0_SHUN_0_OPCODE_Y0 = 1, + BLEZT_BRANCH_OPCODE_X1 = 11, + BLEZ_BRANCH_OPCODE_X1 = 10, + BLEZ_OPCODE_SN = 59, + BLZT_BRANCH_OPCODE_X1 = 9, + BLZ_BRANCH_OPCODE_X1 = 8, + BLZ_OPCODE_SN = 60, + BNZT_BRANCH_OPCODE_X1 = 3, + BNZ_BRANCH_OPCODE_X1 = 2, + BNZ_OPCODE_SN = 57, + BPT_NOREG_RR_IMM_0_OPCODE_SN = 1, + BRANCH_OPCODE_X1 = 5, + BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2, + BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2, + BZT_BRANCH_OPCODE_X1 = 1, + BZ_BRANCH_OPCODE_X1 = 0, + BZ_OPCODE_SN = 56, + CLZ_UN_0_SHUN_0_OPCODE_X0 = 3, + CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3, + CRC32_32_SPECIAL_0_OPCODE_X0 = 9, + CRC32_8_SPECIAL_0_OPCODE_X0 = 10, + CTZ_UN_0_SHUN_0_OPCODE_X0 = 4, + CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4, + DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1, + DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2, + DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95, + FINV_UN_0_SHUN_0_OPCODE_X1 = 3, + FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4, + FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3, + FNOP_UN_0_SHUN_0_OPCODE_X0 = 5, + FNOP_UN_0_SHUN_0_OPCODE_X1 = 5, + FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5, + FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1, + HALT_NOREG_RR_IMM_0_OPCODE_SN = 0, + ICOH_UN_0_SHUN_0_OPCODE_X1 = 6, + ILL_UN_0_SHUN_0_OPCODE_X1 = 7, + ILL_UN_0_SHUN_0_OPCODE_Y1 = 2, + IMM_0_OPCODE_SN = 0, + IMM_0_OPCODE_X0 = 4, + IMM_0_OPCODE_X1 = 6, + IMM_1_OPCODE_SN = 1, + IMM_OPCODE_0_X0 = 5, + INTHB_SPECIAL_0_OPCODE_X0 = 11, + INTHB_SPECIAL_0_OPCODE_X1 = 5, + INTHH_SPECIAL_0_OPCODE_X0 = 12, + INTHH_SPECIAL_0_OPCODE_X1 = 6, + INTLB_SPECIAL_0_OPCODE_X0 = 13, + INTLB_SPECIAL_0_OPCODE_X1 = 7, + INTLH_SPECIAL_0_OPCODE_X0 = 14, + INTLH_SPECIAL_0_OPCODE_X1 = 8, + INV_UN_0_SHUN_0_OPCODE_X1 = 8, + IRET_UN_0_SHUN_0_OPCODE_X1 = 9, + JALB_OPCODE_X1 = 13, + JALF_OPCODE_X1 = 12, + JALRP_SPECIAL_0_OPCODE_X1 = 9, + JALRR_IMM_1_OPCODE_SN = 3, + JALR_RR_IMM_0_OPCODE_SN = 5, + JALR_SPECIAL_0_OPCODE_X1 = 10, + JB_OPCODE_X1 = 11, + JF_OPCODE_X1 = 10, + JRP_SPECIAL_0_OPCODE_X1 = 11, + JRR_IMM_1_OPCODE_SN = 2, + JR_RR_IMM_0_OPCODE_SN = 4, + JR_SPECIAL_0_OPCODE_X1 = 12, + LBADD_IMM_0_OPCODE_X1 = 22, + LBADD_U_IMM_0_OPCODE_X1 = 23, + LB_OPCODE_Y2 = 0, + LB_UN_0_SHUN_0_OPCODE_X1 = 10, + LB_U_OPCODE_Y2 = 1, + LB_U_UN_0_SHUN_0_OPCODE_X1 = 11, + LHADD_IMM_0_OPCODE_X1 = 24, + LHADD_U_IMM_0_OPCODE_X1 = 25, + LH_OPCODE_Y2 = 2, + LH_UN_0_SHUN_0_OPCODE_X1 = 12, + LH_U_OPCODE_Y2 = 3, + LH_U_UN_0_SHUN_0_OPCODE_X1 = 13, + LNK_SPECIAL_0_OPCODE_X1 = 13, + LWADD_IMM_0_OPCODE_X1 = 26, + LWADD_NA_IMM_0_OPCODE_X1 = 27, + LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24, + LW_OPCODE_Y2 = 4, + LW_UN_0_SHUN_0_OPCODE_X1 = 14, + MAXB_U_SPECIAL_0_OPCODE_X0 = 15, + MAXB_U_SPECIAL_0_OPCODE_X1 = 14, + MAXH_SPECIAL_0_OPCODE_X0 = 16, + MAXH_SPECIAL_0_OPCODE_X1 = 15, + MAXIB_U_IMM_0_OPCODE_X0 = 4, + MAXIB_U_IMM_0_OPCODE_X1 = 5, + MAXIH_IMM_0_OPCODE_X0 = 5, + MAXIH_IMM_0_OPCODE_X1 = 6, + MFSPR_IMM_0_OPCODE_X1 = 7, + MF_UN_0_SHUN_0_OPCODE_X1 = 15, + MINB_U_SPECIAL_0_OPCODE_X0 = 17, + MINB_U_SPECIAL_0_OPCODE_X1 = 16, + MINH_SPECIAL_0_OPCODE_X0 = 18, + MINH_SPECIAL_0_OPCODE_X1 = 17, + MINIB_U_IMM_0_OPCODE_X0 = 6, + MINIB_U_IMM_0_OPCODE_X1 = 8, + MINIH_IMM_0_OPCODE_X0 = 7, + MINIH_IMM_0_OPCODE_X1 = 9, + MM_OPCODE_X0 = 6, + MM_OPCODE_X1 = 7, + MNZB_SPECIAL_0_OPCODE_X0 = 19, + MNZB_SPECIAL_0_OPCODE_X1 = 18, + MNZH_SPECIAL_0_OPCODE_X0 = 20, + MNZH_SPECIAL_0_OPCODE_X1 = 19, + MNZ_SPECIAL_0_OPCODE_X0 = 21, + MNZ_SPECIAL_0_OPCODE_X1 = 20, + MNZ_SPECIAL_1_OPCODE_Y0 = 0, + MNZ_SPECIAL_1_OPCODE_Y1 = 1, + MOVEI_IMM_1_OPCODE_SN = 0, + MOVE_RR_IMM_0_OPCODE_SN = 8, + MTSPR_IMM_0_OPCODE_X1 = 10, + MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22, + MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0, + MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23, + MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24, + MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1, + MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25, + MULHH_SS_SPECIAL_0_OPCODE_X0 = 26, + MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0, + MULHH_SU_SPECIAL_0_OPCODE_X0 = 27, + MULHH_UU_SPECIAL_0_OPCODE_X0 = 28, + MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1, + MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29, + MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30, + MULHLA_US_SPECIAL_0_OPCODE_X0 = 31, + MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32, + MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33, + MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0, + MULHL_SS_SPECIAL_0_OPCODE_X0 = 34, + MULHL_SU_SPECIAL_0_OPCODE_X0 = 35, + MULHL_US_SPECIAL_0_OPCODE_X0 = 36, + MULHL_UU_SPECIAL_0_OPCODE_X0 = 37, + MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38, + MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2, + MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39, + MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40, + MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3, + MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41, + MULLL_SS_SPECIAL_0_OPCODE_X0 = 42, + MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2, + MULLL_SU_SPECIAL_0_OPCODE_X0 = 43, + MULLL_UU_SPECIAL_0_OPCODE_X0 = 44, + MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3, + MVNZ_SPECIAL_0_OPCODE_X0 = 45, + MVNZ_SPECIAL_1_OPCODE_Y0 = 1, + MVZ_SPECIAL_0_OPCODE_X0 = 46, + MVZ_SPECIAL_1_OPCODE_Y0 = 2, + MZB_SPECIAL_0_OPCODE_X0 = 47, + MZB_SPECIAL_0_OPCODE_X1 = 21, + MZH_SPECIAL_0_OPCODE_X0 = 48, + MZH_SPECIAL_0_OPCODE_X1 = 22, + MZ_SPECIAL_0_OPCODE_X0 = 49, + MZ_SPECIAL_0_OPCODE_X1 = 23, + MZ_SPECIAL_1_OPCODE_Y0 = 3, + MZ_SPECIAL_1_OPCODE_Y1 = 2, + NAP_UN_0_SHUN_0_OPCODE_X1 = 16, + NOP_NOREG_RR_IMM_0_OPCODE_SN = 2, + NOP_UN_0_SHUN_0_OPCODE_X0 = 6, + NOP_UN_0_SHUN_0_OPCODE_X1 = 17, + NOP_UN_0_SHUN_0_OPCODE_Y0 = 6, + NOP_UN_0_SHUN_0_OPCODE_Y1 = 3, + NOREG_RR_IMM_0_OPCODE_SN = 0, + NOR_SPECIAL_0_OPCODE_X0 = 50, + NOR_SPECIAL_0_OPCODE_X1 = 24, + NOR_SPECIAL_2_OPCODE_Y0 = 1, + NOR_SPECIAL_2_OPCODE_Y1 = 1, + ORI_IMM_0_OPCODE_X0 = 8, + ORI_IMM_0_OPCODE_X1 = 11, + ORI_OPCODE_Y0 = 11, + ORI_OPCODE_Y1 = 9, + OR_SPECIAL_0_OPCODE_X0 = 51, + OR_SPECIAL_0_OPCODE_X1 = 25, + OR_SPECIAL_2_OPCODE_Y0 = 2, + OR_SPECIAL_2_OPCODE_Y1 = 2, + PACKBS_U_SPECIAL_0_OPCODE_X0 = 103, + PACKBS_U_SPECIAL_0_OPCODE_X1 = 73, + PACKHB_SPECIAL_0_OPCODE_X0 = 52, + PACKHB_SPECIAL_0_OPCODE_X1 = 26, + PACKHS_SPECIAL_0_OPCODE_X0 = 102, + PACKHS_SPECIAL_0_OPCODE_X1 = 72, + PACKLB_SPECIAL_0_OPCODE_X0 = 53, + PACKLB_SPECIAL_0_OPCODE_X1 = 27, + PCNT_UN_0_SHUN_0_OPCODE_X0 = 7, + PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7, + RLI_SHUN_0_OPCODE_X0 = 1, + RLI_SHUN_0_OPCODE_X1 = 1, + RLI_SHUN_0_OPCODE_Y0 = 1, + RLI_SHUN_0_OPCODE_Y1 = 1, + RL_SPECIAL_0_OPCODE_X0 = 54, + RL_SPECIAL_0_OPCODE_X1 = 28, + RL_SPECIAL_3_OPCODE_Y0 = 0, + RL_SPECIAL_3_OPCODE_Y1 = 0, + RR_IMM_0_OPCODE_SN = 0, + S1A_SPECIAL_0_OPCODE_X0 = 55, + S1A_SPECIAL_0_OPCODE_X1 = 29, + S1A_SPECIAL_0_OPCODE_Y0 = 1, + S1A_SPECIAL_0_OPCODE_Y1 = 1, + S2A_SPECIAL_0_OPCODE_X0 = 56, + S2A_SPECIAL_0_OPCODE_X1 = 30, + S2A_SPECIAL_0_OPCODE_Y0 = 2, + S2A_SPECIAL_0_OPCODE_Y1 = 2, + S3A_SPECIAL_0_OPCODE_X0 = 57, + S3A_SPECIAL_0_OPCODE_X1 = 31, + S3A_SPECIAL_5_OPCODE_Y0 = 1, + S3A_SPECIAL_5_OPCODE_Y1 = 1, + SADAB_U_SPECIAL_0_OPCODE_X0 = 58, + SADAH_SPECIAL_0_OPCODE_X0 = 59, + SADAH_U_SPECIAL_0_OPCODE_X0 = 60, + SADB_U_SPECIAL_0_OPCODE_X0 = 61, + SADH_SPECIAL_0_OPCODE_X0 = 62, + SADH_U_SPECIAL_0_OPCODE_X0 = 63, + SBADD_IMM_0_OPCODE_X1 = 28, + SB_OPCODE_Y2 = 5, + SB_SPECIAL_0_OPCODE_X1 = 32, + SEQB_SPECIAL_0_OPCODE_X0 = 64, + SEQB_SPECIAL_0_OPCODE_X1 = 33, + SEQH_SPECIAL_0_OPCODE_X0 = 65, + SEQH_SPECIAL_0_OPCODE_X1 = 34, + SEQIB_IMM_0_OPCODE_X0 = 9, + SEQIB_IMM_0_OPCODE_X1 = 12, + SEQIH_IMM_0_OPCODE_X0 = 10, + SEQIH_IMM_0_OPCODE_X1 = 13, + SEQI_IMM_0_OPCODE_X0 = 11, + SEQI_IMM_0_OPCODE_X1 = 14, + SEQI_OPCODE_Y0 = 12, + SEQI_OPCODE_Y1 = 10, + SEQ_SPECIAL_0_OPCODE_X0 = 66, + SEQ_SPECIAL_0_OPCODE_X1 = 35, + SEQ_SPECIAL_5_OPCODE_Y0 = 2, + SEQ_SPECIAL_5_OPCODE_Y1 = 2, + SHADD_IMM_0_OPCODE_X1 = 29, + SHL8II_IMM_0_OPCODE_SN = 3, + SHLB_SPECIAL_0_OPCODE_X0 = 67, + SHLB_SPECIAL_0_OPCODE_X1 = 36, + SHLH_SPECIAL_0_OPCODE_X0 = 68, + SHLH_SPECIAL_0_OPCODE_X1 = 37, + SHLIB_SHUN_0_OPCODE_X0 = 2, + SHLIB_SHUN_0_OPCODE_X1 = 2, + SHLIH_SHUN_0_OPCODE_X0 = 3, + SHLIH_SHUN_0_OPCODE_X1 = 3, + SHLI_SHUN_0_OPCODE_X0 = 4, + SHLI_SHUN_0_OPCODE_X1 = 4, + SHLI_SHUN_0_OPCODE_Y0 = 2, + SHLI_SHUN_0_OPCODE_Y1 = 2, + SHL_SPECIAL_0_OPCODE_X0 = 69, + SHL_SPECIAL_0_OPCODE_X1 = 38, + SHL_SPECIAL_3_OPCODE_Y0 = 1, + SHL_SPECIAL_3_OPCODE_Y1 = 1, + SHR1_RR_IMM_0_OPCODE_SN = 9, + SHRB_SPECIAL_0_OPCODE_X0 = 70, + SHRB_SPECIAL_0_OPCODE_X1 = 39, + SHRH_SPECIAL_0_OPCODE_X0 = 71, + SHRH_SPECIAL_0_OPCODE_X1 = 40, + SHRIB_SHUN_0_OPCODE_X0 = 5, + SHRIB_SHUN_0_OPCODE_X1 = 5, + SHRIH_SHUN_0_OPCODE_X0 = 6, + SHRIH_SHUN_0_OPCODE_X1 = 6, + SHRI_SHUN_0_OPCODE_X0 = 7, + SHRI_SHUN_0_OPCODE_X1 = 7, + SHRI_SHUN_0_OPCODE_Y0 = 3, + SHRI_SHUN_0_OPCODE_Y1 = 3, + SHR_SPECIAL_0_OPCODE_X0 = 72, + SHR_SPECIAL_0_OPCODE_X1 = 41, + SHR_SPECIAL_3_OPCODE_Y0 = 2, + SHR_SPECIAL_3_OPCODE_Y1 = 2, + SHUN_0_OPCODE_X0 = 7, + SHUN_0_OPCODE_X1 = 8, + SHUN_0_OPCODE_Y0 = 13, + SHUN_0_OPCODE_Y1 = 11, + SH_OPCODE_Y2 = 6, + SH_SPECIAL_0_OPCODE_X1 = 42, + SLTB_SPECIAL_0_OPCODE_X0 = 73, + SLTB_SPECIAL_0_OPCODE_X1 = 43, + SLTB_U_SPECIAL_0_OPCODE_X0 = 74, + SLTB_U_SPECIAL_0_OPCODE_X1 = 44, + SLTEB_SPECIAL_0_OPCODE_X0 = 75, + SLTEB_SPECIAL_0_OPCODE_X1 = 45, + SLTEB_U_SPECIAL_0_OPCODE_X0 = 76, + SLTEB_U_SPECIAL_0_OPCODE_X1 = 46, + SLTEH_SPECIAL_0_OPCODE_X0 = 77, + SLTEH_SPECIAL_0_OPCODE_X1 = 47, + SLTEH_U_SPECIAL_0_OPCODE_X0 = 78, + SLTEH_U_SPECIAL_0_OPCODE_X1 = 48, + SLTE_SPECIAL_0_OPCODE_X0 = 79, + SLTE_SPECIAL_0_OPCODE_X1 = 49, + SLTE_SPECIAL_4_OPCODE_Y0 = 0, + SLTE_SPECIAL_4_OPCODE_Y1 = 0, + SLTE_U_SPECIAL_0_OPCODE_X0 = 80, + SLTE_U_SPECIAL_0_OPCODE_X1 = 50, + SLTE_U_SPECIAL_4_OPCODE_Y0 = 1, + SLTE_U_SPECIAL_4_OPCODE_Y1 = 1, + SLTH_SPECIAL_0_OPCODE_X0 = 81, + SLTH_SPECIAL_0_OPCODE_X1 = 51, + SLTH_U_SPECIAL_0_OPCODE_X0 = 82, + SLTH_U_SPECIAL_0_OPCODE_X1 = 52, + SLTIB_IMM_0_OPCODE_X0 = 12, + SLTIB_IMM_0_OPCODE_X1 = 15, + SLTIB_U_IMM_0_OPCODE_X0 = 13, + SLTIB_U_IMM_0_OPCODE_X1 = 16, + SLTIH_IMM_0_OPCODE_X0 = 14, + SLTIH_IMM_0_OPCODE_X1 = 17, + SLTIH_U_IMM_0_OPCODE_X0 = 15, + SLTIH_U_IMM_0_OPCODE_X1 = 18, + SLTI_IMM_0_OPCODE_X0 = 16, + SLTI_IMM_0_OPCODE_X1 = 19, + SLTI_OPCODE_Y0 = 14, + SLTI_OPCODE_Y1 = 12, + SLTI_U_IMM_0_OPCODE_X0 = 17, + SLTI_U_IMM_0_OPCODE_X1 = 20, + SLTI_U_OPCODE_Y0 = 15, + SLTI_U_OPCODE_Y1 = 13, + SLT_SPECIAL_0_OPCODE_X0 = 83, + SLT_SPECIAL_0_OPCODE_X1 = 53, + SLT_SPECIAL_4_OPCODE_Y0 = 2, + SLT_SPECIAL_4_OPCODE_Y1 = 2, + SLT_U_SPECIAL_0_OPCODE_X0 = 84, + SLT_U_SPECIAL_0_OPCODE_X1 = 54, + SLT_U_SPECIAL_4_OPCODE_Y0 = 3, + SLT_U_SPECIAL_4_OPCODE_Y1 = 3, + SNEB_SPECIAL_0_OPCODE_X0 = 85, + SNEB_SPECIAL_0_OPCODE_X1 = 55, + SNEH_SPECIAL_0_OPCODE_X0 = 86, + SNEH_SPECIAL_0_OPCODE_X1 = 56, + SNE_SPECIAL_0_OPCODE_X0 = 87, + SNE_SPECIAL_0_OPCODE_X1 = 57, + SNE_SPECIAL_5_OPCODE_Y0 = 3, + SNE_SPECIAL_5_OPCODE_Y1 = 3, + SPECIAL_0_OPCODE_X0 = 0, + SPECIAL_0_OPCODE_X1 = 1, + SPECIAL_0_OPCODE_Y0 = 1, + SPECIAL_0_OPCODE_Y1 = 1, + SPECIAL_1_OPCODE_Y0 = 2, + SPECIAL_1_OPCODE_Y1 = 2, + SPECIAL_2_OPCODE_Y0 = 3, + SPECIAL_2_OPCODE_Y1 = 3, + SPECIAL_3_OPCODE_Y0 = 4, + SPECIAL_3_OPCODE_Y1 = 4, + SPECIAL_4_OPCODE_Y0 = 5, + SPECIAL_4_OPCODE_Y1 = 5, + SPECIAL_5_OPCODE_Y0 = 6, + SPECIAL_5_OPCODE_Y1 = 6, + SPECIAL_6_OPCODE_Y0 = 7, + SPECIAL_7_OPCODE_Y0 = 8, + SRAB_SPECIAL_0_OPCODE_X0 = 88, + SRAB_SPECIAL_0_OPCODE_X1 = 58, + SRAH_SPECIAL_0_OPCODE_X0 = 89, + SRAH_SPECIAL_0_OPCODE_X1 = 59, + SRAIB_SHUN_0_OPCODE_X0 = 8, + SRAIB_SHUN_0_OPCODE_X1 = 8, + SRAIH_SHUN_0_OPCODE_X0 = 9, + SRAIH_SHUN_0_OPCODE_X1 = 9, + SRAI_SHUN_0_OPCODE_X0 = 10, + SRAI_SHUN_0_OPCODE_X1 = 10, + SRAI_SHUN_0_OPCODE_Y0 = 4, + SRAI_SHUN_0_OPCODE_Y1 = 4, + SRA_SPECIAL_0_OPCODE_X0 = 90, + SRA_SPECIAL_0_OPCODE_X1 = 60, + SRA_SPECIAL_3_OPCODE_Y0 = 3, + SRA_SPECIAL_3_OPCODE_Y1 = 3, + SUBBS_U_SPECIAL_0_OPCODE_X0 = 100, + SUBBS_U_SPECIAL_0_OPCODE_X1 = 70, + SUBB_SPECIAL_0_OPCODE_X0 = 91, + SUBB_SPECIAL_0_OPCODE_X1 = 61, + SUBHS_SPECIAL_0_OPCODE_X0 = 101, + SUBHS_SPECIAL_0_OPCODE_X1 = 71, + SUBH_SPECIAL_0_OPCODE_X0 = 92, + SUBH_SPECIAL_0_OPCODE_X1 = 62, + SUBS_SPECIAL_0_OPCODE_X0 = 97, + SUBS_SPECIAL_0_OPCODE_X1 = 67, + SUB_SPECIAL_0_OPCODE_X0 = 93, + SUB_SPECIAL_0_OPCODE_X1 = 63, + SUB_SPECIAL_0_OPCODE_Y0 = 3, + SUB_SPECIAL_0_OPCODE_Y1 = 3, + SWADD_IMM_0_OPCODE_X1 = 30, + SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18, + SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19, + SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20, + SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21, + SW_OPCODE_Y2 = 7, + SW_SPECIAL_0_OPCODE_X1 = 64, + TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8, + TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8, + TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9, + TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9, + TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10, + TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10, + TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11, + TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11, + TNS_UN_0_SHUN_0_OPCODE_X1 = 22, + UN_0_SHUN_0_OPCODE_X0 = 11, + UN_0_SHUN_0_OPCODE_X1 = 11, + UN_0_SHUN_0_OPCODE_Y0 = 5, + UN_0_SHUN_0_OPCODE_Y1 = 5, + WH64_UN_0_SHUN_0_OPCODE_X1 = 23, + XORI_IMM_0_OPCODE_X0 = 2, + XORI_IMM_0_OPCODE_X1 = 21, + XOR_SPECIAL_0_OPCODE_X0 = 94, + XOR_SPECIAL_0_OPCODE_X1 = 65, + XOR_SPECIAL_2_OPCODE_Y0 = 3, + XOR_SPECIAL_2_OPCODE_Y1 = 3 +}; + +#endif /* !_TILE_OPCODE_CONSTANTS_H */ diff --git a/arch/tile/include/asm/opcode_constants_64.h b/arch/tile/include/asm/opcode_constants_64.h new file mode 100644 index 000000000000..227d033b180c --- /dev/null +++ b/arch/tile/include/asm/opcode_constants_64.h @@ -0,0 +1,480 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* This file is machine-generated; DO NOT EDIT! */ + + +#ifndef _TILE_OPCODE_CONSTANTS_H +#define _TILE_OPCODE_CONSTANTS_H +enum +{ + ADDBS_U_SPECIAL_0_OPCODE_X0 = 98, + ADDBS_U_SPECIAL_0_OPCODE_X1 = 68, + ADDB_SPECIAL_0_OPCODE_X0 = 1, + ADDB_SPECIAL_0_OPCODE_X1 = 1, + ADDHS_SPECIAL_0_OPCODE_X0 = 99, + ADDHS_SPECIAL_0_OPCODE_X1 = 69, + ADDH_SPECIAL_0_OPCODE_X0 = 2, + ADDH_SPECIAL_0_OPCODE_X1 = 2, + ADDIB_IMM_0_OPCODE_X0 = 1, + ADDIB_IMM_0_OPCODE_X1 = 1, + ADDIH_IMM_0_OPCODE_X0 = 2, + ADDIH_IMM_0_OPCODE_X1 = 2, + ADDI_IMM_0_OPCODE_X0 = 3, + ADDI_IMM_0_OPCODE_X1 = 3, + ADDI_IMM_1_OPCODE_SN = 1, + ADDI_OPCODE_Y0 = 9, + ADDI_OPCODE_Y1 = 7, + ADDLIS_OPCODE_X0 = 1, + ADDLIS_OPCODE_X1 = 2, + ADDLI_OPCODE_X0 = 2, + ADDLI_OPCODE_X1 = 3, + ADDS_SPECIAL_0_OPCODE_X0 = 96, + ADDS_SPECIAL_0_OPCODE_X1 = 66, + ADD_SPECIAL_0_OPCODE_X0 = 3, + ADD_SPECIAL_0_OPCODE_X1 = 3, + ADD_SPECIAL_0_OPCODE_Y0 = 0, + ADD_SPECIAL_0_OPCODE_Y1 = 0, + ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4, + ADIFFH_SPECIAL_0_OPCODE_X0 = 5, + ANDI_IMM_0_OPCODE_X0 = 1, + ANDI_IMM_0_OPCODE_X1 = 4, + ANDI_OPCODE_Y0 = 10, + ANDI_OPCODE_Y1 = 8, + AND_SPECIAL_0_OPCODE_X0 = 6, + AND_SPECIAL_0_OPCODE_X1 = 4, + AND_SPECIAL_2_OPCODE_Y0 = 0, + AND_SPECIAL_2_OPCODE_Y1 = 0, + AULI_OPCODE_X0 = 3, + AULI_OPCODE_X1 = 4, + AVGB_U_SPECIAL_0_OPCODE_X0 = 7, + AVGH_SPECIAL_0_OPCODE_X0 = 8, + BBNST_BRANCH_OPCODE_X1 = 15, + BBNS_BRANCH_OPCODE_X1 = 14, + BBNS_OPCODE_SN = 63, + BBST_BRANCH_OPCODE_X1 = 13, + BBS_BRANCH_OPCODE_X1 = 12, + BBS_OPCODE_SN = 62, + BGEZT_BRANCH_OPCODE_X1 = 7, + BGEZ_BRANCH_OPCODE_X1 = 6, + BGEZ_OPCODE_SN = 61, + BGZT_BRANCH_OPCODE_X1 = 5, + BGZ_BRANCH_OPCODE_X1 = 4, + BGZ_OPCODE_SN = 58, + BITX_UN_0_SHUN_0_OPCODE_X0 = 1, + BITX_UN_0_SHUN_0_OPCODE_Y0 = 1, + BLEZT_BRANCH_OPCODE_X1 = 11, + BLEZ_BRANCH_OPCODE_X1 = 10, + BLEZ_OPCODE_SN = 59, + BLZT_BRANCH_OPCODE_X1 = 9, + BLZ_BRANCH_OPCODE_X1 = 8, + BLZ_OPCODE_SN = 60, + BNZT_BRANCH_OPCODE_X1 = 3, + BNZ_BRANCH_OPCODE_X1 = 2, + BNZ_OPCODE_SN = 57, + BPT_NOREG_RR_IMM_0_OPCODE_SN = 1, + BRANCH_OPCODE_X1 = 5, + BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2, + BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2, + BZT_BRANCH_OPCODE_X1 = 1, + BZ_BRANCH_OPCODE_X1 = 0, + BZ_OPCODE_SN = 56, + CLZ_UN_0_SHUN_0_OPCODE_X0 = 3, + CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3, + CRC32_32_SPECIAL_0_OPCODE_X0 = 9, + CRC32_8_SPECIAL_0_OPCODE_X0 = 10, + CTZ_UN_0_SHUN_0_OPCODE_X0 = 4, + CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4, + DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1, + DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2, + DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95, + FINV_UN_0_SHUN_0_OPCODE_X1 = 3, + FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4, + FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3, + FNOP_UN_0_SHUN_0_OPCODE_X0 = 5, + FNOP_UN_0_SHUN_0_OPCODE_X1 = 5, + FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5, + FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1, + HALT_NOREG_RR_IMM_0_OPCODE_SN = 0, + ICOH_UN_0_SHUN_0_OPCODE_X1 = 6, + ILL_UN_0_SHUN_0_OPCODE_X1 = 7, + ILL_UN_0_SHUN_0_OPCODE_Y1 = 2, + IMM_0_OPCODE_SN = 0, + IMM_0_OPCODE_X0 = 4, + IMM_0_OPCODE_X1 = 6, + IMM_1_OPCODE_SN = 1, + IMM_OPCODE_0_X0 = 5, + INTHB_SPECIAL_0_OPCODE_X0 = 11, + INTHB_SPECIAL_0_OPCODE_X1 = 5, + INTHH_SPECIAL_0_OPCODE_X0 = 12, + INTHH_SPECIAL_0_OPCODE_X1 = 6, + INTLB_SPECIAL_0_OPCODE_X0 = 13, + INTLB_SPECIAL_0_OPCODE_X1 = 7, + INTLH_SPECIAL_0_OPCODE_X0 = 14, + INTLH_SPECIAL_0_OPCODE_X1 = 8, + INV_UN_0_SHUN_0_OPCODE_X1 = 8, + IRET_UN_0_SHUN_0_OPCODE_X1 = 9, + JALB_OPCODE_X1 = 13, + JALF_OPCODE_X1 = 12, + JALRP_SPECIAL_0_OPCODE_X1 = 9, + JALRR_IMM_1_OPCODE_SN = 3, + JALR_RR_IMM_0_OPCODE_SN = 5, + JALR_SPECIAL_0_OPCODE_X1 = 10, + JB_OPCODE_X1 = 11, + JF_OPCODE_X1 = 10, + JRP_SPECIAL_0_OPCODE_X1 = 11, + JRR_IMM_1_OPCODE_SN = 2, + JR_RR_IMM_0_OPCODE_SN = 4, + JR_SPECIAL_0_OPCODE_X1 = 12, + LBADD_IMM_0_OPCODE_X1 = 22, + LBADD_U_IMM_0_OPCODE_X1 = 23, + LB_OPCODE_Y2 = 0, + LB_UN_0_SHUN_0_OPCODE_X1 = 10, + LB_U_OPCODE_Y2 = 1, + LB_U_UN_0_SHUN_0_OPCODE_X1 = 11, + LHADD_IMM_0_OPCODE_X1 = 24, + LHADD_U_IMM_0_OPCODE_X1 = 25, + LH_OPCODE_Y2 = 2, + LH_UN_0_SHUN_0_OPCODE_X1 = 12, + LH_U_OPCODE_Y2 = 3, + LH_U_UN_0_SHUN_0_OPCODE_X1 = 13, + LNK_SPECIAL_0_OPCODE_X1 = 13, + LWADD_IMM_0_OPCODE_X1 = 26, + LWADD_NA_IMM_0_OPCODE_X1 = 27, + LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24, + LW_OPCODE_Y2 = 4, + LW_UN_0_SHUN_0_OPCODE_X1 = 14, + MAXB_U_SPECIAL_0_OPCODE_X0 = 15, + MAXB_U_SPECIAL_0_OPCODE_X1 = 14, + MAXH_SPECIAL_0_OPCODE_X0 = 16, + MAXH_SPECIAL_0_OPCODE_X1 = 15, + MAXIB_U_IMM_0_OPCODE_X0 = 4, + MAXIB_U_IMM_0_OPCODE_X1 = 5, + MAXIH_IMM_0_OPCODE_X0 = 5, + MAXIH_IMM_0_OPCODE_X1 = 6, + MFSPR_IMM_0_OPCODE_X1 = 7, + MF_UN_0_SHUN_0_OPCODE_X1 = 15, + MINB_U_SPECIAL_0_OPCODE_X0 = 17, + MINB_U_SPECIAL_0_OPCODE_X1 = 16, + MINH_SPECIAL_0_OPCODE_X0 = 18, + MINH_SPECIAL_0_OPCODE_X1 = 17, + MINIB_U_IMM_0_OPCODE_X0 = 6, + MINIB_U_IMM_0_OPCODE_X1 = 8, + MINIH_IMM_0_OPCODE_X0 = 7, + MINIH_IMM_0_OPCODE_X1 = 9, + MM_OPCODE_X0 = 6, + MM_OPCODE_X1 = 7, + MNZB_SPECIAL_0_OPCODE_X0 = 19, + MNZB_SPECIAL_0_OPCODE_X1 = 18, + MNZH_SPECIAL_0_OPCODE_X0 = 20, + MNZH_SPECIAL_0_OPCODE_X1 = 19, + MNZ_SPECIAL_0_OPCODE_X0 = 21, + MNZ_SPECIAL_0_OPCODE_X1 = 20, + MNZ_SPECIAL_1_OPCODE_Y0 = 0, + MNZ_SPECIAL_1_OPCODE_Y1 = 1, + MOVEI_IMM_1_OPCODE_SN = 0, + MOVE_RR_IMM_0_OPCODE_SN = 8, + MTSPR_IMM_0_OPCODE_X1 = 10, + MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22, + MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0, + MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23, + MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24, + MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1, + MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25, + MULHH_SS_SPECIAL_0_OPCODE_X0 = 26, + MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0, + MULHH_SU_SPECIAL_0_OPCODE_X0 = 27, + MULHH_UU_SPECIAL_0_OPCODE_X0 = 28, + MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1, + MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29, + MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30, + MULHLA_US_SPECIAL_0_OPCODE_X0 = 31, + MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32, + MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33, + MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0, + MULHL_SS_SPECIAL_0_OPCODE_X0 = 34, + MULHL_SU_SPECIAL_0_OPCODE_X0 = 35, + MULHL_US_SPECIAL_0_OPCODE_X0 = 36, + MULHL_UU_SPECIAL_0_OPCODE_X0 = 37, + MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38, + MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2, + MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39, + MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40, + MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3, + MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41, + MULLL_SS_SPECIAL_0_OPCODE_X0 = 42, + MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2, + MULLL_SU_SPECIAL_0_OPCODE_X0 = 43, + MULLL_UU_SPECIAL_0_OPCODE_X0 = 44, + MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3, + MVNZ_SPECIAL_0_OPCODE_X0 = 45, + MVNZ_SPECIAL_1_OPCODE_Y0 = 1, + MVZ_SPECIAL_0_OPCODE_X0 = 46, + MVZ_SPECIAL_1_OPCODE_Y0 = 2, + MZB_SPECIAL_0_OPCODE_X0 = 47, + MZB_SPECIAL_0_OPCODE_X1 = 21, + MZH_SPECIAL_0_OPCODE_X0 = 48, + MZH_SPECIAL_0_OPCODE_X1 = 22, + MZ_SPECIAL_0_OPCODE_X0 = 49, + MZ_SPECIAL_0_OPCODE_X1 = 23, + MZ_SPECIAL_1_OPCODE_Y0 = 3, + MZ_SPECIAL_1_OPCODE_Y1 = 2, + NAP_UN_0_SHUN_0_OPCODE_X1 = 16, + NOP_NOREG_RR_IMM_0_OPCODE_SN = 2, + NOP_UN_0_SHUN_0_OPCODE_X0 = 6, + NOP_UN_0_SHUN_0_OPCODE_X1 = 17, + NOP_UN_0_SHUN_0_OPCODE_Y0 = 6, + NOP_UN_0_SHUN_0_OPCODE_Y1 = 3, + NOREG_RR_IMM_0_OPCODE_SN = 0, + NOR_SPECIAL_0_OPCODE_X0 = 50, + NOR_SPECIAL_0_OPCODE_X1 = 24, + NOR_SPECIAL_2_OPCODE_Y0 = 1, + NOR_SPECIAL_2_OPCODE_Y1 = 1, + ORI_IMM_0_OPCODE_X0 = 8, + ORI_IMM_0_OPCODE_X1 = 11, + ORI_OPCODE_Y0 = 11, + ORI_OPCODE_Y1 = 9, + OR_SPECIAL_0_OPCODE_X0 = 51, + OR_SPECIAL_0_OPCODE_X1 = 25, + OR_SPECIAL_2_OPCODE_Y0 = 2, + OR_SPECIAL_2_OPCODE_Y1 = 2, + PACKBS_U_SPECIAL_0_OPCODE_X0 = 103, + PACKBS_U_SPECIAL_0_OPCODE_X1 = 73, + PACKHB_SPECIAL_0_OPCODE_X0 = 52, + PACKHB_SPECIAL_0_OPCODE_X1 = 26, + PACKHS_SPECIAL_0_OPCODE_X0 = 102, + PACKHS_SPECIAL_0_OPCODE_X1 = 72, + PACKLB_SPECIAL_0_OPCODE_X0 = 53, + PACKLB_SPECIAL_0_OPCODE_X1 = 27, + PCNT_UN_0_SHUN_0_OPCODE_X0 = 7, + PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7, + RLI_SHUN_0_OPCODE_X0 = 1, + RLI_SHUN_0_OPCODE_X1 = 1, + RLI_SHUN_0_OPCODE_Y0 = 1, + RLI_SHUN_0_OPCODE_Y1 = 1, + RL_SPECIAL_0_OPCODE_X0 = 54, + RL_SPECIAL_0_OPCODE_X1 = 28, + RL_SPECIAL_3_OPCODE_Y0 = 0, + RL_SPECIAL_3_OPCODE_Y1 = 0, + RR_IMM_0_OPCODE_SN = 0, + S1A_SPECIAL_0_OPCODE_X0 = 55, + S1A_SPECIAL_0_OPCODE_X1 = 29, + S1A_SPECIAL_0_OPCODE_Y0 = 1, + S1A_SPECIAL_0_OPCODE_Y1 = 1, + S2A_SPECIAL_0_OPCODE_X0 = 56, + S2A_SPECIAL_0_OPCODE_X1 = 30, + S2A_SPECIAL_0_OPCODE_Y0 = 2, + S2A_SPECIAL_0_OPCODE_Y1 = 2, + S3A_SPECIAL_0_OPCODE_X0 = 57, + S3A_SPECIAL_0_OPCODE_X1 = 31, + S3A_SPECIAL_5_OPCODE_Y0 = 1, + S3A_SPECIAL_5_OPCODE_Y1 = 1, + SADAB_U_SPECIAL_0_OPCODE_X0 = 58, + SADAH_SPECIAL_0_OPCODE_X0 = 59, + SADAH_U_SPECIAL_0_OPCODE_X0 = 60, + SADB_U_SPECIAL_0_OPCODE_X0 = 61, + SADH_SPECIAL_0_OPCODE_X0 = 62, + SADH_U_SPECIAL_0_OPCODE_X0 = 63, + SBADD_IMM_0_OPCODE_X1 = 28, + SB_OPCODE_Y2 = 5, + SB_SPECIAL_0_OPCODE_X1 = 32, + SEQB_SPECIAL_0_OPCODE_X0 = 64, + SEQB_SPECIAL_0_OPCODE_X1 = 33, + SEQH_SPECIAL_0_OPCODE_X0 = 65, + SEQH_SPECIAL_0_OPCODE_X1 = 34, + SEQIB_IMM_0_OPCODE_X0 = 9, + SEQIB_IMM_0_OPCODE_X1 = 12, + SEQIH_IMM_0_OPCODE_X0 = 10, + SEQIH_IMM_0_OPCODE_X1 = 13, + SEQI_IMM_0_OPCODE_X0 = 11, + SEQI_IMM_0_OPCODE_X1 = 14, + SEQI_OPCODE_Y0 = 12, + SEQI_OPCODE_Y1 = 10, + SEQ_SPECIAL_0_OPCODE_X0 = 66, + SEQ_SPECIAL_0_OPCODE_X1 = 35, + SEQ_SPECIAL_5_OPCODE_Y0 = 2, + SEQ_SPECIAL_5_OPCODE_Y1 = 2, + SHADD_IMM_0_OPCODE_X1 = 29, + SHL8II_IMM_0_OPCODE_SN = 3, + SHLB_SPECIAL_0_OPCODE_X0 = 67, + SHLB_SPECIAL_0_OPCODE_X1 = 36, + SHLH_SPECIAL_0_OPCODE_X0 = 68, + SHLH_SPECIAL_0_OPCODE_X1 = 37, + SHLIB_SHUN_0_OPCODE_X0 = 2, + SHLIB_SHUN_0_OPCODE_X1 = 2, + SHLIH_SHUN_0_OPCODE_X0 = 3, + SHLIH_SHUN_0_OPCODE_X1 = 3, + SHLI_SHUN_0_OPCODE_X0 = 4, + SHLI_SHUN_0_OPCODE_X1 = 4, + SHLI_SHUN_0_OPCODE_Y0 = 2, + SHLI_SHUN_0_OPCODE_Y1 = 2, + SHL_SPECIAL_0_OPCODE_X0 = 69, + SHL_SPECIAL_0_OPCODE_X1 = 38, + SHL_SPECIAL_3_OPCODE_Y0 = 1, + SHL_SPECIAL_3_OPCODE_Y1 = 1, + SHR1_RR_IMM_0_OPCODE_SN = 9, + SHRB_SPECIAL_0_OPCODE_X0 = 70, + SHRB_SPECIAL_0_OPCODE_X1 = 39, + SHRH_SPECIAL_0_OPCODE_X0 = 71, + SHRH_SPECIAL_0_OPCODE_X1 = 40, + SHRIB_SHUN_0_OPCODE_X0 = 5, + SHRIB_SHUN_0_OPCODE_X1 = 5, + SHRIH_SHUN_0_OPCODE_X0 = 6, + SHRIH_SHUN_0_OPCODE_X1 = 6, + SHRI_SHUN_0_OPCODE_X0 = 7, + SHRI_SHUN_0_OPCODE_X1 = 7, + SHRI_SHUN_0_OPCODE_Y0 = 3, + SHRI_SHUN_0_OPCODE_Y1 = 3, + SHR_SPECIAL_0_OPCODE_X0 = 72, + SHR_SPECIAL_0_OPCODE_X1 = 41, + SHR_SPECIAL_3_OPCODE_Y0 = 2, + SHR_SPECIAL_3_OPCODE_Y1 = 2, + SHUN_0_OPCODE_X0 = 7, + SHUN_0_OPCODE_X1 = 8, + SHUN_0_OPCODE_Y0 = 13, + SHUN_0_OPCODE_Y1 = 11, + SH_OPCODE_Y2 = 6, + SH_SPECIAL_0_OPCODE_X1 = 42, + SLTB_SPECIAL_0_OPCODE_X0 = 73, + SLTB_SPECIAL_0_OPCODE_X1 = 43, + SLTB_U_SPECIAL_0_OPCODE_X0 = 74, + SLTB_U_SPECIAL_0_OPCODE_X1 = 44, + SLTEB_SPECIAL_0_OPCODE_X0 = 75, + SLTEB_SPECIAL_0_OPCODE_X1 = 45, + SLTEB_U_SPECIAL_0_OPCODE_X0 = 76, + SLTEB_U_SPECIAL_0_OPCODE_X1 = 46, + SLTEH_SPECIAL_0_OPCODE_X0 = 77, + SLTEH_SPECIAL_0_OPCODE_X1 = 47, + SLTEH_U_SPECIAL_0_OPCODE_X0 = 78, + SLTEH_U_SPECIAL_0_OPCODE_X1 = 48, + SLTE_SPECIAL_0_OPCODE_X0 = 79, + SLTE_SPECIAL_0_OPCODE_X1 = 49, + SLTE_SPECIAL_4_OPCODE_Y0 = 0, + SLTE_SPECIAL_4_OPCODE_Y1 = 0, + SLTE_U_SPECIAL_0_OPCODE_X0 = 80, + SLTE_U_SPECIAL_0_OPCODE_X1 = 50, + SLTE_U_SPECIAL_4_OPCODE_Y0 = 1, + SLTE_U_SPECIAL_4_OPCODE_Y1 = 1, + SLTH_SPECIAL_0_OPCODE_X0 = 81, + SLTH_SPECIAL_0_OPCODE_X1 = 51, + SLTH_U_SPECIAL_0_OPCODE_X0 = 82, + SLTH_U_SPECIAL_0_OPCODE_X1 = 52, + SLTIB_IMM_0_OPCODE_X0 = 12, + SLTIB_IMM_0_OPCODE_X1 = 15, + SLTIB_U_IMM_0_OPCODE_X0 = 13, + SLTIB_U_IMM_0_OPCODE_X1 = 16, + SLTIH_IMM_0_OPCODE_X0 = 14, + SLTIH_IMM_0_OPCODE_X1 = 17, + SLTIH_U_IMM_0_OPCODE_X0 = 15, + SLTIH_U_IMM_0_OPCODE_X1 = 18, + SLTI_IMM_0_OPCODE_X0 = 16, + SLTI_IMM_0_OPCODE_X1 = 19, + SLTI_OPCODE_Y0 = 14, + SLTI_OPCODE_Y1 = 12, + SLTI_U_IMM_0_OPCODE_X0 = 17, + SLTI_U_IMM_0_OPCODE_X1 = 20, + SLTI_U_OPCODE_Y0 = 15, + SLTI_U_OPCODE_Y1 = 13, + SLT_SPECIAL_0_OPCODE_X0 = 83, + SLT_SPECIAL_0_OPCODE_X1 = 53, + SLT_SPECIAL_4_OPCODE_Y0 = 2, + SLT_SPECIAL_4_OPCODE_Y1 = 2, + SLT_U_SPECIAL_0_OPCODE_X0 = 84, + SLT_U_SPECIAL_0_OPCODE_X1 = 54, + SLT_U_SPECIAL_4_OPCODE_Y0 = 3, + SLT_U_SPECIAL_4_OPCODE_Y1 = 3, + SNEB_SPECIAL_0_OPCODE_X0 = 85, + SNEB_SPECIAL_0_OPCODE_X1 = 55, + SNEH_SPECIAL_0_OPCODE_X0 = 86, + SNEH_SPECIAL_0_OPCODE_X1 = 56, + SNE_SPECIAL_0_OPCODE_X0 = 87, + SNE_SPECIAL_0_OPCODE_X1 = 57, + SNE_SPECIAL_5_OPCODE_Y0 = 3, + SNE_SPECIAL_5_OPCODE_Y1 = 3, + SPECIAL_0_OPCODE_X0 = 0, + SPECIAL_0_OPCODE_X1 = 1, + SPECIAL_0_OPCODE_Y0 = 1, + SPECIAL_0_OPCODE_Y1 = 1, + SPECIAL_1_OPCODE_Y0 = 2, + SPECIAL_1_OPCODE_Y1 = 2, + SPECIAL_2_OPCODE_Y0 = 3, + SPECIAL_2_OPCODE_Y1 = 3, + SPECIAL_3_OPCODE_Y0 = 4, + SPECIAL_3_OPCODE_Y1 = 4, + SPECIAL_4_OPCODE_Y0 = 5, + SPECIAL_4_OPCODE_Y1 = 5, + SPECIAL_5_OPCODE_Y0 = 6, + SPECIAL_5_OPCODE_Y1 = 6, + SPECIAL_6_OPCODE_Y0 = 7, + SPECIAL_7_OPCODE_Y0 = 8, + SRAB_SPECIAL_0_OPCODE_X0 = 88, + SRAB_SPECIAL_0_OPCODE_X1 = 58, + SRAH_SPECIAL_0_OPCODE_X0 = 89, + SRAH_SPECIAL_0_OPCODE_X1 = 59, + SRAIB_SHUN_0_OPCODE_X0 = 8, + SRAIB_SHUN_0_OPCODE_X1 = 8, + SRAIH_SHUN_0_OPCODE_X0 = 9, + SRAIH_SHUN_0_OPCODE_X1 = 9, + SRAI_SHUN_0_OPCODE_X0 = 10, + SRAI_SHUN_0_OPCODE_X1 = 10, + SRAI_SHUN_0_OPCODE_Y0 = 4, + SRAI_SHUN_0_OPCODE_Y1 = 4, + SRA_SPECIAL_0_OPCODE_X0 = 90, + SRA_SPECIAL_0_OPCODE_X1 = 60, + SRA_SPECIAL_3_OPCODE_Y0 = 3, + SRA_SPECIAL_3_OPCODE_Y1 = 3, + SUBBS_U_SPECIAL_0_OPCODE_X0 = 100, + SUBBS_U_SPECIAL_0_OPCODE_X1 = 70, + SUBB_SPECIAL_0_OPCODE_X0 = 91, + SUBB_SPECIAL_0_OPCODE_X1 = 61, + SUBHS_SPECIAL_0_OPCODE_X0 = 101, + SUBHS_SPECIAL_0_OPCODE_X1 = 71, + SUBH_SPECIAL_0_OPCODE_X0 = 92, + SUBH_SPECIAL_0_OPCODE_X1 = 62, + SUBS_SPECIAL_0_OPCODE_X0 = 97, + SUBS_SPECIAL_0_OPCODE_X1 = 67, + SUB_SPECIAL_0_OPCODE_X0 = 93, + SUB_SPECIAL_0_OPCODE_X1 = 63, + SUB_SPECIAL_0_OPCODE_Y0 = 3, + SUB_SPECIAL_0_OPCODE_Y1 = 3, + SWADD_IMM_0_OPCODE_X1 = 30, + SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18, + SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19, + SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20, + SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21, + SW_OPCODE_Y2 = 7, + SW_SPECIAL_0_OPCODE_X1 = 64, + TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8, + TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8, + TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9, + TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9, + TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10, + TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10, + TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11, + TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11, + TNS_UN_0_SHUN_0_OPCODE_X1 = 22, + UN_0_SHUN_0_OPCODE_X0 = 11, + UN_0_SHUN_0_OPCODE_X1 = 11, + UN_0_SHUN_0_OPCODE_Y0 = 5, + UN_0_SHUN_0_OPCODE_Y1 = 5, + WH64_UN_0_SHUN_0_OPCODE_X1 = 23, + XORI_IMM_0_OPCODE_X0 = 2, + XORI_IMM_0_OPCODE_X1 = 21, + XOR_SPECIAL_0_OPCODE_X0 = 94, + XOR_SPECIAL_0_OPCODE_X1 = 65, + XOR_SPECIAL_2_OPCODE_Y0 = 3, + XOR_SPECIAL_2_OPCODE_Y1 = 3 +}; + +#endif /* !_TILE_OPCODE_CONSTANTS_H */ diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h new file mode 100644 index 000000000000..c8301c43d6d9 --- /dev/null +++ b/arch/tile/include/asm/page.h @@ -0,0 +1,334 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PAGE_H +#define _ASM_TILE_PAGE_H + +#include +#include +#include + +/* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ +#define PAGE_SHIFT 16 +#define HPAGE_SHIFT 24 + +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) +#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) + +#define PAGE_MASK (~(PAGE_SIZE - 1)) +#define HPAGE_MASK (~(HPAGE_SIZE - 1)) + +/* + * The {,H}PAGE_SHIFT values must match the HV_LOG2_PAGE_SIZE_xxx + * definitions in . We validate this at build time + * here, and again at runtime during early boot. We provide a + * separate definition since userspace doesn't have . + * + * Be careful to distinguish PAGE_SHIFT from HV_PTE_INDEX_PFN, since + * they are the same on i386 but not TILE. + */ +#if HV_LOG2_PAGE_SIZE_SMALL != PAGE_SHIFT +# error Small page size mismatch in Linux +#endif +#if HV_LOG2_PAGE_SIZE_LARGE != HPAGE_SHIFT +# error Huge page size mismatch in Linux +#endif + +#ifndef __ASSEMBLY__ + +#include +#include + +struct page; + +static inline void clear_page(void *page) +{ + memset(page, 0, PAGE_SIZE); +} + +static inline void copy_page(void *to, void *from) +{ + memcpy(to, from, PAGE_SIZE); +} + +static inline void clear_user_page(void *page, unsigned long vaddr, + struct page *pg) +{ + clear_page(page); +} + +static inline void copy_user_page(void *to, void *from, unsigned long vaddr, + struct page *topage) +{ + copy_page(to, from); +} + +/* + * Hypervisor page tables are made of the same basic structure. + */ + +typedef __u64 pteval_t; +typedef __u64 pmdval_t; +typedef __u64 pudval_t; +typedef __u64 pgdval_t; +typedef __u64 pgprotval_t; + +typedef HV_PTE pte_t; +typedef HV_PTE pgd_t; +typedef HV_PTE pgprot_t; + +/* + * User L2 page tables are managed as one L2 page table per page, + * because we use the page allocator for them. This keeps the allocation + * simple and makes it potentially useful to implement HIGHPTE at some point. + * However, it's also inefficient, since L2 page tables are much smaller + * than pages (currently 2KB vs 64KB). So we should revisit this. + */ +typedef struct page *pgtable_t; + +/* Must be a macro since it is used to create constants. */ +#define __pgprot(val) hv_pte(val) + +static inline u64 pgprot_val(pgprot_t pgprot) +{ + return hv_pte_val(pgprot); +} + +static inline u64 pte_val(pte_t pte) +{ + return hv_pte_val(pte); +} + +static inline u64 pgd_val(pgd_t pgd) +{ + return hv_pte_val(pgd); +} + +#ifdef __tilegx__ + +typedef HV_PTE pmd_t; + +static inline u64 pmd_val(pmd_t pmd) +{ + return hv_pte_val(pmd); +} + +#endif + +#endif /* !__ASSEMBLY__ */ + +#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) + +#define HUGE_MAX_HSTATE 2 + +#ifdef CONFIG_HUGETLB_PAGE +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +#endif + +/* Each memory controller has PAs distinct in their high bits. */ +#define NR_PA_HIGHBIT_SHIFT (CHIP_PA_WIDTH() - CHIP_LOG_NUM_MSHIMS()) +#define NR_PA_HIGHBIT_VALUES (1 << CHIP_LOG_NUM_MSHIMS()) +#define __pa_to_highbits(pa) ((phys_addr_t)(pa) >> NR_PA_HIGHBIT_SHIFT) +#define __pfn_to_highbits(pfn) ((pfn) >> (NR_PA_HIGHBIT_SHIFT - PAGE_SHIFT)) + +#ifdef __tilegx__ + +/* + * We reserve the lower half of memory for user-space programs, and the + * upper half for system code. We re-map all of physical memory in the + * upper half, which takes a quarter of our VA space. Then we have + * the vmalloc regions. The supervisor code lives at 0xfffffff700000000, + * with the hypervisor above that. + * + * Loadable kernel modules are placed immediately after the static + * supervisor code, with each being allocated a 256MB region of + * address space, so we don't have to worry about the range of "jal" + * and other branch instructions. + * + * For now we keep life simple and just allocate one pmd (4GB) for vmalloc. + * Similarly, for now we don't play any struct page mapping games. + */ + +#if CHIP_PA_WIDTH() + 2 > CHIP_VA_WIDTH() +# error Too much PA to map with the VA available! +#endif +#define HALF_VA_SPACE (_AC(1, UL) << (CHIP_VA_WIDTH() - 1)) + +#define MEM_LOW_END (HALF_VA_SPACE - 1) /* low half */ +#define MEM_HIGH_START (-HALF_VA_SPACE) /* high half */ +#define PAGE_OFFSET MEM_HIGH_START +#define _VMALLOC_START _AC(0xfffffff500000000, UL) /* 4 GB */ +#define HUGE_VMAP_BASE _AC(0xfffffff600000000, UL) /* 4 GB */ +#define MEM_SV_START _AC(0xfffffff700000000, UL) /* 256 MB */ +#define MEM_SV_INTRPT MEM_SV_START +#define MEM_MODULE_START _AC(0xfffffff710000000, UL) /* 256 MB */ +#define MEM_MODULE_END (MEM_MODULE_START + (256*1024*1024)) +#define MEM_HV_START _AC(0xfffffff800000000, UL) /* 32 GB */ + +/* Highest DTLB address we will use */ +#define KERNEL_HIGH_VADDR MEM_SV_START + +/* Since we don't currently provide any fixmaps, we use an impossible VA. */ +#define FIXADDR_TOP MEM_HV_START + +#else /* !__tilegx__ */ + +/* + * A PAGE_OFFSET of 0xC0000000 means that the kernel has + * a virtual address space of one gigabyte, which limits the + * amount of physical memory you can use to about 768MB. + * If you want more physical memory than this then see the CONFIG_HIGHMEM + * option in the kernel configuration. + * + * The top two 16MB chunks in the table below (VIRT and HV) are + * unavailable to Linux. Since the kernel interrupt vectors must live + * at 0xfd000000, we map all of the bottom of RAM at this address with + * a huge page table entry to minimize its ITLB footprint (as well as + * at PAGE_OFFSET). The last architected requirement is that user + * interrupt vectors live at 0xfc000000, so we make that range of + * memory available to user processes. The remaining regions are sized + * as shown; after the first four addresses, we show "typical" values, + * since the actual addresses depend on kernel #defines. + * + * MEM_VIRT_INTRPT 0xff000000 + * MEM_HV_INTRPT 0xfe000000 + * MEM_SV_INTRPT (kernel code) 0xfd000000 + * MEM_USER_INTRPT (user vector) 0xfc000000 + * FIX_KMAP_xxx 0xf8000000 (via NR_CPUS * KM_TYPE_NR) + * PKMAP_BASE 0xf7000000 (via LAST_PKMAP) + * HUGE_VMAP 0xf3000000 (via CONFIG_NR_HUGE_VMAPS) + * VMALLOC_START 0xf0000000 (via __VMALLOC_RESERVE) + * mapped LOWMEM 0xc0000000 + */ + +#define MEM_USER_INTRPT _AC(0xfc000000, UL) +#define MEM_SV_INTRPT _AC(0xfd000000, UL) +#define MEM_HV_INTRPT _AC(0xfe000000, UL) +#define MEM_VIRT_INTRPT _AC(0xff000000, UL) + +#define INTRPT_SIZE 0x4000 + +/* Tolerate page size larger than the architecture interrupt region size. */ +#if PAGE_SIZE > INTRPT_SIZE +#undef INTRPT_SIZE +#define INTRPT_SIZE PAGE_SIZE +#endif + +#define KERNEL_HIGH_VADDR MEM_USER_INTRPT +#define FIXADDR_TOP (KERNEL_HIGH_VADDR - PAGE_SIZE) + +#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) + +/* On 32-bit architectures we mix kernel modules in with other vmaps. */ +#define MEM_MODULE_START VMALLOC_START +#define MEM_MODULE_END VMALLOC_END + +#endif /* __tilegx__ */ + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_HIGHMEM + +/* Map kernel virtual addresses to page frames, in HPAGE_SIZE chunks. */ +extern unsigned long pbase_map[]; +extern void *vbase_map[]; + +static inline unsigned long kaddr_to_pfn(const volatile void *_kaddr) +{ + unsigned long kaddr = (unsigned long)_kaddr; + return pbase_map[kaddr >> HPAGE_SHIFT] + + ((kaddr & (HPAGE_SIZE - 1)) >> PAGE_SHIFT); +} + +static inline void *pfn_to_kaddr(unsigned long pfn) +{ + return vbase_map[__pfn_to_highbits(pfn)] + (pfn << PAGE_SHIFT); +} + +static inline phys_addr_t virt_to_phys(const volatile void *kaddr) +{ + unsigned long pfn = kaddr_to_pfn(kaddr); + return ((phys_addr_t)pfn << PAGE_SHIFT) + + ((unsigned long)kaddr & (PAGE_SIZE-1)); +} + +static inline void *phys_to_virt(phys_addr_t paddr) +{ + return pfn_to_kaddr(paddr >> PAGE_SHIFT) + (paddr & (PAGE_SIZE-1)); +} + +/* With HIGHMEM, we pack PAGE_OFFSET through high_memory with all valid VAs. */ +static inline int virt_addr_valid(const volatile void *kaddr) +{ + extern void *high_memory; /* copied from */ + return ((unsigned long)kaddr >= PAGE_OFFSET && kaddr < high_memory); +} + +#else /* !CONFIG_HIGHMEM */ + +static inline unsigned long kaddr_to_pfn(const volatile void *kaddr) +{ + return ((unsigned long)kaddr - PAGE_OFFSET) >> PAGE_SHIFT; +} + +static inline void *pfn_to_kaddr(unsigned long pfn) +{ + return (void *)((pfn << PAGE_SHIFT) + PAGE_OFFSET); +} + +static inline phys_addr_t virt_to_phys(const volatile void *kaddr) +{ + return (phys_addr_t)((unsigned long)kaddr - PAGE_OFFSET); +} + +static inline void *phys_to_virt(phys_addr_t paddr) +{ + return (void *)((unsigned long)paddr + PAGE_OFFSET); +} + +/* Check that the given address is within some mapped range of PAs. */ +#define virt_addr_valid(kaddr) pfn_valid(kaddr_to_pfn(kaddr)) + +#endif /* !CONFIG_HIGHMEM */ + +/* All callers are not consistent in how they call these functions. */ +#define __pa(kaddr) virt_to_phys((void *)(unsigned long)(kaddr)) +#define __va(paddr) phys_to_virt((phys_addr_t)(paddr)) + +extern int devmem_is_allowed(unsigned long pagenr); + +#ifdef CONFIG_FLATMEM +static inline int pfn_valid(unsigned long pfn) +{ + return pfn < max_mapnr; +} +#endif + +/* Provide as macros since these require some other headers included. */ +#define page_to_pa(page) ((phys_addr_t)(page_to_pfn(page)) << PAGE_SHIFT) +#define virt_to_page(kaddr) pfn_to_page(kaddr_to_pfn(kaddr)) +#define page_to_virt(page) pfn_to_kaddr(page_to_pfn(page)) + +struct mm_struct; +extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); + +#endif /* !__ASSEMBLY__ */ + +#define VM_DATA_DEFAULT_FLAGS \ + (VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#include +#include + +#endif /* _ASM_TILE_PAGE_H */ diff --git a/arch/tile/include/asm/param.h b/arch/tile/include/asm/param.h new file mode 100644 index 000000000000..965d45427975 --- /dev/null +++ b/arch/tile/include/asm/param.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/pci-bridge.h b/arch/tile/include/asm/pci-bridge.h new file mode 100644 index 000000000000..e853b0e2793b --- /dev/null +++ b/arch/tile/include/asm/pci-bridge.h @@ -0,0 +1,117 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PCI_BRIDGE_H +#define _ASM_TILE_PCI_BRIDGE_H + +#include +#include + +struct device_node; +struct pci_controller; + +/* + * pci_io_base returns the memory address at which you can access + * the I/O space for PCI bus number `bus' (or NULL on error). + */ +extern void __iomem *pci_bus_io_base(unsigned int bus); +extern unsigned long pci_bus_io_base_phys(unsigned int bus); +extern unsigned long pci_bus_mem_base_phys(unsigned int bus); + +/* Allocate a new PCI host bridge structure */ +extern struct pci_controller *pcibios_alloc_controller(void); + +/* Helper function for setting up resources */ +extern void pci_init_resource(struct resource *res, unsigned long start, + unsigned long end, int flags, char *name); + +/* Get the PCI host controller for a bus */ +extern struct pci_controller *pci_bus_to_hose(int bus); + +/* + * Structure of a PCI controller (host bridge) + */ +struct pci_controller { + int index; /* PCI domain number */ + struct pci_bus *root_bus; + + int first_busno; + int last_busno; + + int hv_cfg_fd[2]; /* config{0,1} fds for this PCIe controller */ + int hv_mem_fd; /* fd to Hypervisor for MMIO operations */ + + struct pci_ops *ops; + + int irq_base; /* Base IRQ from the Hypervisor */ + int plx_gen1; /* flag for PLX Gen 1 configuration */ + + /* Address ranges that are routed to this controller/bridge. */ + struct resource mem_resources[3]; +}; + +static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) +{ + return bus->sysdata; +} + +extern void setup_indirect_pci_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, void __iomem *cfg_data); +extern void setup_indirect_pci(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void setup_grackle(struct pci_controller *hose); + +extern unsigned char common_swizzle(struct pci_dev *, unsigned char *); + +/* + * The following code swizzles for exactly one bridge. The routine + * common_swizzle below handles multiple bridges. But there are a + * some boards that don't follow the PCI spec's suggestion so we + * break this piece out separately. + */ +static inline unsigned char bridge_swizzle(unsigned char pin, + unsigned char idsel) +{ + return (((pin-1) + idsel) % 4) + 1; +} + +/* + * The following macro is used to lookup irqs in a standard table + * format for those PPC systems that do not already have PCI + * interrupts properly routed. + */ +/* FIXME - double check this */ +#define PCI_IRQ_TABLE_LOOKUP ({ \ + long _ctl_ = -1; \ + if (idsel >= min_idsel && idsel <= max_idsel && pin <= irqs_per_slot) \ + _ctl_ = pci_irq_table[idsel - min_idsel][pin-1]; \ + _ctl_; \ +}) + +/* + * Scan the buses below a given PCI host bridge and assign suitable + * resources to all devices found. + */ +extern int pciauto_bus_scan(struct pci_controller *, int); + +#ifdef CONFIG_PCI +extern unsigned long pci_address_to_pio(phys_addr_t address); +#else +static inline unsigned long pci_address_to_pio(phys_addr_t address) +{ + return (unsigned long)-1; +} +#endif + +#endif /* _ASM_TILE_PCI_BRIDGE_H */ diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h new file mode 100644 index 000000000000..b0c15da2d5d5 --- /dev/null +++ b/arch/tile/include/asm/pci.h @@ -0,0 +1,128 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PCI_H +#define _ASM_TILE_PCI_H + +#include + +/* + * The hypervisor maps the entirety of CPA-space as bus addresses, so + * bus addresses are physical addresses. The networking and block + * device layers use this boolean for bounce buffer decisions. + */ +#define PCI_DMA_BUS_IS_PHYS 1 + +struct pci_controller *pci_bus_to_hose(int bus); +unsigned char __init common_swizzle(struct pci_dev *dev, unsigned char *pinp); +int __init tile_pci_init(void); +void pci_iounmap(struct pci_dev *dev, void __iomem *addr); +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +void __devinit pcibios_fixup_bus(struct pci_bus *bus); + +int __devinit _tile_cfg_read(struct pci_controller *hose, + int bus, + int slot, + int function, + int offset, + int size, + u32 *val); +int __devinit _tile_cfg_write(struct pci_controller *hose, + int bus, + int slot, + int function, + int offset, + int size, + u32 val); + +/* + * These are used to to config reads and writes in the early stages of + * setup before the driver infrastructure has been set up enough to be + * able to do config reads and writes. + */ +#define early_cfg_read(where, size, value) \ + _tile_cfg_read(controller, \ + current_bus, \ + pci_slot, \ + pci_fn, \ + where, \ + size, \ + value) + +#define early_cfg_write(where, size, value) \ + _tile_cfg_write(controller, \ + current_bus, \ + pci_slot, \ + pci_fn, \ + where, \ + size, \ + value) + + + +#define PCICFG_BYTE 1 +#define PCICFG_WORD 2 +#define PCICFG_DWORD 4 + +#define TILE_NUM_PCIE 2 + +#define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index) + +/* + * This decides whether to display the domain number in /proc. + */ +static inline int pci_proc_domain(struct pci_bus *bus) +{ + return 1; +} + +/* + * I/O space is currently not supported. + */ + +#define TILE_PCIE_LOWER_IO 0x0 +#define TILE_PCIE_UPPER_IO 0x10000 +#define TILE_PCIE_PCIE_IO_SIZE 0x0000FFFF + +#define _PAGE_NO_CACHE 0 +#define _PAGE_GUARDED 0 + + +#define pcibios_assign_all_busses() pci_assign_all_buses +extern int pci_assign_all_buses; + +static inline void pcibios_set_master(struct pci_dev *dev) +{ + /* No special bus mastering setup handling */ +} + +#define PCIBIOS_MIN_MEM 0 +#define PCIBIOS_MIN_IO TILE_PCIE_LOWER_IO + +/* + * This flag tells if the platform is TILEmpower that needs + * special configuration for the PLX switch chip. + */ +extern int blade_pci; + +/* implement the pci_ DMA API in terms of the generic device dma_ one */ +#include + +/* generic pci stuff */ +#include + +/* Use any cpu for PCI. */ +#define cpumask_of_pcibus(bus) cpu_online_mask + +#endif /* _ASM_TILE_PCI_H */ diff --git a/arch/tile/include/asm/percpu.h b/arch/tile/include/asm/percpu.h new file mode 100644 index 000000000000..63294f5a8efb --- /dev/null +++ b/arch/tile/include/asm/percpu.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PERCPU_H +#define _ASM_TILE_PERCPU_H + +register unsigned long __my_cpu_offset __asm__("tp"); +#define __my_cpu_offset __my_cpu_offset +#define set_my_cpu_offset(tp) (__my_cpu_offset = (tp)) + +#include + +#endif /* _ASM_TILE_PERCPU_H */ diff --git a/arch/tile/include/asm/pgalloc.h b/arch/tile/include/asm/pgalloc.h new file mode 100644 index 000000000000..cf52791a5501 --- /dev/null +++ b/arch/tile/include/asm/pgalloc.h @@ -0,0 +1,119 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PGALLOC_H +#define _ASM_TILE_PGALLOC_H + +#include +#include +#include +#include +#include + +/* Bits for the size of the second-level page table. */ +#define L2_KERNEL_PGTABLE_SHIFT \ + (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL + HV_LOG2_PTE_SIZE) + +/* We currently allocate user L2 page tables by page (unlike kernel L2s). */ +#if L2_KERNEL_PGTABLE_SHIFT < HV_LOG2_PAGE_SIZE_SMALL +#define L2_USER_PGTABLE_SHIFT HV_LOG2_PAGE_SIZE_SMALL +#else +#define L2_USER_PGTABLE_SHIFT L2_KERNEL_PGTABLE_SHIFT +#endif + +/* How many pages do we need, as an "order", for a user L2 page table? */ +#define L2_USER_PGTABLE_ORDER (L2_USER_PGTABLE_SHIFT - HV_LOG2_PAGE_SIZE_SMALL) + +/* How big is a kernel L2 page table? */ +#define L2_KERNEL_PGTABLE_SIZE (1 << L2_KERNEL_PGTABLE_SHIFT) + +static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) +{ +#ifdef CONFIG_64BIT + set_pte_order(pmdp, pmd, L2_USER_PGTABLE_ORDER); +#else + set_pte_order(&pmdp->pud.pgd, pmd.pud.pgd, L2_USER_PGTABLE_ORDER); +#endif +} + +static inline void pmd_populate_kernel(struct mm_struct *mm, + pmd_t *pmd, pte_t *ptep) +{ + set_pmd(pmd, ptfn_pmd(__pa(ptep) >> HV_LOG2_PAGE_TABLE_ALIGN, + __pgprot(_PAGE_PRESENT))); +} + +static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, + pgtable_t page) +{ + set_pmd(pmd, ptfn_pmd(HV_PFN_TO_PTFN(page_to_pfn(page)), + __pgprot(_PAGE_PRESENT))); +} + +/* + * Allocate and free page tables. + */ + +extern pgd_t *pgd_alloc(struct mm_struct *mm); +extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); + +extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address); +extern void pte_free(struct mm_struct *mm, struct page *pte); + +#define pmd_pgtable(pmd) pmd_page(pmd) + +static inline pte_t * +pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +{ + return pfn_to_kaddr(page_to_pfn(pte_alloc_one(mm, address))); +} + +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + BUG_ON((unsigned long)pte & (PAGE_SIZE-1)); + pte_free(mm, virt_to_page(pte)); +} + +extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, + unsigned long address); + +#define check_pgt_cache() do { } while (0) + +/* + * Get the small-page pte_t lowmem entry for a given pfn. + * This may or may not be in use, depending on whether the initial + * huge-page entry for the page has already been shattered. + */ +pte_t *get_prealloc_pte(unsigned long pfn); + +/* During init, we can shatter kernel huge pages if needed. */ +void shatter_pmd(pmd_t *pmd); + +#ifdef __tilegx__ +/* We share a single page allocator for both L1 and L2 page tables. */ +#if HV_L1_SIZE != HV_L2_SIZE +# error Rework assumption that L1 and L2 page tables are same size. +#endif +#define L1_USER_PGTABLE_ORDER L2_USER_PGTABLE_ORDER +#define pud_populate(mm, pud, pmd) \ + pmd_populate_kernel((mm), (pmd_t *)(pud), (pte_t *)(pmd)) +#define pmd_alloc_one(mm, addr) \ + ((pmd_t *)page_to_virt(pte_alloc_one((mm), (addr)))) +#define pmd_free(mm, pmdp) \ + pte_free((mm), virt_to_page(pmdp)) +#define __pmd_free_tlb(tlb, pmdp, address) \ + __pte_free_tlb((tlb), virt_to_page(pmdp), (address)) +#endif + +#endif /* _ASM_TILE_PGALLOC_H */ diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h new file mode 100644 index 000000000000..beb1504e9c10 --- /dev/null +++ b/arch/tile/include/asm/pgtable.h @@ -0,0 +1,475 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This file contains the functions and defines necessary to modify and use + * the TILE page table tree. + */ + +#ifndef _ASM_TILE_PGTABLE_H +#define _ASM_TILE_PGTABLE_H + +#include + +#ifndef __ASSEMBLY__ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct mm_struct; +struct vm_area_struct; + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + +extern pgd_t swapper_pg_dir[]; +extern pgprot_t swapper_pgprot; +extern struct kmem_cache *pgd_cache; +extern spinlock_t pgd_lock; +extern struct list_head pgd_list; + +/* + * The very last slots in the pgd_t are for addresses unusable by Linux + * (pgd_addr_invalid() returns true). So we use them for the list structure. + * The x86 code we are modelled on uses the page->private/index fields + * (older 2.6 kernels) or the lru list (newer 2.6 kernels), but since + * our pgds are so much smaller than a page, it seems a waste to + * spend a whole page on each pgd. + */ +#define PGD_LIST_OFFSET \ + ((PTRS_PER_PGD * sizeof(pgd_t)) - sizeof(struct list_head)) +#define pgd_to_list(pgd) \ + ((struct list_head *)((char *)(pgd) + PGD_LIST_OFFSET)) +#define list_to_pgd(list) \ + ((pgd_t *)((char *)(list) - PGD_LIST_OFFSET)) + +extern void pgtable_cache_init(void); +extern void paging_init(void); +extern void set_page_homes(void); + +#define FIRST_USER_ADDRESS 0 + +#define _PAGE_PRESENT HV_PTE_PRESENT +#define _PAGE_HUGE_PAGE HV_PTE_PAGE +#define _PAGE_READABLE HV_PTE_READABLE +#define _PAGE_WRITABLE HV_PTE_WRITABLE +#define _PAGE_EXECUTABLE HV_PTE_EXECUTABLE +#define _PAGE_ACCESSED HV_PTE_ACCESSED +#define _PAGE_DIRTY HV_PTE_DIRTY +#define _PAGE_GLOBAL HV_PTE_GLOBAL +#define _PAGE_USER HV_PTE_USER + +/* + * All the "standard" bits. Cache-control bits are managed elsewhere. + * This is used to test for valid level-2 page table pointers by checking + * all the bits, and to mask away the cache control bits for mprotect. + */ +#define _PAGE_ALL (\ + _PAGE_PRESENT | \ + _PAGE_HUGE_PAGE | \ + _PAGE_READABLE | \ + _PAGE_WRITABLE | \ + _PAGE_EXECUTABLE | \ + _PAGE_ACCESSED | \ + _PAGE_DIRTY | \ + _PAGE_GLOBAL | \ + _PAGE_USER \ +) + +#define PAGE_NONE \ + __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define PAGE_SHARED \ + __pgprot(_PAGE_PRESENT | _PAGE_READABLE | _PAGE_WRITABLE | \ + _PAGE_USER | _PAGE_ACCESSED) + +#define PAGE_SHARED_EXEC \ + __pgprot(_PAGE_PRESENT | _PAGE_READABLE | _PAGE_WRITABLE | \ + _PAGE_EXECUTABLE | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_COPY_NOEXEC \ + __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_READABLE) +#define PAGE_COPY_EXEC \ + __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | \ + _PAGE_READABLE | _PAGE_EXECUTABLE) +#define PAGE_COPY \ + PAGE_COPY_NOEXEC +#define PAGE_READONLY \ + __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_READABLE) +#define PAGE_READONLY_EXEC \ + __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | \ + _PAGE_READABLE | _PAGE_EXECUTABLE) + +#define _PAGE_KERNEL_RO \ + (_PAGE_PRESENT | _PAGE_GLOBAL | _PAGE_READABLE | _PAGE_ACCESSED) +#define _PAGE_KERNEL \ + (_PAGE_KERNEL_RO | _PAGE_WRITABLE | _PAGE_DIRTY) +#define _PAGE_KERNEL_EXEC (_PAGE_KERNEL_RO | _PAGE_EXECUTABLE) + +#define PAGE_KERNEL __pgprot(_PAGE_KERNEL) +#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO) +#define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL_EXEC) + +#define page_to_kpgprot(p) PAGE_KERNEL + +/* + * We could tighten these up, but for now writable or executable + * implies readable. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY /* this is write-only, which we won't support */ +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY_EXEC +#define __P101 PAGE_READONLY_EXEC +#define __P110 PAGE_COPY_EXEC +#define __P111 PAGE_COPY_EXEC + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY_EXEC +#define __S101 PAGE_READONLY_EXEC +#define __S110 PAGE_SHARED_EXEC +#define __S111 PAGE_SHARED_EXEC + +/* + * All the normal _PAGE_ALL bits are ignored for PMDs, except PAGE_PRESENT + * and PAGE_HUGE_PAGE, which must be one and zero, respectively. + * We set the ignored bits to zero. + */ +#define _PAGE_TABLE _PAGE_PRESENT + +/* Inherit the caching flags from the old protection bits. */ +#define pgprot_modify(oldprot, newprot) \ + (pgprot_t) { ((oldprot).val & ~_PAGE_ALL) | (newprot).val } + +/* Just setting the PFN to zero suffices. */ +#define pte_pgprot(x) hv_pte_set_pfn((x), 0) + +/* + * For PTEs and PDEs, we must clear the Present bit first when + * clearing a page table entry, so clear the bottom half first and + * enforce ordering with a barrier. + */ +static inline void __pte_clear(pte_t *ptep) +{ +#ifdef __tilegx__ + ptep->val = 0; +#else + u32 *tmp = (u32 *)ptep; + tmp[0] = 0; + barrier(); + tmp[1] = 0; +#endif +} +#define pte_clear(mm, addr, ptep) __pte_clear(ptep) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +#define pte_present hv_pte_get_present +#define pte_user hv_pte_get_user +#define pte_read hv_pte_get_readable +#define pte_dirty hv_pte_get_dirty +#define pte_young hv_pte_get_accessed +#define pte_write hv_pte_get_writable +#define pte_exec hv_pte_get_executable +#define pte_huge hv_pte_get_page +#define pte_rdprotect hv_pte_clear_readable +#define pte_exprotect hv_pte_clear_executable +#define pte_mkclean hv_pte_clear_dirty +#define pte_mkold hv_pte_clear_accessed +#define pte_wrprotect hv_pte_clear_writable +#define pte_mksmall hv_pte_clear_page +#define pte_mkread hv_pte_set_readable +#define pte_mkexec hv_pte_set_executable +#define pte_mkdirty hv_pte_set_dirty +#define pte_mkyoung hv_pte_set_accessed +#define pte_mkwrite hv_pte_set_writable +#define pte_mkhuge hv_pte_set_page + +#define pte_special(pte) 0 +#define pte_mkspecial(pte) (pte) + +/* + * Use some spare bits in the PTE for user-caching tags. + */ +#define pte_set_forcecache hv_pte_set_client0 +#define pte_get_forcecache hv_pte_get_client0 +#define pte_clear_forcecache hv_pte_clear_client0 +#define pte_set_anyhome hv_pte_set_client1 +#define pte_get_anyhome hv_pte_get_client1 +#define pte_clear_anyhome hv_pte_clear_client1 + +/* + * A migrating PTE has PAGE_PRESENT clear but all the other bits preserved. + */ +#define pte_migrating hv_pte_get_migrating +#define pte_mkmigrate(x) hv_pte_set_migrating(hv_pte_clear_present(x)) +#define pte_donemigrate(x) hv_pte_set_present(hv_pte_clear_migrating(x)) + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte 0x%016llx.\n", __FILE__, __LINE__, pte_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e)) + +/* + * set_pte_order() sets the given PTE and also sanity-checks the + * requested PTE against the page homecaching. Unspecified parts + * of the PTE are filled in when it is written to memory, i.e. all + * caching attributes if "!forcecache", or the home cpu if "anyhome". + */ +extern void set_pte_order(pte_t *ptep, pte_t pte, int order); + +#define set_pte(ptep, pteval) set_pte_order(ptep, pteval, 0) +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) +#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval) + +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +static inline int pte_none(pte_t pte) +{ + return !pte.val; +} + +static inline unsigned long pte_pfn(pte_t pte) +{ + return hv_pte_get_pfn(pte); +} + +/* Set or get the remote cache cpu in a pgprot with remote caching. */ +extern pgprot_t set_remote_cache_cpu(pgprot_t prot, int cpu); +extern int get_remote_cache_cpu(pgprot_t prot); + +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) +{ + return hv_pte_set_pfn(prot, pfn); +} + +/* Support for priority mappings. */ +extern void start_mm_caching(struct mm_struct *mm); +extern void check_mm_caching(struct mm_struct *prev, struct mm_struct *next); + +/* + * Support non-linear file mappings (see sys_remap_file_pages). + * This is defined by CLIENT1 set but CLIENT0 and _PAGE_PRESENT clear, and the + * file offset in the 32 high bits. + */ +#define _PAGE_FILE HV_PTE_CLIENT1 +#define PTE_FILE_MAX_BITS 32 +#define pte_file(pte) (hv_pte_get_client1(pte) && !hv_pte_get_client0(pte)) +#define pte_to_pgoff(pte) ((pte).val >> 32) +#define pgoff_to_pte(off) ((pte_t) { (((long long)(off)) << 32) | _PAGE_FILE }) + +/* + * Encode and de-code a swap entry (see ). + * We put the swap file type+offset in the 32 high bits; + * I believe we can just leave the low bits clear. + */ +#define __swp_type(swp) ((swp).val & 0x1f) +#define __swp_offset(swp) ((swp).val >> 5) +#define __swp_entry(type, off) ((swp_entry_t) { (type) | ((off) << 5) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).val >> 32 }) +#define __swp_entry_to_pte(swp) ((pte_t) { (((long long) ((swp).val)) << 32) }) + +/* + * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); + * + * dst - pointer to pgd range anwhere on a pgd page + * src - "" + * count - the number of pgds to copy. + * + * dst and src can be on the same page, but the range must not overlap, + * and must not cross a page boundary. + */ +static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) +{ + memcpy(dst, src, count * sizeof(pgd_t)); +} + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ + +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + +/* + * If we are doing an mprotect(), just accept the new vma->vm_page_prot + * value and combine it with the PFN from the old PTE to get a new PTE. + */ +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + return pfn_pte(hv_pte_get_pfn(pte), newprot); +} + +/* + * The pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD] + * + * This macro returns the index of the entry in the pgd page which would + * control the given virtual address. + */ +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) + +/* + * pgd_offset() returns a (pgd_t *) + * pgd_index() is used get the offset into the pgd page's array of pgd_t's. + */ +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) + +/* + * A shortcut which implies the use of the kernel's pgd, instead + * of a process's. + */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +#if defined(CONFIG_HIGHPTE) +extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type); +#define pte_offset_map(dir, address) \ + _pte_offset_map(dir, address, KM_PTE0) +#define pte_offset_map_nested(dir, address) \ + _pte_offset_map(dir, address, KM_PTE1) +#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) +#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) +#else +#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) +#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) +#define pte_unmap(pte) do { } while (0) +#define pte_unmap_nested(pte) do { } while (0) +#endif + +/* Clear a non-executable kernel PTE and flush it from the TLB. */ +#define kpte_clear_flush(ptep, vaddr) \ +do { \ + pte_clear(&init_mm, (vaddr), (ptep)); \ + local_flush_tlb_page(FLUSH_NONEXEC, (vaddr), PAGE_SIZE); \ +} while (0) + +/* + * The kernel page tables contain what we need, and we flush when we + * change specific page table entries. + */ +#define update_mmu_cache(vma, address, pte) do { } while (0) + +#ifdef CONFIG_FLATMEM +#define kern_addr_valid(addr) (1) +#endif /* CONFIG_FLATMEM */ + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + +extern void vmalloc_sync_all(void); + +#endif /* !__ASSEMBLY__ */ + +#ifdef __tilegx__ +#include +#else +#include +#endif + +#ifndef __ASSEMBLY__ + +static inline int pmd_none(pmd_t pmd) +{ + /* + * Only check low word on 32-bit platforms, since it might be + * out of sync with upper half. + */ + return (unsigned long)pmd_val(pmd) == 0; +} + +static inline int pmd_present(pmd_t pmd) +{ + return pmd_val(pmd) & _PAGE_PRESENT; +} + +static inline int pmd_bad(pmd_t pmd) +{ + return ((pmd_val(pmd) & _PAGE_ALL) != _PAGE_TABLE); +} + +static inline unsigned long pages_to_mb(unsigned long npg) +{ + return npg >> (20 - PAGE_SHIFT); +} + +/* + * The pmd can be thought of an array like this: pmd_t[PTRS_PER_PMD] + * + * This function returns the index of the entry in the pmd which would + * control the given virtual address. + */ +static inline unsigned long pmd_index(unsigned long address) +{ + return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); +} + +/* + * A given kernel pmd_t maps to a specific virtual address (either a + * kernel huge page or a kernel pte_t table). Since kernel pte_t + * tables can be aligned at sub-page granularity, this function can + * return non-page-aligned pointers, despite its name. + */ +static inline unsigned long pmd_page_vaddr(pmd_t pmd) +{ + phys_addr_t pa = + (phys_addr_t)pmd_ptfn(pmd) << HV_LOG2_PAGE_TABLE_ALIGN; + return (unsigned long)__va(pa); +} + +/* + * A pmd_t points to the base of a huge page or to a pte_t array. + * If a pte_t array, since we can have multiple per page, we don't + * have a one-to-one mapping of pmd_t's to pages. However, this is + * OK for pte_lockptr(), since we just end up with potentially one + * lock being used for several pte_t arrays. + */ +#define pmd_page(pmd) pfn_to_page(HV_PTFN_TO_PFN(pmd_ptfn(pmd))) + +/* + * The pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] + * + * This macro returns the index of the entry in the pte page which would + * control the given virtual address. + */ +static inline unsigned long pte_index(unsigned long address) +{ + return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); +} + +static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) +{ + return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address); +} + +static inline int pmd_huge_page(pmd_t pmd) +{ + return pmd_val(pmd) & _PAGE_HUGE_PAGE; +} + +#include + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_PGTABLE_H */ diff --git a/arch/tile/include/asm/pgtable_32.h b/arch/tile/include/asm/pgtable_32.h new file mode 100644 index 000000000000..b935fb2ad4f3 --- /dev/null +++ b/arch/tile/include/asm/pgtable_32.h @@ -0,0 +1,117 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ASM_TILE_PGTABLE_32_H +#define _ASM_TILE_PGTABLE_32_H + +/* + * The level-1 index is defined by the huge page size. A PGD is composed + * of PTRS_PER_PGD pgd_t's and is the top level of the page table. + */ +#define PGDIR_SHIFT HV_LOG2_PAGE_SIZE_LARGE +#define PGDIR_SIZE HV_PAGE_SIZE_LARGE +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) + +/* + * The level-2 index is defined by the difference between the huge + * page size and the normal page size. A PTE is composed of + * PTRS_PER_PTE pte_t's and is the bottom level of the page table. + * Note that the hypervisor docs use PTE for what we call pte_t, so + * this nomenclature is somewhat confusing. + */ +#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) + +#ifndef __ASSEMBLY__ + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + * + * HOWEVER, if we are using an allocation scheme with slop after the + * end of the page table (e.g. where our L2 page tables are 2KB but + * our pages are 64KB and we are allocating via the page allocator) + * we can't extend it easily. + */ +#define LAST_PKMAP PTRS_PER_PTE + +#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*LAST_PKMAP) & PGDIR_MASK) + +#ifdef CONFIG_HIGHMEM +# define __VMAPPING_END (PKMAP_BASE & ~(HPAGE_SIZE-1)) +#else +# define __VMAPPING_END (FIXADDR_START & ~(HPAGE_SIZE-1)) +#endif + +#ifdef CONFIG_HUGEVMAP +#define HUGE_VMAP_END __VMAPPING_END +#define HUGE_VMAP_BASE (HUGE_VMAP_END - CONFIG_NR_HUGE_VMAPS * HPAGE_SIZE) +#define _VMALLOC_END HUGE_VMAP_BASE +#else +#define _VMALLOC_END __VMAPPING_END +#endif + +/* + * Align the vmalloc area to an L2 page table, and leave a guard page + * at the beginning and end. The vmalloc code also puts in an internal + * guard page between each allocation. + */ +#define VMALLOC_END (_VMALLOC_END - PAGE_SIZE) +extern unsigned long VMALLOC_RESERVE /* = CONFIG_VMALLOC_RESERVE */; +#define _VMALLOC_START (_VMALLOC_END - VMALLOC_RESERVE) +#define VMALLOC_START (_VMALLOC_START + PAGE_SIZE) + +/* This is the maximum possible amount of lowmem. */ +#define MAXMEM (_VMALLOC_START - PAGE_OFFSET) + +/* We have no pmd or pud since we are strictly a two-level page table */ +#include + +/* We don't define any pgds for these addresses. */ +static inline int pgd_addr_invalid(unsigned long addr) +{ + return addr >= MEM_HV_INTRPT; +} + +/* + * Provide versions of these routines that can be used safely when + * the hypervisor may be asynchronously modifying dirty/accessed bits. + */ +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG +#define __HAVE_ARCH_PTEP_SET_WRPROTECT + +extern int ptep_test_and_clear_young(struct vm_area_struct *, + unsigned long addr, pte_t *); +extern void ptep_set_wrprotect(struct mm_struct *, + unsigned long addr, pte_t *); + +/* Create a pmd from a PTFN. */ +static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot) +{ + return (pmd_t){ { hv_pte_set_ptfn(prot, ptfn) } }; +} + +/* Return the page-table frame number (ptfn) that a pmd_t points at. */ +#define pmd_ptfn(pmd) hv_pte_get_ptfn((pmd).pud.pgd) + +static inline void pmd_clear(pmd_t *pmdp) +{ + __pte_clear(&pmdp->pud.pgd); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_TILE_PGTABLE_32_H */ diff --git a/arch/tile/include/asm/poll.h b/arch/tile/include/asm/poll.h new file mode 100644 index 000000000000..c98509d3149e --- /dev/null +++ b/arch/tile/include/asm/poll.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/posix_types.h b/arch/tile/include/asm/posix_types.h new file mode 100644 index 000000000000..22cae6230ceb --- /dev/null +++ b/arch/tile/include/asm/posix_types.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h new file mode 100644 index 000000000000..96c50d2c4c2b --- /dev/null +++ b/arch/tile/include/asm/processor.h @@ -0,0 +1,339 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PROCESSOR_H +#define _ASM_TILE_PROCESSOR_H + +#ifndef __ASSEMBLY__ + +/* + * NOTE: we don't include or as one + * normally would, due to #include dependencies. + */ +#include +#include + +#include +#include + +struct task_struct; +struct thread_struct; +struct list_head; + +typedef struct { + unsigned long seg; +} mm_segment_t; + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +void *current_text_addr(void); + +#if CHIP_HAS_TILE_DMA() +/* Capture the state of a suspended DMA. */ +struct tile_dma_state { + int enabled; + unsigned long src; + unsigned long dest; + unsigned long strides; + unsigned long chunk_size; + unsigned long src_chunk; + unsigned long dest_chunk; + unsigned long byte; + unsigned long status; +}; + +/* + * A mask of the DMA status register for selecting only the 'running' + * and 'done' bits. + */ +#define DMA_STATUS_MASK \ + (SPR_DMA_STATUS__RUNNING_MASK | SPR_DMA_STATUS__DONE_MASK) +#endif + +/* + * Track asynchronous TLB events (faults and access violations) + * that occur while we are in kernel mode from DMA or the SN processor. + */ +struct async_tlb { + short fault_num; /* original fault number; 0 if none */ + char is_fault; /* was it a fault (vs an access violation) */ + char is_write; /* for fault: was it caused by a write? */ + unsigned long address; /* what address faulted? */ +}; + + +struct thread_struct { + /* kernel stack pointer */ + unsigned long ksp; + /* kernel PC */ + unsigned long pc; + /* starting user stack pointer (for page migration) */ + unsigned long usp0; + /* pid of process that created this one */ + pid_t creator_pid; +#if CHIP_HAS_TILE_DMA() + /* DMA info for suspended threads (byte == 0 means no DMA state) */ + struct tile_dma_state tile_dma_state; +#endif + /* User EX_CONTEXT registers */ + unsigned long ex_context[2]; + /* User SYSTEM_SAVE registers */ + unsigned long system_save[4]; + /* User interrupt mask */ + unsigned long long interrupt_mask; + /* User interrupt-control 0 state */ + unsigned long intctrl_0; +#if CHIP_HAS_PROC_STATUS_SPR() + /* Any other miscellaneous processor state bits */ + unsigned long proc_status; +#endif +#if CHIP_HAS_TILE_DMA() + /* Async DMA TLB fault information */ + struct async_tlb dma_async_tlb; +#endif +#if CHIP_HAS_SN_PROC() + /* Was static network processor when we were switched out? */ + int sn_proc_running; + /* Async SNI TLB fault information */ + struct async_tlb sn_async_tlb; +#endif +}; + +#endif /* !__ASSEMBLY__ */ + +/* + * Start with "sp" this many bytes below the top of the kernel stack. + * This preserves the invariant that a called function may write to *sp. + */ +#define STACK_TOP_DELTA 8 + +/* + * When entering the kernel via a fault, start with the top of the + * pt_regs structure this many bytes below the top of the page. + * This aligns the pt_regs structure optimally for cache-line access. + */ +#ifdef __tilegx__ +#define KSTK_PTREGS_GAP 48 +#else +#define KSTK_PTREGS_GAP 56 +#endif + +#ifndef __ASSEMBLY__ + +#ifdef __tilegx__ +#define TASK_SIZE_MAX (MEM_LOW_END + 1) +#else +#define TASK_SIZE_MAX PAGE_OFFSET +#endif + +/* TASK_SIZE and related variables are always checked in "current" context. */ +#ifdef CONFIG_COMPAT +#define COMPAT_TASK_SIZE (1UL << 31) +#define TASK_SIZE ((current_thread_info()->status & TS_COMPAT) ?\ + COMPAT_TASK_SIZE : TASK_SIZE_MAX) +#else +#define TASK_SIZE TASK_SIZE_MAX +#endif + +/* We provide a minimal "vdso" a la x86; just the sigreturn code for now. */ +#define VDSO_BASE (TASK_SIZE - PAGE_SIZE) + +#define STACK_TOP VDSO_BASE + +/* STACK_TOP_MAX is used temporarily in execve and should not check COMPAT. */ +#define STACK_TOP_MAX TASK_SIZE_MAX + +/* + * This decides where the kernel will search for a free chunk of vm + * space during mmap's, if it is using bottom-up mapping. + */ +#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) + +#define HAVE_ARCH_PICK_MMAP_LAYOUT + +#define INIT_THREAD { \ + .ksp = (unsigned long)init_stack + THREAD_SIZE - STACK_TOP_DELTA, \ + .interrupt_mask = -1ULL \ +} + +/* Kernel stack top for the task that first boots on this cpu. */ +DECLARE_PER_CPU(unsigned long, boot_sp); + +/* PC to boot from on this cpu. */ +DECLARE_PER_CPU(unsigned long, boot_pc); + +/* Do necessary setup to start up a newly executed thread. */ +static inline void start_thread(struct pt_regs *regs, + unsigned long pc, unsigned long usp) +{ + regs->pc = pc; + regs->sp = usp; +} + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ + /* Nothing for now */ +} + +/* Prepare to copy thread state - unlazy all lazy status. */ +#define prepare_to_copy(tsk) do { } while (0) + +extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + +/* Helper routines for setting home cache modes at exec() time. */ + + +/* + * Return saved (kernel) PC of a blocked thread. + * Only used in a printk() in kernel/sched.c, so don't work too hard. + */ +#define thread_saved_pc(t) ((t)->thread.pc) + +unsigned long get_wchan(struct task_struct *p); + +/* Return initial ksp value for given task. */ +#define task_ksp0(task) ((unsigned long)(task)->stack + THREAD_SIZE) + +/* Return some info about the user process TASK. */ +#define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) +#define task_pt_regs(task) \ + ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) +#define task_sp(task) (task_pt_regs(task)->sp) +#define task_pc(task) (task_pt_regs(task)->pc) +/* Aliases for pc and sp (used in fs/proc/array.c) */ +#define KSTK_EIP(task) task_pc(task) +#define KSTK_ESP(task) task_sp(task) + +/* Standard format for printing registers and other word-size data. */ +#ifdef __tilegx__ +# define REGFMT "0x%016lx" +#else +# define REGFMT "0x%08lx" +#endif + +/* + * Do some slow action (e.g. read a slow SPR). + * Note that this must also have compiler-barrier semantics since + * it may be used in a busy loop reading memory. + */ +static inline void cpu_relax(void) +{ + __insn_mfspr(SPR_PASS); + barrier(); +} + +struct siginfo; +extern void arch_coredump_signal(struct siginfo *, struct pt_regs *); +#define arch_coredump_signal arch_coredump_signal + +/* Provide information about the chip model. */ +extern char chip_model[64]; + +/* Data on which physical memory controller corresponds to which NUMA node. */ +extern int node_controller[]; + + +/* Do we dump information to the console when a user application crashes? */ +extern int show_crashinfo; + +#if CHIP_HAS_CBOX_HOME_MAP() +/* Does the heap allocator return hash-for-home pages by default? */ +extern int hash_default; + +/* Should kernel stack pages be hash-for-home? */ +extern int kstack_hash; +#else +#define hash_default 0 +#define kstack_hash 0 +#endif + +/* Are we using huge pages in the TLB for kernel data? */ +extern int kdata_huge; + +/* + * Note that with OLOC the prefetch will return an unused read word to + * the issuing tile, which will cause some MDN traffic. Benchmarking + * should be done to see whether this outweighs prefetching. + */ +#define ARCH_HAS_PREFETCH +#define ARCH_HAS_PREFETCHW +#define ARCH_HAS_SPINLOCK_PREFETCH + +#define prefetch(ptr) __builtin_prefetch((ptr), 0, 3) +#define prefetchw(ptr) __builtin_prefetch((ptr), 1, 3) + +#ifdef CONFIG_SMP +#define spin_lock_prefetch(ptr) prefetchw(ptr) +#else +/* Nothing to prefetch. */ +#define spin_lock_prefetch(lock) do { } while (0) +#endif + +#else /* __ASSEMBLY__ */ + +/* Do some slow action (e.g. read a slow SPR). */ +#define CPU_RELAX mfspr zero, SPR_PASS + +#endif /* !__ASSEMBLY__ */ + +/* Assembly code assumes that the PL is in the low bits. */ +#if SPR_EX_CONTEXT_1_1__PL_SHIFT != 0 +# error Fix assembly assumptions about PL +#endif + +/* We sometimes use these macros for EX_CONTEXT_0_1 as well. */ +#if SPR_EX_CONTEXT_1_1__PL_SHIFT != SPR_EX_CONTEXT_0_1__PL_SHIFT || \ + SPR_EX_CONTEXT_1_1__PL_RMASK != SPR_EX_CONTEXT_0_1__PL_RMASK || \ + SPR_EX_CONTEXT_1_1__ICS_SHIFT != SPR_EX_CONTEXT_0_1__ICS_SHIFT || \ + SPR_EX_CONTEXT_1_1__ICS_RMASK != SPR_EX_CONTEXT_0_1__ICS_RMASK +# error Fix assumptions that EX1 macros work for both PL0 and PL1 +#endif + +/* Allow pulling apart and recombining the PL and ICS bits in EX_CONTEXT. */ +#define EX1_PL(ex1) \ + (((ex1) >> SPR_EX_CONTEXT_1_1__PL_SHIFT) & SPR_EX_CONTEXT_1_1__PL_RMASK) +#define EX1_ICS(ex1) \ + (((ex1) >> SPR_EX_CONTEXT_1_1__ICS_SHIFT) & SPR_EX_CONTEXT_1_1__ICS_RMASK) +#define PL_ICS_EX1(pl, ics) \ + (((pl) << SPR_EX_CONTEXT_1_1__PL_SHIFT) | \ + ((ics) << SPR_EX_CONTEXT_1_1__ICS_SHIFT)) + +/* + * Provide symbolic constants for PLs. + * Note that assembly code assumes that USER_PL is zero. + */ +#define USER_PL 0 +#define KERNEL_PL 1 + +/* SYSTEM_SAVE_1_0 holds the current cpu number ORed with ksp0. */ +#define CPU_LOG_MASK_VALUE 12 +#define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1) +#if CONFIG_NR_CPUS > CPU_MASK_VALUE +# error Too many cpus! +#endif +#define raw_smp_processor_id() \ + ((int)__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & CPU_MASK_VALUE) +#define get_current_ksp0() \ + (__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & ~CPU_MASK_VALUE) +#define next_current_ksp0(task) ({ \ + unsigned long __ksp0 = task_ksp0(task); \ + int __cpu = raw_smp_processor_id(); \ + BUG_ON(__ksp0 & CPU_MASK_VALUE); \ + __ksp0 | __cpu; \ +}) + +#endif /* _ASM_TILE_PROCESSOR_H */ diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h new file mode 100644 index 000000000000..4d1d9953016a --- /dev/null +++ b/arch/tile/include/asm/ptrace.h @@ -0,0 +1,163 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_PTRACE_H +#define _ASM_TILE_PTRACE_H + +#include +#include + +/* These must match struct pt_regs, below. */ +#if CHIP_WORD_SIZE() == 32 +#define PTREGS_OFFSET_REG(n) ((n)*4) +#else +#define PTREGS_OFFSET_REG(n) ((n)*8) +#endif +#define PTREGS_OFFSET_BASE 0 +#define PTREGS_OFFSET_TP PTREGS_OFFSET_REG(53) +#define PTREGS_OFFSET_SP PTREGS_OFFSET_REG(54) +#define PTREGS_OFFSET_LR PTREGS_OFFSET_REG(55) +#define PTREGS_NR_GPRS 56 +#define PTREGS_OFFSET_PC PTREGS_OFFSET_REG(56) +#define PTREGS_OFFSET_EX1 PTREGS_OFFSET_REG(57) +#define PTREGS_OFFSET_FAULTNUM PTREGS_OFFSET_REG(58) +#define PTREGS_OFFSET_ORIG_R0 PTREGS_OFFSET_REG(59) +#define PTREGS_OFFSET_FLAGS PTREGS_OFFSET_REG(60) +#if CHIP_HAS_CMPEXCH() +#define PTREGS_OFFSET_CMPEXCH PTREGS_OFFSET_REG(61) +#endif +#define PTREGS_SIZE PTREGS_OFFSET_REG(64) + +#ifndef __ASSEMBLY__ + +#ifdef __KERNEL__ +/* Benefit from consistent use of "long" on all chips. */ +typedef unsigned long pt_reg_t; +#else +/* Provide appropriate length type to userspace regardless of -m32/-m64. */ +typedef uint_reg_t pt_reg_t; +#endif + +/* + * This struct defines the way the registers are stored on the stack during a + * system call/exception. It should be a multiple of 8 bytes to preserve + * normal stack alignment rules. + * + * Must track and + */ +struct pt_regs { + /* Saved main processor registers; 56..63 are special. */ + /* tp, sp, and lr must immediately follow regs[] for aliasing. */ + pt_reg_t regs[53]; + pt_reg_t tp; /* aliases regs[TREG_TP] */ + pt_reg_t sp; /* aliases regs[TREG_SP] */ + pt_reg_t lr; /* aliases regs[TREG_LR] */ + + /* Saved special registers. */ + pt_reg_t pc; /* stored in EX_CONTEXT_1_0 */ + pt_reg_t ex1; /* stored in EX_CONTEXT_1_1 (PL and ICS bit) */ + pt_reg_t faultnum; /* fault number (INT_SWINT_1 for syscall) */ + pt_reg_t orig_r0; /* r0 at syscall entry, else zero */ + pt_reg_t flags; /* flags (see below) */ +#if !CHIP_HAS_CMPEXCH() + pt_reg_t pad[3]; +#else + pt_reg_t cmpexch; /* value of CMPEXCH_VALUE SPR at interrupt */ + pt_reg_t pad[2]; +#endif +}; + +#endif /* __ASSEMBLY__ */ + +/* Flag bits in pt_regs.flags */ +#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ +#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ +#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ + +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +/* Support TILE-specific ptrace options, with events starting at 16. */ +#define PTRACE_O_TRACEMIGRATE 0x00010000 +#define PTRACE_EVENT_MIGRATE 16 +#ifdef __KERNEL__ +#define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE) +#define PT_TRACE_MIGRATE 0x00080000 +#define PT_TRACE_MASK_TILE (PT_TRACE_MIGRATE) +#endif + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#define instruction_pointer(regs) ((regs)->pc) +#define profile_pc(regs) instruction_pointer(regs) + +/* Does the process account for user or for system time? */ +#define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL) + +/* Fill in a struct pt_regs with the current kernel registers. */ +struct pt_regs *get_pt_regs(struct pt_regs *); + +extern void show_regs(struct pt_regs *); + +#define arch_has_single_step() (1) + +/* + * A structure for all single-stepper state. + * + * Also update defines in assembler section if it changes + */ +struct single_step_state { + /* the page to which we will write hacked-up bundles */ + void *buffer; + + union { + int flags; + struct { + unsigned long is_enabled:1, update:1, update_reg:6; + }; + }; + + unsigned long orig_pc; /* the original PC */ + unsigned long next_pc; /* return PC if no branch (PC + 1) */ + unsigned long branch_next_pc; /* return PC if we did branch/jump */ + unsigned long update_value; /* value to restore to update_target */ +}; + +/* Single-step the instruction at regs->pc */ +extern void single_step_once(struct pt_regs *regs); + +struct task_struct; + +extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code); + +#ifdef __tilegx__ +/* We need this since sigval_t has a user pointer in it, for GETSIGINFO etc. */ +#define __ARCH_WANT_COMPAT_SYS_PTRACE +#endif + +#endif /* !__ASSEMBLY__ */ + +#define SINGLESTEP_STATE_MASK_IS_ENABLED 0x1 +#define SINGLESTEP_STATE_MASK_UPDATE 0x2 +#define SINGLESTEP_STATE_TARGET_LB 2 +#define SINGLESTEP_STATE_TARGET_UB 7 + +#endif /* !__KERNEL__ */ + +#endif /* _ASM_TILE_PTRACE_H */ diff --git a/arch/tile/include/asm/resource.h b/arch/tile/include/asm/resource.h new file mode 100644 index 000000000000..04bc4db8921b --- /dev/null +++ b/arch/tile/include/asm/resource.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/scatterlist.h b/arch/tile/include/asm/scatterlist.h new file mode 100644 index 000000000000..c5604242c0d5 --- /dev/null +++ b/arch/tile/include/asm/scatterlist.h @@ -0,0 +1,22 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SCATTERLIST_H +#define _ASM_TILE_SCATTERLIST_H + +#define ISA_DMA_THRESHOLD (~0UL) + +#include + +#endif /* _ASM_TILE_SCATTERLIST_H */ diff --git a/arch/tile/include/asm/sections.h b/arch/tile/include/asm/sections.h new file mode 100644 index 000000000000..6c111491f0ed --- /dev/null +++ b/arch/tile/include/asm/sections.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SECTIONS_H +#define _ASM_TILE_SECTIONS_H + +#define arch_is_kernel_data arch_is_kernel_data + +#include + +/* Text and data are at different areas in the kernel VA space. */ +extern char _sinitdata[], _einitdata[]; + +/* Write-once data is writable only till the end of initialization. */ +extern char __w1data_begin[], __w1data_end[]; + +extern char __feedback_section_start[], __feedback_section_end[]; + +/* Handle the discontiguity between _sdata and _stext. */ +static inline int arch_is_kernel_data(unsigned long addr) +{ + return addr >= (unsigned long)_sdata && + addr < (unsigned long)_end; +} + +#endif /* _ASM_TILE_SECTIONS_H */ diff --git a/arch/tile/include/asm/sembuf.h b/arch/tile/include/asm/sembuf.h new file mode 100644 index 000000000000..7673b83cfef7 --- /dev/null +++ b/arch/tile/include/asm/sembuf.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/setup.h b/arch/tile/include/asm/setup.h new file mode 100644 index 000000000000..823ddd47ff6e --- /dev/null +++ b/arch/tile/include/asm/setup.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SETUP_H +#define _ASM_TILE_SETUP_H + +#include +#include + +/* + * Reserved space for vmalloc and iomap - defined in asm/page.h + */ +#define MAXMEM_PFN PFN_DOWN(MAXMEM) + +#define COMMAND_LINE_SIZE 2048 + +void early_panic(const char *fmt, ...); +void warn_early_printk(void); +void __init disable_early_printk(void); + +#endif /* _ASM_TILE_SETUP_H */ diff --git a/arch/tile/include/asm/shmbuf.h b/arch/tile/include/asm/shmbuf.h new file mode 100644 index 000000000000..83c05fc2de38 --- /dev/null +++ b/arch/tile/include/asm/shmbuf.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/shmparam.h b/arch/tile/include/asm/shmparam.h new file mode 100644 index 000000000000..93f30deb95d0 --- /dev/null +++ b/arch/tile/include/asm/shmparam.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/sigcontext.h b/arch/tile/include/asm/sigcontext.h new file mode 100644 index 000000000000..7cd7672e3ad4 --- /dev/null +++ b/arch/tile/include/asm/sigcontext.h @@ -0,0 +1,27 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SIGCONTEXT_H +#define _ASM_TILE_SIGCONTEXT_H + +/* NOTE: we can't include due to #include dependencies. */ +#include + +/* Must track */ + +struct sigcontext { + struct pt_regs regs; +}; + +#endif /* _ASM_TILE_SIGCONTEXT_H */ diff --git a/arch/tile/include/asm/sigframe.h b/arch/tile/include/asm/sigframe.h new file mode 100644 index 000000000000..994d3d30205f --- /dev/null +++ b/arch/tile/include/asm/sigframe.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SIGFRAME_H +#define _ASM_TILE_SIGFRAME_H + +/* Indicate that syscall return should not examine r0 */ +#define INT_SWINT_1_SIGRETURN (~0) + +#ifndef __ASSEMBLY__ + +#include + +struct rt_sigframe { + unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */ + struct siginfo info; + struct ucontext uc; +}; + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_SIGFRAME_H */ diff --git a/arch/tile/include/asm/siginfo.h b/arch/tile/include/asm/siginfo.h new file mode 100644 index 000000000000..0c12d1b9ddf2 --- /dev/null +++ b/arch/tile/include/asm/siginfo.h @@ -0,0 +1,30 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SIGINFO_H +#define _ASM_TILE_SIGINFO_H + +#define __ARCH_SI_TRAPNO + +#include + +/* + * Additional Tile-specific SIGILL si_codes + */ +#define ILL_DBLFLT (__SI_FAULT|9) /* double fault */ +#define ILL_HARDWALL (__SI_FAULT|10) /* user networks hardwall violation */ +#undef NSIGILL +#define NSIGILL 10 + +#endif /* _ASM_TILE_SIGINFO_H */ diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h new file mode 100644 index 000000000000..d20d326d201b --- /dev/null +++ b/arch/tile/include/asm/signal.h @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SIGNAL_H +#define _ASM_TILE_SIGNAL_H + +/* Do not notify a ptracer when this signal is handled. */ +#define SA_NOPTRACE 0x02000000u + +/* Used in earlier Tilera releases, so keeping for binary compatibility. */ +#define SA_RESTORER 0x04000000u + +#include + +#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); +int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); +#endif + +#endif /* _ASM_TILE_SIGNAL_H */ diff --git a/arch/tile/include/asm/smp.h b/arch/tile/include/asm/smp.h new file mode 100644 index 000000000000..da24858a7392 --- /dev/null +++ b/arch/tile/include/asm/smp.h @@ -0,0 +1,126 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SMP_H +#define _ASM_TILE_SMP_H + +#ifdef CONFIG_SMP + +#include +#include +#include + +/* Set up this tile to support receiving hypervisor messages */ +void init_messaging(void); + +/* Set up this tile to support receiving device interrupts and IPIs. */ +void init_per_tile_IRQs(void); + +/* Send a message to processors specified in mask */ +void send_IPI_many(const struct cpumask *mask, int tag); + +/* Send a message to all but the sending processor */ +void send_IPI_allbutself(int tag); + +/* Send a message to a specific processor */ +void send_IPI_single(int dest, int tag); + +/* Process an IPI message */ +void evaluate_message(int tag); + +/* Process an IRQ_RESCHEDULE IPI. */ +irqreturn_t handle_reschedule_ipi(int irq, void *token); + +/* Boot a secondary cpu */ +void online_secondary(void); + +/* Call a function on a specified set of CPUs (may include this one). */ +extern void on_each_cpu_mask(const struct cpumask *mask, + void (*func)(void *), void *info, bool wait); + +/* Topology of the supervisor tile grid, and coordinates of boot processor */ +extern HV_Topology smp_topology; + +/* Accessors for grid size */ +#define smp_height (smp_topology.height) +#define smp_width (smp_topology.width) + +/* Hypervisor message tags sent via the tile send_IPI*() routines. */ +#define MSG_TAG_START_CPU 1 +#define MSG_TAG_STOP_CPU 2 +#define MSG_TAG_CALL_FUNCTION_MANY 3 +#define MSG_TAG_CALL_FUNCTION_SINGLE 4 + +/* Hook for the generic smp_call_function_many() routine. */ +static inline void arch_send_call_function_ipi_mask(struct cpumask *mask) +{ + send_IPI_many(mask, MSG_TAG_CALL_FUNCTION_MANY); +} + +/* Hook for the generic smp_call_function_single() routine. */ +static inline void arch_send_call_function_single_ipi(int cpu) +{ + send_IPI_single(cpu, MSG_TAG_CALL_FUNCTION_SINGLE); +} + +/* Print out the boot string describing which cpus were disabled. */ +void print_disabled_cpus(void); + +#else /* !CONFIG_SMP */ + +#define on_each_cpu_mask(mask, func, info, wait) \ + do { if (cpumask_test_cpu(0, (mask))) func(info); } while (0) + +#define smp_master_cpu 0 +#define smp_height 1 +#define smp_width 1 + +#endif /* !CONFIG_SMP */ + + +/* Which cpus may be used as the lotar in a page table entry. */ +extern struct cpumask cpu_lotar_map; +#define cpu_is_valid_lotar(cpu) cpumask_test_cpu((cpu), &cpu_lotar_map) + +#if CHIP_HAS_CBOX_HOME_MAP() +/* Which processors are used for hash-for-home mapping */ +extern struct cpumask hash_for_home_map; +#endif + +/* Which cpus can have their cache flushed by hv_flush_remote(). */ +extern struct cpumask cpu_cacheable_map; +#define cpu_cacheable(cpu) cpumask_test_cpu((cpu), &cpu_cacheable_map) + +/* Convert an HV_LOTAR value into a cpu. */ +static inline int hv_lotar_to_cpu(HV_LOTAR lotar) +{ + return HV_LOTAR_X(lotar) + (HV_LOTAR_Y(lotar) * smp_width); +} + +/* + * Extension of functionality when you just want + * to express a mask or suppression or inclusion region without + * being too concerned about exactly which cpus are valid in that region. + */ +int bitmap_parselist_crop(const char *bp, unsigned long *maskp, int nmaskbits); + +#define cpulist_parse_crop(buf, dst) \ + __cpulist_parse_crop((buf), (dst), NR_CPUS) +static inline int __cpulist_parse_crop(const char *buf, struct cpumask *dstp, + int nbits) +{ + return bitmap_parselist_crop(buf, cpumask_bits(dstp), nbits); +} + +#endif /* _ASM_TILE_SMP_H */ diff --git a/arch/tile/include/asm/socket.h b/arch/tile/include/asm/socket.h new file mode 100644 index 000000000000..6b71384b9d8b --- /dev/null +++ b/arch/tile/include/asm/socket.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/sockios.h b/arch/tile/include/asm/sockios.h new file mode 100644 index 000000000000..def6d4746ee7 --- /dev/null +++ b/arch/tile/include/asm/sockios.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/spinlock.h b/arch/tile/include/asm/spinlock.h new file mode 100644 index 000000000000..1a8bd4740c28 --- /dev/null +++ b/arch/tile/include/asm/spinlock.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SPINLOCK_H +#define _ASM_TILE_SPINLOCK_H + +#ifdef __tilegx__ +#include +#else +#include +#endif + +#endif /* _ASM_TILE_SPINLOCK_H */ diff --git a/arch/tile/include/asm/spinlock_32.h b/arch/tile/include/asm/spinlock_32.h new file mode 100644 index 000000000000..f3a8473c68da --- /dev/null +++ b/arch/tile/include/asm/spinlock_32.h @@ -0,0 +1,200 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * 32-bit SMP spinlocks. + */ + +#ifndef _ASM_TILE_SPINLOCK_32_H +#define _ASM_TILE_SPINLOCK_32_H + +#include +#include +#include +#include + +/* + * We only use even ticket numbers so the '1' inserted by a tns is + * an unambiguous "ticket is busy" flag. + */ +#define TICKET_QUANTUM 2 + + +/* + * SMP ticket spinlocks, allowing only a single CPU anywhere + * + * (the type definitions are in asm/spinlock_types.h) + */ +static inline int arch_spin_is_locked(arch_spinlock_t *lock) +{ + /* + * Note that even if a new ticket is in the process of being + * acquired, so lock->next_ticket is 1, it's still reasonable + * to claim the lock is held, since it will be momentarily + * if not already. There's no need to wait for a "valid" + * lock->next_ticket to become available. + */ + return lock->next_ticket != lock->current_ticket; +} + +void arch_spin_lock(arch_spinlock_t *lock); + +/* We cannot take an interrupt after getting a ticket, so don't enable them. */ +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) + +int arch_spin_trylock(arch_spinlock_t *lock); + +static inline void arch_spin_unlock(arch_spinlock_t *lock) +{ + /* For efficiency, overlap fetching the old ticket with the wmb(). */ + int old_ticket = lock->current_ticket; + wmb(); /* guarantee anything modified under the lock is visible */ + lock->current_ticket = old_ticket + TICKET_QUANTUM; +} + +void arch_spin_unlock_wait(arch_spinlock_t *lock); + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * We use a "tns/store-back" technique on a single word to manage + * the lock state, looping around to retry if the tns returns 1. + */ + +/* Internal layout of the word; do not use. */ +#define _WR_NEXT_SHIFT 8 +#define _WR_CURR_SHIFT 16 +#define _WR_WIDTH 8 +#define _RD_COUNT_SHIFT 24 +#define _RD_COUNT_WIDTH 8 + +/* Internal functions; do not use. */ +void arch_read_lock_slow(arch_rwlock_t *, u32); +int arch_read_trylock_slow(arch_rwlock_t *); +void arch_read_unlock_slow(arch_rwlock_t *); +void arch_write_lock_slow(arch_rwlock_t *, u32); +void arch_write_unlock_slow(arch_rwlock_t *, u32); + +/** + * arch_read_can_lock() - would read_trylock() succeed? + */ +static inline int arch_read_can_lock(arch_rwlock_t *rwlock) +{ + return (rwlock->lock << _RD_COUNT_WIDTH) == 0; +} + +/** + * arch_write_can_lock() - would write_trylock() succeed? + */ +static inline int arch_write_can_lock(arch_rwlock_t *rwlock) +{ + return rwlock->lock == 0; +} + +/** + * arch_read_lock() - acquire a read lock. + */ +static inline void arch_read_lock(arch_rwlock_t *rwlock) +{ + u32 val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val << _RD_COUNT_WIDTH)) { + arch_read_lock_slow(rwlock, val); + return; + } + rwlock->lock = val + (1 << _RD_COUNT_SHIFT); +} + +/** + * arch_read_lock() - acquire a write lock. + */ +static inline void arch_write_lock(arch_rwlock_t *rwlock) +{ + u32 val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val != 0)) { + arch_write_lock_slow(rwlock, val); + return; + } + rwlock->lock = 1 << _WR_NEXT_SHIFT; +} + +/** + * arch_read_trylock() - try to acquire a read lock. + */ +static inline int arch_read_trylock(arch_rwlock_t *rwlock) +{ + int locked; + u32 val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val & 1)) { + return arch_read_trylock_slow(rwlock); + } + locked = (val << _RD_COUNT_WIDTH) == 0; + rwlock->lock = val + (locked << _RD_COUNT_SHIFT); + return locked; +} + +/** + * arch_write_trylock() - try to acquire a write lock. + */ +static inline int arch_write_trylock(arch_rwlock_t *rwlock) +{ + u32 val = __insn_tns((int *)&rwlock->lock); + + /* + * If a tns is in progress, or there's a waiting or active locker, + * or active readers, we can't take the lock, so give up. + */ + if (unlikely(val != 0)) { + if (!(val & 1)) + rwlock->lock = val; + return 0; + } + + /* Set the "next" field to mark it locked. */ + rwlock->lock = 1 << _WR_NEXT_SHIFT; + return 1; +} + +/** + * arch_read_unlock() - release a read lock. + */ +static inline void arch_read_unlock(arch_rwlock_t *rwlock) +{ + u32 val; + mb(); /* guarantee anything modified under the lock is visible */ + val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val & 1)) { + arch_read_unlock_slow(rwlock); + return; + } + rwlock->lock = val - (1 << _RD_COUNT_SHIFT); +} + +/** + * arch_write_unlock() - release a write lock. + */ +static inline void arch_write_unlock(arch_rwlock_t *rwlock) +{ + u32 val; + mb(); /* guarantee anything modified under the lock is visible */ + val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val != (1 << _WR_NEXT_SHIFT))) { + arch_write_unlock_slow(rwlock, val); + return; + } + rwlock->lock = 0; +} + +#define arch_read_lock_flags(lock, flags) arch_read_lock(lock) +#define arch_write_lock_flags(lock, flags) arch_write_lock(lock) + +#endif /* _ASM_TILE_SPINLOCK_32_H */ diff --git a/arch/tile/include/asm/spinlock_types.h b/arch/tile/include/asm/spinlock_types.h new file mode 100644 index 000000000000..a71f59b49c50 --- /dev/null +++ b/arch/tile/include/asm/spinlock_types.h @@ -0,0 +1,60 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SPINLOCK_TYPES_H +#define _ASM_TILE_SPINLOCK_TYPES_H + +#ifndef __LINUX_SPINLOCK_TYPES_H +# error "please don't include this file directly" +#endif + +#ifdef __tilegx__ + +/* Low 15 bits are "next"; high 15 bits are "current". */ +typedef struct arch_spinlock { + unsigned int lock; +} arch_spinlock_t; + +#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } + +/* High bit is "writer owns"; low 31 bits are a count of readers. */ +typedef struct arch_rwlock { + unsigned int lock; +} arch_rwlock_t; + +#define __ARCH_RW_LOCK_UNLOCKED { 0 } + +#else + +typedef struct arch_spinlock { + /* Next ticket number to hand out. */ + int next_ticket; + /* The ticket number that currently owns this lock. */ + int current_ticket; +} arch_spinlock_t; + +#define __ARCH_SPIN_LOCK_UNLOCKED { 0, 0 } + +/* + * Byte 0 for tns (only the low bit is used), byte 1 for ticket-lock "next", + * byte 2 for ticket-lock "current", byte 3 for reader count. + */ +typedef struct arch_rwlock { + unsigned int lock; +} arch_rwlock_t; + +#define __ARCH_RW_LOCK_UNLOCKED { 0 } + +#endif +#endif /* _ASM_TILE_SPINLOCK_TYPES_H */ diff --git a/arch/tile/include/asm/stack.h b/arch/tile/include/asm/stack.h new file mode 100644 index 000000000000..864913bcfbc9 --- /dev/null +++ b/arch/tile/include/asm/stack.h @@ -0,0 +1,68 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_STACK_H +#define _ASM_TILE_STACK_H + +#include +#include +#include +#include + +/* Everything we need to keep track of a backtrace iteration */ +struct KBacktraceIterator { + BacktraceIterator it; + struct task_struct *task; /* task we are backtracing */ + HV_PTE *pgtable; /* page table for user space access */ + int end; /* iteration complete. */ + int new_context; /* new context is starting */ + int profile; /* profiling, so stop on async intrpt */ + int verbose; /* printk extra info (don't want to + * do this for profiling) */ + int is_current; /* backtracing current task */ +}; + +/* Iteration methods for kernel backtraces */ + +/* + * Initialize a KBacktraceIterator from a task_struct, and optionally from + * a set of registers. If the registers are omitted, the process is + * assumed to be descheduled, and registers are read from the process's + * thread_struct and stack. "verbose" means to printk some additional + * information about fault handlers as we pass them on the stack. + */ +extern void KBacktraceIterator_init(struct KBacktraceIterator *kbt, + struct task_struct *, struct pt_regs *); + +/* Initialize iterator based on current stack. */ +extern void KBacktraceIterator_init_current(struct KBacktraceIterator *kbt); + +/* No more frames? */ +extern int KBacktraceIterator_end(struct KBacktraceIterator *kbt); + +/* Advance to the next frame. */ +extern void KBacktraceIterator_next(struct KBacktraceIterator *kbt); + +/* + * Dump stack given complete register info. Use only from the + * architecture-specific code; show_stack() + * and dump_stack() (in entry.S) are architecture-independent entry points. + */ +extern void tile_show_stack(struct KBacktraceIterator *, int headers); + +/* Dump stack of current process, with registers to seed the backtrace. */ +extern void dump_stack_regs(struct pt_regs *); + + +#endif /* _ASM_TILE_STACK_H */ diff --git a/arch/tile/include/asm/stat.h b/arch/tile/include/asm/stat.h new file mode 100644 index 000000000000..3dc90fa92c70 --- /dev/null +++ b/arch/tile/include/asm/stat.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/statfs.h b/arch/tile/include/asm/statfs.h new file mode 100644 index 000000000000..0b91fe198c20 --- /dev/null +++ b/arch/tile/include/asm/statfs.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/string.h b/arch/tile/include/asm/string.h new file mode 100644 index 000000000000..7535cf1a30e4 --- /dev/null +++ b/arch/tile/include/asm/string.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_STRING_H +#define _ASM_TILE_STRING_H + +#define __HAVE_ARCH_MEMCHR +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_STRCHR +#define __HAVE_ARCH_STRLEN + +extern __kernel_size_t strlen(const char *); +extern char *strchr(const char *s, int c); +extern void *memchr(const void *s, int c, size_t n); +extern void *memset(void *, int, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); +extern void *memmove(void *, const void *, __kernel_size_t); + +#endif /* _ASM_TILE_STRING_H */ diff --git a/arch/tile/include/asm/swab.h b/arch/tile/include/asm/swab.h new file mode 100644 index 000000000000..25c686a00f1d --- /dev/null +++ b/arch/tile/include/asm/swab.h @@ -0,0 +1,29 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SWAB_H +#define _ASM_TILE_SWAB_H + +/* Tile gcc is always >= 4.3.0, so we use __builtin_bswap. */ +#define __arch_swab32(x) __builtin_bswap32(x) +#define __arch_swab64(x) __builtin_bswap64(x) + +/* Use the variant that is natural for the wordsize. */ +#ifdef CONFIG_64BIT +#define __arch_swab16(x) (__builtin_bswap64(x) >> 48) +#else +#define __arch_swab16(x) (__builtin_bswap32(x) >> 16) +#endif + +#endif /* _ASM_TILE_SWAB_H */ diff --git a/arch/tile/include/asm/syscall.h b/arch/tile/include/asm/syscall.h new file mode 100644 index 000000000000..d35e0dcb67b1 --- /dev/null +++ b/arch/tile/include/asm/syscall.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * See asm-generic/syscall.h for descriptions of what we must do here. + */ + +#ifndef _ASM_TILE_SYSCALL_H +#define _ASM_TILE_SYSCALL_H + +#include +#include +#include + +/* + * Only the low 32 bits of orig_r0 are meaningful, so we return int. + * This importantly ignores the high bits on 64-bit, so comparisons + * sign-extend the low 32 bits. + */ +static inline int syscall_get_nr(struct task_struct *t, struct pt_regs *regs) +{ + return regs->regs[TREG_SYSCALL_NR]; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->regs[0] = regs->orig_r0; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + unsigned long error = regs->regs[0]; + return IS_ERR_VALUE(error) ? error : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->regs[0]; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->regs[0] = (long) error ?: val; +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(args, ®s[i], n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(®s[i], args, n * sizeof(args[0])); +} + +#endif /* _ASM_TILE_SYSCALL_H */ diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h new file mode 100644 index 000000000000..e1be54d1a7d8 --- /dev/null +++ b/arch/tile/include/asm/syscalls.h @@ -0,0 +1,60 @@ +/* + * syscalls.h - Linux syscall interfaces (arch-specific) + * + * Copyright (c) 2008 Jaswinder Singh Rajput + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SYSCALLS_H +#define _ASM_TILE_SYSCALLS_H + +#include +#include +#include +#include + +/* kernel/process.c */ +int sys_fork(struct pt_regs *); +int sys_vfork(struct pt_regs *); +int sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tidptr, int __user *child_tidptr, + struct pt_regs *); +int sys_execve(char __user *path, char __user *__user *argv, + char __user *__user *envp, struct pt_regs *); + +/* kernel/signal.c */ +int sys_sigaltstack(const stack_t __user *, stack_t __user *, + struct pt_regs *); +long sys_rt_sigreturn(struct pt_regs *); +int sys_raise_fpe(int code, unsigned long addr, struct pt_regs*); + +/* kernel/sys.c */ +ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count); +long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi, + u32 len, int advice); +int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, + u32 len_lo, u32 len_hi, int advice); +long sys_flush_cache(void); +long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset); +long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset); + +#ifndef __tilegx__ +/* mm/fault.c */ +int sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); +#endif + +#endif /* _ASM_TILE_SYSCALLS_H */ diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h new file mode 100644 index 000000000000..d6ca7f816c87 --- /dev/null +++ b/arch/tile/include/asm/system.h @@ -0,0 +1,220 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_SYSTEM_H +#define _ASM_TILE_SYSTEM_H + +#ifndef __ASSEMBLY__ + +#include +#include + +/* NOTE: we can't include due to #include dependencies. */ +#include + +#include +#include +#include + +/* + * read_barrier_depends - Flush all pending reads that subsequents reads + * depend on. + * + * No data-dependent reads from memory-like regions are ever reordered + * over this barrier. All reads preceding this primitive are guaranteed + * to access memory (but not necessarily other CPUs' caches) before any + * reads following this primitive that depend on the data return by + * any of the preceding reads. This primitive is much lighter weight than + * rmb() on most CPUs, and is never heavier weight than is + * rmb(). + * + * These ordering constraints are respected by both the local CPU + * and the compiler. + * + * Ordering is not guaranteed by anything other than these primitives, + * not even by data dependencies. See the documentation for + * memory_barrier() for examples and URLs to more information. + * + * For example, the following code would force ordering (the initial + * value of "a" is zero, "b" is one, and "p" is "&a"): + * + * + * CPU 0 CPU 1 + * + * b = 2; + * memory_barrier(); + * p = &b; q = p; + * read_barrier_depends(); + * d = *q; + * + * + * because the read of "*q" depends on the read of "p" and these + * two reads are separated by a read_barrier_depends(). However, + * the following code, with the same initial values for "a" and "b": + * + * + * CPU 0 CPU 1 + * + * a = 2; + * memory_barrier(); + * b = 3; y = b; + * read_barrier_depends(); + * x = a; + * + * + * does not enforce ordering, since there is no data dependency between + * the read of "a" and the read of "b". Therefore, on some CPUs, such + * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() + * in cases like this where there are no data dependencies. + */ + +#define read_barrier_depends() do { } while (0) + +#define __sync() __insn_mf() + +#if CHIP_HAS_SPLIT_CYCLE() +#define get_cycles_low() __insn_mfspr(SPR_CYCLE_LOW) +#else +#define get_cycles_low() __insn_mfspr(SPR_CYCLE) /* just get all 64 bits */ +#endif + +/* Fence to guarantee visibility of stores to incoherent memory. */ +static inline void +mb_incoherent(void) +{ + __insn_mf(); + +#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS() + { + int __mb_incoherent(void); +#if CHIP_HAS_TILE_WRITE_PENDING() + const unsigned long WRITE_TIMEOUT_CYCLES = 400; + unsigned long start = get_cycles_low(); + do { + if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0) + return; + } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES); +#endif /* CHIP_HAS_TILE_WRITE_PENDING() */ + (void) __mb_incoherent(); + } +#endif /* CHIP_HAS_MF_WAITS_FOR_VICTIMS() */ +} + +#define fast_wmb() __sync() +#define fast_rmb() __sync() +#define fast_mb() __sync() +#define fast_iob() mb_incoherent() + +#define wmb() fast_wmb() +#define rmb() fast_rmb() +#define mb() fast_mb() +#define iob() fast_iob() + +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#define smp_read_barrier_depends() read_barrier_depends() +#else +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#define smp_read_barrier_depends() do { } while (0) +#endif + +#define set_mb(var, value) \ + do { var = value; mb(); } while (0) + +#include + +/* + * Pause the DMA engine and static network before task switching. + */ +#define prepare_arch_switch(next) _prepare_arch_switch(next) +void _prepare_arch_switch(struct task_struct *next); + + +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + * The number of callee-saved registers saved on the kernel stack + * is defined here for use in copy_thread() and must agree with __switch_to(). + */ +#endif /* !__ASSEMBLY__ */ +#define CALLEE_SAVED_FIRST_REG 30 +#define CALLEE_SAVED_REGS_COUNT 24 /* r30 to r52, plus an empty to align */ +#ifndef __ASSEMBLY__ +struct task_struct; +#define switch_to(prev, next, last) ((last) = _switch_to((prev), (next))) +extern struct task_struct *_switch_to(struct task_struct *prev, + struct task_struct *next); + +/* + * On SMP systems, when the scheduler does migration-cost autodetection, + * it needs a way to flush as much of the CPU's caches as possible: + * + * TODO: fill this in! + */ +static inline void sched_cacheflush(void) +{ +} + +#define arch_align_stack(x) (x) + +/* + * Is the kernel doing fixups of unaligned accesses? If <0, no kernel + * intervention occurs and SIGBUS is delivered with no data address + * info. If 0, the kernel single-steps the instruction to discover + * the data address to provide with the SIGBUS. If 1, the kernel does + * a fixup. + */ +extern int unaligned_fixup; + +/* Is the kernel printing on each unaligned fixup? */ +extern int unaligned_printk; + +/* Number of unaligned fixups performed */ +extern unsigned int unaligned_fixup_count; + +/* User-level DMA management functions */ +void grant_dma_mpls(void); +void restrict_dma_mpls(void); + + +/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */ +extern int _sim_syscall(int syscall_num, ...); +#define sim_syscall(syscall_num, ...) \ + _sim_syscall(SIM_CONTROL_SYSCALL + \ + ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \ + ## __VA_ARGS__) + +/* + * Kernel threads can check to see if they need to migrate their + * stack whenever they return from a context switch; for user + * threads, we defer until they are returning to user-space. + */ +#define finish_arch_switch(prev) do { \ + if (unlikely((prev)->state == TASK_DEAD)) \ + __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT | \ + ((prev)->pid << _SIM_CONTROL_OPERATOR_BITS)); \ + __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH | \ + (current->pid << _SIM_CONTROL_OPERATOR_BITS)); \ + if (current->mm == NULL && !kstack_hash && \ + current_thread_info()->homecache_cpu != smp_processor_id()) \ + homecache_migrate_kthread(); \ +} while (0) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_SYSTEM_H */ diff --git a/arch/tile/include/asm/termbits.h b/arch/tile/include/asm/termbits.h new file mode 100644 index 000000000000..3935b106de79 --- /dev/null +++ b/arch/tile/include/asm/termbits.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/termios.h b/arch/tile/include/asm/termios.h new file mode 100644 index 000000000000..280d78a9d966 --- /dev/null +++ b/arch/tile/include/asm/termios.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h new file mode 100644 index 000000000000..9024bf3530aa --- /dev/null +++ b/arch/tile/include/asm/thread_info.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2002 David Howells (dhowells@redhat.com) + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_THREAD_INFO_H +#define _ASM_TILE_THREAD_INFO_H + +#include +#include +#ifndef __ASSEMBLY__ + +/* + * Low level task data that assembly code needs immediate access to. + * The structure is placed at the bottom of the supervisor stack. + */ +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + unsigned long flags; /* low level flags */ + unsigned long status; /* thread-synchronous flags */ + __u32 homecache_cpu; /* CPU we are homecached on */ + __u32 cpu; /* current CPU */ + int preempt_count; /* 0 => preemptable, + <0 => BUG */ + + mm_segment_t addr_limit; /* thread address space + (KERNEL_DS or USER_DS) */ + struct restart_block restart_block; + struct single_step_state *step_state; /* single step state + (if non-zero) */ +}; + +/* + * macros/functions for gaining access to the thread information structure. + */ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ + .step_state = 0, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +#endif /* !__ASSEMBLY__ */ + +#if PAGE_SIZE < 8192 +#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT) +#else +#define THREAD_SIZE_ORDER (0) +#endif + +#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) +#define LOG2_THREAD_SIZE (PAGE_SHIFT + THREAD_SIZE_ORDER) + +#define STACK_WARN (THREAD_SIZE/8) + +#ifndef __ASSEMBLY__ + +/* How to get the thread information struct from C. */ +register unsigned long stack_pointer __asm__("sp"); + +#define current_thread_info() \ + ((struct thread_info *)(stack_pointer & -THREAD_SIZE)) + +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR +extern struct thread_info *alloc_thread_info(struct task_struct *task); +extern void free_thread_info(struct thread_info *info); + +/* Switch boot idle thread to a freshly-allocated stack and free old stack. */ +extern void cpu_idle_on_new_stack(struct thread_info *old_ti, + unsigned long new_sp, + unsigned long new_ss10); + +#else /* __ASSEMBLY__ */ + +/* how to get the thread information struct from ASM */ +#ifdef __tilegx__ +#define GET_THREAD_INFO(reg) move reg, sp; mm reg, zero, LOG2_THREAD_SIZE, 63 +#else +#define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31 +#endif + +#endif /* !__ASSEMBLY__ */ + +#define PREEMPT_ACTIVE 0x10000000 + +/* + * Thread information flags that various assembly files may need to access. + * Keep flags accessed frequently in low bits, particular since it makes + * it easier to build constants in assembly. + */ +#define TIF_SIGPENDING 0 /* signal pending */ +#define TIF_NEED_RESCHED 1 /* rescheduling necessary */ +#define TIF_SINGLESTEP 2 /* restore singlestep on return to + user mode */ +#define TIF_ASYNC_TLB 3 /* got an async TLB fault in kernel */ +#define TIF_SYSCALL_TRACE 4 /* syscall trace active */ +#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ +#define TIF_SECCOMP 6 /* secure computing */ +#define TIF_MEMDIE 7 /* OOM killer at work */ + +#define _TIF_SIGPENDING (1<status & TS_POLLING) + +#ifndef __ASSEMBLY__ +#define HAVE_SET_RESTORE_SIGMASK 1 +static inline void set_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + ti->status |= TS_RESTORE_SIGMASK; + set_bit(TIF_SIGPENDING, &ti->flags); +} +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_TILE_THREAD_INFO_H */ diff --git a/arch/tile/include/asm/timex.h b/arch/tile/include/asm/timex.h new file mode 100644 index 000000000000..3baf5fc4c0a1 --- /dev/null +++ b/arch/tile/include/asm/timex.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_TIMEX_H +#define _ASM_TILE_TIMEX_H + +/* + * This rate should be a multiple of the possible HZ values (100, 250, 1000) + * and a fraction of the possible hardware timer frequencies. Our timer + * frequency is highly tunable but also quite precise, so for the primary use + * of this value (setting ACT_HZ from HZ) we just pick a value that causes + * ACT_HZ to be set to HZ. We make the value somewhat large just to be + * more robust in case someone tries out a new value of HZ. + */ +#define CLOCK_TICK_RATE 1000000 + +typedef unsigned long long cycles_t; + +#if CHIP_HAS_SPLIT_CYCLE() +cycles_t get_cycles(void); +#else +static inline cycles_t get_cycles(void) +{ + return __insn_mfspr(SPR_CYCLE); +} +#endif + +cycles_t get_clock_rate(void); + +/* Called at cpu initialization to set some low-level constants. */ +void setup_clock(void); + +/* Called at cpu initialization to start the tile-timer clock device. */ +void setup_tile_timer(void); + +#endif /* _ASM_TILE_TIMEX_H */ diff --git a/arch/tile/include/asm/tlb.h b/arch/tile/include/asm/tlb.h new file mode 100644 index 000000000000..4a891a1a8df3 --- /dev/null +++ b/arch/tile/include/asm/tlb.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_TLB_H +#define _ASM_TILE_TLB_H + +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#include + +#endif /* _ASM_TILE_TLB_H */ diff --git a/arch/tile/include/asm/tlbflush.h b/arch/tile/include/asm/tlbflush.h new file mode 100644 index 000000000000..96199d214fb8 --- /dev/null +++ b/arch/tile/include/asm/tlbflush.h @@ -0,0 +1,128 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_TLBFLUSH_H +#define _ASM_TILE_TLBFLUSH_H + +#include +#include +#include +#include +#include +#include + +/* + * Rather than associating each mm with its own ASID, we just use + * ASIDs to allow us to lazily flush the TLB when we switch mms. + * This way we only have to do an actual TLB flush on mm switch + * every time we wrap ASIDs, not every single time we switch. + * + * FIXME: We might improve performance by keeping ASIDs around + * properly, though since the hypervisor direct-maps VAs to TSB + * entries, we're likely to have lost at least the executable page + * mappings by the time we switch back to the original mm. + */ +DECLARE_PER_CPU(int, current_asid); + +/* The hypervisor tells us what ASIDs are available to us. */ +extern int min_asid, max_asid; + +static inline unsigned long hv_page_size(const struct vm_area_struct *vma) +{ + return (vma->vm_flags & VM_HUGETLB) ? HPAGE_SIZE : PAGE_SIZE; +} + +/* Pass as vma pointer for non-executable mapping, if no vma available. */ +#define FLUSH_NONEXEC ((const struct vm_area_struct *)-1UL) + +/* Flush a single user page on this cpu. */ +static inline void local_flush_tlb_page(const struct vm_area_struct *vma, + unsigned long addr, + unsigned long page_size) +{ + int rc = hv_flush_page(addr, page_size); + if (rc < 0) + panic("hv_flush_page(%#lx,%#lx) failed: %d", + addr, page_size, rc); + if (!vma || (vma != FLUSH_NONEXEC && (vma->vm_flags & VM_EXEC))) + __flush_icache(); +} + +/* Flush range of user pages on this cpu. */ +static inline void local_flush_tlb_pages(const struct vm_area_struct *vma, + unsigned long addr, + unsigned long page_size, + unsigned long len) +{ + int rc = hv_flush_pages(addr, page_size, len); + if (rc < 0) + panic("hv_flush_pages(%#lx,%#lx,%#lx) failed: %d", + addr, page_size, len, rc); + if (!vma || (vma != FLUSH_NONEXEC && (vma->vm_flags & VM_EXEC))) + __flush_icache(); +} + +/* Flush all user pages on this cpu. */ +static inline void local_flush_tlb(void) +{ + int rc = hv_flush_all(1); /* preserve global mappings */ + if (rc < 0) + panic("hv_flush_all(1) failed: %d", rc); + __flush_icache(); +} + +/* + * Global pages have to be flushed a bit differently. Not a real + * performance problem because this does not happen often. + */ +static inline void local_flush_tlb_all(void) +{ + int i; + for (i = 0; ; ++i) { + HV_VirtAddrRange r = hv_inquire_virtual(i); + if (r.size == 0) + break; + local_flush_tlb_pages(NULL, r.start, PAGE_SIZE, r.size); + local_flush_tlb_pages(NULL, r.start, HPAGE_SIZE, r.size); + } +} + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + * - flush_tlb_others(cpumask, mm, va) flushes TLBs on other cpus + * + * Here (as in vm_area_struct), "end" means the first byte after + * our end address. + */ + +extern void flush_tlb_all(void); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); +extern void flush_tlb_current_task(void); +extern void flush_tlb_mm(struct mm_struct *); +extern void flush_tlb_page(const struct vm_area_struct *, unsigned long); +extern void flush_tlb_page_mm(const struct vm_area_struct *, + struct mm_struct *, unsigned long); +extern void flush_tlb_range(const struct vm_area_struct *, + unsigned long start, unsigned long end); + +#define flush_tlb() flush_tlb_current_task() + +#endif /* _ASM_TILE_TLBFLUSH_H */ diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h new file mode 100644 index 000000000000..343172d422a9 --- /dev/null +++ b/arch/tile/include/asm/topology.h @@ -0,0 +1,85 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_TOPOLOGY_H +#define _ASM_TILE_TOPOLOGY_H + +#ifdef CONFIG_NUMA + +#include + +/* Mappings between logical cpu number and node number. */ +extern struct cpumask node_2_cpu_mask[]; +extern char cpu_2_node[]; + +/* Returns the number of the node containing CPU 'cpu'. */ +static inline int cpu_to_node(int cpu) +{ + return cpu_2_node[cpu]; +} + +/* + * Returns the number of the node containing Node 'node'. + * This architecture is flat, so it is a pretty simple function! + */ +#define parent_node(node) (node) + +/* Returns a bitmask of CPUs on Node 'node'. */ +static inline const struct cpumask *cpumask_of_node(int node) +{ + return &node_2_cpu_mask[node]; +} + +/* For now, use numa node -1 for global allocation. */ +#define pcibus_to_node(bus) ((void)(bus), -1) + +/* sched_domains SD_NODE_INIT for TILE architecture */ +#define SD_NODE_INIT (struct sched_domain) { \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .busy_idx = 3, \ + .idle_idx = 1, \ + .newidle_idx = 2, \ + .wake_idx = 1, \ + .flags = SD_LOAD_BALANCE \ + | SD_BALANCE_NEWIDLE \ + | SD_BALANCE_EXEC \ + | SD_BALANCE_FORK \ + | SD_WAKE_AFFINE \ + | SD_SERIALIZE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ +} + +/* By definition, we create nodes based on online memory. */ +#define node_has_online_mem(nid) 1 + +#endif /* CONFIG_NUMA */ + +#include + +#ifdef CONFIG_SMP +#define topology_physical_package_id(cpu) ((void)(cpu), 0) +#define topology_core_id(cpu) (cpu) +#define topology_core_cpumask(cpu) ((void)(cpu), cpu_online_mask) +#define topology_thread_cpumask(cpu) cpumask_of(cpu) + +/* indicates that pointers to the topology struct cpumask maps are valid */ +#define arch_provides_topology_pointers yes +#endif + +#endif /* _ASM_TILE_TOPOLOGY_H */ diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h new file mode 100644 index 000000000000..eab33d4a917d --- /dev/null +++ b/arch/tile/include/asm/traps.h @@ -0,0 +1,36 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_TRAPS_H +#define _ASM_TILE_TRAPS_H + +/* mm/fault.c */ +void do_page_fault(struct pt_regs *, int fault_num, + unsigned long address, unsigned long write); + +/* kernel/traps.c */ +void do_trap(struct pt_regs *, int fault_num, unsigned long reason); + +/* kernel/time.c */ +void do_timer_interrupt(struct pt_regs *, int fault_num); + +/* kernel/messaging.c */ +void hv_message_intr(struct pt_regs *, int intnum); + +/* kernel/irq.c */ +void tile_dev_intr(struct pt_regs *, int intnum); + + + +#endif /* _ASM_TILE_SYSCALLS_H */ diff --git a/arch/tile/include/asm/types.h b/arch/tile/include/asm/types.h new file mode 100644 index 000000000000..b9e79bc580dd --- /dev/null +++ b/arch/tile/include/asm/types.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h new file mode 100644 index 000000000000..f3058afd5a88 --- /dev/null +++ b/arch/tile/include/asm/uaccess.h @@ -0,0 +1,578 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_UACCESS_H +#define _ASM_TILE_UACCESS_H + +/* + * User space memory access functions + */ +#include +#include +#include +#include +#include + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + */ +#define MAKE_MM_SEG(a) ((mm_segment_t) { (a) }) + +#define KERNEL_DS MAKE_MM_SEG(-1UL) +#define USER_DS MAKE_MM_SEG(PAGE_OFFSET) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(x) (current_thread_info()->addr_limit = (x)) + +#define segment_eq(a, b) ((a).seg == (b).seg) + +#ifndef __tilegx__ +/* + * We could allow mapping all 16 MB at 0xfc000000, but we set up a + * special hack in arch_setup_additional_pages() to auto-create a mapping + * for the first 16 KB, and it would seem strange to have different + * user-accessible semantics for memory at 0xfc000000 and above 0xfc004000. + */ +static inline int is_arch_mappable_range(unsigned long addr, + unsigned long size) +{ + return (addr >= MEM_USER_INTRPT && + addr < (MEM_USER_INTRPT + INTRPT_SIZE) && + size <= (MEM_USER_INTRPT + INTRPT_SIZE) - addr); +} +#define is_arch_mappable_range is_arch_mappable_range +#else +#define is_arch_mappable_range(addr, size) 0 +#endif + +/* + * Test whether a block of memory is a valid user space address. + * Returns 0 if the range is valid, nonzero otherwise. + */ +int __range_ok(unsigned long addr, unsigned long size); + +/** + * access_ok: - Checks if a user space pointer is valid + * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that + * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe + * to write to a block, it is always safe to read from it. + * @addr: User space pointer to start of block to check + * @size: Size of block to check + * + * Context: User context only. This function may sleep. + * + * Checks if a pointer to a block of memory in user space is valid. + * + * Returns true (nonzero) if the memory block may be valid, false (zero) + * if it is definitely invalid. + * + * Note that, depending on architecture, this function probably just + * checks that the pointer is in the user space range - after calling + * this function, memory access functions may still return -EFAULT. + */ +#define access_ok(type, addr, size) \ + (likely(__range_ok((unsigned long)addr, size) == 0)) + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + unsigned long insn, fixup; +}; + +extern int fixup_exception(struct pt_regs *regs); + +/* + * We return the __get_user_N function results in a structure, + * thus in r0 and r1. If "err" is zero, "val" is the result + * of the read; otherwise, "err" is -EFAULT. + * + * We rarely need 8-byte values on a 32-bit architecture, but + * we size the structure to accommodate. In practice, for the + * the smaller reads, we can zero the high word for free, and + * the caller will ignore it by virtue of casting anyway. + */ +struct __get_user { + unsigned long long val; + int err; +}; + +/* + * FIXME: we should express these as inline extended assembler, since + * they're fundamentally just a variable dereference and some + * supporting exception_table gunk. Note that (a la i386) we can + * extend the copy_to_user and copy_from_user routines to call into + * such extended assembler routines, though we will have to use a + * different return code in that case (1, 2, or 4, rather than -EFAULT). + */ +extern struct __get_user __get_user_1(const void *); +extern struct __get_user __get_user_2(const void *); +extern struct __get_user __get_user_4(const void *); +extern struct __get_user __get_user_8(const void *); +extern int __put_user_1(long, void *); +extern int __put_user_2(long, void *); +extern int __put_user_4(long, void *); +extern int __put_user_8(long long, void *); + +/* Unimplemented routines to cause linker failures */ +extern struct __get_user __get_user_bad(void); +extern int __put_user_bad(void); + +/* + * Careful: we have to cast the result to the type of the pointer + * for sign reasons. + */ +/** + * __get_user: - Get a simple variable from user space, with less checking. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + * + * Caller must check the pointer with access_ok() before calling this + * function. + */ +#define __get_user(x, ptr) \ +({ struct __get_user __ret; \ + __typeof__(*(ptr)) const __user *__gu_addr = (ptr); \ + __chk_user_ptr(__gu_addr); \ + switch (sizeof(*(__gu_addr))) { \ + case 1: \ + __ret = __get_user_1(__gu_addr); \ + break; \ + case 2: \ + __ret = __get_user_2(__gu_addr); \ + break; \ + case 4: \ + __ret = __get_user_4(__gu_addr); \ + break; \ + case 8: \ + __ret = __get_user_8(__gu_addr); \ + break; \ + default: \ + __ret = __get_user_bad(); \ + break; \ + } \ + (x) = (__typeof__(*__gu_addr)) (__typeof__(*__gu_addr - *__gu_addr)) \ + __ret.val; \ + __ret.err; \ +}) + +/** + * __put_user: - Write a simple value into user space, with less checking. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + * + * Implementation note: The "case 8" logic of casting to the type of + * the result of subtracting the value from itself is basically a way + * of keeping all integer types the same, but casting any pointers to + * ptrdiff_t, i.e. also an integer type. This way there are no + * questionable casts seen by the compiler on an ILP32 platform. + */ +#define __put_user(x, ptr) \ +({ \ + int __pu_err = 0; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + typeof(*__pu_addr) __pu_val = (x); \ + __chk_user_ptr(__pu_addr); \ + switch (sizeof(__pu_val)) { \ + case 1: \ + __pu_err = __put_user_1((long)__pu_val, __pu_addr); \ + break; \ + case 2: \ + __pu_err = __put_user_2((long)__pu_val, __pu_addr); \ + break; \ + case 4: \ + __pu_err = __put_user_4((long)__pu_val, __pu_addr); \ + break; \ + case 8: \ + __pu_err = \ + __put_user_8((__typeof__(__pu_val - __pu_val))__pu_val,\ + __pu_addr); \ + break; \ + default: \ + __pu_err = __put_user_bad(); \ + break; \ + } \ + __pu_err; \ +}) + +/* + * The versions of get_user and put_user without initial underscores + * check the address of their arguments to make sure they are not + * in kernel space. + */ +#define put_user(x, ptr) \ +({ \ + __typeof__(*(ptr)) __user *__Pu_addr = (ptr); \ + access_ok(VERIFY_WRITE, (__Pu_addr), sizeof(*(__Pu_addr))) ? \ + __put_user((x), (__Pu_addr)) : \ + -EFAULT; \ +}) + +#define get_user(x, ptr) \ +({ \ + __typeof__(*(ptr)) const __user *__Gu_addr = (ptr); \ + access_ok(VERIFY_READ, (__Gu_addr), sizeof(*(__Gu_addr))) ? \ + __get_user((x), (__Gu_addr)) : \ + ((x) = 0, -EFAULT); \ +}) + +/** + * __copy_to_user() - copy data into user space, with less checking. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from kernel space to user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * An alternate version - __copy_to_user_inatomic() - is designed + * to be called from atomic context, typically bracketed by calls + * to pagefault_disable() and pagefault_enable(). + */ +extern unsigned long __must_check __copy_to_user_inatomic( + void __user *to, const void *from, unsigned long n); + +static inline unsigned long __must_check +__copy_to_user(void __user *to, const void *from, unsigned long n) +{ + might_fault(); + return __copy_to_user_inatomic(to, from, n); +} + +static inline unsigned long __must_check +copy_to_user(void __user *to, const void *from, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + n = __copy_to_user(to, from, n); + return n; +} + +/** + * __copy_from_user() - copy data from user space, with less checking. + * @to: Destination address, in kernel space. + * @from: Source address, in user space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to kernel space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + * + * An alternate version - __copy_from_user_inatomic() - is designed + * to be called from atomic context, typically bracketed by calls + * to pagefault_disable() and pagefault_enable(). This version + * does *NOT* pad with zeros. + */ +extern unsigned long __must_check __copy_from_user_inatomic( + void *to, const void __user *from, unsigned long n); +extern unsigned long __must_check __copy_from_user_zeroing( + void *to, const void __user *from, unsigned long n); + +static inline unsigned long __must_check +__copy_from_user(void *to, const void __user *from, unsigned long n) +{ + might_fault(); + return __copy_from_user_zeroing(to, from, n); +} + +static inline unsigned long __must_check +_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + if (access_ok(VERIFY_READ, from, n)) + n = __copy_from_user(to, from, n); + else + memset(to, 0, n); + return n; +} + +#ifdef CONFIG_DEBUG_COPY_FROM_USER +extern void copy_from_user_overflow(void) + __compiletime_warning("copy_from_user() size is not provably correct"); + +static inline unsigned long __must_check copy_from_user(void *to, + const void __user *from, + unsigned long n) +{ + int sz = __compiletime_object_size(to); + + if (likely(sz == -1 || sz >= n)) + n = _copy_from_user(to, from, n); + else + copy_from_user_overflow(); + + return n; +} +#else +#define copy_from_user _copy_from_user +#endif + +#ifdef __tilegx__ +/** + * __copy_in_user() - copy data within user space, with less checking. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to user space. Caller must check + * the specified blocks with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +extern unsigned long __copy_in_user_asm( + void __user *to, const void __user *from, unsigned long n); + +static inline unsigned long __must_check +__copy_in_user(void __user *to, const void __user *from, unsigned long n) +{ + might_sleep(); + return __copy_in_user_asm(to, from, n); +} + +static inline unsigned long __must_check +copy_in_user(void __user *to, const void __user *from, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n)) + n = __copy_in_user(to, from, n); + return n; +} +#endif + + +/** + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +extern long strnlen_user_asm(const char __user *str, long n); +static inline long __must_check strnlen_user(const char __user *str, long n) +{ + might_fault(); + return strnlen_user_asm(str, n); +} +#define strlen_user(str) strnlen_user(str, LONG_MAX) + +/** + * strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * Caller must check the specified block with access_ok() before calling + * this function. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +extern long strncpy_from_user_asm(char *dst, const char __user *src, long); +static inline long __must_check __strncpy_from_user( + char *dst, const char __user *src, long count) +{ + might_fault(); + return strncpy_from_user_asm(dst, src, count); +} +static inline long __must_check strncpy_from_user( + char *dst, const char __user *src, long count) +{ + if (access_ok(VERIFY_READ, src, 1)) + return __strncpy_from_user(dst, src, count); + return -EFAULT; +} + +/** + * clear_user: - Zero a block of memory in user space. + * @mem: Destination address, in user space. + * @len: Number of bytes to zero. + * + * Zero a block of memory in user space. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +extern unsigned long clear_user_asm(void __user *mem, unsigned long len); +static inline unsigned long __must_check __clear_user( + void __user *mem, unsigned long len) +{ + might_fault(); + return clear_user_asm(mem, len); +} +static inline unsigned long __must_check clear_user( + void __user *mem, unsigned long len) +{ + if (access_ok(VERIFY_WRITE, mem, len)) + return __clear_user(mem, len); + return len; +} + +/** + * flush_user: - Flush a block of memory in user space from cache. + * @mem: Destination address, in user space. + * @len: Number of bytes to flush. + * + * Returns number of bytes that could not be flushed. + * On success, this will be zero. + */ +extern unsigned long flush_user_asm(void __user *mem, unsigned long len); +static inline unsigned long __must_check __flush_user( + void __user *mem, unsigned long len) +{ + int retval; + + might_fault(); + retval = flush_user_asm(mem, len); + mb_incoherent(); + return retval; +} + +static inline unsigned long __must_check flush_user( + void __user *mem, unsigned long len) +{ + if (access_ok(VERIFY_WRITE, mem, len)) + return __flush_user(mem, len); + return len; +} + +/** + * inv_user: - Invalidate a block of memory in user space from cache. + * @mem: Destination address, in user space. + * @len: Number of bytes to invalidate. + * + * Returns number of bytes that could not be invalidated. + * On success, this will be zero. + * + * Note that on Tile64, the "inv" operation is in fact a + * "flush and invalidate", so cache write-backs will occur prior + * to the cache being marked invalid. + */ +extern unsigned long inv_user_asm(void __user *mem, unsigned long len); +static inline unsigned long __must_check __inv_user( + void __user *mem, unsigned long len) +{ + int retval; + + might_fault(); + retval = inv_user_asm(mem, len); + mb_incoherent(); + return retval; +} +static inline unsigned long __must_check inv_user( + void __user *mem, unsigned long len) +{ + if (access_ok(VERIFY_WRITE, mem, len)) + return __inv_user(mem, len); + return len; +} + +/** + * finv_user: - Flush-inval a block of memory in user space from cache. + * @mem: Destination address, in user space. + * @len: Number of bytes to invalidate. + * + * Returns number of bytes that could not be flush-invalidated. + * On success, this will be zero. + */ +extern unsigned long finv_user_asm(void __user *mem, unsigned long len); +static inline unsigned long __must_check __finv_user( + void __user *mem, unsigned long len) +{ + int retval; + + might_fault(); + retval = finv_user_asm(mem, len); + mb_incoherent(); + return retval; +} +static inline unsigned long __must_check finv_user( + void __user *mem, unsigned long len) +{ + if (access_ok(VERIFY_WRITE, mem, len)) + return __finv_user(mem, len); + return len; +} + +#endif /* _ASM_TILE_UACCESS_H */ diff --git a/arch/tile/include/asm/ucontext.h b/arch/tile/include/asm/ucontext.h new file mode 100644 index 000000000000..9bc07b9f30fb --- /dev/null +++ b/arch/tile/include/asm/ucontext.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/asm/unaligned.h b/arch/tile/include/asm/unaligned.h new file mode 100644 index 000000000000..137e2de5b102 --- /dev/null +++ b/arch/tile/include/asm/unaligned.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#ifndef _ASM_TILE_UNALIGNED_H +#define _ASM_TILE_UNALIGNED_H + +#include +#include +#include +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le + +#endif /* _ASM_TILE_UNALIGNED_H */ diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h new file mode 100644 index 000000000000..03b3d5d665dd --- /dev/null +++ b/arch/tile/include/asm/unistd.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#if !defined(_ASM_TILE_UNISTD_H) || defined(__SYSCALL) +#define _ASM_TILE_UNISTD_H + + +#ifndef __LP64__ +/* Use the flavor of this syscall that matches the 32-bit API better. */ +#define __ARCH_WANT_SYNC_FILE_RANGE2 +#endif + +/* Use the standard ABI for syscalls. */ +#include + +#ifndef __tilegx__ +/* "Fast" syscalls provide atomic support for 32-bit chips. */ +#define __NR_FAST_cmpxchg -1 +#define __NR_FAST_atomic_update -2 +#define __NR_FAST_cmpxchg64 -3 +#define __NR_cmpxchg_badaddr (__NR_arch_specific_syscall + 0) +__SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr) +#endif + +/* Additional Tilera-specific syscalls. */ +#define __NR_flush_cache (__NR_arch_specific_syscall + 1) +__SYSCALL(__NR_flush_cache, sys_flush_cache) + +#ifdef __KERNEL__ +/* In compat mode, we use sys_llseek() for compat_sys_llseek(). */ +#ifdef CONFIG_COMPAT +#define __ARCH_WANT_SYS_LLSEEK +#endif +#endif + +#endif /* _ASM_TILE_UNISTD_H */ diff --git a/arch/tile/include/asm/user.h b/arch/tile/include/asm/user.h new file mode 100644 index 000000000000..cbc8b4d5a5ce --- /dev/null +++ b/arch/tile/include/asm/user.h @@ -0,0 +1,21 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ASM_TILE_USER_H +#define _ASM_TILE_USER_H + +/* This header is for a.out file formats, which TILE does not support. */ + +#endif /* _ASM_TILE_USER_H */ diff --git a/arch/tile/include/asm/xor.h b/arch/tile/include/asm/xor.h new file mode 100644 index 000000000000..c82eb12a5b18 --- /dev/null +++ b/arch/tile/include/asm/xor.h @@ -0,0 +1 @@ +#include diff --git a/arch/tile/include/hv/drv_pcie_rc_intf.h b/arch/tile/include/hv/drv_pcie_rc_intf.h new file mode 100644 index 000000000000..9bd2243bece0 --- /dev/null +++ b/arch/tile/include/hv/drv_pcie_rc_intf.h @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/** + * @file drv_pcie_rc_intf.h + * Interface definitions for the PCIE Root Complex. + */ + +#ifndef _SYS_HV_DRV_PCIE_RC_INTF_H +#define _SYS_HV_DRV_PCIE_RC_INTF_H + +/** File offset for reading the interrupt base number used for PCIE legacy + interrupts and PLX Gen 1 requirement flag */ +#define PCIE_RC_CONFIG_MASK_OFF 0 + + +/** + * Structure used for obtaining PCIe config information, read from the PCIE + * subsystem /ctl file at initialization + */ +typedef struct pcie_rc_config +{ + int intr; /**< interrupt number used for downcall */ + int plx_gen1; /**< flag for PLX Gen 1 configuration */ +} pcie_rc_config_t; + +#endif /* _SYS_HV_DRV_PCIE_RC_INTF_H */ diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h new file mode 100644 index 000000000000..84b31551080a --- /dev/null +++ b/arch/tile/include/hv/hypervisor.h @@ -0,0 +1,2366 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/** + * @file hypervisor.h + * The hypervisor's public API. + */ + +#ifndef _TILE_HV_H +#define _TILE_HV_H + +#ifdef __tile__ +#include +#else +/* HACK: Allow use by "tools/cpack/". */ +#include "install/include/arch/chip.h" +#endif + +/* Linux builds want unsigned long constants, but assembler wants numbers */ +#ifdef __ASSEMBLER__ +/** One, for assembler */ +#define __HV_SIZE_ONE 1 +#elif !defined(__tile__) && CHIP_VA_WIDTH() > 32 +/** One, for 64-bit on host */ +#define __HV_SIZE_ONE 1ULL +#else +/** One, for Linux */ +#define __HV_SIZE_ONE 1UL +#endif + + +/** The log2 of the span of a level-1 page table, in bytes. + */ +#define HV_LOG2_L1_SPAN 32 + +/** The span of a level-1 page table, in bytes. + */ +#define HV_L1_SPAN (__HV_SIZE_ONE << HV_LOG2_L1_SPAN) + +/** The log2 of the size of small pages, in bytes. This value should + * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). + */ +#define HV_LOG2_PAGE_SIZE_SMALL 16 + +/** The size of small pages, in bytes. This value should be verified + * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). + */ +#define HV_PAGE_SIZE_SMALL (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_SMALL) + +/** The log2 of the size of large pages, in bytes. This value should be + * verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). + */ +#define HV_LOG2_PAGE_SIZE_LARGE 24 + +/** The size of large pages, in bytes. This value should be verified + * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). + */ +#define HV_PAGE_SIZE_LARGE (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_LARGE) + +/** The log2 of the granularity at which page tables must be aligned; + * in other words, the CPA for a page table must have this many zero + * bits at the bottom of the address. + */ +#define HV_LOG2_PAGE_TABLE_ALIGN 11 + +/** The granularity at which page tables must be aligned. + */ +#define HV_PAGE_TABLE_ALIGN (__HV_SIZE_ONE << HV_LOG2_PAGE_TABLE_ALIGN) + +/** Normal start of hypervisor glue in client physical memory. */ +#define HV_GLUE_START_CPA 0x10000 + +/** This much space is reserved at HV_GLUE_START_CPA + * for the hypervisor glue. The client program must start at + * some address higher than this, and in particular the address of + * its text section should be equal to zero modulo HV_PAGE_SIZE_LARGE + * so that relative offsets to the HV glue are correct. + */ +#define HV_GLUE_RESERVED_SIZE 0x10000 + +/** Each entry in the hv dispatch array takes this many bytes. */ +#define HV_DISPATCH_ENTRY_SIZE 32 + +/** Version of the hypervisor interface defined by this file */ +#define _HV_VERSION 10 + +/* Index into hypervisor interface dispatch code blocks. + * + * Hypervisor calls are invoked from user space by calling code + * at an address HV_BASE_ADDRESS + (index) * HV_DISPATCH_ENTRY_SIZE, + * where index is one of these enum values. + * + * Normally a supervisor is expected to produce a set of symbols + * starting at HV_BASE_ADDRESS that obey this convention, but a user + * program could call directly through function pointers if desired. + * + * These numbers are part of the binary API and will not be changed + * without updating HV_VERSION, which should be a rare event. + */ + +/** reserved. */ +#define _HV_DISPATCH_RESERVED 0 + +/** hv_init */ +#define HV_DISPATCH_INIT 1 + +/** hv_install_context */ +#define HV_DISPATCH_INSTALL_CONTEXT 2 + +/** hv_sysconf */ +#define HV_DISPATCH_SYSCONF 3 + +/** hv_get_rtc */ +#define HV_DISPATCH_GET_RTC 4 + +/** hv_set_rtc */ +#define HV_DISPATCH_SET_RTC 5 + +/** hv_flush_asid */ +#define HV_DISPATCH_FLUSH_ASID 6 + +/** hv_flush_page */ +#define HV_DISPATCH_FLUSH_PAGE 7 + +/** hv_flush_pages */ +#define HV_DISPATCH_FLUSH_PAGES 8 + +/** hv_restart */ +#define HV_DISPATCH_RESTART 9 + +/** hv_halt */ +#define HV_DISPATCH_HALT 10 + +/** hv_power_off */ +#define HV_DISPATCH_POWER_OFF 11 + +/** hv_inquire_physical */ +#define HV_DISPATCH_INQUIRE_PHYSICAL 12 + +/** hv_inquire_memory_controller */ +#define HV_DISPATCH_INQUIRE_MEMORY_CONTROLLER 13 + +/** hv_inquire_virtual */ +#define HV_DISPATCH_INQUIRE_VIRTUAL 14 + +/** hv_inquire_asid */ +#define HV_DISPATCH_INQUIRE_ASID 15 + +/** hv_nanosleep */ +#define HV_DISPATCH_NANOSLEEP 16 + +/** hv_console_read_if_ready */ +#define HV_DISPATCH_CONSOLE_READ_IF_READY 17 + +/** hv_console_write */ +#define HV_DISPATCH_CONSOLE_WRITE 18 + +/** hv_downcall_dispatch */ +#define HV_DISPATCH_DOWNCALL_DISPATCH 19 + +/** hv_inquire_topology */ +#define HV_DISPATCH_INQUIRE_TOPOLOGY 20 + +/** hv_fs_findfile */ +#define HV_DISPATCH_FS_FINDFILE 21 + +/** hv_fs_fstat */ +#define HV_DISPATCH_FS_FSTAT 22 + +/** hv_fs_pread */ +#define HV_DISPATCH_FS_PREAD 23 + +/** hv_physaddr_read64 */ +#define HV_DISPATCH_PHYSADDR_READ64 24 + +/** hv_physaddr_write64 */ +#define HV_DISPATCH_PHYSADDR_WRITE64 25 + +/** hv_get_command_line */ +#define HV_DISPATCH_GET_COMMAND_LINE 26 + +/** hv_set_caching */ +#define HV_DISPATCH_SET_CACHING 27 + +/** hv_bzero_page */ +#define HV_DISPATCH_BZERO_PAGE 28 + +/** hv_register_message_state */ +#define HV_DISPATCH_REGISTER_MESSAGE_STATE 29 + +/** hv_send_message */ +#define HV_DISPATCH_SEND_MESSAGE 30 + +/** hv_receive_message */ +#define HV_DISPATCH_RECEIVE_MESSAGE 31 + +/** hv_inquire_context */ +#define HV_DISPATCH_INQUIRE_CONTEXT 32 + +/** hv_start_all_tiles */ +#define HV_DISPATCH_START_ALL_TILES 33 + +/** hv_dev_open */ +#define HV_DISPATCH_DEV_OPEN 34 + +/** hv_dev_close */ +#define HV_DISPATCH_DEV_CLOSE 35 + +/** hv_dev_pread */ +#define HV_DISPATCH_DEV_PREAD 36 + +/** hv_dev_pwrite */ +#define HV_DISPATCH_DEV_PWRITE 37 + +/** hv_dev_poll */ +#define HV_DISPATCH_DEV_POLL 38 + +/** hv_dev_poll_cancel */ +#define HV_DISPATCH_DEV_POLL_CANCEL 39 + +/** hv_dev_preada */ +#define HV_DISPATCH_DEV_PREADA 40 + +/** hv_dev_pwritea */ +#define HV_DISPATCH_DEV_PWRITEA 41 + +/** hv_flush_remote */ +#define HV_DISPATCH_FLUSH_REMOTE 42 + +/** hv_console_putc */ +#define HV_DISPATCH_CONSOLE_PUTC 43 + +/** hv_inquire_tiles */ +#define HV_DISPATCH_INQUIRE_TILES 44 + +/** hv_confstr */ +#define HV_DISPATCH_CONFSTR 45 + +/** hv_reexec */ +#define HV_DISPATCH_REEXEC 46 + +/** hv_set_command_line */ +#define HV_DISPATCH_SET_COMMAND_LINE 47 + +/** hv_dev_register_intr_state */ +#define HV_DISPATCH_DEV_REGISTER_INTR_STATE 48 + +/** hv_enable_intr */ +#define HV_DISPATCH_ENABLE_INTR 49 + +/** hv_disable_intr */ +#define HV_DISPATCH_DISABLE_INTR 50 + +/** hv_trigger_ipi */ +#define HV_DISPATCH_TRIGGER_IPI 51 + +/** hv_store_mapping */ +#define HV_DISPATCH_STORE_MAPPING 52 + +/** hv_inquire_realpa */ +#define HV_DISPATCH_INQUIRE_REALPA 53 + +/** hv_flush_all */ +#define HV_DISPATCH_FLUSH_ALL 54 + +/** One more than the largest dispatch value */ +#define _HV_DISPATCH_END 55 + + +#ifndef __ASSEMBLER__ + +#ifdef __KERNEL__ +#include +typedef u32 __hv32; /**< 32-bit value */ +typedef u64 __hv64; /**< 64-bit value */ +#else +#include +typedef uint32_t __hv32; /**< 32-bit value */ +typedef uint64_t __hv64; /**< 64-bit value */ +#endif + + +/** Hypervisor physical address. */ +typedef __hv64 HV_PhysAddr; + +#if CHIP_VA_WIDTH() > 32 +/** Hypervisor virtual address. */ +typedef __hv64 HV_VirtAddr; +#else +/** Hypervisor virtual address. */ +typedef __hv32 HV_VirtAddr; +#endif /* CHIP_VA_WIDTH() > 32 */ + +/** Hypervisor ASID. */ +typedef unsigned int HV_ASID; + +/** Hypervisor tile location for a memory access + * ("location overridden target"). + */ +typedef unsigned int HV_LOTAR; + +/** Hypervisor size of a page. */ +typedef unsigned long HV_PageSize; + +/** A page table entry. + */ +typedef struct +{ + __hv64 val; /**< Value of PTE */ +} HV_PTE; + +/** Hypervisor error code. */ +typedef int HV_Errno; + +#endif /* !__ASSEMBLER__ */ + +#define HV_OK 0 /**< No error */ +#define HV_EINVAL -801 /**< Invalid argument */ +#define HV_ENODEV -802 /**< No such device */ +#define HV_ENOENT -803 /**< No such file or directory */ +#define HV_EBADF -804 /**< Bad file number */ +#define HV_EFAULT -805 /**< Bad address */ +#define HV_ERECIP -806 /**< Bad recipients */ +#define HV_E2BIG -807 /**< Message too big */ +#define HV_ENOTSUP -808 /**< Service not supported */ +#define HV_EBUSY -809 /**< Device busy */ +#define HV_ENOSYS -810 /**< Invalid syscall */ +#define HV_EPERM -811 /**< No permission */ +#define HV_ENOTREADY -812 /**< Device not ready */ +#define HV_EIO -813 /**< I/O error */ +#define HV_ENOMEM -814 /**< Out of memory */ + +#define HV_ERR_MAX -801 /**< Largest HV error code */ +#define HV_ERR_MIN -814 /**< Smallest HV error code */ + +#ifndef __ASSEMBLER__ + +/** Pass HV_VERSION to hv_init to request this version of the interface. */ +typedef enum { HV_VERSION = _HV_VERSION } HV_VersionNumber; + +/** Initializes the hypervisor. + * + * @param interface_version_number The version of the hypervisor interface + * that this program expects, typically HV_VERSION. + * @param chip_num Architecture number of the chip the client was built for. + * @param chip_rev_num Revision number of the chip the client was built for. + */ +void hv_init(HV_VersionNumber interface_version_number, + int chip_num, int chip_rev_num); + + +/** Queries we can make for hv_sysconf(). + * + * These numbers are part of the binary API and guaranteed not to change. + */ +typedef enum { + /** An invalid value; do not use. */ + _HV_SYSCONF_RESERVED = 0, + + /** The length of the glue section containing the hv_ procs, in bytes. */ + HV_SYSCONF_GLUE_SIZE = 1, + + /** The size of small pages, in bytes. */ + HV_SYSCONF_PAGE_SIZE_SMALL = 2, + + /** The size of large pages, in bytes. */ + HV_SYSCONF_PAGE_SIZE_LARGE = 3, + + /** Processor clock speed, in hertz. */ + HV_SYSCONF_CPU_SPEED = 4, + + /** Processor temperature, in degrees Kelvin. The value + * HV_SYSCONF_TEMP_KTOC may be subtracted from this to get degrees + * Celsius. If that Celsius value is HV_SYSCONF_OVERTEMP, this indicates + * that the temperature has hit an upper limit and is no longer being + * accurately tracked. + */ + HV_SYSCONF_CPU_TEMP = 5, + + /** Board temperature, in degrees Kelvin. The value + * HV_SYSCONF_TEMP_KTOC may be subtracted from this to get degrees + * Celsius. If that Celsius value is HV_SYSCONF_OVERTEMP, this indicates + * that the temperature has hit an upper limit and is no longer being + * accurately tracked. + */ + HV_SYSCONF_BOARD_TEMP = 6 + +} HV_SysconfQuery; + +/** Offset to subtract from returned Kelvin temperature to get degrees + Celsius. */ +#define HV_SYSCONF_TEMP_KTOC 273 + +/** Pseudo-temperature value indicating that the temperature has + * pegged at its upper limit and is no longer accurate; note that this is + * the value after subtracting HV_SYSCONF_TEMP_KTOC. */ +#define HV_SYSCONF_OVERTEMP 999 + +/** Query a configuration value from the hypervisor. + * @param query Which value is requested (HV_SYSCONF_xxx). + * @return The requested value, or -1 the requested value is illegal or + * unavailable. + */ +long hv_sysconf(HV_SysconfQuery query); + + +/** Queries we can make for hv_confstr(). + * + * These numbers are part of the binary API and guaranteed not to change. + */ +typedef enum { + /** An invalid value; do not use. */ + _HV_CONFSTR_RESERVED = 0, + + /** Board part number. */ + HV_CONFSTR_BOARD_PART_NUM = 1, + + /** Board serial number. */ + HV_CONFSTR_BOARD_SERIAL_NUM = 2, + + /** Chip serial number. */ + HV_CONFSTR_CHIP_SERIAL_NUM = 3, + + /** Board revision level. */ + HV_CONFSTR_BOARD_REV = 4, + + /** Hypervisor software version. */ + HV_CONFSTR_HV_SW_VER = 5, + + /** The name for this chip model. */ + HV_CONFSTR_CHIP_MODEL = 6, + + /** Human-readable board description. */ + HV_CONFSTR_BOARD_DESC = 7, + + /** Human-readable description of the hypervisor configuration. */ + HV_CONFSTR_HV_CONFIG = 8, + + /** Human-readable version string for the boot image (for instance, + * who built it and when, what configuration file was used). */ + HV_CONFSTR_HV_CONFIG_VER = 9, + + /** Mezzanine part number. */ + HV_CONFSTR_MEZZ_PART_NUM = 10, + + /** Mezzanine serial number. */ + HV_CONFSTR_MEZZ_SERIAL_NUM = 11, + + /** Mezzanine revision level. */ + HV_CONFSTR_MEZZ_REV = 12, + + /** Human-readable mezzanine description. */ + HV_CONFSTR_MEZZ_DESC = 13, + + /** Control path for the onboard network switch. */ + HV_CONFSTR_SWITCH_CONTROL = 14, + + /** Chip revision level. */ + HV_CONFSTR_CHIP_REV = 15 + +} HV_ConfstrQuery; + +/** Query a configuration string from the hypervisor. + * + * @param query Identifier for the specific string to be retrieved + * (HV_CONFSTR_xxx). + * @param buf Buffer in which to place the string. + * @param len Length of the buffer. + * @return If query is valid, then the length of the corresponding string, + * including the trailing null; if this is greater than len, the string + * was truncated. If query is invalid, HV_EINVAL. If the specified + * buffer is not writable by the client, HV_EFAULT. + */ +int hv_confstr(HV_ConfstrQuery query, HV_VirtAddr buf, int len); + +/** State object used to enable and disable one-shot and level-sensitive + * interrupts. */ +typedef struct +{ +#if CHIP_VA_WIDTH() > 32 + __hv64 opaque[2]; /**< No user-serviceable parts inside */ +#else + __hv32 opaque[2]; /**< No user-serviceable parts inside */ +#endif +} +HV_IntrState; + +/** A set of interrupts. */ +typedef __hv32 HV_IntrMask; + +/** Tile coordinate */ +typedef struct +{ + /** X coordinate, relative to supervisor's top-left coordinate */ + int x; + + /** Y coordinate, relative to supervisor's top-left coordinate */ + int y; +} HV_Coord; + +/** The low interrupt numbers are reserved for use by the client in + * delivering IPIs. Any interrupt numbers higher than this value are + * reserved for use by HV device drivers. */ +#define HV_MAX_IPI_INTERRUPT 7 + +/** Register an interrupt state object. This object is used to enable and + * disable one-shot and level-sensitive interrupts. Once the state is + * registered, the client must not read or write the state object; doing + * so will cause undefined results. + * + * @param intr_state Pointer to interrupt state object. + * @return HV_OK on success, or a hypervisor error code. + */ +HV_Errno hv_dev_register_intr_state(HV_IntrState* intr_state); + +/** Enable a set of one-shot and level-sensitive interrupts. + * + * @param intr_state Pointer to interrupt state object. + * @param enab_mask Bitmap of interrupts to enable. + */ +void hv_enable_intr(HV_IntrState* intr_state, HV_IntrMask enab_mask); + +/** Disable a set of one-shot and level-sensitive interrupts. + * + * @param intr_state Pointer to interrupt state object. + * @param disab_mask Bitmap of interrupts to disable. + */ +void hv_disable_intr(HV_IntrState* intr_state, HV_IntrMask disab_mask); + +/** Trigger a one-shot interrupt on some tile + * + * @param tile Which tile to interrupt. + * @param interrupt Interrupt number to trigger; must be between 0 and + * HV_MAX_IPI_INTERRUPT. + * @return HV_OK on success, or a hypervisor error code. + */ +HV_Errno hv_trigger_ipi(HV_Coord tile, int interrupt); + +/** Store memory mapping in debug memory so that external debugger can read it. + * A maximum of 16 entries can be stored. + * + * @param va VA of memory that is mapped. + * @param len Length of mapped memory. + * @param pa PA of memory that is mapped. + * @return 0 on success, -1 if the maximum number of mappings is exceeded. + */ +int hv_store_mapping(HV_VirtAddr va, unsigned int len, HV_PhysAddr pa); + +/** Given a client PA and a length, return its real (HV) PA. + * + * @param cpa Client physical address. + * @param len Length of mapped memory. + * @return physical address, or -1 if cpa or len is not valid. + */ +HV_PhysAddr hv_inquire_realpa(HV_PhysAddr cpa, unsigned int len); + +/** RTC return flag for no RTC chip present. + */ +#define HV_RTC_NO_CHIP 0x1 + +/** RTC return flag for low-voltage condition, indicating that battery had + * died and time read is unreliable. + */ +#define HV_RTC_LOW_VOLTAGE 0x2 + +/** Date/Time of day */ +typedef struct { +#if CHIP_WORD_SIZE() > 32 + __hv64 tm_sec; /**< Seconds, 0-59 */ + __hv64 tm_min; /**< Minutes, 0-59 */ + __hv64 tm_hour; /**< Hours, 0-23 */ + __hv64 tm_mday; /**< Day of month, 0-30 */ + __hv64 tm_mon; /**< Month, 0-11 */ + __hv64 tm_year; /**< Years since 1900, 0-199 */ + __hv64 flags; /**< Return flags, 0 if no error */ +#else + __hv32 tm_sec; /**< Seconds, 0-59 */ + __hv32 tm_min; /**< Minutes, 0-59 */ + __hv32 tm_hour; /**< Hours, 0-23 */ + __hv32 tm_mday; /**< Day of month, 0-30 */ + __hv32 tm_mon; /**< Month, 0-11 */ + __hv32 tm_year; /**< Years since 1900, 0-199 */ + __hv32 flags; /**< Return flags, 0 if no error */ +#endif +} HV_RTCTime; + +/** Read the current time-of-day clock. + * @return HV_RTCTime of current time (GMT). + */ +HV_RTCTime hv_get_rtc(void); + + +/** Set the current time-of-day clock. + * @param time time to reset time-of-day to (GMT). + */ +void hv_set_rtc(HV_RTCTime time); + +/** Installs a context, comprising a page table and other attributes. + * + * Once this service completes, page_table will be used to translate + * subsequent virtual address references to physical memory. + * + * Installing a context does not cause an implicit TLB flush. Before + * reusing an ASID value for a different address space, the client is + * expected to flush old references from the TLB with hv_flush_asid(). + * (Alternately, hv_flush_all() may be used to flush many ASIDs at once.) + * After invalidating a page table entry, changing its attributes, or + * changing its target CPA, the client is expected to flush old references + * from the TLB with hv_flush_page() or hv_flush_pages(). Making a + * previously invalid page valid does not require a flush. + * + * Specifying an invalid ASID, or an invalid CPA (client physical address) + * (either as page_table_pointer, or within the referenced table), + * or another page table data item documented as above as illegal may + * lead to client termination; since the validation of the table is + * done as needed, this may happen before the service returns, or at + * some later time, or never, depending upon the client's pattern of + * memory references. Page table entries which supply translations for + * invalid virtual addresses may result in client termination, or may + * be silently ignored. "Invalid" in this context means a value which + * was not provided to the client via the appropriate hv_inquire_* routine. + * + * To support changing the instruction VAs at the same time as + * installing the new page table, this call explicitly supports + * setting the "lr" register to a different address and then jumping + * directly to the hv_install_context() routine. In this case, the + * new page table does not need to contain any mapping for the + * hv_install_context address itself. + * + * @param page_table Root of the page table. + * @param access PTE providing info on how to read the page table. This + * value must be consistent between multiple tiles sharing a page table, + * and must also be consistent with any virtual mappings the client + * may be using to access the page table. + * @param asid HV_ASID the page table is to be used for. + * @param flags Context flags, denoting attributes or privileges of the + * current context (HV_CTX_xxx). + * @return Zero on success, or a hypervisor error code on failure. + */ +int hv_install_context(HV_PhysAddr page_table, HV_PTE access, HV_ASID asid, + __hv32 flags); + +#endif /* !__ASSEMBLER__ */ + +#define HV_CTX_DIRECTIO 0x1 /**< Direct I/O requests are accepted from + PL0. */ + +#ifndef __ASSEMBLER__ + +/** Value returned from hv_inquire_context(). */ +typedef struct +{ + /** Physical address of page table */ + HV_PhysAddr page_table; + + /** PTE which defines access method for top of page table */ + HV_PTE access; + + /** ASID associated with this page table */ + HV_ASID asid; + + /** Context flags */ + __hv32 flags; +} HV_Context; + +/** Retrieve information about the currently installed context. + * @return The data passed to the last successful hv_install_context call. + */ +HV_Context hv_inquire_context(void); + + +/** Flushes all translations associated with the named address space + * identifier from the TLB and any other hypervisor data structures. + * Translations installed with the "global" bit are not flushed. + * + * Specifying an invalid ASID may lead to client termination. "Invalid" + * in this context means a value which was not provided to the client + * via hv_inquire_asid(). + * + * @param asid HV_ASID whose entries are to be flushed. + * @return Zero on success, or a hypervisor error code on failure. +*/ +int hv_flush_asid(HV_ASID asid); + + +/** Flushes all translations associated with the named virtual address + * and page size from the TLB and other hypervisor data structures. Only + * pages visible to the current ASID are affected; note that this includes + * global pages in addition to pages specific to the current ASID. + * + * The supplied VA need not be aligned; it may be anywhere in the + * subject page. + * + * Specifying an invalid virtual address may lead to client termination, + * or may silently succeed. "Invalid" in this context means a value + * which was not provided to the client via hv_inquire_virtual. + * + * @param address Address of the page to flush. + * @param page_size Size of pages to assume. + * @return Zero on success, or a hypervisor error code on failure. + */ +int hv_flush_page(HV_VirtAddr address, HV_PageSize page_size); + + +/** Flushes all translations associated with the named virtual address range + * and page size from the TLB and other hypervisor data structures. Only + * pages visible to the current ASID are affected; note that this includes + * global pages in addition to pages specific to the current ASID. + * + * The supplied VA need not be aligned; it may be anywhere in the + * subject page. + * + * Specifying an invalid virtual address may lead to client termination, + * or may silently succeed. "Invalid" in this context means a value + * which was not provided to the client via hv_inquire_virtual. + * + * @param start Address to flush. + * @param page_size Size of pages to assume. + * @param size The number of bytes to flush. Any page in the range + * [start, start + size) will be flushed from the TLB. + * @return Zero on success, or a hypervisor error code on failure. + */ +int hv_flush_pages(HV_VirtAddr start, HV_PageSize page_size, + unsigned long size); + + +/** Flushes all non-global translations (if preserve_global is true), + * or absolutely all translations (if preserve_global is false). + * + * @param preserve_global Non-zero if we want to preserve "global" mappings. + * @return Zero on success, or a hypervisor error code on failure. +*/ +int hv_flush_all(int preserve_global); + + +/** Restart machine with optional restart command and optional args. + * @param cmd Const pointer to command to restart with, or NULL + * @param args Const pointer to argument string to restart with, or NULL + */ +void hv_restart(HV_VirtAddr cmd, HV_VirtAddr args); + + +/** Halt machine. */ +void hv_halt(void); + + +/** Power off machine. */ +void hv_power_off(void); + + +/** Re-enter virtual-is-physical memory translation mode and restart + * execution at a given address. + * @param entry Client physical address at which to begin execution. + * @return A hypervisor error code on failure; if the operation is + * successful the call does not return. + */ +int hv_reexec(HV_PhysAddr entry); + + +/** Chip topology */ +typedef struct +{ + /** Relative coordinates of the querying tile */ + HV_Coord coord; + + /** Width of the querying supervisor's tile rectangle. */ + int width; + + /** Height of the querying supervisor's tile rectangle. */ + int height; + +} HV_Topology; + +/** Returns information about the tile coordinate system. + * + * Each supervisor is given a rectangle of tiles it potentially controls. + * These tiles are labeled using a relative coordinate system with (0,0) as + * the upper left tile regardless of their physical location on the chip. + * + * This call returns both the size of that rectangle and the position + * within that rectangle of the querying tile. + * + * Not all tiles within that rectangle may be available to the supervisor; + * to get the precise set of available tiles, you must also call + * hv_inquire_tiles(HV_INQ_TILES_AVAIL, ...). + **/ +HV_Topology hv_inquire_topology(void); + +/** Sets of tiles we can retrieve with hv_inquire_tiles(). + * + * These numbers are part of the binary API and guaranteed not to change. + */ +typedef enum { + /** An invalid value; do not use. */ + _HV_INQ_TILES_RESERVED = 0, + + /** All available tiles within the supervisor's tile rectangle. */ + HV_INQ_TILES_AVAIL = 1, + + /** The set of tiles used for hash-for-home caching. */ + HV_INQ_TILES_HFH_CACHE = 2, + + /** The set of tiles that can be legally used as a LOTAR for a PTE. */ + HV_INQ_TILES_LOTAR = 3 +} HV_InqTileSet; + +/** Returns specific information about various sets of tiles within the + * supervisor's tile rectangle. + * + * @param set Which set of tiles to retrieve. + * @param cpumask Pointer to a returned bitmask (in row-major order, + * supervisor-relative) of tiles. The low bit of the first word + * corresponds to the tile at the upper left-hand corner of the + * supervisor's rectangle. In order for the supervisor to know the + * buffer length to supply, it should first call hv_inquire_topology. + * @param length Number of bytes available for the returned bitmask. + **/ +HV_Errno hv_inquire_tiles(HV_InqTileSet set, HV_VirtAddr cpumask, int length); + + +/** An identifier for a memory controller. Multiple memory controllers + * may be connected to one chip, and this uniquely identifies each one. + */ +typedef int HV_MemoryController; + +/** A range of physical memory. */ +typedef struct +{ + HV_PhysAddr start; /**< Starting address. */ + __hv64 size; /**< Size in bytes. */ + HV_MemoryController controller; /**< Which memory controller owns this. */ +} HV_PhysAddrRange; + +/** Returns information about a range of physical memory. + * + * hv_inquire_physical() returns one of the ranges of client + * physical addresses which are available to this client. + * + * The first range is retrieved by specifying an idx of 0, and + * successive ranges are returned with subsequent idx values. Ranges + * are ordered by increasing start address (i.e., as idx increases, + * so does start), do not overlap, and do not touch (i.e., the + * available memory is described with the fewest possible ranges). + * + * If an out-of-range idx value is specified, the returned size will be zero. + * A client can count the number of ranges by increasing idx until the + * returned size is zero. There will always be at least one valid range. + * + * Some clients might not be prepared to deal with more than one + * physical address range; they still ought to call this routine and + * issue a warning message if they're given more than one range, on the + * theory that whoever configured the hypervisor to provide that memory + * should know that it's being wasted. + */ +HV_PhysAddrRange hv_inquire_physical(int idx); + + +/** Memory controller information. */ +typedef struct +{ + HV_Coord coord; /**< Relative tile coordinates of the port used by a + specified tile to communicate with this controller. */ + __hv64 speed; /**< Speed of this controller in bytes per second. */ +} HV_MemoryControllerInfo; + +/** Returns information about a particular memory controller. + * + * hv_inquire_memory_controller(coord,idx) returns information about a + * particular controller. Two pieces of information are returned: + * - The relative coordinates of the port on the controller that the specified + * tile would use to contact it. The relative coordinates may lie + * outside the supervisor's rectangle, i.e. the controller may not + * be attached to a node managed by the querying node's supervisor. + * In particular note that x or y may be negative. + * - The speed of the memory controller. (This is a not-to-exceed value + * based on the raw hardware data rate, and may not be achievable in + * practice; it is provided to give clients information on the relative + * performance of the available controllers.) + * + * Clients should avoid calling this interface with invalid values. + * A client who does may be terminated. + * @param coord Tile for which to calculate the relative port position. + * @param controller Index of the controller; identical to value returned + * from other routines like hv_inquire_physical. + * @return Information about the controller. + */ +HV_MemoryControllerInfo hv_inquire_memory_controller(HV_Coord coord, + int controller); + + +/** A range of virtual memory. */ +typedef struct +{ + HV_VirtAddr start; /**< Starting address. */ + __hv64 size; /**< Size in bytes. */ +} HV_VirtAddrRange; + +/** Returns information about a range of virtual memory. + * + * hv_inquire_virtual() returns one of the ranges of client + * virtual addresses which are available to this client. + * + * The first range is retrieved by specifying an idx of 0, and + * successive ranges are returned with subsequent idx values. Ranges + * are ordered by increasing start address (i.e., as idx increases, + * so does start), do not overlap, and do not touch (i.e., the + * available memory is described with the fewest possible ranges). + * + * If an out-of-range idx value is specified, the returned size will be zero. + * A client can count the number of ranges by increasing idx until the + * returned size is zero. There will always be at least one valid range. + * + * Some clients may well have various virtual addresses hardwired + * into themselves; for instance, their instruction stream may + * have been compiled expecting to live at a particular address. + * Such clients should use this interface to verify they've been + * given the virtual address space they expect, and issue a (potentially + * fatal) warning message otherwise. + * + * Note that the returned size is a __hv64, not a __hv32, so it is + * possible to express a single range spanning the entire 32-bit + * address space. + */ +HV_VirtAddrRange hv_inquire_virtual(int idx); + + +/** A range of ASID values. */ +typedef struct +{ + HV_ASID start; /**< First ASID in the range. */ + unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */ +} HV_ASIDRange; + +/** Returns information about a range of ASIDs. + * + * hv_inquire_asid() returns one of the ranges of address + * space identifiers which are available to this client. + * + * The first range is retrieved by specifying an idx of 0, and + * successive ranges are returned with subsequent idx values. Ranges + * are ordered by increasing start value (i.e., as idx increases, + * so does start), do not overlap, and do not touch (i.e., the + * available ASIDs are described with the fewest possible ranges). + * + * If an out-of-range idx value is specified, the returned size will be zero. + * A client can count the number of ranges by increasing idx until the + * returned size is zero. There will always be at least one valid range. + */ +HV_ASIDRange hv_inquire_asid(int idx); + + +/** Waits for at least the specified number of nanoseconds then returns. + * + * @param nanosecs The number of nanoseconds to sleep. + */ +void hv_nanosleep(int nanosecs); + + +/** Reads a character from the console without blocking. + * + * @return A value from 0-255 indicates the value successfully read. + * A negative value means no value was ready. + */ +int hv_console_read_if_ready(void); + + +/** Writes a character to the console, blocking if the console is busy. + * + * This call cannot fail. If the console is broken for some reason, + * output will simply vanish. + * @param byte Character to write. + */ +void hv_console_putc(int byte); + + +/** Writes a string to the console, blocking if the console is busy. + * @param bytes Pointer to characters to write. + * @param len Number of characters to write. + * @return Number of characters written, or HV_EFAULT if the buffer is invalid. + */ +int hv_console_write(HV_VirtAddr bytes, int len); + + +/** Dispatch the next interrupt from the client downcall mechanism. + * + * The hypervisor uses downcalls to notify the client of asynchronous + * events. Some of these events are hypervisor-created (like incoming + * messages). Some are regular interrupts which initially occur in + * the hypervisor, and are normally handled directly by the client; + * when these occur in a client's interrupt critical section, they must + * be delivered through the downcall mechanism. + * + * A downcall is initially delivered to the client as an INTCTRL_1 + * interrupt. Upon entry to the INTCTRL_1 vector, the client must + * immediately invoke the hv_downcall_dispatch service. This service + * will not return; instead it will cause one of the client's actual + * downcall-handling interrupt vectors to be entered. The EX_CONTEXT + * registers in the client will be set so that when the client irets, + * it will return to the code which was interrupted by the INTCTRL_1 + * interrupt. + * + * Any saving of registers should be done by the actual handling + * vectors; no registers should be changed by the INTCTRL_1 handler. + * In particular, the client should not use a jal instruction to invoke + * the hv_downcall_dispatch service, as that would overwrite the client's + * lr register. Note that the hv_downcall_dispatch service may overwrite + * one or more of the client's system save registers. + * + * The client must not modify the INTCTRL_1_STATUS SPR. The hypervisor + * will set this register to cause a downcall to happen, and will clear + * it when no further downcalls are pending. + * + * When a downcall vector is entered, the INTCTRL_1 interrupt will be + * masked. When the client is done processing a downcall, and is ready + * to accept another, it must unmask this interrupt; if more downcalls + * are pending, this will cause the INTCTRL_1 vector to be reentered. + * Currently the following interrupt vectors can be entered through a + * downcall: + * + * INT_MESSAGE_RCV_DWNCL (hypervisor message available) + * INT_DMATLB_MISS_DWNCL (DMA TLB miss) + * INT_SNITLB_MISS_DWNCL (SNI TLB miss) + * INT_DMATLB_ACCESS_DWNCL (DMA TLB access violation) + */ +void hv_downcall_dispatch(void); + +#endif /* !__ASSEMBLER__ */ + +/** We use actual interrupt vectors which never occur (they're only there + * to allow setting MPLs for related SPRs) for our downcall vectors. + */ +/** Message receive downcall interrupt vector */ +#define INT_MESSAGE_RCV_DWNCL INT_BOOT_ACCESS +/** DMA TLB miss downcall interrupt vector */ +#define INT_DMATLB_MISS_DWNCL INT_DMA_ASID +/** Static nework processor instruction TLB miss interrupt vector */ +#define INT_SNITLB_MISS_DWNCL INT_SNI_ASID +/** DMA TLB access violation downcall interrupt vector */ +#define INT_DMATLB_ACCESS_DWNCL INT_DMA_CPL +/** Device interrupt downcall interrupt vector */ +#define INT_DEV_INTR_DWNCL INT_WORLD_ACCESS + +#ifndef __ASSEMBLER__ + +/** Requests the inode for a specific full pathname. + * + * Performs a lookup in the hypervisor filesystem for a given filename. + * Multiple calls with the same filename will always return the same inode. + * If there is no such filename, HV_ENOENT is returned. + * A bad filename pointer may result in HV_EFAULT instead. + * + * @param filename Constant pointer to name of requested file + * @return Inode of requested file + */ +int hv_fs_findfile(HV_VirtAddr filename); + + +/** Data returned from an fstat request. + * Note that this structure should be no more than 40 bytes in size so + * that it can always be returned completely in registers. + */ +typedef struct +{ + int size; /**< Size of file (or HV_Errno on error) */ + unsigned int flags; /**< Flags (see HV_FS_FSTAT_FLAGS) */ +} HV_FS_StatInfo; + +/** Bitmask flags for fstat request */ +typedef enum +{ + HV_FS_ISDIR = 0x0001 /**< Is the entry a directory? */ +} HV_FS_FSTAT_FLAGS; + +/** Get stat information on a given file inode. + * + * Return information on the file with the given inode. + * + * IF the HV_FS_ISDIR bit is set, the "file" is a directory. Reading + * it will return NUL-separated filenames (no directory part) relative + * to the path to the inode of the directory "file". These can be + * appended to the path to the directory "file" after a forward slash + * to create additional filenames. Note that it is not required + * that all valid paths be decomposable into valid parent directories; + * a filesystem may validly have just a few files, none of which have + * HV_FS_ISDIR set. However, if clients may wish to enumerate the + * files in the filesystem, it is recommended to include all the + * appropriate parent directory "files" to give a consistent view. + * + * An invalid file inode will cause an HV_EBADF error to be returned. + * + * @param inode The inode number of the query + * @return An HV_FS_StatInfo structure + */ +HV_FS_StatInfo hv_fs_fstat(int inode); + + +/** Read data from a specific hypervisor file. + * On error, may return HV_EBADF for a bad inode or HV_EFAULT for a bad buf. + * Reads near the end of the file will return fewer bytes than requested. + * Reads at or beyond the end of a file will return zero. + * + * @param inode the hypervisor file to read + * @param buf the buffer to read data into + * @param length the number of bytes of data to read + * @param offset the offset into the file to read the data from + * @return number of bytes successfully read, or an HV_Errno code + */ +int hv_fs_pread(int inode, HV_VirtAddr buf, int length, int offset); + + +/** Read a 64-bit word from the specified physical address. + * The address must be 8-byte aligned. + * Specifying an invalid physical address will lead to client termination. + * @param addr The physical address to read + * @param access The PTE describing how to read the memory + * @return The 64-bit value read from the given address + */ +unsigned long long hv_physaddr_read64(HV_PhysAddr addr, HV_PTE access); + + +/** Write a 64-bit word to the specified physical address. + * The address must be 8-byte aligned. + * Specifying an invalid physical address will lead to client termination. + * @param addr The physical address to write + * @param access The PTE that says how to write the memory + * @param val The 64-bit value to write to the given address + */ +void hv_physaddr_write64(HV_PhysAddr addr, HV_PTE access, + unsigned long long val); + + +/** Get the value of the command-line for the supervisor, if any. + * This will not include the filename of the booted supervisor, but may + * include configured-in boot arguments or the hv_restart() arguments. + * If the buffer is not long enough the hypervisor will NUL the first + * character of the buffer but not write any other data. + * @param buf The virtual address to write the command-line string to. + * @param length The length of buf, in characters. + * @return The actual length of the command line, including the trailing NUL + * (may be larger than "length"). + */ +int hv_get_command_line(HV_VirtAddr buf, int length); + + +/** Set a new value for the command-line for the supervisor, which will + * be returned from subsequent invocations of hv_get_command_line() on + * this tile. + * @param buf The virtual address to read the command-line string from. + * @param length The length of buf, in characters; must be no more than + * HV_COMMAND_LINE_LEN. + * @return Zero if successful, or a hypervisor error code. + */ +HV_Errno hv_set_command_line(HV_VirtAddr buf, int length); + +/** Maximum size of a command line passed to hv_set_command_line(); note + * that a line returned from hv_get_command_line() could be larger than + * this.*/ +#define HV_COMMAND_LINE_LEN 256 + +/** Tell the hypervisor how to cache non-priority pages + * (its own as well as pages explicitly represented in page tables). + * Normally these will be represented as red/black pages, but + * when the supervisor starts to allocate "priority" pages in the PTE + * the hypervisor will need to start marking those pages as (e.g.) "red" + * and non-priority pages as either "black" (if they cache-alias + * with the existing priority pages) or "red/black" (if they don't). + * The bitmask provides information on which parts of the cache + * have been used for pinned pages so far on this tile; if (1 << N) + * appears in the bitmask, that indicates that a page has been marked + * "priority" whose PFN equals N, mod 8. + * @param bitmask A bitmap of priority page set values + */ +void hv_set_caching(unsigned int bitmask); + + +/** Zero out a specified number of pages. + * The va and size must both be multiples of 4096. + * Caches are bypassed and memory is directly set to zero. + * This API is implemented only in the magic hypervisor and is intended + * to provide a performance boost to the minimal supervisor by + * giving it a fast way to zero memory pages when allocating them. + * @param va Virtual address where the page has been mapped + * @param size Number of bytes (must be a page size multiple) + */ +void hv_bzero_page(HV_VirtAddr va, unsigned int size); + + +/** State object for the hypervisor messaging subsystem. */ +typedef struct +{ +#if CHIP_VA_WIDTH() > 32 + __hv64 opaque[2]; /**< No user-serviceable parts inside */ +#else + __hv32 opaque[2]; /**< No user-serviceable parts inside */ +#endif +} +HV_MsgState; + +/** Register to receive incoming messages. + * + * This routine configures the current tile so that it can receive + * incoming messages. It must be called before the client can receive + * messages with the hv_receive_message routine, and must be called on + * each tile which will receive messages. + * + * msgstate is the virtual address of a state object of type HV_MsgState. + * Once the state is registered, the client must not read or write the + * state object; doing so will cause undefined results. + * + * If this routine is called with msgstate set to 0, the client's message + * state will be freed and it will no longer be able to receive messages. + * Note that this may cause the loss of any as-yet-undelivered messages + * for the client. + * + * If another client attempts to send a message to a client which has + * not yet called hv_register_message_state, or which has freed its + * message state, the message will not be delivered, as if the client + * had insufficient buffering. + * + * This routine returns HV_OK if the registration was successful, and + * HV_EINVAL if the supplied state object is unsuitable. Note that some + * errors may not be detected during this routine, but might be detected + * during a subsequent message delivery. + * @param msgstate State object. + **/ +HV_Errno hv_register_message_state(HV_MsgState* msgstate); + +/** Possible message recipient states. */ +typedef enum +{ + HV_TO_BE_SENT, /**< Not sent (not attempted, or recipient not ready) */ + HV_SENT, /**< Successfully sent */ + HV_BAD_RECIP /**< Bad recipient coordinates (permanent error) */ +} HV_Recip_State; + +/** Message recipient. */ +typedef struct +{ + /** X coordinate, relative to supervisor's top-left coordinate */ + unsigned int x:11; + + /** Y coordinate, relative to supervisor's top-left coordinate */ + unsigned int y:11; + + /** Status of this recipient */ + HV_Recip_State state:10; +} HV_Recipient; + +/** Send a message to a set of recipients. + * + * This routine sends a message to a set of recipients. + * + * recips is an array of HV_Recipient structures. Each specifies a tile, + * and a message state; initially, it is expected that the state will + * be set to HV_TO_BE_SENT. nrecip specifies the number of recipients + * in the recips array. + * + * For each recipient whose state is HV_TO_BE_SENT, the hypervisor attempts + * to send that tile the specified message. In order to successfully + * receive the message, the receiver must be a valid tile to which the + * sender has access, must not be the sending tile itself, and must have + * sufficient free buffer space. (The hypervisor guarantees that each + * tile which has called hv_register_message_state() will be able to + * buffer one message from every other tile which can legally send to it; + * more space may be provided but is not guaranteed.) If an invalid tile + * is specified, the recipient's state is set to HV_BAD_RECIP; this is a + * permanent delivery error. If the message is successfully delivered + * to the recipient's buffer, the recipient's state is set to HV_SENT. + * Otherwise, the recipient's state is unchanged. Message delivery is + * synchronous; all attempts to send messages are completed before this + * routine returns. + * + * If no permanent delivery errors were encountered, the routine returns + * the number of messages successfully sent: that is, the number of + * recipients whose states changed from HV_TO_BE_SENT to HV_SENT during + * this operation. If any permanent delivery errors were encountered, + * the routine returns HV_ERECIP. In the event of permanent delivery + * errors, it may be the case that delivery was not attempted to all + * recipients; if any messages were succesfully delivered, however, + * recipients' state values will be updated appropriately. + * + * It is explicitly legal to specify a recipient structure whose state + * is not HV_TO_BE_SENT; such a recipient is ignored. One suggested way + * of using hv_send_message to send a message to multiple tiles is to set + * up a list of recipients, and then call the routine repeatedly with the + * same list, each time accumulating the number of messages successfully + * sent, until all messages are sent, a permanent error is encountered, + * or the desired number of attempts have been made. When used in this + * way, the routine will deliver each message no more than once to each + * recipient. + * + * Note that a message being successfully delivered to the recipient's + * buffer space does not guarantee that it is received by the recipient, + * either immediately or at any time in the future; the recipient might + * never call hv_receive_message, or could register a different state + * buffer, losing the message. + * + * Specifiying the same recipient more than once in the recipient list + * is an error, which will not result in an error return but which may + * or may not result in more than one message being delivered to the + * recipient tile. + * + * buf and buflen specify the message to be sent. buf is a virtual address + * which must be currently mapped in the client's page table; if not, the + * routine returns HV_EFAULT. buflen must be greater than zero and less + * than or equal to HV_MAX_MESSAGE_SIZE, and nrecip must be less than the + * number of tiles to which the sender has access; if not, the routine + * returns HV_EINVAL. + * @param recips List of recipients. + * @param nrecip Number of recipients. + * @param buf Address of message data. + * @param buflen Length of message data. + **/ +int hv_send_message(HV_Recipient *recips, int nrecip, + HV_VirtAddr buf, int buflen); + +/** Maximum hypervisor message size, in bytes */ +#define HV_MAX_MESSAGE_SIZE 28 + + +/** Return value from hv_receive_message() */ +typedef struct +{ + int msglen; /**< Message length in bytes, or an error code */ + __hv32 source; /**< Code identifying message sender (HV_MSG_xxx) */ +} HV_RcvMsgInfo; + +#define HV_MSG_TILE 0x0 /**< Message source is another tile */ +#define HV_MSG_INTR 0x1 /**< Message source is a driver interrupt */ + +/** Receive a message. + * + * This routine retrieves a message from the client's incoming message + * buffer. + * + * Multiple messages sent from a particular sending tile to a particular + * receiving tile are received in the order that they were sent; however, + * no ordering is guaranteed between messages sent by different tiles. + * + * Whenever the a client's message buffer is empty, the first message + * subsequently received will cause the client's MESSAGE_RCV_DWNCL + * interrupt vector to be invoked through the interrupt downcall mechanism + * (see the description of the hv_downcall_dispatch() routine for details + * on downcalls). + * + * Another message-available downcall will not occur until a call to + * this routine is made when the message buffer is empty, and a message + * subsequently arrives. Note that such a downcall could occur while + * this routine is executing. If the calling code does not wish this + * to happen, it is recommended that this routine be called with the + * INTCTRL_1 interrupt masked, or inside an interrupt critical section. + * + * msgstate is the value previously passed to hv_register_message_state(). + * buf is the virtual address of the buffer into which the message will + * be written; buflen is the length of the buffer. + * + * This routine returns an HV_RcvMsgInfo structure. The msglen member + * of that structure is the length of the message received, zero if no + * message is available, or HV_E2BIG if the message is too large for the + * specified buffer. If the message is too large, it is not consumed, + * and may be retrieved by a subsequent call to this routine specifying + * a sufficiently large buffer. A buffer which is HV_MAX_MESSAGE_SIZE + * bytes long is guaranteed to be able to receive any possible message. + * + * The source member of the HV_RcvMsgInfo structure describes the sender + * of the message. For messages sent by another client tile via an + * hv_send_message() call, this value is HV_MSG_TILE; for messages sent + * as a result of a device interrupt, this value is HV_MSG_INTR. + */ + +HV_RcvMsgInfo hv_receive_message(HV_MsgState msgstate, HV_VirtAddr buf, + int buflen); + + +/** Start remaining tiles owned by this supervisor. Initially, only one tile + * executes the client program; after it calls this service, the other tiles + * are started. This allows the initial tile to do one-time configuration + * of shared data structures without having to lock them against simultaneous + * access. + */ +void hv_start_all_tiles(void); + + +/** Open a hypervisor device. + * + * This service initializes an I/O device and its hypervisor driver software, + * and makes it available for use. The open operation is per-device per-chip; + * once it has been performed, the device handle returned may be used in other + * device services calls made by any tile. + * + * @param name Name of the device. A base device name is just a text string + * (say, "pcie"). If there is more than one instance of a device, the + * base name is followed by a slash and a device number (say, "pcie/0"). + * Some devices may support further structure beneath those components; + * most notably, devices which require control operations do so by + * supporting reads and/or writes to a control device whose name + * includes a trailing "/ctl" (say, "pcie/0/ctl"). + * @param flags Flags (HV_DEV_xxx). + * @return A positive integer device handle, or a negative error code. + */ +int hv_dev_open(HV_VirtAddr name, __hv32 flags); + + +/** Close a hypervisor device. + * + * This service uninitializes an I/O device and its hypervisor driver + * software, and makes it unavailable for use. The close operation is + * per-device per-chip; once it has been performed, the device is no longer + * available. Normally there is no need to ever call the close service. + * + * @param devhdl Device handle of the device to be closed. + * @return Zero if the close is successful, otherwise, a negative error code. + */ +int hv_dev_close(int devhdl); + + +/** Read data from a hypervisor device synchronously. + * + * This service transfers data from a hypervisor device to a memory buffer. + * When the service returns, the data has been written from the memory buffer, + * and the buffer will not be further modified by the driver. + * + * No ordering is guaranteed between requests issued from different tiles. + * + * Devices may choose to support both the synchronous and asynchronous read + * operations, only one of them, or neither of them. + * + * @param devhdl Device handle of the device to be read from. + * @param flags Flags (HV_DEV_xxx). + * @param va Virtual address of the target data buffer. This buffer must + * be mapped in the currently installed page table; if not, HV_EFAULT + * may be returned. + * @param len Number of bytes to be transferred. + * @param offset Driver-dependent offset. For a random-access device, this is + * often a byte offset from the beginning of the device; in other cases, + * like on a control device, it may have a different meaning. + * @return A non-negative value if the read was at least partially successful; + * otherwise, a negative error code. The precise interpretation of + * the return value is driver-dependent, but many drivers will return + * the number of bytes successfully transferred. + */ +int hv_dev_pread(int devhdl, __hv32 flags, HV_VirtAddr va, __hv32 len, + __hv64 offset); + +#define HV_DEV_NB_EMPTY 0x1 /**< Don't block when no bytes of data can + be transferred. */ +#define HV_DEV_NB_PARTIAL 0x2 /**< Don't block when some bytes, but not all + of the requested bytes, can be + transferred. */ +#define HV_DEV_NOCACHE 0x4 /**< The caller warrants that none of the + cache lines which might contain data + from the requested buffer are valid. + Useful with asynchronous operations + only. */ + +#define HV_DEV_ALLFLAGS (HV_DEV_NB_EMPTY | HV_DEV_NB_PARTIAL | \ + HV_DEV_NOCACHE) /**< All HV_DEV_xxx flags */ + +/** Write data to a hypervisor device synchronously. + * + * This service transfers data from a memory buffer to a hypervisor device. + * When the service returns, the data has been read from the memory buffer, + * and the buffer may be overwritten by the client; the data may not + * necessarily have been conveyed to the actual hardware I/O interface. + * + * No ordering is guaranteed between requests issued from different tiles. + * + * Devices may choose to support both the synchronous and asynchronous write + * operations, only one of them, or neither of them. + * + * @param devhdl Device handle of the device to be written to. + * @param flags Flags (HV_DEV_xxx). + * @param va Virtual address of the source data buffer. This buffer must + * be mapped in the currently installed page table; if not, HV_EFAULT + * may be returned. + * @param len Number of bytes to be transferred. + * @param offset Driver-dependent offset. For a random-access device, this is + * often a byte offset from the beginning of the device; in other cases, + * like on a control device, it may have a different meaning. + * @return A non-negative value if the write was at least partially successful; + * otherwise, a negative error code. The precise interpretation of + * the return value is driver-dependent, but many drivers will return + * the number of bytes successfully transferred. + */ +int hv_dev_pwrite(int devhdl, __hv32 flags, HV_VirtAddr va, __hv32 len, + __hv64 offset); + + +/** Interrupt arguments, used in the asynchronous I/O interfaces. */ +#if CHIP_VA_WIDTH() > 32 +typedef __hv64 HV_IntArg; +#else +typedef __hv32 HV_IntArg; +#endif + +/** Interrupt messages are delivered via the mechanism as normal messages, + * but have a message source of HV_DEV_INTR. The message is formatted + * as an HV_IntrMsg structure. + */ + +typedef struct +{ + HV_IntArg intarg; /**< Interrupt argument, passed to the poll/preada/pwritea + services */ + HV_IntArg intdata; /**< Interrupt-specific interrupt data */ +} HV_IntrMsg; + +/** Request an interrupt message when a device condition is satisfied. + * + * This service requests that an interrupt message be delivered to the + * requesting tile when a device becomes readable or writable, or when any + * data queued to the device via previous write operations from this tile + * has been actually sent out on the hardware I/O interface. Devices may + * choose to support any, all, or none of the available conditions. + * + * If multiple conditions are specified, only one message will be + * delivered. If the event mask delivered to that interrupt handler + * indicates that some of the conditions have not yet occurred, the + * client must issue another poll() call if it wishes to wait for those + * conditions. + * + * Only one poll may be outstanding per device handle per tile. If more than + * one tile is polling on the same device and condition, they will all be + * notified when it happens. Because of this, clients may not assume that + * the condition signaled is necessarily still true when they request a + * subsequent service; for instance, the readable data which caused the + * poll call to interrupt may have been read by another tile in the interim. + * + * The notification interrupt message could come directly, or via the + * downcall (intctrl1) method, depending on what the tile is doing + * when the condition is satisfied. Note that it is possible for the + * requested interrupt to be delivered after this service is called but + * before it returns. + * + * @param devhdl Device handle of the device to be polled. + * @param events Flags denoting the events which will cause the interrupt to + * be delivered (HV_DEVPOLL_xxx). + * @param intarg Value which will be delivered as the intarg member of the + * eventual interrupt message; the intdata member will be set to a + * mask of HV_DEVPOLL_xxx values indicating which conditions have been + * satisifed. + * @return Zero if the interrupt was successfully scheduled; otherwise, a + * negative error code. + */ +int hv_dev_poll(int devhdl, __hv32 events, HV_IntArg intarg); + +#define HV_DEVPOLL_READ 0x1 /**< Test device for readability */ +#define HV_DEVPOLL_WRITE 0x2 /**< Test device for writability */ +#define HV_DEVPOLL_FLUSH 0x4 /**< Test device for output drained */ + + +/** Cancel a request for an interrupt when a device event occurs. + * + * This service requests that no interrupt be delivered when the events + * noted in the last-issued poll() call happen. Once this service returns, + * the interrupt has been canceled; however, it is possible for the interrupt + * to be delivered after this service is called but before it returns. + * + * @param devhdl Device handle of the device on which to cancel polling. + * @return Zero if the poll was successfully canceled; otherwise, a negative + * error code. + */ +int hv_dev_poll_cancel(int devhdl); + + +/** Scatter-gather list for preada/pwritea calls. */ +typedef struct +#if CHIP_VA_WIDTH() <= 32 +__attribute__ ((packed, aligned(4))) +#endif +{ + HV_PhysAddr pa; /**< Client physical address of the buffer segment. */ + HV_PTE pte; /**< Page table entry describing the caching and location + override characteristics of the buffer segment. Some + drivers ignore this element and will require that + the NOCACHE flag be set on their requests. */ + __hv32 len; /**< Length of the buffer segment. */ +} HV_SGL; + +#define HV_SGL_MAXLEN 16 /**< Maximum number of entries in a scatter-gather + list */ + +/** Read data from a hypervisor device asynchronously. + * + * This service transfers data from a hypervisor device to a memory buffer. + * When the service returns, the read has been scheduled. When the read + * completes, an interrupt message will be delivered, and the buffer will + * not be further modified by the driver. + * + * The number of possible outstanding asynchronous requests is defined by + * each driver, but it is recommended that it be at least two requests + * per tile per device. + * + * No ordering is guaranteed between synchronous and asynchronous requests, + * even those issued on the same tile. + * + * The completion interrupt message could come directly, or via the downcall + * (intctrl1) method, depending on what the tile is doing when the read + * completes. Interrupts do not coalesce; one is delivered for each + * asynchronous I/O request. Note that it is possible for the requested + * interrupt to be delivered after this service is called but before it + * returns. + * + * Devices may choose to support both the synchronous and asynchronous read + * operations, only one of them, or neither of them. + * + * @param devhdl Device handle of the device to be read from. + * @param flags Flags (HV_DEV_xxx). + * @param sgl_len Number of elements in the scatter-gather list. + * @param sgl Scatter-gather list describing the memory to which data will be + * written. + * @param offset Driver-dependent offset. For a random-access device, this is + * often a byte offset from the beginning of the device; in other cases, + * like on a control device, it may have a different meaning. + * @param intarg Value which will be delivered as the intarg member of the + * eventual interrupt message; the intdata member will be set to the + * normal return value from the read request. + * @return Zero if the read was successfully scheduled; otherwise, a negative + * error code. Note that some drivers may choose to pre-validate + * their arguments, and may thus detect certain device error + * conditions at this time rather than when the completion notification + * occurs, but this is not required. + */ +int hv_dev_preada(int devhdl, __hv32 flags, __hv32 sgl_len, + HV_SGL sgl[/* sgl_len */], __hv64 offset, HV_IntArg intarg); + + +/** Write data to a hypervisor device asynchronously. + * + * This service transfers data from a memory buffer to a hypervisor + * device. When the service returns, the write has been scheduled. + * When the write completes, an interrupt message will be delivered, + * and the buffer may be overwritten by the client; the data may not + * necessarily have been conveyed to the actual hardware I/O interface. + * + * The number of possible outstanding asynchronous requests is defined by + * each driver, but it is recommended that it be at least two requests + * per tile per device. + * + * No ordering is guaranteed between synchronous and asynchronous requests, + * even those issued on the same tile. + * + * The completion interrupt message could come directly, or via the downcall + * (intctrl1) method, depending on what the tile is doing when the read + * completes. Interrupts do not coalesce; one is delivered for each + * asynchronous I/O request. Note that it is possible for the requested + * interrupt to be delivered after this service is called but before it + * returns. + * + * Devices may choose to support both the synchronous and asynchronous write + * operations, only one of them, or neither of them. + * + * @param devhdl Device handle of the device to be read from. + * @param flags Flags (HV_DEV_xxx). + * @param sgl_len Number of elements in the scatter-gather list. + * @param sgl Scatter-gather list describing the memory from which data will be + * read. + * @param offset Driver-dependent offset. For a random-access device, this is + * often a byte offset from the beginning of the device; in other cases, + * like on a control device, it may have a different meaning. + * @param intarg Value which will be delivered as the intarg member of the + * eventual interrupt message; the intdata member will be set to the + * normal return value from the write request. + * @return Zero if the write was successfully scheduled; otherwise, a negative + * error code. Note that some drivers may choose to pre-validate + * their arguments, and may thus detect certain device error + * conditions at this time rather than when the completion notification + * occurs, but this is not required. + */ +int hv_dev_pwritea(int devhdl, __hv32 flags, __hv32 sgl_len, + HV_SGL sgl[/* sgl_len */], __hv64 offset, HV_IntArg intarg); + + +/** Define a pair of tile and ASID to identify a user process context. */ +typedef struct +{ + /** X coordinate, relative to supervisor's top-left coordinate */ + unsigned int x:11; + + /** Y coordinate, relative to supervisor's top-left coordinate */ + unsigned int y:11; + + /** ASID of the process on this x,y tile */ + HV_ASID asid:10; +} HV_Remote_ASID; + +/** Flush cache and/or TLB state on remote tiles. + * + * @param cache_pa Client physical address to flush from cache (ignored if + * the length encoded in cache_control is zero, or if + * HV_FLUSH_EVICT_L2 is set, or if cache_cpumask is NULL). + * @param cache_control This argument allows you to specify a length of + * physical address space to flush (maximum HV_FLUSH_MAX_CACHE_LEN). + * You can "or" in HV_FLUSH_EVICT_L2 to flush the whole L2 cache. + * You can "or" in HV_FLUSH_EVICT_LI1 to flush the whole LII cache. + * HV_FLUSH_ALL flushes all caches. + * @param cache_cpumask Bitmask (in row-major order, supervisor-relative) of + * tile indices to perform cache flush on. The low bit of the first + * word corresponds to the tile at the upper left-hand corner of the + * supervisor's rectangle. If passed as a NULL pointer, equivalent + * to an empty bitmask. On chips which support hash-for-home caching, + * if passed as -1, equivalent to a mask containing tiles which could + * be doing hash-for-home caching. + * @param tlb_va Virtual address to flush from TLB (ignored if + * tlb_length is zero or tlb_cpumask is NULL). + * @param tlb_length Number of bytes of data to flush from the TLB. + * @param tlb_pgsize Page size to use for TLB flushes. + * tlb_va and tlb_length need not be aligned to this size. + * @param tlb_cpumask Bitmask for tlb flush, like cache_cpumask. + * If passed as a NULL pointer, equivalent to an empty bitmask. + * @param asids Pointer to an HV_Remote_ASID array of tile/ASID pairs to flush. + * @param asidcount Number of HV_Remote_ASID entries in asids[]. + * @return Zero for success, or else HV_EINVAL or HV_EFAULT for errors that + * are detected while parsing the arguments. + */ +int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control, + unsigned long* cache_cpumask, + HV_VirtAddr tlb_va, unsigned long tlb_length, + unsigned long tlb_pgsize, unsigned long* tlb_cpumask, + HV_Remote_ASID* asids, int asidcount); + +/** Include in cache_control to ensure a flush of the entire L2. */ +#define HV_FLUSH_EVICT_L2 (1UL << 31) + +/** Include in cache_control to ensure a flush of the entire L1I. */ +#define HV_FLUSH_EVICT_L1I (1UL << 30) + +/** Maximum legal size to use for the "length" component of cache_control. */ +#define HV_FLUSH_MAX_CACHE_LEN ((1UL << 30) - 1) + +/** Use for cache_control to ensure a flush of all caches. */ +#define HV_FLUSH_ALL -1UL + +#else /* __ASSEMBLER__ */ + +/** Include in cache_control to ensure a flush of the entire L2. */ +#define HV_FLUSH_EVICT_L2 (1 << 31) + +/** Include in cache_control to ensure a flush of the entire L1I. */ +#define HV_FLUSH_EVICT_L1I (1 << 30) + +/** Maximum legal size to use for the "length" component of cache_control. */ +#define HV_FLUSH_MAX_CACHE_LEN ((1 << 30) - 1) + +/** Use for cache_control to ensure a flush of all caches. */ +#define HV_FLUSH_ALL -1 + +#endif /* __ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ + +/** Return a 64-bit value corresponding to the PTE if needed */ +#define hv_pte_val(pte) ((pte).val) + +/** Cast a 64-bit value to an HV_PTE */ +#define hv_pte(val) ((HV_PTE) { val }) + +#endif /* !__ASSEMBLER__ */ + + +/** Bits in the size of an HV_PTE */ +#define HV_LOG2_PTE_SIZE 3 + +/** Size of an HV_PTE */ +#define HV_PTE_SIZE (1 << HV_LOG2_PTE_SIZE) + + +/* Bits in HV_PTE's low word. */ +#define HV_PTE_INDEX_PRESENT 0 /**< PTE is valid */ +#define HV_PTE_INDEX_MIGRATING 1 /**< Page is migrating */ +#define HV_PTE_INDEX_CLIENT0 2 /**< Page client state 0 */ +#define HV_PTE_INDEX_CLIENT1 3 /**< Page client state 1 */ +#define HV_PTE_INDEX_NC 4 /**< L1$/L2$ incoherent with L3$ */ +#define HV_PTE_INDEX_NO_ALLOC_L1 5 /**< Page is uncached in local L1$ */ +#define HV_PTE_INDEX_NO_ALLOC_L2 6 /**< Page is uncached in local L2$ */ +#define HV_PTE_INDEX_CACHED_PRIORITY 7 /**< Page is priority cached */ +#define HV_PTE_INDEX_PAGE 8 /**< PTE describes a page */ +#define HV_PTE_INDEX_GLOBAL 9 /**< Page is global */ +#define HV_PTE_INDEX_USER 10 /**< Page is user-accessible */ +#define HV_PTE_INDEX_ACCESSED 11 /**< Page has been accessed */ +#define HV_PTE_INDEX_DIRTY 12 /**< Page has been written */ + /* Bits 13-15 are reserved for + future use. */ +#define HV_PTE_INDEX_MODE 16 /**< Page mode; see HV_PTE_MODE_xxx */ +#define HV_PTE_MODE_BITS 3 /**< Number of bits in mode */ + /* Bit 19 is reserved for + future use. */ +#define HV_PTE_INDEX_LOTAR 20 /**< Page's LOTAR; must be high bits + of word */ +#define HV_PTE_LOTAR_BITS 12 /**< Number of bits in a LOTAR */ + +/* Bits in HV_PTE's high word. */ +#define HV_PTE_INDEX_READABLE 32 /**< Page is readable */ +#define HV_PTE_INDEX_WRITABLE 33 /**< Page is writable */ +#define HV_PTE_INDEX_EXECUTABLE 34 /**< Page is executable */ +#define HV_PTE_INDEX_PTFN 35 /**< Page's PTFN; must be high bits + of word */ +#define HV_PTE_PTFN_BITS 29 /**< Number of bits in a PTFN */ + +/** Position of the PFN field within the PTE (subset of the PTFN). */ +#define HV_PTE_INDEX_PFN (HV_PTE_INDEX_PTFN + (HV_LOG2_PAGE_SIZE_SMALL - \ + HV_LOG2_PAGE_TABLE_ALIGN)) + +/** Length of the PFN field within the PTE (subset of the PTFN). */ +#define HV_PTE_INDEX_PFN_BITS (HV_PTE_INDEX_PTFN_BITS - \ + (HV_LOG2_PAGE_SIZE_SMALL - \ + HV_LOG2_PAGE_TABLE_ALIGN)) + +/* + * Legal values for the PTE's mode field + */ +/** Data is not resident in any caches; loads and stores access memory + * directly. + */ +#define HV_PTE_MODE_UNCACHED 1 + +/** Data is resident in the tile's local L1 and/or L2 caches; if a load + * or store misses there, it goes to memory. + * + * The copy in the local L1$/L2$ is not invalidated when the copy in + * memory is changed. + */ +#define HV_PTE_MODE_CACHE_NO_L3 2 + +/** Data is resident in the tile's local L1 and/or L2 caches. If a load + * or store misses there, it goes to an L3 cache in a designated tile; + * if it misses there, it goes to memory. + * + * If the NC bit is not set, the copy in the local L1$/L2$ is invalidated + * when the copy in the remote L3$ is changed. Otherwise, such + * invalidation will not occur. + * + * Chips for which CHIP_HAS_COHERENT_LOCAL_CACHE() is 0 do not support + * invalidation from an L3$ to another tile's L1$/L2$. If the NC bit is + * clear on such a chip, no copy is kept in the local L1$/L2$ in this mode. + */ +#define HV_PTE_MODE_CACHE_TILE_L3 3 + +/** Data is resident in the tile's local L1 and/or L2 caches. If a load + * or store misses there, it goes to an L3 cache in one of a set of + * designated tiles; if it misses there, it goes to memory. Which tile + * is chosen from the set depends upon a hash function applied to the + * physical address. This mode is not supported on chips for which + * CHIP_HAS_CBOX_HOME_MAP() is 0. + * + * If the NC bit is not set, the copy in the local L1$/L2$ is invalidated + * when the copy in the remote L3$ is changed. Otherwise, such + * invalidation will not occur. + * + * Chips for which CHIP_HAS_COHERENT_LOCAL_CACHE() is 0 do not support + * invalidation from an L3$ to another tile's L1$/L2$. If the NC bit is + * clear on such a chip, no copy is kept in the local L1$/L2$ in this mode. + */ +#define HV_PTE_MODE_CACHE_HASH_L3 4 + +/** Data is not resident in memory; accesses are instead made to an I/O + * device, whose tile coordinates are given by the PTE's LOTAR field. + * This mode is only supported on chips for which CHIP_HAS_MMIO() is 1. + * The EXECUTABLE bit may not be set in an MMIO PTE. + */ +#define HV_PTE_MODE_MMIO 5 + + +/* C wants 1ULL so it is typed as __hv64, but the assembler needs just numbers. + * The assembler can't handle shifts greater than 31, but treats them + * as shifts mod 32, so assembler code must be aware of which word + * the bit belongs in when using these macros. + */ +#ifdef __ASSEMBLER__ +#define __HV_PTE_ONE 1 /**< One, for assembler */ +#else +#define __HV_PTE_ONE 1ULL /**< One, for C */ +#endif + +/** Is this PTE present? + * + * If this bit is set, this PTE represents a valid translation or level-2 + * page table pointer. Otherwise, the page table does not contain a + * translation for the subject virtual pages. + * + * If this bit is not set, the other bits in the PTE are not + * interpreted by the hypervisor, and may contain any value. + */ +#define HV_PTE_PRESENT (__HV_PTE_ONE << HV_PTE_INDEX_PRESENT) + +/** Does this PTE map a page? + * + * If this bit is set in the level-1 page table, the entry should be + * interpreted as a level-2 page table entry mapping a large page. + * + * This bit should not be modified by the client while PRESENT is set, as + * doing so may race with the hypervisor's update of ACCESSED and DIRTY bits. + * + * In a level-2 page table, this bit is ignored and must be zero. + */ +#define HV_PTE_PAGE (__HV_PTE_ONE << HV_PTE_INDEX_PAGE) + +/** Is this a global (non-ASID) mapping? + * + * If this bit is set, the translations established by this PTE will + * not be flushed from the TLB by the hv_flush_asid() service; they + * will be flushed by the hv_flush_page() or hv_flush_pages() services. + * + * Setting this bit for translations which are identical in all page + * tables (for instance, code and data belonging to a client OS) can + * be very beneficial, as it will reduce the number of TLB misses. + * Note that, while it is not an error which will be detected by the + * hypervisor, it is an extremely bad idea to set this bit for + * translations which are _not_ identical in all page tables. + * + * This bit should not be modified by the client while PRESENT is set, as + * doing so may race with the hypervisor's update of ACCESSED and DIRTY bits. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_GLOBAL (__HV_PTE_ONE << HV_PTE_INDEX_GLOBAL) + +/** Is this mapping accessible to users? + * + * If this bit is set, code running at any PL will be permitted to + * access the virtual addresses mapped by this PTE. Otherwise, only + * code running at PL 1 or above will be allowed to do so. + * + * This bit should not be modified by the client while PRESENT is set, as + * doing so may race with the hypervisor's update of ACCESSED and DIRTY bits. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_USER (__HV_PTE_ONE << HV_PTE_INDEX_USER) + +/** Has this mapping been accessed? + * + * This bit is set by the hypervisor when the memory described by the + * translation is accessed for the first time. It is never cleared by + * the hypervisor, but may be cleared by the client. After the bit + * has been cleared, subsequent references are not guaranteed to set + * it again until the translation has been flushed from the TLB. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_ACCESSED (__HV_PTE_ONE << HV_PTE_INDEX_ACCESSED) + +/** Is this mapping dirty? + * + * This bit is set by the hypervisor when the memory described by the + * translation is written for the first time. It is never cleared by + * the hypervisor, but may be cleared by the client. After the bit + * has been cleared, subsequent references are not guaranteed to set + * it again until the translation has been flushed from the TLB. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_DIRTY (__HV_PTE_ONE << HV_PTE_INDEX_DIRTY) + +/** Migrating bit in PTE. + * + * This bit is guaranteed not to be inspected or modified by the + * hypervisor. The name is indicative of the suggested use by the client + * to tag pages whose L3 cache is being migrated from one cpu to another. + */ +#define HV_PTE_MIGRATING (__HV_PTE_ONE << HV_PTE_INDEX_MIGRATING) + +/** Client-private bit in PTE. + * + * This bit is guaranteed not to be inspected or modified by the + * hypervisor. + */ +#define HV_PTE_CLIENT0 (__HV_PTE_ONE << HV_PTE_INDEX_CLIENT0) + +/** Client-private bit in PTE. + * + * This bit is guaranteed not to be inspected or modified by the + * hypervisor. + */ +#define HV_PTE_CLIENT1 (__HV_PTE_ONE << HV_PTE_INDEX_CLIENT1) + +/** Non-coherent (NC) bit in PTE. + * + * If this bit is set, the mapping that is set up will be non-coherent + * (also known as non-inclusive). This means that changes to the L3 + * cache will not cause a local copy to be invalidated. It is generally + * recommended only for read-only mappings. + * + * In level-1 PTEs, if the Page bit is clear, this bit determines how the + * level-2 page table is accessed. + */ +#define HV_PTE_NC (__HV_PTE_ONE << HV_PTE_INDEX_NC) + +/** Is this page prevented from filling the L1$? + * + * If this bit is set, the page described by the PTE will not be cached + * the local cpu's L1 cache. + * + * If CHIP_HAS_NC_AND_NOALLOC_BITS() is not true in for this chip, + * it is illegal to use this attribute, and may cause client termination. + * + * In level-1 PTEs, if the Page bit is clear, this bit + * determines how the level-2 page table is accessed. + */ +#define HV_PTE_NO_ALLOC_L1 (__HV_PTE_ONE << HV_PTE_INDEX_NO_ALLOC_L1) + +/** Is this page prevented from filling the L2$? + * + * If this bit is set, the page described by the PTE will not be cached + * the local cpu's L2 cache. + * + * If CHIP_HAS_NC_AND_NOALLOC_BITS() is not true in for this chip, + * it is illegal to use this attribute, and may cause client termination. + * + * In level-1 PTEs, if the Page bit is clear, this bit determines how the + * level-2 page table is accessed. + */ +#define HV_PTE_NO_ALLOC_L2 (__HV_PTE_ONE << HV_PTE_INDEX_NO_ALLOC_L2) + +/** Is this a priority page? + * + * If this bit is set, the page described by the PTE will be given + * priority in the cache. Normally this translates into allowing the + * page to use only the "red" half of the cache. The client may wish to + * then use the hv_set_caching service to specify that other pages which + * alias this page will use only the "black" half of the cache. + * + * If the Cached Priority bit is clear, the hypervisor uses the + * current hv_set_caching() value to choose how to cache the page. + * + * It is illegal to set the Cached Priority bit if the Non-Cached bit + * is set and the Cached Remotely bit is clear, i.e. if requests to + * the page map directly to memory. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_CACHED_PRIORITY (__HV_PTE_ONE << \ + HV_PTE_INDEX_CACHED_PRIORITY) + +/** Is this a readable mapping? + * + * If this bit is set, code will be permitted to read from (e.g., + * issue load instructions against) the virtual addresses mapped by + * this PTE. + * + * It is illegal for this bit to be clear if the Writable bit is set. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_READABLE (__HV_PTE_ONE << HV_PTE_INDEX_READABLE) + +/** Is this a writable mapping? + * + * If this bit is set, code will be permitted to write to (e.g., issue + * store instructions against) the virtual addresses mapped by this + * PTE. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_WRITABLE (__HV_PTE_ONE << HV_PTE_INDEX_WRITABLE) + +/** Is this an executable mapping? + * + * If this bit is set, code will be permitted to execute from + * (e.g., jump to) the virtual addresses mapped by this PTE. + * + * This bit applies to any processor on the tile, if there are more + * than one. + * + * This bit is ignored in level-1 PTEs unless the Page bit is set. + */ +#define HV_PTE_EXECUTABLE (__HV_PTE_ONE << HV_PTE_INDEX_EXECUTABLE) + +/** The width of a LOTAR's x or y bitfield. */ +#define HV_LOTAR_WIDTH 11 + +/** Converts an x,y pair to a LOTAR value. */ +#define HV_XY_TO_LOTAR(x, y) ((HV_LOTAR)(((x) << HV_LOTAR_WIDTH) | (y))) + +/** Extracts the X component of a lotar. */ +#define HV_LOTAR_X(lotar) ((lotar) >> HV_LOTAR_WIDTH) + +/** Extracts the Y component of a lotar. */ +#define HV_LOTAR_Y(lotar) ((lotar) & ((1 << HV_LOTAR_WIDTH) - 1)) + +#ifndef __ASSEMBLER__ + +/** Define accessor functions for a PTE bit. */ +#define _HV_BIT(name, bit) \ +static __inline int \ +hv_pte_get_##name(HV_PTE pte) \ +{ \ + return (pte.val >> HV_PTE_INDEX_##bit) & 1; \ +} \ + \ +static __inline HV_PTE \ +hv_pte_set_##name(HV_PTE pte) \ +{ \ + pte.val |= 1ULL << HV_PTE_INDEX_##bit; \ + return pte; \ +} \ + \ +static __inline HV_PTE \ +hv_pte_clear_##name(HV_PTE pte) \ +{ \ + pte.val &= ~(1ULL << HV_PTE_INDEX_##bit); \ + return pte; \ +} + +/* Generate accessors to get, set, and clear various PTE flags. + */ +_HV_BIT(present, PRESENT) +_HV_BIT(page, PAGE) +_HV_BIT(client0, CLIENT0) +_HV_BIT(client1, CLIENT1) +_HV_BIT(migrating, MIGRATING) +_HV_BIT(nc, NC) +_HV_BIT(readable, READABLE) +_HV_BIT(writable, WRITABLE) +_HV_BIT(executable, EXECUTABLE) +_HV_BIT(accessed, ACCESSED) +_HV_BIT(dirty, DIRTY) +_HV_BIT(no_alloc_l1, NO_ALLOC_L1) +_HV_BIT(no_alloc_l2, NO_ALLOC_L2) +_HV_BIT(cached_priority, CACHED_PRIORITY) +_HV_BIT(global, GLOBAL) +_HV_BIT(user, USER) + +#undef _HV_BIT + +/** Get the page mode from the PTE. + * + * This field generally determines whether and how accesses to the page + * are cached; the HV_PTE_MODE_xxx symbols define the legal values for the + * page mode. The NC, NO_ALLOC_L1, and NO_ALLOC_L2 bits modify this + * general policy. + */ +static __inline unsigned int +hv_pte_get_mode(const HV_PTE pte) +{ + return (((__hv32) pte.val) >> HV_PTE_INDEX_MODE) & + ((1 << HV_PTE_MODE_BITS) - 1); +} + +/** Set the page mode into a PTE. See hv_pte_get_mode. */ +static __inline HV_PTE +hv_pte_set_mode(HV_PTE pte, unsigned int val) +{ + pte.val &= ~(((1ULL << HV_PTE_MODE_BITS) - 1) << HV_PTE_INDEX_MODE); + pte.val |= val << HV_PTE_INDEX_MODE; + return pte; +} + +/** Get the page frame number from the PTE. + * + * This field contains the upper bits of the CPA (client physical + * address) of the target page; the complete CPA is this field with + * HV_LOG2_PAGE_SIZE_SMALL zero bits appended to it. + * + * For PTEs in a level-1 page table where the Page bit is set, the + * CPA must be aligned modulo the large page size. + */ +static __inline unsigned int +hv_pte_get_pfn(const HV_PTE pte) +{ + return pte.val >> HV_PTE_INDEX_PFN; +} + + +/** Set the page frame number into a PTE. See hv_pte_get_pfn. */ +static __inline HV_PTE +hv_pte_set_pfn(HV_PTE pte, unsigned int val) +{ + /* + * Note that the use of "PTFN" in the next line is intentional; we + * don't want any garbage lower bits left in that field. + */ + pte.val &= ~(((1ULL << HV_PTE_PTFN_BITS) - 1) << HV_PTE_INDEX_PTFN); + pte.val |= (__hv64) val << HV_PTE_INDEX_PFN; + return pte; +} + +/** Get the page table frame number from the PTE. + * + * This field contains the upper bits of the CPA (client physical + * address) of the target page table; the complete CPA is this field with + * with HV_PAGE_TABLE_ALIGN zero bits appended to it. + * + * For PTEs in a level-1 page table when the Page bit is not set, the + * CPA must be aligned modulo the sticter of HV_PAGE_TABLE_ALIGN and + * the level-2 page table size. + */ +static __inline unsigned long +hv_pte_get_ptfn(const HV_PTE pte) +{ + return pte.val >> HV_PTE_INDEX_PTFN; +} + + +/** Set the page table frame number into a PTE. See hv_pte_get_ptfn. */ +static __inline HV_PTE +hv_pte_set_ptfn(HV_PTE pte, unsigned long val) +{ + pte.val &= ~(((1ULL << HV_PTE_PTFN_BITS)-1) << HV_PTE_INDEX_PTFN); + pte.val |= (__hv64) val << HV_PTE_INDEX_PTFN; + return pte; +} + + +/** Get the remote tile caching this page. + * + * Specifies the remote tile which is providing the L3 cache for this page. + * + * This field is ignored unless the page mode is HV_PTE_MODE_CACHE_TILE_L3. + * + * In level-1 PTEs, if the Page bit is clear, this field determines how the + * level-2 page table is accessed. + */ +static __inline unsigned int +hv_pte_get_lotar(const HV_PTE pte) +{ + unsigned int lotar = ((__hv32) pte.val) >> HV_PTE_INDEX_LOTAR; + + return HV_XY_TO_LOTAR( (lotar >> (HV_PTE_LOTAR_BITS / 2)), + (lotar & ((1 << (HV_PTE_LOTAR_BITS / 2)) - 1)) ); +} + + +/** Set the remote tile caching a page into a PTE. See hv_pte_get_lotar. */ +static __inline HV_PTE +hv_pte_set_lotar(HV_PTE pte, unsigned int val) +{ + unsigned int x = HV_LOTAR_X(val); + unsigned int y = HV_LOTAR_Y(val); + + pte.val &= ~(((1ULL << HV_PTE_LOTAR_BITS)-1) << HV_PTE_INDEX_LOTAR); + pte.val |= (x << (HV_PTE_INDEX_LOTAR + HV_PTE_LOTAR_BITS / 2)) | + (y << HV_PTE_INDEX_LOTAR); + return pte; +} + +#endif /* !__ASSEMBLER__ */ + +/** Converts a client physical address to a pfn. */ +#define HV_CPA_TO_PFN(p) ((p) >> HV_LOG2_PAGE_SIZE_SMALL) + +/** Converts a pfn to a client physical address. */ +#define HV_PFN_TO_CPA(p) (((HV_PhysAddr)(p)) << HV_LOG2_PAGE_SIZE_SMALL) + +/** Converts a client physical address to a ptfn. */ +#define HV_CPA_TO_PTFN(p) ((p) >> HV_LOG2_PAGE_TABLE_ALIGN) + +/** Converts a ptfn to a client physical address. */ +#define HV_PTFN_TO_CPA(p) (((HV_PhysAddr)(p)) << HV_LOG2_PAGE_TABLE_ALIGN) + +/** Converts a ptfn to a pfn. */ +#define HV_PTFN_TO_PFN(p) \ + ((p) >> (HV_LOG2_PAGE_SIZE_SMALL - HV_LOG2_PAGE_TABLE_ALIGN)) + +/** Converts a pfn to a ptfn. */ +#define HV_PFN_TO_PTFN(p) \ + ((p) << (HV_LOG2_PAGE_SIZE_SMALL - HV_LOG2_PAGE_TABLE_ALIGN)) + +#if CHIP_VA_WIDTH() > 32 + +/** Log number of HV_PTE entries in L0 page table */ +#define HV_LOG2_L0_ENTRIES (CHIP_VA_WIDTH() - HV_LOG2_L1_SPAN) + +/** Number of HV_PTE entries in L0 page table */ +#define HV_L0_ENTRIES (1 << HV_LOG2_L0_ENTRIES) + +/** Log size of L0 page table in bytes */ +#define HV_LOG2_L0_SIZE (HV_LOG2_PTE_SIZE + HV_LOG2_L0_ENTRIES) + +/** Size of L0 page table in bytes */ +#define HV_L0_SIZE (1 << HV_LOG2_L0_SIZE) + +#ifdef __ASSEMBLER__ + +/** Index in L0 for a specific VA */ +#define HV_L0_INDEX(va) \ + (((va) >> HV_LOG2_L1_SPAN) & (HV_L0_ENTRIES - 1)) + +#else + +/** Index in L1 for a specific VA */ +#define HV_L0_INDEX(va) \ + (((HV_VirtAddr)(va) >> HV_LOG2_L1_SPAN) & (HV_L0_ENTRIES - 1)) + +#endif + +#endif /* CHIP_VA_WIDTH() > 32 */ + +/** Log number of HV_PTE entries in L1 page table */ +#define HV_LOG2_L1_ENTRIES (HV_LOG2_L1_SPAN - HV_LOG2_PAGE_SIZE_LARGE) + +/** Number of HV_PTE entries in L1 page table */ +#define HV_L1_ENTRIES (1 << HV_LOG2_L1_ENTRIES) + +/** Log size of L1 page table in bytes */ +#define HV_LOG2_L1_SIZE (HV_LOG2_PTE_SIZE + HV_LOG2_L1_ENTRIES) + +/** Size of L1 page table in bytes */ +#define HV_L1_SIZE (1 << HV_LOG2_L1_SIZE) + +/** Log number of HV_PTE entries in level-2 page table */ +#define HV_LOG2_L2_ENTRIES (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL) + +/** Number of HV_PTE entries in level-2 page table */ +#define HV_L2_ENTRIES (1 << HV_LOG2_L2_ENTRIES) + +/** Log size of level-2 page table in bytes */ +#define HV_LOG2_L2_SIZE (HV_LOG2_PTE_SIZE + HV_LOG2_L2_ENTRIES) + +/** Size of level-2 page table in bytes */ +#define HV_L2_SIZE (1 << HV_LOG2_L2_SIZE) + +#ifdef __ASSEMBLER__ + +#if CHIP_VA_WIDTH() > 32 + +/** Index in L1 for a specific VA */ +#define HV_L1_INDEX(va) \ + (((va) >> HV_LOG2_PAGE_SIZE_LARGE) & (HV_L1_ENTRIES - 1)) + +#else /* CHIP_VA_WIDTH() > 32 */ + +/** Index in L1 for a specific VA */ +#define HV_L1_INDEX(va) \ + (((va) >> HV_LOG2_PAGE_SIZE_LARGE)) + +#endif /* CHIP_VA_WIDTH() > 32 */ + +/** Index in level-2 page table for a specific VA */ +#define HV_L2_INDEX(va) \ + (((va) >> HV_LOG2_PAGE_SIZE_SMALL) & (HV_L2_ENTRIES - 1)) + +#else /* __ASSEMBLER __ */ + +#if CHIP_VA_WIDTH() > 32 + +/** Index in L1 for a specific VA */ +#define HV_L1_INDEX(va) \ + (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_LARGE) & (HV_L1_ENTRIES - 1)) + +#else /* CHIP_VA_WIDTH() > 32 */ + +/** Index in L1 for a specific VA */ +#define HV_L1_INDEX(va) \ + (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_LARGE)) + +#endif /* CHIP_VA_WIDTH() > 32 */ + +/** Index in level-2 page table for a specific VA */ +#define HV_L2_INDEX(va) \ + (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_SMALL) & (HV_L2_ENTRIES - 1)) + +#endif /* __ASSEMBLER __ */ + +#endif /* _TILE_HV_H */ diff --git a/arch/tile/include/hv/syscall_public.h b/arch/tile/include/hv/syscall_public.h new file mode 100644 index 000000000000..9cc0837e69fd --- /dev/null +++ b/arch/tile/include/hv/syscall_public.h @@ -0,0 +1,42 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/** + * @file syscall.h + * Indices for the hypervisor system calls that are intended to be called + * directly, rather than only through hypervisor-generated "glue" code. + */ + +#ifndef _SYS_HV_INCLUDE_SYSCALL_PUBLIC_H +#define _SYS_HV_INCLUDE_SYSCALL_PUBLIC_H + +/** Fast syscall flag bit location. When this bit is set, the hypervisor + * handles the syscall specially. + */ +#define HV_SYS_FAST_SHIFT 14 + +/** Fast syscall flag bit mask. */ +#define HV_SYS_FAST_MASK (1 << HV_SYS_FAST_SHIFT) + +/** Bit location for flagging fast syscalls that can be called from PL0. */ +#define HV_SYS_FAST_PLO_SHIFT 13 + +/** Fast syscall allowing PL0 bit mask. */ +#define HV_SYS_FAST_PL0_MASK (1 << HV_SYS_FAST_PLO_SHIFT) + +/** Perform an MF that waits for all victims to reach DRAM. */ +#define HV_SYS_fence_incoherent (51 | HV_SYS_FAST_MASK \ + | HV_SYS_FAST_PL0_MASK) + +#endif /* !_SYS_HV_INCLUDE_SYSCALL_PUBLIC_H */ diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile new file mode 100644 index 000000000000..756e6ec452d3 --- /dev/null +++ b/arch/tile/kernel/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the Linux/TILE kernel. +# + +extra-y := vmlinux.lds head_$(BITS).o +obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ + pci-dma.o proc.o process.o ptrace.o reboot.o \ + setup.o signal.o single_step.o stack.o sys.o time.o traps.o \ + intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o + +obj-$(CONFIG_TILEGX) += futex_64.o +obj-$(CONFIG_COMPAT) += compat.o compat_signal.o +obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o +obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o diff --git a/arch/tile/kernel/asm-offsets.c b/arch/tile/kernel/asm-offsets.c new file mode 100644 index 000000000000..01ddf19cc36d --- /dev/null +++ b/arch/tile/kernel/asm-offsets.c @@ -0,0 +1,76 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Generates definitions from c-type structures used by assembly sources. + */ + +#include +#include +#include +#include +#include +#include + +/* Check for compatible compiler early in the build. */ +#ifdef CONFIG_TILEGX +# ifndef __tilegx__ +# error Can only build TILE-Gx configurations with tilegx compiler +# endif +# ifndef __LP64__ +# error Must not specify -m32 when building the TILE-Gx kernel +# endif +#else +# ifdef __tilegx__ +# error Can not build TILEPro/TILE64 configurations with tilegx compiler +# endif +#endif + +void foo(void) +{ + DEFINE(SINGLESTEP_STATE_BUFFER_OFFSET, \ + offsetof(struct single_step_state, buffer)); + DEFINE(SINGLESTEP_STATE_FLAGS_OFFSET, \ + offsetof(struct single_step_state, flags)); + DEFINE(SINGLESTEP_STATE_ORIG_PC_OFFSET, \ + offsetof(struct single_step_state, orig_pc)); + DEFINE(SINGLESTEP_STATE_NEXT_PC_OFFSET, \ + offsetof(struct single_step_state, next_pc)); + DEFINE(SINGLESTEP_STATE_BRANCH_NEXT_PC_OFFSET, \ + offsetof(struct single_step_state, branch_next_pc)); + DEFINE(SINGLESTEP_STATE_UPDATE_VALUE_OFFSET, \ + offsetof(struct single_step_state, update_value)); + + DEFINE(THREAD_INFO_TASK_OFFSET, \ + offsetof(struct thread_info, task)); + DEFINE(THREAD_INFO_FLAGS_OFFSET, \ + offsetof(struct thread_info, flags)); + DEFINE(THREAD_INFO_STATUS_OFFSET, \ + offsetof(struct thread_info, status)); + DEFINE(THREAD_INFO_HOMECACHE_CPU_OFFSET, \ + offsetof(struct thread_info, homecache_cpu)); + DEFINE(THREAD_INFO_STEP_STATE_OFFSET, \ + offsetof(struct thread_info, step_state)); + + DEFINE(TASK_STRUCT_THREAD_KSP_OFFSET, + offsetof(struct task_struct, thread.ksp)); + DEFINE(TASK_STRUCT_THREAD_PC_OFFSET, + offsetof(struct task_struct, thread.pc)); + + DEFINE(HV_TOPOLOGY_WIDTH_OFFSET, \ + offsetof(HV_Topology, width)); + DEFINE(HV_TOPOLOGY_HEIGHT_OFFSET, \ + offsetof(HV_Topology, height)); + + DEFINE(IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET, \ + offsetof(irq_cpustat_t, irq_syscall_count)); +} diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c new file mode 100644 index 000000000000..1b0a410ef5e7 --- /dev/null +++ b/arch/tile/kernel/backtrace.c @@ -0,0 +1,634 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include + +#include + +#include + +#if TILE_CHIP < 10 + + +#include + + +#define TREG_SP 54 +#define TREG_LR 55 + + +/** A decoded bundle used for backtracer analysis. */ +typedef struct { + tile_bundle_bits bits; + int num_insns; + struct tile_decoded_instruction + insns[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]; +} BacktraceBundle; + + +/* This implementation only makes sense for native tools. */ +/** Default function to read memory. */ +static bool +bt_read_memory(void *result, VirtualAddress addr, size_t size, void *extra) +{ + /* FIXME: this should do some horrible signal stuff to catch + * SEGV cleanly and fail. + * + * Or else the caller should do the setjmp for efficiency. + */ + + memcpy(result, (const void *)addr, size); + return true; +} + + +/** Locates an instruction inside the given bundle that + * has the specified mnemonic, and whose first 'num_operands_to_match' + * operands exactly match those in 'operand_values'. + */ +static const struct tile_decoded_instruction* +find_matching_insn(const BacktraceBundle *bundle, + tile_mnemonic mnemonic, + const int *operand_values, + int num_operands_to_match) +{ + int i, j; + bool match; + + for (i = 0; i < bundle->num_insns; i++) { + const struct tile_decoded_instruction *insn = + &bundle->insns[i]; + + if (insn->opcode->mnemonic != mnemonic) + continue; + + match = true; + for (j = 0; j < num_operands_to_match; j++) { + if (operand_values[j] != insn->operand_values[j]) { + match = false; + break; + } + } + + if (match) + return insn; + } + + return NULL; +} + +/** Does this bundle contain an 'iret' instruction? */ +static inline bool +bt_has_iret(const BacktraceBundle *bundle) +{ + return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL; +} + +/** Does this bundle contain an 'addi sp, sp, OFFSET' or + * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET? + */ +static bool +bt_has_addi_sp(const BacktraceBundle *bundle, int *adjust) +{ + static const int vals[2] = { TREG_SP, TREG_SP }; + + const struct tile_decoded_instruction *insn = + find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); + if (insn == NULL) + insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); + if (insn == NULL) + return false; + + *adjust = insn->operand_values[2]; + return true; +} + +/** Does this bundle contain any 'info OP' or 'infol OP' + * instruction, and if so, what are their OP? Note that OP is interpreted + * as an unsigned value by this code since that's what the caller wants. + * Returns the number of info ops found. + */ +static int +bt_get_info_ops(const BacktraceBundle *bundle, + int operands[MAX_INFO_OPS_PER_BUNDLE]) +{ + int num_ops = 0; + int i; + + for (i = 0; i < bundle->num_insns; i++) { + const struct tile_decoded_instruction *insn = + &bundle->insns[i]; + + if (insn->opcode->mnemonic == TILE_OPC_INFO || + insn->opcode->mnemonic == TILE_OPC_INFOL) { + operands[num_ops++] = insn->operand_values[0]; + } + } + + return num_ops; +} + +/** Does this bundle contain a jrp instruction, and if so, to which + * register is it jumping? + */ +static bool +bt_has_jrp(const BacktraceBundle *bundle, int *target_reg) +{ + const struct tile_decoded_instruction *insn = + find_matching_insn(bundle, TILE_OPC_JRP, NULL, 0); + if (insn == NULL) + return false; + + *target_reg = insn->operand_values[0]; + return true; +} + +/** Does this bundle modify the specified register in any way? */ +static bool +bt_modifies_reg(const BacktraceBundle *bundle, int reg) +{ + int i, j; + for (i = 0; i < bundle->num_insns; i++) { + const struct tile_decoded_instruction *insn = + &bundle->insns[i]; + + if (insn->opcode->implicitly_written_register == reg) + return true; + + for (j = 0; j < insn->opcode->num_operands; j++) + if (insn->operands[j]->is_dest_reg && + insn->operand_values[j] == reg) + return true; + } + + return false; +} + +/** Does this bundle modify sp? */ +static inline bool +bt_modifies_sp(const BacktraceBundle *bundle) +{ + return bt_modifies_reg(bundle, TREG_SP); +} + +/** Does this bundle modify lr? */ +static inline bool +bt_modifies_lr(const BacktraceBundle *bundle) +{ + return bt_modifies_reg(bundle, TREG_LR); +} + +/** Does this bundle contain the instruction 'move fp, sp'? */ +static inline bool +bt_has_move_r52_sp(const BacktraceBundle *bundle) +{ + static const int vals[2] = { 52, TREG_SP }; + return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; +} + +/** Does this bundle contain the instruction 'sw sp, lr'? */ +static inline bool +bt_has_sw_sp_lr(const BacktraceBundle *bundle) +{ + static const int vals[2] = { TREG_SP, TREG_LR }; + return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL; +} + +/** Locates the caller's PC and SP for a program starting at the + * given address. + */ +static void +find_caller_pc_and_caller_sp(CallerLocation *location, + const VirtualAddress start_pc, + BacktraceMemoryReader read_memory_func, + void *read_memory_func_extra) +{ + /* Have we explicitly decided what the sp is, + * rather than just the default? + */ + bool sp_determined = false; + + /* Has any bundle seen so far modified lr? */ + bool lr_modified = false; + + /* Have we seen a move from sp to fp? */ + bool sp_moved_to_r52 = false; + + /* Have we seen a terminating bundle? */ + bool seen_terminating_bundle = false; + + /* Cut down on round-trip reading overhead by reading several + * bundles at a time. + */ + tile_bundle_bits prefetched_bundles[32]; + int num_bundles_prefetched = 0; + int next_bundle = 0; + VirtualAddress pc; + + /* Default to assuming that the caller's sp is the current sp. + * This is necessary to handle the case where we start backtracing + * right at the end of the epilog. + */ + location->sp_location = SP_LOC_OFFSET; + location->sp_offset = 0; + + /* Default to having no idea where the caller PC is. */ + location->pc_location = PC_LOC_UNKNOWN; + + /* Don't even try if the PC is not aligned. */ + if (start_pc % TILE_BUNDLE_ALIGNMENT_IN_BYTES != 0) + return; + + for (pc = start_pc;; pc += sizeof(tile_bundle_bits)) { + + BacktraceBundle bundle; + int num_info_ops, info_operands[MAX_INFO_OPS_PER_BUNDLE]; + int one_ago, jrp_reg; + bool has_jrp; + + if (next_bundle >= num_bundles_prefetched) { + /* Prefetch some bytes, but don't cross a page + * boundary since that might cause a read failure we + * don't care about if we only need the first few + * bytes. Note: we don't care what the actual page + * size is; using the minimum possible page size will + * prevent any problems. + */ + unsigned int bytes_to_prefetch = 4096 - (pc & 4095); + if (bytes_to_prefetch > sizeof prefetched_bundles) + bytes_to_prefetch = sizeof prefetched_bundles; + + if (!read_memory_func(prefetched_bundles, pc, + bytes_to_prefetch, + read_memory_func_extra)) { + if (pc == start_pc) { + /* The program probably called a bad + * address, such as a NULL pointer. + * So treat this as if we are at the + * start of the function prolog so the + * backtrace will show how we got here. + */ + location->pc_location = PC_LOC_IN_LR; + return; + } + + /* Unreadable address. Give up. */ + break; + } + + next_bundle = 0; + num_bundles_prefetched = + bytes_to_prefetch / sizeof(tile_bundle_bits); + } + + /* Decode the next bundle. */ + bundle.bits = prefetched_bundles[next_bundle++]; + bundle.num_insns = + parse_insn_tile(bundle.bits, pc, bundle.insns); + num_info_ops = bt_get_info_ops(&bundle, info_operands); + + /* First look at any one_ago info ops if they are interesting, + * since they should shadow any non-one-ago info ops. + */ + for (one_ago = (pc != start_pc) ? 1 : 0; + one_ago >= 0; one_ago--) { + int i; + for (i = 0; i < num_info_ops; i++) { + int info_operand = info_operands[i]; + if (info_operand < CALLER_UNKNOWN_BASE) { + /* Weird; reserved value, ignore it. */ + continue; + } + + /* Skip info ops which are not in the + * "one_ago" mode we want right now. + */ + if (((info_operand & ONE_BUNDLE_AGO_FLAG) != 0) + != (one_ago != 0)) + continue; + + /* Clear the flag to make later checking + * easier. */ + info_operand &= ~ONE_BUNDLE_AGO_FLAG; + + /* Default to looking at PC_IN_LR_FLAG. */ + if (info_operand & PC_IN_LR_FLAG) + location->pc_location = + PC_LOC_IN_LR; + else + location->pc_location = + PC_LOC_ON_STACK; + + switch (info_operand) { + case CALLER_UNKNOWN_BASE: + location->pc_location = PC_LOC_UNKNOWN; + location->sp_location = SP_LOC_UNKNOWN; + return; + + case CALLER_SP_IN_R52_BASE: + case CALLER_SP_IN_R52_BASE | PC_IN_LR_FLAG: + location->sp_location = SP_LOC_IN_R52; + return; + + default: + { + const unsigned int val = info_operand + - CALLER_SP_OFFSET_BASE; + const unsigned int sp_offset = + (val >> NUM_INFO_OP_FLAGS) * 8; + if (sp_offset < 32768) { + /* This is a properly encoded + * SP offset. */ + location->sp_location = + SP_LOC_OFFSET; + location->sp_offset = + sp_offset; + return; + } else { + /* This looked like an SP + * offset, but it's outside + * the legal range, so this + * must be an unrecognized + * info operand. Ignore it. + */ + } + } + break; + } + } + } + + if (seen_terminating_bundle) { + /* We saw a terminating bundle during the previous + * iteration, so we were only looking for an info op. + */ + break; + } + + if (bundle.bits == 0) { + /* Wacky terminating bundle. Stop looping, and hope + * we've already seen enough to find the caller. + */ + break; + } + + /* + * Try to determine caller's SP. + */ + + if (!sp_determined) { + int adjust; + if (bt_has_addi_sp(&bundle, &adjust)) { + location->sp_location = SP_LOC_OFFSET; + + if (adjust <= 0) { + /* We are in prolog about to adjust + * SP. */ + location->sp_offset = 0; + } else { + /* We are in epilog restoring SP. */ + location->sp_offset = adjust; + } + + sp_determined = true; + } else { + if (bt_has_move_r52_sp(&bundle)) { + /* Maybe in prolog, creating an + * alloca-style frame. But maybe in + * the middle of a fixed-size frame + * clobbering r52 with SP. + */ + sp_moved_to_r52 = true; + } + + if (bt_modifies_sp(&bundle)) { + if (sp_moved_to_r52) { + /* We saw SP get saved into + * r52 earlier (or now), which + * must have been in the + * prolog, so we now know that + * SP is still holding the + * caller's sp value. + */ + location->sp_location = + SP_LOC_OFFSET; + location->sp_offset = 0; + } else { + /* Someone must have saved + * aside the caller's SP value + * into r52, so r52 holds the + * current value. + */ + location->sp_location = + SP_LOC_IN_R52; + } + sp_determined = true; + } + } + } + + if (bt_has_iret(&bundle)) { + /* This is a terminating bundle. */ + seen_terminating_bundle = true; + continue; + } + + /* + * Try to determine caller's PC. + */ + + jrp_reg = -1; + has_jrp = bt_has_jrp(&bundle, &jrp_reg); + if (has_jrp) + seen_terminating_bundle = true; + + if (location->pc_location == PC_LOC_UNKNOWN) { + if (has_jrp) { + if (jrp_reg == TREG_LR && !lr_modified) { + /* Looks like a leaf function, or else + * lr is already restored. */ + location->pc_location = + PC_LOC_IN_LR; + } else { + location->pc_location = + PC_LOC_ON_STACK; + } + } else if (bt_has_sw_sp_lr(&bundle)) { + /* In prolog, spilling initial lr to stack. */ + location->pc_location = PC_LOC_IN_LR; + } else if (bt_modifies_lr(&bundle)) { + lr_modified = true; + } + } + } +} + +void +backtrace_init(BacktraceIterator *state, + BacktraceMemoryReader read_memory_func, + void *read_memory_func_extra, + VirtualAddress pc, VirtualAddress lr, + VirtualAddress sp, VirtualAddress r52) +{ + CallerLocation location; + VirtualAddress fp, initial_frame_caller_pc; + + if (read_memory_func == NULL) { + read_memory_func = bt_read_memory; + } + + /* Find out where we are in the initial frame. */ + find_caller_pc_and_caller_sp(&location, pc, + read_memory_func, read_memory_func_extra); + + switch (location.sp_location) { + case SP_LOC_UNKNOWN: + /* Give up. */ + fp = -1; + break; + + case SP_LOC_IN_R52: + fp = r52; + break; + + case SP_LOC_OFFSET: + fp = sp + location.sp_offset; + break; + + default: + /* Give up. */ + fp = -1; + break; + } + + /* The frame pointer should theoretically be aligned mod 8. If + * it's not even aligned mod 4 then something terrible happened + * and we should mark it as invalid. + */ + if (fp % 4 != 0) + fp = -1; + + /* -1 means "don't know initial_frame_caller_pc". */ + initial_frame_caller_pc = -1; + + switch (location.pc_location) { + case PC_LOC_UNKNOWN: + /* Give up. */ + fp = -1; + break; + + case PC_LOC_IN_LR: + if (lr == 0 || lr % TILE_BUNDLE_ALIGNMENT_IN_BYTES != 0) { + /* Give up. */ + fp = -1; + } else { + initial_frame_caller_pc = lr; + } + break; + + case PC_LOC_ON_STACK: + /* Leave initial_frame_caller_pc as -1, + * meaning check the stack. + */ + break; + + default: + /* Give up. */ + fp = -1; + break; + } + + state->pc = pc; + state->sp = sp; + state->fp = fp; + state->initial_frame_caller_pc = initial_frame_caller_pc; + state->read_memory_func = read_memory_func; + state->read_memory_func_extra = read_memory_func_extra; +} + +bool +backtrace_next(BacktraceIterator *state) +{ + VirtualAddress next_fp, next_pc, next_frame[2]; + + if (state->fp == -1) { + /* No parent frame. */ + return false; + } + + /* Try to read the frame linkage data chaining to the next function. */ + if (!state->read_memory_func(&next_frame, state->fp, sizeof next_frame, + state->read_memory_func_extra)) { + return false; + } + + next_fp = next_frame[1]; + if (next_fp % 4 != 0) { + /* Caller's frame pointer is suspect, so give up. + * Technically it should be aligned mod 8, but we will + * be forgiving here. + */ + return false; + } + + if (state->initial_frame_caller_pc != -1) { + /* We must be in the initial stack frame and already know the + * caller PC. + */ + next_pc = state->initial_frame_caller_pc; + + /* Force reading stack next time, in case we were in the + * initial frame. We don't do this above just to paranoidly + * avoid changing the struct at all when we return false. + */ + state->initial_frame_caller_pc = -1; + } else { + /* Get the caller PC from the frame linkage area. */ + next_pc = next_frame[0]; + if (next_pc == 0 || + next_pc % TILE_BUNDLE_ALIGNMENT_IN_BYTES != 0) { + /* The PC is suspect, so give up. */ + return false; + } + } + + /* Update state to become the caller's stack frame. */ + state->pc = next_pc; + state->sp = state->fp; + state->fp = next_fp; + + return true; +} + +#else /* TILE_CHIP < 10 */ + +void +backtrace_init(BacktraceIterator *state, + BacktraceMemoryReader read_memory_func, + void *read_memory_func_extra, + VirtualAddress pc, VirtualAddress lr, + VirtualAddress sp, VirtualAddress r52) +{ + state->pc = pc; + state->sp = sp; + state->fp = -1; + state->initial_frame_caller_pc = -1; + state->read_memory_func = read_memory_func; + state->read_memory_func_extra = read_memory_func_extra; +} + +bool backtrace_next(BacktraceIterator *state) { return false; } + +#endif /* TILE_CHIP < 10 */ diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c new file mode 100644 index 000000000000..a374c99deeb6 --- /dev/null +++ b/arch/tile/kernel/compat.c @@ -0,0 +1,183 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +/* Adjust unistd.h to provide 32-bit numbers and functions. */ +#define __SYSCALL_COMPAT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Syscalls that take 64-bit numbers traditionally take them in 32-bit + * "high" and "low" value parts on 32-bit architectures. + * In principle, one could imagine passing some register arguments as + * fully 64-bit on TILE-Gx in 32-bit mode, but it seems easier to + * adapt the usual convention. + */ + +long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high) +{ + return sys_truncate(filename, ((loff_t)high << 32) | low); +} + +long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high) +{ + return sys_ftruncate(fd, ((loff_t)high << 32) | low); +} + +long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, + u32 dummy, u32 low, u32 high) +{ + return sys_pread64(fd, ubuf, count, ((loff_t)high << 32) | low); +} + +long compat_sys_pwrite64(unsigned int fd, char __user *ubuf, size_t count, + u32 dummy, u32 low, u32 high) +{ + return sys_pwrite64(fd, ubuf, count, ((loff_t)high << 32) | low); +} + +long compat_sys_lookup_dcookie(u32 low, u32 high, char __user *buf, size_t len) +{ + return sys_lookup_dcookie(((loff_t)high << 32) | low, buf, len); +} + +long compat_sys_sync_file_range2(int fd, unsigned int flags, + u32 offset_lo, u32 offset_hi, + u32 nbytes_lo, u32 nbytes_hi) +{ + return sys_sync_file_range(fd, ((loff_t)offset_hi << 32) | offset_lo, + ((loff_t)nbytes_hi << 32) | nbytes_lo, + flags); +} + +long compat_sys_fallocate(int fd, int mode, + u32 offset_lo, u32 offset_hi, + u32 len_lo, u32 len_hi) +{ + return sys_fallocate(fd, mode, ((loff_t)offset_hi << 32) | offset_lo, + ((loff_t)len_hi << 32) | len_lo); +} + + + +long compat_sys_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval) +{ + struct timespec t; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); + set_fs(old_fs); + if (put_compat_timespec(&t, interval)) + return -EFAULT; + return ret; +} + +ssize_t compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, + size_t count) +{ + mm_segment_t old_fs = get_fs(); + int ret; + off_t of; + + if (offset && get_user(of, offset)) + return -EFAULT; + + set_fs(KERNEL_DS); + ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, + count); + set_fs(old_fs); + + if (offset && put_user(of, offset)) + return -EFAULT; + return ret; +} + + +/* + * The usual compat_sys_msgsnd() and _msgrcv() seem to be assuming + * some different calling convention than our normal 32-bit tile code. + */ + +/* Already defined in ipc/compat.c, but we need it here. */ +struct compat_msgbuf { + compat_long_t mtype; + char mtext[1]; +}; + +long tile_compat_sys_msgsnd(int msqid, + struct compat_msgbuf __user *msgp, + size_t msgsz, int msgflg) +{ + compat_long_t mtype; + + if (get_user(mtype, &msgp->mtype)) + return -EFAULT; + return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); +} + +long tile_compat_sys_msgrcv(int msqid, + struct compat_msgbuf __user *msgp, + size_t msgsz, long msgtyp, int msgflg) +{ + long err, mtype; + + err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); + if (err < 0) + goto out; + + if (put_user(mtype, &msgp->mtype)) + err = -EFAULT; + out: + return err; +} + +/* Provide the compat syscall number to call mapping. */ +#undef __SYSCALL +#define __SYSCALL(nr, call) [nr] = (compat_##call), + +/* The generic versions of these don't work for Tile. */ +#define compat_sys_msgrcv tile_compat_sys_msgrcv +#define compat_sys_msgsnd tile_compat_sys_msgsnd + +/* See comments in sys.c */ +#define compat_sys_fadvise64 sys32_fadvise64 +#define compat_sys_fadvise64_64 sys32_fadvise64_64 +#define compat_sys_readahead sys32_readahead +#define compat_sys_sync_file_range compat_sys_sync_file_range2 + +/* The native 64-bit "struct stat" matches the 32-bit "struct stat64". */ +#define compat_sys_stat64 sys_newstat +#define compat_sys_lstat64 sys_newlstat +#define compat_sys_fstat64 sys_newfstat +#define compat_sys_fstatat64 sys_newfstatat + +/* Pass full 64-bit values through ptrace. */ +#define compat_sys_ptrace tile_compat_sys_ptrace + +void *compat_sys_call_table[__NR_syscalls] = { + [0 ... __NR_syscalls-1] = sys_ni_syscall, +#include +}; diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c new file mode 100644 index 000000000000..9fa4ba8ed5f4 --- /dev/null +++ b/arch/tile/kernel/compat_signal.c @@ -0,0 +1,433 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct compat_sigaction { + compat_uptr_t sa_handler; + compat_ulong_t sa_flags; + compat_uptr_t sa_restorer; + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct compat_sigaltstack { + compat_uptr_t ss_sp; + int ss_flags; + compat_size_t ss_size; +}; + +struct compat_ucontext { + compat_ulong_t uc_flags; + compat_uptr_t uc_link; + struct compat_sigaltstack uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +struct compat_siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE]; + + /* kill() */ + struct { + unsigned int _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + compat_timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + compat_sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + int _overrun_incr; /* amount to add to overrun */ + } _timer; + + /* POSIX.1b signals */ + struct { + unsigned int _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + unsigned int _pid; /* which child */ + unsigned int _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + unsigned int _addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_TRAPNO + int _trapno; /* TRAP # which caused the signal */ +#endif + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +}; + +struct compat_rt_sigframe { + unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */ + struct compat_siginfo info; + struct compat_ucontext uc; +}; + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, + struct compat_sigaction __user *oact, + size_t sigsetsize) +{ + struct k_sigaction new_sa, old_sa; + int ret = -EINVAL; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + goto out; + + if (act) { + compat_uptr_t handler, restorer; + + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(handler, &act->sa_handler) || + __get_user(new_sa.sa.sa_flags, &act->sa_flags) || + __get_user(restorer, &act->sa_restorer) || + __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask, + sizeof(sigset_t))) + return -EFAULT; + new_sa.sa.sa_handler = compat_ptr(handler); + new_sa.sa.sa_restorer = compat_ptr(restorer); + } + + ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(ptr_to_compat(old_sa.sa.sa_handler), + &oact->sa_handler) || + __put_user(ptr_to_compat(old_sa.sa.sa_restorer), + &oact->sa_restorer) || + __put_user(old_sa.sa.sa_flags, &oact->sa_flags) || + __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask, + sizeof(sigset_t))) + return -EFAULT; + } +out: + return ret; +} + +long compat_sys_rt_sigqueueinfo(int pid, int sig, + struct compat_siginfo __user *uinfo) +{ + siginfo_t info; + int ret; + mm_segment_t old_fs = get_fs(); + + if (copy_siginfo_from_user32(&info, uinfo)) + return -EFAULT; + set_fs(KERNEL_DS); + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); + set_fs(old_fs); + return ret; +} + +int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from) +{ + int err; + + if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo))) + return -EFAULT; + + /* If you change siginfo_t structure, please make sure that + this code is fixed accordingly. + It should never copy any pad contained in the structure + to avoid security leaks, but must copy the generic + 3 ints plus the relevant union member. */ + err = __put_user(from->si_signo, &to->si_signo); + err |= __put_user(from->si_errno, &to->si_errno); + err |= __put_user((short)from->si_code, &to->si_code); + + if (from->si_code < 0) { + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); + } else { + /* + * First 32bits of unions are always present: + * si_pid === si_band === si_tid === si_addr(LS half) + */ + err |= __put_user(from->_sifields._pad[0], + &to->_sifields._pad[0]); + switch (from->si_code >> 16) { + case __SI_FAULT >> 16: + break; + case __SI_CHLD >> 16: + err |= __put_user(from->si_utime, &to->si_utime); + err |= __put_user(from->si_stime, &to->si_stime); + err |= __put_user(from->si_status, &to->si_status); + /* FALL THROUGH */ + default: + case __SI_KILL >> 16: + err |= __put_user(from->si_uid, &to->si_uid); + break; + case __SI_POLL >> 16: + err |= __put_user(from->si_fd, &to->si_fd); + break; + case __SI_TIMER >> 16: + err |= __put_user(from->si_overrun, &to->si_overrun); + err |= __put_user(ptr_to_compat(from->si_ptr), + &to->si_ptr); + break; + /* This is not generated by the kernel as of now. */ + case __SI_RT >> 16: + case __SI_MESGQ >> 16: + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(from->si_int, &to->si_int); + break; + } + } + return err; +} + +int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) +{ + int err; + u32 ptr32; + + if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo))) + return -EFAULT; + + err = __get_user(to->si_signo, &from->si_signo); + err |= __get_user(to->si_errno, &from->si_errno); + err |= __get_user(to->si_code, &from->si_code); + + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + err |= __get_user(ptr32, &from->si_ptr); + to->si_ptr = compat_ptr(ptr32); + + return err; +} + +long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, + struct compat_sigaltstack __user *uoss_ptr, + struct pt_regs *regs) +{ + stack_t uss, uoss; + int ret; + mm_segment_t seg; + + if (uss_ptr) { + u32 ptr; + + memset(&uss, 0, sizeof(stack_t)); + if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) || + __get_user(ptr, &uss_ptr->ss_sp) || + __get_user(uss.ss_flags, &uss_ptr->ss_flags) || + __get_user(uss.ss_size, &uss_ptr->ss_size)) + return -EFAULT; + uss.ss_sp = compat_ptr(ptr); + } + seg = get_fs(); + set_fs(KERNEL_DS); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, + (unsigned long)compat_ptr(regs->sp)); + set_fs(seg); + if (ret >= 0 && uoss_ptr) { + if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || + __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || + __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || + __put_user(uoss.ss_size, &uoss_ptr->ss_size)) + ret = -EFAULT; + } + return ret; +} + +long _compat_sys_rt_sigreturn(struct pt_regs *regs) +{ + struct compat_rt_sigframe __user *frame = + (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); + sigset_t set; + long r0; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) + goto badframe; + + if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) + goto badframe; + + return r0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Determine which stack to use.. + */ +static inline void __user *compat_get_sigframe(struct k_sigaction *ka, + struct pt_regs *regs, + size_t frame_size) +{ + unsigned long sp; + + /* Default to using normal stack */ + sp = (unsigned long)compat_ptr(regs->sp); + + /* + * If we are on the alternate signal stack and would overflow + * it, don't. Return an always-bogus address instead so we + * will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) + return (void __user *) -1L; + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (sas_ss_flags(sp) == 0) + sp = current->sas_ss_sp + current->sas_ss_size; + } + + sp -= frame_size; + /* + * Align the stack pointer according to the TILE ABI, + * i.e. so that on function entry (sp & 15) == 0. + */ + sp &= -16UL; + return (void __user *) sp; +} + +int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + unsigned long restorer; + struct compat_rt_sigframe __user *frame; + int err = 0; + int usig; + + frame = compat_get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + /* Always write at least the signal number for the stack backtracer. */ + if (ka->sa.sa_flags & SA_SIGINFO) { + /* At sigreturn time, restore the callee-save registers too. */ + err |= copy_siginfo_to_user32(&frame->info, info); + regs->flags |= PT_FLAGS_RESTORE_REGS; + } else { + err |= __put_user(info->si_signo, &frame->info.si_signo); + } + + /* Create the ucontext. */ + err |= __clear_user(&frame->save_area, sizeof(frame->save_area)); + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)), + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto give_sigsegv; + + restorer = VDSO_BASE; + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ptr_to_compat_reg(ka->sa.sa_restorer); + + /* + * Set up registers for signal handler. + * Registers that we don't modify keep the value they had from + * user-space at the time we took the signal. + */ + regs->pc = ptr_to_compat_reg(ka->sa.sa_handler); + regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ + regs->sp = ptr_to_compat_reg(frame); + regs->lr = restorer; + regs->regs[0] = (unsigned long) usig; + + if (ka->sa.sa_flags & SA_SIGINFO) { + /* Need extra arguments, so mark to restore caller-saves. */ + regs->regs[1] = ptr_to_compat_reg(&frame->info); + regs->regs[2] = ptr_to_compat_reg(&frame->uc); + regs->flags |= PT_FLAGS_CALLER_SAVES; + } + + /* + * Notify any tracer that was single-stepping it. + * The tracer may want to single-step inside the + * handler too. + */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return -EFAULT; +} diff --git a/arch/tile/kernel/early_printk.c b/arch/tile/kernel/early_printk.c new file mode 100644 index 000000000000..e44d441e3f3f --- /dev/null +++ b/arch/tile/kernel/early_printk.c @@ -0,0 +1,109 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include + +static void early_hv_write(struct console *con, const char *s, unsigned n) +{ + hv_console_write((HV_VirtAddr) s, n); +} + +static struct console early_hv_console = { + .name = "earlyhv", + .write = early_hv_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* Direct interface for emergencies */ +struct console *early_console = &early_hv_console; +static int early_console_initialized; +static int early_console_complete; + +static void early_vprintk(const char *fmt, va_list ap) +{ + char buf[512]; + int n = vscnprintf(buf, sizeof(buf), fmt, ap); + early_console->write(early_console, buf, n); +} + +void early_printk(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + early_vprintk(fmt, ap); + va_end(ap); +} + +void early_panic(const char *fmt, ...) +{ + va_list ap; + raw_local_irq_disable_all(); + va_start(ap, fmt); + early_printk("Kernel panic - not syncing: "); + early_vprintk(fmt, ap); + early_console->write(early_console, "\n", 1); + va_end(ap); + dump_stack(); + hv_halt(); +} + +static int __initdata keep_early; + +static int __init setup_early_printk(char *str) +{ + if (early_console_initialized) + return 1; + + if (str != NULL && strncmp(str, "keep", 4) == 0) + keep_early = 1; + + early_console = &early_hv_console; + early_console_initialized = 1; + register_console(early_console); + + return 0; +} + +void __init disable_early_printk(void) +{ + early_console_complete = 1; + if (!early_console_initialized || !early_console) + return; + if (!keep_early) { + early_printk("disabling early console\n"); + unregister_console(early_console); + early_console_initialized = 0; + } else { + early_printk("keeping early console\n"); + } +} + +void warn_early_printk(void) +{ + if (early_console_complete || early_console_initialized) + return; + early_printk("\ +Machine shutting down before console output is fully initialized.\n\ +You may wish to reboot and add the option 'earlyprintk' to your\n\ +boot command line to see any diagnostic early console output.\n\ +"); +} + +early_param("earlyprintk", setup_early_printk); diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S new file mode 100644 index 000000000000..136261f7d7f9 --- /dev/null +++ b/arch/tile/kernel/entry.S @@ -0,0 +1,141 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +#ifdef __tilegx__ +#define bnzt bnezt +#endif + +STD_ENTRY(current_text_addr) + { move r0, lr; jrp lr } + STD_ENDPROC(current_text_addr) + +STD_ENTRY(_sim_syscall) + /* + * Wait for r0-r9 to be ready (and lr on the off chance we + * want the syscall to locate its caller), then make a magic + * simulator syscall. + * + * We carefully stall until the registers are readable in case they + * are the target of a slow load, etc. so that tile-sim will + * definitely be able to read all of them inside the magic syscall. + * + * Technically this is wrong for r3-r9 and lr, since an interrupt + * could come in and restore the registers with a slow load right + * before executing the mtspr. We may need to modify tile-sim to + * explicitly stall for this case, but we do not yet have + * a way to implement such a stall. + */ + { and zero, lr, r9 ; and zero, r8, r7 } + { and zero, r6, r5 ; and zero, r4, r3 } + { and zero, r2, r1 ; mtspr SIM_CONTROL, r0 } + { jrp lr } + STD_ENDPROC(_sim_syscall) + +/* + * Implement execve(). The i386 code has a note that forking from kernel + * space results in no copy on write until the execve, so we should be + * careful not to write to the stack here. + */ +STD_ENTRY(kernel_execve) + moveli TREG_SYSCALL_NR_NAME, __NR_execve + swint1 + jrp lr + STD_ENDPROC(kernel_execve) + +/* Delay a fixed number of cycles. */ +STD_ENTRY(__delay) + { addi r0, r0, -1; bnzt r0, . } + jrp lr + STD_ENDPROC(__delay) + +/* + * We don't run this function directly, but instead copy it to a page + * we map into every user process. See vdso_setup(). + * + * Note that libc has a copy of this function that it uses to compare + * against the PC when a stack backtrace ends, so if this code is + * changed, the libc implementation(s) should also be updated. + */ + .pushsection .data +ENTRY(__rt_sigreturn) + moveli TREG_SYSCALL_NR_NAME,__NR_rt_sigreturn + swint1 + ENDPROC(__rt_sigreturn) + ENTRY(__rt_sigreturn_end) + .popsection + +STD_ENTRY(dump_stack) + { move r2, lr; lnk r1 } + { move r4, r52; addli r1, r1, dump_stack - . } + { move r3, sp; j _dump_stack } + jrp lr /* keep backtracer happy */ + STD_ENDPROC(dump_stack) + +STD_ENTRY(KBacktraceIterator_init_current) + { move r2, lr; lnk r1 } + { move r4, r52; addli r1, r1, KBacktraceIterator_init_current - . } + { move r3, sp; j _KBacktraceIterator_init_current } + jrp lr /* keep backtracer happy */ + STD_ENDPROC(KBacktraceIterator_init_current) + +/* + * Reset our stack to r1/r2 (sp and ksp0+cpu respectively), then + * free the old stack (passed in r0) and re-invoke cpu_idle(). + * We update sp and ksp0 simultaneously to avoid backtracer warnings. + */ +STD_ENTRY(cpu_idle_on_new_stack) + { + move sp, r1 + mtspr SYSTEM_SAVE_1_0, r2 + } + jal free_thread_info + j cpu_idle + STD_ENDPROC(cpu_idle_on_new_stack) + +/* Loop forever on a nap during SMP boot. */ +STD_ENTRY(smp_nap) + nap + j smp_nap /* we are not architecturally guaranteed not to exit nap */ + jrp lr /* clue in the backtracer */ + STD_ENDPROC(smp_nap) + +/* + * Enable interrupts racelessly and then nap until interrupted. + * This function's _cpu_idle_nap address is special; see intvec.S. + * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and + * as a result return to the function that called _cpu_idle(). + */ +STD_ENTRY(_cpu_idle) + { + lnk r0 + movei r1, 1 + } + { + addli r0, r0, _cpu_idle_nap - . + mtspr INTERRUPT_CRITICAL_SECTION, r1 + } + IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */ + mtspr EX_CONTEXT_1_1, r1 /* PL1, ICS clear */ + mtspr EX_CONTEXT_1_0, r0 + iret + .global _cpu_idle_nap +_cpu_idle_nap: + nap + jrp lr + STD_ENDPROC(_cpu_idle) diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S new file mode 100644 index 000000000000..2b4f6c091701 --- /dev/null +++ b/arch/tile/kernel/head_32.S @@ -0,0 +1,180 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * TILE startup code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This module contains the entry code for kernel images. It performs the + * minimal setup needed to call the generic C routines. + */ + + __HEAD +ENTRY(_start) + /* Notify the hypervisor of what version of the API we want */ + { + movei r1, TILE_CHIP + movei r2, TILE_CHIP_REV + } + { + moveli r0, _HV_VERSION + jal hv_init + } + /* Get a reasonable default ASID in r0 */ + { + move r0, zero + jal hv_inquire_asid + } + /* Install the default page table */ + { + moveli r6, lo16(swapper_pgprot - PAGE_OFFSET) + move r4, r0 /* use starting ASID of range for this page table */ + } + { + moveli r0, lo16(swapper_pg_dir - PAGE_OFFSET) + auli r6, r6, ha16(swapper_pgprot - PAGE_OFFSET) + } + { + lw r2, r6 + addi r6, r6, 4 + } + { + lw r3, r6 + auli r0, r0, ha16(swapper_pg_dir - PAGE_OFFSET) + } + { + inv r6 + move r1, zero /* high 32 bits of CPA is zero */ + } + { + moveli lr, lo16(1f) + move r5, zero + } + { + auli lr, lr, ha16(1f) + j hv_install_context + } +1: + + /* Get our processor number and save it away in SAVE_1_0. */ + jal hv_inquire_topology + mulll_uu r4, r1, r2 /* r1 == y, r2 == width */ + add r4, r4, r0 /* r0 == x, so r4 == cpu == y*width + x */ + +#ifdef CONFIG_SMP + /* + * Load up our per-cpu offset. When the first (master) tile + * boots, this value is still zero, so we will load boot_pc + * with start_kernel, and boot_sp with init_stack + THREAD_SIZE. + * The master tile initializes the per-cpu offset array, so that + * when subsequent (secondary) tiles boot, they will instead load + * from their per-cpu versions of boot_sp and boot_pc. + */ + moveli r5, lo16(__per_cpu_offset) + auli r5, r5, ha16(__per_cpu_offset) + s2a r5, r4, r5 + lw r5, r5 + bnz r5, 1f + + /* + * Save the width and height to the smp_topology variable + * for later use. + */ + moveli r0, lo16(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) + auli r0, r0, ha16(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) + { + sw r0, r2 + addi r0, r0, (HV_TOPOLOGY_HEIGHT_OFFSET - HV_TOPOLOGY_WIDTH_OFFSET) + } + sw r0, r3 +1: +#else + move r5, zero +#endif + + /* Load and go with the correct pc and sp. */ + { + addli r1, r5, lo16(boot_sp) + addli r0, r5, lo16(boot_pc) + } + { + auli r1, r1, ha16(boot_sp) + auli r0, r0, ha16(boot_pc) + } + lw r0, r0 + lw sp, r1 + or r4, sp, r4 + mtspr SYSTEM_SAVE_1_0, r4 /* save ksp0 + cpu */ + addi sp, sp, -STACK_TOP_DELTA + { + move lr, zero /* stop backtraces in the called function */ + jr r0 + } + ENDPROC(_start) + +.section ".bss.page_aligned","w" + .align PAGE_SIZE +ENTRY(empty_zero_page) + .fill PAGE_SIZE,1,0 + END(empty_zero_page) + + .macro PTE va, cpa, bits1, no_org=0 + .ifeq \no_org + .org swapper_pg_dir + HV_L1_INDEX(\va) * HV_PTE_SIZE + .endif + .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \ + (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) + .word (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) + .endm + +.section ".data.page_aligned","wa" + .align PAGE_SIZE +ENTRY(swapper_pg_dir) + /* + * All data pages from PAGE_OFFSET to MEM_USER_INTRPT are mapped as + * VA = PA + PAGE_OFFSET. We remap things with more precise access + * permissions and more respect for size of RAM later. + */ + .set addr, 0 + .rept (MEM_USER_INTRPT - PAGE_OFFSET) >> PGDIR_SHIFT + PTE addr + PAGE_OFFSET, addr, HV_PTE_READABLE | HV_PTE_WRITABLE + .set addr, addr + PGDIR_SIZE + .endr + + /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */ + PTE MEM_SV_INTRPT, 0, HV_PTE_READABLE | HV_PTE_EXECUTABLE + .org swapper_pg_dir + HV_L1_SIZE + END(swapper_pg_dir) + + /* + * Isolate swapper_pgprot to its own cache line, since each cpu + * starting up will read it using VA-is-PA and local homing. + * This would otherwise likely conflict with other data on the cache + * line, once we have set its permanent home in the page tables. + */ + __INITDATA + .align CHIP_L2_LINE_SIZE() +ENTRY(swapper_pgprot) + PTE 0, 0, HV_PTE_READABLE | HV_PTE_WRITABLE, 1 + .align CHIP_L2_LINE_SIZE() + END(swapper_pgprot) diff --git a/arch/tile/kernel/hvglue.lds b/arch/tile/kernel/hvglue.lds new file mode 100644 index 000000000000..698489b4c7ab --- /dev/null +++ b/arch/tile/kernel/hvglue.lds @@ -0,0 +1,56 @@ +/* Hypervisor call vector addresses; see */ +hv_init = TEXT_OFFSET + 0x10020; +hv_install_context = TEXT_OFFSET + 0x10040; +hv_sysconf = TEXT_OFFSET + 0x10060; +hv_get_rtc = TEXT_OFFSET + 0x10080; +hv_set_rtc = TEXT_OFFSET + 0x100a0; +hv_flush_asid = TEXT_OFFSET + 0x100c0; +hv_flush_page = TEXT_OFFSET + 0x100e0; +hv_flush_pages = TEXT_OFFSET + 0x10100; +hv_restart = TEXT_OFFSET + 0x10120; +hv_halt = TEXT_OFFSET + 0x10140; +hv_power_off = TEXT_OFFSET + 0x10160; +hv_inquire_physical = TEXT_OFFSET + 0x10180; +hv_inquire_memory_controller = TEXT_OFFSET + 0x101a0; +hv_inquire_virtual = TEXT_OFFSET + 0x101c0; +hv_inquire_asid = TEXT_OFFSET + 0x101e0; +hv_nanosleep = TEXT_OFFSET + 0x10200; +hv_console_read_if_ready = TEXT_OFFSET + 0x10220; +hv_console_write = TEXT_OFFSET + 0x10240; +hv_downcall_dispatch = TEXT_OFFSET + 0x10260; +hv_inquire_topology = TEXT_OFFSET + 0x10280; +hv_fs_findfile = TEXT_OFFSET + 0x102a0; +hv_fs_fstat = TEXT_OFFSET + 0x102c0; +hv_fs_pread = TEXT_OFFSET + 0x102e0; +hv_physaddr_read64 = TEXT_OFFSET + 0x10300; +hv_physaddr_write64 = TEXT_OFFSET + 0x10320; +hv_get_command_line = TEXT_OFFSET + 0x10340; +hv_set_caching = TEXT_OFFSET + 0x10360; +hv_bzero_page = TEXT_OFFSET + 0x10380; +hv_register_message_state = TEXT_OFFSET + 0x103a0; +hv_send_message = TEXT_OFFSET + 0x103c0; +hv_receive_message = TEXT_OFFSET + 0x103e0; +hv_inquire_context = TEXT_OFFSET + 0x10400; +hv_start_all_tiles = TEXT_OFFSET + 0x10420; +hv_dev_open = TEXT_OFFSET + 0x10440; +hv_dev_close = TEXT_OFFSET + 0x10460; +hv_dev_pread = TEXT_OFFSET + 0x10480; +hv_dev_pwrite = TEXT_OFFSET + 0x104a0; +hv_dev_poll = TEXT_OFFSET + 0x104c0; +hv_dev_poll_cancel = TEXT_OFFSET + 0x104e0; +hv_dev_preada = TEXT_OFFSET + 0x10500; +hv_dev_pwritea = TEXT_OFFSET + 0x10520; +hv_flush_remote = TEXT_OFFSET + 0x10540; +hv_console_putc = TEXT_OFFSET + 0x10560; +hv_inquire_tiles = TEXT_OFFSET + 0x10580; +hv_confstr = TEXT_OFFSET + 0x105a0; +hv_reexec = TEXT_OFFSET + 0x105c0; +hv_set_command_line = TEXT_OFFSET + 0x105e0; +hv_dev_register_intr_state = TEXT_OFFSET + 0x10600; +hv_enable_intr = TEXT_OFFSET + 0x10620; +hv_disable_intr = TEXT_OFFSET + 0x10640; +hv_trigger_ipi = TEXT_OFFSET + 0x10660; +hv_store_mapping = TEXT_OFFSET + 0x10680; +hv_inquire_realpa = TEXT_OFFSET + 0x106a0; +hv_flush_all = TEXT_OFFSET + 0x106c0; +hv_glue_internals = TEXT_OFFSET + 0x106e0; diff --git a/arch/tile/kernel/init_task.c b/arch/tile/kernel/init_task.c new file mode 100644 index 000000000000..928b31870669 --- /dev/null +++ b/arch/tile/kernel/init_task.c @@ -0,0 +1,59 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); + +/* + * Initial thread structure. + * + * We need to make sure that this is THREAD_SIZE aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry.. + */ +union thread_union init_thread_union __init_task_data = { + INIT_THREAD_INFO(init_task) +}; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); +EXPORT_SYMBOL(init_task); + +/* + * per-CPU stack and boot info. + */ +DEFINE_PER_CPU(unsigned long, boot_sp) = + (unsigned long)init_stack + THREAD_SIZE; + +#ifdef CONFIG_SMP +DEFINE_PER_CPU(unsigned long, boot_pc) = (unsigned long)start_kernel; +#else +/* + * The variable must be __initdata since it references __init code. + * With CONFIG_SMP it is per-cpu data, which is exempt from validation. + */ +unsigned long __initdata boot_pc = (unsigned long)start_kernel; +#endif diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S new file mode 100644 index 000000000000..207271f0cce1 --- /dev/null +++ b/arch/tile/kernel/intvec_32.S @@ -0,0 +1,2006 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Linux interrupt vectors. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PREEMPT +# error "No support for kernel preemption currently" +#endif + +#if INT_INTCTRL_1 < 32 || INT_INTCTL_1 >= 48 +# error INT_INTCTRL_1 coded to set high interrupt mask +#endif + +#define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg) + +#define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) + +#if !CHIP_HAS_WH64() + /* By making this an empty macro, we can use wh64 in the code. */ + .macro wh64 reg + .endm +#endif + + .macro push_reg reg, ptr=sp, delta=-4 + { + sw \ptr, \reg + addli \ptr, \ptr, \delta + } + .endm + + .macro pop_reg reg, ptr=sp, delta=4 + { + lw \reg, \ptr + addli \ptr, \ptr, \delta + } + .endm + + .macro pop_reg_zero reg, zreg, ptr=sp, delta=4 + { + move \zreg, zero + lw \reg, \ptr + addi \ptr, \ptr, \delta + } + .endm + + .macro push_extra_callee_saves reg + PTREGS_PTR(\reg, PTREGS_OFFSET_REG(51)) + push_reg r51, \reg + push_reg r50, \reg + push_reg r49, \reg + push_reg r48, \reg + push_reg r47, \reg + push_reg r46, \reg + push_reg r45, \reg + push_reg r44, \reg + push_reg r43, \reg + push_reg r42, \reg + push_reg r41, \reg + push_reg r40, \reg + push_reg r39, \reg + push_reg r38, \reg + push_reg r37, \reg + push_reg r36, \reg + push_reg r35, \reg + push_reg r34, \reg, PTREGS_OFFSET_BASE - PTREGS_OFFSET_REG(34) + .endm + + .macro panic str + .pushsection .rodata, "a" +1: + .asciz "\str" + .popsection + { + moveli r0, lo16(1b) + } + { + auli r0, r0, ha16(1b) + jal panic + } + .endm + +#ifdef __COLLECT_LINKER_FEEDBACK__ + .pushsection .text.intvec_feedback,"ax" +intvec_feedback: + .popsection +#endif + + /* + * Default interrupt handler. + * + * vecnum is where we'll put this code. + * c_routine is the C routine we'll call. + * + * The C routine is passed two arguments: + * - A pointer to the pt_regs state. + * - The interrupt vector number. + * + * The "processing" argument specifies the code for processing + * the interrupt. Defaults to "handle_interrupt". + */ + .macro int_hand vecnum, vecname, c_routine, processing=handle_interrupt + .org (\vecnum << 8) +intvec_\vecname: + .ifc \vecnum, INT_SWINT_1 + blz TREG_SYSCALL_NR_NAME, sys_cmpxchg + .endif + + /* Temporarily save a register so we have somewhere to work. */ + + mtspr SYSTEM_SAVE_1_1, r0 + mfspr r0, EX_CONTEXT_1_1 + + /* The cmpxchg code clears sp to force us to reset it here on fault. */ + { + bz sp, 2f + andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + } + + .ifc \vecnum, INT_DOUBLE_FAULT + /* + * For double-faults from user-space, fall through to the normal + * register save and stack setup path. Otherwise, it's the + * hypervisor giving us one last chance to dump diagnostics, and we + * branch to the kernel_double_fault routine to do so. + */ + bz r0, 1f + j _kernel_double_fault +1: + .else + /* + * If we're coming from user-space, then set sp to the top of + * the kernel stack. Otherwise, assume sp is already valid. + */ + { + bnz r0, 0f + move r0, sp + } + .endif + + .ifc \c_routine, do_page_fault + /* + * The page_fault handler may be downcalled directly by the + * hypervisor even when Linux is running and has ICS set. + * + * In this case the contents of EX_CONTEXT_1_1 reflect the + * previous fault and can't be relied on to choose whether or + * not to reinitialize the stack pointer. So we add a test + * to see whether SYSTEM_SAVE_1_2 has the high bit set, + * and if so we don't reinitialize sp, since we must be coming + * from Linux. (In fact the precise case is !(val & ~1), + * but any Linux PC has to have the high bit set.) + * + * Note that the hypervisor *always* sets SYSTEM_SAVE_1_2 for + * any path that turns into a downcall to one of our TLB handlers. + */ + mfspr r0, SYSTEM_SAVE_1_2 + { + blz r0, 0f /* high bit in S_S_1_2 is for a PC to use */ + move r0, sp + } + .endif + +2: + /* + * SYSTEM_SAVE_1_0 holds the cpu number in the low bits, and + * the current stack top in the higher bits. So we recover + * our stack top by just masking off the low bits, then + * point sp at the top aligned address on the actual stack page. + */ + mfspr r0, SYSTEM_SAVE_1_0 + mm r0, r0, zero, LOG2_THREAD_SIZE, 31 + +0: + /* + * Align the stack mod 64 so we can properly predict what + * cache lines we need to write-hint to reduce memory fetch + * latency as we enter the kernel. The layout of memory is + * as follows, with cache line 0 at the lowest VA, and cache + * line 4 just below the r0 value this "andi" computes. + * Note that we never write to cache line 4, and we skip + * cache line 1 for syscalls. + * + * cache line 4: ptregs padding (two words) + * cache line 3: r46...lr, pc, ex1, faultnum, orig_r0, flags, pad + * cache line 2: r30...r45 + * cache line 1: r14...r29 + * cache line 0: 2 x frame, r0..r13 + */ + andi r0, r0, -64 + + /* + * Push the first four registers on the stack, so that we can set + * them to vector-unique values before we jump to the common code. + * + * Registers are pushed on the stack as a struct pt_regs, + * with the sp initially just above the struct, and when we're + * done, sp points to the base of the struct, minus + * C_ABI_SAVE_AREA_SIZE, so we can directly jal to C code. + * + * This routine saves just the first four registers, plus the + * stack context so we can do proper backtracing right away, + * and defers to handle_interrupt to save the rest. + * The backtracer needs pc, ex1, lr, sp, r52, and faultnum. + */ + addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP) + wh64 r0 /* cache line 3 */ + { + sw r0, lr + addli r0, r0, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR + } + { + sw r0, sp + addli sp, r0, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_SP + } + { + sw sp, r52 + addli sp, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(52) + } + wh64 sp /* cache line 0 */ + { + sw sp, r1 + addli sp, sp, PTREGS_OFFSET_REG(2) - PTREGS_OFFSET_REG(1) + } + { + sw sp, r2 + addli sp, sp, PTREGS_OFFSET_REG(3) - PTREGS_OFFSET_REG(2) + } + { + sw sp, r3 + addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3) + } + mfspr r0, EX_CONTEXT_1_0 + .ifc \processing,handle_syscall + /* + * Bump the saved PC by one bundle so that when we return, we won't + * execute the same swint instruction again. We need to do this while + * we're in the critical section. + */ + addi r0, r0, 8 + .endif + { + sw sp, r0 + addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC + } + mfspr r0, EX_CONTEXT_1_1 + { + sw sp, r0 + addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 + /* + * Use r0 for syscalls so it's a temporary; use r1 for interrupts + * so that it gets passed through unchanged to the handler routine. + * Note that the .if conditional confusingly spans bundles. + */ + .ifc \processing,handle_syscall + movei r0, \vecnum + } + { + sw sp, r0 + .else + movei r1, \vecnum + } + { + sw sp, r1 + .endif + addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM + } + mfspr r0, SYSTEM_SAVE_1_1 /* Original r0 */ + { + sw sp, r0 + addi sp, sp, -PTREGS_OFFSET_REG(0) - 4 + } + { + sw sp, zero /* write zero into "Next SP" frame pointer */ + addi sp, sp, -4 /* leave SP pointing at bottom of frame */ + } + .ifc \processing,handle_syscall + j handle_syscall + .else + /* + * Capture per-interrupt SPR context to registers. + * We overload the meaning of r3 on this path such that if its bit 31 + * is set, we have to mask all interrupts including NMIs before + * clearing the interrupt critical section bit. + * See discussion below at "finish_interrupt_save". + */ + .ifc \c_routine, do_page_fault + mfspr r2, SYSTEM_SAVE_1_3 /* address of page fault */ + mfspr r3, SYSTEM_SAVE_1_2 /* info about page fault */ + .else + .ifc \vecnum, INT_DOUBLE_FAULT + { + mfspr r2, SYSTEM_SAVE_1_2 /* double fault info from HV */ + movei r3, 0 + } + .else + .ifc \c_routine, do_trap + { + mfspr r2, GPV_REASON + movei r3, 0 + } + .else + .ifc \c_routine, op_handle_perf_interrupt + { + mfspr r2, PERF_COUNT_STS + movei r3, -1 /* not used, but set for consistency */ + } + .else +#if CHIP_HAS_AUX_PERF_COUNTERS() + .ifc \c_routine, op_handle_aux_perf_interrupt + { + mfspr r2, AUX_PERF_COUNT_STS + movei r3, -1 /* not used, but set for consistency */ + } + .else +#endif + movei r3, 0 +#if CHIP_HAS_AUX_PERF_COUNTERS() + .endif +#endif + .endif + .endif + .endif + .endif + /* Put function pointer in r0 */ + moveli r0, lo16(\c_routine) + { + auli r0, r0, ha16(\c_routine) + j \processing + } + .endif + ENDPROC(intvec_\vecname) + +#ifdef __COLLECT_LINKER_FEEDBACK__ + .pushsection .text.intvec_feedback,"ax" + .org (\vecnum << 5) + FEEDBACK_ENTER_EXPLICIT(intvec_\vecname, .intrpt1, 1 << 8) + jrp lr + .popsection +#endif + + .endm + + + /* + * Save the rest of the registers that we didn't save in the actual + * vector itself. We can't use r0-r10 inclusive here. + */ + .macro finish_interrupt_save, function + + /* If it's a syscall, save a proper orig_r0, otherwise just zero. */ + PTREGS_PTR(r52, PTREGS_OFFSET_ORIG_R0) + { + .ifc \function,handle_syscall + sw r52, r0 + .else + sw r52, zero + .endif + PTREGS_PTR(r52, PTREGS_OFFSET_TP) + } + + /* + * For ordinary syscalls, we save neither caller- nor callee- + * save registers, since the syscall invoker doesn't expect the + * caller-saves to be saved, and the called kernel functions will + * take care of saving the callee-saves for us. + * + * For interrupts we save just the caller-save registers. Saving + * them is required (since the "caller" can't save them). Again, + * the called kernel functions will restore the callee-save + * registers for us appropriately. + * + * On return, we normally restore nothing special for syscalls, + * and just the caller-save registers for interrupts. + * + * However, there are some important caveats to all this: + * + * - We always save a few callee-save registers to give us + * some scratchpad registers to carry across function calls. + * + * - fork/vfork/etc require us to save all the callee-save + * registers, which we do in PTREGS_SYSCALL_ALL_REGS, below. + * + * - We always save r0..r5 and r10 for syscalls, since we need + * to reload them a bit later for the actual kernel call, and + * since we might need them for -ERESTARTNOINTR, etc. + * + * - Before invoking a signal handler, we save the unsaved + * callee-save registers so they are visible to the + * signal handler or any ptracer. + * + * - If the unsaved callee-save registers are modified, we set + * a bit in pt_regs so we know to reload them from pt_regs + * and not just rely on the kernel function unwinding. + * (Done for ptrace register writes and SA_SIGINFO handler.) + */ + { + sw r52, tp + PTREGS_PTR(r52, PTREGS_OFFSET_REG(33)) + } + wh64 r52 /* cache line 2 */ + push_reg r33, r52 + push_reg r32, r52 + push_reg r31, r52 + .ifc \function,handle_syscall + push_reg r30, r52, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(30) + push_reg TREG_SYSCALL_NR_NAME, r52, \ + PTREGS_OFFSET_REG(5) - PTREGS_OFFSET_SYSCALL + .else + + push_reg r30, r52, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(30) + wh64 r52 /* cache line 1 */ + push_reg r29, r52 + push_reg r28, r52 + push_reg r27, r52 + push_reg r26, r52 + push_reg r25, r52 + push_reg r24, r52 + push_reg r23, r52 + push_reg r22, r52 + push_reg r21, r52 + push_reg r20, r52 + push_reg r19, r52 + push_reg r18, r52 + push_reg r17, r52 + push_reg r16, r52 + push_reg r15, r52 + push_reg r14, r52 + push_reg r13, r52 + push_reg r12, r52 + push_reg r11, r52 + push_reg r10, r52 + push_reg r9, r52 + push_reg r8, r52 + push_reg r7, r52 + push_reg r6, r52 + + .endif + + push_reg r5, r52 + sw r52, r4 + + /* Load tp with our per-cpu offset. */ +#ifdef CONFIG_SMP + { + mfspr r20, SYSTEM_SAVE_1_0 + moveli r21, lo16(__per_cpu_offset) + } + { + auli r21, r21, ha16(__per_cpu_offset) + mm r20, r20, zero, 0, LOG2_THREAD_SIZE-1 + } + s2a r20, r20, r21 + lw tp, r20 +#else + move tp, zero +#endif + + /* + * If we will be returning to the kernel, we will need to + * reset the interrupt masks to the state they had before. + * Set DISABLE_IRQ in flags iff we came from PL1 with irqs disabled. + * We load flags in r32 here so we can jump to .Lrestore_regs + * directly after do_page_fault_ics() if necessary. + */ + mfspr r32, EX_CONTEXT_1_1 + { + andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) + } + bzt r32, 1f /* zero if from user space */ + IRQS_DISABLED(r32) /* zero if irqs enabled */ +#if PT_FLAGS_DISABLE_IRQ != 1 +# error Value of IRQS_DISABLED used to set PT_FLAGS_DISABLE_IRQ; fix +#endif +1: + .ifnc \function,handle_syscall + /* Record the fact that we saved the caller-save registers above. */ + ori r32, r32, PT_FLAGS_CALLER_SAVES + .endif + sw r21, r32 + +#ifdef __COLLECT_LINKER_FEEDBACK__ + /* + * Notify the feedback routines that we were in the + * appropriate fixed interrupt vector area. Note that we + * still have ICS set at this point, so we can't invoke any + * atomic operations or we will panic. The feedback + * routines internally preserve r0..r10 and r30 up. + */ + .ifnc \function,handle_syscall + shli r20, r1, 5 + .else + moveli r20, INT_SWINT_1 << 5 + .endif + addli r20, r20, lo16(intvec_feedback) + auli r20, r20, ha16(intvec_feedback) + jalr r20 + + /* And now notify the feedback routines that we are here. */ + FEEDBACK_ENTER(\function) +#endif + + /* + * we've captured enough state to the stack (including in + * particular our EX_CONTEXT state) that we can now release + * the interrupt critical section and replace it with our + * standard "interrupts disabled" mask value. This allows + * synchronous interrupts (and profile interrupts) to punch + * through from this point onwards. + * + * If bit 31 of r3 is set during a non-NMI interrupt, we know we + * are on the path where the hypervisor has punched through our + * ICS with a page fault, so we call out to do_page_fault_ics() + * to figure out what to do with it. If the fault was in + * an atomic op, we unlock the atomic lock, adjust the + * saved register state a little, and return "zero" in r4, + * falling through into the normal page-fault interrupt code. + * If the fault was in a kernel-space atomic operation, then + * do_page_fault_ics() resolves it itself, returns "one" in r4, + * and as a result goes directly to restoring registers and iret, + * without trying to adjust the interrupt masks at all. + * The do_page_fault_ics() API involves passing and returning + * a five-word struct (in registers) to avoid writing the + * save and restore code here. + */ + .ifc \function,handle_nmi + IRQ_DISABLE_ALL(r20) + .else + .ifnc \function,handle_syscall + bgezt r3, 1f + { + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + jal do_page_fault_ics + } + FEEDBACK_REENTER(\function) + bzt r4, 1f + j .Lrestore_regs +1: + .endif + IRQ_DISABLE(r20, r21) + .endif + mtspr INTERRUPT_CRITICAL_SECTION, zero + +#if CHIP_HAS_WH64() + /* + * Prepare the first 256 stack bytes to be rapidly accessible + * without having to fetch the background data. We don't really + * know how far to write-hint, but kernel stacks generally + * aren't that big, and write-hinting here does take some time. + */ + addi r52, sp, -64 + { + wh64 r52 + addi r52, r52, -64 + } + { + wh64 r52 + addi r52, r52, -64 + } + { + wh64 r52 + addi r52, r52, -64 + } + wh64 r52 +#endif + +#ifdef CONFIG_TRACE_IRQFLAGS + .ifnc \function,handle_nmi + /* + * We finally have enough state set up to notify the irq + * tracing code that irqs were disabled on entry to the handler. + * The TRACE_IRQS_OFF call clobbers registers r0-r29. + * For syscalls, we already have the register state saved away + * on the stack, so we don't bother to do any register saves here, + * and later we pop the registers back off the kernel stack. + * For interrupt handlers, save r0-r3 in callee-saved registers. + */ + .ifnc \function,handle_syscall + { move r30, r0; move r31, r1 } + { move r32, r2; move r33, r3 } + .endif + TRACE_IRQS_OFF + .ifnc \function,handle_syscall + { move r0, r30; move r1, r31 } + { move r2, r32; move r3, r33 } + .endif + .endif +#endif + + .endm + + .macro check_single_stepping, kind, not_single_stepping + /* + * Check for single stepping in user-level priv + * kind can be "normal", "ill", or "syscall" + * At end, if fall-thru + * r29: thread_info->step_state + * r28: &pt_regs->pc + * r27: pt_regs->pc + * r26: thread_info->step_state->buffer + */ + + /* Check for single stepping */ + GET_THREAD_INFO(r29) + { + /* Get pointer to field holding step state */ + addi r29, r29, THREAD_INFO_STEP_STATE_OFFSET + + /* Get pointer to EX1 in register state */ + PTREGS_PTR(r27, PTREGS_OFFSET_EX1) + } + { + /* Get pointer to field holding PC */ + PTREGS_PTR(r28, PTREGS_OFFSET_PC) + + /* Load the pointer to the step state */ + lw r29, r29 + } + /* Load EX1 */ + lw r27, r27 + { + /* Points to flags */ + addi r23, r29, SINGLESTEP_STATE_FLAGS_OFFSET + + /* No single stepping if there is no step state structure */ + bzt r29, \not_single_stepping + } + { + /* mask off ICS and any other high bits */ + andi r27, r27, SPR_EX_CONTEXT_1_1__PL_MASK + + /* Load pointer to single step instruction buffer */ + lw r26, r29 + } + /* Check priv state */ + bnz r27, \not_single_stepping + + /* Get flags */ + lw r22, r23 + { + /* Branch if single-step mode not enabled */ + bbnst r22, \not_single_stepping + + /* Clear enabled flag */ + andi r22, r22, ~SINGLESTEP_STATE_MASK_IS_ENABLED + } + .ifc \kind,normal + { + /* Load PC */ + lw r27, r28 + + /* Point to the entry containing the original PC */ + addi r24, r29, SINGLESTEP_STATE_ORIG_PC_OFFSET + } + { + /* Disable single stepping flag */ + sw r23, r22 + } + { + /* Get the original pc */ + lw r24, r24 + + /* See if the PC is at the start of the single step buffer */ + seq r25, r26, r27 + } + /* + * NOTE: it is really expected that the PC be in the single step buffer + * at this point + */ + bzt r25, \not_single_stepping + + /* Restore the original PC */ + sw r28, r24 + .else + .ifc \kind,syscall + { + /* Load PC */ + lw r27, r28 + + /* Point to the entry containing the next PC */ + addi r24, r29, SINGLESTEP_STATE_NEXT_PC_OFFSET + } + { + /* Increment the stopped PC by the bundle size */ + addi r26, r26, 8 + + /* Disable single stepping flag */ + sw r23, r22 + } + { + /* Get the next pc */ + lw r24, r24 + + /* + * See if the PC is one bundle past the start of the + * single step buffer + */ + seq r25, r26, r27 + } + { + /* + * NOTE: it is really expected that the PC be in the + * single step buffer at this point + */ + bzt r25, \not_single_stepping + } + /* Set to the next PC */ + sw r28, r24 + .else + { + /* Point to 3rd bundle in buffer */ + addi r25, r26, 16 + + /* Load PC */ + lw r27, r28 + } + { + /* Disable single stepping flag */ + sw r23, r22 + + /* See if the PC is in the single step buffer */ + slte_u r24, r26, r27 + } + { + slte_u r25, r27, r25 + + /* + * NOTE: it is really expected that the PC be in the + * single step buffer at this point + */ + bzt r24, \not_single_stepping + } + bzt r25, \not_single_stepping + .endif + .endif + .endm + + /* + * Redispatch a downcall. + */ + .macro dc_dispatch vecnum, vecname + .org (\vecnum << 8) +intvec_\vecname: + j hv_downcall_dispatch + ENDPROC(intvec_\vecname) + .endm + + /* + * Common code for most interrupts. The C function we're eventually + * going to is in r0, and the faultnum is in r1; the original + * values for those registers are on the stack. + */ + .pushsection .text.handle_interrupt,"ax" +handle_interrupt: + finish_interrupt_save handle_interrupt + + /* + * Check for if we are single stepping in user level. If so, then + * we need to restore the PC. + */ + + check_single_stepping normal, .Ldispatch_interrupt +.Ldispatch_interrupt: + + /* Jump to the C routine; it should enable irqs as soon as possible. */ + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_interrupt) + { + movei r30, 0 /* not an NMI */ + j interrupt_return + } + STD_ENDPROC(handle_interrupt) + +/* + * This routine takes a boolean in r30 indicating if this is an NMI. + * If so, we also expect a boolean in r31 indicating whether to + * re-enable the oprofile interrupts. + */ +STD_ENTRY(interrupt_return) + /* If we're resuming to kernel space, don't check thread flags. */ + { + bnz r30, .Lrestore_all /* NMIs don't special-case user-space */ + PTREGS_PTR(r29, PTREGS_OFFSET_EX1) + } + lw r29, r29 + andi r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + { + bzt r29, .Lresume_userspace + PTREGS_PTR(r29, PTREGS_OFFSET_PC) + } + + /* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */ + { + lw r28, r29 + moveli r27, lo16(_cpu_idle_nap) + } + { + auli r27, r27, ha16(_cpu_idle_nap) + } + { + seq r27, r27, r28 + } + { + bbns r27, .Lrestore_all + addi r28, r28, 8 + } + sw r29, r28 + j .Lrestore_all + +.Lresume_userspace: + FEEDBACK_REENTER(interrupt_return) + + /* + * Disable interrupts so as to make sure we don't + * miss an interrupt that sets any of the thread flags (like + * need_resched or sigpending) between sampling and the iret. + * Routines like schedule() or do_signal() may re-enable + * interrupts before returning. + */ + IRQ_DISABLE(r20, r21) + TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ + + /* Get base of stack in r32; note r30/31 are used as arguments here. */ + GET_THREAD_INFO(r32) + + + /* Check to see if there is any work to do before returning to user. */ + { + addi r29, r32, THREAD_INFO_FLAGS_OFFSET + moveli r28, lo16(_TIF_ALLWORK_MASK) + } + { + lw r29, r29 + auli r28, r28, ha16(_TIF_ALLWORK_MASK) + } + and r28, r29, r28 + bnz r28, .Lwork_pending + + /* + * In the NMI case we + * omit the call to single_process_check_nohz, which normally checks + * to see if we should start or stop the scheduler tick, because + * we can't call arbitrary Linux code from an NMI context. + * We always call the homecache TLB deferral code to re-trigger + * the deferral mechanism. + * + * The other chunk of responsibility this code has is to reset the + * interrupt masks appropriately to reset irqs and NMIs. We have + * to call TRACE_IRQS_OFF and TRACE_IRQS_ON to support all the + * lockdep-type stuff, but we can't set ICS until afterwards, since + * ICS can only be used in very tight chunks of code to avoid + * tripping over various assertions that it is off. + * + * (There is what looks like a window of vulnerability here since + * we might take a profile interrupt between the two SPR writes + * that set the mask, but since we write the low SPR word first, + * and our interrupt entry code checks the low SPR word, any + * profile interrupt will actually disable interrupts in both SPRs + * before returning, which is OK.) + */ +.Lrestore_all: + PTREGS_PTR(r0, PTREGS_OFFSET_EX1) + { + lw r0, r0 + PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) + } + { + andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK + lw r32, r32 + } + bnz r0, 1f + j 2f +#if PT_FLAGS_DISABLE_IRQ != 1 +# error Assuming PT_FLAGS_DISABLE_IRQ == 1 so we can use bbnst below +#endif +1: bbnst r32, 2f + IRQ_DISABLE(r20,r21) + TRACE_IRQS_OFF + movei r0, 1 + mtspr INTERRUPT_CRITICAL_SECTION, r0 + bzt r30, .Lrestore_regs + j 3f +2: TRACE_IRQS_ON + movei r0, 1 + mtspr INTERRUPT_CRITICAL_SECTION, r0 + IRQ_ENABLE(r20, r21) + bzt r30, .Lrestore_regs +3: + + + /* + * We now commit to returning from this interrupt, since we will be + * doing things like setting EX_CONTEXT SPRs and unwinding the stack + * frame. No calls should be made to any other code after this point. + * This code should only be entered with ICS set. + * r32 must still be set to ptregs.flags. + * We launch loads to each cache line separately first, so we can + * get some parallelism out of the memory subsystem. + * We start zeroing caller-saved registers throughout, since + * that will save some cycles if this turns out to be a syscall. + */ +.Lrestore_regs: + FEEDBACK_REENTER(interrupt_return) /* called from elsewhere */ + + /* + * Rotate so we have one high bit and one low bit to test. + * - low bit says whether to restore all the callee-saved registers, + * or just r30-r33, and r52 up. + * - high bit (i.e. sign bit) says whether to restore all the + * caller-saved registers, or just r0. + */ +#if PT_FLAGS_CALLER_SAVES != 2 || PT_FLAGS_RESTORE_REGS != 4 +# error Rotate trick does not work :-) +#endif + { + rli r20, r32, 30 + PTREGS_PTR(sp, PTREGS_OFFSET_REG(0)) + } + + /* + * Load cache lines 0, 2, and 3 in that order, then use + * the last loaded value, which makes it likely that the other + * cache lines have also loaded, at which point we should be + * able to safely read all the remaining words on those cache + * lines without waiting for the memory subsystem. + */ + pop_reg_zero r0, r1, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0) + pop_reg_zero r30, r2, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(30) + pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC + pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1 + { + mtspr EX_CONTEXT_1_0, r21 + move r5, zero + } + { + mtspr EX_CONTEXT_1_1, lr + andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + } + + /* Restore callee-saveds that we actually use. */ + pop_reg_zero r52, r6, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_REG(52) + pop_reg_zero r31, r7 + pop_reg_zero r32, r8 + pop_reg_zero r33, r9, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(33) + + /* + * If we modified other callee-saveds, restore them now. + * This is rare, but could be via ptrace or signal handler. + */ + { + move r10, zero + bbs r20, .Lrestore_callees + } +.Lcontinue_restore_regs: + + /* Check if we're returning from a syscall. */ + { + move r11, zero + blzt r20, 1f /* no, so go restore callee-save registers */ + } + + /* + * Check if we're returning to userspace. + * Note that if we're not, we don't worry about zeroing everything. + */ + { + addli sp, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(29) + bnz lr, .Lkernel_return + } + + /* + * On return from syscall, we've restored r0 from pt_regs, but we + * clear the remainder of the caller-saved registers. We could + * restore the syscall arguments, but there's not much point, + * and it ensures user programs aren't trying to use the + * caller-saves if we clear them, as well as avoiding leaking + * kernel pointers into userspace. + */ + pop_reg_zero lr, r12, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR + pop_reg_zero tp, r13, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP + { + lw sp, sp + move r14, zero + move r15, zero + } + { move r16, zero; move r17, zero } + { move r18, zero; move r19, zero } + { move r20, zero; move r21, zero } + { move r22, zero; move r23, zero } + { move r24, zero; move r25, zero } + { move r26, zero; move r27, zero } + { move r28, zero; move r29, zero } + iret + + /* + * Not a syscall, so restore caller-saved registers. + * First kick off a load for cache line 1, which we're touching + * for the first time here. + */ + .align 64 +1: pop_reg r29, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(29) + pop_reg r1 + pop_reg r2 + pop_reg r3 + pop_reg r4 + pop_reg r5 + pop_reg r6 + pop_reg r7 + pop_reg r8 + pop_reg r9 + pop_reg r10 + pop_reg r11 + pop_reg r12 + pop_reg r13 + pop_reg r14 + pop_reg r15 + pop_reg r16 + pop_reg r17 + pop_reg r18 + pop_reg r19 + pop_reg r20 + pop_reg r21 + pop_reg r22 + pop_reg r23 + pop_reg r24 + pop_reg r25 + pop_reg r26 + pop_reg r27 + pop_reg r28, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(28) + /* r29 already restored above */ + bnz lr, .Lkernel_return + pop_reg lr, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR + pop_reg tp, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP + lw sp, sp + iret + + /* + * We can't restore tp when in kernel mode, since a thread might + * have migrated from another cpu and brought a stale tp value. + */ +.Lkernel_return: + pop_reg lr, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR + lw sp, sp + iret + + /* Restore callee-saved registers from r34 to r51. */ +.Lrestore_callees: + addli sp, sp, PTREGS_OFFSET_REG(34) - PTREGS_OFFSET_REG(29) + pop_reg r34 + pop_reg r35 + pop_reg r36 + pop_reg r37 + pop_reg r38 + pop_reg r39 + pop_reg r40 + pop_reg r41 + pop_reg r42 + pop_reg r43 + pop_reg r44 + pop_reg r45 + pop_reg r46 + pop_reg r47 + pop_reg r48 + pop_reg r49 + pop_reg r50 + pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) + j .Lcontinue_restore_regs + +.Lwork_pending: + /* Mask the reschedule flag */ + andi r28, r29, _TIF_NEED_RESCHED + + { + /* + * If the NEED_RESCHED flag is called, we call schedule(), which + * may drop this context right here and go do something else. + * On return, jump back to .Lresume_userspace and recheck. + */ + bz r28, .Lasync_tlb + + /* Mask the async-tlb flag */ + andi r28, r29, _TIF_ASYNC_TLB + } + + jal schedule + FEEDBACK_REENTER(interrupt_return) + + /* Reload the flags and check again */ + j .Lresume_userspace + +.Lasync_tlb: + { + bz r28, .Lneed_sigpending + + /* Mask the sigpending flag */ + andi r28, r29, _TIF_SIGPENDING + } + + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + jal do_async_page_fault + FEEDBACK_REENTER(interrupt_return) + + /* + * Go restart the "resume userspace" process. We may have + * fired a signal, and we need to disable interrupts again. + */ + j .Lresume_userspace + +.Lneed_sigpending: + /* + * At this point we are either doing signal handling or single-step, + * so either way make sure we have all the registers saved. + */ + push_extra_callee_saves r0 + + { + /* If no signal pending, skip to singlestep check */ + bz r28, .Lneed_singlestep + + /* Mask the singlestep flag */ + andi r28, r29, _TIF_SINGLESTEP + } + + jal do_signal + FEEDBACK_REENTER(interrupt_return) + + /* Reload the flags and check again */ + j .Lresume_userspace + +.Lneed_singlestep: + { + /* Get a pointer to the EX1 field */ + PTREGS_PTR(r29, PTREGS_OFFSET_EX1) + + /* If we get here, our bit must be set. */ + bz r28, .Lwork_confusion + } + /* If we are in priv mode, don't single step */ + lw r28, r29 + andi r28, r28, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ + bnz r28, .Lrestore_all + + /* Allow interrupts within the single step code */ + TRACE_IRQS_ON /* Note: clobbers registers r0-r29 */ + IRQ_ENABLE(r20, r21) + + /* try to single-step the current instruction */ + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + jal single_step_once + FEEDBACK_REENTER(interrupt_return) + + /* Re-disable interrupts. TRACE_IRQS_OFF in .Lrestore_all. */ + IRQ_DISABLE(r20,r21) + + j .Lrestore_all + +.Lwork_confusion: + move r0, r28 + panic "thread_info allwork flags unhandled on userspace resume: %#x" + + STD_ENDPROC(interrupt_return) + + /* + * This interrupt variant clears the INT_INTCTRL_1 interrupt mask bit + * before returning, so we can properly get more downcalls. + */ + .pushsection .text.handle_interrupt_downcall,"ax" +handle_interrupt_downcall: + finish_interrupt_save handle_interrupt_downcall + check_single_stepping normal, .Ldispatch_downcall +.Ldispatch_downcall: + + /* Clear INTCTRL_1 from the set of interrupts we ever enable. */ + GET_INTERRUPTS_ENABLED_MASK_PTR(r30) + { + addi r30, r30, 4 + movei r31, INT_MASK(INT_INTCTRL_1) + } + { + lw r20, r30 + nor r21, r31, zero + } + and r20, r20, r21 + sw r30, r20 + + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_interrupt_downcall) + + /* Allow INTCTRL_1 to be enabled next time we enable interrupts. */ + lw r20, r30 + or r20, r20, r31 + sw r30, r20 + + { + movei r30, 0 /* not an NMI */ + j interrupt_return + } + STD_ENDPROC(handle_interrupt_downcall) + + /* + * Some interrupts don't check for single stepping + */ + .pushsection .text.handle_interrupt_no_single_step,"ax" +handle_interrupt_no_single_step: + finish_interrupt_save handle_interrupt_no_single_step + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_interrupt_no_single_step) + { + movei r30, 0 /* not an NMI */ + j interrupt_return + } + STD_ENDPROC(handle_interrupt_no_single_step) + + /* + * "NMI" interrupts mask ALL interrupts before calling the + * handler, and don't check thread flags, etc., on the way + * back out. In general, the only things we do here for NMIs + * are the register save/restore, fixing the PC if we were + * doing single step, and the dataplane kernel-TLB management. + * We don't (for example) deal with start/stop of the sched tick. + */ + .pushsection .text.handle_nmi,"ax" +handle_nmi: + finish_interrupt_save handle_nmi + check_single_stepping normal, .Ldispatch_nmi +.Ldispatch_nmi: + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_nmi) + j interrupt_return + STD_ENDPROC(handle_nmi) + + /* + * Parallel code for syscalls to handle_interrupt. + */ + .pushsection .text.handle_syscall,"ax" +handle_syscall: + finish_interrupt_save handle_syscall + + /* + * Check for if we are single stepping in user level. If so, then + * we need to restore the PC. + */ + check_single_stepping syscall, .Ldispatch_syscall +.Ldispatch_syscall: + + /* Enable irqs. */ + TRACE_IRQS_ON + IRQ_ENABLE(r20, r21) + + /* Bump the counter for syscalls made on this tile. */ + moveli r20, lo16(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) + auli r20, r20, ha16(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) + add r20, r20, tp + lw r21, r20 + addi r21, r21, 1 + sw r20, r21 + + /* Trace syscalls, if requested. */ + GET_THREAD_INFO(r31) + addi r31, r31, THREAD_INFO_FLAGS_OFFSET + lw r30, r31 + andi r30, r30, _TIF_SYSCALL_TRACE + bzt r30, .Lrestore_syscall_regs + jal do_syscall_trace + FEEDBACK_REENTER(handle_syscall) + + /* + * We always reload our registers from the stack at this + * point. They might be valid, if we didn't build with + * TRACE_IRQFLAGS, and this isn't a dataplane tile, and we're not + * doing syscall tracing, but there are enough cases now that it + * seems simplest just to do the reload unconditionally. + */ +.Lrestore_syscall_regs: + PTREGS_PTR(r11, PTREGS_OFFSET_REG(0)) + pop_reg r0, r11 + pop_reg r1, r11 + pop_reg r2, r11 + pop_reg r3, r11 + pop_reg r4, r11 + pop_reg r5, r11, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(5) + pop_reg TREG_SYSCALL_NR_NAME, r11 + + /* Ensure that the syscall number is within the legal range. */ + moveli r21, __NR_syscalls + { + slt_u r21, TREG_SYSCALL_NR_NAME, r21 + moveli r20, lo16(sys_call_table) + } + { + bbns r21, .Linvalid_syscall + auli r20, r20, ha16(sys_call_table) + } + s2a r20, TREG_SYSCALL_NR_NAME, r20 + lw r20, r20 + + /* Jump to syscall handler. */ + jalr r20; .Lhandle_syscall_link: + FEEDBACK_REENTER(handle_syscall) + + /* + * Write our r0 onto the stack so it gets restored instead + * of whatever the user had there before. + */ + PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) + sw r29, r0 + + /* Do syscall trace again, if requested. */ + lw r30, r31 + andi r30, r30, _TIF_SYSCALL_TRACE + bzt r30, 1f + jal do_syscall_trace + FEEDBACK_REENTER(handle_syscall) +1: j .Lresume_userspace /* jump into middle of interrupt_return */ + +.Linvalid_syscall: + /* Report an invalid syscall back to the user program */ + { + PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) + movei r28, -ENOSYS + } + sw r29, r28 + j .Lresume_userspace /* jump into middle of interrupt_return */ + STD_ENDPROC(handle_syscall) + + /* Return the address for oprofile to suppress in backtraces. */ +STD_ENTRY_SECTION(handle_syscall_link_address, .text.handle_syscall) + lnk r0 + { + addli r0, r0, .Lhandle_syscall_link - . + jrp lr + } + STD_ENDPROC(handle_syscall_link_address) + +STD_ENTRY(ret_from_fork) + jal sim_notify_fork + jal schedule_tail + FEEDBACK_REENTER(ret_from_fork) + j .Lresume_userspace /* jump into middle of interrupt_return */ + STD_ENDPROC(ret_from_fork) + + /* + * Code for ill interrupt. + */ + .pushsection .text.handle_ill,"ax" +handle_ill: + finish_interrupt_save handle_ill + + /* + * Check for if we are single stepping in user level. If so, then + * we need to restore the PC. + */ + check_single_stepping ill, .Ldispatch_normal_ill + + { + /* See if the PC is the 1st bundle in the buffer */ + seq r25, r27, r26 + + /* Point to the 2nd bundle in the buffer */ + addi r26, r26, 8 + } + { + /* Point to the original pc */ + addi r24, r29, SINGLESTEP_STATE_ORIG_PC_OFFSET + + /* Branch if the PC is the 1st bundle in the buffer */ + bnz r25, 3f + } + { + /* See if the PC is the 2nd bundle of the buffer */ + seq r25, r27, r26 + + /* Set PC to next instruction */ + addi r24, r29, SINGLESTEP_STATE_NEXT_PC_OFFSET + } + { + /* Point to flags */ + addi r25, r29, SINGLESTEP_STATE_FLAGS_OFFSET + + /* Branch if PC is in the second bundle */ + bz r25, 2f + } + /* Load flags */ + lw r25, r25 + { + /* + * Get the offset for the register to restore + * Note: the lower bound is 2, so we have implicit scaling by 4. + * No multiplication of the register number by the size of a register + * is needed. + */ + mm r27, r25, zero, SINGLESTEP_STATE_TARGET_LB, \ + SINGLESTEP_STATE_TARGET_UB + + /* Mask Rewrite_LR */ + andi r25, r25, SINGLESTEP_STATE_MASK_UPDATE + } + { + addi r29, r29, SINGLESTEP_STATE_UPDATE_VALUE_OFFSET + + /* Don't rewrite temp register */ + bz r25, 3f + } + { + /* Get the temp value */ + lw r29, r29 + + /* Point to where the register is stored */ + add r27, r27, sp + } + + /* Add in the C ABI save area size to the register offset */ + addi r27, r27, C_ABI_SAVE_AREA_SIZE + + /* Restore the user's register with the temp value */ + sw r27, r29 + j 3f + +2: + /* Must be in the third bundle */ + addi r24, r29, SINGLESTEP_STATE_BRANCH_NEXT_PC_OFFSET + +3: + /* set PC and continue */ + lw r26, r24 + sw r28, r26 + + /* Clear TIF_SINGLESTEP */ + GET_THREAD_INFO(r0) + + addi r1, r0, THREAD_INFO_FLAGS_OFFSET + { + lw r2, r1 + addi r0, r0, THREAD_INFO_TASK_OFFSET /* currently a no-op */ + } + andi r2, r2, ~_TIF_SINGLESTEP + sw r1, r2 + + /* Issue a sigtrap */ + { + lw r0, r0 /* indirect thru thread_info to get task_info*/ + addi r1, sp, C_ABI_SAVE_AREA_SIZE /* put ptregs pointer into r1 */ + move r2, zero /* load error code into r2 */ + } + + jal send_sigtrap /* issue a SIGTRAP */ + FEEDBACK_REENTER(handle_ill) + j .Lresume_userspace /* jump into middle of interrupt_return */ + +.Ldispatch_normal_ill: + { + jalr r0 + PTREGS_PTR(r0, PTREGS_OFFSET_BASE) + } + FEEDBACK_REENTER(handle_ill) + { + movei r30, 0 /* not an NMI */ + j interrupt_return + } + STD_ENDPROC(handle_ill) + + .pushsection .rodata, "a" + .align 8 +bpt_code: + bpt + ENDPROC(bpt_code) + .popsection + +/* Various stub interrupt handlers and syscall handlers */ + +STD_ENTRY_LOCAL(_kernel_double_fault) + mfspr r1, EX_CONTEXT_1_0 + move r2, lr + move r3, sp + move r4, r52 + addi sp, sp, -C_ABI_SAVE_AREA_SIZE + j kernel_double_fault + STD_ENDPROC(_kernel_double_fault) + +STD_ENTRY_LOCAL(bad_intr) + mfspr r2, EX_CONTEXT_1_0 + panic "Unhandled interrupt %#x: PC %#lx" + STD_ENDPROC(bad_intr) + +/* Put address of pt_regs in reg and jump. */ +#define PTREGS_SYSCALL(x, reg) \ + STD_ENTRY(x); \ + { \ + PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ + j _##x \ + }; \ + STD_ENDPROC(x) + +PTREGS_SYSCALL(sys_execve, r3) +PTREGS_SYSCALL(sys_sigaltstack, r2) +PTREGS_SYSCALL(sys_rt_sigreturn, r0) + +/* Save additional callee-saves to pt_regs, put address in reg and jump. */ +#define PTREGS_SYSCALL_ALL_REGS(x, reg) \ + STD_ENTRY(x); \ + push_extra_callee_saves reg; \ + j _##x; \ + STD_ENDPROC(x) + +PTREGS_SYSCALL_ALL_REGS(sys_fork, r0) +PTREGS_SYSCALL_ALL_REGS(sys_vfork, r0) +PTREGS_SYSCALL_ALL_REGS(sys_clone, r4) +PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1) + +/* + * This entrypoint is taken for the cmpxchg and atomic_update fast + * swints. We may wish to generalize it to other fast swints at some + * point, but for now there are just two very similar ones, which + * makes it faster. + * + * The fast swint code is designed to have a small footprint. It does + * not save or restore any GPRs, counting on the caller-save registers + * to be available to it on entry. It does not modify any callee-save + * registers (including "lr"). It does not check what PL it is being + * called at, so you'd better not call it other than at PL0. + * + * It does not use the stack, but since it might be re-interrupted by + * a page fault which would assume the stack was valid, it does + * save/restore the stack pointer and zero it out to make sure it gets reset. + * Since we always keep interrupts disabled, the hypervisor won't + * clobber our EX_CONTEXT_1_x registers, so we don't save/restore them + * (other than to advance the PC on return). + * + * We have to manually validate the user vs kernel address range + * (since at PL1 we can read/write both), and for performance reasons + * we don't allow cmpxchg on the fc000000 memory region, since we only + * validate that the user address is below PAGE_OFFSET. + * + * We place it in the __HEAD section to ensure it is relatively + * near to the intvec_SWINT_1 code (reachable by a conditional branch). + * + * Must match register usage in do_page_fault(). + */ + __HEAD + .align 64 + /* Align much later jump on the start of a cache line. */ +#if !ATOMIC_LOCKS_FOUND_VIA_TABLE() + nop; nop +#endif +ENTRY(sys_cmpxchg) + + /* + * Save "sp" and set it zero for any possible page fault. + * + * HACK: We want to both zero sp and check r0's alignment, + * so we do both at once. If "sp" becomes nonzero we + * know r0 is unaligned and branch to the error handler that + * restores sp, so this is OK. + * + * ICS is disabled right now so having a garbage but nonzero + * sp is OK, since we won't execute any faulting instructions + * when it is nonzero. + */ + { + move r27, sp + andi sp, r0, 3 + } + + /* + * Get the lock address in ATOMIC_LOCK_REG, and also validate that the + * address is less than PAGE_OFFSET, since that won't trap at PL1. + * We only use bits less than PAGE_SHIFT to avoid having to worry + * about aliasing among multiple mappings of the same physical page, + * and we ignore the low 3 bits so we have one lock that covers + * both a cmpxchg64() and a cmpxchg() on either its low or high word. + * NOTE: this code must match __atomic_hashed_lock() in lib/atomic.c. + */ + +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + { + /* Check for unaligned input. */ + bnz sp, .Lcmpxchg_badaddr + mm r25, r0, zero, 3, PAGE_SHIFT-1 + } + { + crc32_32 r25, zero, r25 + moveli r21, lo16(atomic_lock_ptr) + } + { + auli r21, r21, ha16(atomic_lock_ptr) + auli r23, zero, hi16(PAGE_OFFSET) /* hugepage-aligned */ + } + { + shri r20, r25, 32 - ATOMIC_HASH_L1_SHIFT + slt_u r23, r0, r23 + + /* + * Ensure that the TLB is loaded before we take out the lock. + * On TILEPro, this will start fetching the value all the way + * into our L1 as well (and if it gets modified before we + * grab the lock, it will be invalidated from our cache + * before we reload it). On tile64, we'll start fetching it + * into our L1 if we're the home, and if we're not, we'll + * still at least start fetching it into the home's L2. + */ + lw r26, r0 + } + { + s2a r21, r20, r21 + bbns r23, .Lcmpxchg_badaddr + } + { + lw r21, r21 + seqi r23, TREG_SYSCALL_NR_NAME, __NR_FAST_cmpxchg64 + andi r25, r25, ATOMIC_HASH_L2_SIZE - 1 + } + { + /* Branch away at this point if we're doing a 64-bit cmpxchg. */ + bbs r23, .Lcmpxchg64 + andi r23, r0, 7 /* Precompute alignment for cmpxchg64. */ + } + + { + /* + * We very carefully align the code that actually runs with + * the lock held (nine bundles) so that we know it is all in + * the icache when we start. This instruction (the jump) is + * at the start of the first cache line, address zero mod 64; + * we jump to somewhere in the second cache line to issue the + * tns, then jump back to finish up. + */ + s2a ATOMIC_LOCK_REG_NAME, r25, r21 + j .Lcmpxchg32_tns + } + +#else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + { + /* Check for unaligned input. */ + bnz sp, .Lcmpxchg_badaddr + auli r23, zero, hi16(PAGE_OFFSET) /* hugepage-aligned */ + } + { + /* + * Slide bits into position for 'mm'. We want to ignore + * the low 3 bits of r0, and consider only the next + * ATOMIC_HASH_SHIFT bits. + * Because of C pointer arithmetic, we want to compute this: + * + * ((char*)atomic_locks + + * (((r0 >> 3) & (1 << (ATOMIC_HASH_SIZE - 1))) << 2)) + * + * Instead of two shifts we just ">> 1", and use 'mm' + * to ignore the low and high bits we don't want. + */ + shri r25, r0, 1 + + slt_u r23, r0, r23 + + /* + * Ensure that the TLB is loaded before we take out the lock. + * On tilepro, this will start fetching the value all the way + * into our L1 as well (and if it gets modified before we + * grab the lock, it will be invalidated from our cache + * before we reload it). On tile64, we'll start fetching it + * into our L1 if we're the home, and if we're not, we'll + * still at least start fetching it into the home's L2. + */ + lw r26, r0 + } + { + /* atomic_locks is page aligned so this suffices to get its addr. */ + auli r21, zero, hi16(atomic_locks) + + bbns r23, .Lcmpxchg_badaddr + } + { + /* + * Insert the hash bits into the page-aligned pointer. + * ATOMIC_HASH_SHIFT is so big that we don't actually hash + * the unmasked address bits, as that may cause unnecessary + * collisions. + */ + mm ATOMIC_LOCK_REG_NAME, r25, r21, 2, (ATOMIC_HASH_SHIFT + 2) - 1 + + seqi r23, TREG_SYSCALL_NR_NAME, __NR_FAST_cmpxchg64 + } + { + /* Branch away at this point if we're doing a 64-bit cmpxchg. */ + bbs r23, .Lcmpxchg64 + andi r23, r0, 7 /* Precompute alignment for cmpxchg64. */ + } + { + /* + * We very carefully align the code that actually runs with + * the lock held (nine bundles) so that we know it is all in + * the icache when we start. This instruction (the jump) is + * at the start of the first cache line, address zero mod 64; + * we jump to somewhere in the second cache line to issue the + * tns, then jump back to finish up. + */ + j .Lcmpxchg32_tns + } + +#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + + ENTRY(__sys_cmpxchg_grab_lock) + + /* + * Perform the actual cmpxchg or atomic_update. + * Note that __futex_mark_unlocked() in uClibc relies on + * atomic_update() to always perform an "mf", so don't make + * it optional or conditional without modifying that code. + */ +.Ldo_cmpxchg32: + { + lw r21, r0 + seqi r23, TREG_SYSCALL_NR_NAME, __NR_FAST_atomic_update + move r24, r2 + } + { + seq r22, r21, r1 /* See if cmpxchg matches. */ + and r25, r21, r1 /* If atomic_update, compute (*mem & mask) */ + } + { + or r22, r22, r23 /* Skip compare branch for atomic_update. */ + add r25, r25, r2 /* Compute (*mem & mask) + addend. */ + } + { + mvnz r24, r23, r25 /* Use atomic_update value if appropriate. */ + bbns r22, .Lcmpxchg32_mismatch + } + sw r0, r24 + + /* Do slow mtspr here so the following "mf" waits less. */ + { + move sp, r27 + mtspr EX_CONTEXT_1_0, r28 + } + mf + + /* The following instruction is the start of the second cache line. */ + { + move r0, r21 + sw ATOMIC_LOCK_REG_NAME, zero + } + iret + + /* Duplicated code here in the case where we don't overlap "mf" */ +.Lcmpxchg32_mismatch: + { + move r0, r21 + sw ATOMIC_LOCK_REG_NAME, zero + } + { + move sp, r27 + mtspr EX_CONTEXT_1_0, r28 + } + iret + + /* + * The locking code is the same for 32-bit cmpxchg/atomic_update, + * and for 64-bit cmpxchg. We provide it as a macro and put + * it into both versions. We can't share the code literally + * since it depends on having the right branch-back address. + * Note that the first few instructions should share the cache + * line with the second half of the actual locked code. + */ + .macro cmpxchg_lock, bitwidth + + /* Lock; if we succeed, jump back up to the read-modify-write. */ +#ifdef CONFIG_SMP + tns r21, ATOMIC_LOCK_REG_NAME +#else + /* + * Non-SMP preserves all the lock infrastructure, to keep the + * code simpler for the interesting (SMP) case. However, we do + * one small optimization here and in atomic_asm.S, which is + * to fake out acquiring the actual lock in the atomic_lock table. + */ + movei r21, 0 +#endif + + /* Issue the slow SPR here while the tns result is in flight. */ + mfspr r28, EX_CONTEXT_1_0 + + { + addi r28, r28, 8 /* return to the instruction after the swint1 */ + bzt r21, .Ldo_cmpxchg\bitwidth + } + /* + * The preceding instruction is the last thing that must be + * on the second cache line. + */ + +#ifdef CONFIG_SMP + /* + * We failed to acquire the tns lock on our first try. Now use + * bounded exponential backoff to retry, like __atomic_spinlock(). + */ + { + moveli r23, 2048 /* maximum backoff time in cycles */ + moveli r25, 32 /* starting backoff time in cycles */ + } +1: mfspr r26, CYCLE_LOW /* get start point for this backoff */ +2: mfspr r22, CYCLE_LOW /* test to see if we've backed off enough */ + sub r22, r22, r26 + slt r22, r22, r25 + bbst r22, 2b + { + shli r25, r25, 1 /* double the backoff; retry the tns */ + tns r21, ATOMIC_LOCK_REG_NAME + } + slt r26, r23, r25 /* is the proposed backoff too big? */ + { + mvnz r25, r26, r23 + bzt r21, .Ldo_cmpxchg\bitwidth + } + j 1b +#endif /* CONFIG_SMP */ + .endm + +.Lcmpxchg32_tns: + cmpxchg_lock 32 + + /* + * This code is invoked from sys_cmpxchg after most of the + * preconditions have been checked. We still need to check + * that r0 is 8-byte aligned, since if it's not we won't + * actually be atomic. However, ATOMIC_LOCK_REG has the atomic + * lock pointer and r27/r28 have the saved SP/PC. + * r23 is holding "r0 & 7" so we can test for alignment. + * The compare value is in r2/r3; the new value is in r4/r5. + * On return, we must put the old value in r0/r1. + */ + .align 64 +.Lcmpxchg64: + { +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + s2a ATOMIC_LOCK_REG_NAME, r25, r21 +#endif + bzt r23, .Lcmpxchg64_tns + } + j .Lcmpxchg_badaddr + +.Ldo_cmpxchg64: + { + lw r21, r0 + addi r25, r0, 4 + } + { + lw r1, r25 + } + seq r26, r21, r2 + { + bz r26, .Lcmpxchg64_mismatch + seq r26, r1, r3 + } + { + bz r26, .Lcmpxchg64_mismatch + } + sw r0, r4 + sw r25, r5 + + /* + * The 32-bit path provides optimized "match" and "mismatch" + * iret paths, but we don't have enough bundles in this cache line + * to do that, so we just make even the "mismatch" path do an "mf". + */ +.Lcmpxchg64_mismatch: + { + move sp, r27 + mtspr EX_CONTEXT_1_0, r28 + } + mf + { + move r0, r21 + sw ATOMIC_LOCK_REG_NAME, zero + } + iret + +.Lcmpxchg64_tns: + cmpxchg_lock 64 + + + /* + * Reset sp and revector to sys_cmpxchg_badaddr(), which will + * just raise the appropriate signal and exit. Doing it this + * way means we don't have to duplicate the code in intvec.S's + * int_hand macro that locates the top of the stack. + */ +.Lcmpxchg_badaddr: + { + moveli TREG_SYSCALL_NR_NAME, __NR_cmpxchg_badaddr + move sp, r27 + } + j intvec_SWINT_1 + ENDPROC(sys_cmpxchg) + ENTRY(__sys_cmpxchg_end) + + +/* The single-step support may need to read all the registers. */ +int_unalign: + push_extra_callee_saves r0 + j do_trap + +/* Include .intrpt1 array of interrupt vectors */ + .section ".intrpt1", "ax" + +#define op_handle_perf_interrupt bad_intr +#define op_handle_aux_perf_interrupt bad_intr + +#define do_hardwall_trap bad_intr + + int_hand INT_ITLB_MISS, ITLB_MISS, \ + do_page_fault, handle_interrupt_no_single_step + int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr + int_hand INT_ILL, ILL, do_trap, handle_ill + int_hand INT_GPV, GPV, do_trap + int_hand INT_SN_ACCESS, SN_ACCESS, do_trap + int_hand INT_IDN_ACCESS, IDN_ACCESS, do_trap + int_hand INT_UDN_ACCESS, UDN_ACCESS, do_trap + int_hand INT_IDN_REFILL, IDN_REFILL, bad_intr + int_hand INT_UDN_REFILL, UDN_REFILL, bad_intr + int_hand INT_IDN_COMPLETE, IDN_COMPLETE, bad_intr + int_hand INT_UDN_COMPLETE, UDN_COMPLETE, bad_intr + int_hand INT_SWINT_3, SWINT_3, do_trap + int_hand INT_SWINT_2, SWINT_2, do_trap + int_hand INT_SWINT_1, SWINT_1, SYSCALL, handle_syscall + int_hand INT_SWINT_0, SWINT_0, do_trap + int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign + int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault + int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault + int_hand INT_DMATLB_MISS, DMATLB_MISS, do_page_fault + int_hand INT_DMATLB_ACCESS, DMATLB_ACCESS, do_page_fault + int_hand INT_SNITLB_MISS, SNITLB_MISS, do_page_fault + int_hand INT_SN_NOTIFY, SN_NOTIFY, bad_intr + int_hand INT_SN_FIREWALL, SN_FIREWALL, do_hardwall_trap + int_hand INT_IDN_FIREWALL, IDN_FIREWALL, bad_intr + int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap + int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt + int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr + int_hand INT_UDN_TIMER, UDN_TIMER, bad_intr + int_hand INT_DMA_NOTIFY, DMA_NOTIFY, bad_intr + int_hand INT_IDN_CA, IDN_CA, bad_intr + int_hand INT_UDN_CA, UDN_CA, bad_intr + int_hand INT_IDN_AVAIL, IDN_AVAIL, bad_intr + int_hand INT_UDN_AVAIL, UDN_AVAIL, bad_intr + int_hand INT_PERF_COUNT, PERF_COUNT, \ + op_handle_perf_interrupt, handle_nmi + int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr + int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr + dc_dispatch INT_INTCTRL_1, INTCTRL_1 + int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr + int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \ + hv_message_intr, handle_interrupt_downcall + int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, \ + tile_dev_intr, handle_interrupt_downcall + int_hand INT_I_ASID, I_ASID, bad_intr + int_hand INT_D_ASID, D_ASID, bad_intr + int_hand INT_DMATLB_MISS_DWNCL, DMATLB_MISS_DWNCL, \ + do_page_fault, handle_interrupt_downcall + int_hand INT_SNITLB_MISS_DWNCL, SNITLB_MISS_DWNCL, \ + do_page_fault, handle_interrupt_downcall + int_hand INT_DMATLB_ACCESS_DWNCL, DMATLB_ACCESS_DWNCL, \ + do_page_fault, handle_interrupt_downcall + int_hand INT_SN_CPL, SN_CPL, bad_intr + int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap +#if CHIP_HAS_AUX_PERF_COUNTERS() + int_hand INT_AUX_PERF_COUNT, AUX_PERF_COUNT, \ + op_handle_aux_perf_interrupt, handle_nmi +#endif + + /* Synthetic interrupt delivered only by the simulator */ + int_hand INT_BREAKPOINT, BREAKPOINT, do_breakpoint diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c new file mode 100644 index 000000000000..24cc6b2abc2c --- /dev/null +++ b/arch/tile/kernel/irq.c @@ -0,0 +1,227 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * The set of interrupts we enable for raw_local_irq_enable(). + * This is initialized to have just a single interrupt that the kernel + * doesn't actually use as a sentinel. During kernel init, + * interrupts are added as the kernel gets prepared to support them. + * NOTE: we could probably initialize them all statically up front. + */ +DEFINE_PER_CPU(unsigned long long, interrupts_enabled_mask) = + INITIAL_INTERRUPTS_ENABLED; +EXPORT_PER_CPU_SYMBOL(interrupts_enabled_mask); + +/* Define per-tile device interrupt state */ +DEFINE_PER_CPU(HV_IntrState, dev_intr_state); + +DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; +EXPORT_PER_CPU_SYMBOL(irq_stat); + + + +/* + * Interrupt dispatcher, invoked upon a hypervisor device interrupt downcall + */ +void tile_dev_intr(struct pt_regs *regs, int intnum) +{ + int irq; + + /* + * Get the device interrupt pending mask from where the hypervisor + * has tucked it away for us. + */ + unsigned long pending_dev_intr_mask = __insn_mfspr(SPR_SYSTEM_SAVE_1_3); + + + /* Track time spent here in an interrupt context. */ + struct pt_regs *old_regs = set_irq_regs(regs); + irq_enter(); + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: less than 1/8th stack free? */ + { + long sp = stack_pointer - (long) current_thread_info(); + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + printk(KERN_EMERG "tile_dev_intr: " + "stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + + for (irq = 0; pending_dev_intr_mask; ++irq) { + if (pending_dev_intr_mask & 0x1) { + generic_handle_irq(irq); + + /* Count device irqs; IPIs are counted elsewhere. */ + if (irq > HV_MAX_IPI_INTERRUPT) + __get_cpu_var(irq_stat).irq_dev_intr_count++; + } + pending_dev_intr_mask >>= 1; + } + + /* + * Track time spent against the current process again and + * process any softirqs if they are waiting. + */ + irq_exit(); + set_irq_regs(old_regs); +} + + +/* Mask an interrupt. */ +static void hv_dev_irq_mask(unsigned int irq) +{ + HV_IntrState *p_intr_state = &__get_cpu_var(dev_intr_state); + hv_disable_intr(p_intr_state, 1 << irq); +} + +/* Unmask an interrupt. */ +static void hv_dev_irq_unmask(unsigned int irq) +{ + /* Re-enable the hypervisor to generate interrupts. */ + HV_IntrState *p_intr_state = &__get_cpu_var(dev_intr_state); + hv_enable_intr(p_intr_state, 1 << irq); +} + +/* + * The HV doesn't latch incoming interrupts while an interrupt is + * disabled, so we need to reenable interrupts before running the + * handler. + * + * ISSUE: Enabling the interrupt this early avoids any race conditions + * but introduces the possibility of nested interrupt stack overflow. + * An imminent change to the HV IRQ model will fix this. + */ +static void hv_dev_irq_ack(unsigned int irq) +{ + hv_dev_irq_unmask(irq); +} + +/* + * Since ack() reenables interrupts, there's nothing to do at eoi(). + */ +static void hv_dev_irq_eoi(unsigned int irq) +{ +} + +static struct irq_chip hv_dev_irq_chip = { + .typename = "hv_dev_irq_chip", + .ack = hv_dev_irq_ack, + .mask = hv_dev_irq_mask, + .unmask = hv_dev_irq_unmask, + .eoi = hv_dev_irq_eoi, +}; + +static struct irqaction resched_action = { + .handler = handle_reschedule_ipi, + .name = "resched", + .dev_id = handle_reschedule_ipi /* unique token */, +}; + +void __init init_IRQ(void) +{ + /* Bind IPI irqs. Does this belong somewhere else in init? */ + tile_irq_activate(IRQ_RESCHEDULE); + BUG_ON(setup_irq(IRQ_RESCHEDULE, &resched_action)); +} + +void __cpuinit init_per_tile_IRQs(void) +{ + int rc; + + /* Set the pointer to the per-tile device interrupt state. */ + HV_IntrState *sv_ptr = &__get_cpu_var(dev_intr_state); + rc = hv_dev_register_intr_state(sv_ptr); + if (rc != HV_OK) + panic("hv_dev_register_intr_state: error %d", rc); + +} + +void tile_irq_activate(unsigned int irq) +{ + /* + * Paravirtualized drivers can call up to the HV to find out + * which irq they're associated with. The HV interface + * doesn't provide a generic call for discovering all valid + * IRQs, so drivers must call this method to initialize newly + * discovered IRQs. + * + * We could also just initialize all 32 IRQs at startup, but + * doing so would lead to a kernel fault if an unexpected + * interrupt fires and jumps to a NULL action. By defering + * the set_irq_chip_and_handler() call, unexpected IRQs are + * handled properly by handle_bad_irq(). + */ + hv_dev_irq_mask(irq); + set_irq_chip_and_handler(irq, &hv_dev_irq_chip, handle_percpu_irq); +} + +void ack_bad_irq(unsigned int irq) +{ + printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); +} + +/* + * Generic, controller-independent functions: + */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *) v, j; + struct irqaction *action; + unsigned long flags; + + if (i == 0) { + seq_printf(p, " "); + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + seq_printf(p, "CPU%-8d", j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + raw_spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ", i); +#ifndef CONFIG_SMP + seq_printf(p, "%10u ", kstat_irqs(i)); +#else + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); +#endif + seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %s", action->name); + + for (action = action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: + raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } + return 0; +} diff --git a/arch/tile/kernel/machine_kexec.c b/arch/tile/kernel/machine_kexec.c new file mode 100644 index 000000000000..ed3e1cb8dcc4 --- /dev/null +++ b/arch/tile/kernel/machine_kexec.c @@ -0,0 +1,291 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * based on machine_kexec.c from other architectures in linux-2.6.18 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * This stuff is not in elf.h and is not in any other kernel include. + * This stuff is needed below in the little boot notes parser to + * extract the command line so we can pass it to the hypervisor. + */ +struct Elf32_Bhdr { + Elf32_Word b_signature; + Elf32_Word b_size; + Elf32_Half b_checksum; + Elf32_Half b_records; +}; +#define ELF_BOOT_MAGIC 0x0E1FB007 +#define EBN_COMMAND_LINE 0x00000004 +#define roundupsz(X) (((X) + 3) & ~3) + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + +void machine_shutdown(void) +{ + /* + * Normally we would stop all the other processors here, but + * the check in machine_kexec_prepare below ensures we'll only + * get this far if we've been booted with "nosmp" on the + * command line or without CONFIG_SMP so there's nothing to do + * here (for now). + */ +} + +void machine_crash_shutdown(struct pt_regs *regs) +{ + /* + * Cannot happen. This type of kexec is disabled on this + * architecture (and enforced in machine_kexec_prepare below). + */ +} + + +int machine_kexec_prepare(struct kimage *image) +{ + if (num_online_cpus() > 1) { + printk(KERN_WARNING "%s: detected attempt to kexec " + "with num_online_cpus() > 1\n", + __func__); + return -ENOSYS; + } + if (image->type != KEXEC_TYPE_DEFAULT) { + printk(KERN_WARNING "%s: detected attempt to kexec " + "with unsupported type: %d\n", + __func__, + image->type); + return -ENOSYS; + } + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ + /* + * We did nothing in machine_kexec_prepare, + * so we have nothing to do here. + */ +} + +/* + * If we can find elf boot notes on this page, return the command + * line. Otherwise, silently return null. Somewhat kludgy, but no + * good way to do this without significantly rearchitecting the + * architecture-independent kexec code. + */ + +static unsigned char *kexec_bn2cl(void *pg) +{ + struct Elf32_Bhdr *bhdrp; + Elf32_Nhdr *nhdrp; + unsigned char *desc; + unsigned char *command_line; + __sum16 csum; + + bhdrp = (struct Elf32_Bhdr *) pg; + + /* + * This routine is invoked for every source page, so make + * sure to quietly ignore every impossible page. + */ + if (bhdrp->b_signature != ELF_BOOT_MAGIC || + bhdrp->b_size > PAGE_SIZE) + return 0; + + /* + * If we get a checksum mismatch, it's possible that this is + * just a false positive, but relatively unlikely. We dump + * out the contents of the section so we can diagnose better. + */ + csum = ip_compute_csum(pg, bhdrp->b_size); + if (csum != 0) { + int i; + unsigned char *p = pg; + int nbytes = min((Elf32_Word)1000, bhdrp->b_size); + printk(KERN_INFO "%s: bad checksum %#x\n", __func__, csum); + printk(KERN_INFO "bytes (%d):", bhdrp->b_size); + for (i = 0; i < nbytes; ++i) + printk(" %02x", p[i]); + if (bhdrp->b_size != nbytes) + printk(" ..."); + printk("\n"); + return 0; + } + + nhdrp = (Elf32_Nhdr *) (bhdrp + 1); + + while (nhdrp->n_type != EBN_COMMAND_LINE) { + + desc = (unsigned char *) (nhdrp + 1); + desc += roundupsz(nhdrp->n_descsz); + + nhdrp = (Elf32_Nhdr *) desc; + + /* still in bounds? */ + if ((unsigned char *) (nhdrp + 1) > + ((unsigned char *) pg) + bhdrp->b_size) { + + printk(KERN_INFO "%s: out of bounds\n", __func__); + return 0; + } + } + + command_line = (unsigned char *) (nhdrp + 1); + desc = command_line; + + while (*desc != '\0') { + desc++; + if (((unsigned long)desc & PAGE_MASK) != (unsigned long)pg) { + printk(KERN_INFO "%s: ran off end of page\n", + __func__); + return 0; + } + } + + return command_line; +} + +static void kexec_find_and_set_command_line(struct kimage *image) +{ + kimage_entry_t *ptr, entry; + + unsigned char *command_line = 0; + unsigned char *r; + HV_Errno hverr; + + for (ptr = &image->head; + (entry = *ptr) && !(entry & IND_DONE); + ptr = (entry & IND_INDIRECTION) ? + phys_to_virt((entry & PAGE_MASK)) : ptr + 1) { + + if ((entry & IND_SOURCE)) { + void *va = + kmap_atomic_pfn(entry >> PAGE_SHIFT, KM_USER0); + r = kexec_bn2cl(va); + if (r) { + command_line = r; + break; + } + kunmap_atomic(va, KM_USER0); + } + } + + if (command_line != 0) { + printk(KERN_INFO "setting new command line to \"%s\"\n", + command_line); + + hverr = hv_set_command_line( + (HV_VirtAddr) command_line, strlen(command_line)); + kunmap_atomic(command_line, KM_USER0); + } else { + printk(KERN_INFO "%s: no command line found; making empty\n", + __func__); + hverr = hv_set_command_line((HV_VirtAddr) command_line, 0); + } + if (hverr) { + printk(KERN_WARNING + "%s: call to hv_set_command_line returned error: %d\n", + __func__, hverr); + + } +} + +/* + * The kexec code range-checks all its PAs, so to avoid having it run + * amok and allocate memory and then sequester it from every other + * controller, we force it to come from controller zero. We also + * disable the oom-killer since if we do end up running out of memory, + * that almost certainly won't help. + */ +struct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order) +{ + gfp_mask |= __GFP_THISNODE | __GFP_NORETRY; + return alloc_pages_node(0, gfp_mask, order); +} + +static void setup_quasi_va_is_pa(void) +{ + HV_PTE *pgtable; + HV_PTE pte; + int i; + + /* + * Flush our TLB to prevent conflicts between the previous contents + * and the new stuff we're about to add. + */ + local_flush_tlb_all(); + + /* setup VA is PA, at least up to PAGE_OFFSET */ + + pgtable = (HV_PTE *)current->mm->pgd; + pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE); + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); + + for (i = 0; i < pgd_index(PAGE_OFFSET); i++) + pgtable[i] = pfn_pte(i << (HPAGE_SHIFT - PAGE_SHIFT), pte); +} + + +NORET_TYPE void machine_kexec(struct kimage *image) +{ + void *reboot_code_buffer; + NORET_TYPE void (*rnk)(unsigned long, void *, unsigned long) + ATTRIB_NORET; + + /* Mask all interrupts before starting to reboot. */ + interrupt_mask_set_mask(~0ULL); + + kexec_find_and_set_command_line(image); + + /* + * Adjust the home caching of the control page to be cached on + * this cpu, and copy the assembly helper into the control + * code page, which we map in the vmalloc area. + */ + homecache_change_page_home(image->control_code_page, 0, + smp_processor_id()); + reboot_code_buffer = vmap(&image->control_code_page, 1, 0, + __pgprot(_PAGE_KERNEL | _PAGE_EXECUTABLE)); + memcpy(reboot_code_buffer, relocate_new_kernel, + relocate_new_kernel_size); + __flush_icache_range( + (unsigned long) reboot_code_buffer, + (unsigned long) reboot_code_buffer + relocate_new_kernel_size); + + setup_quasi_va_is_pa(); + + /* now call it */ + rnk = reboot_code_buffer; + (*rnk)(image->head, reboot_code_buffer, image->start); +} diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c new file mode 100644 index 000000000000..f991f5285d8a --- /dev/null +++ b/arch/tile/kernel/messaging.c @@ -0,0 +1,115 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* All messages are stored here */ +static DEFINE_PER_CPU(HV_MsgState, msg_state); + +void __cpuinit init_messaging() +{ + /* Allocate storage for messages in kernel space */ + HV_MsgState *state = &__get_cpu_var(msg_state); + int rc = hv_register_message_state(state); + if (rc != HV_OK) + panic("hv_register_message_state: error %d", rc); + + /* Make sure downcall interrupts will be enabled. */ + raw_local_irq_unmask(INT_INTCTRL_1); +} + +void hv_message_intr(struct pt_regs *regs, int intnum) +{ + /* + * We enter with interrupts disabled and leave them disabled, + * to match expectations of called functions (e.g. + * do_ccupdate_local() in mm/slab.c). This is also consistent + * with normal call entry for device interrupts. + */ + + int message[HV_MAX_MESSAGE_SIZE/sizeof(int)]; + HV_RcvMsgInfo rmi; + int nmsgs = 0; + + /* Track time spent here in an interrupt context */ + struct pt_regs *old_regs = set_irq_regs(regs); + irq_enter(); + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: less than 1/8th stack free? */ + { + long sp = stack_pointer - (long) current_thread_info(); + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + printk(KERN_EMERG "hv_message_intr: " + "stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + + while (1) { + rmi = hv_receive_message(__get_cpu_var(msg_state), + (HV_VirtAddr) message, + sizeof(message)); + if (rmi.msglen == 0) + break; + + if (rmi.msglen < 0) + panic("hv_receive_message failed: %d", rmi.msglen); + + ++nmsgs; + + if (rmi.source == HV_MSG_TILE) { + int tag; + + /* we just send tags for now */ + BUG_ON(rmi.msglen != sizeof(int)); + + tag = message[0]; +#ifdef CONFIG_SMP + evaluate_message(message[0]); +#else + panic("Received IPI message %d in UP mode", tag); +#endif + } else if (rmi.source == HV_MSG_INTR) { + HV_IntrMsg *him = (HV_IntrMsg *)message; + struct hv_driver_cb *cb = + (struct hv_driver_cb *)him->intarg; + cb->callback(cb, him->intdata); + __get_cpu_var(irq_stat).irq_hv_msg_count++; + } + } + + /* + * We shouldn't have gotten a message downcall with no + * messages available. + */ + if (nmsgs == 0) + panic("Message downcall invoked with no messages!"); + + /* + * Track time spent against the current process again and + * process any softirqs if they are waiting. + */ + irq_exit(); + set_irq_regs(old_regs); +} diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c new file mode 100644 index 000000000000..ed3e91161f88 --- /dev/null +++ b/arch/tile/kernel/module.c @@ -0,0 +1,257 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Based on i386 version, copyright (C) 2001 Rusty Russell. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __tilegx__ +# define Elf_Rela Elf64_Rela +# define ELF_R_SYM ELF64_R_SYM +# define ELF_R_TYPE ELF64_R_TYPE +#else +# define Elf_Rela Elf32_Rela +# define ELF_R_SYM ELF32_R_SYM +# define ELF_R_TYPE ELF32_R_TYPE +#endif + +#ifdef MODULE_DEBUG +#define DEBUGP printk +#else +#define DEBUGP(fmt...) +#endif + +/* + * Allocate some address space in the range MEM_MODULE_START to + * MEM_MODULE_END and populate it with memory. + */ +void *module_alloc(unsigned long size) +{ + struct page **pages; + pgprot_t prot_rwx = __pgprot(_PAGE_KERNEL | _PAGE_KERNEL_EXEC); + struct vm_struct *area; + int i = 0; + int npages; + + if (size == 0) + return NULL; + npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); + if (pages == NULL) + return NULL; + for (; i < npages; ++i) { + pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); + if (!pages[i]) + goto error; + } + + area = __get_vm_area(size, VM_ALLOC, MEM_MODULE_START, MEM_MODULE_END); + if (!area) + goto error; + + if (map_vm_area(area, prot_rwx, &pages)) { + vunmap(area->addr); + goto error; + } + + return area->addr; + +error: + while (--i >= 0) + __free_page(pages[i]); + kfree(pages); + return NULL; +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* + * FIXME: If module_region == mod->init_region, trim exception + * table entries. + */ +} + +/* We don't need anything special. */ +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: .rel relocation unsupported\n", me->name); + return -ENOEXEC; +} + +#ifdef __tilegx__ +/* + * Validate that the high 16 bits of "value" is just the sign-extension of + * the low 48 bits. + */ +static int validate_hw2_last(long value, struct module *me) +{ + if (((value << 16) >> 16) != value) { + printk("module %s: Out of range HW2_LAST value %#lx\n", + me->name, value); + return 0; + } + return 1; +} + +/* + * Validate that "value" isn't too big to hold in a JumpOff relocation. + */ +static int validate_jumpoff(long value) +{ + /* Determine size of jump offset. */ + int shift = __builtin_clzl(get_JumpOff_X1(create_JumpOff_X1(-1))); + + /* Check to see if it fits into the relocation slot. */ + long f = get_JumpOff_X1(create_JumpOff_X1(value)); + f = (f << shift) >> shift; + + return f == value; +} +#endif + +int apply_relocate_add(Elf_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf_Sym *sym; + u64 *location; + unsigned long value; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* + * This is the symbol it is referring to. + * Note that all undefined symbols have been resolved. + */ + sym = (Elf_Sym *)sechdrs[symindex].sh_addr + + ELF_R_SYM(rel[i].r_info); + value = sym->st_value + rel[i].r_addend; + + switch (ELF_R_TYPE(rel[i].r_info)) { + +#define MUNGE(func) (*location = ((*location & ~func(-1)) | func(value))) + +#ifndef __tilegx__ + case R_TILE_32: + *(uint32_t *)location = value; + break; + case R_TILE_IMM16_X0_HA: + value = (value + 0x8000) >> 16; + /*FALLTHROUGH*/ + case R_TILE_IMM16_X0_LO: + MUNGE(create_Imm16_X0); + break; + case R_TILE_IMM16_X1_HA: + value = (value + 0x8000) >> 16; + /*FALLTHROUGH*/ + case R_TILE_IMM16_X1_LO: + MUNGE(create_Imm16_X1); + break; + case R_TILE_JOFFLONG_X1: + value -= (unsigned long) location; /* pc-relative */ + value = (long) value >> 3; /* count by instrs */ + MUNGE(create_JOffLong_X1); + break; +#else + case R_TILEGX_64: + *location = value; + break; + case R_TILEGX_IMM16_X0_HW2_LAST: + if (!validate_hw2_last(value, me)) + return -ENOEXEC; + value >>= 16; + /*FALLTHROUGH*/ + case R_TILEGX_IMM16_X0_HW1: + value >>= 16; + /*FALLTHROUGH*/ + case R_TILEGX_IMM16_X0_HW0: + MUNGE(create_Imm16_X0); + break; + case R_TILEGX_IMM16_X1_HW2_LAST: + if (!validate_hw2_last(value, me)) + return -ENOEXEC; + value >>= 16; + /*FALLTHROUGH*/ + case R_TILEGX_IMM16_X1_HW1: + value >>= 16; + /*FALLTHROUGH*/ + case R_TILEGX_IMM16_X1_HW0: + MUNGE(create_Imm16_X1); + break; + case R_TILEGX_JUMPOFF_X1: + value -= (unsigned long) location; /* pc-relative */ + value = (long) value >> 3; /* count by instrs */ + if (!validate_jumpoff(value)) { + printk("module %s: Out of range jump to" + " %#llx at %#llx (%p)\n", me->name, + sym->st_value + rel[i].r_addend, + rel[i].r_offset, location); + return -ENOEXEC; + } + MUNGE(create_JumpOff_X1); + break; +#endif + +#undef MUNGE + + default: + printk(KERN_ERR "module %s: Unknown relocation: %d\n", + me->name, (int) ELF_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + /* FIXME: perhaps remove the "writable" bit from the TLB? */ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c new file mode 100644 index 000000000000..1d456404f065 --- /dev/null +++ b/arch/tile/kernel/pci-dma.c @@ -0,0 +1,252 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include + +/* Generic DMA mapping functions: */ + +/* + * Allocate what Linux calls "coherent" memory, which for us just + * means uncached. + */ +void *dma_alloc_coherent(struct device *dev, + size_t size, + dma_addr_t *dma_handle, + gfp_t gfp) +{ + u64 dma_mask = dev->coherent_dma_mask ?: DMA_BIT_MASK(32); + int node = dev_to_node(dev); + int order = get_order(size); + struct page *pg; + dma_addr_t addr; + + /* Set GFP_KERNEL to ensure we have memory with a kernel VA. */ + gfp |= GFP_KERNEL | __GFP_ZERO; + + /* + * By forcing NUMA node 0 for 32-bit masks we ensure that the + * high 32 bits of the resulting PA will be zero. If the mask + * size is, e.g., 24, we may still not be able to guarantee a + * suitable memory address, in which case we will return NULL. + * But such devices are uncommon. + */ + if (dma_mask <= DMA_BIT_MASK(32)) + node = 0; + + pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_UNCACHED); + if (pg == NULL) + return NULL; + + addr = page_to_phys(pg); + if (addr + size > dma_mask) { + homecache_free_pages(addr, order); + return NULL; + } + + *dma_handle = addr; + return page_address(pg); +} +EXPORT_SYMBOL(dma_alloc_coherent); + +/* + * Free memory that was allocated with dma_alloc_coherent. + */ +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + homecache_free_pages((unsigned long)vaddr, get_order(size)); +} +EXPORT_SYMBOL(dma_free_coherent); + +/* + * The map routines "map" the specified address range for DMA + * accesses. The memory belongs to the device after this call is + * issued, until it is unmapped with dma_unmap_single. + * + * We don't need to do any mapping, we just flush the address range + * out of the cache and return a DMA address. + * + * The unmap routines do whatever is necessary before the processor + * accesses the memory again, and must be called before the driver + * touches the memory. We can get away with a cache invalidate if we + * can count on nothing having been touched. + */ + + +/* + * dma_map_single can be passed any memory address, and there appear + * to be no alignment constraints. + * + * There is a chance that the start of the buffer will share a cache + * line with some other data that has been touched in the meantime. + */ +dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + struct page *page; + dma_addr_t dma_addr; + int thispage; + + BUG_ON(!valid_dma_direction(direction)); + WARN_ON(size == 0); + + dma_addr = __pa(ptr); + + /* We might have been handed a buffer that wraps a page boundary */ + while ((int)size > 0) { + /* The amount to flush that's on this page */ + thispage = PAGE_SIZE - ((unsigned long)ptr & (PAGE_SIZE - 1)); + thispage = min((int)thispage, (int)size); + /* Is this valid for any page we could be handed? */ + page = pfn_to_page(kaddr_to_pfn(ptr)); + homecache_flush_cache(page, 0); + ptr += thispage; + size -= thispage; + } + + return dma_addr; +} +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); +} +EXPORT_SYMBOL(dma_unmap_single); + +int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, + enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + BUG_ON(!valid_dma_direction(direction)); + + WARN_ON(nents == 0 || sglist->length == 0); + + for_each_sg(sglist, sg, nents, i) { + struct page *page; + sg->dma_address = sg_phys(sg); + page = pfn_to_page(sg->dma_address >> PAGE_SHIFT); + homecache_flush_cache(page, 0); + } + + return nents; +} +EXPORT_SYMBOL(dma_map_sg); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); +} +EXPORT_SYMBOL(dma_unmap_sg); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); + + homecache_flush_cache(page, 0); + + return page_to_pa(page) + offset; +} +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); +} +EXPORT_SYMBOL(dma_unmap_page); + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); +} +EXPORT_SYMBOL(dma_sync_single_for_cpu); + +void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ + unsigned long start = PFN_DOWN(dma_handle); + unsigned long end = PFN_DOWN(dma_handle + size - 1); + unsigned long i; + + BUG_ON(!valid_dma_direction(direction)); + for (i = start; i <= end; ++i) + homecache_flush_cache(pfn_to_page(i), 0); +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); + WARN_ON(nelems == 0 || sg[0].length == 0); +} +EXPORT_SYMBOL(dma_sync_sg_for_cpu); + +/* + * Flush and invalidate cache for scatterlist. + */ +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, + int nelems, enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + BUG_ON(!valid_dma_direction(direction)); + WARN_ON(nelems == 0 || sglist->length == 0); + + for_each_sg(sglist, sg, nelems, i) { + dma_sync_single_for_device(dev, sg->dma_address, + sg_dma_len(sg), direction); + } +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_cpu(dev, dma_handle + offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_cpu); + +void dma_sync_single_range_for_device(struct device *dev, + dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_device(dev, dma_handle + offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_device); + +/* + * dma_alloc_noncoherent() returns non-cacheable memory, so there's no + * need to do any flushing here. + */ +void dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ +} +EXPORT_SYMBOL(dma_cache_sync); diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c new file mode 100644 index 000000000000..92ef925d2f8d --- /dev/null +++ b/arch/tile/kernel/proc.c @@ -0,0 +1,91 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Support /proc/cpuinfo + */ + +#define cpu_to_ptr(n) ((void *)((long)(n)+1)) +#define ptr_to_cpu(p) ((long)(p) - 1) + +static int show_cpuinfo(struct seq_file *m, void *v) +{ + int n = ptr_to_cpu(v); + + if (n == 0) { + char buf[NR_CPUS*5]; + cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask); + seq_printf(m, "cpu count\t: %d\n", num_online_cpus()); + seq_printf(m, "cpu list\t: %s\n", buf); + seq_printf(m, "model name\t: %s\n", chip_model); + seq_printf(m, "flags\t\t:\n"); /* nothing for now */ + seq_printf(m, "cpu MHz\t\t: %llu.%06llu\n", + get_clock_rate() / 1000000, + (get_clock_rate() % 1000000)); + seq_printf(m, "bogomips\t: %lu.%02lu\n\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); + } + +#ifdef CONFIG_SMP + if (!cpu_online(n)) + return 0; +#endif + + seq_printf(m, "processor\t: %d\n", n); + + /* Print only num_online_cpus() blank lines total. */ + if (cpumask_next(n, cpu_online_mask) < nr_cpu_ids) + seq_printf(m, "\n"); + + return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < nr_cpu_ids ? cpu_to_ptr(*pos) : NULL; +} +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} +static void c_stop(struct seq_file *m, void *v) +{ +} +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c new file mode 100644 index 000000000000..824f230e6d1a --- /dev/null +++ b/arch/tile/kernel/process.c @@ -0,0 +1,647 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Use the (x86) "idle=poll" option to prefer low latency when leaving the + * idle loop over low power while in the idle loop, e.g. if we have + * one thread per core and we want to get threads out of futex waits fast. + */ +static int no_idle_nap; +static int __init idle_setup(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "poll")) { + printk("using polling idle threads.\n"); + no_idle_nap = 1; + } else if (!strcmp(str, "halt")) + no_idle_nap = 0; + else + return -1; + + return 0; +} +early_param("idle", idle_setup); + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) +{ + extern void _cpu_idle(void); + int cpu = smp_processor_id(); + + + current_thread_info()->status |= TS_POLLING; + + if (no_idle_nap) { + while (1) { + while (!need_resched()) + cpu_relax(); + schedule(); + } + } + + /* endless idle loop with no priority at all */ + while (1) { + tick_nohz_stop_sched_tick(1); + while (!need_resched()) { + if (cpu_is_offline(cpu)) + BUG(); /* no HOTPLUG_CPU */ + + local_irq_disable(); + __get_cpu_var(irq_stat).idle_timestamp = jiffies; + current_thread_info()->status &= ~TS_POLLING; + /* + * TS_POLLING-cleared state must be visible before we + * test NEED_RESCHED: + */ + smp_mb(); + + if (!need_resched()) + _cpu_idle(); + else + local_irq_enable(); + current_thread_info()->status |= TS_POLLING; + } + tick_nohz_restart_sched_tick(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } +} + +struct thread_info *alloc_thread_info(struct task_struct *task) +{ + struct page *page; + int flags = GFP_KERNEL; + +#ifdef CONFIG_DEBUG_STACK_USAGE + flags |= __GFP_ZERO; +#endif + + page = alloc_pages(flags, THREAD_SIZE_ORDER); + if (!page) + return 0; + + return (struct thread_info *)page_address(page); +} + +/* + * Free a thread_info node, and all of its derivative + * data structures. + */ +void free_thread_info(struct thread_info *info) +{ + struct single_step_state *step_state = info->step_state; + + + if (step_state) { + + /* + * FIXME: we don't munmap step_state->buffer + * because the mm_struct for this process (info->task->mm) + * has already been zeroed in exit_mm(). Keeping a + * reference to it here seems like a bad move, so this + * means we can't munmap() the buffer, and therefore if we + * ptrace multiple threads in a process, we will slowly + * leak user memory. (Note that as soon as the last + * thread in a process dies, we will reclaim all user + * memory including single-step buffers in the usual way.) + * We should either assign a kernel VA to this buffer + * somehow, or we should associate the buffer(s) with the + * mm itself so we can clean them up that way. + */ + kfree(step_state); + } + + free_page((unsigned long)info); +} + +static void save_arch_state(struct thread_struct *t); + +extern void ret_from_fork(void); + +int copy_thread(unsigned long clone_flags, unsigned long sp, + unsigned long stack_size, + struct task_struct *p, struct pt_regs *regs) +{ + struct pt_regs *childregs; + unsigned long ksp; + + /* + * When creating a new kernel thread we pass sp as zero. + * Assign it to a reasonable value now that we have the stack. + */ + if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) + sp = KSTK_TOP(p); + + /* + * Do not clone step state from the parent; each thread + * must make its own lazily. + */ + task_thread_info(p)->step_state = NULL; + + /* + * Start new thread in ret_from_fork so it schedules properly + * and then return from interrupt like the parent. + */ + p->thread.pc = (unsigned long) ret_from_fork; + + /* Save user stack top pointer so we can ID the stack vm area later. */ + p->thread.usp0 = sp; + + /* Record the pid of the process that created this one. */ + p->thread.creator_pid = current->pid; + + /* + * Copy the registers onto the kernel stack so the + * return-from-interrupt code will reload it into registers. + */ + childregs = task_pt_regs(p); + *childregs = *regs; + childregs->regs[0] = 0; /* return value is zero */ + childregs->sp = sp; /* override with new user stack pointer */ + + /* + * Copy the callee-saved registers from the passed pt_regs struct + * into the context-switch callee-saved registers area. + * We have to restore the callee-saved registers since we may + * be cloning a userspace task with userspace register state, + * and we won't be unwinding the same kernel frames to restore them. + * Zero out the C ABI save area to mark the top of the stack. + */ + ksp = (unsigned long) childregs; + ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); + memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG], + CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); + ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + p->thread.ksp = ksp; + +#if CHIP_HAS_TILE_DMA() + /* + * No DMA in the new thread. We model this on the fact that + * fork() clears the pending signals, alarms, and aio for the child. + */ + memset(&p->thread.tile_dma_state, 0, sizeof(struct tile_dma_state)); + memset(&p->thread.dma_async_tlb, 0, sizeof(struct async_tlb)); +#endif + +#if CHIP_HAS_SN_PROC() + /* Likewise, the new thread is not running static processor code. */ + p->thread.sn_proc_running = 0; + memset(&p->thread.sn_async_tlb, 0, sizeof(struct async_tlb)); +#endif + +#if CHIP_HAS_PROC_STATUS_SPR() + /* New thread has its miscellaneous processor state bits clear. */ + p->thread.proc_status = 0; +#endif + + + + /* + * Start the new thread with the current architecture state + * (user interrupt masks, etc.). + */ + save_arch_state(&p->thread); + + return 0; +} + +/* + * Return "current" if it looks plausible, or else a pointer to a dummy. + * This can be helpful if we are just trying to emit a clean panic. + */ +struct task_struct *validate_current(void) +{ + static struct task_struct corrupt = { .comm = "" }; + struct task_struct *tsk = current; + if (unlikely((unsigned long)tsk < PAGE_OFFSET || + (void *)tsk > high_memory || + ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) { + printk("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer); + tsk = &corrupt; + } + return tsk; +} + +/* Take and return the pointer to the previous task, for schedule_tail(). */ +struct task_struct *sim_notify_fork(struct task_struct *prev) +{ + struct task_struct *tsk = current; + __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_FORK_PARENT | + (tsk->thread.creator_pid << _SIM_CONTROL_OPERATOR_BITS)); + __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_FORK | + (tsk->pid << _SIM_CONTROL_OPERATOR_BITS)); + return prev; +} + +int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) +{ + struct pt_regs *ptregs = task_pt_regs(tsk); + elf_core_copy_regs(regs, ptregs); + return 1; +} + +#if CHIP_HAS_TILE_DMA() + +/* Allow user processes to access the DMA SPRs */ +void grant_dma_mpls(void) +{ + __insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1); + __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1); +} + +/* Forbid user processes from accessing the DMA SPRs */ +void restrict_dma_mpls(void) +{ + __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1); + __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1); +} + +/* Pause the DMA engine, then save off its state registers. */ +static void save_tile_dma_state(struct tile_dma_state *dma) +{ + unsigned long state = __insn_mfspr(SPR_DMA_USER_STATUS); + unsigned long post_suspend_state; + + /* If we're running, suspend the engine. */ + if ((state & DMA_STATUS_MASK) == SPR_DMA_STATUS__RUNNING_MASK) + __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__SUSPEND_MASK); + + /* + * Wait for the engine to idle, then save regs. Note that we + * want to record the "running" bit from before suspension, + * and the "done" bit from after, so that we can properly + * distinguish a case where the user suspended the engine from + * the case where the kernel suspended as part of the context + * swap. + */ + do { + post_suspend_state = __insn_mfspr(SPR_DMA_USER_STATUS); + } while (post_suspend_state & SPR_DMA_STATUS__BUSY_MASK); + + dma->src = __insn_mfspr(SPR_DMA_SRC_ADDR); + dma->src_chunk = __insn_mfspr(SPR_DMA_SRC_CHUNK_ADDR); + dma->dest = __insn_mfspr(SPR_DMA_DST_ADDR); + dma->dest_chunk = __insn_mfspr(SPR_DMA_DST_CHUNK_ADDR); + dma->strides = __insn_mfspr(SPR_DMA_STRIDE); + dma->chunk_size = __insn_mfspr(SPR_DMA_CHUNK_SIZE); + dma->byte = __insn_mfspr(SPR_DMA_BYTE); + dma->status = (state & SPR_DMA_STATUS__RUNNING_MASK) | + (post_suspend_state & SPR_DMA_STATUS__DONE_MASK); +} + +/* Restart a DMA that was running before we were context-switched out. */ +static void restore_tile_dma_state(struct thread_struct *t) +{ + const struct tile_dma_state *dma = &t->tile_dma_state; + + /* + * The only way to restore the done bit is to run a zero + * length transaction. + */ + if ((dma->status & SPR_DMA_STATUS__DONE_MASK) && + !(__insn_mfspr(SPR_DMA_USER_STATUS) & SPR_DMA_STATUS__DONE_MASK)) { + __insn_mtspr(SPR_DMA_BYTE, 0); + __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__REQUEST_MASK); + while (__insn_mfspr(SPR_DMA_USER_STATUS) & + SPR_DMA_STATUS__BUSY_MASK) + ; + } + + __insn_mtspr(SPR_DMA_SRC_ADDR, dma->src); + __insn_mtspr(SPR_DMA_SRC_CHUNK_ADDR, dma->src_chunk); + __insn_mtspr(SPR_DMA_DST_ADDR, dma->dest); + __insn_mtspr(SPR_DMA_DST_CHUNK_ADDR, dma->dest_chunk); + __insn_mtspr(SPR_DMA_STRIDE, dma->strides); + __insn_mtspr(SPR_DMA_CHUNK_SIZE, dma->chunk_size); + __insn_mtspr(SPR_DMA_BYTE, dma->byte); + + /* + * Restart the engine if we were running and not done. + * Clear a pending async DMA fault that we were waiting on return + * to user space to execute, since we expect the DMA engine + * to regenerate those faults for us now. Note that we don't + * try to clear the TIF_ASYNC_TLB flag, since it's relatively + * harmless if set, and it covers both DMA and the SN processor. + */ + if ((dma->status & DMA_STATUS_MASK) == SPR_DMA_STATUS__RUNNING_MASK) { + t->dma_async_tlb.fault_num = 0; + __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__REQUEST_MASK); + } +} + +#endif + +static void save_arch_state(struct thread_struct *t) +{ +#if CHIP_HAS_SPLIT_INTR_MASK() + t->interrupt_mask = __insn_mfspr(SPR_INTERRUPT_MASK_0_0) | + ((u64)__insn_mfspr(SPR_INTERRUPT_MASK_0_1) << 32); +#else + t->interrupt_mask = __insn_mfspr(SPR_INTERRUPT_MASK_0); +#endif + t->ex_context[0] = __insn_mfspr(SPR_EX_CONTEXT_0_0); + t->ex_context[1] = __insn_mfspr(SPR_EX_CONTEXT_0_1); + t->system_save[0] = __insn_mfspr(SPR_SYSTEM_SAVE_0_0); + t->system_save[1] = __insn_mfspr(SPR_SYSTEM_SAVE_0_1); + t->system_save[2] = __insn_mfspr(SPR_SYSTEM_SAVE_0_2); + t->system_save[3] = __insn_mfspr(SPR_SYSTEM_SAVE_0_3); + t->intctrl_0 = __insn_mfspr(SPR_INTCTRL_0_STATUS); +#if CHIP_HAS_PROC_STATUS_SPR() + t->proc_status = __insn_mfspr(SPR_PROC_STATUS); +#endif +} + +static void restore_arch_state(const struct thread_struct *t) +{ +#if CHIP_HAS_SPLIT_INTR_MASK() + __insn_mtspr(SPR_INTERRUPT_MASK_0_0, (u32) t->interrupt_mask); + __insn_mtspr(SPR_INTERRUPT_MASK_0_1, t->interrupt_mask >> 32); +#else + __insn_mtspr(SPR_INTERRUPT_MASK_0, t->interrupt_mask); +#endif + __insn_mtspr(SPR_EX_CONTEXT_0_0, t->ex_context[0]); + __insn_mtspr(SPR_EX_CONTEXT_0_1, t->ex_context[1]); + __insn_mtspr(SPR_SYSTEM_SAVE_0_0, t->system_save[0]); + __insn_mtspr(SPR_SYSTEM_SAVE_0_1, t->system_save[1]); + __insn_mtspr(SPR_SYSTEM_SAVE_0_2, t->system_save[2]); + __insn_mtspr(SPR_SYSTEM_SAVE_0_3, t->system_save[3]); + __insn_mtspr(SPR_INTCTRL_0_STATUS, t->intctrl_0); +#if CHIP_HAS_PROC_STATUS_SPR() + __insn_mtspr(SPR_PROC_STATUS, t->proc_status); +#endif +#if CHIP_HAS_TILE_RTF_HWM() + /* + * Clear this whenever we switch back to a process in case + * the previous process was monkeying with it. Even if enabled + * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a + * performance hint, so isn't worth a full save/restore. + */ + __insn_mtspr(SPR_TILE_RTF_HWM, 0); +#endif +} + + +void _prepare_arch_switch(struct task_struct *next) +{ +#if CHIP_HAS_SN_PROC() + int snctl; +#endif +#if CHIP_HAS_TILE_DMA() + struct tile_dma_state *dma = ¤t->thread.tile_dma_state; + if (dma->enabled) + save_tile_dma_state(dma); +#endif +#if CHIP_HAS_SN_PROC() + /* + * Suspend the static network processor if it was running. + * We do not suspend the fabric itself, just like we don't + * try to suspend the UDN. + */ + snctl = __insn_mfspr(SPR_SNCTL); + current->thread.sn_proc_running = + (snctl & SPR_SNCTL__FRZPROC_MASK) == 0; + if (current->thread.sn_proc_running) + __insn_mtspr(SPR_SNCTL, snctl | SPR_SNCTL__FRZPROC_MASK); +#endif +} + + +extern struct task_struct *__switch_to(struct task_struct *prev, + struct task_struct *next, + unsigned long new_system_save_1_0); + +struct task_struct *__sched _switch_to(struct task_struct *prev, + struct task_struct *next) +{ + /* DMA state is already saved; save off other arch state. */ + save_arch_state(&prev->thread); + +#if CHIP_HAS_TILE_DMA() + /* + * Restore DMA in new task if desired. + * Note that it is only safe to restart here since interrupts + * are disabled, so we can't take any DMATLB miss or access + * interrupts before we have finished switching stacks. + */ + if (next->thread.tile_dma_state.enabled) { + restore_tile_dma_state(&next->thread); + grant_dma_mpls(); + } else { + restrict_dma_mpls(); + } +#endif + + /* Restore other arch state. */ + restore_arch_state(&next->thread); + +#if CHIP_HAS_SN_PROC() + /* + * Restart static network processor in the new process + * if it was running before. + */ + if (next->thread.sn_proc_running) { + int snctl = __insn_mfspr(SPR_SNCTL); + __insn_mtspr(SPR_SNCTL, snctl & ~SPR_SNCTL__FRZPROC_MASK); + } +#endif + + + /* + * Switch kernel SP, PC, and callee-saved registers. + * In the context of the new task, return the old task pointer + * (i.e. the task that actually called __switch_to). + * Pass the value to use for SYSTEM_SAVE_1_0 when we reset our sp. + */ + return __switch_to(prev, next, next_current_ksp0(next)); +} + +int _sys_fork(struct pt_regs *regs) +{ + return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); +} + +int _sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tidptr, int __user *child_tidptr, + struct pt_regs *regs) +{ + if (!newsp) + newsp = regs->sp; + return do_fork(clone_flags, newsp, regs, 0, + parent_tidptr, child_tidptr); +} + +int _sys_vfork(struct pt_regs *regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, + regs, 0, NULL, NULL); +} + +/* + * sys_execve() executes a new program. + */ +int _sys_execve(char __user *path, char __user *__user *argv, + char __user *__user *envp, struct pt_regs *regs) +{ + int error; + char *filename; + + filename = getname(path); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, argv, envp, regs); + putname(filename); +out: + return error; +} + +#ifdef CONFIG_COMPAT +int _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, + compat_uptr_t __user *envp, struct pt_regs *regs) +{ + int error; + char *filename; + + filename = getname(path); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = compat_do_execve(filename, argv, envp, regs); + putname(filename); +out: + return error; +} +#endif + +unsigned long get_wchan(struct task_struct *p) +{ + struct KBacktraceIterator kbt; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + for (KBacktraceIterator_init(&kbt, p, NULL); + !KBacktraceIterator_end(&kbt); + KBacktraceIterator_next(&kbt)) { + if (!in_sched_functions(kbt.it.pc)) + return kbt.it.pc; + } + + return 0; +} + +/* + * We pass in lr as zero (cleared in kernel_thread) and the caller + * part of the backtrace ABI on the stack also zeroed (in copy_thread) + * so that backtraces will stop with this function. + * Note that we don't use r0, since copy_thread() clears it. + */ +static void start_kernel_thread(int dummy, int (*fn)(int), int arg) +{ + do_exit(fn(arg)); +} + +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ + regs.pc = (long) start_kernel_thread; + regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ + regs.regs[1] = (long) fn; /* function pointer */ + regs.regs[2] = (long) arg; /* parameter register */ + + /* Ok, create the new process.. */ + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, + 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); + +/* Flush thread state. */ +void flush_thread(void) +{ + /* Nothing */ +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ + /* Nothing */ +} + +#ifdef __tilegx__ +# define LINECOUNT 3 +# define EXTRA_NL "\n" +#else +# define LINECOUNT 4 +# define EXTRA_NL "" +#endif + +void show_regs(struct pt_regs *regs) +{ + struct task_struct *tsk = validate_current(); + int i, linebreak; + printk("\n"); + printk(" Pid: %d, comm: %20s, CPU: %d\n", + tsk->pid, tsk->comm, smp_processor_id()); + for (i = linebreak = 0; i < 53; ++i) { + printk(" r%-2d: "REGFMT, i, regs->regs[i]); + if (++linebreak == LINECOUNT) { + linebreak = 0; + printk("\n"); + } + } + printk(" tp : "REGFMT EXTRA_NL " sp : "REGFMT" lr : "REGFMT"\n", + regs->tp, regs->sp, regs->lr); + printk(" pc : "REGFMT" ex1: %ld faultnum: %ld\n", + regs->pc, regs->ex1, regs->faultnum); + + dump_stack_regs(regs); +} diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c new file mode 100644 index 000000000000..468054928e7d --- /dev/null +++ b/arch/tile/kernel/ptrace.c @@ -0,0 +1,203 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Copied from i386: Ross Biro 1/23/92 + */ + +#include +#include +#include +#include +#include + +void user_enable_single_step(struct task_struct *child) +{ + set_tsk_thread_flag(child, TIF_SINGLESTEP); +} + +void user_disable_single_step(struct task_struct *child) +{ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); +} + +/* + * This routine will put a word on the process's privileged stack. + */ +static void putreg(struct task_struct *task, + unsigned long addr, unsigned long value) +{ + unsigned int regno = addr / sizeof(unsigned long); + struct pt_regs *childregs = task_pt_regs(task); + childregs->regs[regno] = value; + childregs->flags |= PT_FLAGS_RESTORE_REGS; +} + +static unsigned long getreg(struct task_struct *task, unsigned long addr) +{ + unsigned int regno = addr / sizeof(unsigned long); + struct pt_regs *childregs = task_pt_regs(task); + return childregs->regs[regno]; +} + +/* + * Called by kernel/ptrace.c when detaching.. + */ +void ptrace_disable(struct task_struct *child) +{ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); + + /* + * These two are currently unused, but will be set by arch_ptrace() + * and used in the syscall assembly when we do support them. + */ + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); +} + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + unsigned long __user *datap; + unsigned long tmp; + int i; + long ret = -EIO; + +#ifdef CONFIG_COMPAT + if (task_thread_info(current)->status & TS_COMPAT) + data = (u32)data; + if (task_thread_info(child)->status & TS_COMPAT) + addr = (u32)addr; +#endif + datap = (unsigned long __user *)data; + + switch (request) { + + case PTRACE_PEEKUSR: /* Read register from pt_regs. */ + if (addr & (sizeof(data)-1)) + break; + if (addr < 0 || addr >= PTREGS_SIZE) + break; + tmp = getreg(child, addr); /* Read register */ + ret = put_user(tmp, datap); + break; + + case PTRACE_POKEUSR: /* Write register in pt_regs. */ + if (addr & (sizeof(data)-1)) + break; + if (addr < 0 || addr >= PTREGS_SIZE) + break; + putreg(child, addr, data); /* Write register */ + break; + + case PTRACE_GETREGS: /* Get all registers from the child. */ + if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) + break; + for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { + ret = __put_user(getreg(child, i), datap); + if (ret != 0) + break; + datap++; + } + break; + + case PTRACE_SETREGS: /* Set all registers in the child. */ + if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) + break; + for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { + ret = __get_user(tmp, datap); + if (ret != 0) + break; + putreg(child, i, tmp); + datap++; + } + break; + + case PTRACE_GETFPREGS: /* Get the child FPU state. */ + case PTRACE_SETFPREGS: /* Set the child FPU state. */ + break; + + case PTRACE_SETOPTIONS: + /* Support TILE-specific ptrace options. */ + child->ptrace &= ~PT_TRACE_MASK_TILE; + tmp = data & PTRACE_O_MASK_TILE; + data &= ~PTRACE_O_MASK_TILE; + ret = ptrace_request(child, request, addr, data); + if (tmp & PTRACE_O_TRACEMIGRATE) + child->ptrace |= PT_TRACE_MIGRATE; + break; + + default: +#ifdef CONFIG_COMPAT + if (task_thread_info(current)->status & TS_COMPAT) { + ret = compat_ptrace_request(child, request, + addr, data); + break; + } +#endif + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +/* Not used; we handle compat issues in arch_ptrace() directly. */ +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + BUG(); +} +#endif + +void do_syscall_trace(void) +{ + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + + if (!(current->ptrace & PT_PTRACED)) + return; + + /* + * The 0x80 provides a way for the tracing parent to distinguish + * between a syscall stop and SIGTRAP delivery + */ + ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} + +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) +{ + struct siginfo info; + + memset(&info, 0, sizeof(info)); + info.si_signo = SIGTRAP; + info.si_code = TRAP_BRKPT; + info.si_addr = (void __user *) regs->pc; + + /* Send us the fakey SIGTRAP */ + force_sig_info(SIGTRAP, &info, tsk); +} + +/* Handle synthetic interrupt delivered only by the simulator. */ +void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num) +{ + send_sigtrap(current, regs, fault_num); +} diff --git a/arch/tile/kernel/reboot.c b/arch/tile/kernel/reboot.c new file mode 100644 index 000000000000..a4523923605e --- /dev/null +++ b/arch/tile/kernel/reboot.c @@ -0,0 +1,52 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_SMP +#define smp_send_stop() +#endif + +void machine_halt(void) +{ + warn_early_printk(); + raw_local_irq_disable_all(); + smp_send_stop(); + hv_halt(); +} + +void machine_power_off(void) +{ + warn_early_printk(); + raw_local_irq_disable_all(); + smp_send_stop(); + hv_power_off(); +} + +void machine_restart(char *cmd) +{ + raw_local_irq_disable_all(); + smp_send_stop(); + hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd); +} + +/* + * Power off function, if any + */ +void (*pm_power_off)(void) = machine_power_off; diff --git a/arch/tile/kernel/regs_32.S b/arch/tile/kernel/regs_32.S new file mode 100644 index 000000000000..e88d6e122783 --- /dev/null +++ b/arch/tile/kernel/regs_32.S @@ -0,0 +1,145 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include + +/* + * See ; called with prev and next task_struct pointers. + * "prev" is returned in r0 for _switch_to and also for ret_from_fork. + * + * We want to save pc/sp in "prev", and get the new pc/sp from "next". + * We also need to save all the callee-saved registers on the stack. + * + * Intel enables/disables access to the hardware cycle counter in + * seccomp (secure computing) environments if necessary, based on + * has_secure_computing(). We might want to do this at some point, + * though it would require virtualizing the other SPRs under WORLD_ACCESS. + * + * Since we're saving to the stack, we omit sp from this list. + * And for parallels with other architectures, we save lr separately, + * in the thread_struct itself (as the "pc" field). + * + * This code also needs to be aligned with process.c copy_thread() + */ + +#if CALLEE_SAVED_REGS_COUNT != 24 +# error Mismatch between and kernel/entry.S +#endif +#define FRAME_SIZE ((2 + CALLEE_SAVED_REGS_COUNT) * 4) + +#define SAVE_REG(r) { sw r12, r; addi r12, r12, 4 } +#define LOAD_REG(r) { lw r, r12; addi r12, r12, 4 } +#define FOR_EACH_CALLEE_SAVED_REG(f) \ + f(r30); f(r31); \ + f(r32); f(r33); f(r34); f(r35); f(r36); f(r37); f(r38); f(r39); \ + f(r40); f(r41); f(r42); f(r43); f(r44); f(r45); f(r46); f(r47); \ + f(r48); f(r49); f(r50); f(r51); f(r52); + +STD_ENTRY_SECTION(__switch_to, .sched.text) + { + move r10, sp + sw sp, lr + addi sp, sp, -FRAME_SIZE + } + { + addi r11, sp, 4 + addi r12, sp, 8 + } + { + sw r11, r10 + addli r4, r1, TASK_STRUCT_THREAD_KSP_OFFSET + } + { + lw r13, r4 /* Load new sp to a temp register early. */ + addli r3, r0, TASK_STRUCT_THREAD_KSP_OFFSET + } + FOR_EACH_CALLEE_SAVED_REG(SAVE_REG) + { + sw r3, sp + addli r3, r0, TASK_STRUCT_THREAD_PC_OFFSET + } + { + sw r3, lr + addli r4, r1, TASK_STRUCT_THREAD_PC_OFFSET + } + { + lw lr, r4 + addi r12, r13, 8 + } + { + /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */ + move sp, r13 + mtspr SYSTEM_SAVE_1_0, r2 + } + FOR_EACH_CALLEE_SAVED_REG(LOAD_REG) +.L__switch_to_pc: + { + addi sp, sp, FRAME_SIZE + jrp lr /* r0 is still valid here, so return it */ + } + STD_ENDPROC(__switch_to) + +/* Return a suitable address for the backtracer for suspended threads */ +STD_ENTRY_SECTION(get_switch_to_pc, .sched.text) + lnk r0 + { + addli r0, r0, .L__switch_to_pc - . + jrp lr + } + STD_ENDPROC(get_switch_to_pc) + +STD_ENTRY(get_pt_regs) + .irp reg, r0, r1, r2, r3, r4, r5, r6, r7, \ + r8, r9, r10, r11, r12, r13, r14, r15, \ + r16, r17, r18, r19, r20, r21, r22, r23, \ + r24, r25, r26, r27, r28, r29, r30, r31, \ + r32, r33, r34, r35, r36, r37, r38, r39, \ + r40, r41, r42, r43, r44, r45, r46, r47, \ + r48, r49, r50, r51, r52, tp, sp + { + sw r0, \reg + addi r0, r0, 4 + } + .endr + { + sw r0, lr + addi r0, r0, PTREGS_OFFSET_PC - PTREGS_OFFSET_LR + } + lnk r1 + { + sw r0, r1 + addi r0, r0, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC + } + mfspr r1, INTERRUPT_CRITICAL_SECTION + shli r1, r1, SPR_EX_CONTEXT_1_1__ICS_SHIFT + ori r1, r1, KERNEL_PL + { + sw r0, r1 + addi r0, r0, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 + } + { + sw r0, zero /* clear faultnum */ + addi r0, r0, PTREGS_OFFSET_ORIG_R0 - PTREGS_OFFSET_FAULTNUM + } + { + sw r0, zero /* clear orig_r0 */ + addli r0, r0, -PTREGS_OFFSET_ORIG_R0 /* restore r0 to base */ + } + jrp lr + STD_ENDPROC(get_pt_regs) diff --git a/arch/tile/kernel/relocate_kernel.S b/arch/tile/kernel/relocate_kernel.S new file mode 100644 index 000000000000..010b418515f8 --- /dev/null +++ b/arch/tile/kernel/relocate_kernel.S @@ -0,0 +1,280 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * copy new kernel into place and then call hv_reexec + * + */ + +#include +#include +#include +#include + +#define ___hvb MEM_SV_INTRPT + HV_GLUE_START_CPA + +#define ___hv_dispatch(f) (___hvb + (HV_DISPATCH_ENTRY_SIZE * f)) + +#define ___hv_console_putc ___hv_dispatch(HV_DISPATCH_CONSOLE_PUTC) +#define ___hv_halt ___hv_dispatch(HV_DISPATCH_HALT) +#define ___hv_reexec ___hv_dispatch(HV_DISPATCH_REEXEC) +#define ___hv_flush_remote ___hv_dispatch(HV_DISPATCH_FLUSH_REMOTE) + +#undef RELOCATE_NEW_KERNEL_VERBOSE + +STD_ENTRY(relocate_new_kernel) + + move r30, r0 /* page list */ + move r31, r1 /* address of page we are on */ + move r32, r2 /* start address of new kernel */ + + shri r1, r1, PAGE_SHIFT + addi r1, r1, 1 + shli sp, r1, PAGE_SHIFT + addi sp, sp, -8 + /* we now have a stack (whether we need one or not) */ + + moveli r40, lo16(___hv_console_putc) + auli r40, r40, ha16(___hv_console_putc) + +#ifdef RELOCATE_NEW_KERNEL_VERBOSE + moveli r0, 'r' + jalr r40 + + moveli r0, '_' + jalr r40 + + moveli r0, 'n' + jalr r40 + + moveli r0, '_' + jalr r40 + + moveli r0, 'k' + jalr r40 + + moveli r0, '\n' + jalr r40 +#endif + + /* + * Throughout this code r30 is pointer to the element of page + * list we are working on. + * + * Normally we get to the next element of the page list by + * incrementing r30 by four. The exception is if the element + * on the page list is an IND_INDIRECTION in which case we use + * the element with the low bits masked off as the new value + * of r30. + * + * To get this started, we need the value passed to us (which + * will always be an IND_INDIRECTION) in memory somewhere with + * r30 pointing at it. To do that, we push the value passed + * to us on the stack and make r30 point to it. + */ + + sw sp, r30 + move r30, sp + addi sp, sp, -8 + +#if CHIP_HAS_CBOX_HOME_MAP() + /* + * On TILEPro, we need to flush all tiles' caches, since we may + * have been doing hash-for-home caching there. Note that we + * must do this _after_ we're completely done modifying any memory + * other than our output buffer (which we know is locally cached). + * We want the caches to be fully clean when we do the reexec, + * because the hypervisor is going to do this flush again at that + * point, and we don't want that second flush to overwrite any memory. + */ + { + move r0, zero /* cache_pa */ + move r1, zero + } + { + auli r2, zero, ha16(HV_FLUSH_EVICT_L2) /* cache_control */ + movei r3, -1 /* cache_cpumask; -1 means all client tiles */ + } + { + move r4, zero /* tlb_va */ + move r5, zero /* tlb_length */ + } + { + move r6, zero /* tlb_pgsize */ + move r7, zero /* tlb_cpumask */ + } + { + move r8, zero /* asids */ + moveli r20, lo16(___hv_flush_remote) + } + { + move r9, zero /* asidcount */ + auli r20, r20, ha16(___hv_flush_remote) + } + + jalr r20 +#endif + + /* r33 is destination pointer, default to zero */ + + moveli r33, 0 + +.Lloop: lw r10, r30 + + andi r9, r10, 0xf /* low 4 bits tell us what type it is */ + xor r10, r10, r9 /* r10 is now value with low 4 bits stripped */ + + seqi r0, r9, 0x1 /* IND_DESTINATION */ + bzt r0, .Ltry2 + + move r33, r10 + +#ifdef RELOCATE_NEW_KERNEL_VERBOSE + moveli r0, 'd' + jalr r40 +#endif + + addi r30, r30, 4 + j .Lloop + +.Ltry2: + seqi r0, r9, 0x2 /* IND_INDIRECTION */ + bzt r0, .Ltry4 + + move r30, r10 + +#ifdef RELOCATE_NEW_KERNEL_VERBOSE + moveli r0, 'i' + jalr r40 +#endif + + j .Lloop + +.Ltry4: + seqi r0, r9, 0x4 /* IND_DONE */ + bzt r0, .Ltry8 + + mf + +#ifdef RELOCATE_NEW_KERNEL_VERBOSE + moveli r0, 'D' + jalr r40 + moveli r0, '\n' + jalr r40 +#endif + + move r0, r32 + moveli r1, 0 /* arg to hv_reexec is 64 bits */ + + moveli r41, lo16(___hv_reexec) + auli r41, r41, ha16(___hv_reexec) + + jalr r41 + + /* we should not get here */ + + moveli r0, '?' + jalr r40 + moveli r0, '\n' + jalr r40 + + j .Lhalt + +.Ltry8: seqi r0, r9, 0x8 /* IND_SOURCE */ + bz r0, .Lerr /* unknown type */ + + /* copy page at r10 to page at r33 */ + + move r11, r33 + + moveli r0, lo16(PAGE_SIZE) + auli r0, r0, ha16(PAGE_SIZE) + add r33, r33, r0 + + /* copy word at r10 to word at r11 until r11 equals r33 */ + + /* We know page size must be multiple of 16, so we can unroll + * 16 times safely without any edge case checking. + * + * Issue a flush of the destination every 16 words to avoid + * incoherence when starting the new kernel. (Now this is + * just good paranoia because the hv_reexec call will also + * take care of this.) + */ + +1: + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0; addi r11, r11, 4 } + { lw r0, r10; addi r10, r10, 4 } + { sw r11, r0 } + { flush r11 ; addi r11, r11, 4 } + + seq r0, r33, r11 + bzt r0, 1b + +#ifdef RELOCATE_NEW_KERNEL_VERBOSE + moveli r0, 's' + jalr r40 +#endif + + addi r30, r30, 4 + j .Lloop + + +.Lerr: moveli r0, 'e' + jalr r40 + moveli r0, 'r' + jalr r40 + moveli r0, 'r' + jalr r40 + moveli r0, '\n' + jalr r40 +.Lhalt: + moveli r41, lo16(___hv_halt) + auli r41, r41, ha16(___hv_halt) + + jalr r41 + STD_ENDPROC(relocate_new_kernel) + + .section .rodata,"a" + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long .Lend_relocate_new_kernel - relocate_new_kernel diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c new file mode 100644 index 000000000000..934136b61ceb --- /dev/null +++ b/arch/tile/kernel/setup.c @@ -0,0 +1,1497 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* doesn't provide this definition. */ +#ifndef CONFIG_SMP +#define setup_max_cpus 1 +#endif + +static inline int ABS(int x) { return x >= 0 ? x : -x; } + +/* Chip information */ +char chip_model[64] __write_once; + +struct pglist_data node_data[MAX_NUMNODES] __read_mostly; +EXPORT_SYMBOL(node_data); + +/* We only create bootmem data on node 0. */ +static bootmem_data_t __initdata node0_bdata; + +/* Information on the NUMA nodes that we compute early */ +unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; +unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; +unsigned long __initdata node_memmap_pfn[MAX_NUMNODES]; +unsigned long __initdata node_percpu_pfn[MAX_NUMNODES]; +unsigned long __initdata node_free_pfn[MAX_NUMNODES]; + +#ifdef CONFIG_HIGHMEM +/* Page frame index of end of lowmem on each controller. */ +unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES]; + +/* Number of pages that can be mapped into lowmem. */ +static unsigned long __initdata mappable_physpages; +#endif + +/* Data on which physical memory controller corresponds to which NUMA node */ +int node_controller[MAX_NUMNODES] = { [0 ... MAX_NUMNODES-1] = -1 }; + +#ifdef CONFIG_HIGHMEM +/* Map information from VAs to PAs */ +unsigned long pbase_map[1 << (32 - HPAGE_SHIFT)] + __write_once __attribute__((aligned(L2_CACHE_BYTES))); +EXPORT_SYMBOL(pbase_map); + +/* Map information from PAs to VAs */ +void *vbase_map[NR_PA_HIGHBIT_VALUES] + __write_once __attribute__((aligned(L2_CACHE_BYTES))); +EXPORT_SYMBOL(vbase_map); +#endif + +/* Node number as a function of the high PA bits */ +int highbits_to_node[NR_PA_HIGHBIT_VALUES] __write_once; +EXPORT_SYMBOL(highbits_to_node); + +static unsigned int __initdata maxmem_pfn = -1U; +static unsigned int __initdata maxnodemem_pfn[MAX_NUMNODES] = { + [0 ... MAX_NUMNODES-1] = -1U +}; +static nodemask_t __initdata isolnodes; + +#ifdef CONFIG_PCI +enum { DEFAULT_PCI_RESERVE_MB = 64 }; +static unsigned int __initdata pci_reserve_mb = DEFAULT_PCI_RESERVE_MB; +unsigned long __initdata pci_reserve_start_pfn = -1U; +unsigned long __initdata pci_reserve_end_pfn = -1U; +#endif + +static int __init setup_maxmem(char *str) +{ + long maxmem_mb; + if (str == NULL || strict_strtol(str, 0, &maxmem_mb) != 0 || + maxmem_mb == 0) + return -EINVAL; + + maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT - 20)) << + (HPAGE_SHIFT - PAGE_SHIFT); + printk("Forcing RAM used to no more than %dMB\n", + maxmem_pfn >> (20 - PAGE_SHIFT)); + return 0; +} +early_param("maxmem", setup_maxmem); + +static int __init setup_maxnodemem(char *str) +{ + char *endp; + long maxnodemem_mb, node; + + node = str ? simple_strtoul(str, &endp, 0) : INT_MAX; + if (node >= MAX_NUMNODES || *endp != ':' || + strict_strtol(endp+1, 0, &maxnodemem_mb) != 0) + return -EINVAL; + + maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT - 20)) << + (HPAGE_SHIFT - PAGE_SHIFT); + printk("Forcing RAM used on node %ld to no more than %dMB\n", + node, maxnodemem_pfn[node] >> (20 - PAGE_SHIFT)); + return 0; +} +early_param("maxnodemem", setup_maxnodemem); + +static int __init setup_isolnodes(char *str) +{ + char buf[MAX_NUMNODES * 5]; + if (str == NULL || nodelist_parse(str, isolnodes) != 0) + return -EINVAL; + + nodelist_scnprintf(buf, sizeof(buf), isolnodes); + printk("Set isolnodes value to '%s'\n", buf); + return 0; +} +early_param("isolnodes", setup_isolnodes); + +#ifdef CONFIG_PCI +static int __init setup_pci_reserve(char* str) +{ + unsigned long mb; + + if (str == NULL || strict_strtoul(str, 0, &mb) != 0 || + mb > 3 * 1024) + return -EINVAL; + + pci_reserve_mb = mb; + printk("Reserving %dMB for PCIE root complex mappings\n", + pci_reserve_mb); + return 0; +} +early_param("pci_reserve", setup_pci_reserve); +#endif + +#ifndef __tilegx__ +/* + * vmalloc=size forces the vmalloc area to be exactly 'size' bytes. + * This can be used to increase (or decrease) the vmalloc area. + */ +static int __init parse_vmalloc(char *arg) +{ + if (!arg) + return -EINVAL; + + VMALLOC_RESERVE = (memparse(arg, &arg) + PGDIR_SIZE - 1) & PGDIR_MASK; + + /* See validate_va() for more on this test. */ + if ((long)_VMALLOC_START >= 0) + early_panic("\"vmalloc=%#lx\" value too large: maximum %#lx\n", + VMALLOC_RESERVE, _VMALLOC_END - 0x80000000UL); + + return 0; +} +early_param("vmalloc", parse_vmalloc); +#endif + +#ifdef CONFIG_HIGHMEM +/* + * Determine for each controller where its lowmem is mapped and how + * much of it is mapped there. On controller zero, the first few + * megabytes are mapped at 0xfd000000 as code, so in principle we + * could start our data mappings higher up, but for now we don't + * bother, to avoid additional confusion. + * + * One question is whether, on systems with more than 768 Mb and + * controllers of different sizes, to map in a proportionate amount of + * each one, or to try to map the same amount from each controller. + * (E.g. if we have three controllers with 256MB, 1GB, and 256MB + * respectively, do we map 256MB from each, or do we map 128 MB, 512 + * MB, and 128 MB respectively?) For now we use a proportionate + * solution like the latter. + * + * The VA/PA mapping demands that we align our decisions at 16 MB + * boundaries so that we can rapidly convert VA to PA. + */ +static void *__init setup_pa_va_mapping(void) +{ + unsigned long curr_pages = 0; + unsigned long vaddr = PAGE_OFFSET; + nodemask_t highonlynodes = isolnodes; + int i, j; + + memset(pbase_map, -1, sizeof(pbase_map)); + memset(vbase_map, -1, sizeof(vbase_map)); + + /* Node zero cannot be isolated for LOWMEM purposes. */ + node_clear(0, highonlynodes); + + /* Count up the number of pages on non-highonlynodes controllers. */ + mappable_physpages = 0; + for_each_online_node(i) { + if (!node_isset(i, highonlynodes)) + mappable_physpages += + node_end_pfn[i] - node_start_pfn[i]; + } + + for_each_online_node(i) { + unsigned long start = node_start_pfn[i]; + unsigned long end = node_end_pfn[i]; + unsigned long size = end - start; + unsigned long vaddr_end; + + if (node_isset(i, highonlynodes)) { + /* Mark this controller as having no lowmem. */ + node_lowmem_end_pfn[i] = start; + continue; + } + + curr_pages += size; + if (mappable_physpages > MAXMEM_PFN) { + vaddr_end = PAGE_OFFSET + + (((u64)curr_pages * MAXMEM_PFN / + mappable_physpages) + << PAGE_SHIFT); + } else { + vaddr_end = PAGE_OFFSET + (curr_pages << PAGE_SHIFT); + } + for (j = 0; vaddr < vaddr_end; vaddr += HPAGE_SIZE, ++j) { + unsigned long this_pfn = + start + (j << HUGETLB_PAGE_ORDER); + pbase_map[vaddr >> HPAGE_SHIFT] = this_pfn; + if (vbase_map[__pfn_to_highbits(this_pfn)] == + (void *)-1) + vbase_map[__pfn_to_highbits(this_pfn)] = + (void *)(vaddr & HPAGE_MASK); + } + node_lowmem_end_pfn[i] = start + (j << HUGETLB_PAGE_ORDER); + BUG_ON(node_lowmem_end_pfn[i] > end); + } + + /* Return highest address of any mapped memory. */ + return (void *)vaddr; +} +#endif /* CONFIG_HIGHMEM */ + +/* + * Register our most important memory mappings with the debug stub. + * + * This is up to 4 mappings for lowmem, one mapping per memory + * controller, plus one for our text segment. + */ +void __cpuinit store_permanent_mappings(void) +{ + int i; + + for_each_online_node(i) { + HV_PhysAddr pa = ((HV_PhysAddr)node_start_pfn[i]) << PAGE_SHIFT; +#ifdef CONFIG_HIGHMEM + HV_PhysAddr high_mapped_pa = node_lowmem_end_pfn[i]; +#else + HV_PhysAddr high_mapped_pa = node_end_pfn[i]; +#endif + + unsigned long pages = high_mapped_pa - node_start_pfn[i]; + HV_VirtAddr addr = (HV_VirtAddr) __va(pa); + hv_store_mapping(addr, pages << PAGE_SHIFT, pa); + } + + hv_store_mapping((HV_VirtAddr)_stext, + (uint32_t)(_einittext - _stext), 0); +} + +/* + * Use hv_inquire_physical() to populate node_{start,end}_pfn[] + * and node_online_map, doing suitable sanity-checking. + * Also set min_low_pfn, max_low_pfn, and max_pfn. + */ +static void __init setup_memory(void) +{ + int i, j; + int highbits_seen[NR_PA_HIGHBIT_VALUES] = { 0 }; +#ifdef CONFIG_HIGHMEM + long highmem_pages; +#endif +#ifndef __tilegx__ + int cap; +#endif +#if defined(CONFIG_HIGHMEM) || defined(__tilegx__) + long lowmem_pages; +#endif + + /* We are using a char to hold the cpu_2_node[] mapping */ + BUG_ON(MAX_NUMNODES > 127); + + /* Discover the ranges of memory available to us */ + for (i = 0; ; ++i) { + unsigned long start, size, end, highbits; + HV_PhysAddrRange range = hv_inquire_physical(i); + if (range.size == 0) + break; +#ifdef CONFIG_FLATMEM + if (i > 0) { + printk("Can't use discontiguous PAs: %#llx..%#llx\n", + range.size, range.start + range.size); + continue; + } +#endif +#ifndef __tilegx__ + if ((unsigned long)range.start) { + printk("Range not at 4GB multiple: %#llx..%#llx\n", + range.start, range.start + range.size); + continue; + } +#endif + if ((range.start & (HPAGE_SIZE-1)) != 0 || + (range.size & (HPAGE_SIZE-1)) != 0) { + unsigned long long start_pa = range.start; + unsigned long long size = range.size; + range.start = (start_pa + HPAGE_SIZE - 1) & HPAGE_MASK; + range.size -= (range.start - start_pa); + range.size &= HPAGE_MASK; + printk("Range not hugepage-aligned: %#llx..%#llx:" + " now %#llx-%#llx\n", + start_pa, start_pa + size, + range.start, range.start + range.size); + } + highbits = __pa_to_highbits(range.start); + if (highbits >= NR_PA_HIGHBIT_VALUES) { + printk("PA high bits too high: %#llx..%#llx\n", + range.start, range.start + range.size); + continue; + } + if (highbits_seen[highbits]) { + printk("Range overlaps in high bits: %#llx..%#llx\n", + range.start, range.start + range.size); + continue; + } + highbits_seen[highbits] = 1; + if (PFN_DOWN(range.size) > maxnodemem_pfn[i]) { + int size = maxnodemem_pfn[i]; + if (size > 0) { + printk("Maxnodemem reduced node %d to" + " %d pages\n", i, size); + range.size = (HV_PhysAddr)size << PAGE_SHIFT; + } else { + printk("Maxnodemem disabled node %d\n", i); + continue; + } + } + if (num_physpages + PFN_DOWN(range.size) > maxmem_pfn) { + int size = maxmem_pfn - num_physpages; + if (size > 0) { + printk("Maxmem reduced node %d to %d pages\n", + i, size); + range.size = (HV_PhysAddr)size << PAGE_SHIFT; + } else { + printk("Maxmem disabled node %d\n", i); + continue; + } + } + if (i >= MAX_NUMNODES) { + printk("Too many PA nodes (#%d): %#llx...%#llx\n", + i, range.size, range.size + range.start); + continue; + } + + start = range.start >> PAGE_SHIFT; + size = range.size >> PAGE_SHIFT; + end = start + size; + +#ifndef __tilegx__ + if (((HV_PhysAddr)end << PAGE_SHIFT) != + (range.start + range.size)) { + printk("PAs too high to represent: %#llx..%#llx\n", + range.start, range.start + range.size); + continue; + } +#endif +#ifdef CONFIG_PCI + /* + * Blocks that overlap the pci reserved region must + * have enough space to hold the maximum percpu data + * region at the top of the range. If there isn't + * enough space above the reserved region, just + * truncate the node. + */ + if (start <= pci_reserve_start_pfn && + end > pci_reserve_start_pfn) { + unsigned int per_cpu_size = + __per_cpu_end - __per_cpu_start; + unsigned int percpu_pages = + NR_CPUS * (PFN_UP(per_cpu_size) >> PAGE_SHIFT); + if (end < pci_reserve_end_pfn + percpu_pages) { + end = pci_reserve_start_pfn; + printk("PCI mapping region reduced node %d to" + " %ld pages\n", i, end - start); + } + } +#endif + + for (j = __pfn_to_highbits(start); + j <= __pfn_to_highbits(end - 1); j++) + highbits_to_node[j] = i; + + node_start_pfn[i] = start; + node_end_pfn[i] = end; + node_controller[i] = range.controller; + num_physpages += size; + max_pfn = end; + + /* Mark node as online */ + node_set(i, node_online_map); + node_set(i, node_possible_map); + } + +#ifndef __tilegx__ + /* + * For 4KB pages, mem_map "struct page" data is 1% of the size + * of the physical memory, so can be quite big (640 MB for + * four 16G zones). These structures must be mapped in + * lowmem, and since we currently cap out at about 768 MB, + * it's impractical to try to use this much address space. + * For now, arbitrarily cap the amount of physical memory + * we're willing to use at 8 million pages (32GB of 4KB pages). + */ + cap = 8 * 1024 * 1024; /* 8 million pages */ + if (num_physpages > cap) { + int num_nodes = num_online_nodes(); + int cap_each = cap / num_nodes; + unsigned long dropped_pages = 0; + for (i = 0; i < num_nodes; ++i) { + int size = node_end_pfn[i] - node_start_pfn[i]; + if (size > cap_each) { + dropped_pages += (size - cap_each); + node_end_pfn[i] = node_start_pfn[i] + cap_each; + } + } + num_physpages -= dropped_pages; + printk(KERN_WARNING "Only using %ldMB memory;" + " ignoring %ldMB.\n", + num_physpages >> (20 - PAGE_SHIFT), + dropped_pages >> (20 - PAGE_SHIFT)); + printk(KERN_WARNING "Consider using a larger page size.\n"); + } +#endif + + /* Heap starts just above the last loaded address. */ + min_low_pfn = PFN_UP((unsigned long)_end - PAGE_OFFSET); + +#ifdef CONFIG_HIGHMEM + /* Find where we map lowmem from each controller. */ + high_memory = setup_pa_va_mapping(); + + /* Set max_low_pfn based on what node 0 can directly address. */ + max_low_pfn = node_lowmem_end_pfn[0]; + + lowmem_pages = (mappable_physpages > MAXMEM_PFN) ? + MAXMEM_PFN : mappable_physpages; + highmem_pages = (long) (num_physpages - lowmem_pages); + + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + pages_to_mb(highmem_pages > 0 ? highmem_pages : 0)); + printk(KERN_NOTICE "%ldMB LOWMEM available.\n", + pages_to_mb(lowmem_pages)); +#else + /* Set max_low_pfn based on what node 0 can directly address. */ + max_low_pfn = node_end_pfn[0]; + +#ifndef __tilegx__ + if (node_end_pfn[0] > MAXMEM_PFN) { + printk(KERN_WARNING "Only using %ldMB LOWMEM.\n", + MAXMEM>>20); + printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); + max_low_pfn = MAXMEM_PFN; + max_pfn = MAXMEM_PFN; + num_physpages = MAXMEM_PFN; + node_end_pfn[0] = MAXMEM_PFN; + } else { + printk(KERN_NOTICE "%ldMB memory available.\n", + pages_to_mb(node_end_pfn[0])); + } + for (i = 1; i < MAX_NUMNODES; ++i) { + node_start_pfn[i] = 0; + node_end_pfn[i] = 0; + } + high_memory = __va(node_end_pfn[0]); +#else + lowmem_pages = 0; + for (i = 0; i < MAX_NUMNODES; ++i) { + int pages = node_end_pfn[i] - node_start_pfn[i]; + lowmem_pages += pages; + if (pages) + high_memory = pfn_to_kaddr(node_end_pfn[i]); + } + printk(KERN_NOTICE "%ldMB memory available.\n", + pages_to_mb(lowmem_pages)); +#endif +#endif +} + +static void __init setup_bootmem_allocator(void) +{ + unsigned long bootmap_size, first_alloc_pfn, last_alloc_pfn; + + /* Provide a node 0 bdata. */ + NODE_DATA(0)->bdata = &node0_bdata; + +#ifdef CONFIG_PCI + /* Don't let boot memory alias the PCI region. */ + last_alloc_pfn = min(max_low_pfn, pci_reserve_start_pfn); +#else + last_alloc_pfn = max_low_pfn; +#endif + + /* + * Initialize the boot-time allocator (with low memory only): + * The first argument says where to put the bitmap, and the + * second says where the end of allocatable memory is. + */ + bootmap_size = init_bootmem(min_low_pfn, last_alloc_pfn); + + /* + * Let the bootmem allocator use all the space we've given it + * except for its own bitmap. + */ + first_alloc_pfn = min_low_pfn + PFN_UP(bootmap_size); + if (first_alloc_pfn >= last_alloc_pfn) + early_panic("Not enough memory on controller 0 for bootmem\n"); + + free_bootmem(PFN_PHYS(first_alloc_pfn), + PFN_PHYS(last_alloc_pfn - first_alloc_pfn)); + +#ifdef CONFIG_KEXEC + if (crashk_res.start != crashk_res.end) + reserve_bootmem(crashk_res.start, + crashk_res.end - crashk_res.start + 1, 0); +#endif + +} + +void *__init alloc_remap(int nid, unsigned long size) +{ + int pages = node_end_pfn[nid] - node_start_pfn[nid]; + void *map = pfn_to_kaddr(node_memmap_pfn[nid]); + BUG_ON(size != pages * sizeof(struct page)); + memset(map, 0, size); + return map; +} + +static int __init percpu_size(void) +{ + int size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE); +#ifdef CONFIG_MODULES + if (size < PERCPU_ENOUGH_ROOM) + size = PERCPU_ENOUGH_ROOM; +#endif + /* In several places we assume the per-cpu data fits on a huge page. */ + BUG_ON(kdata_huge && size > HPAGE_SIZE); + return size; +} + +static inline unsigned long alloc_bootmem_pfn(int size, unsigned long goal) +{ + void *kva = __alloc_bootmem(size, PAGE_SIZE, goal); + unsigned long pfn = kaddr_to_pfn(kva); + BUG_ON(goal && PFN_PHYS(pfn) != goal); + return pfn; +} + +static void __init zone_sizes_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES] = { 0 }; + unsigned long node_percpu[MAX_NUMNODES] = { 0 }; + int size = percpu_size(); + int num_cpus = smp_height * smp_width; + int i; + + for (i = 0; i < num_cpus; ++i) + node_percpu[cpu_to_node(i)] += size; + + for_each_online_node(i) { + unsigned long start = node_start_pfn[i]; + unsigned long end = node_end_pfn[i]; +#ifdef CONFIG_HIGHMEM + unsigned long lowmem_end = node_lowmem_end_pfn[i]; +#else + unsigned long lowmem_end = end; +#endif + int memmap_size = (end - start) * sizeof(struct page); + node_free_pfn[i] = start; + + /* + * Set aside pages for per-cpu data and the mem_map array. + * + * Since the per-cpu data requires special homecaching, + * if we are in kdata_huge mode, we put it at the end of + * the lowmem region. If we're not in kdata_huge mode, + * we take the per-cpu pages from the bottom of the + * controller, since that avoids fragmenting a huge page + * that users might want. We always take the memmap + * from the bottom of the controller, since with + * kdata_huge that lets it be under a huge TLB entry. + * + * If the user has requested isolnodes for a controller, + * though, there'll be no lowmem, so we just alloc_bootmem + * the memmap. There will be no percpu memory either. + */ + if (__pfn_to_highbits(start) == 0) { + /* In low PAs, allocate via bootmem. */ + unsigned long goal = 0; + node_memmap_pfn[i] = + alloc_bootmem_pfn(memmap_size, goal); + if (kdata_huge) + goal = PFN_PHYS(lowmem_end) - node_percpu[i]; + if (node_percpu[i]) + node_percpu_pfn[i] = + alloc_bootmem_pfn(node_percpu[i], goal); + } else if (cpu_isset(i, isolnodes)) { + node_memmap_pfn[i] = alloc_bootmem_pfn(memmap_size, 0); + BUG_ON(node_percpu[i] != 0); + } else { + /* In high PAs, just reserve some pages. */ + node_memmap_pfn[i] = node_free_pfn[i]; + node_free_pfn[i] += PFN_UP(memmap_size); + if (!kdata_huge) { + node_percpu_pfn[i] = node_free_pfn[i]; + node_free_pfn[i] += PFN_UP(node_percpu[i]); + } else { + node_percpu_pfn[i] = + lowmem_end - PFN_UP(node_percpu[i]); + } + } + +#ifdef CONFIG_HIGHMEM + if (start > lowmem_end) { + zones_size[ZONE_NORMAL] = 0; + zones_size[ZONE_HIGHMEM] = end - start; + } else { + zones_size[ZONE_NORMAL] = lowmem_end - start; + zones_size[ZONE_HIGHMEM] = end - lowmem_end; + } +#else + zones_size[ZONE_NORMAL] = end - start; +#endif + + /* + * Everyone shares node 0's bootmem allocator, but + * we use alloc_remap(), above, to put the actual + * struct page array on the individual controllers, + * which is most of the data that we actually care about. + * We can't place bootmem allocators on the other + * controllers since the bootmem allocator can only + * operate on 32-bit physical addresses. + */ + NODE_DATA(i)->bdata = NODE_DATA(0)->bdata; + + free_area_init_node(i, zones_size, start, NULL); + printk(KERN_DEBUG " DMA zone: %ld per-cpu pages\n", + PFN_UP(node_percpu[i])); + + /* Track the type of memory on each node */ + if (zones_size[ZONE_NORMAL]) + node_set_state(i, N_NORMAL_MEMORY); +#ifdef CONFIG_HIGHMEM + if (end != start) + node_set_state(i, N_HIGH_MEMORY); +#endif + + node_set_online(i); + } +} + +#ifdef CONFIG_NUMA + +/* which logical CPUs are on which nodes */ +struct cpumask node_2_cpu_mask[MAX_NUMNODES] __write_once; +EXPORT_SYMBOL(node_2_cpu_mask); + +/* which node each logical CPU is on */ +char cpu_2_node[NR_CPUS] __write_once __attribute__((aligned(L2_CACHE_BYTES))); +EXPORT_SYMBOL(cpu_2_node); + +/* Return cpu_to_node() except for cpus not yet assigned, which return -1 */ +static int __init cpu_to_bound_node(int cpu, struct cpumask* unbound_cpus) +{ + if (!cpu_possible(cpu) || cpumask_test_cpu(cpu, unbound_cpus)) + return -1; + else + return cpu_to_node(cpu); +} + +/* Return number of immediately-adjacent tiles sharing the same NUMA node. */ +static int __init node_neighbors(int node, int cpu, + struct cpumask *unbound_cpus) +{ + int neighbors = 0; + int w = smp_width; + int h = smp_height; + int x = cpu % w; + int y = cpu / w; + if (x > 0 && cpu_to_bound_node(cpu-1, unbound_cpus) == node) + ++neighbors; + if (x < w-1 && cpu_to_bound_node(cpu+1, unbound_cpus) == node) + ++neighbors; + if (y > 0 && cpu_to_bound_node(cpu-w, unbound_cpus) == node) + ++neighbors; + if (y < h-1 && cpu_to_bound_node(cpu+w, unbound_cpus) == node) + ++neighbors; + return neighbors; +} + +static void __init setup_numa_mapping(void) +{ + int distance[MAX_NUMNODES][NR_CPUS]; + HV_Coord coord; + int cpu, node, cpus, i, x, y; + int num_nodes = num_online_nodes(); + struct cpumask unbound_cpus; + nodemask_t default_nodes; + + cpumask_clear(&unbound_cpus); + + /* Get set of nodes we will use for defaults */ + nodes_andnot(default_nodes, node_online_map, isolnodes); + if (nodes_empty(default_nodes)) { + BUG_ON(!node_isset(0, node_online_map)); + printk("Forcing NUMA node zero available as a default node\n"); + node_set(0, default_nodes); + } + + /* Populate the distance[] array */ + memset(distance, -1, sizeof(distance)); + cpu = 0; + for (coord.y = 0; coord.y < smp_height; ++coord.y) { + for (coord.x = 0; coord.x < smp_width; + ++coord.x, ++cpu) { + BUG_ON(cpu >= nr_cpu_ids); + if (!cpu_possible(cpu)) { + cpu_2_node[cpu] = -1; + continue; + } + for_each_node_mask(node, default_nodes) { + HV_MemoryControllerInfo info = + hv_inquire_memory_controller( + coord, node_controller[node]); + distance[node][cpu] = + ABS(info.coord.x) + ABS(info.coord.y); + } + cpumask_set_cpu(cpu, &unbound_cpus); + } + } + cpus = cpu; + + /* + * Round-robin through the NUMA nodes until all the cpus are + * assigned. We could be more clever here (e.g. create four + * sorted linked lists on the same set of cpu nodes, and pull + * off them in round-robin sequence, removing from all four + * lists each time) but given the relatively small numbers + * involved, O(n^2) seem OK for a one-time cost. + */ + node = first_node(default_nodes); + while (!cpumask_empty(&unbound_cpus)) { + int best_cpu = -1; + int best_distance = INT_MAX; + for (cpu = 0; cpu < cpus; ++cpu) { + if (cpumask_test_cpu(cpu, &unbound_cpus)) { + /* + * Compute metric, which is how much + * closer the cpu is to this memory + * controller than the others, shifted + * up, and then the number of + * neighbors already in the node as an + * epsilon adjustment to try to keep + * the nodes compact. + */ + int d = distance[node][cpu] * num_nodes; + for_each_node_mask(i, default_nodes) { + if (i != node) + d -= distance[i][cpu]; + } + d *= 8; /* allow space for epsilon */ + d -= node_neighbors(node, cpu, &unbound_cpus); + if (d < best_distance) { + best_cpu = cpu; + best_distance = d; + } + } + } + BUG_ON(best_cpu < 0); + cpumask_set_cpu(best_cpu, &node_2_cpu_mask[node]); + cpu_2_node[best_cpu] = node; + cpumask_clear_cpu(best_cpu, &unbound_cpus); + node = next_node(node, default_nodes); + if (node == MAX_NUMNODES) + node = first_node(default_nodes); + } + + /* Print out node assignments and set defaults for disabled cpus */ + cpu = 0; + for (y = 0; y < smp_height; ++y) { + printk(KERN_DEBUG "NUMA cpu-to-node row %d:", y); + for (x = 0; x < smp_width; ++x, ++cpu) { + if (cpu_to_node(cpu) < 0) { + printk(" -"); + cpu_2_node[cpu] = first_node(default_nodes); + } else { + printk(" %d", cpu_to_node(cpu)); + } + } + printk("\n"); + } +} + +static struct cpu cpu_devices[NR_CPUS]; + +static int __init topology_init(void) +{ + int i; + + for_each_online_node(i) + register_one_node(i); + + for_each_present_cpu(i) + register_cpu(&cpu_devices[i], i); + + return 0; +} + +subsys_initcall(topology_init); + +#else /* !CONFIG_NUMA */ + +#define setup_numa_mapping() do { } while (0) + +#endif /* CONFIG_NUMA */ + +/** + * setup_mpls() - Allow the user-space code to access various SPRs. + * + * Also called from online_secondary(). + */ +void __cpuinit setup_mpls(void) +{ + /* Allow asynchronous TLB interrupts. */ +#if CHIP_HAS_TILE_DMA() + raw_local_irq_unmask(INT_DMATLB_MISS); + raw_local_irq_unmask(INT_DMATLB_ACCESS); +#endif +#if CHIP_HAS_SN_PROC() + raw_local_irq_unmask(INT_SNITLB_MISS); +#endif + + /* + * Allow user access to many generic SPRs, like the cycle + * counter, PASS/FAIL/DONE, INTERRUPT_CRITICAL_SECTION, etc. + */ + __insn_mtspr(SPR_MPL_WORLD_ACCESS_SET_0, 1); + +#if CHIP_HAS_SN() + /* Static network is not restricted. */ + __insn_mtspr(SPR_MPL_SN_ACCESS_SET_0, 1); +#endif +#if CHIP_HAS_SN_PROC() + __insn_mtspr(SPR_MPL_SN_NOTIFY_SET_0, 1); + __insn_mtspr(SPR_MPL_SN_CPL_SET_0, 1); +#endif + + /* + * Set the MPL for interrupt control 0 to user level. + * This includes access to the SYSTEM_SAVE and EX_CONTEXT SPRs, + * as well as the PL 0 interrupt mask. + */ + __insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1); +} + +static int __initdata set_initramfs_file; +static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; + +static int __init setup_initramfs_file(char *str) +{ + if (str == NULL) + return -EINVAL; + strncpy(initramfs_file, str, sizeof(initramfs_file) - 1); + set_initramfs_file = 1; + + return 0; +} +early_param("initramfs_file", setup_initramfs_file); + +/* + * We look for an additional "initramfs.cpio.gz" file in the hvfs. + * If there is one, we allocate some memory for it and it will be + * unpacked to the initramfs after any built-in initramfs_data. + */ +static void __init load_hv_initrd(void) +{ + HV_FS_StatInfo stat; + int fd, rc; + void *initrd; + + fd = hv_fs_findfile((HV_VirtAddr) initramfs_file); + if (fd == HV_ENOENT) { + if (set_initramfs_file) + printk("No such hvfs initramfs file '%s'\n", + initramfs_file); + return; + } + BUG_ON(fd < 0); + stat = hv_fs_fstat(fd); + BUG_ON(stat.size < 0); + if (stat.flags & HV_FS_ISDIR) { + printk("Ignoring hvfs file '%s': it's a directory.\n", + initramfs_file); + return; + } + initrd = alloc_bootmem_pages(stat.size); + rc = hv_fs_pread(fd, (HV_VirtAddr) initrd, stat.size, 0); + if (rc != stat.size) { + printk("Error reading %d bytes from hvfs file '%s': %d\n", + stat.size, initramfs_file, rc); + free_bootmem((unsigned long) initrd, stat.size); + return; + } + initrd_start = (unsigned long) initrd; + initrd_end = initrd_start + stat.size; +} + +void __init free_initrd_mem(unsigned long begin, unsigned long end) +{ + free_bootmem(begin, end - begin); +} + +static void __init validate_hv(void) +{ + /* + * It may already be too late, but let's check our built-in + * configuration against what the hypervisor is providing. + */ + unsigned long glue_size = hv_sysconf(HV_SYSCONF_GLUE_SIZE); + int hv_page_size = hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL); + int hv_hpage_size = hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE); + HV_ASIDRange asid_range; + +#ifndef CONFIG_SMP + HV_Topology topology = hv_inquire_topology(); + BUG_ON(topology.coord.x != 0 || topology.coord.y != 0); + if (topology.width != 1 || topology.height != 1) { + printk("Warning: booting UP kernel on %dx%d grid;" + " will ignore all but first tile.\n", + topology.width, topology.height); + } +#endif + + if (PAGE_OFFSET + HV_GLUE_START_CPA + glue_size > (unsigned long)_text) + early_panic("Hypervisor glue size %ld is too big!\n", + glue_size); + if (hv_page_size != PAGE_SIZE) + early_panic("Hypervisor page size %#x != our %#lx\n", + hv_page_size, PAGE_SIZE); + if (hv_hpage_size != HPAGE_SIZE) + early_panic("Hypervisor huge page size %#x != our %#lx\n", + hv_hpage_size, HPAGE_SIZE); + +#ifdef CONFIG_SMP + /* + * Some hypervisor APIs take a pointer to a bitmap array + * whose size is at least the number of cpus on the chip. + * We use a struct cpumask for this, so it must be big enough. + */ + if ((smp_height * smp_width) > nr_cpu_ids) + early_panic("Hypervisor %d x %d grid too big for Linux" + " NR_CPUS %d\n", smp_height, smp_width, + nr_cpu_ids); +#endif + + /* + * Check that we're using allowed ASIDs, and initialize the + * various asid variables to their appropriate initial states. + */ + asid_range = hv_inquire_asid(0); + __get_cpu_var(current_asid) = min_asid = asid_range.start; + max_asid = asid_range.start + asid_range.size - 1; + + if (hv_confstr(HV_CONFSTR_CHIP_MODEL, (HV_VirtAddr)chip_model, + sizeof(chip_model)) < 0) { + printk("Warning: HV_CONFSTR_CHIP_MODEL not available\n"); + strlcpy(chip_model, "unknown", sizeof(chip_model)); + } +} + +static void __init validate_va(void) +{ +#ifndef __tilegx__ /* FIXME: GX: probably some validation relevant here */ + /* + * Similarly, make sure we're only using allowed VAs. + * We assume we can contiguously use MEM_USER_INTRPT .. MEM_HV_INTRPT, + * and 0 .. KERNEL_HIGH_VADDR. + * In addition, make sure we CAN'T use the end of memory, since + * we use the last chunk of each pgd for the pgd_list. + */ + int i, fc_fd_ok = 0; + unsigned long max_va = 0; + unsigned long list_va = + ((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT); + + for (i = 0; ; ++i) { + HV_VirtAddrRange range = hv_inquire_virtual(i); + if (range.size == 0) + break; + if (range.start <= MEM_USER_INTRPT && + range.start + range.size >= MEM_HV_INTRPT) + fc_fd_ok = 1; + if (range.start == 0) + max_va = range.size; + BUG_ON(range.start + range.size > list_va); + } + if (!fc_fd_ok) + early_panic("Hypervisor not configured for VAs 0xfc/0xfd\n"); + if (max_va == 0) + early_panic("Hypervisor not configured for low VAs\n"); + if (max_va < KERNEL_HIGH_VADDR) + early_panic("Hypervisor max VA %#lx smaller than %#lx\n", + max_va, KERNEL_HIGH_VADDR); + + /* Kernel PCs must have their high bit set; see intvec.S. */ + if ((long)VMALLOC_START >= 0) + early_panic( + "Linux VMALLOC region below the 2GB line (%#lx)!\n" + "Reconfigure the kernel with fewer NR_HUGE_VMAPS\n" + "or smaller VMALLOC_RESERVE.\n", + VMALLOC_START); +#endif +} + +/* + * cpu_lotar_map lists all the cpus that are valid for the supervisor + * to cache data on at a page level, i.e. what cpus can be placed in + * the LOTAR field of a PTE. It is equivalent to the set of possible + * cpus plus any other cpus that are willing to share their cache. + * It is set by hv_inquire_tiles(HV_INQ_TILES_LOTAR). + */ +struct cpumask __write_once cpu_lotar_map; +EXPORT_SYMBOL(cpu_lotar_map); + +#if CHIP_HAS_CBOX_HOME_MAP() +/* + * hash_for_home_map lists all the tiles that hash-for-home data + * will be cached on. Note that this may includes tiles that are not + * valid for this supervisor to use otherwise (e.g. if a hypervisor + * device is being shared between multiple supervisors). + * It is set by hv_inquire_tiles(HV_INQ_TILES_HFH_CACHE). + */ +struct cpumask hash_for_home_map; +EXPORT_SYMBOL(hash_for_home_map); +#endif + +/* + * cpu_cacheable_map lists all the cpus whose caches the hypervisor can + * flush on our behalf. It is set to cpu_possible_map OR'ed with + * hash_for_home_map, and it is what should be passed to + * hv_flush_remote() to flush all caches. Note that if there are + * dedicated hypervisor driver tiles that have authorized use of their + * cache, those tiles will only appear in cpu_lotar_map, NOT in + * cpu_cacheable_map, as they are a special case. + */ +struct cpumask __write_once cpu_cacheable_map; +EXPORT_SYMBOL(cpu_cacheable_map); + +static __initdata struct cpumask disabled_map; + +static int __init disabled_cpus(char *str) +{ + int boot_cpu = smp_processor_id(); + + if (str == NULL || cpulist_parse_crop(str, &disabled_map) != 0) + return -EINVAL; + if (cpumask_test_cpu(boot_cpu, &disabled_map)) { + printk("disabled_cpus: can't disable boot cpu %d\n", boot_cpu); + cpumask_clear_cpu(boot_cpu, &disabled_map); + } + return 0; +} + +early_param("disabled_cpus", disabled_cpus); + +void __init print_disabled_cpus() +{ + if (!cpumask_empty(&disabled_map)) { + char buf[100]; + cpulist_scnprintf(buf, sizeof(buf), &disabled_map); + printk(KERN_INFO "CPUs not available for Linux: %s\n", buf); + } +} + +static void __init setup_cpu_maps(void) +{ + struct cpumask hv_disabled_map, cpu_possible_init; + int boot_cpu = smp_processor_id(); + int cpus, i, rc; + + /* Learn which cpus are allowed by the hypervisor. */ + rc = hv_inquire_tiles(HV_INQ_TILES_AVAIL, + (HV_VirtAddr) cpumask_bits(&cpu_possible_init), + sizeof(cpu_cacheable_map)); + if (rc < 0) + early_panic("hv_inquire_tiles(AVAIL) failed: rc %d\n", rc); + if (!cpumask_test_cpu(boot_cpu, &cpu_possible_init)) + early_panic("Boot CPU %d disabled by hypervisor!\n", boot_cpu); + + /* Compute the cpus disabled by the hvconfig file. */ + cpumask_complement(&hv_disabled_map, &cpu_possible_init); + + /* Include them with the cpus disabled by "disabled_cpus". */ + cpumask_or(&disabled_map, &disabled_map, &hv_disabled_map); + + /* + * Disable every cpu after "setup_max_cpus". But don't mark + * as disabled the cpus that are outside of our initial rectangle, + * since that turns out to be confusing. + */ + cpus = 1; /* this cpu */ + cpumask_set_cpu(boot_cpu, &disabled_map); /* ignore this cpu */ + for (i = 0; cpus < setup_max_cpus; ++i) + if (!cpumask_test_cpu(i, &disabled_map)) + ++cpus; + for (; i < smp_height * smp_width; ++i) + cpumask_set_cpu(i, &disabled_map); + cpumask_clear_cpu(boot_cpu, &disabled_map); /* reset this cpu */ + for (i = smp_height * smp_width; i < NR_CPUS; ++i) + cpumask_clear_cpu(i, &disabled_map); + + /* + * Setup cpu_possible map as every cpu allocated to us, minus + * the results of any "disabled_cpus" settings. + */ + cpumask_andnot(&cpu_possible_init, &cpu_possible_init, &disabled_map); + init_cpu_possible(&cpu_possible_init); + + /* Learn which cpus are valid for LOTAR caching. */ + rc = hv_inquire_tiles(HV_INQ_TILES_LOTAR, + (HV_VirtAddr) cpumask_bits(&cpu_lotar_map), + sizeof(cpu_lotar_map)); + if (rc < 0) { + printk("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n"); + cpu_lotar_map = cpu_possible_map; + } + +#if CHIP_HAS_CBOX_HOME_MAP() + /* Retrieve set of CPUs used for hash-for-home caching */ + rc = hv_inquire_tiles(HV_INQ_TILES_HFH_CACHE, + (HV_VirtAddr) hash_for_home_map.bits, + sizeof(hash_for_home_map)); + if (rc < 0) + early_panic("hv_inquire_tiles(HFH_CACHE) failed: rc %d\n", rc); + cpumask_or(&cpu_cacheable_map, &cpu_possible_map, &hash_for_home_map); +#else + cpu_cacheable_map = cpu_possible_map; +#endif +} + + +static int __init dataplane(char *str) +{ + printk("WARNING: dataplane support disabled in this kernel\n"); + return 0; +} + +early_param("dataplane", dataplane); + +#ifdef CONFIG_CMDLINE_BOOL +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; +#endif + +void __init setup_arch(char **cmdline_p) +{ + int len; + +#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) + len = hv_get_command_line((HV_VirtAddr) boot_command_line, + COMMAND_LINE_SIZE); + if (boot_command_line[0]) + printk("WARNING: ignoring dynamic command line \"%s\"\n", + boot_command_line); + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +#else + char *hv_cmdline; +#if defined(CONFIG_CMDLINE_BOOL) + if (builtin_cmdline[0]) { + int builtin_len = strlcpy(boot_command_line, builtin_cmdline, + COMMAND_LINE_SIZE); + if (builtin_len < COMMAND_LINE_SIZE-1) + boot_command_line[builtin_len++] = ' '; + hv_cmdline = &boot_command_line[builtin_len]; + len = COMMAND_LINE_SIZE - builtin_len; + } else +#endif + { + hv_cmdline = boot_command_line; + len = COMMAND_LINE_SIZE; + } + len = hv_get_command_line((HV_VirtAddr) hv_cmdline, len); + if (len < 0 || len > COMMAND_LINE_SIZE) + early_panic("hv_get_command_line failed: %d\n", len); +#endif + + *cmdline_p = boot_command_line; + + /* Set disabled_map and setup_max_cpus very early */ + parse_early_param(); + + /* Make sure the kernel is compatible with the hypervisor. */ + validate_hv(); + validate_va(); + + setup_cpu_maps(); + + +#ifdef CONFIG_PCI + /* + * Initialize the PCI structures. This is done before memory + * setup so that we know whether or not a pci_reserve region + * is necessary. + */ + if (tile_pci_init() == 0) + pci_reserve_mb = 0; + + /* PCI systems reserve a region just below 4GB for mapping iomem. */ + pci_reserve_end_pfn = (1 << (32 - PAGE_SHIFT)); + pci_reserve_start_pfn = pci_reserve_end_pfn - + (pci_reserve_mb << (20 - PAGE_SHIFT)); +#endif + + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; + + setup_memory(); + store_permanent_mappings(); + setup_bootmem_allocator(); + + /* + * NOTE: before this point _nobody_ is allowed to allocate + * any memory using the bootmem allocator. + */ + + paging_init(); + setup_numa_mapping(); + zone_sizes_init(); + set_page_homes(); + setup_mpls(); + setup_clock(); + load_hv_initrd(); +} + + +/* + * Set up per-cpu memory. + */ + +unsigned long __per_cpu_offset[NR_CPUS] __write_once; +EXPORT_SYMBOL(__per_cpu_offset); + +static size_t __initdata pfn_offset[MAX_NUMNODES] = { 0 }; +static unsigned long __initdata percpu_pfn[NR_CPUS] = { 0 }; + +/* + * As the percpu code allocates pages, we return the pages from the + * end of the node for the specified cpu. + */ +static void *__init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) +{ + int nid = cpu_to_node(cpu); + unsigned long pfn = node_percpu_pfn[nid] + pfn_offset[nid]; + + BUG_ON(size % PAGE_SIZE != 0); + pfn_offset[nid] += size / PAGE_SIZE; + if (percpu_pfn[cpu] == 0) + percpu_pfn[cpu] = pfn; + return pfn_to_kaddr(pfn); +} + +/* + * Pages reserved for percpu memory are not freeable, and in any case we are + * on a short path to panic() in setup_per_cpu_area() at this point anyway. + */ +static void __init pcpu_fc_free(void *ptr, size_t size) +{ +} + +/* + * Set up vmalloc page tables using bootmem for the percpu code. + */ +static void __init pcpu_fc_populate_pte(unsigned long addr) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + BUG_ON(pgd_addr_invalid(addr)); + + pgd = swapper_pg_dir + pgd_index(addr); + pud = pud_offset(pgd, addr); + BUG_ON(!pud_present(*pud)); + pmd = pmd_offset(pud, addr); + if (pmd_present(*pmd)) { + BUG_ON(pmd_huge_page(*pmd)); + } else { + pte = __alloc_bootmem(L2_KERNEL_PGTABLE_SIZE, + HV_PAGE_TABLE_ALIGN, 0); + pmd_populate_kernel(&init_mm, pmd, pte); + } +} + +void __init setup_per_cpu_areas(void) +{ + struct page *pg; + unsigned long delta, pfn, lowmem_va; + unsigned long size = percpu_size(); + char *ptr; + int rc, cpu, i; + + rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE, pcpu_fc_alloc, + pcpu_fc_free, pcpu_fc_populate_pte); + if (rc < 0) + panic("Cannot initialize percpu area (err=%d)", rc); + + delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; + for_each_possible_cpu(cpu) { + __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; + + /* finv the copy out of cache so we can change homecache */ + ptr = pcpu_base_addr + pcpu_unit_offsets[cpu]; + __finv_buffer(ptr, size); + pfn = percpu_pfn[cpu]; + + /* Rewrite the page tables to cache on that cpu */ + pg = pfn_to_page(pfn); + for (i = 0; i < size; i += PAGE_SIZE, ++pfn, ++pg) { + + /* Update the vmalloc mapping and page home. */ + pte_t *ptep = + virt_to_pte(NULL, (unsigned long)ptr + i); + pte_t pte = *ptep; + BUG_ON(pfn != pte_pfn(pte)); + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3); + pte = set_remote_cache_cpu(pte, cpu); + set_pte(ptep, pte); + + /* Update the lowmem mapping for consistency. */ + lowmem_va = (unsigned long)pfn_to_kaddr(pfn); + ptep = virt_to_pte(NULL, lowmem_va); + if (pte_huge(*ptep)) { + printk(KERN_DEBUG "early shatter of huge page" + " at %#lx\n", lowmem_va); + shatter_pmd((pmd_t *)ptep); + ptep = virt_to_pte(NULL, lowmem_va); + BUG_ON(pte_huge(*ptep)); + } + BUG_ON(pfn != pte_pfn(*ptep)); + set_pte(ptep, pte); + } + } + + /* Set our thread pointer appropriately. */ + set_my_cpu_offset(__per_cpu_offset[smp_processor_id()]); + + /* Make sure the finv's have completed. */ + mb_incoherent(); + + /* Flush the TLB so we reference it properly from here on out. */ + local_flush_tlb_all(); +} + +static struct resource data_resource = { + .name = "Kernel data", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource code_resource = { + .name = "Kernel code", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +/* + * We reserve all resources above 4GB so that PCI won't try to put + * mappings above 4GB; the standard allows that for some devices but + * the probing code trunates values to 32 bits. + */ +#ifdef CONFIG_PCI +static struct resource* __init +insert_non_bus_resource(void) +{ + struct resource *res = + kzalloc(sizeof(struct resource), GFP_ATOMIC); + res->name = "Non-Bus Physical Address Space"; + res->start = (1ULL << 32); + res->end = -1LL; + res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + if (insert_resource(&iomem_resource, res)) { + kfree(res); + return NULL; + } + return res; +} +#endif + +static struct resource* __init +insert_ram_resource(u64 start_pfn, u64 end_pfn) +{ + struct resource *res = + kzalloc(sizeof(struct resource), GFP_ATOMIC); + res->name = "System RAM"; + res->start = start_pfn << PAGE_SHIFT; + res->end = (end_pfn << PAGE_SHIFT) - 1; + res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + if (insert_resource(&iomem_resource, res)) { + kfree(res); + return NULL; + } + return res; +} + +/* + * Request address space for all standard resources + * + * If the system includes PCI root complex drivers, we need to create + * a window just below 4GB where PCI BARs can be mapped. + */ +static int __init request_standard_resources(void) +{ + int i; + enum { CODE_DELTA = MEM_SV_INTRPT - PAGE_OFFSET }; + + iomem_resource.end = -1LL; +#ifdef CONFIG_PCI + insert_non_bus_resource(); +#endif + + for_each_online_node(i) { + u64 start_pfn = node_start_pfn[i]; + u64 end_pfn = node_end_pfn[i]; + +#ifdef CONFIG_PCI + if (start_pfn <= pci_reserve_start_pfn && + end_pfn > pci_reserve_start_pfn) { + if (end_pfn > pci_reserve_end_pfn) + insert_ram_resource(pci_reserve_end_pfn, + end_pfn); + end_pfn = pci_reserve_start_pfn; + } +#endif + insert_ram_resource(start_pfn, end_pfn); + } + + code_resource.start = __pa(_text - CODE_DELTA); + code_resource.end = __pa(_etext - CODE_DELTA)-1; + data_resource.start = __pa(_sdata); + data_resource.end = __pa(_end)-1; + + insert_resource(&iomem_resource, &code_resource); + insert_resource(&iomem_resource, &data_resource); + +#ifdef CONFIG_KEXEC + insert_resource(&iomem_resource, &crashk_res); +#endif + + return 0; +} + +subsys_initcall(request_standard_resources); diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c new file mode 100644 index 000000000000..7ea85eb85242 --- /dev/null +++ b/arch/tile/kernel/signal.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_SIG 0 + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + + +/* Caller before callee in this file; other callee is in assembler */ +void do_signal(struct pt_regs *regs); + +int _sys_sigaltstack(const stack_t __user *uss, + stack_t __user *uoss, struct pt_regs *regs) +{ + return do_sigaltstack(uss, uoss, regs->sp); +} + + +/* + * Do a signal return; undo the signal stack. + */ + +int restore_sigcontext(struct pt_regs *regs, + struct sigcontext __user *sc, long *pr0) +{ + int err = 0; + int i; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) + err |= __get_user(((long *)regs)[i], + &((long *)(&sc->regs))[i]); + + regs->faultnum = INT_SWINT_1_SIGRETURN; + + err |= __get_user(*pr0, &sc->regs.regs[0]); + return err; +} + +int _sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe __user *frame = + (struct rt_sigframe __user *)(regs->sp); + sigset_t set; + long r0; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) + goto badframe; + + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) + goto badframe; + + return r0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) +{ + int i, err = 0; + + for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) + err |= __put_user(((long *)regs)[i], + &((long *)(&sc->regs))[i]); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void __user *get_sigframe(struct k_sigaction *ka, + struct pt_regs *regs, + size_t frame_size) +{ + unsigned long sp; + + /* Default to using normal stack */ + sp = regs->sp; + + /* + * If we are on the alternate signal stack and would overflow + * it, don't. Return an always-bogus address instead so we + * will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) + return (void __user *) -1L; + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (sas_ss_flags(sp) == 0) + sp = current->sas_ss_sp + current->sas_ss_size; + } + + sp -= frame_size; + /* + * Align the stack pointer according to the TILE ABI, + * i.e. so that on function entry (sp & 15) == 0. + */ + sp &= -16UL; + return (void __user *) sp; +} + +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + unsigned long restorer; + struct rt_sigframe __user *frame; + int err = 0; + int usig; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + /* Always write at least the signal number for the stack backtracer. */ + if (ka->sa.sa_flags & SA_SIGINFO) { + /* At sigreturn time, restore the callee-save registers too. */ + err |= copy_siginfo_to_user(&frame->info, info); + regs->flags |= PT_FLAGS_RESTORE_REGS; + } else { + err |= __put_user(info->si_signo, &frame->info.si_signo); + } + + /* Create the ucontext. */ + err |= __clear_user(&frame->save_area, sizeof(frame->save_area)); + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)(current->sas_ss_sp), + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto give_sigsegv; + + restorer = VDSO_BASE; + if (ka->sa.sa_flags & SA_RESTORER) + restorer = (unsigned long) ka->sa.sa_restorer; + + /* + * Set up registers for signal handler. + * Registers that we don't modify keep the value they had from + * user-space at the time we took the signal. + */ + regs->pc = (unsigned long) ka->sa.sa_handler; + regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ + regs->sp = (unsigned long) frame; + regs->lr = restorer; + regs->regs[0] = (unsigned long) usig; + + if (ka->sa.sa_flags & SA_SIGINFO) { + /* Need extra arguments, so mark to restore caller-saves. */ + regs->regs[1] = (unsigned long) &frame->info; + regs->regs[2] = (unsigned long) &frame->uc; + regs->flags |= PT_FLAGS_CALLER_SAVES; + } + + /* + * Notify any tracer that was single-stepping it. + * The tracer may want to single-step inside the + * handler too. + */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return -EFAULT; +} + +/* + * OK, we're invoking a handler + */ + +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, + struct pt_regs *regs) +{ + int ret; + + + /* Are we from a system call? */ + if (regs->faultnum == INT_SWINT_1) { + /* If so, check system call restarting.. */ + switch (regs->regs[0]) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + regs->regs[0] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[0] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* Reload caller-saves to restore r0..r5 and r10. */ + regs->flags |= PT_FLAGS_CALLER_SAVES; + regs->regs[0] = regs->orig_r0; + regs->pc -= 8; + } + } + + /* Set up the stack frame */ +#ifdef CONFIG_COMPAT + if (is_compat_task()) + ret = compat_setup_rt_frame(sig, ka, info, oldset, regs); + else +#endif + ret = setup_rt_frame(sig, ka, info, oldset, regs); + if (ret == 0) { + /* This code is only called from system calls or from + * the work_pending path in the return-to-user code, and + * either way we can re-enable interrupts unconditionally. + */ + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, + ¤t->blocked, &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + return ret; +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + */ +void do_signal(struct pt_regs *regs) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; + sigset_t *oldset; + + /* + * i386 will check if we're coming from kernel mode and bail out + * here. In my experience this just turns weird crashes into + * weird spin-hangs. But if we find a case where this seems + * helpful, we can reinstate the check on "!user_mode(regs)". + */ + + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } + + return; + } + + /* Did we come from a system call? */ + if (regs->faultnum == INT_SWINT_1) { + /* Restart the system call - no handlers present */ + switch (regs->regs[0]) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + regs->flags |= PT_FLAGS_CALLER_SAVES; + regs->regs[0] = regs->orig_r0; + regs->pc -= 8; + break; + + case -ERESTART_RESTARTBLOCK: + regs->flags |= PT_FLAGS_CALLER_SAVES; + regs->regs[TREG_SYSCALL_NR] = __NR_restart_syscall; + regs->pc -= 8; + break; + } + } + + /* If there's no signal to deliver, just put the saved sigmask back. */ + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } +} diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c new file mode 100644 index 000000000000..266aae123632 --- /dev/null +++ b/arch/tile/kernel/single_step.c @@ -0,0 +1,656 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * A code-rewriter that enables instruction single-stepping. + * Derived from iLib's single-stepping code. + */ + +#ifndef __tilegx__ /* No support for single-step yet. */ + +/* These functions are only used on the TILE platform */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define signExtend17(val) sign_extend((val), 17) +#define TILE_X1_MASK (0xffffffffULL << 31) + +int unaligned_printk; + +static int __init setup_unaligned_printk(char *str) +{ + long val; + if (strict_strtol(str, 0, &val) != 0) + return 0; + unaligned_printk = val; + printk("Printk for each unaligned data accesses is %s\n", + unaligned_printk ? "enabled" : "disabled"); + return 1; +} +__setup("unaligned_printk=", setup_unaligned_printk); + +unsigned int unaligned_fixup_count; + +enum mem_op { + MEMOP_NONE, + MEMOP_LOAD, + MEMOP_STORE, + MEMOP_LOAD_POSTINCR, + MEMOP_STORE_POSTINCR +}; + +static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, int32_t offset) +{ + tile_bundle_bits result; + + /* mask out the old offset */ + tile_bundle_bits mask = create_BrOff_X1(-1); + result = n & (~mask); + + /* or in the new offset */ + result |= create_BrOff_X1(offset); + + return result; +} + +static inline tile_bundle_bits move_X1(tile_bundle_bits n, int dest, int src) +{ + tile_bundle_bits result; + tile_bundle_bits op; + + result = n & (~TILE_X1_MASK); + + op = create_Opcode_X1(SPECIAL_0_OPCODE_X1) | + create_RRROpcodeExtension_X1(OR_SPECIAL_0_OPCODE_X1) | + create_Dest_X1(dest) | + create_SrcB_X1(TREG_ZERO) | + create_SrcA_X1(src) ; + + result |= op; + return result; +} + +static inline tile_bundle_bits nop_X1(tile_bundle_bits n) +{ + return move_X1(n, TREG_ZERO, TREG_ZERO); +} + +static inline tile_bundle_bits addi_X1( + tile_bundle_bits n, int dest, int src, int imm) +{ + n &= ~TILE_X1_MASK; + + n |= (create_SrcA_X1(src) | + create_Dest_X1(dest) | + create_Imm8_X1(imm) | + create_S_X1(0) | + create_Opcode_X1(IMM_0_OPCODE_X1) | + create_ImmOpcodeExtension_X1(ADDI_IMM_0_OPCODE_X1)); + + return n; +} + +static tile_bundle_bits rewrite_load_store_unaligned( + struct single_step_state *state, + tile_bundle_bits bundle, + struct pt_regs *regs, + enum mem_op mem_op, + int size, int sign_ext) +{ + unsigned char *addr; + int val_reg, addr_reg, err, val; + + /* Get address and value registers */ + if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) { + addr_reg = get_SrcA_Y2(bundle); + val_reg = get_SrcBDest_Y2(bundle); + } else if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { + addr_reg = get_SrcA_X1(bundle); + val_reg = get_Dest_X1(bundle); + } else { + addr_reg = get_SrcA_X1(bundle); + val_reg = get_SrcB_X1(bundle); + } + + /* + * If registers are not GPRs, don't try to handle it. + * + * FIXME: we could handle non-GPR loads by getting the real value + * from memory, writing it to the single step buffer, using a + * temp_reg to hold a pointer to that memory, then executing that + * instruction and resetting temp_reg. For non-GPR stores, it's a + * little trickier; we could use the single step buffer for that + * too, but we'd have to add some more state bits so that we could + * call back in here to copy that value to the real target. For + * now, we just handle the simple case. + */ + if ((val_reg >= PTREGS_NR_GPRS && + (val_reg != TREG_ZERO || + mem_op == MEMOP_LOAD || + mem_op == MEMOP_LOAD_POSTINCR)) || + addr_reg >= PTREGS_NR_GPRS) + return bundle; + + /* If it's aligned, don't handle it specially */ + addr = (void *)regs->regs[addr_reg]; + if (((unsigned long)addr % size) == 0) + return bundle; + +#ifndef __LITTLE_ENDIAN +# error We assume little-endian representation with copy_xx_user size 2 here +#endif + /* Handle unaligned load/store */ + if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { + unsigned short val_16; + switch (size) { + case 2: + err = copy_from_user(&val_16, addr, sizeof(val_16)); + val = sign_ext ? ((short)val_16) : val_16; + break; + case 4: + err = copy_from_user(&val, addr, sizeof(val)); + break; + default: + BUG(); + } + if (err == 0) { + state->update_reg = val_reg; + state->update_value = val; + state->update = 1; + } + } else { + val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg]; + err = copy_to_user(addr, &val, size); + } + + if (err) { + siginfo_t info = { + .si_signo = SIGSEGV, + .si_code = SEGV_MAPERR, + .si_addr = (void __user *)addr + }; + force_sig_info(info.si_signo, &info, current); + return (tile_bundle_bits) 0; + } + + if (unaligned_fixup == 0) { + siginfo_t info = { + .si_signo = SIGBUS, + .si_code = BUS_ADRALN, + .si_addr = (void __user *)addr + }; + force_sig_info(info.si_signo, &info, current); + return (tile_bundle_bits) 0; + } + + if (unaligned_printk || unaligned_fixup_count == 0) { + printk("Process %d/%s: PC %#lx: Fixup of" + " unaligned %s at %#lx.\n", + current->pid, current->comm, regs->pc, + (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) ? + "load" : "store", + (unsigned long)addr); + if (!unaligned_printk) { + printk("\n" +"Unaligned fixups in the kernel will slow your application considerably.\n" +"You can find them by writing \"1\" to /proc/sys/tile/unaligned_fixup/printk,\n" +"which requests the kernel show all unaligned fixups, or writing a \"0\"\n" +"to /proc/sys/tile/unaligned_fixup/enabled, in which case each unaligned\n" +"access will become a SIGBUS you can debug. No further warnings will be\n" +"shown so as to avoid additional slowdown, but you can track the number\n" +"of fixups performed via /proc/sys/tile/unaligned_fixup/count.\n" +"Use the tile-addr2line command (see \"info addr2line\") to decode PCs.\n" + "\n"); + } + } + ++unaligned_fixup_count; + + if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) { + /* Convert the Y2 instruction to a prefetch. */ + bundle &= ~(create_SrcBDest_Y2(-1) | + create_Opcode_Y2(-1)); + bundle |= (create_SrcBDest_Y2(TREG_ZERO) | + create_Opcode_Y2(LW_OPCODE_Y2)); + /* Replace the load postincr with an addi */ + } else if (mem_op == MEMOP_LOAD_POSTINCR) { + bundle = addi_X1(bundle, addr_reg, addr_reg, + get_Imm8_X1(bundle)); + /* Replace the store postincr with an addi */ + } else if (mem_op == MEMOP_STORE_POSTINCR) { + bundle = addi_X1(bundle, addr_reg, addr_reg, + get_Dest_Imm8_X1(bundle)); + } else { + /* Convert the X1 instruction to a nop. */ + bundle &= ~(create_Opcode_X1(-1) | + create_UnShOpcodeExtension_X1(-1) | + create_UnOpcodeExtension_X1(-1)); + bundle |= (create_Opcode_X1(SHUN_0_OPCODE_X1) | + create_UnShOpcodeExtension_X1( + UN_0_SHUN_0_OPCODE_X1) | + create_UnOpcodeExtension_X1( + NOP_UN_0_SHUN_0_OPCODE_X1)); + } + + return bundle; +} + +/** + * single_step_once() - entry point when single stepping has been triggered. + * @regs: The machine register state + * + * When we arrive at this routine via a trampoline, the single step + * engine copies the executing bundle to the single step buffer. + * If the instruction is a condition branch, then the target is + * reset to one past the next instruction. If the instruction + * sets the lr, then that is noted. If the instruction is a jump + * or call, then the new target pc is preserved and the current + * bundle instruction set to null. + * + * The necessary post-single-step rewriting information is stored in + * single_step_state-> We use data segment values because the + * stack will be rewound when we run the rewritten single-stepped + * instruction. + */ +void single_step_once(struct pt_regs *regs) +{ + extern tile_bundle_bits __single_step_ill_insn; + extern tile_bundle_bits __single_step_j_insn; + extern tile_bundle_bits __single_step_addli_insn; + extern tile_bundle_bits __single_step_auli_insn; + struct thread_info *info = (void *)current_thread_info(); + struct single_step_state *state = info->step_state; + int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); + tile_bundle_bits *buffer, *pc; + tile_bundle_bits bundle; + int temp_reg; + int target_reg = TREG_LR; + int err; + enum mem_op mem_op = MEMOP_NONE; + int size = 0, sign_ext = 0; /* happy compiler */ + + asm( +" .pushsection .rodata.single_step\n" +" .align 8\n" +" .globl __single_step_ill_insn\n" +"__single_step_ill_insn:\n" +" ill\n" +" .globl __single_step_addli_insn\n" +"__single_step_addli_insn:\n" +" { nop; addli r0, zero, 0 }\n" +" .globl __single_step_auli_insn\n" +"__single_step_auli_insn:\n" +" { nop; auli r0, r0, 0 }\n" +" .globl __single_step_j_insn\n" +"__single_step_j_insn:\n" +" j .\n" +" .popsection\n" + ); + + if (state == NULL) { + /* allocate a page of writable, executable memory */ + state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); + if (state == NULL) { + printk("Out of kernel memory trying to single-step\n"); + return; + } + + /* allocate a cache line of writable, executable memory */ + down_write(¤t->mm->mmap_sem); + buffer = (void *) do_mmap(0, 0, 64, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + 0); + up_write(¤t->mm->mmap_sem); + + if ((int)buffer < 0 && (int)buffer > -PAGE_SIZE) { + kfree(state); + printk("Out of kernel pages trying to single-step\n"); + return; + } + + state->buffer = buffer; + state->is_enabled = 0; + + info->step_state = state; + + /* Validate our stored instruction patterns */ + BUG_ON(get_Opcode_X1(__single_step_addli_insn) != + ADDLI_OPCODE_X1); + BUG_ON(get_Opcode_X1(__single_step_auli_insn) != + AULI_OPCODE_X1); + BUG_ON(get_SrcA_X1(__single_step_addli_insn) != TREG_ZERO); + BUG_ON(get_Dest_X1(__single_step_addli_insn) != 0); + BUG_ON(get_JOffLong_X1(__single_step_j_insn) != 0); + } + + /* + * If we are returning from a syscall, we still haven't hit the + * "ill" for the swint1 instruction. So back the PC up to be + * pointing at the swint1, but we'll actually return directly + * back to the "ill" so we come back in via SIGILL as if we + * had "executed" the swint1 without ever being in kernel space. + */ + if (regs->faultnum == INT_SWINT_1) + regs->pc -= 8; + + pc = (tile_bundle_bits *)(regs->pc); + bundle = pc[0]; + + /* We'll follow the instruction with 2 ill op bundles */ + state->orig_pc = (unsigned long) pc; + state->next_pc = (unsigned long)(pc + 1); + state->branch_next_pc = 0; + state->update = 0; + + if (!(bundle & TILE_BUNDLE_Y_ENCODING_MASK)) { + /* two wide, check for control flow */ + int opcode = get_Opcode_X1(bundle); + + switch (opcode) { + /* branches */ + case BRANCH_OPCODE_X1: + { + int32_t offset = signExtend17(get_BrOff_X1(bundle)); + + /* + * For branches, we use a rewriting trick to let the + * hardware evaluate whether the branch is taken or + * untaken. We record the target offset and then + * rewrite the branch instruction to target 1 insn + * ahead if the branch is taken. We then follow the + * rewritten branch with two bundles, each containing + * an "ill" instruction. The supervisor examines the + * pc after the single step code is executed, and if + * the pc is the first ill instruction, then the + * branch (if any) was not taken. If the pc is the + * second ill instruction, then the branch was + * taken. The new pc is computed for these cases, and + * inserted into the registers for the thread. If + * the pc is the start of the single step code, then + * an exception or interrupt was taken before the + * code started processing, and the same "original" + * pc is restored. This change, different from the + * original implementation, has the advantage of + * executing a single user instruction. + */ + state->branch_next_pc = (unsigned long)(pc + offset); + + /* rewrite branch offset to go forward one bundle */ + bundle = set_BrOff_X1(bundle, 2); + } + break; + + /* jumps */ + case JALB_OPCODE_X1: + case JALF_OPCODE_X1: + state->update = 1; + state->next_pc = + (unsigned long) (pc + get_JOffLong_X1(bundle)); + break; + + case JB_OPCODE_X1: + case JF_OPCODE_X1: + state->next_pc = + (unsigned long) (pc + get_JOffLong_X1(bundle)); + bundle = nop_X1(bundle); + break; + + case SPECIAL_0_OPCODE_X1: + switch (get_RRROpcodeExtension_X1(bundle)) { + /* jump-register */ + case JALRP_SPECIAL_0_OPCODE_X1: + case JALR_SPECIAL_0_OPCODE_X1: + state->update = 1; + state->next_pc = + regs->regs[get_SrcA_X1(bundle)]; + break; + + case JRP_SPECIAL_0_OPCODE_X1: + case JR_SPECIAL_0_OPCODE_X1: + state->next_pc = + regs->regs[get_SrcA_X1(bundle)]; + bundle = nop_X1(bundle); + break; + + case LNK_SPECIAL_0_OPCODE_X1: + state->update = 1; + target_reg = get_Dest_X1(bundle); + break; + + /* stores */ + case SH_SPECIAL_0_OPCODE_X1: + mem_op = MEMOP_STORE; + size = 2; + break; + + case SW_SPECIAL_0_OPCODE_X1: + mem_op = MEMOP_STORE; + size = 4; + break; + } + break; + + /* loads and iret */ + case SHUN_0_OPCODE_X1: + if (get_UnShOpcodeExtension_X1(bundle) == + UN_0_SHUN_0_OPCODE_X1) { + switch (get_UnOpcodeExtension_X1(bundle)) { + case LH_UN_0_SHUN_0_OPCODE_X1: + mem_op = MEMOP_LOAD; + size = 2; + sign_ext = 1; + break; + + case LH_U_UN_0_SHUN_0_OPCODE_X1: + mem_op = MEMOP_LOAD; + size = 2; + sign_ext = 0; + break; + + case LW_UN_0_SHUN_0_OPCODE_X1: + mem_op = MEMOP_LOAD; + size = 4; + break; + + case IRET_UN_0_SHUN_0_OPCODE_X1: + { + unsigned long ex0_0 = __insn_mfspr( + SPR_EX_CONTEXT_0_0); + unsigned long ex0_1 = __insn_mfspr( + SPR_EX_CONTEXT_0_1); + /* + * Special-case it if we're iret'ing + * to PL0 again. Otherwise just let + * it run and it will generate SIGILL. + */ + if (EX1_PL(ex0_1) == USER_PL) { + state->next_pc = ex0_0; + regs->ex1 = ex0_1; + bundle = nop_X1(bundle); + } + } + } + } + break; + +#if CHIP_HAS_WH64() + /* postincrement operations */ + case IMM_0_OPCODE_X1: + switch (get_ImmOpcodeExtension_X1(bundle)) { + case LWADD_IMM_0_OPCODE_X1: + mem_op = MEMOP_LOAD_POSTINCR; + size = 4; + break; + + case LHADD_IMM_0_OPCODE_X1: + mem_op = MEMOP_LOAD_POSTINCR; + size = 2; + sign_ext = 1; + break; + + case LHADD_U_IMM_0_OPCODE_X1: + mem_op = MEMOP_LOAD_POSTINCR; + size = 2; + sign_ext = 0; + break; + + case SWADD_IMM_0_OPCODE_X1: + mem_op = MEMOP_STORE_POSTINCR; + size = 4; + break; + + case SHADD_IMM_0_OPCODE_X1: + mem_op = MEMOP_STORE_POSTINCR; + size = 2; + break; + + default: + break; + } + break; +#endif /* CHIP_HAS_WH64() */ + } + + if (state->update) { + /* + * Get an available register. We start with a + * bitmask with 1's for available registers. + * We truncate to the low 32 registers since + * we are guaranteed to have set bits in the + * low 32 bits, then use ctz to pick the first. + */ + u32 mask = (u32) ~((1ULL << get_Dest_X0(bundle)) | + (1ULL << get_SrcA_X0(bundle)) | + (1ULL << get_SrcB_X0(bundle)) | + (1ULL << target_reg)); + temp_reg = __builtin_ctz(mask); + state->update_reg = temp_reg; + state->update_value = regs->regs[temp_reg]; + regs->regs[temp_reg] = (unsigned long) (pc+1); + regs->flags |= PT_FLAGS_RESTORE_REGS; + bundle = move_X1(bundle, target_reg, temp_reg); + } + } else { + int opcode = get_Opcode_Y2(bundle); + + switch (opcode) { + /* loads */ + case LH_OPCODE_Y2: + mem_op = MEMOP_LOAD; + size = 2; + sign_ext = 1; + break; + + case LH_U_OPCODE_Y2: + mem_op = MEMOP_LOAD; + size = 2; + sign_ext = 0; + break; + + case LW_OPCODE_Y2: + mem_op = MEMOP_LOAD; + size = 4; + break; + + /* stores */ + case SH_OPCODE_Y2: + mem_op = MEMOP_STORE; + size = 2; + break; + + case SW_OPCODE_Y2: + mem_op = MEMOP_STORE; + size = 4; + break; + } + } + + /* + * Check if we need to rewrite an unaligned load/store. + * Returning zero is a special value meaning we need to SIGSEGV. + */ + if (mem_op != MEMOP_NONE && unaligned_fixup >= 0) { + bundle = rewrite_load_store_unaligned(state, bundle, regs, + mem_op, size, sign_ext); + if (bundle == 0) + return; + } + + /* write the bundle to our execution area */ + buffer = state->buffer; + err = __put_user(bundle, buffer++); + + /* + * If we're really single-stepping, we take an INT_ILL after. + * If we're just handling an unaligned access, we can just + * jump directly back to where we were in user code. + */ + if (is_single_step) { + err |= __put_user(__single_step_ill_insn, buffer++); + err |= __put_user(__single_step_ill_insn, buffer++); + } else { + long delta; + + if (state->update) { + /* We have some state to update; do it inline */ + int ha16; + bundle = __single_step_addli_insn; + bundle |= create_Dest_X1(state->update_reg); + bundle |= create_Imm16_X1(state->update_value); + err |= __put_user(bundle, buffer++); + bundle = __single_step_auli_insn; + bundle |= create_Dest_X1(state->update_reg); + bundle |= create_SrcA_X1(state->update_reg); + ha16 = (state->update_value + 0x8000) >> 16; + bundle |= create_Imm16_X1(ha16); + err |= __put_user(bundle, buffer++); + state->update = 0; + } + + /* End with a jump back to the next instruction */ + delta = ((regs->pc + TILE_BUNDLE_SIZE_IN_BYTES) - + (unsigned long)buffer) >> + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES; + bundle = __single_step_j_insn; + bundle |= create_JOffLong_X1(delta); + err |= __put_user(bundle, buffer++); + } + + if (err) { + printk("Fault when writing to single-step buffer\n"); + return; + } + + /* + * Flush the buffer. + * We do a local flush only, since this is a thread-specific buffer. + */ + __flush_icache_range((unsigned long) state->buffer, + (unsigned long) buffer); + + /* Indicate enabled */ + state->is_enabled = is_single_step; + regs->pc = (unsigned long) state->buffer; + + /* Fault immediately if we are coming back from a syscall. */ + if (regs->faultnum == INT_SWINT_1) + regs->pc += 8; +} + +#endif /* !__tilegx__ */ diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c new file mode 100644 index 000000000000..782c1bfa6dfe --- /dev/null +++ b/arch/tile/kernel/smp.c @@ -0,0 +1,202 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * TILE SMP support routines. + */ + +#include +#include +#include + +HV_Topology smp_topology __write_once; + + +/* + * Top-level send_IPI*() functions to send messages to other cpus. + */ + +/* Set by smp_send_stop() to avoid recursive panics. */ +static int stopping_cpus; + +void send_IPI_single(int cpu, int tag) +{ + HV_Recipient recip = { + .y = cpu / smp_width, + .x = cpu % smp_width, + .state = HV_TO_BE_SENT + }; + int rc = hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag)); + BUG_ON(rc <= 0); +} + +void send_IPI_many(const struct cpumask *mask, int tag) +{ + HV_Recipient recip[NR_CPUS]; + int cpu, sent; + int nrecip = 0; + int my_cpu = smp_processor_id(); + for_each_cpu(cpu, mask) { + HV_Recipient *r; + BUG_ON(cpu == my_cpu); + r = &recip[nrecip++]; + r->y = cpu / smp_width; + r->x = cpu % smp_width; + r->state = HV_TO_BE_SENT; + } + sent = 0; + while (sent < nrecip) { + int rc = hv_send_message(recip, nrecip, + (HV_VirtAddr)&tag, sizeof(tag)); + if (rc <= 0) { + if (!stopping_cpus) /* avoid recursive panic */ + panic("hv_send_message returned %d", rc); + break; + } + sent += rc; + } +} + +void send_IPI_allbutself(int tag) +{ + struct cpumask mask; + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); + send_IPI_many(&mask, tag); +} + + +/* + * Provide smp_call_function_mask, but also run function locally + * if specified in the mask. + */ +void on_each_cpu_mask(const struct cpumask *mask, void (*func)(void *), + void *info, bool wait) +{ + int cpu = get_cpu(); + smp_call_function_many(mask, func, info, wait); + if (cpumask_test_cpu(cpu, mask)) { + local_irq_disable(); + func(info); + local_irq_enable(); + } + put_cpu(); +} + + +/* + * Functions related to starting/stopping cpus. + */ + +/* Handler to start the current cpu. */ +static void smp_start_cpu_interrupt(void) +{ + extern unsigned long start_cpu_function_addr; + get_irq_regs()->pc = start_cpu_function_addr; +} + +/* Handler to stop the current cpu. */ +static void smp_stop_cpu_interrupt(void) +{ + set_cpu_online(smp_processor_id(), 0); + raw_local_irq_disable_all(); + for (;;) + asm("nap"); +} + +/* This function calls the 'stop' function on all other CPUs in the system. */ +void smp_send_stop(void) +{ + stopping_cpus = 1; + send_IPI_allbutself(MSG_TAG_STOP_CPU); +} + + +/* + * Dispatch code called from hv_message_intr() for HV_MSG_TILE hv messages. + */ +void evaluate_message(int tag) +{ + switch (tag) { + case MSG_TAG_START_CPU: /* Start up a cpu */ + smp_start_cpu_interrupt(); + break; + + case MSG_TAG_STOP_CPU: /* Sent to shut down slave CPU's */ + smp_stop_cpu_interrupt(); + break; + + case MSG_TAG_CALL_FUNCTION_MANY: /* Call function on cpumask */ + generic_smp_call_function_interrupt(); + break; + + case MSG_TAG_CALL_FUNCTION_SINGLE: /* Call function on one other CPU */ + generic_smp_call_function_single_interrupt(); + break; + + default: + panic("Unknown IPI message tag %d", tag); + break; + } +} + + +/* + * flush_icache_range() code uses smp_call_function(). + */ + +struct ipi_flush { + unsigned long start; + unsigned long end; +}; + +static void ipi_flush_icache_range(void *info) +{ + struct ipi_flush *flush = (struct ipi_flush *) info; + __flush_icache_range(flush->start, flush->end); +} + +void flush_icache_range(unsigned long start, unsigned long end) +{ + struct ipi_flush flush = { start, end }; + preempt_disable(); + on_each_cpu(ipi_flush_icache_range, &flush, 1); + preempt_enable(); +} + + +/* + * The smp_send_reschedule() path does not use the hv_message_intr() + * path but instead the faster tile_dev_intr() path for interrupts. + */ + +irqreturn_t handle_reschedule_ipi(int irq, void *token) +{ + /* + * Nothing to do here; when we return from interrupt, the + * rescheduling will occur there. But do bump the interrupt + * profiler count in the meantime. + */ + __get_cpu_var(irq_stat).irq_resched_count++; + + return IRQ_HANDLED; +} + +void smp_send_reschedule(int cpu) +{ + HV_Coord coord; + + WARN_ON(cpu_is_offline(cpu)); + coord.y = cpu / smp_width; + coord.x = cpu % smp_width; + hv_trigger_ipi(coord, IRQ_RESCHEDULE); +} diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c new file mode 100644 index 000000000000..aa3aafdb4b93 --- /dev/null +++ b/arch/tile/kernel/smpboot.c @@ -0,0 +1,293 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This assembly function is provided in entry.S. + * When called, it loops on a nap instruction forever. + * FIXME: should be in a header somewhere. + */ +extern void smp_nap(void); + +/* State of each CPU. */ +DEFINE_PER_CPU(int, cpu_state) = { 0 }; + +/* The messaging code jumps to this pointer during boot-up */ +unsigned long start_cpu_function_addr; + +/* Called very early during startup to mark boot cpu as online */ +void __init smp_prepare_boot_cpu(void) +{ + int cpu = smp_processor_id(); + set_cpu_online(cpu, 1); + set_cpu_present(cpu, 1); + __get_cpu_var(cpu_state) = CPU_ONLINE; + + init_messaging(); +} + +static void start_secondary(void); + +/* + * Called at the top of init() to launch all the other CPUs. + * They run free to complete their initialization and then wait + * until they get an IPI from the boot cpu to come online. + */ +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + long rc; + int cpu, cpu_count; + int boot_cpu = smp_processor_id(); + + current_thread_info()->cpu = boot_cpu; + + /* + * Pin this task to the boot CPU while we bring up the others, + * just to make sure we don't uselessly migrate as they come up. + */ + rc = sched_setaffinity(current->pid, cpumask_of(boot_cpu)); + if (rc != 0) + printk("Couldn't set init affinity to boot cpu (%ld)\n", rc); + + /* Print information about disabled and dataplane cpus. */ + print_disabled_cpus(); + + /* + * Tell the messaging subsystem how to respond to the + * startup message. We use a level of indirection to avoid + * confusing the linker with the fact that the messaging + * subsystem is calling __init code. + */ + start_cpu_function_addr = (unsigned long) &online_secondary; + + /* Set up thread context for all new processors. */ + cpu_count = 1; + for (cpu = 0; cpu < NR_CPUS; ++cpu) { + struct task_struct *idle; + + if (cpu == boot_cpu) + continue; + + if (!cpu_possible(cpu)) { + /* + * Make this processor do nothing on boot. + * Note that we don't give the boot_pc function + * a stack, so it has to be assembly code. + */ + per_cpu(boot_sp, cpu) = 0; + per_cpu(boot_pc, cpu) = (unsigned long) smp_nap; + continue; + } + + /* Create a new idle thread to run start_secondary() */ + idle = fork_idle(cpu); + if (IS_ERR(idle)) + panic("failed fork for CPU %d", cpu); + idle->thread.pc = (unsigned long) start_secondary; + + /* Make this thread the boot thread for this processor */ + per_cpu(boot_sp, cpu) = task_ksp0(idle); + per_cpu(boot_pc, cpu) = idle->thread.pc; + + ++cpu_count; + } + BUG_ON(cpu_count > (max_cpus ? max_cpus : 1)); + + /* Fire up the other tiles, if any */ + init_cpu_present(cpu_possible_mask); + if (cpumask_weight(cpu_present_mask) > 1) { + mb(); /* make sure all data is visible to new processors */ + hv_start_all_tiles(); + } +} + +static __initdata struct cpumask init_affinity; + +static __init int reset_init_affinity(void) +{ + long rc = sched_setaffinity(current->pid, &init_affinity); + if (rc != 0) + printk(KERN_WARNING "couldn't reset init affinity (%ld)\n", + rc); + return 0; +} +late_initcall(reset_init_affinity); + +struct cpumask cpu_started __cpuinitdata; + +/* + * Activate a secondary processor. Very minimal; don't add anything + * to this path without knowing what you're doing, since SMP booting + * is pretty fragile. + */ +static void __cpuinit start_secondary(void) +{ + int cpuid = smp_processor_id(); + + /* Set our thread pointer appropriately. */ + set_my_cpu_offset(__per_cpu_offset[cpuid]); + + preempt_disable(); + + /* + * In large machines even this will slow us down, since we + * will be contending for for the printk spinlock. + */ + /* printk(KERN_DEBUG "Initializing CPU#%d\n", cpuid); */ + + /* Initialize the current asid for our first page table. */ + __get_cpu_var(current_asid) = min_asid; + + /* Set up this thread as another owner of the init_mm */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + if (current->mm) + BUG(); + enter_lazy_tlb(&init_mm, current); + + /* Enable IRQs. */ + init_per_tile_IRQs(); + + /* Allow hypervisor messages to be received */ + init_messaging(); + local_irq_enable(); + + /* Indicate that we're ready to come up. */ + /* Must not do this before we're ready to receive messages */ + if (cpumask_test_and_set_cpu(cpuid, &cpu_started)) { + printk(KERN_WARNING "CPU#%d already started!\n", cpuid); + for (;;) + local_irq_enable(); + } + + smp_nap(); +} + +void setup_mpls(void); /* from kernel/setup.c */ +void store_permanent_mappings(void); + +/* + * Bring a secondary processor online. + */ +void __cpuinit online_secondary() +{ + /* + * low-memory mappings have been cleared, flush them from + * the local TLBs too. + */ + local_flush_tlb(); + + BUG_ON(in_interrupt()); + + /* This must be done before setting cpu_online_mask */ + wmb(); + + /* + * We need to hold call_lock, so there is no inconsistency + * between the time smp_call_function() determines number of + * IPI recipients, and the time when the determination is made + * for which cpus receive the IPI. Holding this + * lock helps us to not include this cpu in a currently in progress + * smp_call_function(). + */ + ipi_call_lock(); + set_cpu_online(smp_processor_id(), 1); + ipi_call_unlock(); + __get_cpu_var(cpu_state) = CPU_ONLINE; + + /* Set up MPLs for this processor */ + setup_mpls(); + + + /* Set up tile-timer clock-event device on this cpu */ + setup_tile_timer(); + + preempt_enable(); + + store_permanent_mappings(); + + cpu_idle(); +} + +int __cpuinit __cpu_up(unsigned int cpu) +{ + /* Wait 5s total for all CPUs for them to come online */ + static int timeout; + for (; !cpumask_test_cpu(cpu, &cpu_started); timeout++) { + if (timeout >= 50000) { + printk(KERN_INFO "skipping unresponsive cpu%d\n", cpu); + local_irq_enable(); + return -EIO; + } + udelay(100); + } + + local_irq_enable(); + per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; + + /* Unleash the CPU! */ + send_IPI_single(cpu, MSG_TAG_START_CPU); + while (!cpumask_test_cpu(cpu, cpu_online_mask)) + cpu_relax(); + return 0; +} + +static void panic_start_cpu(void) +{ + panic("Received a MSG_START_CPU IPI after boot finished."); +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ + int cpu, next, rc; + + /* Reset the response to a (now illegal) MSG_START_CPU IPI. */ + start_cpu_function_addr = (unsigned long) &panic_start_cpu; + + cpumask_copy(&init_affinity, cpu_online_mask); + + /* + * Pin ourselves to a single cpu in the initial affinity set + * so that kernel mappings for the rootfs are not in the dataplane, + * if set, and to avoid unnecessary migrating during bringup. + * Use the last cpu just in case the whole chip has been + * isolated from the scheduler, to keep init away from likely + * more useful user code. This also ensures that work scheduled + * via schedule_delayed_work() in the init routines will land + * on this cpu. + */ + for (cpu = cpumask_first(&init_affinity); + (next = cpumask_next(cpu, &init_affinity)) < nr_cpu_ids; + cpu = next) + ; + rc = sched_setaffinity(current->pid, cpumask_of(cpu)); + if (rc != 0) + printk("Couldn't set init affinity to cpu %d (%d)\n", cpu, rc); +} diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c new file mode 100644 index 000000000000..382170b4b40a --- /dev/null +++ b/arch/tile/kernel/stack.c @@ -0,0 +1,485 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Is address on the specified kernel stack? */ +static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) +{ + ulong kstack_base = (ulong) kbt->task->stack; + if (kstack_base == 0) /* corrupt task pointer; just follow stack... */ + return sp >= PAGE_OFFSET && sp < (unsigned long)high_memory; + return sp >= kstack_base && sp < kstack_base + THREAD_SIZE; +} + +/* Is address in the specified kernel code? */ +static int in_kernel_text(VirtualAddress address) +{ + return (address >= MEM_SV_INTRPT && + address < MEM_SV_INTRPT + HPAGE_SIZE); +} + +/* Is address valid for reading? */ +static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) +{ + HV_PTE *l1_pgtable = kbt->pgtable; + HV_PTE *l2_pgtable; + unsigned long pfn; + HV_PTE pte; + struct page *page; + + pte = l1_pgtable[HV_L1_INDEX(address)]; + if (!hv_pte_get_present(pte)) + return 0; + pfn = hv_pte_get_pfn(pte); + if (pte_huge(pte)) { + if (!pfn_valid(pfn)) { + printk(KERN_ERR "huge page has bad pfn %#lx\n", pfn); + return 0; + } + return hv_pte_get_present(pte) && hv_pte_get_readable(pte); + } + + page = pfn_to_page(pfn); + if (PageHighMem(page)) { + printk(KERN_ERR "L2 page table not in LOWMEM (%#llx)\n", + HV_PFN_TO_CPA(pfn)); + return 0; + } + l2_pgtable = (HV_PTE *)pfn_to_kaddr(pfn); + pte = l2_pgtable[HV_L2_INDEX(address)]; + return hv_pte_get_present(pte) && hv_pte_get_readable(pte); +} + +/* Callback for backtracer; basically a glorified memcpy */ +static bool read_memory_func(void *result, VirtualAddress address, + unsigned int size, void *vkbt) +{ + int retval; + struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt; + if (in_kernel_text(address)) { + /* OK to read kernel code. */ + } else if (address >= PAGE_OFFSET) { + /* We only tolerate kernel-space reads of this task's stack */ + if (!in_kernel_stack(kbt, address)) + return 0; + } else if (kbt->pgtable == NULL) { + return 0; /* can't read user space in other tasks */ + } else if (!valid_address(kbt, address)) { + return 0; /* invalid user-space address */ + } + pagefault_disable(); + retval = __copy_from_user_inatomic(result, (const void *)address, + size); + pagefault_enable(); + return (retval == 0); +} + +/* Return a pt_regs pointer for a valid fault handler frame */ +static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) +{ +#ifndef __tilegx__ + const char *fault = NULL; /* happy compiler */ + char fault_buf[64]; + VirtualAddress sp = kbt->it.sp; + struct pt_regs *p; + + if (!in_kernel_stack(kbt, sp)) + return NULL; + if (!in_kernel_stack(kbt, sp + C_ABI_SAVE_AREA_SIZE + PTREGS_SIZE-1)) + return NULL; + p = (struct pt_regs *)(sp + C_ABI_SAVE_AREA_SIZE); + if (p->faultnum == INT_SWINT_1 || p->faultnum == INT_SWINT_1_SIGRETURN) + fault = "syscall"; + else { + if (kbt->verbose) { /* else we aren't going to use it */ + snprintf(fault_buf, sizeof(fault_buf), + "interrupt %ld", p->faultnum); + fault = fault_buf; + } + } + if (EX1_PL(p->ex1) == KERNEL_PL && + in_kernel_text(p->pc) && + in_kernel_stack(kbt, p->sp) && + p->sp >= sp) { + if (kbt->verbose) + printk(KERN_ERR " <%s while in kernel mode>\n", fault); + } else if (EX1_PL(p->ex1) == USER_PL && + p->pc < PAGE_OFFSET && + p->sp < PAGE_OFFSET) { + if (kbt->verbose) + printk(KERN_ERR " <%s while in user mode>\n", fault); + } else if (kbt->verbose) { + printk(KERN_ERR " (odd fault: pc %#lx, sp %#lx, ex1 %#lx?)\n", + p->pc, p->sp, p->ex1); + p = NULL; + } + if (!kbt->profile || (INT_MASK(p->faultnum) & QUEUED_INTERRUPTS) == 0) + return p; +#endif + return NULL; +} + +/* Is the pc pointing to a sigreturn trampoline? */ +static int is_sigreturn(VirtualAddress pc) +{ + return (pc == VDSO_BASE); +} + +/* Return a pt_regs pointer for a valid signal handler frame */ +static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) +{ + BacktraceIterator *b = &kbt->it; + + if (b->pc == VDSO_BASE) { + struct rt_sigframe *frame; + unsigned long sigframe_top = + b->sp + sizeof(struct rt_sigframe) - 1; + if (!valid_address(kbt, b->sp) || + !valid_address(kbt, sigframe_top)) { + if (kbt->verbose) + printk(" (odd signal: sp %#lx?)\n", + (unsigned long)(b->sp)); + return NULL; + } + frame = (struct rt_sigframe *)b->sp; + if (kbt->verbose) { + printk(KERN_ERR " \n", + frame->info.si_signo); + } + return &frame->uc.uc_mcontext.regs; + } + return NULL; +} + +int KBacktraceIterator_is_sigreturn(struct KBacktraceIterator *kbt) +{ + return is_sigreturn(kbt->it.pc); +} + +static int KBacktraceIterator_restart(struct KBacktraceIterator *kbt) +{ + struct pt_regs *p; + + p = valid_fault_handler(kbt); + if (p == NULL) + p = valid_sigframe(kbt); + if (p == NULL) + return 0; + backtrace_init(&kbt->it, read_memory_func, kbt, + p->pc, p->lr, p->sp, p->regs[52]); + kbt->new_context = 1; + return 1; +} + +/* Find a frame that isn't a sigreturn, if there is one. */ +static int KBacktraceIterator_next_item_inclusive( + struct KBacktraceIterator *kbt) +{ + for (;;) { + do { + if (!KBacktraceIterator_is_sigreturn(kbt)) + return 1; + } while (backtrace_next(&kbt->it)); + + if (!KBacktraceIterator_restart(kbt)) + return 0; + } +} + +/* + * If the current sp is on a page different than what we recorded + * as the top-of-kernel-stack last time we context switched, we have + * probably blown the stack, and nothing is going to work out well. + * If we can at least get out a warning, that may help the debug, + * though we probably won't be able to backtrace into the code that + * actually did the recursive damage. + */ +static void validate_stack(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + unsigned long ksp0 = get_current_ksp0(); + unsigned long ksp0_base = ksp0 - THREAD_SIZE; + unsigned long sp = stack_pointer; + + if (EX1_PL(regs->ex1) == KERNEL_PL && regs->sp >= ksp0) { + printk("WARNING: cpu %d: kernel stack page %#lx underrun!\n" + " sp %#lx (%#lx in caller), caller pc %#lx, lr %#lx\n", + cpu, ksp0_base, sp, regs->sp, regs->pc, regs->lr); + } + + else if (sp < ksp0_base + sizeof(struct thread_info)) { + printk("WARNING: cpu %d: kernel stack page %#lx overrun!\n" + " sp %#lx (%#lx in caller), caller pc %#lx, lr %#lx\n", + cpu, ksp0_base, sp, regs->sp, regs->pc, regs->lr); + } +} + +void KBacktraceIterator_init(struct KBacktraceIterator *kbt, + struct task_struct *t, struct pt_regs *regs) +{ + VirtualAddress pc, lr, sp, r52; + int is_current; + + /* + * Set up callback information. We grab the kernel stack base + * so we will allow reads of that address range, and if we're + * asking about the current process we grab the page table + * so we can check user accesses before trying to read them. + * We flush the TLB to avoid any weird skew issues. + */ + is_current = (t == NULL); + kbt->is_current = is_current; + if (is_current) + t = validate_current(); + kbt->task = t; + kbt->pgtable = NULL; + kbt->verbose = 0; /* override in caller if desired */ + kbt->profile = 0; /* override in caller if desired */ + kbt->end = 0; + kbt->new_context = 0; + if (is_current) { + HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; + if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) { + /* + * Not just an optimization: this also allows + * this to work at all before va/pa mappings + * are set up. + */ + kbt->pgtable = swapper_pg_dir; + } else { + struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa)); + if (!PageHighMem(page)) + kbt->pgtable = __va(pgdir_pa); + else + printk(KERN_ERR "page table not in LOWMEM" + " (%#llx)\n", pgdir_pa); + } + local_flush_tlb_all(); + validate_stack(regs); + } + + if (regs == NULL) { + extern const void *get_switch_to_pc(void); + if (is_current || t->state == TASK_RUNNING) { + /* Can't do this; we need registers */ + kbt->end = 1; + return; + } + pc = (ulong) get_switch_to_pc(); + lr = t->thread.pc; + sp = t->thread.ksp; + r52 = 0; + } else { + pc = regs->pc; + lr = regs->lr; + sp = regs->sp; + r52 = regs->regs[52]; + } + + backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); + kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); +} +EXPORT_SYMBOL(KBacktraceIterator_init); + +int KBacktraceIterator_end(struct KBacktraceIterator *kbt) +{ + return kbt->end; +} +EXPORT_SYMBOL(KBacktraceIterator_end); + +void KBacktraceIterator_next(struct KBacktraceIterator *kbt) +{ + kbt->new_context = 0; + if (!backtrace_next(&kbt->it) && + !KBacktraceIterator_restart(kbt)) { + kbt->end = 1; + return; + } + + kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); +} +EXPORT_SYMBOL(KBacktraceIterator_next); + +/* + * This method wraps the backtracer's more generic support. + * It is only invoked from the architecture-specific code; show_stack() + * and dump_stack() (in entry.S) are architecture-independent entry points. + */ +void tile_show_stack(struct KBacktraceIterator *kbt, int headers) +{ + int i; + + if (headers) { + /* + * Add a blank line since if we are called from panic(), + * then bust_spinlocks() spit out a space in front of us + * and it will mess up our KERN_ERR. + */ + printk("\n"); + printk(KERN_ERR "Starting stack dump of tid %d, pid %d (%s)" + " on cpu %d at cycle %lld\n", + kbt->task->pid, kbt->task->tgid, kbt->task->comm, + smp_processor_id(), get_cycles()); + } +#ifdef __tilegx__ + if (kbt->is_current) { + __insn_mtspr(SPR_SIM_CONTROL, + SIM_DUMP_SPR_ARG(SIM_DUMP_BACKTRACE)); + } +#endif + kbt->verbose = 1; + i = 0; + for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) { + char *modname; + const char *name; + unsigned long address = kbt->it.pc; + unsigned long offset, size; + char namebuf[KSYM_NAME_LEN+100]; + + if (address >= PAGE_OFFSET) + name = kallsyms_lookup(address, &size, &offset, + &modname, namebuf); + else + name = NULL; + + if (!name) + namebuf[0] = '\0'; + else { + size_t namelen = strlen(namebuf); + size_t remaining = (sizeof(namebuf) - 1) - namelen; + char *p = namebuf + namelen; + int rc = snprintf(p, remaining, "+%#lx/%#lx ", + offset, size); + if (modname && rc < remaining) + snprintf(p + rc, remaining - rc, + "[%s] ", modname); + namebuf[sizeof(namebuf)-1] = '\0'; + } + + printk(KERN_ERR " frame %d: 0x%lx %s(sp 0x%lx)\n", + i++, address, namebuf, (unsigned long)(kbt->it.sp)); + + if (i >= 100) { + printk(KERN_ERR "Stack dump truncated" + " (%d frames)\n", i); + break; + } + } + if (headers) + printk(KERN_ERR "Stack dump complete\n"); +} +EXPORT_SYMBOL(tile_show_stack); + + +/* This is called from show_regs() and _dump_stack() */ +void dump_stack_regs(struct pt_regs *regs) +{ + struct KBacktraceIterator kbt; + KBacktraceIterator_init(&kbt, NULL, regs); + tile_show_stack(&kbt, 1); +} +EXPORT_SYMBOL(dump_stack_regs); + +static struct pt_regs *regs_to_pt_regs(struct pt_regs *regs, + ulong pc, ulong lr, ulong sp, ulong r52) +{ + memset(regs, 0, sizeof(struct pt_regs)); + regs->pc = pc; + regs->lr = lr; + regs->sp = sp; + regs->regs[52] = r52; + return regs; +} + +/* This is called from dump_stack() and just converts to pt_regs */ +void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) +{ + struct pt_regs regs; + dump_stack_regs(regs_to_pt_regs(®s, pc, lr, sp, r52)); +} + +/* This is called from KBacktraceIterator_init_current() */ +void _KBacktraceIterator_init_current(struct KBacktraceIterator *kbt, ulong pc, + ulong lr, ulong sp, ulong r52) +{ + struct pt_regs regs; + KBacktraceIterator_init(kbt, NULL, + regs_to_pt_regs(®s, pc, lr, sp, r52)); +} + +/* This is called only from kernel/sched.c, with esp == NULL */ +void show_stack(struct task_struct *task, unsigned long *esp) +{ + struct KBacktraceIterator kbt; + if (task == NULL || task == current) + KBacktraceIterator_init_current(&kbt); + else + KBacktraceIterator_init(&kbt, task, NULL); + tile_show_stack(&kbt, 0); +} + +#ifdef CONFIG_STACKTRACE + +/* Support generic Linux stack API too */ + +void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace) +{ + struct KBacktraceIterator kbt; + int skip = trace->skip; + int i = 0; + + if (task == NULL || task == current) + KBacktraceIterator_init_current(&kbt); + else + KBacktraceIterator_init(&kbt, task, NULL); + for (; !KBacktraceIterator_end(&kbt); KBacktraceIterator_next(&kbt)) { + if (skip) { + --skip; + continue; + } + if (i >= trace->max_entries || kbt.it.pc < PAGE_OFFSET) + break; + trace->entries[i++] = kbt.it.pc; + } + trace->nr_entries = i; +} +EXPORT_SYMBOL(save_stack_trace_tsk); + +void save_stack_trace(struct stack_trace *trace) +{ + save_stack_trace_tsk(NULL, trace); +} + +#endif + +/* In entry.S */ +EXPORT_SYMBOL(KBacktraceIterator_init_current); diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c new file mode 100644 index 000000000000..a3d982b212b4 --- /dev/null +++ b/arch/tile/kernel/sys.c @@ -0,0 +1,122 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/TILE + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +SYSCALL_DEFINE0(flush_cache) +{ + homecache_evict(cpumask_of(smp_processor_id())); + return 0; +} + +/* + * Syscalls that pass 64-bit values on 32-bit systems normally + * pass them as (low,high) word packed into the immediately adjacent + * registers. If the low word naturally falls on an even register, + * our ABI makes it work correctly; if not, we adjust it here. + * Handling it here means we don't have to fix uclibc AND glibc AND + * any other standard libcs we want to support. + */ + +#if !defined(__tilegx__) || defined(CONFIG_COMPAT) + +ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count) +{ + return sys_readahead(fd, ((loff_t)offset_hi << 32) | offset_lo, count); +} + +long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi, + u32 len, int advice) +{ + return sys_fadvise64_64(fd, ((loff_t)offset_hi << 32) | offset_lo, + len, advice); +} + +int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, + u32 len_lo, u32 len_hi, int advice) +{ + return sys_fadvise64_64(fd, ((loff_t)offset_hi << 32) | offset_lo, + ((loff_t)len_hi << 32) | len_lo, advice); +} + +#endif /* 32-bit syscall wrappers */ + +/* + * This API uses a 4KB-page-count offset into the file descriptor. + * It is likely not the right API to use on a 64-bit platform. + */ +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, off_4k) +{ +#define PAGE_ADJUST (PAGE_SHIFT - 12) + if (off_4k & ((1 << PAGE_ADJUST) - 1)) + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, + off_4k >> PAGE_ADJUST); +} + +/* + * This API uses a byte offset into the file descriptor. + * It is likely not the right API to use on a 32-bit platform. + */ +SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, offset) +{ + if (offset & ((1 << PAGE_SHIFT) - 1)) + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, + offset >> PAGE_SHIFT); +} + + +/* Provide the actual syscall number to call mapping. */ +#undef __SYSCALL +#define __SYSCALL(nr, call) [nr] = (call), + +#ifndef __tilegx__ +/* See comments at the top of the file. */ +#define sys_fadvise64 sys32_fadvise64 +#define sys_fadvise64_64 sys32_fadvise64_64 +#define sys_readahead sys32_readahead +#define sys_sync_file_range sys_sync_file_range2 +#endif + +void *sys_call_table[__NR_syscalls] = { + [0 ... __NR_syscalls-1] = sys_ni_syscall, +#include +}; diff --git a/arch/tile/kernel/tile-desc_32.c b/arch/tile/kernel/tile-desc_32.c new file mode 100644 index 000000000000..3b78369f86b0 --- /dev/null +++ b/arch/tile/kernel/tile-desc_32.c @@ -0,0 +1,13826 @@ +/* Define to include "bfd.h" and get actual BFD relocations below. */ +/* #define WANT_BFD_RELOCS */ + +#ifdef WANT_BFD_RELOCS +#include "bfd.h" +#define MAYBE_BFD_RELOC(X) (X) +#else +#define MAYBE_BFD_RELOC(X) -1 +#endif + +/* Special registers. */ +#define TREG_LR 55 +#define TREG_SN 56 +#define TREG_ZERO 63 + +/* FIXME: Rename this. */ +#include + + +const struct tile_opcode tile_opcodes[394] = +{ + { "bpt", TILE_OPC_BPT, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbffffff80000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b3cae00000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "info", TILE_OPC_INFO, 0xf /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0 }, + { 1 }, + { 2 }, + { 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00fffULL, + 0xfff807ff80000000ULL, + 0x8000000078000fffULL, + 0xf80007ff80000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000050100fffULL, + 0x302007ff80000000ULL, + 0x8000000050000fffULL, + 0xc00007ff80000000ULL, + -1ULL + } + }, + { "infol", TILE_OPC_INFOL, 0x3 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 4 }, + { 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000fffULL, + 0xf80007ff80000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000030000fffULL, + 0x200007ff80000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "j", TILE_OPC_J, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 6 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf000000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x5000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jal", TILE_OPC_JAL, 0x2 /* pipes */, 1 /* num_operands */, + TREG_LR, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 6 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf000000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x6000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "move", TILE_OPC_MOVE, 0xf /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 9, 10 }, + { 11, 12 }, + { 13, 14 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0xfffff80000000000ULL, + 0x80000000780ff000ULL, + 0xf807f80000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000cff000ULL, + 0x0833f80000000000ULL, + 0x80000000180bf000ULL, + 0x9805f80000000000ULL, + -1ULL + } + }, + { "move.sn", TILE_OPC_MOVE_SN, 0x3 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008cff000ULL, + 0x0c33f80000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "movei", TILE_OPC_MOVEI, 0xf /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 0 }, + { 9, 1 }, + { 11, 2 }, + { 13, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00fc0ULL, + 0xfff807e000000000ULL, + 0x8000000078000fc0ULL, + 0xf80007e000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040800fc0ULL, + 0x305807e000000000ULL, + 0x8000000058000fc0ULL, + 0xc80007e000000000ULL, + -1ULL + } + }, + { "movei.sn", TILE_OPC_MOVEI_SN, 0x3 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 0 }, + { 9, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00fc0ULL, + 0xfff807e000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048800fc0ULL, + 0x345807e000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "moveli", TILE_OPC_MOVELI, 0x3 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 4 }, + { 9, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000fc0ULL, + 0xf80007e000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000020000fc0ULL, + 0x180007e000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "moveli.sn", TILE_OPC_MOVELI_SN, 0x3 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 4 }, + { 9, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000fc0ULL, + 0xf80007e000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000010000fc0ULL, + 0x100007e000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "movelis", TILE_OPC_MOVELIS, 0x3 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 4 }, + { 9, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000fc0ULL, + 0xf80007e000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000010000fc0ULL, + 0x100007e000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "prefetch", TILE_OPC_PREFETCH, 0x12 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff81f80000000ULL, + 0ULL, + 0ULL, + 0x8700000003f00000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b501f80000000ULL, + -1ULL, + -1ULL, + 0x8000000003f00000ULL + } + }, + { "add", TILE_OPC_ADD, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000000c0000ULL, + 0x0806000000000000ULL, + 0x8000000008000000ULL, + 0x8800000000000000ULL, + -1ULL + } + }, + { "add.sn", TILE_OPC_ADD_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000080c0000ULL, + 0x0c06000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addb", TILE_OPC_ADDB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000040000ULL, + 0x0802000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addb.sn", TILE_OPC_ADDB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008040000ULL, + 0x0c02000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addbs_u", TILE_OPC_ADDBS_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001880000ULL, + 0x0888000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addbs_u.sn", TILE_OPC_ADDBS_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009880000ULL, + 0x0c88000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addh", TILE_OPC_ADDH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000080000ULL, + 0x0804000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addh.sn", TILE_OPC_ADDH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008080000ULL, + 0x0c04000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addhs", TILE_OPC_ADDHS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000018c0000ULL, + 0x088a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addhs.sn", TILE_OPC_ADDHS_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000098c0000ULL, + 0x0c8a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addi", TILE_OPC_ADDI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040300000ULL, + 0x3018000000000000ULL, + 0x8000000048000000ULL, + 0xb800000000000000ULL, + -1ULL + } + }, + { "addi.sn", TILE_OPC_ADDI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048300000ULL, + 0x3418000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addib", TILE_OPC_ADDIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040100000ULL, + 0x3008000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addib.sn", TILE_OPC_ADDIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048100000ULL, + 0x3408000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addih", TILE_OPC_ADDIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040200000ULL, + 0x3010000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addih.sn", TILE_OPC_ADDIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048200000ULL, + 0x3410000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addli", TILE_OPC_ADDLI, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 4 }, + { 9, 10, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000000ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000020000000ULL, + 0x1800000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addli.sn", TILE_OPC_ADDLI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 4 }, + { 9, 10, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000000ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000010000000ULL, + 0x1000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "addlis", TILE_OPC_ADDLIS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 4 }, + { 9, 10, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000000ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000010000000ULL, + 0x1000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adds", TILE_OPC_ADDS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001800000ULL, + 0x0884000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adds.sn", TILE_OPC_ADDS_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009800000ULL, + 0x0c84000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adiffb_u", TILE_OPC_ADIFFB_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000100000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adiffb_u.sn", TILE_OPC_ADIFFB_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008100000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adiffh", TILE_OPC_ADIFFH, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000140000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "adiffh.sn", TILE_OPC_ADIFFH_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008140000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "and", TILE_OPC_AND, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000180000ULL, + 0x0808000000000000ULL, + 0x8000000018000000ULL, + 0x9800000000000000ULL, + -1ULL + } + }, + { "and.sn", TILE_OPC_AND_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008180000ULL, + 0x0c08000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "andi", TILE_OPC_ANDI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000050100000ULL, + 0x3020000000000000ULL, + 0x8000000050000000ULL, + 0xc000000000000000ULL, + -1ULL + } + }, + { "andi.sn", TILE_OPC_ANDI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000058100000ULL, + 0x3420000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "auli", TILE_OPC_AULI, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 4 }, + { 9, 10, 5 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000000ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000030000000ULL, + 0x2000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "avgb_u", TILE_OPC_AVGB_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000001c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "avgb_u.sn", TILE_OPC_AVGB_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000081c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "avgh", TILE_OPC_AVGH, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000200000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "avgh.sn", TILE_OPC_AVGH_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008200000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbns", TILE_OPC_BBNS, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000700000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbns.sn", TILE_OPC_BBNS_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000700000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbnst", TILE_OPC_BBNST, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000780000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbnst.sn", TILE_OPC_BBNST_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000780000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbs", TILE_OPC_BBS, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000600000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbs.sn", TILE_OPC_BBS_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000600000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbst", TILE_OPC_BBST, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000680000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bbst.sn", TILE_OPC_BBST_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000680000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgez", TILE_OPC_BGEZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000300000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgez.sn", TILE_OPC_BGEZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000300000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgezt", TILE_OPC_BGEZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000380000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgezt.sn", TILE_OPC_BGEZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000380000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgz", TILE_OPC_BGZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000200000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgz.sn", TILE_OPC_BGZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000200000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgzt", TILE_OPC_BGZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000280000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bgzt.sn", TILE_OPC_BGZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000280000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bitx", TILE_OPC_BITX, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 11, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070161000ULL, + -1ULL, + 0x80000000680a1000ULL, + -1ULL, + -1ULL + } + }, + { "bitx.sn", TILE_OPC_BITX_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078161000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blez", TILE_OPC_BLEZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000500000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blez.sn", TILE_OPC_BLEZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000500000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blezt", TILE_OPC_BLEZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000580000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blezt.sn", TILE_OPC_BLEZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000580000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blz", TILE_OPC_BLZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000400000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blz.sn", TILE_OPC_BLZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000400000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blzt", TILE_OPC_BLZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000480000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "blzt.sn", TILE_OPC_BLZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000480000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bnz", TILE_OPC_BNZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000100000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bnz.sn", TILE_OPC_BNZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000100000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bnzt", TILE_OPC_BNZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000180000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bnzt.sn", TILE_OPC_BNZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000180000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bytex", TILE_OPC_BYTEX, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 11, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070162000ULL, + -1ULL, + 0x80000000680a2000ULL, + -1ULL, + -1ULL + } + }, + { "bytex.sn", TILE_OPC_BYTEX_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078162000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bz", TILE_OPC_BZ, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bz.sn", TILE_OPC_BZ_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bzt", TILE_OPC_BZT, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2800000080000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "bzt.sn", TILE_OPC_BZT_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 20 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfc00000780000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x2c00000080000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "clz", TILE_OPC_CLZ, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 11, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070163000ULL, + -1ULL, + 0x80000000680a3000ULL, + -1ULL, + -1ULL + } + }, + { "clz.sn", TILE_OPC_CLZ_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078163000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "crc32_32", TILE_OPC_CRC32_32, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000240000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "crc32_32.sn", TILE_OPC_CRC32_32_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008240000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "crc32_8", TILE_OPC_CRC32_8, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000280000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "crc32_8.sn", TILE_OPC_CRC32_8_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008280000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "ctz", TILE_OPC_CTZ, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 11, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070164000ULL, + -1ULL, + 0x80000000680a4000ULL, + -1ULL, + -1ULL + } + }, + { "ctz.sn", TILE_OPC_CTZ_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078164000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "drain", TILE_OPC_DRAIN, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b080000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "dtlbpr", TILE_OPC_DTLBPR, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b100000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "dword_align", TILE_OPC_DWORD_ALIGN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000017c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "dword_align.sn", TILE_OPC_DWORD_ALIGN_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000097c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "finv", TILE_OPC_FINV, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b180000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "flush", TILE_OPC_FLUSH, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b200000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "fnop", TILE_OPC_FNOP, 0xf /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { }, + { }, + { }, + { }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000077fff000ULL, + 0xfbfff80000000000ULL, + 0x80000000780ff000ULL, + 0xf807f80000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070165000ULL, + 0x400b280000000000ULL, + 0x80000000680a5000ULL, + 0xd805080000000000ULL, + -1ULL + } + }, + { "icoh", TILE_OPC_ICOH, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b300000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "ill", TILE_OPC_ILL, 0xa /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0xf807f80000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b380000000000ULL, + -1ULL, + 0xd805100000000000ULL, + -1ULL + } + }, + { "inthb", TILE_OPC_INTHB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000002c0000ULL, + 0x080a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "inthb.sn", TILE_OPC_INTHB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000082c0000ULL, + 0x0c0a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "inthh", TILE_OPC_INTHH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000300000ULL, + 0x080c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "inthh.sn", TILE_OPC_INTHH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008300000ULL, + 0x0c0c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "intlb", TILE_OPC_INTLB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000340000ULL, + 0x080e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "intlb.sn", TILE_OPC_INTLB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008340000ULL, + 0x0c0e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "intlh", TILE_OPC_INTLH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000380000ULL, + 0x0810000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "intlh.sn", TILE_OPC_INTLH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008380000ULL, + 0x0c10000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "inv", TILE_OPC_INV, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b400000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "iret", TILE_OPC_IRET, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b480000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jalb", TILE_OPC_JALB, 0x2 /* pipes */, 1 /* num_operands */, + TREG_LR, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 22 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x6800000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jalf", TILE_OPC_JALF, 0x2 /* pipes */, 1 /* num_operands */, + TREG_LR, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 22 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x6000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jalr", TILE_OPC_JALR, 0x2 /* pipes */, 1 /* num_operands */, + TREG_LR, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0814000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jalrp", TILE_OPC_JALRP, 0x2 /* pipes */, 1 /* num_operands */, + TREG_LR, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0812000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jb", TILE_OPC_JB, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 22 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x5800000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jf", TILE_OPC_JF, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 22 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x5000000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jr", TILE_OPC_JR, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0818000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "jrp", TILE_OPC_JRP, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0816000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lb", TILE_OPC_LB, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 23, 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b500000000000ULL, + -1ULL, + -1ULL, + 0x8000000000000000ULL + } + }, + { "lb.sn", TILE_OPC_LB_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440b500000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lb_u", TILE_OPC_LB_U, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 23, 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b580000000000ULL, + -1ULL, + -1ULL, + 0x8100000000000000ULL + } + }, + { "lb_u.sn", TILE_OPC_LB_U_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440b580000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lbadd", TILE_OPC_LBADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30b0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lbadd.sn", TILE_OPC_LBADD_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34b0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lbadd_u", TILE_OPC_LBADD_U, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30b8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lbadd_u.sn", TILE_OPC_LBADD_U_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34b8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lh", TILE_OPC_LH, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 23, 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b600000000000ULL, + -1ULL, + -1ULL, + 0x8200000000000000ULL + } + }, + { "lh.sn", TILE_OPC_LH_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440b600000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lh_u", TILE_OPC_LH_U, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 23, 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b680000000000ULL, + -1ULL, + -1ULL, + 0x8300000000000000ULL + } + }, + { "lh_u.sn", TILE_OPC_LH_U_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440b680000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lhadd", TILE_OPC_LHADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30c0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lhadd.sn", TILE_OPC_LHADD_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34c0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lhadd_u", TILE_OPC_LHADD_U, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30c8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lhadd_u.sn", TILE_OPC_LHADD_U_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34c8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lnk", TILE_OPC_LNK, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x081a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lnk.sn", TILE_OPC_LNK_SN, 0x2 /* pipes */, 1 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0c1a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lw", TILE_OPC_LW, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 23, 15 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b700000000000ULL, + -1ULL, + -1ULL, + 0x8400000000000000ULL + } + }, + { "lw.sn", TILE_OPC_LW_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440b700000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lw_na", TILE_OPC_LW_NA, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400bc00000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lw_na.sn", TILE_OPC_LW_NA_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440bc00000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lwadd", TILE_OPC_LWADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30d0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lwadd.sn", TILE_OPC_LWADD_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34d0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lwadd_na", TILE_OPC_LWADD_NA, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30d8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "lwadd_na.sn", TILE_OPC_LWADD_NA_SN, 0x2 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 24, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x34d8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxb_u", TILE_OPC_MAXB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000003c0000ULL, + 0x081c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxb_u.sn", TILE_OPC_MAXB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000083c0000ULL, + 0x0c1c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxh", TILE_OPC_MAXH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000400000ULL, + 0x081e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxh.sn", TILE_OPC_MAXH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008400000ULL, + 0x0c1e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxib_u", TILE_OPC_MAXIB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040400000ULL, + 0x3028000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxib_u.sn", TILE_OPC_MAXIB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048400000ULL, + 0x3428000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxih", TILE_OPC_MAXIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040500000ULL, + 0x3030000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "maxih.sn", TILE_OPC_MAXIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048500000ULL, + 0x3430000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mf", TILE_OPC_MF, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b780000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mfspr", TILE_OPC_MFSPR, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 25 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbf8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x3038000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minb_u", TILE_OPC_MINB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000440000ULL, + 0x0820000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minb_u.sn", TILE_OPC_MINB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008440000ULL, + 0x0c20000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minh", TILE_OPC_MINH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000480000ULL, + 0x0822000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minh.sn", TILE_OPC_MINH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008480000ULL, + 0x0c22000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minib_u", TILE_OPC_MINIB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040600000ULL, + 0x3040000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minib_u.sn", TILE_OPC_MINIB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048600000ULL, + 0x3440000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minih", TILE_OPC_MINIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040700000ULL, + 0x3048000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "minih.sn", TILE_OPC_MINIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048700000ULL, + 0x3448000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mm", TILE_OPC_MM, 0x3 /* pipes */, 5 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16, 26, 27 }, + { 9, 10, 17, 28, 29 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000070000000ULL, + 0xf800000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000060000000ULL, + 0x3800000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mnz", TILE_OPC_MNZ, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000540000ULL, + 0x0828000000000000ULL, + 0x8000000010000000ULL, + 0x9002000000000000ULL, + -1ULL + } + }, + { "mnz.sn", TILE_OPC_MNZ_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008540000ULL, + 0x0c28000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mnzb", TILE_OPC_MNZB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000004c0000ULL, + 0x0824000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mnzb.sn", TILE_OPC_MNZB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000084c0000ULL, + 0x0c24000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mnzh", TILE_OPC_MNZH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000500000ULL, + 0x0826000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mnzh.sn", TILE_OPC_MNZH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008500000ULL, + 0x0c26000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mtspr", TILE_OPC_MTSPR, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 30, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbf8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x3050000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_ss", TILE_OPC_MULHH_SS, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 11, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000680000ULL, + -1ULL, + 0x8000000038000000ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_ss.sn", TILE_OPC_MULHH_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008680000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_su", TILE_OPC_MULHH_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000006c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_su.sn", TILE_OPC_MULHH_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000086c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_uu", TILE_OPC_MULHH_UU, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 11, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000700000ULL, + -1ULL, + 0x8000000038040000ULL, + -1ULL, + -1ULL + } + }, + { "mulhh_uu.sn", TILE_OPC_MULHH_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008700000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_ss", TILE_OPC_MULHHA_SS, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000580000ULL, + -1ULL, + 0x8000000040000000ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_ss.sn", TILE_OPC_MULHHA_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008580000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_su", TILE_OPC_MULHHA_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000005c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_su.sn", TILE_OPC_MULHHA_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000085c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_uu", TILE_OPC_MULHHA_UU, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000600000ULL, + -1ULL, + 0x8000000040040000ULL, + -1ULL, + -1ULL + } + }, + { "mulhha_uu.sn", TILE_OPC_MULHHA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008600000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhhsa_uu", TILE_OPC_MULHHSA_UU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000640000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhhsa_uu.sn", TILE_OPC_MULHHSA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008640000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_ss", TILE_OPC_MULHL_SS, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000880000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_ss.sn", TILE_OPC_MULHL_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008880000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_su", TILE_OPC_MULHL_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000008c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_su.sn", TILE_OPC_MULHL_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000088c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_us", TILE_OPC_MULHL_US, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000900000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_us.sn", TILE_OPC_MULHL_US_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008900000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_uu", TILE_OPC_MULHL_UU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000940000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhl_uu.sn", TILE_OPC_MULHL_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008940000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_ss", TILE_OPC_MULHLA_SS, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000740000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_ss.sn", TILE_OPC_MULHLA_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008740000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_su", TILE_OPC_MULHLA_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000780000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_su.sn", TILE_OPC_MULHLA_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008780000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_us", TILE_OPC_MULHLA_US, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000007c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_us.sn", TILE_OPC_MULHLA_US_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000087c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_uu", TILE_OPC_MULHLA_UU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000800000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhla_uu.sn", TILE_OPC_MULHLA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008800000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulhlsa_uu", TILE_OPC_MULHLSA_UU, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000840000ULL, + -1ULL, + 0x8000000030000000ULL, + -1ULL, + -1ULL + } + }, + { "mulhlsa_uu.sn", TILE_OPC_MULHLSA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008840000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulll_ss", TILE_OPC_MULLL_SS, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 11, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000a80000ULL, + -1ULL, + 0x8000000038080000ULL, + -1ULL, + -1ULL + } + }, + { "mulll_ss.sn", TILE_OPC_MULLL_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008a80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulll_su", TILE_OPC_MULLL_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000ac0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulll_su.sn", TILE_OPC_MULLL_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008ac0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulll_uu", TILE_OPC_MULLL_UU, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 11, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000b00000ULL, + -1ULL, + 0x80000000380c0000ULL, + -1ULL, + -1ULL + } + }, + { "mulll_uu.sn", TILE_OPC_MULLL_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008b00000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mullla_ss", TILE_OPC_MULLLA_SS, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000980000ULL, + -1ULL, + 0x8000000040080000ULL, + -1ULL, + -1ULL + } + }, + { "mullla_ss.sn", TILE_OPC_MULLLA_SS_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008980000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mullla_su", TILE_OPC_MULLLA_SU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000009c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mullla_su.sn", TILE_OPC_MULLLA_SU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000089c0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mullla_uu", TILE_OPC_MULLLA_UU, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000a00000ULL, + -1ULL, + 0x80000000400c0000ULL, + -1ULL, + -1ULL + } + }, + { "mullla_uu.sn", TILE_OPC_MULLLA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008a00000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulllsa_uu", TILE_OPC_MULLLSA_UU, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000a40000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mulllsa_uu.sn", TILE_OPC_MULLLSA_UU_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008a40000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mvnz", TILE_OPC_MVNZ, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000b40000ULL, + -1ULL, + 0x8000000010040000ULL, + -1ULL, + -1ULL + } + }, + { "mvnz.sn", TILE_OPC_MVNZ_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008b40000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mvz", TILE_OPC_MVZ, 0x5 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 31, 12, 18 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0x80000000780c0000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000b80000ULL, + -1ULL, + 0x8000000010080000ULL, + -1ULL, + -1ULL + } + }, + { "mvz.sn", TILE_OPC_MVZ_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008b80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mz", TILE_OPC_MZ, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000c40000ULL, + 0x082e000000000000ULL, + 0x80000000100c0000ULL, + 0x9004000000000000ULL, + -1ULL + } + }, + { "mz.sn", TILE_OPC_MZ_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008c40000ULL, + 0x0c2e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mzb", TILE_OPC_MZB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000bc0000ULL, + 0x082a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mzb.sn", TILE_OPC_MZB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008bc0000ULL, + 0x0c2a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mzh", TILE_OPC_MZH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000c00000ULL, + 0x082c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "mzh.sn", TILE_OPC_MZH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008c00000ULL, + 0x0c2c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "nap", TILE_OPC_NAP, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b800000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "nop", TILE_OPC_NOP, 0xf /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { }, + { }, + { }, + { }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x8000000077fff000ULL, + 0xfbfff80000000000ULL, + 0x80000000780ff000ULL, + 0xf807f80000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070166000ULL, + 0x400b880000000000ULL, + 0x80000000680a6000ULL, + 0xd805180000000000ULL, + -1ULL + } + }, + { "nor", TILE_OPC_NOR, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000c80000ULL, + 0x0830000000000000ULL, + 0x8000000018040000ULL, + 0x9802000000000000ULL, + -1ULL + } + }, + { "nor.sn", TILE_OPC_NOR_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008c80000ULL, + 0x0c30000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "or", TILE_OPC_OR, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000cc0000ULL, + 0x0832000000000000ULL, + 0x8000000018080000ULL, + 0x9804000000000000ULL, + -1ULL + } + }, + { "or.sn", TILE_OPC_OR_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008cc0000ULL, + 0x0c32000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "ori", TILE_OPC_ORI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040800000ULL, + 0x3058000000000000ULL, + 0x8000000058000000ULL, + 0xc800000000000000ULL, + -1ULL + } + }, + { "ori.sn", TILE_OPC_ORI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048800000ULL, + 0x3458000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packbs_u", TILE_OPC_PACKBS_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000019c0000ULL, + 0x0892000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packbs_u.sn", TILE_OPC_PACKBS_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000099c0000ULL, + 0x0c92000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packhb", TILE_OPC_PACKHB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000d00000ULL, + 0x0834000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packhb.sn", TILE_OPC_PACKHB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008d00000ULL, + 0x0c34000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packhs", TILE_OPC_PACKHS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001980000ULL, + 0x0890000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packhs.sn", TILE_OPC_PACKHS_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009980000ULL, + 0x0c90000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packlb", TILE_OPC_PACKLB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000d40000ULL, + 0x0836000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "packlb.sn", TILE_OPC_PACKLB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008d40000ULL, + 0x0c36000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "pcnt", TILE_OPC_PCNT, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 11, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070167000ULL, + -1ULL, + 0x80000000680a7000ULL, + -1ULL, + -1ULL + } + }, + { "pcnt.sn", TILE_OPC_PCNT_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078167000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "rl", TILE_OPC_RL, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000d80000ULL, + 0x0838000000000000ULL, + 0x8000000020000000ULL, + 0xa000000000000000ULL, + -1ULL + } + }, + { "rl.sn", TILE_OPC_RL_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008d80000ULL, + 0x0c38000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "rli", TILE_OPC_RLI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 11, 12, 34 }, + { 13, 14, 35 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0x80000000780e0000ULL, + 0xf807000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070020000ULL, + 0x4001000000000000ULL, + 0x8000000068020000ULL, + 0xd801000000000000ULL, + -1ULL + } + }, + { "rli.sn", TILE_OPC_RLI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078020000ULL, + 0x4401000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "s1a", TILE_OPC_S1A, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000dc0000ULL, + 0x083a000000000000ULL, + 0x8000000008040000ULL, + 0x8802000000000000ULL, + -1ULL + } + }, + { "s1a.sn", TILE_OPC_S1A_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008dc0000ULL, + 0x0c3a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "s2a", TILE_OPC_S2A, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000e00000ULL, + 0x083c000000000000ULL, + 0x8000000008080000ULL, + 0x8804000000000000ULL, + -1ULL + } + }, + { "s2a.sn", TILE_OPC_S2A_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008e00000ULL, + 0x0c3c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "s3a", TILE_OPC_S3A, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000e40000ULL, + 0x083e000000000000ULL, + 0x8000000030040000ULL, + 0xb002000000000000ULL, + -1ULL + } + }, + { "s3a.sn", TILE_OPC_S3A_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008e40000ULL, + 0x0c3e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadab_u", TILE_OPC_SADAB_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000e80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadab_u.sn", TILE_OPC_SADAB_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008e80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadah", TILE_OPC_SADAH, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000ec0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadah.sn", TILE_OPC_SADAH_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008ec0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadah_u", TILE_OPC_SADAH_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000f00000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadah_u.sn", TILE_OPC_SADAH_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008f00000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadb_u", TILE_OPC_SADB_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000f40000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadb_u.sn", TILE_OPC_SADB_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008f40000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadh", TILE_OPC_SADH, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000f80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadh.sn", TILE_OPC_SADH_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008f80000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadh_u", TILE_OPC_SADH_U, 0x1 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000000fc0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sadh_u.sn", TILE_OPC_SADH_U_SN, 0x1 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000008fc0000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sb", TILE_OPC_SB, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 17 }, + { 0, }, + { 0, }, + { 15, 36 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0840000000000000ULL, + -1ULL, + -1ULL, + 0x8500000000000000ULL + } + }, + { "sbadd", TILE_OPC_SBADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 24, 17, 37 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbf8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30e0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seq", TILE_OPC_SEQ, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001080000ULL, + 0x0846000000000000ULL, + 0x8000000030080000ULL, + 0xb004000000000000ULL, + -1ULL + } + }, + { "seq.sn", TILE_OPC_SEQ_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009080000ULL, + 0x0c46000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqb", TILE_OPC_SEQB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001000000ULL, + 0x0842000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqb.sn", TILE_OPC_SEQB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009000000ULL, + 0x0c42000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqh", TILE_OPC_SEQH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001040000ULL, + 0x0844000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqh.sn", TILE_OPC_SEQH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009040000ULL, + 0x0c44000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqi", TILE_OPC_SEQI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040b00000ULL, + 0x3070000000000000ULL, + 0x8000000060000000ULL, + 0xd000000000000000ULL, + -1ULL + } + }, + { "seqi.sn", TILE_OPC_SEQI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048b00000ULL, + 0x3470000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqib", TILE_OPC_SEQIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040900000ULL, + 0x3060000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqib.sn", TILE_OPC_SEQIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048900000ULL, + 0x3460000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqih", TILE_OPC_SEQIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040a00000ULL, + 0x3068000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "seqih.sn", TILE_OPC_SEQIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048a00000ULL, + 0x3468000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sh", TILE_OPC_SH, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 17 }, + { 0, }, + { 0, }, + { 15, 36 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0854000000000000ULL, + -1ULL, + -1ULL, + 0x8600000000000000ULL + } + }, + { "shadd", TILE_OPC_SHADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 24, 17, 37 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbf8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30e8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shl", TILE_OPC_SHL, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001140000ULL, + 0x084c000000000000ULL, + 0x8000000020040000ULL, + 0xa002000000000000ULL, + -1ULL + } + }, + { "shl.sn", TILE_OPC_SHL_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009140000ULL, + 0x0c4c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlb", TILE_OPC_SHLB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000010c0000ULL, + 0x0848000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlb.sn", TILE_OPC_SHLB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000090c0000ULL, + 0x0c48000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlh", TILE_OPC_SHLH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001100000ULL, + 0x084a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlh.sn", TILE_OPC_SHLH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009100000ULL, + 0x0c4a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shli", TILE_OPC_SHLI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 11, 12, 34 }, + { 13, 14, 35 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0x80000000780e0000ULL, + 0xf807000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070080000ULL, + 0x4004000000000000ULL, + 0x8000000068040000ULL, + 0xd802000000000000ULL, + -1ULL + } + }, + { "shli.sn", TILE_OPC_SHLI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078080000ULL, + 0x4404000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlib", TILE_OPC_SHLIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070040000ULL, + 0x4002000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlib.sn", TILE_OPC_SHLIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078040000ULL, + 0x4402000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlih", TILE_OPC_SHLIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070060000ULL, + 0x4003000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shlih.sn", TILE_OPC_SHLIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078060000ULL, + 0x4403000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shr", TILE_OPC_SHR, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001200000ULL, + 0x0852000000000000ULL, + 0x8000000020080000ULL, + 0xa004000000000000ULL, + -1ULL + } + }, + { "shr.sn", TILE_OPC_SHR_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009200000ULL, + 0x0c52000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrb", TILE_OPC_SHRB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001180000ULL, + 0x084e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrb.sn", TILE_OPC_SHRB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009180000ULL, + 0x0c4e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrh", TILE_OPC_SHRH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000011c0000ULL, + 0x0850000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrh.sn", TILE_OPC_SHRH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000091c0000ULL, + 0x0c50000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shri", TILE_OPC_SHRI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 11, 12, 34 }, + { 13, 14, 35 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0x80000000780e0000ULL, + 0xf807000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000700e0000ULL, + 0x4007000000000000ULL, + 0x8000000068060000ULL, + 0xd803000000000000ULL, + -1ULL + } + }, + { "shri.sn", TILE_OPC_SHRI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000780e0000ULL, + 0x4407000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrib", TILE_OPC_SHRIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000700a0000ULL, + 0x4005000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrib.sn", TILE_OPC_SHRIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000780a0000ULL, + 0x4405000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrih", TILE_OPC_SHRIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000700c0000ULL, + 0x4006000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "shrih.sn", TILE_OPC_SHRIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000780c0000ULL, + 0x4406000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slt", TILE_OPC_SLT, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000014c0000ULL, + 0x086a000000000000ULL, + 0x8000000028080000ULL, + 0xa804000000000000ULL, + -1ULL + } + }, + { "slt.sn", TILE_OPC_SLT_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000094c0000ULL, + 0x0c6a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slt_u", TILE_OPC_SLT_U, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001500000ULL, + 0x086c000000000000ULL, + 0x80000000280c0000ULL, + 0xa806000000000000ULL, + -1ULL + } + }, + { "slt_u.sn", TILE_OPC_SLT_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009500000ULL, + 0x0c6c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltb", TILE_OPC_SLTB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001240000ULL, + 0x0856000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltb.sn", TILE_OPC_SLTB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009240000ULL, + 0x0c56000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltb_u", TILE_OPC_SLTB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001280000ULL, + 0x0858000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltb_u.sn", TILE_OPC_SLTB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009280000ULL, + 0x0c58000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slte", TILE_OPC_SLTE, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000013c0000ULL, + 0x0862000000000000ULL, + 0x8000000028000000ULL, + 0xa800000000000000ULL, + -1ULL + } + }, + { "slte.sn", TILE_OPC_SLTE_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000093c0000ULL, + 0x0c62000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slte_u", TILE_OPC_SLTE_U, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001400000ULL, + 0x0864000000000000ULL, + 0x8000000028040000ULL, + 0xa802000000000000ULL, + -1ULL + } + }, + { "slte_u.sn", TILE_OPC_SLTE_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009400000ULL, + 0x0c64000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteb", TILE_OPC_SLTEB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000012c0000ULL, + 0x085a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteb.sn", TILE_OPC_SLTEB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000092c0000ULL, + 0x0c5a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteb_u", TILE_OPC_SLTEB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001300000ULL, + 0x085c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteb_u.sn", TILE_OPC_SLTEB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009300000ULL, + 0x0c5c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteh", TILE_OPC_SLTEH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001340000ULL, + 0x085e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteh.sn", TILE_OPC_SLTEH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009340000ULL, + 0x0c5e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteh_u", TILE_OPC_SLTEH_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001380000ULL, + 0x0860000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slteh_u.sn", TILE_OPC_SLTEH_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009380000ULL, + 0x0c60000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slth", TILE_OPC_SLTH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001440000ULL, + 0x0866000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slth.sn", TILE_OPC_SLTH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009440000ULL, + 0x0c66000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slth_u", TILE_OPC_SLTH_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001480000ULL, + 0x0868000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slth_u.sn", TILE_OPC_SLTH_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009480000ULL, + 0x0c68000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slti", TILE_OPC_SLTI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000041000000ULL, + 0x3098000000000000ULL, + 0x8000000070000000ULL, + 0xe000000000000000ULL, + -1ULL + } + }, + { "slti.sn", TILE_OPC_SLTI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000049000000ULL, + 0x3498000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "slti_u", TILE_OPC_SLTI_U, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 11, 12, 2 }, + { 13, 14, 3 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0x8000000078000000ULL, + 0xf800000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000041100000ULL, + 0x30a0000000000000ULL, + 0x8000000078000000ULL, + 0xe800000000000000ULL, + -1ULL + } + }, + { "slti_u.sn", TILE_OPC_SLTI_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000049100000ULL, + 0x34a0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltib", TILE_OPC_SLTIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040c00000ULL, + 0x3078000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltib.sn", TILE_OPC_SLTIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048c00000ULL, + 0x3478000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltib_u", TILE_OPC_SLTIB_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040d00000ULL, + 0x3080000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltib_u.sn", TILE_OPC_SLTIB_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048d00000ULL, + 0x3480000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltih", TILE_OPC_SLTIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040e00000ULL, + 0x3088000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltih.sn", TILE_OPC_SLTIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048e00000ULL, + 0x3488000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltih_u", TILE_OPC_SLTIH_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000040f00000ULL, + 0x3090000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sltih_u.sn", TILE_OPC_SLTIH_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000048f00000ULL, + 0x3490000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sne", TILE_OPC_SNE, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000015c0000ULL, + 0x0872000000000000ULL, + 0x80000000300c0000ULL, + 0xb006000000000000ULL, + -1ULL + } + }, + { "sne.sn", TILE_OPC_SNE_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000095c0000ULL, + 0x0c72000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sneb", TILE_OPC_SNEB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001540000ULL, + 0x086e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sneb.sn", TILE_OPC_SNEB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009540000ULL, + 0x0c6e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sneh", TILE_OPC_SNEH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001580000ULL, + 0x0870000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sneh.sn", TILE_OPC_SNEH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009580000ULL, + 0x0c70000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sra", TILE_OPC_SRA, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001680000ULL, + 0x0878000000000000ULL, + 0x80000000200c0000ULL, + 0xa006000000000000ULL, + -1ULL + } + }, + { "sra.sn", TILE_OPC_SRA_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009680000ULL, + 0x0c78000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "srab", TILE_OPC_SRAB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001600000ULL, + 0x0874000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "srab.sn", TILE_OPC_SRAB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009600000ULL, + 0x0c74000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "srah", TILE_OPC_SRAH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001640000ULL, + 0x0876000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "srah.sn", TILE_OPC_SRAH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009640000ULL, + 0x0c76000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "srai", TILE_OPC_SRAI, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 11, 12, 34 }, + { 13, 14, 35 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0x80000000780e0000ULL, + 0xf807000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070140000ULL, + 0x400a000000000000ULL, + 0x8000000068080000ULL, + 0xd804000000000000ULL, + -1ULL + } + }, + { "srai.sn", TILE_OPC_SRAI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078140000ULL, + 0x440a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sraib", TILE_OPC_SRAIB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070100000ULL, + 0x4008000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sraib.sn", TILE_OPC_SRAIB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078100000ULL, + 0x4408000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sraih", TILE_OPC_SRAIH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070120000ULL, + 0x4009000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sraih.sn", TILE_OPC_SRAIH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 32 }, + { 9, 10, 33 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffe0000ULL, + 0xffff000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078120000ULL, + 0x4409000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sub", TILE_OPC_SUB, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001740000ULL, + 0x087e000000000000ULL, + 0x80000000080c0000ULL, + 0x8806000000000000ULL, + -1ULL + } + }, + { "sub.sn", TILE_OPC_SUB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009740000ULL, + 0x0c7e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subb", TILE_OPC_SUBB, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000016c0000ULL, + 0x087a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subb.sn", TILE_OPC_SUBB_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x00000000096c0000ULL, + 0x0c7a000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subbs_u", TILE_OPC_SUBBS_U, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001900000ULL, + 0x088c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subbs_u.sn", TILE_OPC_SUBBS_U_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009900000ULL, + 0x0c8c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subh", TILE_OPC_SUBH, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001700000ULL, + 0x087c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subh.sn", TILE_OPC_SUBH_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009700000ULL, + 0x0c7c000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subhs", TILE_OPC_SUBHS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001940000ULL, + 0x088e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subhs.sn", TILE_OPC_SUBHS_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009940000ULL, + 0x0c8e000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subs", TILE_OPC_SUBS, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001840000ULL, + 0x0886000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "subs.sn", TILE_OPC_SUBS_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009840000ULL, + 0x0c86000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "sw", TILE_OPC_SW, 0x12 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10, 17 }, + { 0, }, + { 0, }, + { 15, 36 } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfe000000000000ULL, + 0ULL, + 0ULL, + 0x8700000000000000ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x0880000000000000ULL, + -1ULL, + -1ULL, + 0x8700000000000000ULL + } + }, + { "swadd", TILE_OPC_SWADD, 0x2 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 24, 17, 37 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbf8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x30f0000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "swint0", TILE_OPC_SWINT0, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b900000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "swint1", TILE_OPC_SWINT1, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400b980000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "swint2", TILE_OPC_SWINT2, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400ba00000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "swint3", TILE_OPC_SWINT3, 0x2 /* pipes */, 0 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 0, /* can_bundle */ + { + /* operands */ + { 0, }, + { }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400ba80000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb0", TILE_OPC_TBLIDXB0, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 31, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070168000ULL, + -1ULL, + 0x80000000680a8000ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb0.sn", TILE_OPC_TBLIDXB0_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078168000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb1", TILE_OPC_TBLIDXB1, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 31, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000070169000ULL, + -1ULL, + 0x80000000680a9000ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb1.sn", TILE_OPC_TBLIDXB1_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000078169000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb2", TILE_OPC_TBLIDXB2, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 31, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x000000007016a000ULL, + -1ULL, + 0x80000000680aa000ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb2.sn", TILE_OPC_TBLIDXB2_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x000000007816a000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb3", TILE_OPC_TBLIDXB3, 0x5 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 31, 12 }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0x80000000780ff000ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x000000007016b000ULL, + -1ULL, + 0x80000000680ab000ULL, + -1ULL, + -1ULL + } + }, + { "tblidxb3.sn", TILE_OPC_TBLIDXB3_SN, 0x1 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 21, 8 }, + { 0, }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffff000ULL, + 0ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x000000007816b000ULL, + -1ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tns", TILE_OPC_TNS, 0x2 /* pipes */, 2 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400bb00000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "tns.sn", TILE_OPC_TNS_SN, 0x2 /* pipes */, 2 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 9, 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfffff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x440bb00000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "wh64", TILE_OPC_WH64, 0x2 /* pipes */, 1 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 0, }, + { 10 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0ULL, + 0xfbfff80000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + -1ULL, + 0x400bb80000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "xor", TILE_OPC_XOR, 0xf /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 11, 12, 18 }, + { 13, 14, 19 }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0x80000000780c0000ULL, + 0xf806000000000000ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000001780000ULL, + 0x0882000000000000ULL, + 0x80000000180c0000ULL, + 0x9806000000000000ULL, + -1ULL + } + }, + { "xor.sn", TILE_OPC_XOR_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 16 }, + { 9, 10, 17 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ffc0000ULL, + 0xfffe000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000009780000ULL, + 0x0c82000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "xori", TILE_OPC_XORI, 0x3 /* pipes */, 3 /* num_operands */, + TREG_ZERO, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000050200000ULL, + 0x30a8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { "xori.sn", TILE_OPC_XORI_SN, 0x3 /* pipes */, 3 /* num_operands */, + TREG_SN, /* implicitly_written_register */ + 1, /* can_bundle */ + { + /* operands */ + { 7, 8, 0 }, + { 9, 10, 1 }, + { 0, }, + { 0, }, + { 0, } + }, + { + /* fixed_bit_masks */ + 0x800000007ff00000ULL, + 0xfff8000000000000ULL, + 0ULL, + 0ULL, + 0ULL + }, + { + /* fixed_bit_values */ + 0x0000000058200000ULL, + 0x34a8000000000000ULL, + -1ULL, + -1ULL, + -1ULL + } + }, + { 0, TILE_OPC_NONE, 0, 0, 0, TREG_ZERO, { { 0, } }, { 0, }, { 0, } + } +}; +#define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6)) +#define CHILD(array_index) (TILE_OPC_NONE + (array_index)) + +static const unsigned short decode_X0_fsm[1153] = +{ + BITFIELD(22, 9) /* index 0 */, + CHILD(513), CHILD(530), CHILD(547), CHILD(564), CHILD(596), CHILD(613), + CHILD(630), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, CHILD(663), CHILD(680), CHILD(697), CHILD(714), CHILD(746), + CHILD(763), CHILD(780), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), + CHILD(813), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), + CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(873), CHILD(878), CHILD(883), + CHILD(903), CHILD(908), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(913), + CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, CHILD(953), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(988), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(993), + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, CHILD(1076), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(18, 4) /* index 513 */, + TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD, + TILE_OPC_ADIFFB_U, TILE_OPC_ADIFFH, TILE_OPC_AND, TILE_OPC_AVGB_U, + TILE_OPC_AVGH, TILE_OPC_CRC32_32, TILE_OPC_CRC32_8, TILE_OPC_INTHB, + TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH, TILE_OPC_MAXB_U, + BITFIELD(18, 4) /* index 530 */, + TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH, TILE_OPC_MNZB, TILE_OPC_MNZH, + TILE_OPC_MNZ, TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_SU, TILE_OPC_MULHHA_UU, + TILE_OPC_MULHHSA_UU, TILE_OPC_MULHH_SS, TILE_OPC_MULHH_SU, + TILE_OPC_MULHH_UU, TILE_OPC_MULHLA_SS, TILE_OPC_MULHLA_SU, + TILE_OPC_MULHLA_US, + BITFIELD(18, 4) /* index 547 */, + TILE_OPC_MULHLA_UU, TILE_OPC_MULHLSA_UU, TILE_OPC_MULHL_SS, + TILE_OPC_MULHL_SU, TILE_OPC_MULHL_US, TILE_OPC_MULHL_UU, TILE_OPC_MULLLA_SS, + TILE_OPC_MULLLA_SU, TILE_OPC_MULLLA_UU, TILE_OPC_MULLLSA_UU, + TILE_OPC_MULLL_SS, TILE_OPC_MULLL_SU, TILE_OPC_MULLL_UU, TILE_OPC_MVNZ, + TILE_OPC_MVZ, TILE_OPC_MZB, + BITFIELD(18, 4) /* index 564 */, + TILE_OPC_MZH, TILE_OPC_MZ, TILE_OPC_NOR, CHILD(581), TILE_OPC_PACKHB, + TILE_OPC_PACKLB, TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A, + TILE_OPC_SADAB_U, TILE_OPC_SADAH, TILE_OPC_SADAH_U, TILE_OPC_SADB_U, + TILE_OPC_SADH, TILE_OPC_SADH_U, + BITFIELD(12, 2) /* index 581 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(586), + BITFIELD(14, 2) /* index 586 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(591), + BITFIELD(16, 2) /* index 591 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE, + BITFIELD(18, 4) /* index 596 */, + TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB, TILE_OPC_SHLH, + TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR, TILE_OPC_SLTB, + TILE_OPC_SLTB_U, TILE_OPC_SLTEB, TILE_OPC_SLTEB_U, TILE_OPC_SLTEH, + TILE_OPC_SLTEH_U, TILE_OPC_SLTE, + BITFIELD(18, 4) /* index 613 */, + TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT, + TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB, + TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB, + TILE_OPC_XOR, TILE_OPC_DWORD_ALIGN, + BITFIELD(18, 3) /* index 630 */, + CHILD(639), CHILD(642), CHILD(645), CHILD(648), CHILD(651), CHILD(654), + CHILD(657), CHILD(660), + BITFIELD(21, 1) /* index 639 */, + TILE_OPC_ADDS, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 642 */, + TILE_OPC_SUBS, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 645 */, + TILE_OPC_ADDBS_U, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 648 */, + TILE_OPC_ADDHS, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 651 */, + TILE_OPC_SUBBS_U, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 654 */, + TILE_OPC_SUBHS, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 657 */, + TILE_OPC_PACKHS, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 660 */, + TILE_OPC_PACKBS_U, TILE_OPC_NONE, + BITFIELD(18, 4) /* index 663 */, + TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN, + TILE_OPC_ADIFFB_U_SN, TILE_OPC_ADIFFH_SN, TILE_OPC_AND_SN, + TILE_OPC_AVGB_U_SN, TILE_OPC_AVGH_SN, TILE_OPC_CRC32_32_SN, + TILE_OPC_CRC32_8_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN, + TILE_OPC_INTLB_SN, TILE_OPC_INTLH_SN, TILE_OPC_MAXB_U_SN, + BITFIELD(18, 4) /* index 680 */, + TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN, TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN, + TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN, TILE_OPC_MULHHA_SS_SN, + TILE_OPC_MULHHA_SU_SN, TILE_OPC_MULHHA_UU_SN, TILE_OPC_MULHHSA_UU_SN, + TILE_OPC_MULHH_SS_SN, TILE_OPC_MULHH_SU_SN, TILE_OPC_MULHH_UU_SN, + TILE_OPC_MULHLA_SS_SN, TILE_OPC_MULHLA_SU_SN, TILE_OPC_MULHLA_US_SN, + BITFIELD(18, 4) /* index 697 */, + TILE_OPC_MULHLA_UU_SN, TILE_OPC_MULHLSA_UU_SN, TILE_OPC_MULHL_SS_SN, + TILE_OPC_MULHL_SU_SN, TILE_OPC_MULHL_US_SN, TILE_OPC_MULHL_UU_SN, + TILE_OPC_MULLLA_SS_SN, TILE_OPC_MULLLA_SU_SN, TILE_OPC_MULLLA_UU_SN, + TILE_OPC_MULLLSA_UU_SN, TILE_OPC_MULLL_SS_SN, TILE_OPC_MULLL_SU_SN, + TILE_OPC_MULLL_UU_SN, TILE_OPC_MVNZ_SN, TILE_OPC_MVZ_SN, TILE_OPC_MZB_SN, + BITFIELD(18, 4) /* index 714 */, + TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN, CHILD(731), + TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN, TILE_OPC_S1A_SN, + TILE_OPC_S2A_SN, TILE_OPC_S3A_SN, TILE_OPC_SADAB_U_SN, TILE_OPC_SADAH_SN, + TILE_OPC_SADAH_U_SN, TILE_OPC_SADB_U_SN, TILE_OPC_SADH_SN, + TILE_OPC_SADH_U_SN, + BITFIELD(12, 2) /* index 731 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(736), + BITFIELD(14, 2) /* index 736 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(741), + BITFIELD(16, 2) /* index 741 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN, + BITFIELD(18, 4) /* index 746 */, + TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN, TILE_OPC_SHLB_SN, + TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN, TILE_OPC_SHRH_SN, + TILE_OPC_SHR_SN, TILE_OPC_SLTB_SN, TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN, + TILE_OPC_SLTEB_U_SN, TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN, + TILE_OPC_SLTE_SN, + BITFIELD(18, 4) /* index 763 */, + TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN, + TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN, + TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN, + TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN, TILE_OPC_XOR_SN, TILE_OPC_DWORD_ALIGN_SN, + BITFIELD(18, 3) /* index 780 */, + CHILD(789), CHILD(792), CHILD(795), CHILD(798), CHILD(801), CHILD(804), + CHILD(807), CHILD(810), + BITFIELD(21, 1) /* index 789 */, + TILE_OPC_ADDS_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 792 */, + TILE_OPC_SUBS_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 795 */, + TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 798 */, + TILE_OPC_ADDHS_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 801 */, + TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 804 */, + TILE_OPC_SUBHS_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 807 */, + TILE_OPC_PACKHS_SN, TILE_OPC_NONE, + BITFIELD(21, 1) /* index 810 */, + TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE, + BITFIELD(6, 2) /* index 813 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(818), + BITFIELD(8, 2) /* index 818 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(823), + BITFIELD(10, 2) /* index 823 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN, + BITFIELD(6, 2) /* index 828 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(833), + BITFIELD(8, 2) /* index 833 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(838), + BITFIELD(10, 2) /* index 838 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI, + BITFIELD(0, 2) /* index 843 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(848), + BITFIELD(2, 2) /* index 848 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(853), + BITFIELD(4, 2) /* index 853 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(858), + BITFIELD(6, 2) /* index 858 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(863), + BITFIELD(8, 2) /* index 863 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(868), + BITFIELD(10, 2) /* index 868 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL, + BITFIELD(20, 2) /* index 873 */, + TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI, + BITFIELD(20, 2) /* index 878 */, + TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MINIB_U, TILE_OPC_MINIH, + BITFIELD(20, 2) /* index 883 */, + CHILD(888), TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI, + BITFIELD(6, 2) /* index 888 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(893), + BITFIELD(8, 2) /* index 893 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(898), + BITFIELD(10, 2) /* index 898 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI, + BITFIELD(20, 2) /* index 903 */, + TILE_OPC_SLTIB, TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U, + BITFIELD(20, 2) /* index 908 */, + TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(20, 2) /* index 913 */, + TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN, + BITFIELD(20, 2) /* index 918 */, + TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MINIB_U_SN, + TILE_OPC_MINIH_SN, + BITFIELD(20, 2) /* index 923 */, + CHILD(928), TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN, + BITFIELD(6, 2) /* index 928 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(933), + BITFIELD(8, 2) /* index 933 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(938), + BITFIELD(10, 2) /* index 938 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN, + BITFIELD(20, 2) /* index 943 */, + TILE_OPC_SLTIB_SN, TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN, + TILE_OPC_SLTIH_U_SN, + BITFIELD(20, 2) /* index 948 */, + TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(20, 2) /* index 953 */, + TILE_OPC_NONE, CHILD(958), TILE_OPC_XORI, TILE_OPC_NONE, + BITFIELD(0, 2) /* index 958 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(963), + BITFIELD(2, 2) /* index 963 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(968), + BITFIELD(4, 2) /* index 968 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(973), + BITFIELD(6, 2) /* index 973 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(978), + BITFIELD(8, 2) /* index 978 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(983), + BITFIELD(10, 2) /* index 983 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO, + BITFIELD(20, 2) /* index 988 */, + TILE_OPC_NONE, TILE_OPC_ANDI_SN, TILE_OPC_XORI_SN, TILE_OPC_NONE, + BITFIELD(17, 5) /* index 993 */, + TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLIB, TILE_OPC_SHLIH, TILE_OPC_SHLI, + TILE_OPC_SHRIB, TILE_OPC_SHRIH, TILE_OPC_SHRI, TILE_OPC_SRAIB, + TILE_OPC_SRAIH, TILE_OPC_SRAI, CHILD(1026), TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(12, 4) /* index 1026 */, + TILE_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052), + CHILD(1055), CHILD(1058), CHILD(1061), CHILD(1064), CHILD(1067), + CHILD(1070), CHILD(1073), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1043 */, + TILE_OPC_BITX, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1046 */, + TILE_OPC_BYTEX, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1049 */, + TILE_OPC_CLZ, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1052 */, + TILE_OPC_CTZ, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1055 */, + TILE_OPC_FNOP, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1058 */, + TILE_OPC_NOP, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1061 */, + TILE_OPC_PCNT, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1064 */, + TILE_OPC_TBLIDXB0, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1067 */, + TILE_OPC_TBLIDXB1, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1070 */, + TILE_OPC_TBLIDXB2, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1073 */, + TILE_OPC_TBLIDXB3, TILE_OPC_NONE, + BITFIELD(17, 5) /* index 1076 */, + TILE_OPC_NONE, TILE_OPC_RLI_SN, TILE_OPC_SHLIB_SN, TILE_OPC_SHLIH_SN, + TILE_OPC_SHLI_SN, TILE_OPC_SHRIB_SN, TILE_OPC_SHRIH_SN, TILE_OPC_SHRI_SN, + TILE_OPC_SRAIB_SN, TILE_OPC_SRAIH_SN, TILE_OPC_SRAI_SN, CHILD(1109), + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(12, 4) /* index 1109 */, + TILE_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135), + CHILD(1055), CHILD(1058), CHILD(1138), CHILD(1141), CHILD(1144), + CHILD(1147), CHILD(1150), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1126 */, + TILE_OPC_BITX_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1129 */, + TILE_OPC_BYTEX_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1132 */, + TILE_OPC_CLZ_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1135 */, + TILE_OPC_CTZ_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1138 */, + TILE_OPC_PCNT_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1141 */, + TILE_OPC_TBLIDXB0_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1144 */, + TILE_OPC_TBLIDXB1_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1147 */, + TILE_OPC_TBLIDXB2_SN, TILE_OPC_NONE, + BITFIELD(16, 1) /* index 1150 */, + TILE_OPC_TBLIDXB3_SN, TILE_OPC_NONE, +}; + +static const unsigned short decode_X1_fsm[1509] = +{ + BITFIELD(54, 9) /* index 0 */, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, CHILD(513), CHILD(561), CHILD(594), + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(641), CHILD(689), + CHILD(722), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(766), + CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), + CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), + CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), + CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), + CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), + CHILD(766), CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), + CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), + CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), + CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), + CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), CHILD(781), + CHILD(781), CHILD(781), CHILD(781), CHILD(796), CHILD(796), CHILD(796), + CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), + CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), + CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), + CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), + CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(796), CHILD(826), + CHILD(826), CHILD(826), CHILD(826), CHILD(826), CHILD(826), CHILD(826), + CHILD(826), CHILD(826), CHILD(826), CHILD(826), CHILD(826), CHILD(826), + CHILD(826), CHILD(826), CHILD(826), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), + CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, CHILD(941), CHILD(950), CHILD(974), CHILD(983), + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, + TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(992), + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + CHILD(1303), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, + TILE_OPC_J, TILE_OPC_J, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, + TILE_OPC_JAL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(49, 5) /* index 513 */, + TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD, TILE_OPC_AND, + TILE_OPC_INTHB, TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH, + TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR, TILE_OPC_LNK, + TILE_OPC_MAXB_U, TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH, + TILE_OPC_MNZB, TILE_OPC_MNZH, TILE_OPC_MNZ, TILE_OPC_MZB, TILE_OPC_MZH, + TILE_OPC_MZ, TILE_OPC_NOR, CHILD(546), TILE_OPC_PACKHB, TILE_OPC_PACKLB, + TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A, + BITFIELD(43, 2) /* index 546 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(551), + BITFIELD(45, 2) /* index 551 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(556), + BITFIELD(47, 2) /* index 556 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE, + BITFIELD(49, 5) /* index 561 */, + TILE_OPC_SB, TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB, + TILE_OPC_SHLH, TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR, + TILE_OPC_SH, TILE_OPC_SLTB, TILE_OPC_SLTB_U, TILE_OPC_SLTEB, + TILE_OPC_SLTEB_U, TILE_OPC_SLTEH, TILE_OPC_SLTEH_U, TILE_OPC_SLTE, + TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT, + TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB, + TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB, + BITFIELD(49, 4) /* index 594 */, + CHILD(611), CHILD(614), CHILD(617), CHILD(620), CHILD(623), CHILD(626), + CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 611 */, + TILE_OPC_SW, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 614 */, + TILE_OPC_XOR, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 617 */, + TILE_OPC_ADDS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 620 */, + TILE_OPC_SUBS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 623 */, + TILE_OPC_ADDBS_U, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 626 */, + TILE_OPC_ADDHS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 629 */, + TILE_OPC_SUBBS_U, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 632 */, + TILE_OPC_SUBHS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 635 */, + TILE_OPC_PACKHS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 638 */, + TILE_OPC_PACKBS_U, TILE_OPC_NONE, + BITFIELD(49, 5) /* index 641 */, + TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN, + TILE_OPC_AND_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN, TILE_OPC_INTLB_SN, + TILE_OPC_INTLH_SN, TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR, + TILE_OPC_LNK_SN, TILE_OPC_MAXB_U_SN, TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN, + TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN, TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN, + TILE_OPC_MZB_SN, TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN, + CHILD(674), TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN, + TILE_OPC_S1A_SN, TILE_OPC_S2A_SN, TILE_OPC_S3A_SN, + BITFIELD(43, 2) /* index 674 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(679), + BITFIELD(45, 2) /* index 679 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(684), + BITFIELD(47, 2) /* index 684 */, + TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN, + BITFIELD(49, 5) /* index 689 */, + TILE_OPC_SB, TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN, + TILE_OPC_SHLB_SN, TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN, + TILE_OPC_SHRH_SN, TILE_OPC_SHR_SN, TILE_OPC_SH, TILE_OPC_SLTB_SN, + TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN, TILE_OPC_SLTEB_U_SN, + TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN, TILE_OPC_SLTE_SN, + TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN, + TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN, + TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN, + TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN, + BITFIELD(49, 4) /* index 722 */, + CHILD(611), CHILD(739), CHILD(742), CHILD(745), CHILD(748), CHILD(751), + CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 739 */, + TILE_OPC_XOR_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 742 */, + TILE_OPC_ADDS_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 745 */, + TILE_OPC_SUBS_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 748 */, + TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 751 */, + TILE_OPC_ADDHS_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 754 */, + TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 757 */, + TILE_OPC_SUBHS_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 760 */, + TILE_OPC_PACKHS_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 763 */, + TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE, + BITFIELD(37, 2) /* index 766 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(771), + BITFIELD(39, 2) /* index 771 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(776), + BITFIELD(41, 2) /* index 776 */, + TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN, + BITFIELD(37, 2) /* index 781 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(786), + BITFIELD(39, 2) /* index 786 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(791), + BITFIELD(41, 2) /* index 791 */, + TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI, + BITFIELD(31, 2) /* index 796 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(801), + BITFIELD(33, 2) /* index 801 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(806), + BITFIELD(35, 2) /* index 806 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(811), + BITFIELD(37, 2) /* index 811 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(816), + BITFIELD(39, 2) /* index 816 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(821), + BITFIELD(41, 2) /* index 821 */, + TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL, + BITFIELD(31, 4) /* index 826 */, + TILE_OPC_BZ, TILE_OPC_BZT, TILE_OPC_BNZ, TILE_OPC_BNZT, TILE_OPC_BGZ, + TILE_OPC_BGZT, TILE_OPC_BGEZ, TILE_OPC_BGEZT, TILE_OPC_BLZ, TILE_OPC_BLZT, + TILE_OPC_BLEZ, TILE_OPC_BLEZT, TILE_OPC_BBS, TILE_OPC_BBST, TILE_OPC_BBNS, + TILE_OPC_BBNST, + BITFIELD(31, 4) /* index 843 */, + TILE_OPC_BZ_SN, TILE_OPC_BZT_SN, TILE_OPC_BNZ_SN, TILE_OPC_BNZT_SN, + TILE_OPC_BGZ_SN, TILE_OPC_BGZT_SN, TILE_OPC_BGEZ_SN, TILE_OPC_BGEZT_SN, + TILE_OPC_BLZ_SN, TILE_OPC_BLZT_SN, TILE_OPC_BLEZ_SN, TILE_OPC_BLEZT_SN, + TILE_OPC_BBS_SN, TILE_OPC_BBST_SN, TILE_OPC_BBNS_SN, TILE_OPC_BBNST_SN, + BITFIELD(51, 3) /* index 860 */, + TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI, CHILD(869), + TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MFSPR, + BITFIELD(31, 2) /* index 869 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(874), + BITFIELD(33, 2) /* index 874 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(879), + BITFIELD(35, 2) /* index 879 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(884), + BITFIELD(37, 2) /* index 884 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(889), + BITFIELD(39, 2) /* index 889 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(894), + BITFIELD(41, 2) /* index 894 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO, + BITFIELD(51, 3) /* index 899 */, + TILE_OPC_MINIB_U, TILE_OPC_MINIH, TILE_OPC_MTSPR, CHILD(908), + TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI, TILE_OPC_SLTIB, + BITFIELD(37, 2) /* index 908 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(913), + BITFIELD(39, 2) /* index 913 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(918), + BITFIELD(41, 2) /* index 918 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI, + BITFIELD(51, 3) /* index 923 */, + TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U, TILE_OPC_SLTI, + TILE_OPC_SLTI_U, TILE_OPC_XORI, TILE_OPC_LBADD, TILE_OPC_LBADD_U, + BITFIELD(51, 3) /* index 932 */, + TILE_OPC_LHADD, TILE_OPC_LHADD_U, TILE_OPC_LWADD, TILE_OPC_LWADD_NA, + TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD, TILE_OPC_NONE, + BITFIELD(51, 3) /* index 941 */, + TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN, + TILE_OPC_ANDI_SN, TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MFSPR, + BITFIELD(51, 3) /* index 950 */, + TILE_OPC_MINIB_U_SN, TILE_OPC_MINIH_SN, TILE_OPC_MTSPR, CHILD(959), + TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN, TILE_OPC_SLTIB_SN, + BITFIELD(37, 2) /* index 959 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(964), + BITFIELD(39, 2) /* index 964 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(969), + BITFIELD(41, 2) /* index 969 */, + TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN, + BITFIELD(51, 3) /* index 974 */, + TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN, TILE_OPC_SLTIH_U_SN, + TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_XORI_SN, TILE_OPC_LBADD_SN, + TILE_OPC_LBADD_U_SN, + BITFIELD(51, 3) /* index 983 */, + TILE_OPC_LHADD_SN, TILE_OPC_LHADD_U_SN, TILE_OPC_LWADD_SN, + TILE_OPC_LWADD_NA_SN, TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD, + TILE_OPC_NONE, + BITFIELD(46, 7) /* index 992 */, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1121), + CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124), CHILD(1124), + CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127), CHILD(1127), + CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130), CHILD(1130), + CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1136), + CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139), CHILD(1139), + CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142), CHILD(1142), + CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145), CHILD(1145), + CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1151), + CHILD(1211), CHILD(1259), CHILD(1292), TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1121 */, + TILE_OPC_RLI, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1124 */, + TILE_OPC_SHLIB, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1127 */, + TILE_OPC_SHLIH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1130 */, + TILE_OPC_SHLI, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1133 */, + TILE_OPC_SHRIB, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1136 */, + TILE_OPC_SHRIH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1139 */, + TILE_OPC_SHRI, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1142 */, + TILE_OPC_SRAIB, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1145 */, + TILE_OPC_SRAIH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1148 */, + TILE_OPC_SRAI, TILE_OPC_NONE, + BITFIELD(43, 3) /* index 1151 */, + TILE_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169), + CHILD(1172), CHILD(1175), CHILD(1178), + BITFIELD(53, 1) /* index 1160 */, + TILE_OPC_DRAIN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1163 */, + TILE_OPC_DTLBPR, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1166 */, + TILE_OPC_FINV, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1169 */, + TILE_OPC_FLUSH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1172 */, + TILE_OPC_FNOP, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1175 */, + TILE_OPC_ICOH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1178 */, + CHILD(1181), TILE_OPC_NONE, + BITFIELD(31, 2) /* index 1181 */, + CHILD(1186), TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, + BITFIELD(33, 2) /* index 1186 */, + TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1191), + BITFIELD(35, 2) /* index 1191 */, + TILE_OPC_ILL, CHILD(1196), TILE_OPC_ILL, TILE_OPC_ILL, + BITFIELD(37, 2) /* index 1196 */, + TILE_OPC_ILL, CHILD(1201), TILE_OPC_ILL, TILE_OPC_ILL, + BITFIELD(39, 2) /* index 1201 */, + TILE_OPC_ILL, CHILD(1206), TILE_OPC_ILL, TILE_OPC_ILL, + BITFIELD(41, 2) /* index 1206 */, + TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_BPT, TILE_OPC_ILL, + BITFIELD(43, 3) /* index 1211 */, + CHILD(1220), CHILD(1223), CHILD(1226), CHILD(1244), CHILD(1247), + CHILD(1250), CHILD(1253), CHILD(1256), + BITFIELD(53, 1) /* index 1220 */, + TILE_OPC_INV, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1223 */, + TILE_OPC_IRET, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1226 */, + CHILD(1229), TILE_OPC_NONE, + BITFIELD(31, 2) /* index 1229 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1234), + BITFIELD(33, 2) /* index 1234 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1239), + BITFIELD(35, 2) /* index 1239 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH, + BITFIELD(53, 1) /* index 1244 */, + TILE_OPC_LB_U, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1247 */, + TILE_OPC_LH, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1250 */, + TILE_OPC_LH_U, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1253 */, + TILE_OPC_LW, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1256 */, + TILE_OPC_MF, TILE_OPC_NONE, + BITFIELD(43, 3) /* index 1259 */, + CHILD(1268), CHILD(1271), CHILD(1274), CHILD(1277), CHILD(1280), + CHILD(1283), CHILD(1286), CHILD(1289), + BITFIELD(53, 1) /* index 1268 */, + TILE_OPC_NAP, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1271 */, + TILE_OPC_NOP, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1274 */, + TILE_OPC_SWINT0, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1277 */, + TILE_OPC_SWINT1, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1280 */, + TILE_OPC_SWINT2, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1283 */, + TILE_OPC_SWINT3, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1286 */, + TILE_OPC_TNS, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1289 */, + TILE_OPC_WH64, TILE_OPC_NONE, + BITFIELD(43, 2) /* index 1292 */, + CHILD(1297), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(45, 1) /* index 1297 */, + CHILD(1300), TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1300 */, + TILE_OPC_LW_NA, TILE_OPC_NONE, + BITFIELD(46, 7) /* index 1303 */, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1432), + CHILD(1432), CHILD(1432), CHILD(1432), CHILD(1435), CHILD(1435), + CHILD(1435), CHILD(1435), CHILD(1438), CHILD(1438), CHILD(1438), + CHILD(1438), CHILD(1441), CHILD(1441), CHILD(1441), CHILD(1441), + CHILD(1444), CHILD(1444), CHILD(1444), CHILD(1444), CHILD(1447), + CHILD(1447), CHILD(1447), CHILD(1447), CHILD(1450), CHILD(1450), + CHILD(1450), CHILD(1450), CHILD(1453), CHILD(1453), CHILD(1453), + CHILD(1453), CHILD(1456), CHILD(1456), CHILD(1456), CHILD(1456), + CHILD(1459), CHILD(1459), CHILD(1459), CHILD(1459), CHILD(1151), + CHILD(1462), CHILD(1486), CHILD(1498), TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1432 */, + TILE_OPC_RLI_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1435 */, + TILE_OPC_SHLIB_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1438 */, + TILE_OPC_SHLIH_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1441 */, + TILE_OPC_SHLI_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1444 */, + TILE_OPC_SHRIB_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1447 */, + TILE_OPC_SHRIH_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1450 */, + TILE_OPC_SHRI_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1453 */, + TILE_OPC_SRAIB_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1456 */, + TILE_OPC_SRAIH_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1459 */, + TILE_OPC_SRAI_SN, TILE_OPC_NONE, + BITFIELD(43, 3) /* index 1462 */, + CHILD(1220), CHILD(1223), CHILD(1471), CHILD(1474), CHILD(1477), + CHILD(1480), CHILD(1483), CHILD(1256), + BITFIELD(53, 1) /* index 1471 */, + TILE_OPC_LB_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1474 */, + TILE_OPC_LB_U_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1477 */, + TILE_OPC_LH_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1480 */, + TILE_OPC_LH_U_SN, TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1483 */, + TILE_OPC_LW_SN, TILE_OPC_NONE, + BITFIELD(43, 3) /* index 1486 */, + CHILD(1268), CHILD(1271), CHILD(1274), CHILD(1277), CHILD(1280), + CHILD(1283), CHILD(1495), CHILD(1289), + BITFIELD(53, 1) /* index 1495 */, + TILE_OPC_TNS_SN, TILE_OPC_NONE, + BITFIELD(43, 2) /* index 1498 */, + CHILD(1503), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(45, 1) /* index 1503 */, + CHILD(1506), TILE_OPC_NONE, + BITFIELD(53, 1) /* index 1506 */, + TILE_OPC_LW_NA_SN, TILE_OPC_NONE, +}; + +static const unsigned short decode_Y0_fsm[168] = +{ + BITFIELD(27, 4) /* index 0 */, + TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52), + CHILD(57), CHILD(62), CHILD(67), TILE_OPC_ADDI, CHILD(72), CHILD(102), + TILE_OPC_SEQI, CHILD(117), TILE_OPC_SLTI, TILE_OPC_SLTI_U, + BITFIELD(18, 2) /* index 17 */, + TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB, + BITFIELD(18, 2) /* index 22 */, + TILE_OPC_MNZ, TILE_OPC_MVNZ, TILE_OPC_MVZ, TILE_OPC_MZ, + BITFIELD(18, 2) /* index 27 */, + TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR, + BITFIELD(12, 2) /* index 32 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37), + BITFIELD(14, 2) /* index 37 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42), + BITFIELD(16, 2) /* index 42 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE, + BITFIELD(18, 2) /* index 47 */, + TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA, + BITFIELD(18, 2) /* index 52 */, + TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U, + BITFIELD(18, 2) /* index 57 */, + TILE_OPC_MULHLSA_UU, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE, + BITFIELD(18, 2) /* index 62 */, + TILE_OPC_MULHH_SS, TILE_OPC_MULHH_UU, TILE_OPC_MULLL_SS, TILE_OPC_MULLL_UU, + BITFIELD(18, 2) /* index 67 */, + TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_UU, TILE_OPC_MULLLA_SS, + TILE_OPC_MULLLA_UU, + BITFIELD(0, 2) /* index 72 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77), + BITFIELD(2, 2) /* index 77 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82), + BITFIELD(4, 2) /* index 82 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87), + BITFIELD(6, 2) /* index 87 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(92), + BITFIELD(8, 2) /* index 92 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(97), + BITFIELD(10, 2) /* index 97 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO, + BITFIELD(6, 2) /* index 102 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(107), + BITFIELD(8, 2) /* index 107 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(112), + BITFIELD(10, 2) /* index 112 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI, + BITFIELD(15, 5) /* index 117 */, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_RLI, + TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHLI, + TILE_OPC_SHLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SHRI, TILE_OPC_SHRI, + TILE_OPC_SHRI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI, + CHILD(150), CHILD(159), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(12, 3) /* index 150 */, + TILE_OPC_NONE, TILE_OPC_BITX, TILE_OPC_BYTEX, TILE_OPC_CLZ, TILE_OPC_CTZ, + TILE_OPC_FNOP, TILE_OPC_NOP, TILE_OPC_PCNT, + BITFIELD(12, 3) /* index 159 */, + TILE_OPC_TBLIDXB0, TILE_OPC_TBLIDXB1, TILE_OPC_TBLIDXB2, TILE_OPC_TBLIDXB3, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, +}; + +static const unsigned short decode_Y1_fsm[140] = +{ + BITFIELD(59, 4) /* index 0 */, + TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52), + CHILD(57), TILE_OPC_ADDI, CHILD(62), CHILD(92), TILE_OPC_SEQI, CHILD(107), + TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(49, 2) /* index 17 */, + TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB, + BITFIELD(49, 2) /* index 22 */, + TILE_OPC_NONE, TILE_OPC_MNZ, TILE_OPC_MZ, TILE_OPC_NONE, + BITFIELD(49, 2) /* index 27 */, + TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR, + BITFIELD(43, 2) /* index 32 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37), + BITFIELD(45, 2) /* index 37 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42), + BITFIELD(47, 2) /* index 42 */, + TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE, + BITFIELD(49, 2) /* index 47 */, + TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA, + BITFIELD(49, 2) /* index 52 */, + TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U, + BITFIELD(49, 2) /* index 57 */, + TILE_OPC_NONE, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE, + BITFIELD(31, 2) /* index 62 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(67), + BITFIELD(33, 2) /* index 67 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(72), + BITFIELD(35, 2) /* index 72 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77), + BITFIELD(37, 2) /* index 77 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82), + BITFIELD(39, 2) /* index 82 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87), + BITFIELD(41, 2) /* index 87 */, + TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO, + BITFIELD(37, 2) /* index 92 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(97), + BITFIELD(39, 2) /* index 97 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(102), + BITFIELD(41, 2) /* index 102 */, + TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI, + BITFIELD(48, 3) /* index 107 */, + TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SRAI, + CHILD(116), TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(43, 3) /* index 116 */, + TILE_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILE_OPC_NONE, + TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(46, 2) /* index 125 */, + TILE_OPC_FNOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(46, 2) /* index 130 */, + TILE_OPC_ILL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, + BITFIELD(46, 2) /* index 135 */, + TILE_OPC_NOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, +}; + +static const unsigned short decode_Y2_fsm[24] = +{ + BITFIELD(56, 3) /* index 0 */, + CHILD(9), TILE_OPC_LB_U, TILE_OPC_LH, TILE_OPC_LH_U, TILE_OPC_LW, + TILE_OPC_SB, TILE_OPC_SH, TILE_OPC_SW, + BITFIELD(20, 2) /* index 9 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(14), + BITFIELD(22, 2) /* index 14 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(19), + BITFIELD(24, 2) /* index 19 */, + TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH, +}; + +#undef BITFIELD +#undef CHILD +const unsigned short * const +tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS] = +{ + decode_X0_fsm, + decode_X1_fsm, + decode_Y0_fsm, + decode_Y1_fsm, + decode_Y2_fsm +}; +const struct tile_sn_opcode tile_sn_opcodes[23] = +{ + { "bz", TILE_SN_OPC_BZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xe000 + }, + { "bnz", TILE_SN_OPC_BNZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xe400 + }, + { "jrr", TILE_SN_OPC_JRR, + 1 /* num_operands */, + /* operands */ + { 39 }, + /* fixed_bit_mask */ + 0xff00, + /* fixed_bit_value */ + 0x0600 + }, + { "fnop", TILE_SN_OPC_FNOP, + 0 /* num_operands */, + /* operands */ + { 0, }, + /* fixed_bit_mask */ + 0xffff, + /* fixed_bit_value */ + 0x0003 + }, + { "blz", TILE_SN_OPC_BLZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xf000 + }, + { "nop", TILE_SN_OPC_NOP, + 0 /* num_operands */, + /* operands */ + { 0, }, + /* fixed_bit_mask */ + 0xffff, + /* fixed_bit_value */ + 0x0002 + }, + { "movei", TILE_SN_OPC_MOVEI, + 1 /* num_operands */, + /* operands */ + { 40 }, + /* fixed_bit_mask */ + 0xff00, + /* fixed_bit_value */ + 0x0400 + }, + { "move", TILE_SN_OPC_MOVE, + 2 /* num_operands */, + /* operands */ + { 41, 42 }, + /* fixed_bit_mask */ + 0xfff0, + /* fixed_bit_value */ + 0x0080 + }, + { "bgez", TILE_SN_OPC_BGEZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xf400 + }, + { "jr", TILE_SN_OPC_JR, + 1 /* num_operands */, + /* operands */ + { 42 }, + /* fixed_bit_mask */ + 0xfff0, + /* fixed_bit_value */ + 0x0040 + }, + { "blez", TILE_SN_OPC_BLEZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xec00 + }, + { "bbns", TILE_SN_OPC_BBNS, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xfc00 + }, + { "jalrr", TILE_SN_OPC_JALRR, + 1 /* num_operands */, + /* operands */ + { 39 }, + /* fixed_bit_mask */ + 0xff00, + /* fixed_bit_value */ + 0x0700 + }, + { "bpt", TILE_SN_OPC_BPT, + 0 /* num_operands */, + /* operands */ + { 0, }, + /* fixed_bit_mask */ + 0xffff, + /* fixed_bit_value */ + 0x0001 + }, + { "jalr", TILE_SN_OPC_JALR, + 1 /* num_operands */, + /* operands */ + { 42 }, + /* fixed_bit_mask */ + 0xfff0, + /* fixed_bit_value */ + 0x0050 + }, + { "shr1", TILE_SN_OPC_SHR1, + 2 /* num_operands */, + /* operands */ + { 41, 42 }, + /* fixed_bit_mask */ + 0xfff0, + /* fixed_bit_value */ + 0x0090 + }, + { "bgz", TILE_SN_OPC_BGZ, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xe800 + }, + { "bbs", TILE_SN_OPC_BBS, + 1 /* num_operands */, + /* operands */ + { 38 }, + /* fixed_bit_mask */ + 0xfc00, + /* fixed_bit_value */ + 0xf800 + }, + { "shl8ii", TILE_SN_OPC_SHL8II, + 1 /* num_operands */, + /* operands */ + { 39 }, + /* fixed_bit_mask */ + 0xff00, + /* fixed_bit_value */ + 0x0300 + }, + { "addi", TILE_SN_OPC_ADDI, + 1 /* num_operands */, + /* operands */ + { 40 }, + /* fixed_bit_mask */ + 0xff00, + /* fixed_bit_value */ + 0x0500 + }, + { "halt", TILE_SN_OPC_HALT, + 0 /* num_operands */, + /* operands */ + { 0, }, + /* fixed_bit_mask */ + 0xffff, + /* fixed_bit_value */ + 0x0000 + }, + { "route", TILE_SN_OPC_ROUTE, 0, { 0, }, 0, 0, + }, + { 0, TILE_SN_OPC_NONE, 0, { 0, }, 0, 0, + } +}; +const unsigned char tile_sn_route_encode[6 * 6 * 6] = +{ + 0xdf, + 0xde, + 0xdd, + 0xdc, + 0xdb, + 0xda, + 0xb9, + 0xb8, + 0xa1, + 0xa0, + 0x11, + 0x10, + 0x9f, + 0x9e, + 0x9d, + 0x9c, + 0x9b, + 0x9a, + 0x79, + 0x78, + 0x61, + 0x60, + 0xb, + 0xa, + 0x5f, + 0x5e, + 0x5d, + 0x5c, + 0x5b, + 0x5a, + 0x1f, + 0x1e, + 0x1d, + 0x1c, + 0x1b, + 0x1a, + 0xd7, + 0xd6, + 0xd5, + 0xd4, + 0xd3, + 0xd2, + 0xa7, + 0xa6, + 0xb1, + 0xb0, + 0x13, + 0x12, + 0x97, + 0x96, + 0x95, + 0x94, + 0x93, + 0x92, + 0x67, + 0x66, + 0x71, + 0x70, + 0x9, + 0x8, + 0x57, + 0x56, + 0x55, + 0x54, + 0x53, + 0x52, + 0x17, + 0x16, + 0x15, + 0x14, + 0x19, + 0x18, + 0xcf, + 0xce, + 0xcd, + 0xcc, + 0xcb, + 0xca, + 0xaf, + 0xae, + 0xad, + 0xac, + 0xab, + 0xaa, + 0x8f, + 0x8e, + 0x8d, + 0x8c, + 0x8b, + 0x8a, + 0x6f, + 0x6e, + 0x6d, + 0x6c, + 0x6b, + 0x6a, + 0x4f, + 0x4e, + 0x4d, + 0x4c, + 0x4b, + 0x4a, + 0x2f, + 0x2e, + 0x2d, + 0x2c, + 0x2b, + 0x2a, + 0xc9, + 0xc8, + 0xc5, + 0xc4, + 0xc3, + 0xc2, + 0xa9, + 0xa8, + 0xa5, + 0xa4, + 0xa3, + 0xa2, + 0x89, + 0x88, + 0x85, + 0x84, + 0x83, + 0x82, + 0x69, + 0x68, + 0x65, + 0x64, + 0x63, + 0x62, + 0x47, + 0x46, + 0x45, + 0x44, + 0x43, + 0x42, + 0x27, + 0x26, + 0x25, + 0x24, + 0x23, + 0x22, + 0xd9, + 0xd8, + 0xc1, + 0xc0, + 0x3b, + 0x3a, + 0xbf, + 0xbe, + 0xbd, + 0xbc, + 0xbb, + 0xba, + 0x99, + 0x98, + 0x81, + 0x80, + 0x31, + 0x30, + 0x7f, + 0x7e, + 0x7d, + 0x7c, + 0x7b, + 0x7a, + 0x59, + 0x58, + 0x3d, + 0x3c, + 0x49, + 0x48, + 0xf, + 0xe, + 0xd, + 0xc, + 0x29, + 0x28, + 0xc7, + 0xc6, + 0xd1, + 0xd0, + 0x39, + 0x38, + 0xb7, + 0xb6, + 0xb5, + 0xb4, + 0xb3, + 0xb2, + 0x87, + 0x86, + 0x91, + 0x90, + 0x33, + 0x32, + 0x77, + 0x76, + 0x75, + 0x74, + 0x73, + 0x72, + 0x3f, + 0x3e, + 0x51, + 0x50, + 0x41, + 0x40, + 0x37, + 0x36, + 0x35, + 0x34, + 0x21, + 0x20 +}; + +const signed char tile_sn_route_decode[256][3] = +{ + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { 5, 3, 1 }, + { 4, 3, 1 }, + { 5, 3, 0 }, + { 4, 3, 0 }, + { 3, 5, 4 }, + { 2, 5, 4 }, + { 1, 5, 4 }, + { 0, 5, 4 }, + { 5, 1, 0 }, + { 4, 1, 0 }, + { 5, 1, 1 }, + { 4, 1, 1 }, + { 3, 5, 1 }, + { 2, 5, 1 }, + { 1, 5, 1 }, + { 0, 5, 1 }, + { 5, 5, 1 }, + { 4, 5, 1 }, + { 5, 5, 0 }, + { 4, 5, 0 }, + { 3, 5, 0 }, + { 2, 5, 0 }, + { 1, 5, 0 }, + { 0, 5, 0 }, + { 5, 5, 5 }, + { 4, 5, 5 }, + { 5, 5, 3 }, + { 4, 5, 3 }, + { 3, 5, 3 }, + { 2, 5, 3 }, + { 1, 5, 3 }, + { 0, 5, 3 }, + { 5, 5, 4 }, + { 4, 5, 4 }, + { 5, 5, 2 }, + { 4, 5, 2 }, + { 3, 5, 2 }, + { 2, 5, 2 }, + { 1, 5, 2 }, + { 0, 5, 2 }, + { 5, 2, 4 }, + { 4, 2, 4 }, + { 5, 2, 5 }, + { 4, 2, 5 }, + { 3, 5, 5 }, + { 2, 5, 5 }, + { 1, 5, 5 }, + { 0, 5, 5 }, + { 5, 0, 5 }, + { 4, 0, 5 }, + { 5, 0, 4 }, + { 4, 0, 4 }, + { 3, 4, 4 }, + { 2, 4, 4 }, + { 1, 4, 5 }, + { 0, 4, 5 }, + { 5, 4, 5 }, + { 4, 4, 5 }, + { 5, 4, 3 }, + { 4, 4, 3 }, + { 3, 4, 3 }, + { 2, 4, 3 }, + { 1, 4, 3 }, + { 0, 4, 3 }, + { 5, 4, 4 }, + { 4, 4, 4 }, + { 5, 4, 2 }, + { 4, 4, 2 }, + { 3, 4, 2 }, + { 2, 4, 2 }, + { 1, 4, 2 }, + { 0, 4, 2 }, + { 3, 4, 5 }, + { 2, 4, 5 }, + { 5, 4, 1 }, + { 4, 4, 1 }, + { 3, 4, 1 }, + { 2, 4, 1 }, + { 1, 4, 1 }, + { 0, 4, 1 }, + { 1, 4, 4 }, + { 0, 4, 4 }, + { 5, 4, 0 }, + { 4, 4, 0 }, + { 3, 4, 0 }, + { 2, 4, 0 }, + { 1, 4, 0 }, + { 0, 4, 0 }, + { 3, 3, 0 }, + { 2, 3, 0 }, + { 5, 3, 3 }, + { 4, 3, 3 }, + { 3, 3, 3 }, + { 2, 3, 3 }, + { 1, 3, 1 }, + { 0, 3, 1 }, + { 1, 3, 3 }, + { 0, 3, 3 }, + { 5, 3, 2 }, + { 4, 3, 2 }, + { 3, 3, 2 }, + { 2, 3, 2 }, + { 1, 3, 2 }, + { 0, 3, 2 }, + { 3, 3, 1 }, + { 2, 3, 1 }, + { 5, 3, 5 }, + { 4, 3, 5 }, + { 3, 3, 5 }, + { 2, 3, 5 }, + { 1, 3, 5 }, + { 0, 3, 5 }, + { 1, 3, 0 }, + { 0, 3, 0 }, + { 5, 3, 4 }, + { 4, 3, 4 }, + { 3, 3, 4 }, + { 2, 3, 4 }, + { 1, 3, 4 }, + { 0, 3, 4 }, + { 3, 2, 4 }, + { 2, 2, 4 }, + { 5, 2, 3 }, + { 4, 2, 3 }, + { 3, 2, 3 }, + { 2, 2, 3 }, + { 1, 2, 5 }, + { 0, 2, 5 }, + { 1, 2, 3 }, + { 0, 2, 3 }, + { 5, 2, 2 }, + { 4, 2, 2 }, + { 3, 2, 2 }, + { 2, 2, 2 }, + { 1, 2, 2 }, + { 0, 2, 2 }, + { 3, 2, 5 }, + { 2, 2, 5 }, + { 5, 2, 1 }, + { 4, 2, 1 }, + { 3, 2, 1 }, + { 2, 2, 1 }, + { 1, 2, 1 }, + { 0, 2, 1 }, + { 1, 2, 4 }, + { 0, 2, 4 }, + { 5, 2, 0 }, + { 4, 2, 0 }, + { 3, 2, 0 }, + { 2, 2, 0 }, + { 1, 2, 0 }, + { 0, 2, 0 }, + { 3, 1, 0 }, + { 2, 1, 0 }, + { 5, 1, 3 }, + { 4, 1, 3 }, + { 3, 1, 3 }, + { 2, 1, 3 }, + { 1, 1, 1 }, + { 0, 1, 1 }, + { 1, 1, 3 }, + { 0, 1, 3 }, + { 5, 1, 2 }, + { 4, 1, 2 }, + { 3, 1, 2 }, + { 2, 1, 2 }, + { 1, 1, 2 }, + { 0, 1, 2 }, + { 3, 1, 1 }, + { 2, 1, 1 }, + { 5, 1, 5 }, + { 4, 1, 5 }, + { 3, 1, 5 }, + { 2, 1, 5 }, + { 1, 1, 5 }, + { 0, 1, 5 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 5, 1, 4 }, + { 4, 1, 4 }, + { 3, 1, 4 }, + { 2, 1, 4 }, + { 1, 1, 4 }, + { 0, 1, 4 }, + { 3, 0, 4 }, + { 2, 0, 4 }, + { 5, 0, 3 }, + { 4, 0, 3 }, + { 3, 0, 3 }, + { 2, 0, 3 }, + { 1, 0, 5 }, + { 0, 0, 5 }, + { 1, 0, 3 }, + { 0, 0, 3 }, + { 5, 0, 2 }, + { 4, 0, 2 }, + { 3, 0, 2 }, + { 2, 0, 2 }, + { 1, 0, 2 }, + { 0, 0, 2 }, + { 3, 0, 5 }, + { 2, 0, 5 }, + { 5, 0, 1 }, + { 4, 0, 1 }, + { 3, 0, 1 }, + { 2, 0, 1 }, + { 1, 0, 1 }, + { 0, 0, 1 }, + { 1, 0, 4 }, + { 0, 0, 4 }, + { 5, 0, 0 }, + { 4, 0, 0 }, + { 3, 0, 0 }, + { 2, 0, 0 }, + { 1, 0, 0 }, + { 0, 0, 0 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 } +}; + +const char tile_sn_direction_names[6][5] = +{ + "w", + "c", + "acc", + "n", + "e", + "s" +}; + +const signed char tile_sn_dest_map[6][6] = { + { -1, 3, 4, 5, 1, 2 } /* val -> w */, + { -1, 3, 4, 5, 0, 2 } /* val -> c */, + { -1, 3, 4, 5, 0, 1 } /* val -> acc */, + { -1, 4, 5, 0, 1, 2 } /* val -> n */, + { -1, 3, 5, 0, 1, 2 } /* val -> e */, + { -1, 3, 4, 0, 1, 2 } /* val -> s */ +}; + +const struct tile_operand tile_operands[43] = +{ + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM8_X0), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_X0, /* insert */ + get_Imm8_X0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM8_X1), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_X1, /* insert */ + get_Imm8_X1 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM8_Y0), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_Y0, /* insert */ + get_Imm8_Y0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM8_Y1), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_Y1, /* insert */ + get_Imm8_Y1 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM16_X0), /* default_reloc */ + 16, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm16_X0, /* insert */ + get_Imm16_X0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_IMM16_X1), /* default_reloc */ + 16, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm16_X1, /* insert */ + get_Imm16_X1 /* extract */ + }, + { + TILE_OP_TYPE_ADDRESS, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_JOFFLONG_X1), /* default_reloc */ + 29, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 1, /* is_pc_relative */ + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, /* rightshift */ + create_JOffLong_X1, /* insert */ + get_JOffLong_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_X0, /* insert */ + get_Dest_X0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_X0, /* insert */ + get_SrcA_X0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_X1, /* insert */ + get_Dest_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_X1, /* insert */ + get_SrcA_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_Y0, /* insert */ + get_Dest_Y0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_Y0, /* insert */ + get_SrcA_Y0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_Y1, /* insert */ + get_Dest_Y1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_Y1, /* insert */ + get_SrcA_Y1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_Y2, /* insert */ + get_SrcA_Y2 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcB_X0, /* insert */ + get_SrcB_X0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcB_X1, /* insert */ + get_SrcB_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcB_Y0, /* insert */ + get_SrcB_Y0 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcB_Y1, /* insert */ + get_SrcB_Y1 /* extract */ + }, + { + TILE_OP_TYPE_ADDRESS, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_BROFF_X1), /* default_reloc */ + 17, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 1, /* is_pc_relative */ + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, /* rightshift */ + create_BrOff_X1, /* insert */ + get_BrOff_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_X0, /* insert */ + get_Dest_X0 /* extract */ + }, + { + TILE_OP_TYPE_ADDRESS, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 28, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 1, /* is_pc_relative */ + TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, /* rightshift */ + create_JOff_X1, /* insert */ + get_JOff_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcBDest_Y2, /* insert */ + get_SrcBDest_Y2 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcA_X1, /* insert */ + get_SrcA_X1 /* extract */ + }, + { + TILE_OP_TYPE_SPR, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MF_IMM15_X1), /* default_reloc */ + 15, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MF_Imm15_X1, /* insert */ + get_MF_Imm15_X1 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MMSTART_X0), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MMStart_X0, /* insert */ + get_MMStart_X0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MMEND_X0), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MMEnd_X0, /* insert */ + get_MMEnd_X0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MMSTART_X1), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MMStart_X1, /* insert */ + get_MMStart_X1 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MMEND_X1), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MMEnd_X1, /* insert */ + get_MMEnd_X1 /* extract */ + }, + { + TILE_OP_TYPE_SPR, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_MT_IMM15_X1), /* default_reloc */ + 15, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_MT_Imm15_X1, /* insert */ + get_MT_Imm15_X1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_Y0, /* insert */ + get_Dest_Y0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SHAMT_X0), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_ShAmt_X0, /* insert */ + get_ShAmt_X0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SHAMT_X1), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_ShAmt_X1, /* insert */ + get_ShAmt_X1 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SHAMT_Y0), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_ShAmt_Y0, /* insert */ + get_ShAmt_Y0 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SHAMT_Y1), /* default_reloc */ + 5, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_ShAmt_Y1, /* insert */ + get_ShAmt_Y1 /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 6, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_SrcBDest_Y2, /* insert */ + get_SrcBDest_Y2 /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_Imm8_X1, /* insert */ + get_Dest_Imm8_X1 /* extract */ + }, + { + TILE_OP_TYPE_ADDRESS, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SN_BROFF), /* default_reloc */ + 10, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 1, /* is_pc_relative */ + TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES, /* rightshift */ + create_BrOff_SN, /* insert */ + get_BrOff_SN /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SN_UIMM8), /* default_reloc */ + 8, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_SN, /* insert */ + get_Imm8_SN /* extract */ + }, + { + TILE_OP_TYPE_IMMEDIATE, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_TILE_SN_IMM8), /* default_reloc */ + 8, /* num_bits */ + 1, /* is_signed */ + 0, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Imm8_SN, /* insert */ + get_Imm8_SN /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 2, /* num_bits */ + 0, /* is_signed */ + 0, /* is_src_reg */ + 1, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Dest_SN, /* insert */ + get_Dest_SN /* extract */ + }, + { + TILE_OP_TYPE_REGISTER, /* type */ + MAYBE_BFD_RELOC(BFD_RELOC_NONE), /* default_reloc */ + 2, /* num_bits */ + 0, /* is_signed */ + 1, /* is_src_reg */ + 0, /* is_dest_reg */ + 0, /* is_pc_relative */ + 0, /* rightshift */ + create_Src_SN, /* insert */ + get_Src_SN /* extract */ + } +}; + +const struct tile_spr tile_sprs[] = { + { 0, "MPL_ITLB_MISS_SET_0" }, + { 1, "MPL_ITLB_MISS_SET_1" }, + { 2, "MPL_ITLB_MISS_SET_2" }, + { 3, "MPL_ITLB_MISS_SET_3" }, + { 4, "MPL_ITLB_MISS" }, + { 256, "ITLB_CURRENT_0" }, + { 257, "ITLB_CURRENT_1" }, + { 258, "ITLB_CURRENT_2" }, + { 259, "ITLB_CURRENT_3" }, + { 260, "ITLB_INDEX" }, + { 261, "ITLB_MATCH_0" }, + { 262, "ITLB_PR" }, + { 263, "NUMBER_ITLB" }, + { 264, "REPLACEMENT_ITLB" }, + { 265, "WIRED_ITLB" }, + { 266, "ITLB_PERF" }, + { 512, "MPL_MEM_ERROR_SET_0" }, + { 513, "MPL_MEM_ERROR_SET_1" }, + { 514, "MPL_MEM_ERROR_SET_2" }, + { 515, "MPL_MEM_ERROR_SET_3" }, + { 516, "MPL_MEM_ERROR" }, + { 517, "L1_I_ERROR" }, + { 518, "MEM_ERROR_CBOX_ADDR" }, + { 519, "MEM_ERROR_CBOX_STATUS" }, + { 520, "MEM_ERROR_ENABLE" }, + { 521, "MEM_ERROR_MBOX_ADDR" }, + { 522, "MEM_ERROR_MBOX_STATUS" }, + { 523, "SNIC_ERROR_LOG_STATUS" }, + { 524, "SNIC_ERROR_LOG_VA" }, + { 525, "XDN_DEMUX_ERROR" }, + { 1024, "MPL_ILL_SET_0" }, + { 1025, "MPL_ILL_SET_1" }, + { 1026, "MPL_ILL_SET_2" }, + { 1027, "MPL_ILL_SET_3" }, + { 1028, "MPL_ILL" }, + { 1536, "MPL_GPV_SET_0" }, + { 1537, "MPL_GPV_SET_1" }, + { 1538, "MPL_GPV_SET_2" }, + { 1539, "MPL_GPV_SET_3" }, + { 1540, "MPL_GPV" }, + { 1541, "GPV_REASON" }, + { 2048, "MPL_SN_ACCESS_SET_0" }, + { 2049, "MPL_SN_ACCESS_SET_1" }, + { 2050, "MPL_SN_ACCESS_SET_2" }, + { 2051, "MPL_SN_ACCESS_SET_3" }, + { 2052, "MPL_SN_ACCESS" }, + { 2053, "SNCTL" }, + { 2054, "SNFIFO_DATA" }, + { 2055, "SNFIFO_SEL" }, + { 2056, "SNIC_INVADDR" }, + { 2057, "SNISTATE" }, + { 2058, "SNOSTATE" }, + { 2059, "SNPC" }, + { 2060, "SNSTATIC" }, + { 2304, "SN_DATA_AVAIL" }, + { 2560, "MPL_IDN_ACCESS_SET_0" }, + { 2561, "MPL_IDN_ACCESS_SET_1" }, + { 2562, "MPL_IDN_ACCESS_SET_2" }, + { 2563, "MPL_IDN_ACCESS_SET_3" }, + { 2564, "MPL_IDN_ACCESS" }, + { 2565, "IDN_DEMUX_CA_COUNT" }, + { 2566, "IDN_DEMUX_COUNT_0" }, + { 2567, "IDN_DEMUX_COUNT_1" }, + { 2568, "IDN_DEMUX_CTL" }, + { 2569, "IDN_DEMUX_CURR_TAG" }, + { 2570, "IDN_DEMUX_QUEUE_SEL" }, + { 2571, "IDN_DEMUX_STATUS" }, + { 2572, "IDN_DEMUX_WRITE_FIFO" }, + { 2573, "IDN_DEMUX_WRITE_QUEUE" }, + { 2574, "IDN_PENDING" }, + { 2575, "IDN_SP_FIFO_DATA" }, + { 2576, "IDN_SP_FIFO_SEL" }, + { 2577, "IDN_SP_FREEZE" }, + { 2578, "IDN_SP_STATE" }, + { 2579, "IDN_TAG_0" }, + { 2580, "IDN_TAG_1" }, + { 2581, "IDN_TAG_VALID" }, + { 2582, "IDN_TILE_COORD" }, + { 2816, "IDN_CA_DATA" }, + { 2817, "IDN_CA_REM" }, + { 2818, "IDN_CA_TAG" }, + { 2819, "IDN_DATA_AVAIL" }, + { 3072, "MPL_UDN_ACCESS_SET_0" }, + { 3073, "MPL_UDN_ACCESS_SET_1" }, + { 3074, "MPL_UDN_ACCESS_SET_2" }, + { 3075, "MPL_UDN_ACCESS_SET_3" }, + { 3076, "MPL_UDN_ACCESS" }, + { 3077, "UDN_DEMUX_CA_COUNT" }, + { 3078, "UDN_DEMUX_COUNT_0" }, + { 3079, "UDN_DEMUX_COUNT_1" }, + { 3080, "UDN_DEMUX_COUNT_2" }, + { 3081, "UDN_DEMUX_COUNT_3" }, + { 3082, "UDN_DEMUX_CTL" }, + { 3083, "UDN_DEMUX_CURR_TAG" }, + { 3084, "UDN_DEMUX_QUEUE_SEL" }, + { 3085, "UDN_DEMUX_STATUS" }, + { 3086, "UDN_DEMUX_WRITE_FIFO" }, + { 3087, "UDN_DEMUX_WRITE_QUEUE" }, + { 3088, "UDN_PENDING" }, + { 3089, "UDN_SP_FIFO_DATA" }, + { 3090, "UDN_SP_FIFO_SEL" }, + { 3091, "UDN_SP_FREEZE" }, + { 3092, "UDN_SP_STATE" }, + { 3093, "UDN_TAG_0" }, + { 3094, "UDN_TAG_1" }, + { 3095, "UDN_TAG_2" }, + { 3096, "UDN_TAG_3" }, + { 3097, "UDN_TAG_VALID" }, + { 3098, "UDN_TILE_COORD" }, + { 3328, "UDN_CA_DATA" }, + { 3329, "UDN_CA_REM" }, + { 3330, "UDN_CA_TAG" }, + { 3331, "UDN_DATA_AVAIL" }, + { 3584, "MPL_IDN_REFILL_SET_0" }, + { 3585, "MPL_IDN_REFILL_SET_1" }, + { 3586, "MPL_IDN_REFILL_SET_2" }, + { 3587, "MPL_IDN_REFILL_SET_3" }, + { 3588, "MPL_IDN_REFILL" }, + { 3589, "IDN_REFILL_EN" }, + { 4096, "MPL_UDN_REFILL_SET_0" }, + { 4097, "MPL_UDN_REFILL_SET_1" }, + { 4098, "MPL_UDN_REFILL_SET_2" }, + { 4099, "MPL_UDN_REFILL_SET_3" }, + { 4100, "MPL_UDN_REFILL" }, + { 4101, "UDN_REFILL_EN" }, + { 4608, "MPL_IDN_COMPLETE_SET_0" }, + { 4609, "MPL_IDN_COMPLETE_SET_1" }, + { 4610, "MPL_IDN_COMPLETE_SET_2" }, + { 4611, "MPL_IDN_COMPLETE_SET_3" }, + { 4612, "MPL_IDN_COMPLETE" }, + { 4613, "IDN_REMAINING" }, + { 5120, "MPL_UDN_COMPLETE_SET_0" }, + { 5121, "MPL_UDN_COMPLETE_SET_1" }, + { 5122, "MPL_UDN_COMPLETE_SET_2" }, + { 5123, "MPL_UDN_COMPLETE_SET_3" }, + { 5124, "MPL_UDN_COMPLETE" }, + { 5125, "UDN_REMAINING" }, + { 5632, "MPL_SWINT_3_SET_0" }, + { 5633, "MPL_SWINT_3_SET_1" }, + { 5634, "MPL_SWINT_3_SET_2" }, + { 5635, "MPL_SWINT_3_SET_3" }, + { 5636, "MPL_SWINT_3" }, + { 6144, "MPL_SWINT_2_SET_0" }, + { 6145, "MPL_SWINT_2_SET_1" }, + { 6146, "MPL_SWINT_2_SET_2" }, + { 6147, "MPL_SWINT_2_SET_3" }, + { 6148, "MPL_SWINT_2" }, + { 6656, "MPL_SWINT_1_SET_0" }, + { 6657, "MPL_SWINT_1_SET_1" }, + { 6658, "MPL_SWINT_1_SET_2" }, + { 6659, "MPL_SWINT_1_SET_3" }, + { 6660, "MPL_SWINT_1" }, + { 7168, "MPL_SWINT_0_SET_0" }, + { 7169, "MPL_SWINT_0_SET_1" }, + { 7170, "MPL_SWINT_0_SET_2" }, + { 7171, "MPL_SWINT_0_SET_3" }, + { 7172, "MPL_SWINT_0" }, + { 7680, "MPL_UNALIGN_DATA_SET_0" }, + { 7681, "MPL_UNALIGN_DATA_SET_1" }, + { 7682, "MPL_UNALIGN_DATA_SET_2" }, + { 7683, "MPL_UNALIGN_DATA_SET_3" }, + { 7684, "MPL_UNALIGN_DATA" }, + { 8192, "MPL_DTLB_MISS_SET_0" }, + { 8193, "MPL_DTLB_MISS_SET_1" }, + { 8194, "MPL_DTLB_MISS_SET_2" }, + { 8195, "MPL_DTLB_MISS_SET_3" }, + { 8196, "MPL_DTLB_MISS" }, + { 8448, "AER_0" }, + { 8449, "AER_1" }, + { 8450, "DTLB_BAD_ADDR" }, + { 8451, "DTLB_BAD_ADDR_REASON" }, + { 8452, "DTLB_CURRENT_0" }, + { 8453, "DTLB_CURRENT_1" }, + { 8454, "DTLB_CURRENT_2" }, + { 8455, "DTLB_CURRENT_3" }, + { 8456, "DTLB_INDEX" }, + { 8457, "DTLB_MATCH_0" }, + { 8458, "NUMBER_DTLB" }, + { 8459, "PHYSICAL_MEMORY_MODE" }, + { 8460, "REPLACEMENT_DTLB" }, + { 8461, "WIRED_DTLB" }, + { 8462, "CACHE_RED_WAY_OVERRIDDEN" }, + { 8463, "DTLB_PERF" }, + { 8704, "MPL_DTLB_ACCESS_SET_0" }, + { 8705, "MPL_DTLB_ACCESS_SET_1" }, + { 8706, "MPL_DTLB_ACCESS_SET_2" }, + { 8707, "MPL_DTLB_ACCESS_SET_3" }, + { 8708, "MPL_DTLB_ACCESS" }, + { 9216, "MPL_DMATLB_MISS_SET_0" }, + { 9217, "MPL_DMATLB_MISS_SET_1" }, + { 9218, "MPL_DMATLB_MISS_SET_2" }, + { 9219, "MPL_DMATLB_MISS_SET_3" }, + { 9220, "MPL_DMATLB_MISS" }, + { 9472, "DMA_BAD_ADDR" }, + { 9473, "DMA_STATUS" }, + { 9728, "MPL_DMATLB_ACCESS_SET_0" }, + { 9729, "MPL_DMATLB_ACCESS_SET_1" }, + { 9730, "MPL_DMATLB_ACCESS_SET_2" }, + { 9731, "MPL_DMATLB_ACCESS_SET_3" }, + { 9732, "MPL_DMATLB_ACCESS" }, + { 10240, "MPL_SNITLB_MISS_SET_0" }, + { 10241, "MPL_SNITLB_MISS_SET_1" }, + { 10242, "MPL_SNITLB_MISS_SET_2" }, + { 10243, "MPL_SNITLB_MISS_SET_3" }, + { 10244, "MPL_SNITLB_MISS" }, + { 10245, "NUMBER_SNITLB" }, + { 10246, "REPLACEMENT_SNITLB" }, + { 10247, "SNITLB_CURRENT_0" }, + { 10248, "SNITLB_CURRENT_1" }, + { 10249, "SNITLB_CURRENT_2" }, + { 10250, "SNITLB_CURRENT_3" }, + { 10251, "SNITLB_INDEX" }, + { 10252, "SNITLB_MATCH_0" }, + { 10253, "SNITLB_PR" }, + { 10254, "WIRED_SNITLB" }, + { 10255, "SNITLB_STATUS" }, + { 10752, "MPL_SN_NOTIFY_SET_0" }, + { 10753, "MPL_SN_NOTIFY_SET_1" }, + { 10754, "MPL_SN_NOTIFY_SET_2" }, + { 10755, "MPL_SN_NOTIFY_SET_3" }, + { 10756, "MPL_SN_NOTIFY" }, + { 10757, "SN_NOTIFY_STATUS" }, + { 11264, "MPL_SN_FIREWALL_SET_0" }, + { 11265, "MPL_SN_FIREWALL_SET_1" }, + { 11266, "MPL_SN_FIREWALL_SET_2" }, + { 11267, "MPL_SN_FIREWALL_SET_3" }, + { 11268, "MPL_SN_FIREWALL" }, + { 11269, "SN_DIRECTION_PROTECT" }, + { 11776, "MPL_IDN_FIREWALL_SET_0" }, + { 11777, "MPL_IDN_FIREWALL_SET_1" }, + { 11778, "MPL_IDN_FIREWALL_SET_2" }, + { 11779, "MPL_IDN_FIREWALL_SET_3" }, + { 11780, "MPL_IDN_FIREWALL" }, + { 11781, "IDN_DIRECTION_PROTECT" }, + { 12288, "MPL_UDN_FIREWALL_SET_0" }, + { 12289, "MPL_UDN_FIREWALL_SET_1" }, + { 12290, "MPL_UDN_FIREWALL_SET_2" }, + { 12291, "MPL_UDN_FIREWALL_SET_3" }, + { 12292, "MPL_UDN_FIREWALL" }, + { 12293, "UDN_DIRECTION_PROTECT" }, + { 12800, "MPL_TILE_TIMER_SET_0" }, + { 12801, "MPL_TILE_TIMER_SET_1" }, + { 12802, "MPL_TILE_TIMER_SET_2" }, + { 12803, "MPL_TILE_TIMER_SET_3" }, + { 12804, "MPL_TILE_TIMER" }, + { 12805, "TILE_TIMER_CONTROL" }, + { 13312, "MPL_IDN_TIMER_SET_0" }, + { 13313, "MPL_IDN_TIMER_SET_1" }, + { 13314, "MPL_IDN_TIMER_SET_2" }, + { 13315, "MPL_IDN_TIMER_SET_3" }, + { 13316, "MPL_IDN_TIMER" }, + { 13317, "IDN_DEADLOCK_COUNT" }, + { 13318, "IDN_DEADLOCK_TIMEOUT" }, + { 13824, "MPL_UDN_TIMER_SET_0" }, + { 13825, "MPL_UDN_TIMER_SET_1" }, + { 13826, "MPL_UDN_TIMER_SET_2" }, + { 13827, "MPL_UDN_TIMER_SET_3" }, + { 13828, "MPL_UDN_TIMER" }, + { 13829, "UDN_DEADLOCK_COUNT" }, + { 13830, "UDN_DEADLOCK_TIMEOUT" }, + { 14336, "MPL_DMA_NOTIFY_SET_0" }, + { 14337, "MPL_DMA_NOTIFY_SET_1" }, + { 14338, "MPL_DMA_NOTIFY_SET_2" }, + { 14339, "MPL_DMA_NOTIFY_SET_3" }, + { 14340, "MPL_DMA_NOTIFY" }, + { 14592, "DMA_BYTE" }, + { 14593, "DMA_CHUNK_SIZE" }, + { 14594, "DMA_CTR" }, + { 14595, "DMA_DST_ADDR" }, + { 14596, "DMA_DST_CHUNK_ADDR" }, + { 14597, "DMA_SRC_ADDR" }, + { 14598, "DMA_SRC_CHUNK_ADDR" }, + { 14599, "DMA_STRIDE" }, + { 14600, "DMA_USER_STATUS" }, + { 14848, "MPL_IDN_CA_SET_0" }, + { 14849, "MPL_IDN_CA_SET_1" }, + { 14850, "MPL_IDN_CA_SET_2" }, + { 14851, "MPL_IDN_CA_SET_3" }, + { 14852, "MPL_IDN_CA" }, + { 15360, "MPL_UDN_CA_SET_0" }, + { 15361, "MPL_UDN_CA_SET_1" }, + { 15362, "MPL_UDN_CA_SET_2" }, + { 15363, "MPL_UDN_CA_SET_3" }, + { 15364, "MPL_UDN_CA" }, + { 15872, "MPL_IDN_AVAIL_SET_0" }, + { 15873, "MPL_IDN_AVAIL_SET_1" }, + { 15874, "MPL_IDN_AVAIL_SET_2" }, + { 15875, "MPL_IDN_AVAIL_SET_3" }, + { 15876, "MPL_IDN_AVAIL" }, + { 15877, "IDN_AVAIL_EN" }, + { 16384, "MPL_UDN_AVAIL_SET_0" }, + { 16385, "MPL_UDN_AVAIL_SET_1" }, + { 16386, "MPL_UDN_AVAIL_SET_2" }, + { 16387, "MPL_UDN_AVAIL_SET_3" }, + { 16388, "MPL_UDN_AVAIL" }, + { 16389, "UDN_AVAIL_EN" }, + { 16896, "MPL_PERF_COUNT_SET_0" }, + { 16897, "MPL_PERF_COUNT_SET_1" }, + { 16898, "MPL_PERF_COUNT_SET_2" }, + { 16899, "MPL_PERF_COUNT_SET_3" }, + { 16900, "MPL_PERF_COUNT" }, + { 16901, "PERF_COUNT_0" }, + { 16902, "PERF_COUNT_1" }, + { 16903, "PERF_COUNT_CTL" }, + { 16904, "PERF_COUNT_STS" }, + { 16905, "WATCH_CTL" }, + { 16906, "WATCH_MASK" }, + { 16907, "WATCH_VAL" }, + { 16912, "PERF_COUNT_DN_CTL" }, + { 17408, "MPL_INTCTRL_3_SET_0" }, + { 17409, "MPL_INTCTRL_3_SET_1" }, + { 17410, "MPL_INTCTRL_3_SET_2" }, + { 17411, "MPL_INTCTRL_3_SET_3" }, + { 17412, "MPL_INTCTRL_3" }, + { 17413, "EX_CONTEXT_3_0" }, + { 17414, "EX_CONTEXT_3_1" }, + { 17415, "INTERRUPT_MASK_3_0" }, + { 17416, "INTERRUPT_MASK_3_1" }, + { 17417, "INTERRUPT_MASK_RESET_3_0" }, + { 17418, "INTERRUPT_MASK_RESET_3_1" }, + { 17419, "INTERRUPT_MASK_SET_3_0" }, + { 17420, "INTERRUPT_MASK_SET_3_1" }, + { 17432, "INTCTRL_3_STATUS" }, + { 17664, "SYSTEM_SAVE_3_0" }, + { 17665, "SYSTEM_SAVE_3_1" }, + { 17666, "SYSTEM_SAVE_3_2" }, + { 17667, "SYSTEM_SAVE_3_3" }, + { 17920, "MPL_INTCTRL_2_SET_0" }, + { 17921, "MPL_INTCTRL_2_SET_1" }, + { 17922, "MPL_INTCTRL_2_SET_2" }, + { 17923, "MPL_INTCTRL_2_SET_3" }, + { 17924, "MPL_INTCTRL_2" }, + { 17925, "EX_CONTEXT_2_0" }, + { 17926, "EX_CONTEXT_2_1" }, + { 17927, "INTCTRL_2_STATUS" }, + { 17928, "INTERRUPT_MASK_2_0" }, + { 17929, "INTERRUPT_MASK_2_1" }, + { 17930, "INTERRUPT_MASK_RESET_2_0" }, + { 17931, "INTERRUPT_MASK_RESET_2_1" }, + { 17932, "INTERRUPT_MASK_SET_2_0" }, + { 17933, "INTERRUPT_MASK_SET_2_1" }, + { 18176, "SYSTEM_SAVE_2_0" }, + { 18177, "SYSTEM_SAVE_2_1" }, + { 18178, "SYSTEM_SAVE_2_2" }, + { 18179, "SYSTEM_SAVE_2_3" }, + { 18432, "MPL_INTCTRL_1_SET_0" }, + { 18433, "MPL_INTCTRL_1_SET_1" }, + { 18434, "MPL_INTCTRL_1_SET_2" }, + { 18435, "MPL_INTCTRL_1_SET_3" }, + { 18436, "MPL_INTCTRL_1" }, + { 18437, "EX_CONTEXT_1_0" }, + { 18438, "EX_CONTEXT_1_1" }, + { 18439, "INTCTRL_1_STATUS" }, + { 18440, "INTCTRL_3_STATUS_REV0" }, + { 18441, "INTERRUPT_MASK_1_0" }, + { 18442, "INTERRUPT_MASK_1_1" }, + { 18443, "INTERRUPT_MASK_RESET_1_0" }, + { 18444, "INTERRUPT_MASK_RESET_1_1" }, + { 18445, "INTERRUPT_MASK_SET_1_0" }, + { 18446, "INTERRUPT_MASK_SET_1_1" }, + { 18688, "SYSTEM_SAVE_1_0" }, + { 18689, "SYSTEM_SAVE_1_1" }, + { 18690, "SYSTEM_SAVE_1_2" }, + { 18691, "SYSTEM_SAVE_1_3" }, + { 18944, "MPL_INTCTRL_0_SET_0" }, + { 18945, "MPL_INTCTRL_0_SET_1" }, + { 18946, "MPL_INTCTRL_0_SET_2" }, + { 18947, "MPL_INTCTRL_0_SET_3" }, + { 18948, "MPL_INTCTRL_0" }, + { 18949, "EX_CONTEXT_0_0" }, + { 18950, "EX_CONTEXT_0_1" }, + { 18951, "INTCTRL_0_STATUS" }, + { 18952, "INTERRUPT_MASK_0_0" }, + { 18953, "INTERRUPT_MASK_0_1" }, + { 18954, "INTERRUPT_MASK_RESET_0_0" }, + { 18955, "INTERRUPT_MASK_RESET_0_1" }, + { 18956, "INTERRUPT_MASK_SET_0_0" }, + { 18957, "INTERRUPT_MASK_SET_0_1" }, + { 19200, "SYSTEM_SAVE_0_0" }, + { 19201, "SYSTEM_SAVE_0_1" }, + { 19202, "SYSTEM_SAVE_0_2" }, + { 19203, "SYSTEM_SAVE_0_3" }, + { 19456, "MPL_BOOT_ACCESS_SET_0" }, + { 19457, "MPL_BOOT_ACCESS_SET_1" }, + { 19458, "MPL_BOOT_ACCESS_SET_2" }, + { 19459, "MPL_BOOT_ACCESS_SET_3" }, + { 19460, "MPL_BOOT_ACCESS" }, + { 19461, "CBOX_CACHEASRAM_CONFIG" }, + { 19462, "CBOX_CACHE_CONFIG" }, + { 19463, "CBOX_MMAP_0" }, + { 19464, "CBOX_MMAP_1" }, + { 19465, "CBOX_MMAP_2" }, + { 19466, "CBOX_MMAP_3" }, + { 19467, "CBOX_MSR" }, + { 19468, "CBOX_SRC_ID" }, + { 19469, "CYCLE_HIGH_MODIFY" }, + { 19470, "CYCLE_LOW_MODIFY" }, + { 19471, "DIAG_BCST_CTL" }, + { 19472, "DIAG_BCST_MASK" }, + { 19473, "DIAG_BCST_TRIGGER" }, + { 19474, "DIAG_MUX_CTL" }, + { 19475, "DIAG_TRACE_CTL" }, + { 19476, "DIAG_TRACE_STS" }, + { 19477, "IDN_DEMUX_BUF_THRESH" }, + { 19478, "SBOX_CONFIG" }, + { 19479, "TILE_COORD" }, + { 19480, "UDN_DEMUX_BUF_THRESH" }, + { 19481, "CBOX_HOME_MAP_ADDR" }, + { 19482, "CBOX_HOME_MAP_DATA" }, + { 19483, "CBOX_MSR1" }, + { 19484, "BIG_ENDIAN_CONFIG" }, + { 19485, "MEM_STRIPE_CONFIG" }, + { 19486, "DIAG_TRACE_WAY" }, + { 19487, "VDN_SNOOP_SHIM_CTL" }, + { 19488, "PERF_COUNT_PLS" }, + { 19489, "DIAG_TRACE_DATA" }, + { 19712, "I_AER_0" }, + { 19713, "I_AER_1" }, + { 19714, "I_PHYSICAL_MEMORY_MODE" }, + { 19968, "MPL_WORLD_ACCESS_SET_0" }, + { 19969, "MPL_WORLD_ACCESS_SET_1" }, + { 19970, "MPL_WORLD_ACCESS_SET_2" }, + { 19971, "MPL_WORLD_ACCESS_SET_3" }, + { 19972, "MPL_WORLD_ACCESS" }, + { 19973, "SIM_SOCKET" }, + { 19974, "CYCLE_HIGH" }, + { 19975, "CYCLE_LOW" }, + { 19976, "DONE" }, + { 19977, "FAIL" }, + { 19978, "INTERRUPT_CRITICAL_SECTION" }, + { 19979, "PASS" }, + { 19980, "SIM_CONTROL" }, + { 19981, "EVENT_BEGIN" }, + { 19982, "EVENT_END" }, + { 19983, "TILE_WRITE_PENDING" }, + { 19984, "TILE_RTF_HWM" }, + { 20224, "PROC_STATUS" }, + { 20225, "STATUS_SATURATE" }, + { 20480, "MPL_I_ASID_SET_0" }, + { 20481, "MPL_I_ASID_SET_1" }, + { 20482, "MPL_I_ASID_SET_2" }, + { 20483, "MPL_I_ASID_SET_3" }, + { 20484, "MPL_I_ASID" }, + { 20485, "I_ASID" }, + { 20992, "MPL_D_ASID_SET_0" }, + { 20993, "MPL_D_ASID_SET_1" }, + { 20994, "MPL_D_ASID_SET_2" }, + { 20995, "MPL_D_ASID_SET_3" }, + { 20996, "MPL_D_ASID" }, + { 20997, "D_ASID" }, + { 21504, "MPL_DMA_ASID_SET_0" }, + { 21505, "MPL_DMA_ASID_SET_1" }, + { 21506, "MPL_DMA_ASID_SET_2" }, + { 21507, "MPL_DMA_ASID_SET_3" }, + { 21508, "MPL_DMA_ASID" }, + { 21509, "DMA_ASID" }, + { 22016, "MPL_SNI_ASID_SET_0" }, + { 22017, "MPL_SNI_ASID_SET_1" }, + { 22018, "MPL_SNI_ASID_SET_2" }, + { 22019, "MPL_SNI_ASID_SET_3" }, + { 22020, "MPL_SNI_ASID" }, + { 22021, "SNI_ASID" }, + { 22528, "MPL_DMA_CPL_SET_0" }, + { 22529, "MPL_DMA_CPL_SET_1" }, + { 22530, "MPL_DMA_CPL_SET_2" }, + { 22531, "MPL_DMA_CPL_SET_3" }, + { 22532, "MPL_DMA_CPL" }, + { 23040, "MPL_SN_CPL_SET_0" }, + { 23041, "MPL_SN_CPL_SET_1" }, + { 23042, "MPL_SN_CPL_SET_2" }, + { 23043, "MPL_SN_CPL_SET_3" }, + { 23044, "MPL_SN_CPL" }, + { 23552, "MPL_DOUBLE_FAULT_SET_0" }, + { 23553, "MPL_DOUBLE_FAULT_SET_1" }, + { 23554, "MPL_DOUBLE_FAULT_SET_2" }, + { 23555, "MPL_DOUBLE_FAULT_SET_3" }, + { 23556, "MPL_DOUBLE_FAULT" }, + { 23557, "LAST_INTERRUPT_REASON" }, + { 24064, "MPL_SN_STATIC_ACCESS_SET_0" }, + { 24065, "MPL_SN_STATIC_ACCESS_SET_1" }, + { 24066, "MPL_SN_STATIC_ACCESS_SET_2" }, + { 24067, "MPL_SN_STATIC_ACCESS_SET_3" }, + { 24068, "MPL_SN_STATIC_ACCESS" }, + { 24069, "SN_STATIC_CTL" }, + { 24070, "SN_STATIC_FIFO_DATA" }, + { 24071, "SN_STATIC_FIFO_SEL" }, + { 24073, "SN_STATIC_ISTATE" }, + { 24074, "SN_STATIC_OSTATE" }, + { 24076, "SN_STATIC_STATIC" }, + { 24320, "SN_STATIC_DATA_AVAIL" }, + { 24576, "MPL_AUX_PERF_COUNT_SET_0" }, + { 24577, "MPL_AUX_PERF_COUNT_SET_1" }, + { 24578, "MPL_AUX_PERF_COUNT_SET_2" }, + { 24579, "MPL_AUX_PERF_COUNT_SET_3" }, + { 24580, "MPL_AUX_PERF_COUNT" }, + { 24581, "AUX_PERF_COUNT_0" }, + { 24582, "AUX_PERF_COUNT_1" }, + { 24583, "AUX_PERF_COUNT_CTL" }, + { 24584, "AUX_PERF_COUNT_STS" }, +}; + +const int tile_num_sprs = 499; + + + + +/* Canonical name of each register. */ +const char *const tile_register_names[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", + "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", + "r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr", + "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero" +}; + + +/* Given a set of bundle bits and the lookup FSM for a specific pipe, + * returns which instruction the bundle contains in that pipe. + */ +static const struct tile_opcode * +find_opcode(tile_bundle_bits bits, const unsigned short *table) +{ + int index = 0; + + while (1) + { + unsigned short bitspec = table[index]; + unsigned int bitfield = + ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6); + + unsigned short next = table[index + 1 + bitfield]; + if (next <= TILE_OPC_NONE) + return &tile_opcodes[next]; + + index = next - TILE_OPC_NONE; + } +} + + +int +parse_insn_tile(tile_bundle_bits bits, + unsigned int pc, + struct tile_decoded_instruction + decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]) +{ + int num_instructions = 0; + int pipe; + + int min_pipe, max_pipe; + if ((bits & TILE_BUNDLE_Y_ENCODING_MASK) == 0) + { + min_pipe = TILE_PIPELINE_X0; + max_pipe = TILE_PIPELINE_X1; + } + else + { + min_pipe = TILE_PIPELINE_Y0; + max_pipe = TILE_PIPELINE_Y2; + } + + /* For each pipe, find an instruction that fits. */ + for (pipe = min_pipe; pipe <= max_pipe; pipe++) + { + const struct tile_opcode *opc; + struct tile_decoded_instruction *d; + int i; + + d = &decoded[num_instructions++]; + opc = find_opcode (bits, tile_bundle_decoder_fsms[pipe]); + d->opcode = opc; + + /* Decode each operand, sign extending, etc. as appropriate. */ + for (i = 0; i < opc->num_operands; i++) + { + const struct tile_operand *op = + &tile_operands[opc->operands[pipe][i]]; + int opval = op->extract (bits); + if (op->is_signed) + { + /* Sign-extend the operand. */ + int shift = (int)((sizeof(int) * 8) - op->num_bits); + opval = (opval << shift) >> shift; + } + + /* Adjust PC-relative scaled branch offsets. */ + if (op->type == TILE_OP_TYPE_ADDRESS) + { + opval *= TILE_BUNDLE_SIZE_IN_BYTES; + opval += (int)pc; + } + + /* Record the final value. */ + d->operands[i] = op; + d->operand_values[i] = opval; + } + } + + return num_instructions; +} diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c new file mode 100644 index 000000000000..47500a324e32 --- /dev/null +++ b/arch/tile/kernel/time.c @@ -0,0 +1,220 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Support the cycle counter clocksource and tile timer clock event device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Define the cycle counter clock source. + */ + +/* How many cycles per second we are running at. */ +static cycles_t cycles_per_sec __write_once; + +/* + * We set up shift and multiply values with a minsec of five seconds, + * since our timer counter counts down 31 bits at a frequency of + * no less than 500 MHz. See @minsec for clocks_calc_mult_shift(). + * We could use a different value for the 64-bit free-running + * cycle counter, but we use the same one for consistency, and since + * we will be reasonably precise with this value anyway. + */ +#define TILE_MINSEC 5 + +cycles_t get_clock_rate() +{ + return cycles_per_sec; +} + +#if CHIP_HAS_SPLIT_CYCLE() +cycles_t get_cycles() +{ + unsigned int high = __insn_mfspr(SPR_CYCLE_HIGH); + unsigned int low = __insn_mfspr(SPR_CYCLE_LOW); + unsigned int high2 = __insn_mfspr(SPR_CYCLE_HIGH); + + while (unlikely(high != high2)) { + low = __insn_mfspr(SPR_CYCLE_LOW); + high = high2; + high2 = __insn_mfspr(SPR_CYCLE_HIGH); + } + + return (((cycles_t)high) << 32) | low; +} +#endif + +cycles_t clocksource_get_cycles(struct clocksource *cs) +{ + return get_cycles(); +} + +static struct clocksource cycle_counter_cs = { + .name = "cycle counter", + .rating = 300, + .read = clocksource_get_cycles, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +/* + * Called very early from setup_arch() to set cycles_per_sec. + * We initialize it early so we can use it to set up loops_per_jiffy. + */ +void __init setup_clock(void) +{ + cycles_per_sec = hv_sysconf(HV_SYSCONF_CPU_SPEED); + clocksource_calc_mult_shift(&cycle_counter_cs, cycles_per_sec, + TILE_MINSEC); +} + +void __init calibrate_delay(void) +{ + loops_per_jiffy = get_clock_rate() / HZ; + pr_info("Clock rate yields %lu.%02lu BogoMIPS (lpj=%lu)\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); +} + +/* Called fairly late in init/main.c, but before we go smp. */ +void __init time_init(void) +{ + /* Initialize and register the clock source. */ + clocksource_register(&cycle_counter_cs); + + /* Start up the tile-timer interrupt source on the boot cpu. */ + setup_tile_timer(); +} + + +/* + * Define the tile timer clock event device. The timer is driven by + * the TILE_TIMER_CONTROL register, which consists of a 31-bit down + * counter, plus bit 31, which signifies that the counter has wrapped + * from zero to (2**31) - 1. The INT_TILE_TIMER interrupt will be + * raised as long as bit 31 is set. + */ + +#define MAX_TICK 0x7fffffff /* we have 31 bits of countdown timer */ + +static int tile_timer_set_next_event(unsigned long ticks, + struct clock_event_device *evt) +{ + BUG_ON(ticks > MAX_TICK); + __insn_mtspr(SPR_TILE_TIMER_CONTROL, ticks); + raw_local_irq_unmask_now(INT_TILE_TIMER); + return 0; +} + +/* + * Whenever anyone tries to change modes, we just mask interrupts + * and wait for the next event to get set. + */ +static void tile_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + raw_local_irq_mask_now(INT_TILE_TIMER); +} + +/* + * Set min_delta_ns to 1 microsecond, since it takes about + * that long to fire the interrupt. + */ +static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { + .name = "tile timer", + .features = CLOCK_EVT_FEAT_ONESHOT, + .min_delta_ns = 1000, + .rating = 100, + .irq = -1, + .set_next_event = tile_timer_set_next_event, + .set_mode = tile_timer_set_mode, +}; + +void __cpuinit setup_tile_timer(void) +{ + struct clock_event_device *evt = &__get_cpu_var(tile_timer); + + /* Fill in fields that are speed-specific. */ + clockevents_calc_mult_shift(evt, cycles_per_sec, TILE_MINSEC); + evt->max_delta_ns = clockevent_delta2ns(MAX_TICK, evt); + + /* Mark as being for this cpu only. */ + evt->cpumask = cpumask_of(smp_processor_id()); + + /* Start out with timer not firing. */ + raw_local_irq_mask_now(INT_TILE_TIMER); + + /* Register tile timer. */ + clockevents_register_device(evt); +} + +/* Called from the interrupt vector. */ +void do_timer_interrupt(struct pt_regs *regs, int fault_num) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + struct clock_event_device *evt = &__get_cpu_var(tile_timer); + + /* + * Mask the timer interrupt here, since we are a oneshot timer + * and there are now by definition no events pending. + */ + raw_local_irq_mask(INT_TILE_TIMER); + + /* Track time spent here in an interrupt context */ + irq_enter(); + + /* Track interrupt count. */ + __get_cpu_var(irq_stat).irq_timer_count++; + + /* Call the generic timer handler */ + evt->event_handler(evt); + + /* + * Track time spent against the current process again and + * process any softirqs if they are waiting. + */ + irq_exit(); + + set_irq_regs(old_regs); +} + +/* + * Scheduler clock - returns current time in nanosec units. + * Note that with LOCKDEP, this is called during lockdep_init(), and + * we will claim that sched_clock() is zero for a little while, until + * we run setup_clock(), above. + */ +unsigned long long sched_clock(void) +{ + return clocksource_cyc2ns(get_cycles(), + cycle_counter_cs.mult, + cycle_counter_cs.shift); +} + +int setup_profiling_timer(unsigned int multiplier) +{ + return -EINVAL; +} diff --git a/arch/tile/kernel/tlb.c b/arch/tile/kernel/tlb.c new file mode 100644 index 000000000000..2dffc1044d83 --- /dev/null +++ b/arch/tile/kernel/tlb.c @@ -0,0 +1,97 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include + +/* From tlbflush.h */ +DEFINE_PER_CPU(int, current_asid); +int min_asid, max_asid; + +/* + * Note that we flush the L1I (for VM_EXEC pages) as well as the TLB + * so that when we are unmapping an executable page, we also flush it. + * Combined with flushing the L1I at context switch time, this means + * we don't have to do any other icache flushes. + */ + +void flush_tlb_mm(struct mm_struct *mm) +{ + HV_Remote_ASID asids[NR_CPUS]; + int i = 0, cpu; + for_each_cpu(cpu, &mm->cpu_vm_mask) { + HV_Remote_ASID *asid = &asids[i++]; + asid->y = cpu / smp_topology.width; + asid->x = cpu % smp_topology.width; + asid->asid = per_cpu(current_asid, cpu); + } + flush_remote(0, HV_FLUSH_EVICT_L1I, &mm->cpu_vm_mask, + 0, 0, 0, NULL, asids, i); +} + +void flush_tlb_current_task(void) +{ + flush_tlb_mm(current->mm); +} + +void flush_tlb_page_mm(const struct vm_area_struct *vma, struct mm_struct *mm, + unsigned long va) +{ + unsigned long size = hv_page_size(vma); + int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; + flush_remote(0, cache, &mm->cpu_vm_mask, + va, size, size, &mm->cpu_vm_mask, NULL, 0); +} + +void flush_tlb_page(const struct vm_area_struct *vma, unsigned long va) +{ + flush_tlb_page_mm(vma, vma->vm_mm, va); +} +EXPORT_SYMBOL(flush_tlb_page); + +void flush_tlb_range(const struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + unsigned long size = hv_page_size(vma); + struct mm_struct *mm = vma->vm_mm; + int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; + flush_remote(0, cache, &mm->cpu_vm_mask, start, end - start, size, + &mm->cpu_vm_mask, NULL, 0); +} + +void flush_tlb_all(void) +{ + int i; + for (i = 0; ; ++i) { + HV_VirtAddrRange r = hv_inquire_virtual(i); + if (r.size == 0) + break; + flush_remote(0, HV_FLUSH_EVICT_L1I, cpu_online_mask, + r.start, r.size, PAGE_SIZE, cpu_online_mask, + NULL, 0); + flush_remote(0, 0, NULL, + r.start, r.size, HPAGE_SIZE, cpu_online_mask, + NULL, 0); + } +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + flush_remote(0, HV_FLUSH_EVICT_L1I, cpu_online_mask, + start, end - start, PAGE_SIZE, cpu_online_mask, NULL, 0); +} diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c new file mode 100644 index 000000000000..12cb10f38527 --- /dev/null +++ b/arch/tile/kernel/traps.c @@ -0,0 +1,237 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +void __init trap_init(void) +{ + /* Nothing needed here since we link code at .intrpt1 */ +} + +int unaligned_fixup = 1; + +static int __init setup_unaligned_fixup(char *str) +{ + /* + * Say "=-1" to completely disable it. If you just do "=0", we + * will still parse the instruction, then fire a SIGBUS with + * the correct address from inside the single_step code. + */ + long val; + if (strict_strtol(str, 0, &val) != 0) + return 0; + unaligned_fixup = val; + printk("Fixups for unaligned data accesses are %s\n", + unaligned_fixup >= 0 ? + (unaligned_fixup ? "enabled" : "disabled") : + "completely disabled"); + return 1; +} +__setup("unaligned_fixup=", setup_unaligned_fixup); + +#if CHIP_HAS_TILE_DMA() + +static int dma_disabled; + +static int __init nodma(char *str) +{ + printk("User-space DMA is disabled\n"); + dma_disabled = 1; + return 1; +} +__setup("nodma", nodma); + +/* How to decode SPR_GPV_REASON */ +#define IRET_ERROR (1U << 31) +#define MT_ERROR (1U << 30) +#define MF_ERROR (1U << 29) +#define SPR_INDEX ((1U << 15) - 1) +#define SPR_MPL_SHIFT 9 /* starting bit position for MPL encoded in SPR */ + +/* + * See if this GPV is just to notify the kernel of SPR use and we can + * retry the user instruction after adjusting some MPLs suitably. + */ +static int retry_gpv(unsigned int gpv_reason) +{ + int mpl; + + if (gpv_reason & IRET_ERROR) + return 0; + + BUG_ON((gpv_reason & (MT_ERROR|MF_ERROR)) == 0); + mpl = (gpv_reason & SPR_INDEX) >> SPR_MPL_SHIFT; + if (mpl == INT_DMA_NOTIFY && !dma_disabled) { + /* User is turning on DMA. Allow it and retry. */ + printk(KERN_DEBUG "Process %d/%s is now enabled for DMA\n", + current->pid, current->comm); + BUG_ON(current->thread.tile_dma_state.enabled); + current->thread.tile_dma_state.enabled = 1; + grant_dma_mpls(); + return 1; + } + + return 0; +} + +#endif /* CHIP_HAS_TILE_DMA() */ + +/* Defined inside do_trap(), below. */ +#ifdef __tilegx__ +extern tilegx_bundle_bits bpt_code; +#else +extern tile_bundle_bits bpt_code; +#endif + +void __kprobes do_trap(struct pt_regs *regs, int fault_num, + unsigned long reason) +{ + siginfo_t info = { 0 }; + int signo, code; + unsigned long address; + __typeof__(bpt_code) instr; + + /* Re-enable interrupts. */ + local_irq_enable(); + + /* + * If it hits in kernel mode and we can't fix it up, just exit the + * current process and hope for the best. + */ + if (!user_mode(regs)) { + if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */ + return; + printk(KERN_ALERT "Kernel took bad trap %d at PC %#lx\n", + fault_num, regs->pc); + if (fault_num == INT_GPV) + printk(KERN_ALERT "GPV_REASON is %#lx\n", reason); + show_regs(regs); + do_exit(SIGKILL); /* FIXME: implement i386 die() */ + return; + } + + switch (fault_num) { + case INT_ILL: + asm(".pushsection .rodata.bpt_code,\"a\";" + ".align 8;" + "bpt_code: bpt;" + ".size bpt_code,.-bpt_code;" + ".popsection"); + + if (copy_from_user(&instr, (void *)regs->pc, sizeof(instr))) { + printk(KERN_ERR "Unreadable instruction for INT_ILL:" + " %#lx\n", regs->pc); + do_exit(SIGKILL); + return; + } + if (instr == bpt_code) { + signo = SIGTRAP; + code = TRAP_BRKPT; + } else { + signo = SIGILL; + code = ILL_ILLOPC; + } + address = regs->pc; + break; + case INT_GPV: +#if CHIP_HAS_TILE_DMA() + if (retry_gpv(reason)) + return; +#endif + /*FALLTHROUGH*/ + case INT_UDN_ACCESS: + case INT_IDN_ACCESS: +#if CHIP_HAS_SN() + case INT_SN_ACCESS: +#endif + signo = SIGILL; + code = ILL_PRVREG; + address = regs->pc; + break; + case INT_SWINT_3: + case INT_SWINT_2: + case INT_SWINT_0: + signo = SIGILL; + code = ILL_ILLTRP; + address = regs->pc; + break; + case INT_UNALIGN_DATA: +#ifndef __tilegx__ /* FIXME: GX: no single-step yet */ + if (unaligned_fixup >= 0) { + struct single_step_state *state = + current_thread_info()->step_state; + if (!state || (void *)(regs->pc) != state->buffer) { + single_step_once(regs); + return; + } + } +#endif + signo = SIGBUS; + code = BUS_ADRALN; + address = 0; + break; + case INT_DOUBLE_FAULT: + /* + * For double fault, "reason" is actually passed as + * SYSTEM_SAVE_1_2, the hypervisor's double-fault info, so + * we can provide the original fault number rather than + * the uninteresting "INT_DOUBLE_FAULT" so the user can + * learn what actually struck while PL0 ICS was set. + */ + fault_num = reason; + signo = SIGILL; + code = ILL_DBLFLT; + address = regs->pc; + break; +#ifdef __tilegx__ + case INT_ILL_TRANS: + signo = SIGSEGV; + code = SEGV_MAPERR; + if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK) + address = regs->pc; + else + address = 0; /* FIXME: GX: single-step for address */ + break; +#endif + default: + panic("Unexpected do_trap interrupt number %d", fault_num); + return; + } + + info.si_signo = signo; + info.si_code = code; + info.si_addr = (void *)address; + if (signo == SIGILL) + info.si_trapno = fault_num; + force_sig_info(signo, &info, current); +} + +extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52); + +void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) +{ + _dump_stack(dummy, pc, lr, sp, r52); + printk("Double fault: exiting\n"); + machine_halt(); +} diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..77388c1415bd --- /dev/null +++ b/arch/tile/kernel/vmlinux.lds.S @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +/* Text loads starting from the supervisor interrupt vector address. */ +#define TEXT_OFFSET MEM_SV_INTRPT + +OUTPUT_ARCH(tile) +ENTRY(_start) +jiffies = jiffies_64; + +PHDRS +{ + intrpt1 PT_LOAD ; + text PT_LOAD ; + data PT_LOAD ; +} +SECTIONS +{ + /* Text is loaded with a different VA than data; start with text. */ + #undef LOAD_OFFSET + #define LOAD_OFFSET TEXT_OFFSET + + /* Interrupt vectors */ + .intrpt1 (LOAD_OFFSET) : AT ( 0 ) /* put at the start of physical memory */ + { + _text = .; + _stext = .; + *(.intrpt1) + } :intrpt1 =0 + + /* Hypervisor call vectors */ + #include "hvglue.lds" + + /* Now the real code */ + . = ALIGN(0x20000); + HEAD_TEXT_SECTION :text =0 + .text : AT (ADDR(.text) - LOAD_OFFSET) { + SCHED_TEXT + LOCK_TEXT + __fix_text_end = .; /* tile-cpack won't rearrange before this */ + TEXT_TEXT + *(.text.*) + *(.coldtext*) + *(.fixup) + *(.gnu.warning) + } + _etext = .; + + /* "Init" is divided into two areas with very different virtual addresses. */ + INIT_TEXT_SECTION(PAGE_SIZE) + + /* Now we skip back to PAGE_OFFSET for the data. */ + . = (. - TEXT_OFFSET + PAGE_OFFSET); + #undef LOAD_OFFSET + #define LOAD_OFFSET PAGE_OFFSET + + . = ALIGN(PAGE_SIZE); + VMLINUX_SYMBOL(_sinitdata) = .; + .init.page : AT (ADDR(.init.page) - LOAD_OFFSET) { + *(.init.page) + } :data =0 + INIT_DATA_SECTION(16) + PERCPU(PAGE_SIZE) + . = ALIGN(PAGE_SIZE); + VMLINUX_SYMBOL(_einitdata) = .; + + _sdata = .; /* Start of data section */ + + RO_DATA_SECTION(PAGE_SIZE) + + /* initially writeable, then read-only */ + . = ALIGN(PAGE_SIZE); + __w1data_begin = .; + .w1data : AT(ADDR(.w1data) - LOAD_OFFSET) { + VMLINUX_SYMBOL(__w1data_begin) = .; + *(.w1data) + VMLINUX_SYMBOL(__w1data_end) = .; + } + + RW_DATA_SECTION(L2_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) + + _edata = .; + + EXCEPTION_TABLE(L2_CACHE_BYTES) + NOTES + + + BSS_SECTION(8, PAGE_SIZE, 1) + _end = . ; + + STABS_DEBUG + DWARF_DEBUG + + DISCARDS +} diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile new file mode 100644 index 000000000000..ea9c209d33fb --- /dev/null +++ b/arch/tile/lib/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for TILE-specific library files.. +# + +lib-y = checksum.o cpumask.o delay.o __invalidate_icache.o \ + mb_incoherent.o uaccess.o \ + memcpy_$(BITS).o memchr_$(BITS).o memmove_$(BITS).o memset_$(BITS).o \ + strchr_$(BITS).o strlen_$(BITS).o + +ifneq ($(CONFIG_TILEGX),y) +lib-y += atomic_32.o atomic_asm_32.o memcpy_tile64.o +endif + +lib-$(CONFIG_SMP) += spinlock_$(BITS).o usercopy_$(BITS).o + +obj-$(CONFIG_MODULES) += exports.o diff --git a/arch/tile/lib/__invalidate_icache.S b/arch/tile/lib/__invalidate_icache.S new file mode 100644 index 000000000000..92e705059127 --- /dev/null +++ b/arch/tile/lib/__invalidate_icache.S @@ -0,0 +1,106 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * A routine for synchronizing the instruction and data caches. + * Useful for self-modifying code. + * + * r0 holds the buffer address + * r1 holds the size in bytes + */ + +#include +#include + +#if defined(__NEWLIB__) || defined(__BME__) +#include +#else +#include +#endif + +#ifdef __tilegx__ +/* Share code among Tile family chips but adjust opcodes appropriately. */ +#define slt cmpltu +#define bbst blbst +#define bnezt bnzt +#endif + +#if defined(__tilegx__) && __SIZEOF_POINTER__ == 4 +/* Force 32-bit ops so pointers wrap around appropriately. */ +#define ADD_PTR addx +#define ADDI_PTR addxi +#else +#define ADD_PTR add +#define ADDI_PTR addi +#endif + + .section .text.__invalidate_icache, "ax" + .global __invalidate_icache + .type __invalidate_icache,@function + .hidden __invalidate_icache + .align 8 +__invalidate_icache: + FEEDBACK_ENTER(__invalidate_icache) + { + ADD_PTR r1, r0, r1 /* end of buffer */ + blez r1, .Lexit /* skip out if size <= 0 */ + } + { + ADDI_PTR r1, r1, -1 /* point to last byte to flush */ + andi r0, r0, -CHIP_L1I_LINE_SIZE() /* align to cache-line size */ + } + { + andi r1, r1, -CHIP_L1I_LINE_SIZE() /* last cache line to flush */ + mf + } +#if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE + { + moveli r4, CHIP_L1I_CACHE_SIZE() / PAGE_SIZE /* loop counter */ + move r2, r0 /* remember starting address */ + } +#endif + drain + { + slt r3, r0, r1 /* set up loop invariant */ +#if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE + moveli r6, PAGE_SIZE +#endif + } +.Lentry: + { + icoh r0 + ADDI_PTR r0, r0, CHIP_L1I_LINE_SIZE() /* advance buffer */ + } + { + slt r3, r0, r1 /* check if buffer < buffer + size */ + bbst r3, .Lentry /* loop if buffer < buffer + size */ + } +#if CHIP_L1I_CACHE_SIZE() > PAGE_SIZE + { + ADD_PTR r2, r2, r6 + ADD_PTR r1, r1, r6 + } + { + move r0, r2 + addi r4, r4, -1 + } + { + slt r3, r0, r1 /* set up loop invariant */ + bnezt r4, .Lentry + } +#endif + drain +.Lexit: + jrp lr + +.Lend___invalidate_icache: + .size __invalidate_icache, \ + .Lend___invalidate_icache - __invalidate_icache diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c new file mode 100644 index 000000000000..be1e8acd105d --- /dev/null +++ b/arch/tile/lib/atomic_32.c @@ -0,0 +1,347 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* The routines in atomic_asm.S are private, so we only declare them here. */ +extern struct __get_user __atomic_cmpxchg(volatile int *p, + int *lock, int o, int n); +extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n); +extern struct __get_user __atomic_xchg_add(volatile int *p, int *lock, int n); +extern struct __get_user __atomic_xchg_add_unless(volatile int *p, + int *lock, int o, int n); +extern struct __get_user __atomic_or(volatile int *p, int *lock, int n); +extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n); +extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n); + +extern u64 __atomic64_cmpxchg(volatile u64 *p, int *lock, u64 o, u64 n); +extern u64 __atomic64_xchg(volatile u64 *p, int *lock, u64 n); +extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n); +extern u64 __atomic64_xchg_add_unless(volatile u64 *p, + int *lock, u64 o, u64 n); + + +/* See */ +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + +/* + * A block of memory containing locks for atomic ops. Each instance of this + * struct will be homed on a different CPU. + */ +struct atomic_locks_on_cpu { + int lock[ATOMIC_HASH_L2_SIZE]; +} __attribute__((aligned(ATOMIC_HASH_L2_SIZE * 4))); + +static DEFINE_PER_CPU(struct atomic_locks_on_cpu, atomic_lock_pool); + +/* The locks we'll use until __init_atomic_per_cpu is called. */ +static struct atomic_locks_on_cpu __initdata initial_atomic_locks; + +/* Hash into this vector to get a pointer to lock for the given atomic. */ +struct atomic_locks_on_cpu *atomic_lock_ptr[ATOMIC_HASH_L1_SIZE] + __write_once = { + [0 ... ATOMIC_HASH_L1_SIZE-1] (&initial_atomic_locks) +}; + +#else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + +/* This page is remapped on startup to be hash-for-home. */ +int atomic_locks[PAGE_SIZE / sizeof(int) /* Only ATOMIC_HASH_SIZE is used */] + __attribute__((aligned(PAGE_SIZE), section(".bss.page_aligned"))); + +#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + +static inline int *__atomic_hashed_lock(volatile void *v) +{ + /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec.S */ +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + unsigned long i = + (unsigned long) v & ((PAGE_SIZE-1) & -sizeof(long long)); + unsigned long n = __insn_crc32_32(0, i); + + /* Grab high bits for L1 index. */ + unsigned long l1_index = n >> ((sizeof(n) * 8) - ATOMIC_HASH_L1_SHIFT); + /* Grab low bits for L2 index. */ + unsigned long l2_index = n & (ATOMIC_HASH_L2_SIZE - 1); + + return &atomic_lock_ptr[l1_index]->lock[l2_index]; +#else + /* + * Use bits [3, 3 + ATOMIC_HASH_SHIFT) as the lock index. + * Using mm works here because atomic_locks is page aligned. + */ + unsigned long ptr = __insn_mm((unsigned long)v >> 1, + (unsigned long)atomic_locks, + 2, (ATOMIC_HASH_SHIFT + 2) - 1); + return (int *)ptr; +#endif +} + +#ifdef CONFIG_SMP +/* Return whether the passed pointer is a valid atomic lock pointer. */ +static int is_atomic_lock(int *p) +{ +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + int i; + for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { + + if (p >= &atomic_lock_ptr[i]->lock[0] && + p < &atomic_lock_ptr[i]->lock[ATOMIC_HASH_L2_SIZE]) { + return 1; + } + } + return 0; +#else + return p >= &atomic_locks[0] && p < &atomic_locks[ATOMIC_HASH_SIZE]; +#endif +} + +void __atomic_fault_unlock(int *irqlock_word) +{ + BUG_ON(!is_atomic_lock(irqlock_word)); + BUG_ON(*irqlock_word != 1); + *irqlock_word = 0; +} + +#endif /* CONFIG_SMP */ + +static inline int *__atomic_setup(volatile void *v) +{ + /* Issue a load to the target to bring it into cache. */ + *(volatile int *)v; + return __atomic_hashed_lock(v); +} + +int _atomic_xchg(atomic_t *v, int n) +{ + return __atomic_xchg(&v->counter, __atomic_setup(v), n).val; +} +EXPORT_SYMBOL(_atomic_xchg); + +int _atomic_xchg_add(atomic_t *v, int i) +{ + return __atomic_xchg_add(&v->counter, __atomic_setup(v), i).val; +} +EXPORT_SYMBOL(_atomic_xchg_add); + +int _atomic_xchg_add_unless(atomic_t *v, int a, int u) +{ + /* + * Note: argument order is switched here since it is easier + * to use the first argument consistently as the "old value" + * in the assembly, as is done for _atomic_cmpxchg(). + */ + return __atomic_xchg_add_unless(&v->counter, __atomic_setup(v), u, a) + .val; +} +EXPORT_SYMBOL(_atomic_xchg_add_unless); + +int _atomic_cmpxchg(atomic_t *v, int o, int n) +{ + return __atomic_cmpxchg(&v->counter, __atomic_setup(v), o, n).val; +} +EXPORT_SYMBOL(_atomic_cmpxchg); + +unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask) +{ + return __atomic_or((int *)p, __atomic_setup(p), mask).val; +} +EXPORT_SYMBOL(_atomic_or); + +unsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask) +{ + return __atomic_andn((int *)p, __atomic_setup(p), mask).val; +} +EXPORT_SYMBOL(_atomic_andn); + +unsigned long _atomic_xor(volatile unsigned long *p, unsigned long mask) +{ + return __atomic_xor((int *)p, __atomic_setup(p), mask).val; +} +EXPORT_SYMBOL(_atomic_xor); + + +u64 _atomic64_xchg(atomic64_t *v, u64 n) +{ + return __atomic64_xchg(&v->counter, __atomic_setup(v), n); +} +EXPORT_SYMBOL(_atomic64_xchg); + +u64 _atomic64_xchg_add(atomic64_t *v, u64 i) +{ + return __atomic64_xchg_add(&v->counter, __atomic_setup(v), i); +} +EXPORT_SYMBOL(_atomic64_xchg_add); + +u64 _atomic64_xchg_add_unless(atomic64_t *v, u64 a, u64 u) +{ + /* + * Note: argument order is switched here since it is easier + * to use the first argument consistently as the "old value" + * in the assembly, as is done for _atomic_cmpxchg(). + */ + return __atomic64_xchg_add_unless(&v->counter, __atomic_setup(v), + u, a); +} +EXPORT_SYMBOL(_atomic64_xchg_add_unless); + +u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n) +{ + return __atomic64_cmpxchg(&v->counter, __atomic_setup(v), o, n); +} +EXPORT_SYMBOL(_atomic64_cmpxchg); + + +static inline int *__futex_setup(__user int *v) +{ + /* + * Issue a prefetch to the counter to bring it into cache. + * As for __atomic_setup, but we can't do a read into the L1 + * since it might fault; instead we do a prefetch into the L2. + */ + __insn_prefetch(v); + return __atomic_hashed_lock(v); +} + +struct __get_user futex_set(int *v, int i) +{ + return __atomic_xchg(v, __futex_setup(v), i); +} + +struct __get_user futex_add(int *v, int n) +{ + return __atomic_xchg_add(v, __futex_setup(v), n); +} + +struct __get_user futex_or(int *v, int n) +{ + return __atomic_or(v, __futex_setup(v), n); +} + +struct __get_user futex_andn(int *v, int n) +{ + return __atomic_andn(v, __futex_setup(v), n); +} + +struct __get_user futex_xor(int *v, int n) +{ + return __atomic_xor(v, __futex_setup(v), n); +} + +struct __get_user futex_cmpxchg(int *v, int o, int n) +{ + return __atomic_cmpxchg(v, __futex_setup(v), o, n); +} + +/* + * If any of the atomic or futex routines hit a bad address (not in + * the page tables at kernel PL) this routine is called. The futex + * routines are never used on kernel space, and the normal atomics and + * bitops are never used on user space. So a fault on kernel space + * must be fatal, but a fault on userspace is a futex fault and we + * need to return -EFAULT. Note that the context this routine is + * invoked in is the context of the "_atomic_xxx()" routines called + * by the functions in this file. + */ +struct __get_user __atomic_bad_address(int *addr) +{ + if (unlikely(!access_ok(VERIFY_WRITE, addr, sizeof(int)))) + panic("Bad address used for kernel atomic op: %p\n", addr); + return (struct __get_user) { .err = -EFAULT }; +} + + +#if CHIP_HAS_CBOX_HOME_MAP() +static int __init noatomichash(char *str) +{ + printk("noatomichash is deprecated.\n"); + return 1; +} +__setup("noatomichash", noatomichash); +#endif + +void __init __init_atomic_per_cpu(void) +{ +#if ATOMIC_LOCKS_FOUND_VIA_TABLE() + + unsigned int i; + int actual_cpu; + + /* + * Before this is called from setup, we just have one lock for + * all atomic objects/operations. Here we replace the + * elements of atomic_lock_ptr so that they point at per_cpu + * integers. This seemingly over-complex approach stems from + * the fact that DEFINE_PER_CPU defines an entry for each cpu + * in the grid, not each cpu from 0..ATOMIC_HASH_SIZE-1. But + * for efficient hashing of atomics to their locks we want a + * compile time constant power of 2 for the size of this + * table, so we use ATOMIC_HASH_SIZE. + * + * Here we populate atomic_lock_ptr from the per cpu + * atomic_lock_pool, interspersing by actual cpu so that + * subsequent elements are homed on consecutive cpus. + */ + + actual_cpu = cpumask_first(cpu_possible_mask); + + for (i = 0; i < ATOMIC_HASH_L1_SIZE; ++i) { + /* + * Preincrement to slightly bias against using cpu 0, + * which has plenty of stuff homed on it already. + */ + actual_cpu = cpumask_next(actual_cpu, cpu_possible_mask); + if (actual_cpu >= nr_cpu_ids) + actual_cpu = cpumask_first(cpu_possible_mask); + + atomic_lock_ptr[i] = &per_cpu(atomic_lock_pool, actual_cpu); + } + +#else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + + /* Validate power-of-two and "bigger than cpus" assumption */ + BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1)); + BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids); + + /* + * On TILEPro we prefer to use a single hash-for-home + * page, since this means atomic operations are less + * likely to encounter a TLB fault and thus should + * in general perform faster. You may wish to disable + * this in situations where few hash-for-home tiles + * are configured. + */ + BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0); + + /* The locks must all fit on one page. */ + BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE); + + /* + * We use the page offset of the atomic value's address as + * an index into atomic_locks, excluding the low 3 bits. + * That should not produce more indices than ATOMIC_HASH_SIZE. + */ + BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE); + +#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ + + /* The futex code makes this assumption, so we validate it here. */ + BUG_ON(sizeof(atomic_t) != sizeof(int)); +} diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S new file mode 100644 index 000000000000..c0d058578192 --- /dev/null +++ b/arch/tile/lib/atomic_asm_32.S @@ -0,0 +1,197 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Support routines for atomic operations. Each function takes: + * + * r0: address to manipulate + * r1: pointer to atomic lock guarding this operation (for FUTEX_LOCK_REG) + * r2: new value to write, or for cmpxchg/add_unless, value to compare against + * r3: (cmpxchg/xchg_add_unless) new value to write or add; + * (atomic64 ops) high word of value to write + * r4/r5: (cmpxchg64/add_unless64) new value to write or add + * + * The 32-bit routines return a "struct __get_user" so that the futex code + * has an opportunity to return -EFAULT to the user if needed. + * The 64-bit routines just return a "long long" with the value, + * since they are only used from kernel space and don't expect to fault. + * Support for 16-bit ops is included in the framework but we don't provide + * any (x86_64 has an atomic_inc_short(), so we might want to some day). + * + * Note that the caller is advised to issue a suitable L1 or L2 + * prefetch on the address being manipulated to avoid extra stalls. + * In addition, the hot path is on two icache lines, and we start with + * a jump to the second line to make sure they are both in cache so + * that we never stall waiting on icache fill while holding the lock. + * (This doesn't work out with most 64-bit ops, since they consume + * too many bundles, so may take an extra i-cache stall.) + * + * These routines set the INTERRUPT_CRITICAL_SECTION bit, just + * like sys_cmpxchg(), so that NMIs like PERF_COUNT will not interrupt + * the code, just page faults. + * + * If the load or store faults in a way that can be directly fixed in + * the do_page_fault_ics() handler (e.g. a vmalloc reference) we fix it + * directly, return to the instruction that faulted, and retry it. + * + * If the load or store faults in a way that potentially requires us + * to release the atomic lock, then retry (e.g. a migrating PTE), we + * reset the PC in do_page_fault_ics() to the "tns" instruction so + * that on return we will reacquire the lock and restart the op. We + * are somewhat overloading the exception_table_entry notion by doing + * this, since those entries are not normally used for migrating PTEs. + * + * If the main page fault handler discovers a bad address, it will see + * the PC pointing to the "tns" instruction (due to the earlier + * exception_table_entry processing in do_page_fault_ics), and + * re-reset the PC to the fault handler, atomic_bad_address(), which + * effectively takes over from the atomic op and can either return a + * bad "struct __get_user" (for user addresses) or can just panic (for + * bad kernel addresses). + * + * Note that if the value we would store is the same as what we + * loaded, we bypass the load. Other platforms with true atomics can + * make the guarantee that a non-atomic __clear_bit(), for example, + * can safely race with an atomic test_and_set_bit(); this example is + * from bit_spinlock.h in slub_lock() / slub_unlock(). We can't do + * that on Tile since the "atomic" op is really just a + * read/modify/write, and can race with the non-atomic + * read/modify/write. However, if we can short-circuit the write when + * it is not needed, in the atomic case, we avoid the race. + */ + +#include +#include +#include +#include + + .section .text.atomic,"ax" +ENTRY(__start_atomic_asm_code) + + .macro atomic_op, name, bitwidth, body + .align 64 +STD_ENTRY_SECTION(__atomic\name, .text.atomic) + { + movei r24, 1 + j 4f /* branch to second cache line */ + } +1: { + .ifc \bitwidth,16 + lh r22, r0 + .else + lw r22, r0 + addi r23, r0, 4 + .endif + } + .ifc \bitwidth,64 + lw r23, r23 + .endif + \body /* set r24, and r25 if 64-bit */ + { + seq r26, r22, r24 + seq r27, r23, r25 + } + .ifc \bitwidth,64 + bbnst r27, 2f + .endif + bbs r26, 3f /* skip write-back if it's the same value */ +2: { + .ifc \bitwidth,16 + sh r0, r24 + .else + sw r0, r24 + addi r23, r0, 4 + .endif + } + .ifc \bitwidth,64 + sw r23, r25 + .endif + mf +3: { + move r0, r22 + .ifc \bitwidth,64 + move r1, r23 + .else + move r1, zero + .endif + sw ATOMIC_LOCK_REG_NAME, zero + } + mtspr INTERRUPT_CRITICAL_SECTION, zero + jrp lr +4: { + move ATOMIC_LOCK_REG_NAME, r1 + mtspr INTERRUPT_CRITICAL_SECTION, r24 + } +#ifndef CONFIG_SMP + j 1b /* no atomic locks */ +#else + { + tns r21, ATOMIC_LOCK_REG_NAME + moveli r23, 2048 /* maximum backoff time in cycles */ + } + { + bzt r21, 1b /* branch if lock acquired */ + moveli r25, 32 /* starting backoff time in cycles */ + } +5: mtspr INTERRUPT_CRITICAL_SECTION, zero + mfspr r26, CYCLE_LOW /* get start point for this backoff */ +6: mfspr r22, CYCLE_LOW /* test to see if we've backed off enough */ + sub r22, r22, r26 + slt r22, r22, r25 + bbst r22, 6b + { + mtspr INTERRUPT_CRITICAL_SECTION, r24 + shli r25, r25, 1 /* double the backoff; retry the tns */ + } + { + tns r21, ATOMIC_LOCK_REG_NAME + slt r26, r23, r25 /* is the proposed backoff too big? */ + } + { + bzt r21, 1b /* branch if lock acquired */ + mvnz r25, r26, r23 + } + j 5b +#endif + STD_ENDPROC(__atomic\name) + .ifc \bitwidth,32 + .pushsection __ex_table,"a" + .word 1b, __atomic\name + .word 2b, __atomic\name + .word __atomic\name, __atomic_bad_address + .popsection + .endif + .endm + +atomic_op _cmpxchg, 32, "seq r26, r22, r2; { bbns r26, 3f; move r24, r3 }" +atomic_op _xchg, 32, "move r24, r2" +atomic_op _xchg_add, 32, "add r24, r22, r2" +atomic_op _xchg_add_unless, 32, \ + "sne r26, r22, r2; { bbns r26, 3f; add r24, r22, r3 }" +atomic_op _or, 32, "or r24, r22, r2" +atomic_op _andn, 32, "nor r2, r2, zero; and r24, r22, r2" +atomic_op _xor, 32, "xor r24, r22, r2" + +atomic_op 64_cmpxchg, 64, "{ seq r26, r22, r2; seq r27, r23, r3 }; \ + { bbns r26, 3f; move r24, r4 }; { bbns r27, 3f; move r25, r5 }" +atomic_op 64_xchg, 64, "{ move r24, r2; move r25, r3 }" +atomic_op 64_xchg_add, 64, "{ add r24, r22, r2; add r25, r23, r3 }; \ + slt_u r26, r24, r22; add r25, r25, r26" +atomic_op 64_xchg_add_unless, 64, \ + "{ sne r26, r22, r2; sne r27, r23, r3 }; \ + { bbns r26, 3f; add r24, r22, r4 }; \ + { bbns r27, 3f; add r25, r23, r5 }; \ + slt_u r26, r24, r22; add r25, r25, r26" + + jrp lr /* happy backtracer */ + +ENTRY(__end_atomic_asm_code) diff --git a/arch/tile/lib/checksum.c b/arch/tile/lib/checksum.c new file mode 100644 index 000000000000..e4bab5bd3f31 --- /dev/null +++ b/arch/tile/lib/checksum.c @@ -0,0 +1,102 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * Support code for the main lib/checksum.c. + */ + +#include +#include + +static inline unsigned int longto16(unsigned long x) +{ + unsigned long ret; +#ifdef __tilegx__ + ret = __insn_v2sadu(x, 0); + ret = __insn_v2sadu(ret, 0); +#else + ret = __insn_sadh_u(x, 0); + ret = __insn_sadh_u(ret, 0); +#endif + return ret; +} + +__wsum do_csum(const unsigned char *buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = (*buff << 8); + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(const unsigned short *)buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { +#ifdef __tilegx__ + if (4 & (unsigned long) buff) { + unsigned int w = *(const unsigned int *)buff; + result = __insn_v2sadau(result, w, 0); + count--; + len -= 4; + buff += 4; + } + count >>= 1; /* nr of 64-bit words.. */ +#endif + + /* + * This algorithm could wrap around for very + * large buffers, but those should be impossible. + */ + BUG_ON(count >= 65530); + + while (count) { + unsigned long w = *(const unsigned long *)buff; + count--; + buff += sizeof(w); +#ifdef __tilegx__ + result = __insn_v2sadau(result, w, 0); +#else + result = __insn_sadah_u(result, w, 0); +#endif + } +#ifdef __tilegx__ + if (len & 4) { + unsigned int w = *(const unsigned int *)buff; + result = __insn_v2sadau(result, w, 0); + buff += 4; + } +#endif + } + if (len & 2) { + result += *(const unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += *buff; + result = longto16(result); + if (odd) + result = swab16(result); +out: + return result; +} diff --git a/arch/tile/lib/cpumask.c b/arch/tile/lib/cpumask.c new file mode 100644 index 000000000000..af745b3b2559 --- /dev/null +++ b/arch/tile/lib/cpumask.c @@ -0,0 +1,51 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +/* + * Allow cropping out bits beyond the end of the array. + * Move to "lib" directory if more clients want to use this routine. + */ +int bitmap_parselist_crop(const char *bp, unsigned long *maskp, int nmaskbits) +{ + unsigned a, b; + + bitmap_zero(maskp, nmaskbits); + do { + if (!isdigit(*bp)) + return -EINVAL; + a = simple_strtoul(bp, (char **)&bp, 10); + b = a; + if (*bp == '-') { + bp++; + if (!isdigit(*bp)) + return -EINVAL; + b = simple_strtoul(bp, (char **)&bp, 10); + } + if (!(a <= b)) + return -EINVAL; + if (b >= nmaskbits) + b = nmaskbits-1; + while (a <= b) { + set_bit(a, maskp); + a++; + } + if (*bp == ',') + bp++; + } while (*bp != '\0' && *bp != '\n'); + return 0; +} diff --git a/arch/tile/lib/delay.c b/arch/tile/lib/delay.c new file mode 100644 index 000000000000..5801b03c13ef --- /dev/null +++ b/arch/tile/lib/delay.c @@ -0,0 +1,34 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include + +void __udelay(unsigned long usecs) +{ + hv_nanosleep(usecs * 1000); +} +EXPORT_SYMBOL(__udelay); + +void __ndelay(unsigned long nsecs) +{ + hv_nanosleep(nsecs); +} +EXPORT_SYMBOL(__ndelay); + +/* FIXME: should be declared in a header somewhere. */ +EXPORT_SYMBOL(__delay); diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c new file mode 100644 index 000000000000..af8e70e2a0ce --- /dev/null +++ b/arch/tile/lib/exports.c @@ -0,0 +1,78 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Exports from assembler code and from libtile-cc. + */ + +#include + +/* arch/tile/lib/usercopy.S */ +#include +EXPORT_SYMBOL(__get_user_1); +EXPORT_SYMBOL(__get_user_2); +EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__put_user_1); +EXPORT_SYMBOL(__put_user_2); +EXPORT_SYMBOL(__put_user_4); +EXPORT_SYMBOL(__put_user_8); +EXPORT_SYMBOL(strnlen_user_asm); +EXPORT_SYMBOL(strncpy_from_user_asm); +EXPORT_SYMBOL(clear_user_asm); + +/* arch/tile/kernel/entry.S */ +#include +#include +EXPORT_SYMBOL(current_text_addr); +EXPORT_SYMBOL(dump_stack); + +/* arch/tile/lib/__memcpy.S */ +/* NOTE: on TILE64, these symbols appear in arch/tile/lib/memcpy_tile64.c */ +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(__copy_to_user_inatomic); +EXPORT_SYMBOL(__copy_from_user_inatomic); +EXPORT_SYMBOL(__copy_from_user_zeroing); + +/* hypervisor glue */ +#include +EXPORT_SYMBOL(hv_dev_open); +EXPORT_SYMBOL(hv_dev_pread); +EXPORT_SYMBOL(hv_dev_pwrite); +EXPORT_SYMBOL(hv_dev_close); + +/* -ltile-cc */ +uint32_t __udivsi3(uint32_t dividend, uint32_t divisor); +EXPORT_SYMBOL(__udivsi3); +int32_t __divsi3(int32_t dividend, int32_t divisor); +EXPORT_SYMBOL(__divsi3); +uint64_t __udivdi3(uint64_t dividend, uint64_t divisor); +EXPORT_SYMBOL(__udivdi3); +int64_t __divdi3(int64_t dividend, int64_t divisor); +EXPORT_SYMBOL(__divdi3); +uint32_t __umodsi3(uint32_t dividend, uint32_t divisor); +EXPORT_SYMBOL(__umodsi3); +int32_t __modsi3(int32_t dividend, int32_t divisor); +EXPORT_SYMBOL(__modsi3); +uint64_t __umoddi3(uint64_t dividend, uint64_t divisor); +EXPORT_SYMBOL(__umoddi3); +int64_t __moddi3(int64_t dividend, int64_t divisor); +EXPORT_SYMBOL(__moddi3); +#ifndef __tilegx__ +uint64_t __ll_mul(uint64_t n0, uint64_t n1); +EXPORT_SYMBOL(__ll_mul); +#endif +#ifndef __tilegx__ +int64_t __muldi3(int64_t, int64_t); +EXPORT_SYMBOL(__muldi3); +uint64_t __lshrdi3(uint64_t, unsigned int); +EXPORT_SYMBOL(__lshrdi3); +#endif diff --git a/arch/tile/lib/mb_incoherent.S b/arch/tile/lib/mb_incoherent.S new file mode 100644 index 000000000000..989ad7b68d5a --- /dev/null +++ b/arch/tile/lib/mb_incoherent.S @@ -0,0 +1,34 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Assembly code for invoking the HV's fence_incoherent syscall. + */ + +#include +#include +#include +#include + +#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS() + +/* + * Invoke the hypervisor's fence_incoherent syscall, which guarantees + * that all victims for cachelines homed on this tile have reached memory. + */ +STD_ENTRY(__mb_incoherent) + moveli TREG_SYSCALL_NR_NAME, HV_SYS_fence_incoherent + swint2 + jrp lr + STD_ENDPROC(__mb_incoherent) + +#endif diff --git a/arch/tile/lib/memchr_32.c b/arch/tile/lib/memchr_32.c new file mode 100644 index 000000000000..6235283b4859 --- /dev/null +++ b/arch/tile/lib/memchr_32.c @@ -0,0 +1,68 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +void *memchr(const void *s, int c, size_t n) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *)(s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + * will not match goal. + * + * Note that this shift count expression works because we know + * shift counts are taken mod 32. + */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & before_mask); + + /* Compute the address of the last byte. */ + const char *const last_byte_ptr = (const char *)s + n - 1; + + /* Compute the address of the word containing the last byte. */ + const uint32_t *const last_word_ptr = + (const uint32_t *)((uintptr_t) last_byte_ptr & -4); + + uint32_t bits; + char *ret; + + if (__builtin_expect(n == 0, 0)) { + /* Don't dereference any memory if the array is empty. */ + return NULL; + } + + while ((bits = __insn_seqb(v, goal)) == 0) { + if (__builtin_expect(p == last_word_ptr, 0)) { + /* We already read the last word in the array, + * so give up. + */ + return NULL; + } + v = *++p; + } + + /* We found a match, but it might be in a byte past the end + * of the array. + */ + ret = ((char *)p) + (__insn_ctz(bits) >> 3); + return (ret <= last_byte_ptr) ? ret : NULL; +} +EXPORT_SYMBOL(memchr); diff --git a/arch/tile/lib/memcpy_32.S b/arch/tile/lib/memcpy_32.S new file mode 100644 index 000000000000..f92984bf60ec --- /dev/null +++ b/arch/tile/lib/memcpy_32.S @@ -0,0 +1,628 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This file shares the implementation of the userspace memcpy and + * the kernel's memcpy, copy_to_user and copy_from_user. + */ + +#include + +#if CHIP_HAS_WH64() || defined(MEMCPY_TEST_WH64) +#define MEMCPY_USE_WH64 +#endif + + +#include + +/* On TILE64, we wrap these functions via arch/tile/lib/memcpy_tile64.c */ +#if !CHIP_HAS_COHERENT_LOCAL_CACHE() +#define memcpy __memcpy_asm +#define __copy_to_user_inatomic __copy_to_user_inatomic_asm +#define __copy_from_user_inatomic __copy_from_user_inatomic_asm +#define __copy_from_user_zeroing __copy_from_user_zeroing_asm +#endif + +#define IS_MEMCPY 0 +#define IS_COPY_FROM_USER 1 +#define IS_COPY_FROM_USER_ZEROING 2 +#define IS_COPY_TO_USER -1 + + .section .text.memcpy_common, "ax" + .align 64 + +/* Use this to preface each bundle that can cause an exception so + * the kernel can clean up properly. The special cleanup code should + * not use these, since it knows what it is doing. + */ +#define EX \ + .pushsection __ex_table, "a"; \ + .word 9f, memcpy_common_fixup; \ + .popsection; \ + 9 + + +/* __copy_from_user_inatomic takes the kernel target address in r0, + * the user source in r1, and the bytes to copy in r2. + * It returns the number of uncopiable bytes (hopefully zero) in r0. + */ +ENTRY(__copy_from_user_inatomic) +.type __copy_from_user_inatomic, @function + FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \ + .text.memcpy_common, \ + .Lend_memcpy_common - __copy_from_user_inatomic) + { movei r29, IS_COPY_FROM_USER; j memcpy_common } + .size __copy_from_user_inatomic, . - __copy_from_user_inatomic + +/* __copy_from_user_zeroing is like __copy_from_user_inatomic, but + * any uncopiable bytes are zeroed in the target. + */ +ENTRY(__copy_from_user_zeroing) +.type __copy_from_user_zeroing, @function + FEEDBACK_REENTER(__copy_from_user_inatomic) + { movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common } + .size __copy_from_user_zeroing, . - __copy_from_user_zeroing + +/* __copy_to_user_inatomic takes the user target address in r0, + * the kernel source in r1, and the bytes to copy in r2. + * It returns the number of uncopiable bytes (hopefully zero) in r0. + */ +ENTRY(__copy_to_user_inatomic) +.type __copy_to_user_inatomic, @function + FEEDBACK_REENTER(__copy_from_user_inatomic) + { movei r29, IS_COPY_TO_USER; j memcpy_common } + .size __copy_to_user_inatomic, . - __copy_to_user_inatomic + +ENTRY(memcpy) +.type memcpy, @function + FEEDBACK_REENTER(__copy_from_user_inatomic) + { movei r29, IS_MEMCPY } + .size memcpy, . - memcpy + /* Fall through */ + + .type memcpy_common, @function +memcpy_common: + /* On entry, r29 holds one of the IS_* macro values from above. */ + + + /* r0 is the dest, r1 is the source, r2 is the size. */ + + /* Save aside original dest so we can return it at the end. */ + { sw sp, lr; move r23, r0; or r4, r0, r1 } + + /* Check for an empty size. */ + { bz r2, .Ldone; andi r4, r4, 3 } + + /* Save aside original values in case of a fault. */ + { move r24, r1; move r25, r2 } + move r27, lr + + /* Check for an unaligned source or dest. */ + { bnz r4, .Lcopy_unaligned_maybe_many; addli r4, r2, -256 } + +.Lcheck_aligned_copy_size: + /* If we are copying < 256 bytes, branch to simple case. */ + { blzt r4, .Lcopy_8_check; slti_u r8, r2, 8 } + + /* Copying >= 256 bytes, so jump to complex prefetching loop. */ + { andi r6, r1, 63; j .Lcopy_many } + +/* + * + * Aligned 4 byte at a time copy loop + * + */ + +.Lcopy_8_loop: + /* Copy two words at a time to hide load latency. */ +EX: { lw r3, r1; addi r1, r1, 4; slti_u r8, r2, 16 } +EX: { lw r4, r1; addi r1, r1, 4 } +EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } +EX: { sw r0, r4; addi r0, r0, 4; addi r2, r2, -4 } +.Lcopy_8_check: + { bzt r8, .Lcopy_8_loop; slti_u r4, r2, 4 } + + /* Copy odd leftover word, if any. */ + { bnzt r4, .Lcheck_odd_stragglers } +EX: { lw r3, r1; addi r1, r1, 4 } +EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } + +.Lcheck_odd_stragglers: + { bnz r2, .Lcopy_unaligned_few } + +.Ldone: + /* For memcpy return original dest address, else zero. */ + { mz r0, r29, r23; jrp lr } + + +/* + * + * Prefetching multiple cache line copy handler (for large transfers). + * + */ + + /* Copy words until r1 is cache-line-aligned. */ +.Lalign_loop: +EX: { lw r3, r1; addi r1, r1, 4 } + { andi r6, r1, 63 } +EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } +.Lcopy_many: + { bnzt r6, .Lalign_loop; addi r9, r0, 63 } + + { addi r3, r1, 60; andi r9, r9, -64 } + +#ifdef MEMCPY_USE_WH64 + /* No need to prefetch dst, we'll just do the wh64 + * right before we copy a line. + */ +#endif + +EX: { lw r5, r3; addi r3, r3, 64; movei r4, 1 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, .; move r27, lr } +EX: { lw r6, r3; addi r3, r3, 64 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, . } +EX: { lw r7, r3; addi r3, r3, 64 } +#ifndef MEMCPY_USE_WH64 + /* Prefetch the dest */ + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, . } + /* Use a real load to cause a TLB miss if necessary. We aren't using + * r28, so this should be fine. + */ +EX: { lw r28, r9; addi r9, r9, 64 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, . } + { prefetch r9; addi r9, r9, 64 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, . } + { prefetch r9; addi r9, r9, 64 } +#endif + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bz zero, .Lbig_loop2 } + + /* On entry to this loop: + * - r0 points to the start of dst line 0 + * - r1 points to start of src line 0 + * - r2 >= (256 - 60), only the first time the loop trips. + * - r3 contains r1 + 128 + 60 [pointer to end of source line 2] + * This is our prefetch address. When we get near the end + * rather than prefetching off the end this is changed to point + * to some "safe" recently loaded address. + * - r5 contains *(r1 + 60) [i.e. last word of source line 0] + * - r6 contains *(r1 + 64 + 60) [i.e. last word of source line 1] + * - r9 contains ((r0 + 63) & -64) + * [start of next dst cache line.] + */ + +.Lbig_loop: + { jal .Lcopy_line2; add r15, r1, r2 } + +.Lbig_loop2: + /* Copy line 0, first stalling until r5 is ready. */ +EX: { move r12, r5; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ +EX: { lw r5, r3; addi r3, r3, 64 } + { jal .Lcopy_line } + + /* Copy line 1, first stalling until r6 is ready. */ +EX: { move r12, r6; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ +EX: { lw r6, r3; addi r3, r3, 64 } + { jal .Lcopy_line } + + /* Copy line 2, first stalling until r7 is ready. */ +EX: { move r12, r7; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ +EX: { lw r7, r3; addi r3, r3, 64 } + /* Use up a caches-busy cycle by jumping back to the top of the + * loop. Might as well get it out of the way now. + */ + { j .Lbig_loop } + + + /* On entry: + * - r0 points to the destination line. + * - r1 points to the source line. + * - r3 is the next prefetch address. + * - r9 holds the last address used for wh64. + * - r12 = WORD_15 + * - r16 = WORD_0. + * - r17 == r1 + 16. + * - r27 holds saved lr to restore. + * + * On exit: + * - r0 is incremented by 64. + * - r1 is incremented by 64, unless that would point to a word + * beyond the end of the source array, in which case it is redirected + * to point to an arbitrary word already in the cache. + * - r2 is decremented by 64. + * - r3 is unchanged, unless it points to a word beyond the + * end of the source array, in which case it is redirected + * to point to an arbitrary word already in the cache. + * Redirecting is OK since if we are that close to the end + * of the array we will not come back to this subroutine + * and use the contents of the prefetched address. + * - r4 is nonzero iff r2 >= 64. + * - r9 is incremented by 64, unless it points beyond the + * end of the last full destination cache line, in which + * case it is redirected to a "safe address" that can be + * clobbered (sp - 64) + * - lr contains the value in r27. + */ + +/* r26 unused */ + +.Lcopy_line: + /* TODO: when r3 goes past the end, we would like to redirect it + * to prefetch the last partial cache line (if any) just once, for the + * benefit of the final cleanup loop. But we don't want to + * prefetch that line more than once, or subsequent prefetches + * will go into the RTF. But then .Lbig_loop should unconditionally + * branch to top of loop to execute final prefetch, and its + * nop should become a conditional branch. + */ + + /* We need two non-memory cycles here to cover the resources + * used by the loads initiated by the caller. + */ + { add r15, r1, r2 } +.Lcopy_line2: + { slt_u r13, r3, r15; addi r17, r1, 16 } + + /* NOTE: this will stall for one cycle as L1 is busy. */ + + /* Fill second L1D line. */ +EX: { lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 } /* r17 = WORD_4 */ + +#ifdef MEMCPY_TEST_WH64 + /* Issue a fake wh64 that clobbers the destination words + * with random garbage, for testing. + */ + { movei r19, 64; crc32_32 r10, r2, r9 } +.Lwh64_test_loop: +EX: { sw r9, r10; addi r9, r9, 4; addi r19, r19, -4 } + { bnzt r19, .Lwh64_test_loop; crc32_32 r10, r10, r19 } +#elif CHIP_HAS_WH64() + /* Prepare destination line for writing. */ +EX: { wh64 r9; addi r9, r9, 64 } +#else + /* Prefetch dest line */ + { prefetch r9; addi r9, r9, 64 } +#endif + /* Load seven words that are L1D hits to cover wh64 L2 usage. */ + + /* Load the three remaining words from the last L1D line, which + * we know has already filled the L1D. + */ +EX: { lw r4, r1; addi r1, r1, 4; addi r20, r1, 16 } /* r4 = WORD_12 */ +EX: { lw r8, r1; addi r1, r1, 4; slt_u r13, r20, r15 }/* r8 = WORD_13 */ +EX: { lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 } /* r11 = WORD_14 */ + + /* Load the three remaining words from the first L1D line, first + * stalling until it has filled by "looking at" r16. + */ +EX: { lw r13, r1; addi r1, r1, 4; move zero, r16 } /* r13 = WORD_1 */ +EX: { lw r14, r1; addi r1, r1, 4 } /* r14 = WORD_2 */ +EX: { lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 } /* r15 = WORD_3 */ + + /* Load second word from the second L1D line, first + * stalling until it has filled by "looking at" r17. + */ +EX: { lw r19, r1; addi r1, r1, 4; move zero, r17 } /* r19 = WORD_5 */ + + /* Store last word to the destination line, potentially dirtying it + * for the first time, which keeps the L2 busy for two cycles. + */ +EX: { sw r10, r12 } /* store(WORD_15) */ + + /* Use two L1D hits to cover the sw L2 access above. */ +EX: { lw r10, r1; addi r1, r1, 4 } /* r10 = WORD_6 */ +EX: { lw r12, r1; addi r1, r1, 4 } /* r12 = WORD_7 */ + + /* Fill third L1D line. */ +EX: { lw r18, r1; addi r1, r1, 4 } /* r18 = WORD_8 */ + + /* Store first L1D line. */ +EX: { sw r0, r16; addi r0, r0, 4; add r16, r0, r2 } /* store(WORD_0) */ +EX: { sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 } /* store(WORD_1) */ +EX: { sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 } /* store(WORD_2) */ +#ifdef MEMCPY_USE_WH64 +EX: { sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 } /* store(WORD_3) */ +#else + /* Back up the r9 to a cache line we are already storing to + * if it gets past the end of the dest vector. Strictly speaking, + * we don't need to back up to the start of a cache line, but it's free + * and tidy, so why not? + */ +EX: { sw r0, r15; addi r0, r0, 4; andi r13, r0, -64 } /* store(WORD_3) */ +#endif + /* Store second L1D line. */ +EX: { sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }/* store(WORD_4) */ +EX: { sw r0, r19; addi r0, r0, 4 } /* store(WORD_5) */ +EX: { sw r0, r10; addi r0, r0, 4 } /* store(WORD_6) */ +EX: { sw r0, r12; addi r0, r0, 4 } /* store(WORD_7) */ + +EX: { lw r13, r1; addi r1, r1, 4; move zero, r18 } /* r13 = WORD_9 */ +EX: { lw r14, r1; addi r1, r1, 4 } /* r14 = WORD_10 */ +EX: { lw r15, r1; move r1, r20 } /* r15 = WORD_11 */ + + /* Store third L1D line. */ +EX: { sw r0, r18; addi r0, r0, 4 } /* store(WORD_8) */ +EX: { sw r0, r13; addi r0, r0, 4 } /* store(WORD_9) */ +EX: { sw r0, r14; addi r0, r0, 4 } /* store(WORD_10) */ +EX: { sw r0, r15; addi r0, r0, 4 } /* store(WORD_11) */ + + /* Store rest of fourth L1D line. */ +EX: { sw r0, r4; addi r0, r0, 4 } /* store(WORD_12) */ + { +EX: sw r0, r8 /* store(WORD_13) */ + addi r0, r0, 4 + /* Will r2 be > 64 after we subtract 64 below? */ + shri r4, r2, 7 + } + { +EX: sw r0, r11 /* store(WORD_14) */ + addi r0, r0, 8 + /* Record 64 bytes successfully copied. */ + addi r2, r2, -64 + } + + { jrp lr; move lr, r27 } + + /* Convey to the backtrace library that the stack frame is size + * zero, and the real return address is on the stack rather than + * in 'lr'. + */ + { info 8 } + + .align 64 +.Lcopy_unaligned_maybe_many: + /* Skip the setup overhead if we aren't copying many bytes. */ + { slti_u r8, r2, 20; sub r4, zero, r0 } + { bnzt r8, .Lcopy_unaligned_few; andi r4, r4, 3 } + { bz r4, .Ldest_is_word_aligned; add r18, r1, r2 } + +/* + * + * unaligned 4 byte at a time copy handler. + * + */ + + /* Copy single bytes until r0 == 0 mod 4, so we can store words. */ +.Lalign_dest_loop: +EX: { lb_u r3, r1; addi r1, r1, 1; addi r4, r4, -1 } +EX: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r4, .Lalign_dest_loop; andi r3, r1, 3 } + + /* If source and dest are now *both* aligned, do an aligned copy. */ + { bz r3, .Lcheck_aligned_copy_size; addli r4, r2, -256 } + +.Ldest_is_word_aligned: + +#if CHIP_HAS_DWORD_ALIGN() +EX: { andi r8, r0, 63; lwadd_na r6, r1, 4} + { slti_u r9, r2, 64; bz r8, .Ldest_is_L2_line_aligned } + + /* This copies unaligned words until either there are fewer + * than 4 bytes left to copy, or until the destination pointer + * is cache-aligned, whichever comes first. + * + * On entry: + * - r0 is the next store address. + * - r1 points 4 bytes past the load address corresponding to r0. + * - r2 >= 4 + * - r6 is the next aligned word loaded. + */ +.Lcopy_unaligned_src_words: +EX: { lwadd_na r7, r1, 4; slti_u r8, r2, 4 + 4 } + /* stall */ + { dword_align r6, r7, r1; slti_u r9, r2, 64 + 4 } +EX: { swadd r0, r6, 4; addi r2, r2, -4 } + { bnz r8, .Lcleanup_unaligned_words; andi r8, r0, 63 } + { bnzt r8, .Lcopy_unaligned_src_words; move r6, r7 } + + /* On entry: + * - r0 is the next store address. + * - r1 points 4 bytes past the load address corresponding to r0. + * - r2 >= 4 (# of bytes left to store). + * - r6 is the next aligned src word value. + * - r9 = (r2 < 64U). + * - r18 points one byte past the end of source memory. + */ +.Ldest_is_L2_line_aligned: + + { + /* Not a full cache line remains. */ + bnz r9, .Lcleanup_unaligned_words + move r7, r6 + } + + /* r2 >= 64 */ + + /* Kick off two prefetches, but don't go past the end. */ + { addi r3, r1, 63 - 4; addi r8, r1, 64 + 63 - 4 } + { prefetch r3; move r3, r8; slt_u r8, r8, r18 } + { mvz r3, r8, r1; addi r8, r3, 64 } + { prefetch r3; move r3, r8; slt_u r8, r8, r18 } + { mvz r3, r8, r1; movei r17, 0 } + +.Lcopy_unaligned_line: + /* Prefetch another line. */ + { prefetch r3; addi r15, r1, 60; addi r3, r3, 64 } + /* Fire off a load of the last word we are about to copy. */ +EX: { lw_na r15, r15; slt_u r8, r3, r18 } + +EX: { mvz r3, r8, r1; wh64 r0 } + + /* This loop runs twice. + * + * On entry: + * - r17 is even before the first iteration, and odd before + * the second. It is incremented inside the loop. Encountering + * an even value at the end of the loop makes it stop. + */ +.Lcopy_half_an_unaligned_line: +EX: { + /* Stall until the last byte is ready. In the steady state this + * guarantees all words to load below will be in the L2 cache, which + * avoids shunting the loads to the RTF. + */ + move zero, r15 + lwadd_na r7, r1, 16 + } +EX: { lwadd_na r11, r1, 12 } +EX: { lwadd_na r14, r1, -24 } +EX: { lwadd_na r8, r1, 4 } +EX: { lwadd_na r9, r1, 4 } +EX: { + lwadd_na r10, r1, 8 + /* r16 = (r2 < 64), after we subtract 32 from r2 below. */ + slti_u r16, r2, 64 + 32 + } +EX: { lwadd_na r12, r1, 4; addi r17, r17, 1 } +EX: { lwadd_na r13, r1, 8; dword_align r6, r7, r1 } +EX: { swadd r0, r6, 4; dword_align r7, r8, r1 } +EX: { swadd r0, r7, 4; dword_align r8, r9, r1 } +EX: { swadd r0, r8, 4; dword_align r9, r10, r1 } +EX: { swadd r0, r9, 4; dword_align r10, r11, r1 } +EX: { swadd r0, r10, 4; dword_align r11, r12, r1 } +EX: { swadd r0, r11, 4; dword_align r12, r13, r1 } +EX: { swadd r0, r12, 4; dword_align r13, r14, r1 } +EX: { swadd r0, r13, 4; addi r2, r2, -32 } + { move r6, r14; bbst r17, .Lcopy_half_an_unaligned_line } + + { bzt r16, .Lcopy_unaligned_line; move r7, r6 } + + /* On entry: + * - r0 is the next store address. + * - r1 points 4 bytes past the load address corresponding to r0. + * - r2 >= 0 (# of bytes left to store). + * - r7 is the next aligned src word value. + */ +.Lcleanup_unaligned_words: + /* Handle any trailing bytes. */ + { bz r2, .Lcopy_unaligned_done; slti_u r8, r2, 4 } + { bzt r8, .Lcopy_unaligned_src_words; move r6, r7 } + + /* Move r1 back to the point where it corresponds to r0. */ + { addi r1, r1, -4 } + +#else /* !CHIP_HAS_DWORD_ALIGN() */ + + /* Compute right/left shift counts and load initial source words. */ + { andi r5, r1, -4; andi r3, r1, 3 } +EX: { lw r6, r5; addi r5, r5, 4; shli r3, r3, 3 } +EX: { lw r7, r5; addi r5, r5, 4; sub r4, zero, r3 } + + /* Load and store one word at a time, using shifts and ORs + * to correct for the misaligned src. + */ +.Lcopy_unaligned_src_loop: + { shr r6, r6, r3; shl r8, r7, r4 } +EX: { lw r7, r5; or r8, r8, r6; move r6, r7 } +EX: { sw r0, r8; addi r0, r0, 4; addi r2, r2, -4 } + { addi r5, r5, 4; slti_u r8, r2, 8 } + { bzt r8, .Lcopy_unaligned_src_loop; addi r1, r1, 4 } + + { bz r2, .Lcopy_unaligned_done } +#endif /* !CHIP_HAS_DWORD_ALIGN() */ + + /* Fall through */ + +/* + * + * 1 byte at a time copy handler. + * + */ + +.Lcopy_unaligned_few: +EX: { lb_u r3, r1; addi r1, r1, 1 } +EX: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r2, .Lcopy_unaligned_few } + +.Lcopy_unaligned_done: + + /* For memcpy return original dest address, else zero. */ + { mz r0, r29, r23; jrp lr } + +.Lend_memcpy_common: + .size memcpy_common, .Lend_memcpy_common - memcpy_common + + .section .fixup,"ax" +memcpy_common_fixup: + .type memcpy_common_fixup, @function + + /* Skip any bytes we already successfully copied. + * r2 (num remaining) is correct, but r0 (dst) and r1 (src) + * may not be quite right because of unrolling and prefetching. + * So we need to recompute their values as the address just + * after the last byte we are sure was successfully loaded and + * then stored. + */ + + /* Determine how many bytes we successfully copied. */ + { sub r3, r25, r2 } + + /* Add this to the original r0 and r1 to get their new values. */ + { add r0, r23, r3; add r1, r24, r3 } + + { bzt r29, memcpy_fixup_loop } + { blzt r29, copy_to_user_fixup_loop } + +copy_from_user_fixup_loop: + /* Try copying the rest one byte at a time, expecting a load fault. */ +.Lcfu: { lb_u r3, r1; addi r1, r1, 1 } + { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r2, copy_from_user_fixup_loop } + +.Lcopy_from_user_fixup_zero_remainder: + { bbs r29, 2f } /* low bit set means IS_COPY_FROM_USER */ + /* byte-at-a-time loop faulted, so zero the rest. */ + { move r3, r2; bz r2, 2f /* should be impossible, but handle it. */ } +1: { sb r0, zero; addi r0, r0, 1; addi r3, r3, -1 } + { bnzt r3, 1b } +2: move lr, r27 + { move r0, r2; jrp lr } + +copy_to_user_fixup_loop: + /* Try copying the rest one byte at a time, expecting a store fault. */ + { lb_u r3, r1; addi r1, r1, 1 } +.Lctu: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r2, copy_to_user_fixup_loop } +.Lcopy_to_user_fixup_done: + move lr, r27 + { move r0, r2; jrp lr } + +memcpy_fixup_loop: + /* Try copying the rest one byte at a time. We expect a disastrous + * fault to happen since we are in fixup code, but let it happen. + */ + { lb_u r3, r1; addi r1, r1, 1 } + { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r2, memcpy_fixup_loop } + /* This should be unreachable, we should have faulted again. + * But be paranoid and handle it in case some interrupt changed + * the TLB or something. + */ + move lr, r27 + { move r0, r23; jrp lr } + + .size memcpy_common_fixup, . - memcpy_common_fixup + + .section __ex_table,"a" + .word .Lcfu, .Lcopy_from_user_fixup_zero_remainder + .word .Lctu, .Lcopy_to_user_fixup_done diff --git a/arch/tile/lib/memcpy_tile64.c b/arch/tile/lib/memcpy_tile64.c new file mode 100644 index 000000000000..4f0047342469 --- /dev/null +++ b/arch/tile/lib/memcpy_tile64.c @@ -0,0 +1,271 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !CHIP_HAS_COHERENT_LOCAL_CACHE() + +/* Defined in memcpy.S */ +extern unsigned long __memcpy_asm(void *to, const void *from, unsigned long n); +extern unsigned long __copy_to_user_inatomic_asm( + void __user *to, const void *from, unsigned long n); +extern unsigned long __copy_from_user_inatomic_asm( + void *to, const void __user *from, unsigned long n); +extern unsigned long __copy_from_user_zeroing_asm( + void *to, const void __user *from, unsigned long n); + +typedef unsigned long (*memcpy_t)(void *, const void *, unsigned long); + +/* Size above which to consider TLB games for performance */ +#define LARGE_COPY_CUTOFF 2048 + +/* Communicate to the simulator what we are trying to do. */ +#define sim_allow_multiple_caching(b) \ + __insn_mtspr(SPR_SIM_CONTROL, \ + SIM_CONTROL_ALLOW_MULTIPLE_CACHING | ((b) << _SIM_CONTROL_OPERATOR_BITS)) + +/* + * Copy memory by briefly enabling incoherent cacheline-at-a-time mode. + * + * We set up our own source and destination PTEs that we fully control. + * This is the only way to guarantee that we don't race with another + * thread that is modifying the PTE; we can't afford to try the + * copy_{to,from}_user() technique of catching the interrupt, since + * we must run with interrupts disabled to avoid the risk of some + * other code seeing the incoherent data in our cache. (Recall that + * our cache is indexed by PA, so even if the other code doesn't use + * our KM_MEMCPY virtual addresses, they'll still hit in cache using + * the normal VAs that aren't supposed to hit in cache.) + */ +static void memcpy_multicache(void *dest, const void *source, + pte_t dst_pte, pte_t src_pte, int len) +{ + int idx, i; + unsigned long flags, newsrc, newdst, endsrc; + pmd_t *pmdp; + pte_t *ptep; + int cpu = get_cpu(); + + /* + * Disable interrupts so that we don't recurse into memcpy() + * in an interrupt handler, nor accidentally reference + * the PA of the source from an interrupt routine. Also + * notify the simulator that we're playing games so we don't + * generate spurious coherency warnings. + */ + local_irq_save(flags); + sim_allow_multiple_caching(1); + + /* Set up the new dest mapping */ + idx = FIX_KMAP_BEGIN + (KM_TYPE_NR * cpu) + KM_MEMCPY0; + newdst = __fix_to_virt(idx) + ((unsigned long)dest & (PAGE_SIZE-1)); + pmdp = pmd_offset(pud_offset(pgd_offset_k(newdst), newdst), newdst); + ptep = pte_offset_kernel(pmdp, newdst); + if (pte_val(*ptep) != pte_val(dst_pte)) { + set_pte(ptep, dst_pte); + local_flush_tlb_page(NULL, newdst, PAGE_SIZE); + } + + /* Set up the new source mapping */ + idx += (KM_MEMCPY0 - KM_MEMCPY1); + src_pte = hv_pte_set_nc(src_pte); + src_pte = hv_pte_clear_writable(src_pte); /* be paranoid */ + newsrc = __fix_to_virt(idx) + ((unsigned long)source & (PAGE_SIZE-1)); + pmdp = pmd_offset(pud_offset(pgd_offset_k(newsrc), newsrc), newsrc); + ptep = pte_offset_kernel(pmdp, newsrc); + *ptep = src_pte; /* set_pte() would be confused by this */ + local_flush_tlb_page(NULL, newsrc, PAGE_SIZE); + + /* Actually move the data. */ + __memcpy_asm((void *)newdst, (const void *)newsrc, len); + + /* + * Remap the source as locally-cached and not OLOC'ed so that + * we can inval without also invaling the remote cpu's cache. + * This also avoids known errata with inv'ing cacheable oloc data. + */ + src_pte = hv_pte_set_mode(src_pte, HV_PTE_MODE_CACHE_NO_L3); + src_pte = hv_pte_set_writable(src_pte); /* need write access for inv */ + *ptep = src_pte; /* set_pte() would be confused by this */ + local_flush_tlb_page(NULL, newsrc, PAGE_SIZE); + + /* + * Do the actual invalidation, covering the full L2 cache line + * at the end since __memcpy_asm() is somewhat aggressive. + */ + __inv_buffer((void *)newsrc, len); + + /* + * We're done: notify the simulator that all is back to normal, + * and re-enable interrupts and pre-emption. + */ + sim_allow_multiple_caching(0); + local_irq_restore(flags); + put_cpu_no_resched(); +} + +/* + * Identify large copies from remotely-cached memory, and copy them + * via memcpy_multicache() if they look good, otherwise fall back + * to the particular kind of copying passed as the memcpy_t function. + */ +static unsigned long fast_copy(void *dest, const void *source, int len, + memcpy_t func) +{ + /* + * Check if it's big enough to bother with. We may end up doing a + * small copy via TLB manipulation if we're near a page boundary, + * but presumably we'll make it up when we hit the second page. + */ + while (len >= LARGE_COPY_CUTOFF) { + int copy_size, bytes_left_on_page; + pte_t *src_ptep, *dst_ptep; + pte_t src_pte, dst_pte; + struct page *src_page, *dst_page; + + /* Is the source page oloc'ed to a remote cpu? */ +retry_source: + src_ptep = virt_to_pte(current->mm, (unsigned long)source); + if (src_ptep == NULL) + break; + src_pte = *src_ptep; + if (!hv_pte_get_present(src_pte) || + !hv_pte_get_readable(src_pte) || + hv_pte_get_mode(src_pte) != HV_PTE_MODE_CACHE_TILE_L3) + break; + if (get_remote_cache_cpu(src_pte) == smp_processor_id()) + break; + src_page = pfn_to_page(hv_pte_get_pfn(src_pte)); + get_page(src_page); + if (pte_val(src_pte) != pte_val(*src_ptep)) { + put_page(src_page); + goto retry_source; + } + if (pte_huge(src_pte)) { + /* Adjust the PTE to correspond to a small page */ + int pfn = hv_pte_get_pfn(src_pte); + pfn += (((unsigned long)source & (HPAGE_SIZE-1)) + >> PAGE_SHIFT); + src_pte = pfn_pte(pfn, src_pte); + src_pte = pte_mksmall(src_pte); + } + + /* Is the destination page writable? */ +retry_dest: + dst_ptep = virt_to_pte(current->mm, (unsigned long)dest); + if (dst_ptep == NULL) { + put_page(src_page); + break; + } + dst_pte = *dst_ptep; + if (!hv_pte_get_present(dst_pte) || + !hv_pte_get_writable(dst_pte)) { + put_page(src_page); + break; + } + dst_page = pfn_to_page(hv_pte_get_pfn(dst_pte)); + if (dst_page == src_page) { + /* + * Source and dest are on the same page; this + * potentially exposes us to incoherence if any + * part of src and dest overlap on a cache line. + * Just give up rather than trying to be precise. + */ + put_page(src_page); + break; + } + get_page(dst_page); + if (pte_val(dst_pte) != pte_val(*dst_ptep)) { + put_page(dst_page); + goto retry_dest; + } + if (pte_huge(dst_pte)) { + /* Adjust the PTE to correspond to a small page */ + int pfn = hv_pte_get_pfn(dst_pte); + pfn += (((unsigned long)dest & (HPAGE_SIZE-1)) + >> PAGE_SHIFT); + dst_pte = pfn_pte(pfn, dst_pte); + dst_pte = pte_mksmall(dst_pte); + } + + /* All looks good: create a cachable PTE and copy from it */ + copy_size = len; + bytes_left_on_page = + PAGE_SIZE - (((int)source) & (PAGE_SIZE-1)); + if (copy_size > bytes_left_on_page) + copy_size = bytes_left_on_page; + bytes_left_on_page = + PAGE_SIZE - (((int)dest) & (PAGE_SIZE-1)); + if (copy_size > bytes_left_on_page) + copy_size = bytes_left_on_page; + memcpy_multicache(dest, source, dst_pte, src_pte, copy_size); + + /* Release the pages */ + put_page(dst_page); + put_page(src_page); + + /* Continue on the next page */ + dest += copy_size; + source += copy_size; + len -= copy_size; + } + + return func(dest, source, len); +} + +void *memcpy(void *to, const void *from, __kernel_size_t n) +{ + if (n < LARGE_COPY_CUTOFF) + return (void *)__memcpy_asm(to, from, n); + else + return (void *)fast_copy(to, from, n, __memcpy_asm); +} + +unsigned long __copy_to_user_inatomic(void __user *to, const void *from, + unsigned long n) +{ + if (n < LARGE_COPY_CUTOFF) + return __copy_to_user_inatomic_asm(to, from, n); + else + return fast_copy(to, from, n, __copy_to_user_inatomic_asm); +} + +unsigned long __copy_from_user_inatomic(void *to, const void __user *from, + unsigned long n) +{ + if (n < LARGE_COPY_CUTOFF) + return __copy_from_user_inatomic_asm(to, from, n); + else + return fast_copy(to, from, n, __copy_from_user_inatomic_asm); +} + +unsigned long __copy_from_user_zeroing(void *to, const void __user *from, + unsigned long n) +{ + if (n < LARGE_COPY_CUTOFF) + return __copy_from_user_zeroing_asm(to, from, n); + else + return fast_copy(to, from, n, __copy_from_user_zeroing_asm); +} + +#endif /* !CHIP_HAS_COHERENT_LOCAL_CACHE() */ diff --git a/arch/tile/lib/memmove_32.c b/arch/tile/lib/memmove_32.c new file mode 100644 index 000000000000..f09d8c4523ec --- /dev/null +++ b/arch/tile/lib/memmove_32.c @@ -0,0 +1,63 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +void *memmove(void *dest, const void *src, size_t n) +{ + if ((const char *)src >= (char *)dest + n + || (char *)dest >= (const char *)src + n) { + /* We found no overlap, so let memcpy do all the heavy + * lifting (prefetching, etc.) + */ + return memcpy(dest, src, n); + } + + if (n != 0) { + const uint8_t *in; + uint8_t x; + uint8_t *out; + int stride; + + if (src < dest) { + /* copy backwards */ + in = (const uint8_t *)src + n - 1; + out = (uint8_t *)dest + n - 1; + stride = -1; + } else { + /* copy forwards */ + in = (const uint8_t *)src; + out = (uint8_t *)dest; + stride = 1; + } + + /* Manually software-pipeline this loop. */ + x = *in; + in += stride; + + while (--n != 0) { + *out = x; + out += stride; + x = *in; + in += stride; + } + + *out = x; + } + + return dest; +} +EXPORT_SYMBOL(memmove); diff --git a/arch/tile/lib/memset_32.c b/arch/tile/lib/memset_32.c new file mode 100644 index 000000000000..8593bc82398a --- /dev/null +++ b/arch/tile/lib/memset_32.c @@ -0,0 +1,274 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include + +#include +#include +#include + + +void *memset(void *s, int c, size_t n) +{ + uint32_t *out32; + int n32; + uint32_t v16, v32; + uint8_t *out8 = s; +#if !CHIP_HAS_WH64() + int ahead32; +#else + int to_align32; +#endif + + /* Experimentation shows that a trivial tight loop is a win up until + * around a size of 20, where writing a word at a time starts to win. + */ +#define BYTE_CUTOFF 20 + +#if BYTE_CUTOFF < 3 + /* This must be at least at least this big, or some code later + * on doesn't work. + */ +#error "BYTE_CUTOFF is too small" +#endif + + if (n < BYTE_CUTOFF) { + /* Strangely, this turns out to be the tightest way to + * write this loop. + */ + if (n != 0) { + do { + /* Strangely, combining these into one line + * performs worse. + */ + *out8 = c; + out8++; + } while (--n != 0); + } + + return s; + } + +#if !CHIP_HAS_WH64() + /* Use a spare issue slot to start prefetching the first cache + * line early. This instruction is free as the store can be buried + * in otherwise idle issue slots doing ALU ops. + */ + __insn_prefetch(out8); + + /* We prefetch the end so that a short memset that spans two cache + * lines gets some prefetching benefit. Again we believe this is free + * to issue. + */ + __insn_prefetch(&out8[n - 1]); +#endif /* !CHIP_HAS_WH64() */ + + + /* Align 'out8'. We know n >= 3 so this won't write past the end. */ + while (((uintptr_t) out8 & 3) != 0) { + *out8++ = c; + --n; + } + + /* Align 'n'. */ + while (n & 3) + out8[--n] = c; + + out32 = (uint32_t *) out8; + n32 = n >> 2; + + /* Tile input byte out to 32 bits. */ + v16 = __insn_intlb(c, c); + v32 = __insn_intlh(v16, v16); + + /* This must be at least 8 or the following loop doesn't work. */ +#define CACHE_LINE_SIZE_IN_WORDS (CHIP_L2_LINE_SIZE() / 4) + +#if !CHIP_HAS_WH64() + + ahead32 = CACHE_LINE_SIZE_IN_WORDS; + + /* We already prefetched the first and last cache lines, so + * we only need to do more prefetching if we are storing + * to more than two cache lines. + */ + if (n32 > CACHE_LINE_SIZE_IN_WORDS * 2) { + int i; + + /* Prefetch the next several cache lines. + * This is the setup code for the software-pipelined + * loop below. + */ +#define MAX_PREFETCH 5 + ahead32 = n32 & -CACHE_LINE_SIZE_IN_WORDS; + if (ahead32 > MAX_PREFETCH * CACHE_LINE_SIZE_IN_WORDS) + ahead32 = MAX_PREFETCH * CACHE_LINE_SIZE_IN_WORDS; + + for (i = CACHE_LINE_SIZE_IN_WORDS; + i < ahead32; i += CACHE_LINE_SIZE_IN_WORDS) + __insn_prefetch(&out32[i]); + } + + if (n32 > ahead32) { + while (1) { + int j; + + /* Prefetch by reading one word several cache lines + * ahead. Since loads are non-blocking this will + * cause the full cache line to be read while we are + * finishing earlier cache lines. Using a store + * here causes microarchitectural performance + * problems where a victimizing store miss goes to + * the head of the retry FIFO and locks the pipe for + * a few cycles. So a few subsequent stores in this + * loop go into the retry FIFO, and then later + * stores see other stores to the same cache line + * are already in the retry FIFO and themselves go + * into the retry FIFO, filling it up and grinding + * to a halt waiting for the original miss to be + * satisfied. + */ + __insn_prefetch(&out32[ahead32]); + +#if 1 +#if CACHE_LINE_SIZE_IN_WORDS % 4 != 0 +#error "Unhandled CACHE_LINE_SIZE_IN_WORDS" +#endif + + n32 -= CACHE_LINE_SIZE_IN_WORDS; + + /* Save icache space by only partially unrolling + * this loop. + */ + for (j = CACHE_LINE_SIZE_IN_WORDS / 4; j > 0; j--) { + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + } +#else + /* Unfortunately, due to a code generator flaw this + * allocates a separate register for each of these + * stores, which requires a large number of spills, + * which makes this procedure enormously bigger + * (something like 70%) + */ + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + n32 -= 16; +#endif + + /* To save compiled code size, reuse this loop even + * when we run out of prefetching to do by dropping + * ahead32 down. + */ + if (n32 <= ahead32) { + /* Not even a full cache line left, + * so stop now. + */ + if (n32 < CACHE_LINE_SIZE_IN_WORDS) + break; + + /* Choose a small enough value that we don't + * prefetch past the end. There's no sense + * in touching cache lines we don't have to. + */ + ahead32 = CACHE_LINE_SIZE_IN_WORDS - 1; + } + } + } + +#else /* CHIP_HAS_WH64() */ + + /* Determine how many words we need to emit before the 'out32' + * pointer becomes aligned modulo the cache line size. + */ + to_align32 = + (-((uintptr_t)out32 >> 2)) & (CACHE_LINE_SIZE_IN_WORDS - 1); + + /* Only bother aligning and using wh64 if there is at least + * one full cache line to process. This check also prevents + * overrunning the end of the buffer with alignment words. + */ + if (to_align32 <= n32 - CACHE_LINE_SIZE_IN_WORDS) { + int lines_left; + + /* Align out32 mod the cache line size so we can use wh64. */ + n32 -= to_align32; + for (; to_align32 != 0; to_align32--) { + *out32 = v32; + out32++; + } + + /* Use unsigned divide to turn this into a right shift. */ + lines_left = (unsigned)n32 / CACHE_LINE_SIZE_IN_WORDS; + + do { + /* Only wh64 a few lines at a time, so we don't + * exceed the maximum number of victim lines. + */ + int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS()) + ? lines_left + : CHIP_MAX_OUTSTANDING_VICTIMS()); + uint32_t *wh = out32; + int i = x; + int j; + + lines_left -= x; + + do { + __insn_wh64(wh); + wh += CACHE_LINE_SIZE_IN_WORDS; + } while (--i); + + for (j = x * (CACHE_LINE_SIZE_IN_WORDS / 4); j != 0; j--) { + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + } + } while (lines_left != 0); + + /* We processed all full lines above, so only this many + * words remain to be processed. + */ + n32 &= CACHE_LINE_SIZE_IN_WORDS - 1; + } + +#endif /* CHIP_HAS_WH64() */ + + /* Now handle any leftover values. */ + if (n32 != 0) { + do { + *out32 = v32; + out32++; + } while (--n32 != 0); + } + + return s; +} +EXPORT_SYMBOL(memset); diff --git a/arch/tile/lib/spinlock_32.c b/arch/tile/lib/spinlock_32.c new file mode 100644 index 000000000000..485e24d62c6b --- /dev/null +++ b/arch/tile/lib/spinlock_32.c @@ -0,0 +1,221 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +#include "spinlock_common.h" + +void arch_spin_lock(arch_spinlock_t *lock) +{ + int my_ticket; + int iterations = 0; + int delta; + + while ((my_ticket = __insn_tns((void *)&lock->next_ticket)) & 1) + delay_backoff(iterations++); + + /* Increment the next ticket number, implicitly releasing tns lock. */ + lock->next_ticket = my_ticket + TICKET_QUANTUM; + + /* Wait until it's our turn. */ + while ((delta = my_ticket - lock->current_ticket) != 0) + relax((128 / CYCLES_PER_RELAX_LOOP) * delta); +} +EXPORT_SYMBOL(arch_spin_lock); + +int arch_spin_trylock(arch_spinlock_t *lock) +{ + /* + * Grab a ticket; no need to retry if it's busy, we'll just + * treat that the same as "locked", since someone else + * will lock it momentarily anyway. + */ + int my_ticket = __insn_tns((void *)&lock->next_ticket); + + if (my_ticket == lock->current_ticket) { + /* Not currently locked, so lock it by keeping this ticket. */ + lock->next_ticket = my_ticket + TICKET_QUANTUM; + /* Success! */ + return 1; + } + + if (!(my_ticket & 1)) { + /* Release next_ticket. */ + lock->next_ticket = my_ticket; + } + + return 0; +} +EXPORT_SYMBOL(arch_spin_trylock); + +void arch_spin_unlock_wait(arch_spinlock_t *lock) +{ + u32 iterations = 0; + while (arch_spin_is_locked(lock)) + delay_backoff(iterations++); +} +EXPORT_SYMBOL(arch_spin_unlock_wait); + +/* + * The low byte is always reserved to be the marker for a "tns" operation + * since the low bit is set to "1" by a tns. The next seven bits are + * zeroes. The next byte holds the "next" writer value, i.e. the ticket + * available for the next task that wants to write. The third byte holds + * the current writer value, i.e. the writer who holds the current ticket. + * If current == next == 0, there are no interested writers. + */ +#define WR_NEXT_SHIFT _WR_NEXT_SHIFT +#define WR_CURR_SHIFT _WR_CURR_SHIFT +#define WR_WIDTH _WR_WIDTH +#define WR_MASK ((1 << WR_WIDTH) - 1) + +/* + * The last eight bits hold the active reader count. This has to be + * zero before a writer can start to write. + */ +#define RD_COUNT_SHIFT _RD_COUNT_SHIFT +#define RD_COUNT_WIDTH _RD_COUNT_WIDTH +#define RD_COUNT_MASK ((1 << RD_COUNT_WIDTH) - 1) + + +/* Lock the word, spinning until there are no tns-ers. */ +static inline u32 get_rwlock(arch_rwlock_t *rwlock) +{ + u32 iterations = 0; + for (;;) { + u32 val = __insn_tns((int *)&rwlock->lock); + if (unlikely(val & 1)) { + delay_backoff(iterations++); + continue; + } + return val; + } +} + +int arch_read_trylock_slow(arch_rwlock_t *rwlock) +{ + u32 val = get_rwlock(rwlock); + int locked = (val << RD_COUNT_WIDTH) == 0; + rwlock->lock = val + (locked << RD_COUNT_SHIFT); + return locked; +} +EXPORT_SYMBOL(arch_read_trylock_slow); + +void arch_read_unlock_slow(arch_rwlock_t *rwlock) +{ + u32 val = get_rwlock(rwlock); + rwlock->lock = val - (1 << RD_COUNT_SHIFT); +} +EXPORT_SYMBOL(arch_read_unlock_slow); + +void arch_write_unlock_slow(arch_rwlock_t *rwlock, u32 val) +{ + u32 eq, mask = 1 << WR_CURR_SHIFT; + while (unlikely(val & 1)) { + /* Limited backoff since we are the highest-priority task. */ + relax(4); + val = __insn_tns((int *)&rwlock->lock); + } + val = __insn_addb(val, mask); + eq = __insn_seqb(val, val << (WR_CURR_SHIFT - WR_NEXT_SHIFT)); + val = __insn_mz(eq & mask, val); + rwlock->lock = val; +} +EXPORT_SYMBOL(arch_write_unlock_slow); + +/* + * We spin until everything but the reader bits (which are in the high + * part of the word) are zero, i.e. no active or waiting writers, no tns. + * + * ISSUE: This approach can permanently starve readers. A reader who sees + * a writer could instead take a ticket lock (just like a writer would), + * and atomically enter read mode (with 1 reader) when it gets the ticket. + * This way both readers and writers will always make forward progress + * in a finite time. + */ +void arch_read_lock_slow(arch_rwlock_t *rwlock, u32 val) +{ + u32 iterations = 0; + do { + if (!(val & 1)) + rwlock->lock = val; + delay_backoff(iterations++); + val = __insn_tns((int *)&rwlock->lock); + } while ((val << RD_COUNT_WIDTH) != 0); + rwlock->lock = val + (1 << RD_COUNT_SHIFT); +} +EXPORT_SYMBOL(arch_read_lock_slow); + +void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val) +{ + /* + * The trailing underscore on this variable (and curr_ below) + * reminds us that the high bits are garbage; we mask them out + * when we compare them. + */ + u32 my_ticket_; + + /* Take out the next ticket; this will also stop would-be readers. */ + if (val & 1) + val = get_rwlock(rwlock); + rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT); + + /* Extract my ticket value from the original word. */ + my_ticket_ = val >> WR_NEXT_SHIFT; + + /* + * Wait until the "current" field matches our ticket, and + * there are no remaining readers. + */ + for (;;) { + u32 curr_ = val >> WR_CURR_SHIFT; + u32 readers = val >> RD_COUNT_SHIFT; + u32 delta = ((my_ticket_ - curr_) & WR_MASK) + !!readers; + if (likely(delta == 0)) + break; + + /* Delay based on how many lock-holders are still out there. */ + relax((256 / CYCLES_PER_RELAX_LOOP) * delta); + + /* + * Get a non-tns value to check; we don't need to tns + * it ourselves. Since we're not tns'ing, we retry + * more rapidly to get a valid value. + */ + while ((val = rwlock->lock) & 1) + relax(4); + } +} +EXPORT_SYMBOL(arch_write_lock_slow); + +int __tns_atomic_acquire(atomic_t *lock) +{ + int ret; + u32 iterations = 0; + + BUG_ON(__insn_mfspr(SPR_INTERRUPT_CRITICAL_SECTION)); + __insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1); + + while ((ret = __insn_tns((void *)&lock->counter)) == 1) + delay_backoff(iterations++); + return ret; +} + +void __tns_atomic_release(atomic_t *p, int v) +{ + p->counter = v; + __insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0); +} diff --git a/arch/tile/lib/spinlock_common.h b/arch/tile/lib/spinlock_common.h new file mode 100644 index 000000000000..8dffebde6630 --- /dev/null +++ b/arch/tile/lib/spinlock_common.h @@ -0,0 +1,64 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * This file is included into spinlock_32.c or _64.c. + */ + +/* + * The mfspr in __spinlock_relax() is 5 or 6 cycles plus 2 for loop + * overhead. + */ +#ifdef __tilegx__ +#define CYCLES_PER_RELAX_LOOP 7 +#else +#define CYCLES_PER_RELAX_LOOP 8 +#endif + +/* + * Idle the core for CYCLES_PER_RELAX_LOOP * iterations cycles. + */ +static inline void +relax(int iterations) +{ + for (/*above*/; iterations > 0; iterations--) + __insn_mfspr(SPR_PASS); + barrier(); +} + +/* Perform bounded exponential backoff.*/ +void delay_backoff(int iterations) +{ + u32 exponent, loops; + + /* + * 2^exponent is how many times we go around the loop, + * which takes 8 cycles. We want to start with a 16- to 31-cycle + * loop, so we need to go around minimum 2 = 2^1 times, so we + * bias the original value up by 1. + */ + exponent = iterations + 1; + + /* + * Don't allow exponent to exceed 7, so we have 128 loops, + * or 1,024 (to 2,047) cycles, as our maximum. + */ + if (exponent > 8) + exponent = 8; + + loops = 1 << exponent; + + /* Add a randomness factor so two cpus never get in lock step. */ + loops += __insn_crc32_32(stack_pointer, get_cycles_low()) & + (loops - 1); + + relax(1 << exponent); +} diff --git a/arch/tile/lib/strchr_32.c b/arch/tile/lib/strchr_32.c new file mode 100644 index 000000000000..c94e6f7ae7b5 --- /dev/null +++ b/arch/tile/lib/strchr_32.c @@ -0,0 +1,66 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +#undef strchr + +char *strchr(const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *)(s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + * match neither zero nor goal (we make sure the high bit of each + * byte is 1, and the low 7 bits are all the opposite of the goal + * byte). + * + * Note that this shift count expression works because we know shift + * counts are taken mod 32. + */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib(before_mask, 1)); + + uint32_t zero_matches, goal_matches; + while (1) { + /* Look for a terminating '\0'. */ + zero_matches = __insn_seqb(v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_seqb(v, goal); + + if (__builtin_expect(zero_matches | goal_matches, 0)) + break; + + v = *++p; + } + + z = __insn_ctz(zero_matches); + g = __insn_ctz(goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + * then g == z, and we correctly return the address of the '\0' + * rather than NULL. + */ + return (g <= z) ? ((char *)p) + (g >> 3) : NULL; +} +EXPORT_SYMBOL(strchr); diff --git a/arch/tile/lib/strlen_32.c b/arch/tile/lib/strlen_32.c new file mode 100644 index 000000000000..f26f88e11e4a --- /dev/null +++ b/arch/tile/lib/strlen_32.c @@ -0,0 +1,36 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +size_t strlen(const char *s) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *)(s_int & -4); + + /* Read the first word, but force bytes before the string to be nonzero. + * This expression works because we know shift counts are taken mod 32. + */ + uint32_t v = *p | ((1 << (s_int << 3)) - 1); + + uint32_t bits; + while ((bits = __insn_seqb(v, 0)) == 0) + v = *++p; + + return ((const char *)p) + (__insn_ctz(bits) >> 3) - s; +} +EXPORT_SYMBOL(strlen); diff --git a/arch/tile/lib/uaccess.c b/arch/tile/lib/uaccess.c new file mode 100644 index 000000000000..9ae182568b77 --- /dev/null +++ b/arch/tile/lib/uaccess.c @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include + +int __range_ok(unsigned long addr, unsigned long size) +{ + unsigned long limit = current_thread_info()->addr_limit.seg; + __chk_user_ptr(addr); + return !((addr < limit && size <= limit - addr) || + is_arch_mappable_range(addr, size)); +} +EXPORT_SYMBOL(__range_ok); + +void copy_from_user_overflow(void) +{ + WARN(1, "Buffer overflow detected!\n"); +} +EXPORT_SYMBOL(copy_from_user_overflow); diff --git a/arch/tile/lib/usercopy_32.S b/arch/tile/lib/usercopy_32.S new file mode 100644 index 000000000000..979f76d83746 --- /dev/null +++ b/arch/tile/lib/usercopy_32.S @@ -0,0 +1,223 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +/* Access user memory, but use MMU to avoid propagating kernel exceptions. */ + + .pushsection .fixup,"ax" + +get_user_fault: + { move r0, zero; move r1, zero } + { movei r2, -EFAULT; jrp lr } + ENDPROC(get_user_fault) + +put_user_fault: + { movei r0, -EFAULT; jrp lr } + ENDPROC(put_user_fault) + + .popsection + +/* + * __get_user_N functions take a pointer in r0, and return 0 in r2 + * on success, with the value in r0; or else -EFAULT in r2. + */ +#define __get_user_N(bytes, LOAD) \ + STD_ENTRY(__get_user_##bytes); \ +1: { LOAD r0, r0; move r1, zero; move r2, zero }; \ + jrp lr; \ + STD_ENDPROC(__get_user_##bytes); \ + .pushsection __ex_table,"a"; \ + .word 1b, get_user_fault; \ + .popsection + +__get_user_N(1, lb_u) +__get_user_N(2, lh_u) +__get_user_N(4, lw) + +/* + * __get_user_8 takes a pointer in r0, and returns 0 in r2 + * on success, with the value in r0/r1; or else -EFAULT in r2. + */ + STD_ENTRY(__get_user_8); +1: { lw r0, r0; addi r1, r0, 4 }; +2: { lw r1, r1; move r2, zero }; + jrp lr; + STD_ENDPROC(__get_user_8); + .pushsection __ex_table,"a"; + .word 1b, get_user_fault; + .word 2b, get_user_fault; + .popsection + +/* + * __put_user_N functions take a value in r0 and a pointer in r1, + * and return 0 in r0 on success or -EFAULT on failure. + */ +#define __put_user_N(bytes, STORE) \ + STD_ENTRY(__put_user_##bytes); \ +1: { STORE r1, r0; move r0, zero }; \ + jrp lr; \ + STD_ENDPROC(__put_user_##bytes); \ + .pushsection __ex_table,"a"; \ + .word 1b, put_user_fault; \ + .popsection + +__put_user_N(1, sb) +__put_user_N(2, sh) +__put_user_N(4, sw) + +/* + * __put_user_8 takes a value in r0/r1 and a pointer in r2, + * and returns 0 in r0 on success or -EFAULT on failure. + */ +STD_ENTRY(__put_user_8) +1: { sw r2, r0; addi r2, r2, 4 } +2: { sw r2, r1; move r0, zero } + jrp lr + STD_ENDPROC(__put_user_8) + .pushsection __ex_table,"a" + .word 1b, put_user_fault + .word 2b, put_user_fault + .popsection + + +/* + * strnlen_user_asm takes the pointer in r0, and the length bound in r1. + * It returns the length, including the terminating NUL, or zero on exception. + * If length is greater than the bound, returns one plus the bound. + */ +STD_ENTRY(strnlen_user_asm) + { bz r1, 2f; addi r3, r0, -1 } /* bias down to include NUL */ +1: { lb_u r4, r0; addi r1, r1, -1 } + bz r4, 2f + { bnzt r1, 1b; addi r0, r0, 1 } +2: { sub r0, r0, r3; jrp lr } + STD_ENDPROC(strnlen_user_asm) + .pushsection .fixup,"ax" +strnlen_user_fault: + { move r0, zero; jrp lr } + ENDPROC(strnlen_user_fault) + .section __ex_table,"a" + .word 1b, strnlen_user_fault + .popsection + +/* + * strncpy_from_user_asm takes the kernel target pointer in r0, + * the userspace source pointer in r1, and the length bound (including + * the trailing NUL) in r2. On success, it returns the string length + * (not including the trailing NUL), or -EFAULT on failure. + */ +STD_ENTRY(strncpy_from_user_asm) + { bz r2, 2f; move r3, r0 } +1: { lb_u r4, r1; addi r1, r1, 1; addi r2, r2, -1 } + { sb r0, r4; addi r0, r0, 1 } + bz r2, 2f + bnzt r4, 1b + addi r0, r0, -1 /* don't count the trailing NUL */ +2: { sub r0, r0, r3; jrp lr } + STD_ENDPROC(strncpy_from_user_asm) + .pushsection .fixup,"ax" +strncpy_from_user_fault: + { movei r0, -EFAULT; jrp lr } + ENDPROC(strncpy_from_user_fault) + .section __ex_table,"a" + .word 1b, strncpy_from_user_fault + .popsection + +/* + * clear_user_asm takes the user target address in r0 and the + * number of bytes to zero in r1. + * It returns the number of uncopiable bytes (hopefully zero) in r0. + * Note that we don't use a separate .fixup section here since we fall + * through into the "fixup" code as the last straight-line bundle anyway. + */ +STD_ENTRY(clear_user_asm) + { bz r1, 2f; or r2, r0, r1 } + andi r2, r2, 3 + bzt r2, .Lclear_aligned_user_asm +1: { sb r0, zero; addi r0, r0, 1; addi r1, r1, -1 } + bnzt r1, 1b +2: { move r0, r1; jrp lr } + .pushsection __ex_table,"a" + .word 1b, 2b + .popsection + +.Lclear_aligned_user_asm: +1: { sw r0, zero; addi r0, r0, 4; addi r1, r1, -4 } + bnzt r1, 1b +2: { move r0, r1; jrp lr } + STD_ENDPROC(clear_user_asm) + .pushsection __ex_table,"a" + .word 1b, 2b + .popsection + +/* + * flush_user_asm takes the user target address in r0 and the + * number of bytes to flush in r1. + * It returns the number of unflushable bytes (hopefully zero) in r0. + */ +STD_ENTRY(flush_user_asm) + bz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { flush r0; addi r1, r1, -CHIP_FLUSH_STRIDE() } + { addi r0, r0, CHIP_FLUSH_STRIDE(); bnzt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(flush_user_asm) + .pushsection __ex_table,"a" + .word 1b, 2b + .popsection + +/* + * inv_user_asm takes the user target address in r0 and the + * number of bytes to invalidate in r1. + * It returns the number of not inv'able bytes (hopefully zero) in r0. + */ +STD_ENTRY(inv_user_asm) + bz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() } + { addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(inv_user_asm) + .pushsection __ex_table,"a" + .word 1b, 2b + .popsection + +/* + * finv_user_asm takes the user target address in r0 and the + * number of bytes to flush-invalidate in r1. + * It returns the number of not finv'able bytes (hopefully zero) in r0. + */ +STD_ENTRY(finv_user_asm) + bz r1, 2f + { movei r2, L2_CACHE_BYTES; add r1, r0, r1 } + { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 } + { and r0, r0, r2; and r1, r1, r2 } + { sub r1, r1, r0 } +1: { finv r0; addi r1, r1, -CHIP_FINV_STRIDE() } + { addi r0, r0, CHIP_FINV_STRIDE(); bnzt r1, 1b } +2: { move r0, r1; jrp lr } + STD_ENDPROC(finv_user_asm) + .pushsection __ex_table,"a" + .word 1b, 2b + .popsection diff --git a/arch/tile/mm/Makefile b/arch/tile/mm/Makefile new file mode 100644 index 000000000000..e252aeddc17d --- /dev/null +++ b/arch/tile/mm/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the linux tile-specific parts of the memory manager. +# + +obj-y := init.o pgtable.o fault.o extable.o elf.o \ + mmap.o homecache.o migrate_$(BITS).o + +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_HIGHMEM) += highmem.o diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c new file mode 100644 index 000000000000..818c9bef060c --- /dev/null +++ b/arch/tile/mm/elf.c @@ -0,0 +1,164 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Notify a running simulator, if any, that an exec just occurred. */ +static void sim_notify_exec(const char *binary_name) +{ + unsigned char c; + do { + c = *binary_name++; + __insn_mtspr(SPR_SIM_CONTROL, + (SIM_CONTROL_OS_EXEC + | (c << _SIM_CONTROL_OPERATOR_BITS))); + + } while (c); +} + +static int notify_exec(void) +{ + int retval = 0; /* failure */ + struct vm_area_struct *vma = current->mm->mmap; + while (vma) { + if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) + break; + vma = vma->vm_next; + } + if (vma) { + char *buf = (char *) __get_free_page(GFP_KERNEL); + if (buf) { + char *path = d_path(&vma->vm_file->f_path, + buf, PAGE_SIZE); + if (!IS_ERR(path)) { + sim_notify_exec(path); + retval = 1; + } + free_page((unsigned long)buf); + } + } + return retval; +} + +/* Notify a running simulator, if any, that we loaded an interpreter. */ +static void sim_notify_interp(unsigned long load_addr) +{ + size_t i; + for (i = 0; i < sizeof(load_addr); i++) { + unsigned char c = load_addr >> (i * 8); + __insn_mtspr(SPR_SIM_CONTROL, + (SIM_CONTROL_OS_INTERP + | (c << _SIM_CONTROL_OPERATOR_BITS))); + } +} + + +/* Kernel address of page used to map read-only kernel data into userspace. */ +static void *vdso_page; + +/* One-entry array used for install_special_mapping. */ +static struct page *vdso_pages[1]; + +int __init vdso_setup(void) +{ + extern char __rt_sigreturn[], __rt_sigreturn_end[]; + vdso_page = (void *)get_zeroed_page(GFP_ATOMIC); + memcpy(vdso_page, __rt_sigreturn, __rt_sigreturn_end - __rt_sigreturn); + vdso_pages[0] = virt_to_page(vdso_page); + return 0; +} +device_initcall(vdso_setup); + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_private_data == vdso_pages) + return "[vdso]"; +#ifndef __tilegx__ + if (vma->vm_start == MEM_USER_INTRPT) + return "[intrpt]"; +#endif + return NULL; +} + +int arch_setup_additional_pages(struct linux_binprm *bprm, + int executable_stack) +{ + struct mm_struct *mm = current->mm; + unsigned long vdso_base; + int retval = 0; + + /* + * Notify the simulator that an exec just occurred. + * If we can't find the filename of the mapping, just use + * whatever was passed as the linux_binprm filename. + */ + if (!notify_exec()) + sim_notify_exec(bprm->filename); + + down_write(&mm->mmap_sem); + + /* + * MAYWRITE to allow gdb to COW and set breakpoints + * + * Make sure the vDSO gets into every core dump. Dumping its + * contents makes post-mortem fully interpretable later + * without matching up the same kernel and hardware config to + * see what PC values meant. + */ + vdso_base = VDSO_BASE; + retval = install_special_mapping(mm, vdso_base, PAGE_SIZE, + VM_READ|VM_EXEC| + VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| + VM_ALWAYSDUMP, + vdso_pages); + +#ifndef __tilegx__ + /* + * Set up a user-interrupt mapping here; the user can't + * create one themselves since it is above TASK_SIZE. + * We make it unwritable by default, so the model for adding + * interrupt vectors always involves an mprotect. + */ + if (!retval) { + unsigned long addr = MEM_USER_INTRPT; + addr = mmap_region(NULL, addr, INTRPT_SIZE, + MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, + VM_READ|VM_EXEC| + VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 0); + if (addr > (unsigned long) -PAGE_SIZE) + retval = (int) addr; + } +#endif + + up_write(&mm->mmap_sem); + + return retval; +} + + +void elf_plat_init(struct pt_regs *regs, unsigned long load_addr) +{ + /* Zero all registers. */ + memset(regs, 0, sizeof(*regs)); + + /* Report the interpreter's load address. */ + sim_notify_interp(load_addr); +} diff --git a/arch/tile/mm/extable.c b/arch/tile/mm/extable.c new file mode 100644 index 000000000000..4fb0acb9d154 --- /dev/null +++ b/arch/tile/mm/extable.c @@ -0,0 +1,30 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return 1; + } + + return 0; +} diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c new file mode 100644 index 000000000000..9b6b92f07def --- /dev/null +++ b/arch/tile/mm/fault.c @@ -0,0 +1,905 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * From i386 code copyright (C) 1995 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For unblank_screen() */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Unlock any spinlocks which will prevent us from getting the + * message out + */ +void bust_spinlocks(int yes) +{ + int loglevel_save = console_loglevel; + + if (yes) { + oops_in_progress = 1; + return; + } + oops_in_progress = 0; + /* + * OK, the message is on the console. Now we call printk() + * without oops_in_progress set so that printk will give klogd + * a poke. Hold onto your hats... + */ + console_loglevel = 15; /* NMI oopser may have shut the console up */ + printk(" "); + console_loglevel = loglevel_save; +} + +static noinline void force_sig_info_fault(int si_signo, int si_code, + unsigned long address, int fault_num, struct task_struct *tsk) +{ + siginfo_t info; + + if (unlikely(tsk->pid < 2)) { + panic("Signal %d (code %d) at %#lx sent to %s!", + si_signo, si_code & 0xffff, address, + tsk->pid ? "init" : "the idle task"); + } + + info.si_signo = si_signo; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void __user *)address; + info.si_trapno = fault_num; + force_sig_info(si_signo, &info, tsk); +} + +#ifndef __tilegx__ +/* + * Synthesize the fault a PL0 process would get by doing a word-load of + * an unaligned address or a high kernel address. Called indirectly + * from sys_cmpxchg() in kernel/intvec.S. + */ +int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *regs) +{ + if (address >= PAGE_OFFSET) + force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address, + INT_DTLB_MISS, current); + else + force_sig_info_fault(SIGBUS, BUS_ADRALN, address, + INT_UNALIGN_DATA, current); + + /* + * Adjust pc to point at the actual instruction, which is unusual + * for syscalls normally, but is appropriate when we are claiming + * that a syscall swint1 caused a page fault or bus error. + */ + regs->pc -= 8; + + /* + * Mark this as a caller-save interrupt, like a normal page fault, + * so that when we go through the signal handler path we will + * properly restore r0, r1, and r2 for the signal handler arguments. + */ + regs->flags |= PT_FLAGS_CALLER_SAVES; + + return 0; +} +#endif + +static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) +{ + unsigned index = pgd_index(address); + pgd_t *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd += index; + pgd_k = init_mm.pgd + index; + + if (!pgd_present(*pgd_k)) + return NULL; + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (!pud_present(*pud_k)) + return NULL; + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + return NULL; + if (!pmd_present(*pmd)) { + set_pmd(pmd, *pmd_k); + arch_flush_lazy_mmu_mode(); + } else + BUG_ON(pmd_ptfn(*pmd) != pmd_ptfn(*pmd_k)); + return pmd_k; +} + +/* + * Handle a fault on the vmalloc or module mapping area + */ +static inline int vmalloc_fault(pgd_t *pgd, unsigned long address) +{ + pmd_t *pmd_k; + pte_t *pte_k; + + /* Make sure we are in vmalloc area */ + if (!(address >= VMALLOC_START && address < VMALLOC_END)) + return -1; + + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + */ + pmd_k = vmalloc_sync_one(pgd, address); + if (!pmd_k) + return -1; + if (pmd_huge(*pmd_k)) + return 0; /* support TILE huge_vmap() API */ + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + return -1; + return 0; +} + +/* Wait until this PTE has completed migration. */ +static void wait_for_migration(pte_t *pte) +{ + if (pte_migrating(*pte)) { + /* + * Wait until the migrater fixes up this pte. + * We scale the loop count by the clock rate so we'll wait for + * a few seconds here. + */ + int retries = 0; + int bound = get_clock_rate(); + while (pte_migrating(*pte)) { + barrier(); + if (++retries > bound) + panic("Hit migrating PTE (%#llx) and" + " page PFN %#lx still migrating", + pte->val, pte_pfn(*pte)); + } + } +} + +/* + * It's not generally safe to use "current" to get the page table pointer, + * since we might be running an oprofile interrupt in the middle of a + * task switch. + */ +static pgd_t *get_current_pgd(void) +{ + HV_Context ctx = hv_inquire_context(); + unsigned long pgd_pfn = ctx.page_table >> PAGE_SHIFT; + struct page *pgd_page = pfn_to_page(pgd_pfn); + BUG_ON(PageHighMem(pgd_page)); /* oops, HIGHPTE? */ + return (pgd_t *) __va(ctx.page_table); +} + +/* + * We can receive a page fault from a migrating PTE at any time. + * Handle it by just waiting until the fault resolves. + * + * It's also possible to get a migrating kernel PTE that resolves + * itself during the downcall from hypervisor to Linux. We just check + * here to see if the PTE seems valid, and if so we retry it. + * + * NOTE! We MUST NOT take any locks for this case. We may be in an + * interrupt or a critical region, and must do as little as possible. + * Similarly, we can't use atomic ops here, since we may be handling a + * fault caused by an atomic op access. + */ +static int handle_migrating_pte(pgd_t *pgd, int fault_num, + unsigned long address, + int is_kernel_mode, int write) +{ + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + pte_t pteval; + + if (pgd_addr_invalid(address)) + return 0; + + pgd += pgd_index(address); + pud = pud_offset(pgd, address); + if (!pud || !pud_present(*pud)) + return 0; + pmd = pmd_offset(pud, address); + if (!pmd || !pmd_present(*pmd)) + return 0; + pte = pmd_huge_page(*pmd) ? ((pte_t *)pmd) : + pte_offset_kernel(pmd, address); + pteval = *pte; + if (pte_migrating(pteval)) { + wait_for_migration(pte); + return 1; + } + + if (!is_kernel_mode || !pte_present(pteval)) + return 0; + if (fault_num == INT_ITLB_MISS) { + if (pte_exec(pteval)) + return 1; + } else if (write) { + if (pte_write(pteval)) + return 1; + } else { + if (pte_read(pteval)) + return 1; + } + + return 0; +} + +/* + * This routine is responsible for faulting in user pages. + * It passes the work off to one of the appropriate routines. + * It returns true if the fault was successfully handled. + */ +static int handle_page_fault(struct pt_regs *regs, + int fault_num, + int is_page_fault, + unsigned long address, + int write) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct *vma; + unsigned long stack_offset; + int fault; + int si_code; + int is_kernel_mode; + pgd_t *pgd; + + /* on TILE, protection faults are always writes */ + if (!is_page_fault) + write = 1; + + is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL); + + tsk = validate_current(); + + /* + * Check to see if we might be overwriting the stack, and bail + * out if so. The page fault code is a relatively likely + * place to get trapped in an infinite regress, and once we + * overwrite the whole stack, it becomes very hard to recover. + */ + stack_offset = stack_pointer & (THREAD_SIZE-1); + if (stack_offset < THREAD_SIZE / 8) { + printk(KERN_ALERT "Potential stack overrun: sp %#lx\n", + stack_pointer); + show_regs(regs); + printk(KERN_ALERT "Killing current process %d/%s\n", + tsk->pid, tsk->comm); + do_group_exit(SIGKILL); + } + + /* + * Early on, we need to check for migrating PTE entries; + * see homecache.c. If we find a migrating PTE, we wait until + * the backing page claims to be done migrating, then we procede. + * For kernel PTEs, we rewrite the PTE and return and retry. + * Otherwise, we treat the fault like a normal "no PTE" fault, + * rather than trying to patch up the existing PTE. + */ + pgd = get_current_pgd(); + if (handle_migrating_pte(pgd, fault_num, address, + is_kernel_mode, write)) + return 1; + + si_code = SEGV_MAPERR; + + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + * + * This verifies that the fault happens in kernel space + * and that the fault was not a protection fault. + */ + if (unlikely(address >= TASK_SIZE && + !is_arch_mappable_range(address, 0))) { + if (is_kernel_mode && is_page_fault && + vmalloc_fault(pgd, address) >= 0) + return 1; + /* + * Don't take the mm semaphore here. If we fixup a prefetch + * fault we could otherwise deadlock. + */ + mm = NULL; /* happy compiler */ + vma = NULL; + goto bad_area_nosemaphore; + } + + /* + * If we're trying to touch user-space addresses, we must + * be either at PL0, or else with interrupts enabled in the + * kernel, so either way we can re-enable interrupts here. + */ + local_irq_enable(); + + mm = tsk->mm; + + /* + * If we're in an interrupt, have no user context or are running in an + * atomic region then we must not take the fault. + */ + if (in_atomic() || !mm) { + vma = NULL; /* happy compiler */ + goto bad_area_nosemaphore; + } + + /* + * When running in the kernel we expect faults to occur only to + * addresses in user space. All other faults represent errors in the + * kernel and should generate an OOPS. Unfortunately, in the case of an + * erroneous fault occurring in a code path which already holds mmap_sem + * we will deadlock attempting to validate the fault against the + * address space. Luckily the kernel only validly references user + * space from well defined areas of code, which are listed in the + * exceptions table. + * + * As the vast majority of faults will be valid we will only perform + * the source reference check when there is a possibility of a deadlock. + * Attempt to lock the address space, if we cannot we then validate the + * source. If this is invalid we can skip the address space check, + * thus avoiding the deadlock. + */ + if (!down_read_trylock(&mm->mmap_sem)) { + if (is_kernel_mode && + !search_exception_tables(regs->pc)) { + vma = NULL; /* happy compiler */ + goto bad_area_nosemaphore; + } + down_read(&mm->mmap_sem); + } + + vma = find_vma(mm, address); + if (!vma) + goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (regs->sp < PAGE_OFFSET) { + /* + * accessing the stack below sp is always a bug. + */ + if (address < regs->sp) + goto bad_area; + } + if (expand_stack(vma, address)) + goto bad_area; + +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + si_code = SEGV_ACCERR; + if (fault_num == INT_ITLB_MISS) { + if (!(vma->vm_flags & VM_EXEC)) + goto bad_area; + } else if (write) { +#ifdef TEST_VERIFY_AREA + if (!is_page_fault && regs->cs == KERNEL_CS) + printk("WP fault at "REGFMT"\n", regs->eip); +#endif + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!is_page_fault || !(vma->vm_flags & VM_READ)) + goto bad_area; + } + + survive: + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + fault = handle_mm_fault(mm, vma, address, write); + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); + } + if (fault & VM_FAULT_MAJOR) + tsk->maj_flt++; + else + tsk->min_flt++; + + /* + * If this was an asynchronous fault, + * restart the appropriate engine. + */ + switch (fault_num) { +#if CHIP_HAS_TILE_DMA() + case INT_DMATLB_MISS: + case INT_DMATLB_MISS_DWNCL: + case INT_DMATLB_ACCESS: + case INT_DMATLB_ACCESS_DWNCL: + __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__REQUEST_MASK); + break; +#endif +#if CHIP_HAS_SN_PROC() + case INT_SNITLB_MISS: + case INT_SNITLB_MISS_DWNCL: + __insn_mtspr(SPR_SNCTL, + __insn_mfspr(SPR_SNCTL) & + ~SPR_SNCTL__FRZPROC_MASK); + break; +#endif + } + + up_read(&mm->mmap_sem); + return 1; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up_read(&mm->mmap_sem); + +bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (!is_kernel_mode) { + /* + * It's possible to have interrupts off here. + */ + local_irq_enable(); + + force_sig_info_fault(SIGSEGV, si_code, address, + fault_num, tsk); + return 0; + } + +no_context: + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) + return 0; + +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + + bust_spinlocks(1); + + /* FIXME: no lookup_address() yet */ +#ifdef SUPPORT_LOOKUP_ADDRESS + if (fault_num == INT_ITLB_MISS) { + pte_t *pte = lookup_address(address); + + if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) + printk(KERN_CRIT "kernel tried to execute" + " non-executable page - exploit attempt?" + " (uid: %d)\n", current->uid); + } +#endif + if (address < PAGE_SIZE) + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference\n"); + else + printk(KERN_ALERT "Unable to handle kernel paging request\n"); + printk(" at virtual address "REGFMT", pc "REGFMT"\n", + address, regs->pc); + + show_regs(regs); + + if (unlikely(tsk->pid < 2)) { + panic("Kernel page fault running %s!", + tsk->pid ? "init" : "the idle task"); + } + + /* + * More FIXME: we should probably copy the i386 here and + * implement a generic die() routine. Not today. + */ +#ifdef SUPPORT_DIE + die("Oops", regs); +#endif + bust_spinlocks(1); + + do_group_exit(SIGKILL); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + up_read(&mm->mmap_sem); + if (is_global_init(tsk)) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", tsk->comm); + if (!is_kernel_mode) + do_group_exit(SIGKILL); + goto no_context; + +do_sigbus: + up_read(&mm->mmap_sem); + + /* Kernel mode? Handle exceptions or die */ + if (is_kernel_mode) + goto no_context; + + force_sig_info_fault(SIGBUS, BUS_ADRERR, address, fault_num, tsk); + return 0; +} + +#ifndef __tilegx__ + +extern char sys_cmpxchg[], __sys_cmpxchg_end[]; +extern char __sys_cmpxchg_grab_lock[]; +extern char __start_atomic_asm_code[], __end_atomic_asm_code[]; + +/* + * We return this structure in registers to avoid having to write + * additional save/restore code in the intvec.S caller. + */ +struct intvec_state { + void *handler; + unsigned long vecnum; + unsigned long fault_num; + unsigned long info; + unsigned long retval; +}; + +/* We must release ICS before panicking or we won't get anywhere. */ +#define ics_panic(fmt, ...) do { \ + __insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0); \ + panic(fmt, __VA_ARGS__); \ +} while (0) + +void do_page_fault(struct pt_regs *regs, int fault_num, + unsigned long address, unsigned long write); + +/* + * When we take an ITLB or DTLB fault or access violation in the + * supervisor while the critical section bit is set, the hypervisor is + * reluctant to write new values into the EX_CONTEXT_1_x registers, + * since that might indicate we have not yet squirreled the SPR + * contents away and can thus safely take a recursive interrupt. + * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_1_2. + */ +struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num, + unsigned long address, + unsigned long info) +{ + unsigned long pc = info & ~1; + int write = info & 1; + pgd_t *pgd = get_current_pgd(); + + /* Retval is 1 at first since we will handle the fault fully. */ + struct intvec_state state = { + do_page_fault, fault_num, address, write, 1 + }; + + /* Validate that we are plausibly in the right routine. */ + if ((pc & 0x7) != 0 || pc < PAGE_OFFSET || + (fault_num != INT_DTLB_MISS && + fault_num != INT_DTLB_ACCESS)) { + unsigned long old_pc = regs->pc; + regs->pc = pc; + ics_panic("Bad ICS page fault args:" + " old PC %#lx, fault %d/%d at %#lx\n", + old_pc, fault_num, write, address); + } + + /* We might be faulting on a vmalloc page, so check that first. */ + if (fault_num != INT_DTLB_ACCESS && vmalloc_fault(pgd, address) >= 0) + return state; + + /* + * If we faulted with ICS set in sys_cmpxchg, we are providing + * a user syscall service that should generate a signal on + * fault. We didn't set up a kernel stack on initial entry to + * sys_cmpxchg, but instead had one set up by the fault, which + * (because sys_cmpxchg never releases ICS) came to us via the + * SYSTEM_SAVE_1_2 mechanism, and thus EX_CONTEXT_1_[01] are + * still referencing the original user code. We release the + * atomic lock and rewrite pt_regs so that it appears that we + * came from user-space directly, and after we finish the + * fault we'll go back to user space and re-issue the swint. + * This way the backtrace information is correct if we need to + * emit a stack dump at any point while handling this. + * + * Must match register use in sys_cmpxchg(). + */ + if (pc >= (unsigned long) sys_cmpxchg && + pc < (unsigned long) __sys_cmpxchg_end) { +#ifdef CONFIG_SMP + /* Don't unlock before we could have locked. */ + if (pc >= (unsigned long)__sys_cmpxchg_grab_lock) { + int *lock_ptr = (int *)(regs->regs[ATOMIC_LOCK_REG]); + __atomic_fault_unlock(lock_ptr); + } +#endif + regs->sp = regs->regs[27]; + } + + /* + * We can also fault in the atomic assembly, in which + * case we use the exception table to do the first-level fixup. + * We may re-fixup again in the real fault handler if it + * turns out the faulting address is just bad, and not, + * for example, migrating. + */ + else if (pc >= (unsigned long) __start_atomic_asm_code && + pc < (unsigned long) __end_atomic_asm_code) { + const struct exception_table_entry *fixup; +#ifdef CONFIG_SMP + /* Unlock the atomic lock. */ + int *lock_ptr = (int *)(regs->regs[ATOMIC_LOCK_REG]); + __atomic_fault_unlock(lock_ptr); +#endif + fixup = search_exception_tables(pc); + if (!fixup) + ics_panic("ICS atomic fault not in table:" + " PC %#lx, fault %d", pc, fault_num); + regs->pc = fixup->fixup; + regs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); + } + + /* + * NOTE: the one other type of access that might bring us here + * are the memory ops in __tns_atomic_acquire/__tns_atomic_release, + * but we don't have to check specially for them since we can + * always safely return to the address of the fault and retry, + * since no separate atomic locks are involved. + */ + + /* + * Now that we have released the atomic lock (if necessary), + * it's safe to spin if the PTE that caused the fault was migrating. + */ + if (fault_num == INT_DTLB_ACCESS) + write = 1; + if (handle_migrating_pte(pgd, fault_num, address, 1, write)) + return state; + + /* Return zero so that we continue on with normal fault handling. */ + state.retval = 0; + return state; +} + +#endif /* !__tilegx__ */ + +/* + * This routine handles page faults. It determines the address, and the + * problem, and then passes it handle_page_fault() for normal DTLB and + * ITLB issues, and for DMA or SN processor faults when we are in user + * space. For the latter, if we're in kernel mode, we just save the + * interrupt away appropriately and return immediately. We can't do + * page faults for user code while in kernel mode. + */ +void do_page_fault(struct pt_regs *regs, int fault_num, + unsigned long address, unsigned long write) +{ + int is_page_fault; + + /* This case should have been handled by do_page_fault_ics(). */ + BUG_ON(write & ~1); + +#if CHIP_HAS_TILE_DMA() + /* + * If it's a DMA fault, suspend the transfer while we're + * handling the miss; we'll restart after it's handled. If we + * don't suspend, it's possible that this process could swap + * out and back in, and restart the engine since the DMA is + * still 'running'. + */ + if (fault_num == INT_DMATLB_MISS || + fault_num == INT_DMATLB_ACCESS || + fault_num == INT_DMATLB_MISS_DWNCL || + fault_num == INT_DMATLB_ACCESS_DWNCL) { + __insn_mtspr(SPR_DMA_CTR, SPR_DMA_CTR__SUSPEND_MASK); + while (__insn_mfspr(SPR_DMA_USER_STATUS) & + SPR_DMA_STATUS__BUSY_MASK) + ; + } +#endif + + /* Validate fault num and decide if this is a first-time page fault. */ + switch (fault_num) { + case INT_ITLB_MISS: + case INT_DTLB_MISS: +#if CHIP_HAS_TILE_DMA() + case INT_DMATLB_MISS: + case INT_DMATLB_MISS_DWNCL: +#endif +#if CHIP_HAS_SN_PROC() + case INT_SNITLB_MISS: + case INT_SNITLB_MISS_DWNCL: +#endif + is_page_fault = 1; + break; + + case INT_DTLB_ACCESS: +#if CHIP_HAS_TILE_DMA() + case INT_DMATLB_ACCESS: + case INT_DMATLB_ACCESS_DWNCL: +#endif + is_page_fault = 0; + break; + + default: + panic("Bad fault number %d in do_page_fault", fault_num); + } + + if (EX1_PL(regs->ex1) != USER_PL) { + struct async_tlb *async; + switch (fault_num) { +#if CHIP_HAS_TILE_DMA() + case INT_DMATLB_MISS: + case INT_DMATLB_ACCESS: + case INT_DMATLB_MISS_DWNCL: + case INT_DMATLB_ACCESS_DWNCL: + async = ¤t->thread.dma_async_tlb; + break; +#endif +#if CHIP_HAS_SN_PROC() + case INT_SNITLB_MISS: + case INT_SNITLB_MISS_DWNCL: + async = ¤t->thread.sn_async_tlb; + break; +#endif + default: + async = NULL; + } + if (async) { + + /* + * No vmalloc check required, so we can allow + * interrupts immediately at this point. + */ + local_irq_enable(); + + set_thread_flag(TIF_ASYNC_TLB); + if (async->fault_num != 0) { + panic("Second async fault %d;" + " old fault was %d (%#lx/%ld)", + fault_num, async->fault_num, + address, write); + } + BUG_ON(fault_num == 0); + async->fault_num = fault_num; + async->is_fault = is_page_fault; + async->is_write = write; + async->address = address; + return; + } + } + + handle_page_fault(regs, fault_num, is_page_fault, address, write); +} + + +#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() +/* + * Check an async_tlb structure to see if a deferred fault is waiting, + * and if so pass it to the page-fault code. + */ +static void handle_async_page_fault(struct pt_regs *regs, + struct async_tlb *async) +{ + if (async->fault_num) { + /* + * Clear async->fault_num before calling the page-fault + * handler so that if we re-interrupt before returning + * from the function we have somewhere to put the + * information from the new interrupt. + */ + int fault_num = async->fault_num; + async->fault_num = 0; + handle_page_fault(regs, fault_num, async->is_fault, + async->address, async->is_write); + } +} +#endif /* CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() */ + + +/* + * This routine effectively re-issues asynchronous page faults + * when we are returning to user space. + */ +void do_async_page_fault(struct pt_regs *regs) +{ + /* + * Clear thread flag early. If we re-interrupt while processing + * code here, we will reset it and recall this routine before + * returning to user space. + */ + clear_thread_flag(TIF_ASYNC_TLB); + +#if CHIP_HAS_TILE_DMA() + handle_async_page_fault(regs, ¤t->thread.dma_async_tlb); +#endif +#if CHIP_HAS_SN_PROC() + handle_async_page_fault(regs, ¤t->thread.sn_async_tlb); +#endif +} + +void vmalloc_sync_all(void) +{ +#ifdef __tilegx__ + /* Currently all L1 kernel pmd's are static and shared. */ + BUG_ON(pgd_index(VMALLOC_END) != pgd_index(VMALLOC_START)); +#else + /* + * Note that races in the updates of insync and start aren't + * problematic: insync can only get set bits added, and updates to + * start are only improving performance (without affecting correctness + * if undone). + */ + static DECLARE_BITMAP(insync, PTRS_PER_PGD); + static unsigned long start = PAGE_OFFSET; + unsigned long address; + + BUILD_BUG_ON(PAGE_OFFSET & ~PGDIR_MASK); + for (address = start; address >= PAGE_OFFSET; address += PGDIR_SIZE) { + if (!test_bit(pgd_index(address), insync)) { + unsigned long flags; + struct list_head *pos; + + spin_lock_irqsave(&pgd_lock, flags); + list_for_each(pos, &pgd_list) + if (!vmalloc_sync_one(list_to_pgd(pos), + address)) { + /* Must be at first entry in list. */ + BUG_ON(pos != pgd_list.next); + break; + } + spin_unlock_irqrestore(&pgd_lock, flags); + if (pos != pgd_list.next) + set_bit(pgd_index(address), insync); + } + if (address == start && test_bit(pgd_index(address), insync)) + start = address + PGDIR_SIZE; + } +#endif +} diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c new file mode 100644 index 000000000000..1fcecc5b9e03 --- /dev/null +++ b/arch/tile/mm/highmem.c @@ -0,0 +1,328 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +#define kmap_get_pte(vaddr) \ + pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ + (vaddr)), (vaddr)) + + +void *kmap(struct page *page) +{ + void *kva; + unsigned long flags; + pte_t *ptep; + + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + kva = kmap_high(page); + + /* + * Rewrite the PTE under the lock. This ensures that the page + * is not currently migrating. + */ + ptep = kmap_get_pte((unsigned long)kva); + flags = homecache_kpte_lock(); + set_pte_at(&init_mm, kva, ptep, mk_pte(page, page_to_kpgprot(page))); + homecache_kpte_unlock(flags); + + return kva; +} +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} +EXPORT_SYMBOL(kunmap); + +static void debug_kmap_atomic_prot(enum km_type type) +{ +#ifdef CONFIG_DEBUG_HIGHMEM + static unsigned warn_count = 10; + + if (unlikely(warn_count == 0)) + return; + + if (unlikely(in_interrupt())) { + if (in_irq()) { + if (type != KM_IRQ0 && type != KM_IRQ1 && + type != KM_BIO_SRC_IRQ && + /* type != KM_BIO_DST_IRQ && */ + type != KM_BOUNCE_READ) { + WARN_ON(1); + warn_count--; + } + } else if (!irqs_disabled()) { /* softirq */ + if (type != KM_IRQ0 && type != KM_IRQ1 && + type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && + type != KM_SKB_SUNRPC_DATA && + type != KM_SKB_DATA_SOFTIRQ && + type != KM_BOUNCE_READ) { + WARN_ON(1); + warn_count--; + } + } + } + + if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || + type == KM_BIO_SRC_IRQ /* || type == KM_BIO_DST_IRQ */) { + if (!irqs_disabled()) { + WARN_ON(1); + warn_count--; + } + } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { + if (irq_count() == 0 && !irqs_disabled()) { + WARN_ON(1); + warn_count--; + } + } +#endif +} + +/* + * Describe a single atomic mapping of a page on a given cpu at a + * given address, and allow it to be linked into a list. + */ +struct atomic_mapped_page { + struct list_head list; + struct page *page; + int cpu; + unsigned long va; +}; + +static spinlock_t amp_lock = __SPIN_LOCK_UNLOCKED(&_lock); +static struct list_head amp_list = LIST_HEAD_INIT(amp_list); + +/* + * Combining this structure with a per-cpu declaration lets us give + * each cpu an atomic_mapped_page structure per type. + */ +struct kmap_amps { + struct atomic_mapped_page per_type[KM_TYPE_NR]; +}; +DEFINE_PER_CPU(struct kmap_amps, amps); + +/* + * Add a page and va, on this cpu, to the list of kmap_atomic pages, + * and write the new pte to memory. Writing the new PTE under the + * lock guarantees that it is either on the list before migration starts + * (if we won the race), or set_pte() sets the migrating bit in the PTE + * (if we lost the race). And doing it under the lock guarantees + * that when kmap_atomic_fix_one_pte() comes along, it finds a valid + * PTE in memory, iff the mapping is still on the amp_list. + * + * Finally, doing it under the lock lets us safely examine the page + * to see if it is immutable or not, for the generic kmap_atomic() case. + * If we examine it earlier we are exposed to a race where it looks + * writable earlier, but becomes immutable before we write the PTE. + */ +static void kmap_atomic_register(struct page *page, enum km_type type, + unsigned long va, pte_t *ptep, pte_t pteval) +{ + unsigned long flags; + struct atomic_mapped_page *amp; + + flags = homecache_kpte_lock(); + spin_lock(&_lock); + + /* With interrupts disabled, now fill in the per-cpu info. */ + amp = &__get_cpu_var(amps).per_type[type]; + amp->page = page; + amp->cpu = smp_processor_id(); + amp->va = va; + + /* For generic kmap_atomic(), choose the PTE writability now. */ + if (!pte_read(pteval)) + pteval = mk_pte(page, page_to_kpgprot(page)); + + list_add(&->list, &_list); + set_pte(ptep, pteval); + arch_flush_lazy_mmu_mode(); + + spin_unlock(&_lock); + homecache_kpte_unlock(flags); +} + +/* + * Remove a page and va, on this cpu, from the list of kmap_atomic pages. + * Linear-time search, but we count on the lists being short. + * We don't need to adjust the PTE under the lock (as opposed to the + * kmap_atomic_register() case), since we're just unconditionally + * zeroing the PTE after it's off the list. + */ +static void kmap_atomic_unregister(struct page *page, unsigned long va) +{ + unsigned long flags; + struct atomic_mapped_page *amp; + int cpu = smp_processor_id(); + spin_lock_irqsave(&_lock, flags); + list_for_each_entry(amp, &_list, list) { + if (amp->page == page && amp->cpu == cpu && amp->va == va) + break; + } + BUG_ON(&->list == &_list); + list_del(&->list); + spin_unlock_irqrestore(&_lock, flags); +} + +/* Helper routine for kmap_atomic_fix_kpte(), below. */ +static void kmap_atomic_fix_one_kpte(struct atomic_mapped_page *amp, + int finished) +{ + pte_t *ptep = kmap_get_pte(amp->va); + if (!finished) { + set_pte(ptep, pte_mkmigrate(*ptep)); + flush_remote(0, 0, NULL, amp->va, PAGE_SIZE, PAGE_SIZE, + cpumask_of(amp->cpu), NULL, 0); + } else { + /* + * Rewrite a default kernel PTE for this page. + * We rely on the fact that set_pte() writes the + * present+migrating bits last. + */ + pte_t pte = mk_pte(amp->page, page_to_kpgprot(amp->page)); + set_pte(ptep, pte); + } +} + +/* + * This routine is a helper function for homecache_fix_kpte(); see + * its comments for more information on the "finished" argument here. + * + * Note that we hold the lock while doing the remote flushes, which + * will stall any unrelated cpus trying to do kmap_atomic operations. + * We could just update the PTEs under the lock, and save away copies + * of the structs (or just the va+cpu), then flush them after we + * release the lock, but it seems easier just to do it all under the lock. + */ +void kmap_atomic_fix_kpte(struct page *page, int finished) +{ + struct atomic_mapped_page *amp; + unsigned long flags; + spin_lock_irqsave(&_lock, flags); + list_for_each_entry(amp, &_list, list) { + if (amp->page == page) + kmap_atomic_fix_one_kpte(amp, finished); + } + spin_unlock_irqrestore(&_lock, flags); +} + +/* + * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap + * because the kmap code must perform a global TLB invalidation when + * the kmap pool wraps. + * + * Note that they may be slower than on x86 (etc.) because unlike on + * those platforms, we do have to take a global lock to map and unmap + * pages on Tile (see above). + * + * When holding an atomic kmap is is not legal to sleep, so atomic + * kmaps are appropriate for short, tight code paths only. + */ +void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) +{ + enum fixed_addresses idx; + unsigned long vaddr; + pte_t *pte; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + pagefault_disable(); + + /* Avoid icache flushes by disallowing atomic executable mappings. */ + BUG_ON(pte_exec(prot)); + + if (!PageHighMem(page)) + return page_address(page); + + debug_kmap_atomic_prot(type); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + pte = kmap_get_pte(vaddr); + BUG_ON(!pte_none(*pte)); + + /* Register that this page is mapped atomically on this cpu. */ + kmap_atomic_register(page, type, vaddr, pte, mk_pte(page, prot)); + + return (void *)vaddr; +} +EXPORT_SYMBOL(kmap_atomic_prot); + +void *kmap_atomic(struct page *page, enum km_type type) +{ + /* PAGE_NONE is a magic value that tells us to check immutability. */ + return kmap_atomic_prot(page, type, PAGE_NONE); +} +EXPORT_SYMBOL(kmap_atomic); + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + /* + * Force other mappings to Oops if they try to access this pte without + * first remapping it. Keeping stale mappings around is a bad idea. + */ + if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) { + pte_t *pte = kmap_get_pte(vaddr); + pte_t pteval = *pte; + BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); + kmap_atomic_unregister(pte_page(pteval), vaddr); + kpte_clear_flush(pte, vaddr); + } else { + /* Must be a lowmem page */ + BUG_ON(vaddr < PAGE_OFFSET); + BUG_ON(vaddr >= (unsigned long)high_memory); + } + + arch_flush_lazy_mmu_mode(); + pagefault_enable(); +} +EXPORT_SYMBOL(kunmap_atomic); + +/* + * This API is supposed to allow us to map memory without a "struct page". + * Currently we don't support this, though this may change in the future. + */ +void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) +{ + return kmap_atomic(pfn_to_page(pfn), type); +} +void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) +{ + return kmap_atomic_prot(pfn_to_page(pfn), type, prot); +} + +struct page *kmap_atomic_to_page(void *ptr) +{ + pte_t *pte; + unsigned long vaddr = (unsigned long)ptr; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + pte = kmap_get_pte(vaddr); + return pte_page(*pte); +} diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c new file mode 100644 index 000000000000..52feb77133ce --- /dev/null +++ b/arch/tile/mm/homecache.c @@ -0,0 +1,445 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This code maintains the "home" for each page in the system. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "migrate.h" + + +#if CHIP_HAS_COHERENT_LOCAL_CACHE() + +/* + * The noallocl2 option suppresses all use of the L2 cache to cache + * locally from a remote home. There's no point in using it if we + * don't have coherent local caching, though. + */ +int __write_once noallocl2; +static int __init set_noallocl2(char *str) +{ + noallocl2 = 1; + return 0; +} +early_param("noallocl2", set_noallocl2); + +#else + +#define noallocl2 0 + +#endif + + + +/* Provide no-op versions of these routines to keep flush_remote() cleaner. */ +#define mark_caches_evicted_start() 0 +#define mark_caches_evicted_finish(mask, timestamp) do {} while (0) + + + + +/* + * Update the irq_stat for cpus that we are going to interrupt + * with TLB or cache flushes. Also handle removing dataplane cpus + * from the TLB flush set, and setting dataplane_tlb_state instead. + */ +static void hv_flush_update(const struct cpumask *cache_cpumask, + struct cpumask *tlb_cpumask, + unsigned long tlb_va, unsigned long tlb_length, + HV_Remote_ASID *asids, int asidcount) +{ + struct cpumask mask; + int i, cpu; + + cpumask_clear(&mask); + if (cache_cpumask) + cpumask_or(&mask, &mask, cache_cpumask); + if (tlb_cpumask && tlb_length) { + cpumask_or(&mask, &mask, tlb_cpumask); + } + + for (i = 0; i < asidcount; ++i) + cpumask_set_cpu(asids[i].y * smp_width + asids[i].x, &mask); + + /* + * Don't bother to update atomically; losing a count + * here is not that critical. + */ + for_each_cpu(cpu, &mask) + ++per_cpu(irq_stat, cpu).irq_hv_flush_count; +} + +/* + * This wrapper function around hv_flush_remote() does several things: + * + * - Provides a return value error-checking panic path, since + * there's never any good reason for hv_flush_remote() to fail. + * - Accepts a 32-bit PFN rather than a 64-bit PA, which generally + * is the type that Linux wants to pass around anyway. + * - Centralizes the mark_caches_evicted() handling. + * - Canonicalizes that lengths of zero make cpumasks NULL. + * - Handles deferring TLB flushes for dataplane tiles. + * - Tracks remote interrupts in the per-cpu irq_cpustat_t. + * + * Note that we have to wait until the cache flush completes before + * updating the per-cpu last_cache_flush word, since otherwise another + * concurrent flush can race, conclude the flush has already + * completed, and start to use the page while it's still dirty + * remotely (running concurrently with the actual evict, presumably). + */ +void flush_remote(unsigned long cache_pfn, unsigned long cache_control, + const struct cpumask *cache_cpumask_orig, + HV_VirtAddr tlb_va, unsigned long tlb_length, + unsigned long tlb_pgsize, + const struct cpumask *tlb_cpumask_orig, + HV_Remote_ASID *asids, int asidcount) +{ + int rc; + int timestamp = 0; /* happy compiler */ + struct cpumask cache_cpumask_copy, tlb_cpumask_copy; + struct cpumask *cache_cpumask, *tlb_cpumask; + HV_PhysAddr cache_pa; + char cache_buf[NR_CPUS*5], tlb_buf[NR_CPUS*5]; + + mb(); /* provided just to simplify "magic hypervisor" mode */ + + /* + * Canonicalize and copy the cpumasks. + */ + if (cache_cpumask_orig && cache_control) { + cpumask_copy(&cache_cpumask_copy, cache_cpumask_orig); + cache_cpumask = &cache_cpumask_copy; + } else { + cpumask_clear(&cache_cpumask_copy); + cache_cpumask = NULL; + } + if (cache_cpumask == NULL) + cache_control = 0; + if (tlb_cpumask_orig && tlb_length) { + cpumask_copy(&tlb_cpumask_copy, tlb_cpumask_orig); + tlb_cpumask = &tlb_cpumask_copy; + } else { + cpumask_clear(&tlb_cpumask_copy); + tlb_cpumask = NULL; + } + + hv_flush_update(cache_cpumask, tlb_cpumask, tlb_va, tlb_length, + asids, asidcount); + cache_pa = (HV_PhysAddr)cache_pfn << PAGE_SHIFT; + if (cache_control & HV_FLUSH_EVICT_L2) + timestamp = mark_caches_evicted_start(); + rc = hv_flush_remote(cache_pa, cache_control, + cpumask_bits(cache_cpumask), + tlb_va, tlb_length, tlb_pgsize, + cpumask_bits(tlb_cpumask), + asids, asidcount); + if (cache_control & HV_FLUSH_EVICT_L2) + mark_caches_evicted_finish(cache_cpumask, timestamp); + if (rc == 0) + return; + cpumask_scnprintf(cache_buf, sizeof(cache_buf), &cache_cpumask_copy); + cpumask_scnprintf(tlb_buf, sizeof(tlb_buf), &tlb_cpumask_copy); + + printk("hv_flush_remote(%#llx, %#lx, %p [%s]," + " %#lx, %#lx, %#lx, %p [%s], %p, %d) = %d\n", + cache_pa, cache_control, cache_cpumask, cache_buf, + (unsigned long)tlb_va, tlb_length, tlb_pgsize, + tlb_cpumask, tlb_buf, + asids, asidcount, rc); + if (asidcount > 0) { + int i; + printk(" asids:"); + for (i = 0; i < asidcount; ++i) + printk(" %d,%d,%d", + asids[i].x, asids[i].y, asids[i].asid); + printk("\n"); + } + panic("Unsafe to continue."); +} + +void homecache_evict(const struct cpumask *mask) +{ + flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0); +} + +/* Return a mask of the cpus whose caches currently own these pages. */ +static void homecache_mask(struct page *page, int pages, + struct cpumask *home_mask) +{ + int i; + cpumask_clear(home_mask); + for (i = 0; i < pages; ++i) { + int home = page_home(&page[i]); + if (home == PAGE_HOME_IMMUTABLE || + home == PAGE_HOME_INCOHERENT) { + cpumask_copy(home_mask, cpu_possible_mask); + return; + } +#if CHIP_HAS_CBOX_HOME_MAP() + if (home == PAGE_HOME_HASH) { + cpumask_or(home_mask, home_mask, &hash_for_home_map); + continue; + } +#endif + if (home == PAGE_HOME_UNCACHED) + continue; + BUG_ON(home < 0 || home >= NR_CPUS); + cpumask_set_cpu(home, home_mask); + } +} + +/* + * Return the passed length, or zero if it's long enough that we + * believe we should evict the whole L2 cache. + */ +static unsigned long cache_flush_length(unsigned long length) +{ + return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; +} + +/* On the simulator, confirm lines have been evicted everywhere. */ +static void validate_lines_evicted(unsigned long pfn, size_t length) +{ + sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, + (HV_PhysAddr)pfn << PAGE_SHIFT, length); +} + +/* Flush a page out of whatever cache(s) it is in. */ +void homecache_flush_cache(struct page *page, int order) +{ + int pages = 1 << order; + int length = cache_flush_length(pages * PAGE_SIZE); + unsigned long pfn = page_to_pfn(page); + struct cpumask home_mask; + + homecache_mask(page, pages, &home_mask); + flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); + validate_lines_evicted(pfn, pages * PAGE_SIZE); +} + + +/* Report the home corresponding to a given PTE. */ +static int pte_to_home(pte_t pte) +{ + if (hv_pte_get_nc(pte)) + return PAGE_HOME_IMMUTABLE; + switch (hv_pte_get_mode(pte)) { + case HV_PTE_MODE_CACHE_TILE_L3: + return get_remote_cache_cpu(pte); + case HV_PTE_MODE_CACHE_NO_L3: + return PAGE_HOME_INCOHERENT; + case HV_PTE_MODE_UNCACHED: + return PAGE_HOME_UNCACHED; +#if CHIP_HAS_CBOX_HOME_MAP() + case HV_PTE_MODE_CACHE_HASH_L3: + return PAGE_HOME_HASH; +#endif + } + panic("Bad PTE %#llx\n", pte.val); +} + +/* Update the home of a PTE if necessary (can also be used for a pgprot_t). */ +pte_t pte_set_home(pte_t pte, int home) +{ + /* Check for non-linear file mapping "PTEs" and pass them through. */ + if (pte_file(pte)) + return pte; + +#if CHIP_HAS_MMIO() + /* Check for MMIO mappings and pass them through. */ + if (hv_pte_get_mode(pte) == HV_PTE_MODE_MMIO) + return pte; +#endif + + + /* + * Only immutable pages get NC mappings. If we have a + * non-coherent PTE, but the underlying page is not + * immutable, it's likely the result of a forced + * caching setting running up against ptrace setting + * the page to be writable underneath. In this case, + * just keep the PTE coherent. + */ + if (hv_pte_get_nc(pte) && home != PAGE_HOME_IMMUTABLE) { + pte = hv_pte_clear_nc(pte); + printk("non-immutable page incoherently referenced: %#llx\n", + pte.val); + } + + switch (home) { + + case PAGE_HOME_UNCACHED: + pte = hv_pte_set_mode(pte, HV_PTE_MODE_UNCACHED); + break; + + case PAGE_HOME_INCOHERENT: + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); + break; + + case PAGE_HOME_IMMUTABLE: + /* + * We could home this page anywhere, since it's immutable, + * but by default just home it to follow "hash_default". + */ + BUG_ON(hv_pte_get_writable(pte)); + if (pte_get_forcecache(pte)) { + /* Upgrade "force any cpu" to "No L3" for immutable. */ + if (hv_pte_get_mode(pte) == HV_PTE_MODE_CACHE_TILE_L3 + && pte_get_anyhome(pte)) { + pte = hv_pte_set_mode(pte, + HV_PTE_MODE_CACHE_NO_L3); + } + } else +#if CHIP_HAS_CBOX_HOME_MAP() + if (hash_default) + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_HASH_L3); + else +#endif + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); + pte = hv_pte_set_nc(pte); + break; + +#if CHIP_HAS_CBOX_HOME_MAP() + case PAGE_HOME_HASH: + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_HASH_L3); + break; +#endif + + default: + BUG_ON(home < 0 || home >= NR_CPUS || + !cpu_is_valid_lotar(home)); + pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3); + pte = set_remote_cache_cpu(pte, home); + break; + } + +#if CHIP_HAS_NC_AND_NOALLOC_BITS() + if (noallocl2) + pte = hv_pte_set_no_alloc_l2(pte); + + /* Simplify "no local and no l3" to "uncached" */ + if (hv_pte_get_no_alloc_l2(pte) && hv_pte_get_no_alloc_l1(pte) && + hv_pte_get_mode(pte) == HV_PTE_MODE_CACHE_NO_L3) { + pte = hv_pte_set_mode(pte, HV_PTE_MODE_UNCACHED); + } +#endif + + /* Checking this case here gives a better panic than from the hv. */ + BUG_ON(hv_pte_get_mode(pte) == 0); + + return pte; +} + +/* + * The routines in this section are the "static" versions of the normal + * dynamic homecaching routines; they just set the home cache + * of a kernel page once, and require a full-chip cache/TLB flush, + * so they're not suitable for anything but infrequent use. + */ + +#if CHIP_HAS_CBOX_HOME_MAP() +static inline int initial_page_home(void) { return PAGE_HOME_HASH; } +#else +static inline int initial_page_home(void) { return 0; } +#endif + +int page_home(struct page *page) +{ + if (PageHighMem(page)) { + return initial_page_home(); + } else { + unsigned long kva = (unsigned long)page_address(page); + return pte_to_home(*virt_to_pte(NULL, kva)); + } +} + +void homecache_change_page_home(struct page *page, int order, int home) +{ + int i, pages = (1 << order); + unsigned long kva; + + BUG_ON(PageHighMem(page)); + BUG_ON(page_count(page) > 1); + BUG_ON(page_mapcount(page) != 0); + kva = (unsigned long) page_address(page); + flush_remote(0, HV_FLUSH_EVICT_L2, &cpu_cacheable_map, + kva, pages * PAGE_SIZE, PAGE_SIZE, cpu_online_mask, + NULL, 0); + + for (i = 0; i < pages; ++i, kva += PAGE_SIZE) { + pte_t *ptep = virt_to_pte(NULL, kva); + pte_t pteval = *ptep; + BUG_ON(!pte_present(pteval) || pte_huge(pteval)); + *ptep = pte_set_home(pteval, home); + } +} + +struct page *homecache_alloc_pages(gfp_t gfp_mask, + unsigned int order, int home) +{ + struct page *page; + BUG_ON(gfp_mask & __GFP_HIGHMEM); /* must be lowmem */ + page = alloc_pages(gfp_mask, order); + if (page) + homecache_change_page_home(page, order, home); + return page; +} + +struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask, + unsigned int order, int home) +{ + struct page *page; + BUG_ON(gfp_mask & __GFP_HIGHMEM); /* must be lowmem */ + page = alloc_pages_node(nid, gfp_mask, order); + if (page) + homecache_change_page_home(page, order, home); + return page; +} + +void homecache_free_pages(unsigned long addr, unsigned int order) +{ + struct page *page; + + if (addr == 0) + return; + + VM_BUG_ON(!virt_addr_valid((void *)addr)); + page = virt_to_page((void *)addr); + if (put_page_testzero(page)) { + int pages = (1 << order); + homecache_change_page_home(page, order, initial_page_home()); + while (pages--) + __free_page(page++); + } +} diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c new file mode 100644 index 000000000000..c38570f8f0d0 --- /dev/null +++ b/arch/tile/mm/hugetlbpage.c @@ -0,0 +1,343 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * TILE Huge TLB Page Support for Kernel. + * Taken from i386 hugetlb implementation: + * Copyright (C) 2002, Rohit Seth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +pte_t *huge_pte_alloc(struct mm_struct *mm, + unsigned long addr, unsigned long sz) +{ + pgd_t *pgd; + pud_t *pud; + pte_t *pte = NULL; + + /* We do not yet support multiple huge page sizes. */ + BUG_ON(sz != PMD_SIZE); + + pgd = pgd_offset(mm, addr); + pud = pud_alloc(mm, pgd, addr); + if (pud) + pte = (pte_t *) pmd_alloc(mm, pud, addr); + BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); + + return pte; +} + +pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd = NULL; + + pgd = pgd_offset(mm, addr); + if (pgd_present(*pgd)) { + pud = pud_offset(pgd, addr); + if (pud_present(*pud)) + pmd = pmd_offset(pud, addr); + } + return (pte_t *) pmd; +} + +#ifdef HUGETLB_TEST +struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + int write) +{ + unsigned long start = address; + int length = 1; + int nr; + struct page *page; + struct vm_area_struct *vma; + + vma = find_vma(mm, addr); + if (!vma || !is_vm_hugetlb_page(vma)) + return ERR_PTR(-EINVAL); + + pte = huge_pte_offset(mm, address); + + /* hugetlb should be locked, and hence, prefaulted */ + WARN_ON(!pte || pte_none(*pte)); + + page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; + + WARN_ON(!PageHead(page)); + + return page; +} + +int pmd_huge(pmd_t pmd) +{ + return 0; +} + +int pud_huge(pud_t pud) +{ + return 0; +} + +struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, + pmd_t *pmd, int write) +{ + return NULL; +} + +#else + +struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + int write) +{ + return ERR_PTR(-EINVAL); +} + +int pmd_huge(pmd_t pmd) +{ + return !!(pmd_val(pmd) & _PAGE_HUGE_PAGE); +} + +int pud_huge(pud_t pud) +{ + return !!(pud_val(pud) & _PAGE_HUGE_PAGE); +} + +struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, + pmd_t *pmd, int write) +{ + struct page *page; + + page = pte_page(*(pte_t *)pmd); + if (page) + page += ((address & ~PMD_MASK) >> PAGE_SHIFT); + return page; +} + +struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address, + pud_t *pud, int write) +{ + struct page *page; + + page = pte_page(*(pte_t *)pud); + if (page) + page += ((address & ~PUD_MASK) >> PAGE_SHIFT); + return page; +} + +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + +#endif + +#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA +static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct hstate *h = hstate_file(file); + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start_addr; + + if (len > mm->cached_hole_size) { + start_addr = mm->free_area_cache; + } else { + start_addr = TASK_UNMAPPED_BASE; + mm->cached_hole_size = 0; + } + +full_search: + addr = ALIGN(start_addr, huge_page_size(h)); + + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) { + /* + * Start a new search - just in case we missed + * some holes. + */ + if (start_addr != TASK_UNMAPPED_BASE) { + start_addr = TASK_UNMAPPED_BASE; + mm->cached_hole_size = 0; + goto full_search; + } + return -ENOMEM; + } + if (!vma || addr + len <= vma->vm_start) { + mm->free_area_cache = addr + len; + return addr; + } + if (addr + mm->cached_hole_size < vma->vm_start) + mm->cached_hole_size = vma->vm_start - addr; + addr = ALIGN(vma->vm_end, huge_page_size(h)); + } +} + +static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, + unsigned long addr0, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct hstate *h = hstate_file(file); + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma, *prev_vma; + unsigned long base = mm->mmap_base, addr = addr0; + unsigned long largest_hole = mm->cached_hole_size; + int first_time = 1; + + /* don't allow allocations above current base */ + if (mm->free_area_cache > base) + mm->free_area_cache = base; + + if (len <= largest_hole) { + largest_hole = 0; + mm->free_area_cache = base; + } +try_again: + /* make sure it can fit in the remaining address space */ + if (mm->free_area_cache < len) + goto fail; + + /* either no address requested or cant fit in requested address hole */ + addr = (mm->free_area_cache - len) & huge_page_mask(h); + do { + /* + * Lookup failure means no vma is above this address, + * i.e. return with success: + */ + vma = find_vma_prev(mm, addr, &prev_vma); + if (!vma) { + return addr; + break; + } + + /* + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ + if (addr + len <= vma->vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) { + /* remember the address as a hint for next time */ + mm->cached_hole_size = largest_hole; + mm->free_area_cache = addr; + return addr; + } else { + /* pull free_area_cache down to the first hole */ + if (mm->free_area_cache == vma->vm_end) { + mm->free_area_cache = vma->vm_start; + mm->cached_hole_size = largest_hole; + } + } + + /* remember the largest hole we saw so far */ + if (addr + largest_hole < vma->vm_start) + largest_hole = vma->vm_start - addr; + + /* try just below the current vma->vm_start */ + addr = (vma->vm_start - len) & huge_page_mask(h); + + } while (len <= vma->vm_start); + +fail: + /* + * if hint left us with no space for the requested + * mapping then try again: + */ + if (first_time) { + mm->free_area_cache = base; + largest_hole = 0; + first_time = 0; + goto try_again; + } + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + mm->free_area_cache = TASK_UNMAPPED_BASE; + mm->cached_hole_size = ~0UL; + addr = hugetlb_get_unmapped_area_bottomup(file, addr0, + len, pgoff, flags); + + /* + * Restore the topdown base: + */ + mm->free_area_cache = base; + mm->cached_hole_size = ~0UL; + + return addr; +} + +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct hstate *h = hstate_file(file); + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + + if (len & ~huge_page_mask(h)) + return -EINVAL; + if (len > TASK_SIZE) + return -ENOMEM; + + if (flags & MAP_FIXED) { + if (prepare_hugepage_range(file, addr, len)) + return -EINVAL; + return addr; + } + + if (addr) { + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + if (current->mm->get_unmapped_area == arch_get_unmapped_area) + return hugetlb_get_unmapped_area_bottomup(file, addr, len, + pgoff, flags); + else + return hugetlb_get_unmapped_area_topdown(file, addr, len, + pgoff, flags); +} + +static __init int setup_hugepagesz(char *opt) +{ + unsigned long ps = memparse(opt, &opt); + if (ps == PMD_SIZE) { + hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); + } else if (ps == PUD_SIZE) { + hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); + } else { + printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n", + ps >> 20); + return 0; + } + return 1; +} +__setup("hugepagesz=", setup_hugepagesz); + +#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c new file mode 100644 index 000000000000..125ac53b60fc --- /dev/null +++ b/arch/tile/mm/init.c @@ -0,0 +1,1082 @@ +/* + * Copyright (C) 1995 Linus Torvalds + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "migrate.h" + +/* + * We could set FORCE_MAX_ZONEORDER to "(HPAGE_SHIFT - PAGE_SHIFT + 1)" + * in the Tile Kconfig, but this generates configure warnings. + * Do it here and force people to get it right to compile this file. + * The problem is that with 4KB small pages and 16MB huge pages, + * the default value doesn't allow us to group enough small pages + * together to make up a huge page. + */ +#if CONFIG_FORCE_MAX_ZONEORDER < HPAGE_SHIFT - PAGE_SHIFT + 1 +# error "Change FORCE_MAX_ZONEORDER in arch/tile/Kconfig to match page size" +#endif + +#define clear_pgd(pmdptr) (*(pmdptr) = hv_pte(0)) + +unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE; + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + +/* Create an L2 page table */ +static pte_t * __init alloc_pte(void) +{ + return __alloc_bootmem(L2_KERNEL_PGTABLE_SIZE, HV_PAGE_TABLE_ALIGN, 0); +} + +/* + * L2 page tables per controller. We allocate these all at once from + * the bootmem allocator and store them here. This saves on kernel L2 + * page table memory, compared to allocating a full 64K page per L2 + * page table, and also means that in cases where we use huge pages, + * we are guaranteed to later be able to shatter those huge pages and + * switch to using these page tables instead, without requiring + * further allocation. Each l2_ptes[] entry points to the first page + * table for the first hugepage-size piece of memory on the + * controller; other page tables are just indexed directly, i.e. the + * L2 page tables are contiguous in memory for each controller. + */ +static pte_t *l2_ptes[MAX_NUMNODES]; +static int num_l2_ptes[MAX_NUMNODES]; + +static void init_prealloc_ptes(int node, int pages) +{ + BUG_ON(pages & (HV_L2_ENTRIES-1)); + if (pages) { + num_l2_ptes[node] = pages; + l2_ptes[node] = __alloc_bootmem(pages * sizeof(pte_t), + HV_PAGE_TABLE_ALIGN, 0); + } +} + +pte_t *get_prealloc_pte(unsigned long pfn) +{ + int node = pfn_to_nid(pfn); + pfn &= ~(-1UL << (NR_PA_HIGHBIT_SHIFT - PAGE_SHIFT)); + BUG_ON(node >= MAX_NUMNODES); + BUG_ON(pfn >= num_l2_ptes[node]); + return &l2_ptes[node][pfn]; +} + +/* + * What caching do we expect pages from the heap to have when + * they are allocated during bootup? (Once we've installed the + * "real" swapper_pg_dir.) + */ +static int initial_heap_home(void) +{ +#if CHIP_HAS_CBOX_HOME_MAP() + if (hash_default) + return PAGE_HOME_HASH; +#endif + return smp_processor_id(); +} + +/* + * Place a pointer to an L2 page table in a middle page + * directory entry. + */ +static void __init assign_pte(pmd_t *pmd, pte_t *page_table) +{ + phys_addr_t pa = __pa(page_table); + unsigned long l2_ptfn = pa >> HV_LOG2_PAGE_TABLE_ALIGN; + pte_t pteval = hv_pte_set_ptfn(__pgprot(_PAGE_TABLE), l2_ptfn); + BUG_ON((pa & (HV_PAGE_TABLE_ALIGN-1)) != 0); + pteval = pte_set_home(pteval, initial_heap_home()); + *(pte_t *)pmd = pteval; + if (page_table != (pte_t *)pmd_page_vaddr(*pmd)) + BUG(); +} + +#ifdef __tilegx__ + +#if HV_L1_SIZE != HV_L2_SIZE +# error Rework assumption that L1 and L2 page tables are same size. +#endif + +/* Since pmd_t arrays and pte_t arrays are the same size, just use casts. */ +static inline pmd_t *alloc_pmd(void) +{ + return (pmd_t *)alloc_pte(); +} + +static inline void assign_pmd(pud_t *pud, pmd_t *pmd) +{ + assign_pte((pmd_t *)pud, (pte_t *)pmd); +} + +#endif /* __tilegx__ */ + +/* Replace the given pmd with a full PTE table. */ +void __init shatter_pmd(pmd_t *pmd) +{ + pte_t *pte = get_prealloc_pte(pte_pfn(*(pte_t *)pmd)); + assign_pte(pmd, pte); +} + +#ifdef CONFIG_HIGHMEM +/* + * This function initializes a certain range of kernel virtual memory + * with new bootmem page tables, everywhere page tables are missing in + * the given range. + */ + +/* + * NOTE: The pagetables are allocated contiguous on the physical space + * so we can cache the place of the first one and move around without + * checking the pgd every time. + */ +static void __init page_table_range_init(unsigned long start, + unsigned long end, pgd_t *pgd_base) +{ + pgd_t *pgd; + int pgd_idx; + unsigned long vaddr; + + vaddr = start; + pgd_idx = pgd_index(vaddr); + pgd = pgd_base + pgd_idx; + + for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { + pmd_t *pmd = pmd_offset(pud_offset(pgd, vaddr), vaddr); + if (pmd_none(*pmd)) + assign_pte(pmd, alloc_pte()); + vaddr += PMD_SIZE; + } +} +#endif /* CONFIG_HIGHMEM */ + + +#if CHIP_HAS_CBOX_HOME_MAP() + +static int __initdata ktext_hash = 1; /* .text pages */ +static int __initdata kdata_hash = 1; /* .data and .bss pages */ +int __write_once hash_default = 1; /* kernel allocator pages */ +EXPORT_SYMBOL(hash_default); +int __write_once kstack_hash = 1; /* if no homecaching, use h4h */ +#endif /* CHIP_HAS_CBOX_HOME_MAP */ + +/* + * CPUs to use to for striping the pages of kernel data. If hash-for-home + * is available, this is only relevant if kcache_hash sets up the + * .data and .bss to be page-homed, and we don't want the default mode + * of using the full set of kernel cpus for the striping. + */ +static __initdata struct cpumask kdata_mask; +static __initdata int kdata_arg_seen; + +int __write_once kdata_huge; /* if no homecaching, small pages */ + + +/* Combine a generic pgprot_t with cache home to get a cache-aware pgprot. */ +static pgprot_t __init construct_pgprot(pgprot_t prot, int home) +{ + prot = pte_set_home(prot, home); +#if CHIP_HAS_CBOX_HOME_MAP() + if (home == PAGE_HOME_IMMUTABLE) { + if (ktext_hash) + prot = hv_pte_set_mode(prot, HV_PTE_MODE_CACHE_HASH_L3); + else + prot = hv_pte_set_mode(prot, HV_PTE_MODE_CACHE_NO_L3); + } +#endif + return prot; +} + +/* + * For a given kernel data VA, how should it be cached? + * We return the complete pgprot_t with caching bits set. + */ +static pgprot_t __init init_pgprot(ulong address) +{ + int cpu; + unsigned long page; + enum { CODE_DELTA = MEM_SV_INTRPT - PAGE_OFFSET }; + +#if CHIP_HAS_CBOX_HOME_MAP() + /* For kdata=huge, everything is just hash-for-home. */ + if (kdata_huge) + return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH); +#endif + + /* We map the aliased pages of permanent text inaccessible. */ + if (address < (ulong) _sinittext - CODE_DELTA) + return PAGE_NONE; + + /* + * We map read-only data non-coherent for performance. We could + * use neighborhood caching on TILE64, but it's not clear it's a win. + */ + if ((address >= (ulong) __start_rodata && + address < (ulong) __end_rodata) || + address == (ulong) empty_zero_page) { + return construct_pgprot(PAGE_KERNEL_RO, PAGE_HOME_IMMUTABLE); + } + + /* As a performance optimization, keep the boot init stack here. */ + if (address >= (ulong)&init_thread_union && + address < (ulong)&init_thread_union + THREAD_SIZE) + return construct_pgprot(PAGE_KERNEL, smp_processor_id()); + +#ifndef __tilegx__ +#if !ATOMIC_LOCKS_FOUND_VIA_TABLE() + /* Force the atomic_locks[] array page to be hash-for-home. */ + if (address == (ulong) atomic_locks) + return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH); +#endif +#endif + + /* + * Everything else that isn't data or bss is heap, so mark it + * with the initial heap home (hash-for-home, or this cpu). This + * includes any addresses after the loaded image; any address before + * _einittext (since we already captured the case of text before + * _sinittext); and any init-data pages. + * + * All the LOWMEM pages that we mark this way will get their + * struct page homecache properly marked later, in set_page_homes(). + * The HIGHMEM pages we leave with a default zero for their + * homes, but with a zero free_time we don't have to actually + * do a flush action the first time we use them, either. + */ + if (address >= (ulong) _end || address < (ulong) _sdata || + (address >= (ulong) _sinitdata && + address < (ulong) _einitdata)) + return construct_pgprot(PAGE_KERNEL, initial_heap_home()); + +#if CHIP_HAS_CBOX_HOME_MAP() + /* Use hash-for-home if requested for data/bss. */ + if (kdata_hash) + return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH); +#endif + + /* + * Otherwise we just hand out consecutive cpus. To avoid + * requiring this function to hold state, we just walk forward from + * _sdata by PAGE_SIZE, skipping the readonly and init data, to reach + * the requested address, while walking cpu home around kdata_mask. + * This is typically no more than a dozen or so iterations. + */ + BUG_ON(_einitdata != __bss_start); + for (page = (ulong)_sdata, cpu = NR_CPUS; ; ) { + cpu = cpumask_next(cpu, &kdata_mask); + if (cpu == NR_CPUS) + cpu = cpumask_first(&kdata_mask); + if (page >= address) + break; + page += PAGE_SIZE; + if (page == (ulong)__start_rodata) + page = (ulong)__end_rodata; + if (page == (ulong)&init_thread_union) + page += THREAD_SIZE; + if (page == (ulong)_sinitdata) + page = (ulong)_einitdata; + if (page == (ulong)empty_zero_page) + page += PAGE_SIZE; +#ifndef __tilegx__ +#if !ATOMIC_LOCKS_FOUND_VIA_TABLE() + if (page == (ulong)atomic_locks) + page += PAGE_SIZE; +#endif +#endif + + } + return construct_pgprot(PAGE_KERNEL, cpu); +} + +/* + * This function sets up how we cache the kernel text. If we have + * hash-for-home support, normally that is used instead (see the + * kcache_hash boot flag for more information). But if we end up + * using a page-based caching technique, this option sets up the + * details of that. In addition, the "ktext=nocache" option may + * always be used to disable local caching of text pages, if desired. + */ + +static int __initdata ktext_arg_seen; +static int __initdata ktext_small; +static int __initdata ktext_local; +static int __initdata ktext_all; +static int __initdata ktext_nondataplane; +static int __initdata ktext_nocache; +static struct cpumask __initdata ktext_mask; + +static int __init setup_ktext(char *str) +{ + if (str == NULL) + return -EINVAL; + + /* If you have a leading "nocache", turn off ktext caching */ + if (strncmp(str, "nocache", 7) == 0) { + ktext_nocache = 1; + printk("ktext: disabling local caching of kernel text\n"); + str += 7; + if (*str == ',') + ++str; + if (*str == '\0') + return 0; + } + + ktext_arg_seen = 1; + + /* Default setting on Tile64: use a huge page */ + if (strcmp(str, "huge") == 0) + printk("ktext: using one huge locally cached page\n"); + + /* Pay TLB cost but get no cache benefit: cache small pages locally */ + else if (strcmp(str, "local") == 0) { + ktext_small = 1; + ktext_local = 1; + printk("ktext: using small pages with local caching\n"); + } + + /* Neighborhood cache ktext pages on all cpus. */ + else if (strcmp(str, "all") == 0) { + ktext_small = 1; + ktext_all = 1; + printk("ktext: using maximal caching neighborhood\n"); + } + + + /* Neighborhood ktext pages on specified mask */ + else if (cpulist_parse(str, &ktext_mask) == 0) { + char buf[NR_CPUS * 5]; + cpulist_scnprintf(buf, sizeof(buf), &ktext_mask); + if (cpumask_weight(&ktext_mask) > 1) { + ktext_small = 1; + printk("ktext: using caching neighborhood %s " + "with small pages\n", buf); + } else { + printk("ktext: caching on cpu %s with one huge page\n", + buf); + } + } + + else if (*str) + return -EINVAL; + + return 0; +} + +early_param("ktext", setup_ktext); + + +static inline pgprot_t ktext_set_nocache(pgprot_t prot) +{ + if (!ktext_nocache) + prot = hv_pte_set_nc(prot); +#if CHIP_HAS_NC_AND_NOALLOC_BITS() + else + prot = hv_pte_set_no_alloc_l2(prot); +#endif + return prot; +} + +#ifndef __tilegx__ +static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va) +{ + return pmd_offset(pud_offset(&pgtables[pgd_index(va)], va), va); +} +#else +static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va) +{ + pud_t *pud = pud_offset(&pgtables[pgd_index(va)], va); + if (pud_none(*pud)) + assign_pmd(pud, alloc_pmd()); + return pmd_offset(pud, va); +} +#endif + +/* Temporary page table we use for staging. */ +static pgd_t pgtables[PTRS_PER_PGD] + __attribute__((section(".init.page"))); + +/* + * This maps the physical memory to kernel virtual address space, a total + * of max_low_pfn pages, by creating page tables starting from address + * PAGE_OFFSET. + * + * This routine transitions us from using a set of compiled-in large + * pages to using some more precise caching, including removing access + * to code pages mapped at PAGE_OFFSET (executed only at MEM_SV_START) + * marking read-only data as locally cacheable, striping the remaining + * .data and .bss across all the available tiles, and removing access + * to pages above the top of RAM (thus ensuring a page fault from a bad + * virtual address rather than a hypervisor shoot down for accessing + * memory outside the assigned limits). + */ +static void __init kernel_physical_mapping_init(pgd_t *pgd_base) +{ + unsigned long address, pfn; + pmd_t *pmd; + pte_t *pte; + int pte_ofs; + const struct cpumask *my_cpu_mask = cpumask_of(smp_processor_id()); + struct cpumask kstripe_mask; + int rc, i; + +#if CHIP_HAS_CBOX_HOME_MAP() + if (ktext_arg_seen && ktext_hash) { + printk("warning: \"ktext\" boot argument ignored" + " if \"kcache_hash\" sets up text hash-for-home\n"); + ktext_small = 0; + } + + if (kdata_arg_seen && kdata_hash) { + printk("warning: \"kdata\" boot argument ignored" + " if \"kcache_hash\" sets up data hash-for-home\n"); + } + + if (kdata_huge && !hash_default) { + printk("warning: disabling \"kdata=huge\"; requires" + " kcache_hash=all or =allbutstack\n"); + kdata_huge = 0; + } +#endif + + /* + * Set up a mask for cpus to use for kernel striping. + * This is normally all cpus, but minus dataplane cpus if any. + * If the dataplane covers the whole chip, we stripe over + * the whole chip too. + */ + cpumask_copy(&kstripe_mask, cpu_possible_mask); + if (!kdata_arg_seen) + kdata_mask = kstripe_mask; + + /* Allocate and fill in L2 page tables */ + for (i = 0; i < MAX_NUMNODES; ++i) { +#ifdef CONFIG_HIGHMEM + unsigned long end_pfn = node_lowmem_end_pfn[i]; +#else + unsigned long end_pfn = node_end_pfn[i]; +#endif + unsigned long end_huge_pfn = 0; + + /* Pre-shatter the last huge page to allow per-cpu pages. */ + if (kdata_huge) + end_huge_pfn = end_pfn - (HPAGE_SIZE >> PAGE_SHIFT); + + pfn = node_start_pfn[i]; + + /* Allocate enough memory to hold L2 page tables for node. */ + init_prealloc_ptes(i, end_pfn - pfn); + + address = (unsigned long) pfn_to_kaddr(pfn); + while (pfn < end_pfn) { + BUG_ON(address & (HPAGE_SIZE-1)); + pmd = get_pmd(pgtables, address); + pte = get_prealloc_pte(pfn); + if (pfn < end_huge_pfn) { + pgprot_t prot = init_pgprot(address); + *(pte_t *)pmd = pte_mkhuge(pfn_pte(pfn, prot)); + for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE; + pfn++, pte_ofs++, address += PAGE_SIZE) + pte[pte_ofs] = pfn_pte(pfn, prot); + } else { + if (kdata_huge) + printk(KERN_DEBUG "pre-shattered huge" + " page at %#lx\n", address); + for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE; + pfn++, pte_ofs++, address += PAGE_SIZE) { + pgprot_t prot = init_pgprot(address); + pte[pte_ofs] = pfn_pte(pfn, prot); + } + assign_pte(pmd, pte); + } + } + } + + /* + * Set or check ktext_map now that we have cpu_possible_mask + * and kstripe_mask to work with. + */ + if (ktext_all) + cpumask_copy(&ktext_mask, cpu_possible_mask); + else if (ktext_nondataplane) + ktext_mask = kstripe_mask; + else if (!cpumask_empty(&ktext_mask)) { + /* Sanity-check any mask that was requested */ + struct cpumask bad; + cpumask_andnot(&bad, &ktext_mask, cpu_possible_mask); + cpumask_and(&ktext_mask, &ktext_mask, cpu_possible_mask); + if (!cpumask_empty(&bad)) { + char buf[NR_CPUS * 5]; + cpulist_scnprintf(buf, sizeof(buf), &bad); + printk("ktext: not using unavailable cpus %s\n", buf); + } + if (cpumask_empty(&ktext_mask)) { + printk("ktext: no valid cpus; caching on %d.\n", + smp_processor_id()); + cpumask_copy(&ktext_mask, + cpumask_of(smp_processor_id())); + } + } + + address = MEM_SV_INTRPT; + pmd = get_pmd(pgtables, address); + if (ktext_small) { + /* Allocate an L2 PTE for the kernel text */ + int cpu = 0; + pgprot_t prot = construct_pgprot(PAGE_KERNEL_EXEC, + PAGE_HOME_IMMUTABLE); + + if (ktext_local) { + if (ktext_nocache) + prot = hv_pte_set_mode(prot, + HV_PTE_MODE_UNCACHED); + else + prot = hv_pte_set_mode(prot, + HV_PTE_MODE_CACHE_NO_L3); + } else { + prot = hv_pte_set_mode(prot, + HV_PTE_MODE_CACHE_TILE_L3); + cpu = cpumask_first(&ktext_mask); + + prot = ktext_set_nocache(prot); + } + + BUG_ON(address != (unsigned long)_stext); + pfn = 0; /* code starts at PA 0 */ + pte = alloc_pte(); + for (pte_ofs = 0; address < (unsigned long)_einittext; + pfn++, pte_ofs++, address += PAGE_SIZE) { + if (!ktext_local) { + prot = set_remote_cache_cpu(prot, cpu); + cpu = cpumask_next(cpu, &ktext_mask); + if (cpu == NR_CPUS) + cpu = cpumask_first(&ktext_mask); + } + pte[pte_ofs] = pfn_pte(pfn, prot); + } + assign_pte(pmd, pte); + } else { + pte_t pteval = pfn_pte(0, PAGE_KERNEL_EXEC); + pteval = pte_mkhuge(pteval); +#if CHIP_HAS_CBOX_HOME_MAP() + if (ktext_hash) { + pteval = hv_pte_set_mode(pteval, + HV_PTE_MODE_CACHE_HASH_L3); + pteval = ktext_set_nocache(pteval); + } else +#endif /* CHIP_HAS_CBOX_HOME_MAP() */ + if (cpumask_weight(&ktext_mask) == 1) { + pteval = set_remote_cache_cpu(pteval, + cpumask_first(&ktext_mask)); + pteval = hv_pte_set_mode(pteval, + HV_PTE_MODE_CACHE_TILE_L3); + pteval = ktext_set_nocache(pteval); + } else if (ktext_nocache) + pteval = hv_pte_set_mode(pteval, + HV_PTE_MODE_UNCACHED); + else + pteval = hv_pte_set_mode(pteval, + HV_PTE_MODE_CACHE_NO_L3); + *(pte_t *)pmd = pteval; + } + + /* Set swapper_pgprot here so it is flushed to memory right away. */ + swapper_pgprot = init_pgprot((unsigned long)swapper_pg_dir); + + /* + * Since we may be changing the caching of the stack and page + * table itself, we invoke an assembly helper to do the + * following steps: + * + * - flush the cache so we start with an empty slate + * - install pgtables[] as the real page table + * - flush the TLB so the new page table takes effect + */ + rc = flush_and_install_context(__pa(pgtables), + init_pgprot((unsigned long)pgtables), + __get_cpu_var(current_asid), + cpumask_bits(my_cpu_mask)); + BUG_ON(rc != 0); + + /* Copy the page table back to the normal swapper_pg_dir. */ + memcpy(pgd_base, pgtables, sizeof(pgtables)); + __install_page_table(pgd_base, __get_cpu_var(current_asid), + swapper_pgprot); +} + +/* + * devmem_is_allowed() checks to see if /dev/mem access to a certain address + * is valid. The argument is a physical page number. + * + * On Tile, the only valid things for which we can just hand out unchecked + * PTEs are the kernel code and data. Anything else might change its + * homing with time, and we wouldn't know to adjust the /dev/mem PTEs. + * Note that init_thread_union is released to heap soon after boot, + * so we include it in the init data. + * + * For TILE-Gx, we might want to consider allowing access to PA + * regions corresponding to PCI space, etc. + */ +int devmem_is_allowed(unsigned long pagenr) +{ + return pagenr < kaddr_to_pfn(_end) && + !(pagenr >= kaddr_to_pfn(&init_thread_union) || + pagenr < kaddr_to_pfn(_einitdata)) && + !(pagenr >= kaddr_to_pfn(_sinittext) || + pagenr <= kaddr_to_pfn(_einittext-1)); +} + +#ifdef CONFIG_HIGHMEM +static void __init permanent_kmaps_init(pgd_t *pgd_base) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + unsigned long vaddr; + + vaddr = PKMAP_BASE; + page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); + + pgd = swapper_pg_dir + pgd_index(vaddr); + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); + pte = pte_offset_kernel(pmd, vaddr); + pkmap_page_table = pte; +} +#endif /* CONFIG_HIGHMEM */ + + +static void __init init_free_pfn_range(unsigned long start, unsigned long end) +{ + unsigned long pfn; + struct page *page = pfn_to_page(start); + + for (pfn = start; pfn < end; ) { + /* Optimize by freeing pages in large batches */ + int order = __ffs(pfn); + int count, i; + struct page *p; + + if (order >= MAX_ORDER) + order = MAX_ORDER-1; + count = 1 << order; + while (pfn + count > end) { + count >>= 1; + --order; + } + for (p = page, i = 0; i < count; ++i, ++p) { + __ClearPageReserved(p); + /* + * Hacky direct set to avoid unnecessary + * lock take/release for EVERY page here. + */ + p->_count.counter = 0; + p->_mapcount.counter = -1; + } + init_page_count(page); + __free_pages(page, order); + totalram_pages += count; + + page += count; + pfn += count; + } +} + +static void __init set_non_bootmem_pages_init(void) +{ + struct zone *z; + for_each_zone(z) { + unsigned long start, end; + int nid = z->zone_pgdat->node_id; + + start = z->zone_start_pfn; + if (start == 0) + continue; /* bootmem */ + end = start + z->spanned_pages; + if (zone_idx(z) == ZONE_NORMAL) { + BUG_ON(start != node_start_pfn[nid]); + start = node_free_pfn[nid]; + } +#ifdef CONFIG_HIGHMEM + if (zone_idx(z) == ZONE_HIGHMEM) + totalhigh_pages += z->spanned_pages; +#endif + if (kdata_huge) { + unsigned long percpu_pfn = node_percpu_pfn[nid]; + if (start < percpu_pfn && end > percpu_pfn) + end = percpu_pfn; + } +#ifdef CONFIG_PCI + if (start <= pci_reserve_start_pfn && + end > pci_reserve_start_pfn) { + if (end > pci_reserve_end_pfn) + init_free_pfn_range(pci_reserve_end_pfn, end); + end = pci_reserve_start_pfn; + } +#endif + init_free_pfn_range(start, end); + } +} + +/* + * paging_init() sets up the page tables - note that all of lowmem is + * already mapped by head.S. + */ +void __init paging_init(void) +{ +#ifdef CONFIG_HIGHMEM + unsigned long vaddr, end; +#endif +#ifdef __tilegx__ + pud_t *pud; +#endif + pgd_t *pgd_base = swapper_pg_dir; + + kernel_physical_mapping_init(pgd_base); + +#ifdef CONFIG_HIGHMEM + /* + * Fixed mappings, only the page table structure has to be + * created - mappings will be set by set_fixmap(): + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; + page_table_range_init(vaddr, end, pgd_base); + permanent_kmaps_init(pgd_base); +#endif + +#ifdef __tilegx__ + /* + * Since GX allocates just one pmd_t array worth of vmalloc space, + * we go ahead and allocate it statically here, then share it + * globally. As a result we don't have to worry about any task + * changing init_mm once we get up and running, and there's no + * need for e.g. vmalloc_sync_all(). + */ + BUILD_BUG_ON(pgd_index(VMALLOC_START) != pgd_index(VMALLOC_END)); + pud = pud_offset(pgd_base + pgd_index(VMALLOC_START), VMALLOC_START); + assign_pmd(pud, alloc_pmd()); +#endif +} + + +/* + * Walk the kernel page tables and derive the page_home() from + * the PTEs, so that set_pte() can properly validate the caching + * of all PTEs it sees. + */ +void __init set_page_homes(void) +{ +} + +static void __init set_max_mapnr_init(void) +{ +#ifdef CONFIG_FLATMEM + max_mapnr = max_low_pfn; +#endif +} + +void __init mem_init(void) +{ + int codesize, datasize, initsize; + int i; +#ifndef __tilegx__ + void *last; +#endif + +#ifdef CONFIG_FLATMEM + if (!mem_map) + BUG(); +#endif + +#ifdef CONFIG_HIGHMEM + /* check that fixmap and pkmap do not overlap */ + if (PKMAP_ADDR(LAST_PKMAP-1) >= FIXADDR_START) { + printk(KERN_ERR "fixmap and kmap areas overlap" + " - this will crash\n"); + printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n", + PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP-1), + FIXADDR_START); + BUG(); + } +#endif + + set_max_mapnr_init(); + + /* this will put all bootmem onto the freelists */ + totalram_pages += free_all_bootmem(); + + /* count all remaining LOWMEM and give all HIGHMEM to page allocator */ + set_non_bootmem_pages_init(); + + codesize = (unsigned long)&_etext - (unsigned long)&_text; + datasize = (unsigned long)&_end - (unsigned long)&_sdata; + initsize = (unsigned long)&_einittext - (unsigned long)&_sinittext; + initsize += (unsigned long)&_einitdata - (unsigned long)&_sinitdata; + + printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n", + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10), + codesize >> 10, + datasize >> 10, + initsize >> 10, + (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) + ); + + /* + * In debug mode, dump some interesting memory mappings. + */ +#ifdef CONFIG_HIGHMEM + printk(KERN_DEBUG " KMAP %#lx - %#lx\n", + FIXADDR_START, FIXADDR_TOP + PAGE_SIZE - 1); + printk(KERN_DEBUG " PKMAP %#lx - %#lx\n", + PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP) - 1); +#endif +#ifdef CONFIG_HUGEVMAP + printk(KERN_DEBUG " HUGEMAP %#lx - %#lx\n", + HUGE_VMAP_BASE, HUGE_VMAP_END - 1); +#endif + printk(KERN_DEBUG " VMALLOC %#lx - %#lx\n", + _VMALLOC_START, _VMALLOC_END - 1); +#ifdef __tilegx__ + for (i = MAX_NUMNODES-1; i >= 0; --i) { + struct pglist_data *node = &node_data[i]; + if (node->node_present_pages) { + unsigned long start = (unsigned long) + pfn_to_kaddr(node->node_start_pfn); + unsigned long end = start + + (node->node_present_pages << PAGE_SHIFT); + printk(KERN_DEBUG " MEM%d %#lx - %#lx\n", + i, start, end - 1); + } + } +#else + last = high_memory; + for (i = MAX_NUMNODES-1; i >= 0; --i) { + if ((unsigned long)vbase_map[i] != -1UL) { + printk(KERN_DEBUG " LOWMEM%d %#lx - %#lx\n", + i, (unsigned long) (vbase_map[i]), + (unsigned long) (last-1)); + last = vbase_map[i]; + } + } +#endif + +#ifndef __tilegx__ + /* + * Convert from using one lock for all atomic operations to + * one per cpu. + */ + __init_atomic_per_cpu(); +#endif +} + +/* + * this is for the non-NUMA, single node SMP system case. + * Specifically, in the case of x86, we will always add + * memory to the highmem for now. + */ +#ifndef CONFIG_NEED_MULTIPLE_NODES +int arch_add_memory(u64 start, u64 size) +{ + struct pglist_data *pgdata = &contig_page_data; + struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + + return __add_pages(zone, start_pfn, nr_pages); +} + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +#endif + +struct kmem_cache *pgd_cache; + +void __init pgtable_cache_init(void) +{ + pgd_cache = kmem_cache_create("pgd", + PTRS_PER_PGD*sizeof(pgd_t), + PTRS_PER_PGD*sizeof(pgd_t), + 0, + NULL); + if (!pgd_cache) + panic("pgtable_cache_init(): Cannot create pgd cache"); +} + +#if !CHIP_HAS_COHERENT_LOCAL_CACHE() +/* + * The __w1data area holds data that is only written during initialization, + * and is read-only and thus freely cacheable thereafter. Fix the page + * table entries that cover that region accordingly. + */ +static void mark_w1data_ro(void) +{ + /* Loop over page table entries */ + unsigned long addr = (unsigned long)__w1data_begin; + BUG_ON((addr & (PAGE_SIZE-1)) != 0); + for (; addr <= (unsigned long)__w1data_end - 1; addr += PAGE_SIZE) { + unsigned long pfn = kaddr_to_pfn((void *)addr); + struct page *page = pfn_to_page(pfn); + pte_t *ptep = virt_to_pte(NULL, addr); + BUG_ON(pte_huge(*ptep)); /* not relevant for kdata_huge */ + set_pte_at(&init_mm, addr, ptep, pfn_pte(pfn, PAGE_KERNEL_RO)); + } +} +#endif + +#ifdef CONFIG_DEBUG_PAGEALLOC +static long __write_once initfree; +#else +static long __write_once initfree = 1; +#endif + +/* Select whether to free (1) or mark unusable (0) the __init pages. */ +static int __init set_initfree(char *str) +{ + strict_strtol(str, 0, &initfree); + printk("initfree: %s free init pages\n", initfree ? "will" : "won't"); + return 1; +} +__setup("initfree=", set_initfree); + +static void free_init_pages(char *what, unsigned long begin, unsigned long end) +{ + unsigned long addr = (unsigned long) begin; + + if (kdata_huge && !initfree) { + printk("Warning: ignoring initfree=0:" + " incompatible with kdata=huge\n"); + initfree = 1; + } + end = (end + PAGE_SIZE - 1) & PAGE_MASK; + local_flush_tlb_pages(NULL, begin, PAGE_SIZE, end - begin); + for (addr = begin; addr < end; addr += PAGE_SIZE) { + /* + * Note we just reset the home here directly in the + * page table. We know this is safe because our caller + * just flushed the caches on all the other cpus, + * and they won't be touching any of these pages. + */ + int pfn = kaddr_to_pfn((void *)addr); + struct page *page = pfn_to_page(pfn); + pte_t *ptep = virt_to_pte(NULL, addr); + if (!initfree) { + /* + * If debugging page accesses then do not free + * this memory but mark them not present - any + * buggy init-section access will create a + * kernel page fault: + */ + pte_clear(&init_mm, addr, ptep); + continue; + } + __ClearPageReserved(page); + init_page_count(page); + if (pte_huge(*ptep)) + BUG_ON(!kdata_huge); + else + set_pte_at(&init_mm, addr, ptep, + pfn_pte(pfn, PAGE_KERNEL)); + memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); + free_page(addr); + totalram_pages++; + } + printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); +} + +void free_initmem(void) +{ + const unsigned long text_delta = MEM_SV_INTRPT - PAGE_OFFSET; + + /* + * Evict the dirty initdata on the boot cpu, evict the w1data + * wherever it's homed, and evict all the init code everywhere. + * We are guaranteed that no one will touch the init pages any + * more, and although other cpus may be touching the w1data, + * we only actually change the caching on tile64, which won't + * be keeping local copies in the other tiles' caches anyway. + */ + homecache_evict(&cpu_cacheable_map); + + /* Free the data pages that we won't use again after init. */ + free_init_pages("unused kernel data", + (unsigned long)_sinitdata, + (unsigned long)_einitdata); + + /* + * Free the pages mapped from 0xc0000000 that correspond to code + * pages from 0xfd000000 that we won't use again after init. + */ + free_init_pages("unused kernel text", + (unsigned long)_sinittext - text_delta, + (unsigned long)_einittext - text_delta); + +#if !CHIP_HAS_COHERENT_LOCAL_CACHE() + /* + * Upgrade the .w1data section to globally cached. + * We don't do this on tilepro, since the cache architecture + * pretty much makes it irrelevant, and in any case we end + * up having racing issues with other tiles that may touch + * the data after we flush the cache but before we update + * the PTEs and flush the TLBs, causing sharer shootdowns + * later. Even though this is to clean data, it seems like + * an unnecessary complication. + */ + mark_w1data_ro(); +#endif + + /* Do a global TLB flush so everyone sees the changes. */ + flush_tlb_all(); +} diff --git a/arch/tile/mm/migrate.h b/arch/tile/mm/migrate.h new file mode 100644 index 000000000000..cd45a0837fa6 --- /dev/null +++ b/arch/tile/mm/migrate.h @@ -0,0 +1,50 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Structure definitions for migration, exposed here for use by + * arch/tile/kernel/asm-offsets.c. + */ + +#ifndef MM_MIGRATE_H +#define MM_MIGRATE_H + +#include +#include + +/* + * This function is used as a helper when setting up the initial + * page table (swapper_pg_dir). + */ +extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access, + HV_ASID asid, + const unsigned long *cpumask); + +/* + * This function supports migration as a "helper" as follows: + * + * - Set the stack PTE itself to "migrating". + * - Do a global TLB flush for (va,length) and the specified ASIDs. + * - Do a cache-evict on all necessary cpus. + * - Write the new stack PTE. + * + * Note that any non-NULL pointers must not point to the page that + * is handled by the stack_pte itself. + */ +extern int homecache_migrate_stack_and_flush(pte_t stack_pte, unsigned long va, + size_t length, pte_t *stack_ptep, + const struct cpumask *cache_cpumask, + const struct cpumask *tlb_cpumask, + HV_Remote_ASID *asids, + int asidcount); + +#endif /* MM_MIGRATE_H */ diff --git a/arch/tile/mm/migrate_32.S b/arch/tile/mm/migrate_32.S new file mode 100644 index 000000000000..f738765cd1e6 --- /dev/null +++ b/arch/tile/mm/migrate_32.S @@ -0,0 +1,211 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * This routine is a helper for migrating the home of a set of pages to + * a new cpu. See the documentation in homecache.c for more information. + */ + +#include +#include +#include +#include +#include +#include + + .text + +/* + * First, some definitions that apply to all the code in the file. + */ + +/* Locals (caller-save) */ +#define r_tmp r10 +#define r_save_sp r11 + +/* What we save where in the stack frame; must include all callee-saves. */ +#define FRAME_SP 4 +#define FRAME_R30 8 +#define FRAME_R31 12 +#define FRAME_R32 16 +#define FRAME_R33 20 +#define FRAME_R34 24 +#define FRAME_R35 28 +#define FRAME_SIZE 32 + + + + +/* + * On entry: + * + * r0 low word of the new context PA to install (moved to r_context_lo) + * r1 high word of the new context PA to install (moved to r_context_hi) + * r2 low word of PTE to use for context access (moved to r_access_lo) + * r3 high word of PTE to use for context access (moved to r_access_lo) + * r4 ASID to use for new context (moved to r_asid) + * r5 pointer to cpumask with just this cpu set in it (r_my_cpumask) + */ + +/* Arguments (caller-save) */ +#define r_context_lo_in r0 +#define r_context_hi_in r1 +#define r_access_lo_in r2 +#define r_access_hi_in r3 +#define r_asid_in r4 +#define r_my_cpumask r5 + +/* Locals (callee-save); must not be more than FRAME_xxx above. */ +#define r_save_ics r30 +#define r_context_lo r31 +#define r_context_hi r32 +#define r_access_lo r33 +#define r_access_hi r34 +#define r_asid r35 + +STD_ENTRY(flush_and_install_context) + /* + * Create a stack frame; we can't touch it once we flush the + * cache until we install the new page table and flush the TLB. + */ + { + move r_save_sp, sp + sw sp, lr + addi sp, sp, -FRAME_SIZE + } + addi r_tmp, sp, FRAME_SP + { + sw r_tmp, r_save_sp + addi r_tmp, sp, FRAME_R30 + } + { + sw r_tmp, r30 + addi r_tmp, sp, FRAME_R31 + } + { + sw r_tmp, r31 + addi r_tmp, sp, FRAME_R32 + } + { + sw r_tmp, r32 + addi r_tmp, sp, FRAME_R33 + } + { + sw r_tmp, r33 + addi r_tmp, sp, FRAME_R34 + } + { + sw r_tmp, r34 + addi r_tmp, sp, FRAME_R35 + } + sw r_tmp, r35 + + /* Move some arguments to callee-save registers. */ + { + move r_context_lo, r_context_lo_in + move r_context_hi, r_context_hi_in + } + { + move r_access_lo, r_access_lo_in + move r_access_hi, r_access_hi_in + } + move r_asid, r_asid_in + + /* Disable interrupts, since we can't use our stack. */ + { + mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION + movei r_tmp, 1 + } + mtspr INTERRUPT_CRITICAL_SECTION, r_tmp + + /* First, flush our L2 cache. */ + { + move r0, zero /* cache_pa */ + move r1, zero + } + { + auli r2, zero, ha16(HV_FLUSH_EVICT_L2) /* cache_control */ + move r3, r_my_cpumask /* cache_cpumask */ + } + { + move r4, zero /* tlb_va */ + move r5, zero /* tlb_length */ + } + { + move r6, zero /* tlb_pgsize */ + move r7, zero /* tlb_cpumask */ + } + { + move r8, zero /* asids */ + move r9, zero /* asidcount */ + } + jal hv_flush_remote + bnz r0, .Ldone + + /* Now install the new page table. */ + { + move r0, r_context_lo + move r1, r_context_hi + } + { + move r2, r_access_lo + move r3, r_access_hi + } + { + move r4, r_asid + movei r5, HV_CTX_DIRECTIO + } + jal hv_install_context + bnz r0, .Ldone + + /* Finally, flush the TLB. */ + { + movei r0, 0 /* preserve_global */ + jal hv_flush_all + } + +.Ldone: + /* Reset interrupts back how they were before. */ + mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics + + /* Restore the callee-saved registers and return. */ + addli lr, sp, FRAME_SIZE + { + lw lr, lr + addli r_tmp, sp, FRAME_R30 + } + { + lw r30, r_tmp + addli r_tmp, sp, FRAME_R31 + } + { + lw r31, r_tmp + addli r_tmp, sp, FRAME_R32 + } + { + lw r32, r_tmp + addli r_tmp, sp, FRAME_R33 + } + { + lw r33, r_tmp + addli r_tmp, sp, FRAME_R34 + } + { + lw r34, r_tmp + addli r_tmp, sp, FRAME_R35 + } + { + lw r35, r_tmp + addi sp, sp, FRAME_SIZE + } + jrp lr + STD_ENDPROC(flush_and_install_context) diff --git a/arch/tile/mm/mmap.c b/arch/tile/mm/mmap.c new file mode 100644 index 000000000000..f96f4cec602a --- /dev/null +++ b/arch/tile/mm/mmap.c @@ -0,0 +1,75 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + * Taken from the i386 architecture and simplified. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(struct mm_struct *mm) +{ + unsigned long gap = rlimit(RLIMIT_STACK); + unsigned long random_factor = 0; + + if (current->flags & PF_RANDOMIZE) + random_factor = get_random_int() % (1024*1024); + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return PAGE_ALIGN(TASK_SIZE - gap - random_factor); +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void arch_pick_mmap_layout(struct mm_struct *mm) +{ +#if !defined(__tilegx__) + int is_32bit = 1; +#elif defined(CONFIG_COMPAT) + int is_32bit = is_compat_task(); +#else + int is_32bit = 0; +#endif + + /* + * Use standard layout if the expected stack growth is unlimited + * or we are running native 64 bits. + */ + if (!is_32bit || rlimit(RLIMIT_STACK) == RLIM_INFINITY) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(mm); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c new file mode 100644 index 000000000000..289e729bbd76 --- /dev/null +++ b/arch/tile/mm/pgtable.c @@ -0,0 +1,566 @@ +/* + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define K(x) ((x) << (PAGE_SHIFT-10)) + +/* + * The normal show_free_areas() is too verbose on Tile, with dozens + * of processors and often four NUMA zones each with high and lowmem. + */ +void show_mem(void) +{ + struct zone *zone; + + printk("Active:%lu inactive:%lu dirty:%lu writeback:%lu unstable:%lu" + " free:%lu\n slab:%lu mapped:%lu pagetables:%lu bounce:%lu" + " pagecache:%lu swap:%lu\n", + (global_page_state(NR_ACTIVE_ANON) + + global_page_state(NR_ACTIVE_FILE)), + (global_page_state(NR_INACTIVE_ANON) + + global_page_state(NR_INACTIVE_FILE)), + global_page_state(NR_FILE_DIRTY), + global_page_state(NR_WRITEBACK), + global_page_state(NR_UNSTABLE_NFS), + global_page_state(NR_FREE_PAGES), + (global_page_state(NR_SLAB_RECLAIMABLE) + + global_page_state(NR_SLAB_UNRECLAIMABLE)), + global_page_state(NR_FILE_MAPPED), + global_page_state(NR_PAGETABLE), + global_page_state(NR_BOUNCE), + global_page_state(NR_FILE_PAGES), + nr_swap_pages); + + for_each_zone(zone) { + unsigned long flags, order, total = 0, largest_order = -1; + + if (!populated_zone(zone)) + continue; + + printk("Node %d %7s: ", zone_to_nid(zone), zone->name); + spin_lock_irqsave(&zone->lock, flags); + for (order = 0; order < MAX_ORDER; order++) { + int nr = zone->free_area[order].nr_free; + total += nr << order; + if (nr) + largest_order = order; + } + spin_unlock_irqrestore(&zone->lock, flags); + printk("%lukB (largest %luKb)\n", + K(total), largest_order ? K(1UL) << largest_order : 0); + } +} + +/* + * Associate a virtual page frame with a given physical page frame + * and protection flags for that frame. + */ +static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + pgd = swapper_pg_dir + pgd_index(vaddr); + if (pgd_none(*pgd)) { + BUG(); + return; + } + pud = pud_offset(pgd, vaddr); + if (pud_none(*pud)) { + BUG(); + return; + } + pmd = pmd_offset(pud, vaddr); + if (pmd_none(*pmd)) { + BUG(); + return; + } + pte = pte_offset_kernel(pmd, vaddr); + /* stored as-is, to permit clearing entries */ + set_pte(pte, pfn_pte(pfn, flags)); + + /* + * It's enough to flush this one mapping. + * This appears conservative since it is only called + * from __set_fixmap. + */ + local_flush_tlb_page(NULL, vaddr, PAGE_SIZE); +} + +/* + * Associate a huge virtual page frame with a given physical page frame + * and protection flags for that frame. pfn is for the base of the page, + * vaddr is what the page gets mapped to - both must be properly aligned. + * The pmd must already be instantiated. + */ +void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */ + printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n"); + return; /* BUG(); */ + } + if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */ + printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n"); + return; /* BUG(); */ + } + pgd = swapper_pg_dir + pgd_index(vaddr); + if (pgd_none(*pgd)) { + printk(KERN_WARNING "set_pmd_pfn: pgd_none\n"); + return; /* BUG(); */ + } + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); + set_pmd(pmd, ptfn_pmd(HV_PFN_TO_PTFN(pfn), flags)); + /* + * It's enough to flush this one mapping. + * We flush both small and huge TSBs to be sure. + */ + local_flush_tlb_page(NULL, vaddr, HPAGE_SIZE); + local_flush_tlb_pages(NULL, vaddr, PAGE_SIZE, HPAGE_SIZE); +} + +void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags) +{ + unsigned long address = __fix_to_virt(idx); + + if (idx >= __end_of_fixed_addresses) { + BUG(); + return; + } + set_pte_pfn(address, phys >> PAGE_SHIFT, flags); +} + +#if defined(CONFIG_HIGHPTE) +pte_t *_pte_offset_map(pmd_t *dir, unsigned long address, enum km_type type) +{ + pte_t *pte = kmap_atomic(pmd_page(*dir), type) + + (pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK; + return &pte[pte_index(address)]; +} +#endif + +/* + * List of all pgd's needed so it can invalidate entries in both cached + * and uncached pgd's. This is essentially codepath-based locking + * against pageattr.c; it is the unique case in which a valid change + * of kernel pagetables can't be lazily synchronized by vmalloc faults. + * vmalloc faults work because attached pagetables are never freed. + * The locking scheme was chosen on the basis of manfred's + * recommendations and having no core impact whatsoever. + * -- wli + */ +DEFINE_SPINLOCK(pgd_lock); +LIST_HEAD(pgd_list); + +static inline void pgd_list_add(pgd_t *pgd) +{ + list_add(pgd_to_list(pgd), &pgd_list); +} + +static inline void pgd_list_del(pgd_t *pgd) +{ + list_del(pgd_to_list(pgd)); +} + +#define KERNEL_PGD_INDEX_START pgd_index(PAGE_OFFSET) +#define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_INDEX_START) + +static void pgd_ctor(pgd_t *pgd) +{ + unsigned long flags; + + memset(pgd, 0, KERNEL_PGD_INDEX_START*sizeof(pgd_t)); + spin_lock_irqsave(&pgd_lock, flags); + +#ifndef __tilegx__ + /* + * Check that the user interrupt vector has no L2. + * It never should for the swapper, and new page tables + * should always start with an empty user interrupt vector. + */ + BUG_ON(((u64 *)swapper_pg_dir)[pgd_index(MEM_USER_INTRPT)] != 0); +#endif + + clone_pgd_range(pgd + KERNEL_PGD_INDEX_START, + swapper_pg_dir + KERNEL_PGD_INDEX_START, + KERNEL_PGD_PTRS); + + pgd_list_add(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); +} + +static void pgd_dtor(pgd_t *pgd) +{ + unsigned long flags; /* can be called from interrupt context */ + + spin_lock_irqsave(&pgd_lock, flags); + pgd_list_del(pgd); + spin_unlock_irqrestore(&pgd_lock, flags); +} + +pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); + if (pgd) + pgd_ctor(pgd); + return pgd; +} + +void pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ + pgd_dtor(pgd); + kmem_cache_free(pgd_cache, pgd); +} + + +#define L2_USER_PGTABLE_PAGES (1 << L2_USER_PGTABLE_ORDER) + +struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +{ + int flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO|__GFP_COMP; + struct page *p; + +#ifdef CONFIG_HIGHPTE + flags |= __GFP_HIGHMEM; +#endif + + p = alloc_pages(flags, L2_USER_PGTABLE_ORDER); + if (p == NULL) + return NULL; + + pgtable_page_ctor(p); + return p; +} + +/* + * Free page immediately (used in __pte_alloc if we raced with another + * process). We have to correct whatever pte_alloc_one() did before + * returning the pages to the allocator. + */ +void pte_free(struct mm_struct *mm, struct page *p) +{ + pgtable_page_dtor(p); + __free_pages(p, L2_USER_PGTABLE_ORDER); +} + +void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, + unsigned long address) +{ + int i; + + pgtable_page_dtor(pte); + tlb->need_flush = 1; + if (tlb_fast_mode(tlb)) { + struct page *pte_pages[L2_USER_PGTABLE_PAGES]; + for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) + pte_pages[i] = pte + i; + free_pages_and_swap_cache(pte_pages, L2_USER_PGTABLE_PAGES); + return; + } + for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) { + tlb->pages[tlb->nr++] = pte + i; + if (tlb->nr >= FREE_PTE_NR) + tlb_flush_mmu(tlb, 0, 0); + } +} + +#ifndef __tilegx__ + +/* + * FIXME: needs to be atomic vs hypervisor writes. For now we make the + * window of vulnerability a bit smaller by doing an unlocked 8-bit update. + */ +int ptep_test_and_clear_young(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) +{ +#if HV_PTE_INDEX_ACCESSED < 8 || HV_PTE_INDEX_ACCESSED >= 16 +# error Code assumes HV_PTE "accessed" bit in second byte +#endif + u8 *tmp = (u8 *)ptep; + u8 second_byte = tmp[1]; + if (!(second_byte & (1 << (HV_PTE_INDEX_ACCESSED - 8)))) + return 0; + tmp[1] = second_byte & ~(1 << (HV_PTE_INDEX_ACCESSED - 8)); + return 1; +} + +/* + * This implementation is atomic vs hypervisor writes, since the hypervisor + * always writes the low word (where "accessed" and "dirty" are) and this + * routine only writes the high word. + */ +void ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ +#if HV_PTE_INDEX_WRITABLE < 32 +# error Code assumes HV_PTE "writable" bit in high word +#endif + u32 *tmp = (u32 *)ptep; + tmp[1] = tmp[1] & ~(1 << (HV_PTE_INDEX_WRITABLE - 32)); +} + +#endif + +pte_t *virt_to_pte(struct mm_struct* mm, unsigned long addr) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + if (pgd_addr_invalid(addr)) + return NULL; + + pgd = mm ? pgd_offset(mm, addr) : swapper_pg_dir + pgd_index(addr); + pud = pud_offset(pgd, addr); + if (!pud_present(*pud)) + return NULL; + pmd = pmd_offset(pud, addr); + if (pmd_huge_page(*pmd)) + return (pte_t *)pmd; + if (!pmd_present(*pmd)) + return NULL; + return pte_offset_kernel(pmd, addr); +} + +pgprot_t set_remote_cache_cpu(pgprot_t prot, int cpu) +{ + unsigned int width = smp_width; + int x = cpu % width; + int y = cpu / width; + BUG_ON(y >= smp_height); + BUG_ON(hv_pte_get_mode(prot) != HV_PTE_MODE_CACHE_TILE_L3); + BUG_ON(cpu < 0 || cpu >= NR_CPUS); + BUG_ON(!cpu_is_valid_lotar(cpu)); + return hv_pte_set_lotar(prot, HV_XY_TO_LOTAR(x, y)); +} + +int get_remote_cache_cpu(pgprot_t prot) +{ + HV_LOTAR lotar = hv_pte_get_lotar(prot); + int x = HV_LOTAR_X(lotar); + int y = HV_LOTAR_Y(lotar); + BUG_ON(hv_pte_get_mode(prot) != HV_PTE_MODE_CACHE_TILE_L3); + return x + y * smp_width; +} + +void set_pte_order(pte_t *ptep, pte_t pte, int order) +{ + unsigned long pfn = pte_pfn(pte); + struct page *page = pfn_to_page(pfn); + + /* Update the home of a PTE if necessary */ + pte = pte_set_home(pte, page_home(page)); + +#ifdef __tilegx__ + *ptep = pte; +#else + /* + * When setting a PTE, write the high bits first, then write + * the low bits. This sets the "present" bit only after the + * other bits are in place. If a particular PTE update + * involves transitioning from one valid PTE to another, it + * may be necessary to call set_pte_order() more than once, + * transitioning via a suitable intermediate state. + * Note that this sequence also means that if we are transitioning + * from any migrating PTE to a non-migrating one, we will not + * see a half-updated PTE with the migrating bit off. + */ +#if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32 +# error Must write the present and migrating bits last +#endif + ((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32); + barrier(); + ((u32 *)ptep)[0] = (u32)(pte_val(pte)); +#endif +} + +/* Can this mm load a PTE with cached_priority set? */ +static inline int mm_is_priority_cached(struct mm_struct *mm) +{ + return mm->context.priority_cached; +} + +/* + * Add a priority mapping to an mm_context and + * notify the hypervisor if this is the first one. + */ +void start_mm_caching(struct mm_struct *mm) +{ + if (!mm_is_priority_cached(mm)) { + mm->context.priority_cached = -1U; + hv_set_caching(-1U); + } +} + +/* + * Validate and return the priority_cached flag. We know if it's zero + * that we don't need to scan, since we immediately set it non-zero + * when we first consider a MAP_CACHE_PRIORITY mapping. + * + * We only _try_ to acquire the mmap_sem semaphore; if we can't acquire it, + * since we're in an interrupt context (servicing switch_mm) we don't + * worry about it and don't unset the "priority_cached" field. + * Presumably we'll come back later and have more luck and clear + * the value then; for now we'll just keep the cache marked for priority. + */ +static unsigned int update_priority_cached(struct mm_struct *mm) +{ + if (mm->context.priority_cached && down_write_trylock(&mm->mmap_sem)) { + struct vm_area_struct *vm; + for (vm = mm->mmap; vm; vm = vm->vm_next) { + if (hv_pte_get_cached_priority(vm->vm_page_prot)) + break; + } + if (vm == NULL) + mm->context.priority_cached = 0; + up_write(&mm->mmap_sem); + } + return mm->context.priority_cached; +} + +/* Set caching correctly for an mm that we are switching to. */ +void check_mm_caching(struct mm_struct *prev, struct mm_struct *next) +{ + if (!mm_is_priority_cached(next)) { + /* + * If the new mm doesn't use priority caching, just see if we + * need the hv_set_caching(), or can assume it's already zero. + */ + if (mm_is_priority_cached(prev)) + hv_set_caching(0); + } else { + hv_set_caching(update_priority_cached(next)); + } +} + +#if CHIP_HAS_MMIO() + +/* Map an arbitrary MMIO address, homed according to pgprot, into VA space. */ +void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size, + pgprot_t home) +{ + void *addr; + struct vm_struct *area; + unsigned long offset, last_addr; + pgprot_t pgprot; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* Create a read/write, MMIO VA mapping homed at the requested shim. */ + pgprot = PAGE_KERNEL; + pgprot = hv_pte_set_mode(pgprot, HV_PTE_MODE_MMIO); + pgprot = hv_pte_set_lotar(pgprot, hv_pte_get_lotar(home)); + + /* + * Mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr+1) - phys_addr; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size, VM_IOREMAP /* | other flags? */); + if (!area) + return NULL; + area->phys_addr = phys_addr; + addr = area->addr; + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { + remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr)); + return NULL; + } + return (__force void __iomem *) (offset + (char *)addr); +} +EXPORT_SYMBOL(ioremap_prot); + +/* Map a PCI MMIO bus address into VA space. */ +void __iomem *ioremap(resource_size_t phys_addr, unsigned long size) +{ + panic("ioremap for PCI MMIO is not supported"); +} +EXPORT_SYMBOL(ioremap); + +/* Unmap an MMIO VA mapping. */ +void iounmap(volatile void __iomem *addr_in) +{ + volatile void __iomem *addr = (volatile void __iomem *) + (PAGE_MASK & (unsigned long __force)addr_in); +#if 1 + vunmap((void * __force)addr); +#else + /* x86 uses this complicated flow instead of vunmap(). Is + * there any particular reason we should do the same? */ + struct vm_struct *p, *o; + + /* Use the vm area unlocked, assuming the caller + ensures there isn't another iounmap for the same address + in parallel. Reuse of the virtual address is prevented by + leaving it in the global lists until we're done with it. + cpa takes care of the direct mappings. */ + read_lock(&vmlist_lock); + for (p = vmlist; p; p = p->next) { + if (p->addr == addr) + break; + } + read_unlock(&vmlist_lock); + + if (!p) { + printk("iounmap: bad address %p\n", addr); + dump_stack(); + return; + } + + /* Finally remove it */ + o = remove_vm_area((void *)addr); + BUG_ON(p != o || o == NULL); + kfree(p); +#endif +} +EXPORT_SYMBOL(iounmap); + +#endif /* CHIP_HAS_MMIO() */ diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 88d6eac69754..273cee1cc77b 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o +obj-$(CONFIG_HVC_TILE) += hvc_tile.o obj-$(CONFIG_HVC_BEAT) += hvc_beat.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_HVC_IRQ) += hvc_irq.o diff --git a/drivers/char/hvc_tile.c b/drivers/char/hvc_tile.c new file mode 100644 index 000000000000..75715b32f22a --- /dev/null +++ b/drivers/char/hvc_tile.c @@ -0,0 +1,67 @@ +/* + * %LINUX_LICENSE% + * + * + * + * + * + * + * + * + * + * + * + * Tilera TILE Processor hypervisor console + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "hvc_console.h" + +static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count) +{ + return hv_console_write((HV_VirtAddr)buf, count); +} + +static int hvc_tile_get_chars(uint32_t vt, char *buf, int count) +{ + int i, c; + + for (i = 0; i < count; ++i) { + c = hv_console_read_if_ready(); + if (c < 0) + break; + buf[i] = c; + } + + return i; +} + +static const struct hv_ops hvc_tile_get_put_ops = { + .get_chars = hvc_tile_get_chars, + .put_chars = hvc_tile_put_chars, +}; + +static int __init hvc_tile_console_init(void) +{ + extern void disable_early_printk(void); + hvc_instantiate(0, 0, &hvc_tile_get_put_ops); + add_preferred_console("hvc", 0, NULL); + disable_early_printk(); + return 0; +} +console_initcall(hvc_tile_console_init); + +static int __init hvc_tile_init(void) +{ + hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128); + return 0; +} +device_initcall(hvc_tile_init); -- cgit v1.2.3 From 494a43bb188c10b9b21375bbfe2691e41e3cb145 Mon Sep 17 00:00:00 2001 From: Alan Olsen Date: Mon, 26 Apr 2010 10:50:19 -0700 Subject: Moorestown "Post Beta" nand driver. Contains the fixes for nand corruption with the watchdog driver. New features compares to MRST NAND driver Post Alpah2 2.0: 1. Enable CDMA feature of NAND controller How to use this driver: The same with before. That is, to enable this driver, you can set CONFIG_MRST_NAND=y CONFIG_MRST_NAND_HW=y Signed-off-by: Gao Yunpeng Signed-off-by: Alan Olsen --- drivers/block/Kconfig | 2 + drivers/block/Makefile | 2 + drivers/block/spectra/Kconfig | 27 + drivers/block/spectra/Makefile | 7 + drivers/block/spectra/README | 29 + drivers/block/spectra/ffsdefs.h | 58 + drivers/block/spectra/ffsport.c | 847 ++++++ drivers/block/spectra/ffsport.h | 84 + drivers/block/spectra/flash.c | 4731 +++++++++++++++++++++++++++++++ drivers/block/spectra/flash.h | 198 ++ drivers/block/spectra/lld.c | 258 ++ drivers/block/spectra/lld.h | 111 + drivers/block/spectra/lld_cdma.c | 910 ++++++ drivers/block/spectra/lld_cdma.h | 123 + drivers/block/spectra/lld_emu.c | 780 +++++ drivers/block/spectra/lld_emu.h | 51 + drivers/block/spectra/lld_nand.c | 2601 +++++++++++++++++ drivers/block/spectra/lld_nand.h | 131 + drivers/block/spectra/nand_regs.h | 619 ++++ drivers/block/spectra/spectraswconfig.h | 81 + 20 files changed, 11650 insertions(+) create mode 100644 drivers/block/spectra/Kconfig create mode 100644 drivers/block/spectra/Makefile create mode 100644 drivers/block/spectra/README create mode 100644 drivers/block/spectra/ffsdefs.h create mode 100644 drivers/block/spectra/ffsport.c create mode 100644 drivers/block/spectra/ffsport.h create mode 100644 drivers/block/spectra/flash.c create mode 100644 drivers/block/spectra/flash.h create mode 100644 drivers/block/spectra/lld.c create mode 100644 drivers/block/spectra/lld.h create mode 100644 drivers/block/spectra/lld_cdma.c create mode 100644 drivers/block/spectra/lld_cdma.h create mode 100644 drivers/block/spectra/lld_emu.c create mode 100644 drivers/block/spectra/lld_emu.h create mode 100644 drivers/block/spectra/lld_nand.c create mode 100644 drivers/block/spectra/lld_nand.h create mode 100644 drivers/block/spectra/nand_regs.h create mode 100644 drivers/block/spectra/spectraswconfig.h (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 77bfce52e9ca..d62b95d2ab00 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -488,4 +488,6 @@ config BLK_DEV_HD If unsure, say N. +source "drivers/block/spectra/Kconfig" + endif # BLK_DEV diff --git a/drivers/block/Makefile b/drivers/block/Makefile index aff5ac925c34..568ba651cb5e 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -38,4 +38,6 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ +obj-$(CONFIG_MRST_NAND) += spectra/ + swim_mod-objs := swim.o swim_asm.o diff --git a/drivers/block/spectra/Kconfig b/drivers/block/spectra/Kconfig new file mode 100644 index 000000000000..fbece109f6c6 --- /dev/null +++ b/drivers/block/spectra/Kconfig @@ -0,0 +1,27 @@ + +menuconfig MRST_NAND + tristate "Moorestown NAND Flash controller" + depends on BLOCK + default n + ---help--- + Enable the driver for the NAND Flash controller in Intel Moorestown + Platform + +choice + prompt "Compile for" + depends on MRST_NAND + default MRST_NAND_HW + +config MRST_NAND_HW + bool "Actual hardware mode" + help + Driver communicates with the actual hardware's register interface. + in DMA mode. + +config MRST_NAND_EMU + bool "RAM emulator testing" + help + Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer. + +endchoice + diff --git a/drivers/block/spectra/Makefile b/drivers/block/spectra/Makefile new file mode 100644 index 000000000000..261891c23577 --- /dev/null +++ b/drivers/block/spectra/Makefile @@ -0,0 +1,7 @@ +# +# Makefile of Intel Moorestown NAND controller driver +# + +obj-$(CONFIG_MRST_NAND) += spectra.o +spectra-objs := ffsport.o flash.o lld.o lld_emu.o lld_nand.o lld_cdma.o + diff --git a/drivers/block/spectra/README b/drivers/block/spectra/README new file mode 100644 index 000000000000..ecba559b899c --- /dev/null +++ b/drivers/block/spectra/README @@ -0,0 +1,29 @@ +This is a driver for NAND controller of Intel Moorestown platform. + +This driver is a standalone linux block device driver, it acts as if it's a normal hard disk. +It includes three layer: + block layer interface - file ffsport.c + Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on) + Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access) + +This driver can be build as modules or build-in. + +Dependency: +This driver has dependency on IA Firmware of Intel Moorestown platform. +It need the IA Firmware to create the block table for the first time. +And to validate this driver code without IA Firmware, you can change the +macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the +driver will erase the whole nand flash and create a new block table. + +TODO: + - Enable Command DMA feature support + - lower the memory footprint + - Remove most of the unnecessary global variables + - Change all the upcase variable / functions name to lowercase + - Some other misc bugs + +Please send patches to: + Greg Kroah-Hartman + +And Cc to: Gao Yunpeng + diff --git a/drivers/block/spectra/ffsdefs.h b/drivers/block/spectra/ffsdefs.h new file mode 100644 index 000000000000..a9e9cd233d2a --- /dev/null +++ b/drivers/block/spectra/ffsdefs.h @@ -0,0 +1,58 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FFSDEFS_ +#define _FFSDEFS_ + +#define CLEAR 0 /*use this to clear a field instead of "fail"*/ +#define SET 1 /*use this to set a field instead of "pass"*/ +#define FAIL 1 /*failed flag*/ +#define PASS 0 /*success flag*/ +#define ERR -1 /*error flag*/ + +#define ERASE_CMD 10 +#define WRITE_MAIN_CMD 11 +#define READ_MAIN_CMD 12 +#define WRITE_SPARE_CMD 13 +#define READ_SPARE_CMD 14 +#define WRITE_MAIN_SPARE_CMD 15 +#define READ_MAIN_SPARE_CMD 16 +#define MEMCOPY_CMD 17 +#define DUMMY_CMD 99 + +#define EVENT_PASS 0x00 +#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01 +#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02 +#define EVENT_TIME_OUT 0x03 +#define EVENT_PROGRAM_FAILURE 0x04 +#define EVENT_ERASE_FAILURE 0x05 +#define EVENT_MEMCOPY_FAILURE 0x06 +#define EVENT_FAIL 0x07 + +#define EVENT_NONE 0x22 +#define EVENT_DMA_CMD_COMP 0x77 +#define EVENT_ECC_TRANSACTION_DONE 0x88 +#define EVENT_DMA_CMD_FAIL 0x99 + +#define CMD_PASS 0 +#define CMD_FAIL 1 +#define CMD_ABORT 2 +#define CMD_NOT_DONE 3 + +#endif /* _FFSDEFS_ */ diff --git a/drivers/block/spectra/ffsport.c b/drivers/block/spectra/ffsport.c new file mode 100644 index 000000000000..0b3d49d2f8a5 --- /dev/null +++ b/drivers/block/spectra/ffsport.c @@ -0,0 +1,847 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "ffsport.h" +#include "flash.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/**** Helper functions used for Div, Remainder operation on u64 ****/ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_Calc_Used_Bits +* Inputs: Power of 2 number +* Outputs: Number of Used Bits +* 0, if the argument is 0 +* Description: Calculate the number of bits used by a given power of 2 number +* Number can be upto 32 bit +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_Calc_Used_Bits(u32 n) +{ + int tot_bits = 0; + + if (n >= 1 << 16) { + n >>= 16; + tot_bits += 16; + } + + if (n >= 1 << 8) { + n >>= 8; + tot_bits += 8; + } + + if (n >= 1 << 4) { + n >>= 4; + tot_bits += 4; + } + + if (n >= 1 << 2) { + n >>= 2; + tot_bits += 2; + } + + if (n >= 1 << 1) + tot_bits += 1; + + return ((n == 0) ? (0) : tot_bits); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_u64_Div +* Inputs: Number of u64 +* A power of 2 number as Division +* Outputs: Quotient of the Divisor operation +* Description: It divides the address by divisor by using bit shift operation +* (essentially without explicitely using "/"). +* Divisor is a power of 2 number and Divided is of u64 +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u64 GLOB_u64_Div(u64 addr, u32 divisor) +{ + return (u64)(addr >> GLOB_Calc_Used_Bits(divisor)); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_u64_Remainder +* Inputs: Number of u64 +* Divisor Type (1 -PageAddress, 2- BlockAddress) +* Outputs: Remainder of the Division operation +* Description: It calculates the remainder of a number (of u64) by +* divisor(power of 2 number ) by using bit shifting and multiply +* operation(essentially without explicitely using "/"). +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) +{ + u64 result = 0; + + if (divisor_type == 1) { /* Remainder -- Page */ + result = (addr >> DeviceInfo.nBitsInPageDataSize); + result = result * DeviceInfo.wPageDataSize; + } else if (divisor_type == 2) { /* Remainder -- Block */ + result = (addr >> DeviceInfo.nBitsInBlockDataSize); + result = result * DeviceInfo.wBlockDataSize; + } + + result = addr - result; + + return result; +} + +#define NUM_DEVICES 1 +#define PARTITIONS 8 + +#define GLOB_SBD_NAME "nd" +#define GLOB_SBD_IRQ_NUM (29) +#define GLOB_VERSION "driver version 20091110" + +#define GLOB_SBD_IOCTL_GC (0x7701) +#define GLOB_SBD_IOCTL_WL (0x7702) +#define GLOB_SBD_IOCTL_FORMAT (0x7703) +#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704) +#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705) +#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706) +#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707) +#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708) +#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709) +#define GLOB_SBD_IOCTL_READ_DATA (0x770A) + +static u32 reserved_mb_for_os_image = 0; + +int nand_debug_level; +module_param(nand_debug_level, int, 0644); +MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3"); + +MODULE_LICENSE("GPL"); + +struct spectra_nand_dev { + struct pci_dev *dev; + u64 size; + u16 users; + spinlock_t qlock; + void __iomem *ioaddr; /* Mapped address */ + struct request_queue *queue; + struct task_struct *thread; + struct gendisk *gd; + u8 *tmp_buf; +}; + + +static int GLOB_SBD_majornum; + +static char *GLOB_version = GLOB_VERSION; + +static struct spectra_nand_dev nand_device[NUM_DEVICES]; + +static struct mutex spectra_lock; + +static int res_blks_os = 1; + +struct spectra_indentfy_dev_tag IdentifyDeviceData; + +static int force_flush_cache(void) +{ + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (ERR == GLOB_FTL_Flush_Cache()) { + printk(KERN_ERR "Fail to Flush FTL Cache!\n"); + return -EFAULT; + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; +} + +struct ioctl_rw_page_info { + u8 *data; + unsigned int page; +}; + +static int ioctl_read_page_data(unsigned long arg) +{ + u8 *buf; + struct ioctl_rw_page_info info; + int result = PASS; + + if (copy_from_user(&info, (void __user *)arg, sizeof(info))) + return -EFAULT; + + buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!buf) { + printk(KERN_ERR "ioctl_read_page_data: " + "failed to allocate memory\n"); + return -ENOMEM; + } + + mutex_lock(&spectra_lock); + result = GLOB_FTL_Page_Read(buf, + (u64)info.page * IdentifyDeviceData.PageDataSize); + mutex_unlock(&spectra_lock); + + if (copy_to_user((void __user *)info.data, buf, + IdentifyDeviceData.PageDataSize)) { + printk(KERN_ERR "ioctl_read_page_data: " + "failed to copy user data\n"); + kfree(buf); + return -EFAULT; + } + + kfree(buf); + return result; +} + +static int ioctl_write_page_data(unsigned long arg) +{ + u8 *buf; + struct ioctl_rw_page_info info; + int result = PASS; + + if (copy_from_user(&info, (void __user *)arg, sizeof(info))) + return -EFAULT; + + buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!buf) { + printk(KERN_ERR "ioctl_write_page_data: " + "failed to allocate memory\n"); + return -ENOMEM; + } + + if (copy_from_user(buf, (void __user *)info.data, + IdentifyDeviceData.PageDataSize)) { + printk(KERN_ERR "ioctl_write_page_data: " + "failed to copy user data\n"); + kfree(buf); + return -EFAULT; + } + + mutex_lock(&spectra_lock); + result = GLOB_FTL_Page_Write(buf, + (u64)info.page * IdentifyDeviceData.PageDataSize); + mutex_unlock(&spectra_lock); + + kfree(buf); + return result; +} + +/* Return how many blocks should be reserved for bad block replacement */ +static int get_res_blk_num_bad_blk(void) +{ + return IdentifyDeviceData.wDataBlockNum / 10; +} + +/* Return how many blocks should be reserved for OS image */ +static int get_res_blk_num_os(void) +{ + u32 res_blks, blk_size; + + blk_size = IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock; + + res_blks = (reserved_mb_for_os_image * 1024 * 1024) / blk_size; + + if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum)) + res_blks = 1; /* Reserved 1 block for block table */ + + return res_blks; +} + +static void SBD_prepare_flush(struct request_queue *q, struct request *rq) +{ + rq->cmd_type = REQ_TYPE_LINUX_BLOCK; + /* rq->timeout = 5 * HZ; */ + rq->cmd[0] = REQ_LB_OP_FLUSH; +} + +/* Transfer a full request. */ +static int do_transfer(struct spectra_nand_dev *tr, struct request *req) +{ + u64 start_addr, addr; + u32 logical_start_sect, hd_start_sect; + u32 nsect, hd_sects; + u32 rsect, tsect = 0; + char *buf; + u32 ratio = IdentifyDeviceData.PageDataSize >> 9; + + start_addr = (u64)(blk_rq_pos(req)) << 9; + /* Add a big enough offset to prevent the OS Image from + * being accessed or damaged by file system */ + start_addr += IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock * + res_blks_os; + + if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && + req->cmd[0] == REQ_LB_OP_FLUSH) { + if (force_flush_cache()) /* Fail to flush cache */ + return -EIO; + else + return 0; + } + + if (!blk_fs_request(req)) + return -EIO; + + if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) { + printk(KERN_ERR "Spectra error: request over the NAND " + "capacity!sector %d, current_nr_sectors %d, " + "while capacity is %d\n", + (int)blk_rq_pos(req), + blk_rq_cur_sectors(req), + (int)get_capacity(tr->gd)); + return -EIO; + } + + logical_start_sect = start_addr >> 9; + hd_start_sect = logical_start_sect / ratio; + rsect = logical_start_sect - hd_start_sect * ratio; + + addr = (u64)hd_start_sect * ratio * 512; + buf = req->buffer; + nsect = blk_rq_cur_sectors(req); + + if (rsect) + tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect; + + switch (rq_data_dir(req)) { + case READ: + /* Read the first NAND page */ + if (rsect) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9); + addr += IdentifyDeviceData.PageDataSize; + buf += tsect << 9; + nsect -= tsect; + } + + /* Read the other NAND pages */ + for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { + if (GLOB_FTL_Page_Read(buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += IdentifyDeviceData.PageDataSize; + } + + /* Read the last NAND pages */ + if (nsect % ratio) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9); + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; + + case WRITE: + /* Write the first NAND page */ + if (rsect) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9); + if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += tsect << 9; + nsect -= tsect; + } + + /* Write the other NAND pages */ + for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { + if (GLOB_FTL_Page_Write(buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += IdentifyDeviceData.PageDataSize; + } + + /* Write the last NAND pages */ + if (nsect % ratio) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9); + if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; + + default: + printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); + return -EIO; + } +} + +/* This function is copied from drivers/mtd/mtd_blkdevs.c */ +static int spectra_trans_thread(void *arg) +{ + struct spectra_nand_dev *tr = arg; + struct request_queue *rq = tr->queue; + struct request *req = NULL; + + /* we might get involved when memory gets low, so use PF_MEMALLOC */ + current->flags |= PF_MEMALLOC; + + spin_lock_irq(rq->queue_lock); + while (!kthread_should_stop()) { + int res; + + if (!req) { + req = blk_fetch_request(rq); + if (!req) { + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(rq->queue_lock); + schedule(); + spin_lock_irq(rq->queue_lock); + continue; + } + } + + spin_unlock_irq(rq->queue_lock); + + mutex_lock(&spectra_lock); + res = do_transfer(tr, req); + mutex_unlock(&spectra_lock); + + spin_lock_irq(rq->queue_lock); + + if (!__blk_end_request_cur(req, res)) + req = NULL; + } + + if (req) + __blk_end_request_all(req, -EIO); + + spin_unlock_irq(rq->queue_lock); + + return 0; +} + + +/* Request function that "handles clustering". */ +static void GLOB_SBD_request(struct request_queue *rq) +{ + struct spectra_nand_dev *pdev = rq->queuedata; + wake_up_process(pdev->thread); +} + +static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode) + +{ + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + return 0; +} + +static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode) +{ + int ret; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + mutex_lock(&spectra_lock); + ret = force_flush_cache(); + mutex_unlock(&spectra_lock); + + return 0; +} + +static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + geo->heads = 4; + geo->sectors = 16; + geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); + + nand_dbg_print(NAND_DBG_DEBUG, + "heads: %d, sectors: %d, cylinders: %d\n", + geo->heads, geo->sectors, geo->cylinders); + + return 0; +} + +int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + switch (cmd) { + case GLOB_SBD_IOCTL_GC: + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra IOCTL: Garbage Collection " + "being performed\n"); + if (PASS != GLOB_FTL_Garbage_Collection()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_WL: + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra IOCTL: Static Wear Leveling " + "being performed\n"); + if (PASS != GLOB_FTL_Wear_Leveling()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_FORMAT: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format " + "being performed\n"); + if (PASS != GLOB_FTL_Flash_Format()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_FLUSH_CACHE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush " + "being performed\n"); + mutex_lock(&spectra_lock); + ret = force_flush_cache(); + mutex_unlock(&spectra_lock); + return ret; + + case GLOB_SBD_IOCTL_COPY_BLK_TABLE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Copy block table\n"); + if (copy_to_user((void __user *)arg, + get_blk_table_start_addr(), + get_blk_table_len())) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Copy wear leveling table\n"); + if (copy_to_user((void __user *)arg, + get_wear_leveling_table_start_addr(), + get_wear_leveling_table_len())) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_GET_NAND_INFO: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Get NAND info\n"); + if (copy_to_user((void __user *)arg, &IdentifyDeviceData, + sizeof(IdentifyDeviceData))) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_WRITE_DATA: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Write one page data\n"); + return ioctl_write_page_data(arg); + + case GLOB_SBD_IOCTL_READ_DATA: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Read one page data\n"); + return ioctl_read_page_data(arg); + } + + return -ENOTTY; +} + +static struct block_device_operations GLOB_SBD_ops = { + .owner = THIS_MODULE, + .open = GLOB_SBD_open, + .release = GLOB_SBD_release, + .locked_ioctl = GLOB_SBD_ioctl, + .getgeo = GLOB_SBD_getgeo, +}; + +static int SBD_setup_device(struct spectra_nand_dev *dev, int which) +{ + int res_blks; + u32 sects; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + memset(dev, 0, sizeof(struct spectra_nand_dev)); + + nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks " + "for OS image, %d blocks for bad block replacement.\n", + get_res_blk_num_os(), + get_res_blk_num_bad_blk()); + + res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os(); + + dev->size = (u64)IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock * + (IdentifyDeviceData.wDataBlockNum - res_blks); + + res_blks_os = get_res_blk_num_os(); + + spin_lock_init(&dev->qlock); + + dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!dev->tmp_buf) { + printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n", + __FILE__, __LINE__); + goto out_vfree; + } + + dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock); + if (dev->queue == NULL) { + printk(KERN_ERR + "Spectra: Request queue could not be initialized." + " Aborting\n "); + goto out_vfree; + } + dev->queue->queuedata = dev; + + /* As Linux block layer doens't support >4KB hardware sector, */ + /* Here we force report 512 byte hardware sector size to Kernel */ + blk_queue_logical_block_size(dev->queue, 512); + + blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH, + SBD_prepare_flush); + + dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd"); + if (IS_ERR(dev->thread)) { + blk_cleanup_queue(dev->queue); + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + return PTR_ERR(dev->thread); + } + + dev->gd = alloc_disk(PARTITIONS); + if (!dev->gd) { + printk(KERN_ERR + "Spectra: Could not allocate disk. Aborting \n "); + goto out_vfree; + } + dev->gd->major = GLOB_SBD_majornum; + dev->gd->first_minor = which * PARTITIONS; + dev->gd->fops = &GLOB_SBD_ops; + dev->gd->queue = dev->queue; + dev->gd->private_data = dev; + snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a'); + + sects = dev->size >> 9; + nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects); + set_capacity(dev->gd, sects); + + add_disk(dev->gd); + + return 0; +out_vfree: + return -ENOMEM; +} + +/* +static ssize_t show_nand_block_num(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.wDataBlockNum); +} + +static ssize_t show_nand_pages_per_block(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.PagesPerBlock); +} + +static ssize_t show_nand_page_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.PageDataSize); +} + +static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL); +static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL); +static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL); + +static void create_sysfs_entry(struct device *dev) +{ + if (device_create_file(dev, &dev_attr_nand_block_num)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_block_num.\n"); + if (device_create_file(dev, &dev_attr_nand_pages_per_block)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_pages_per_block.\n"); + if (device_create_file(dev, &dev_attr_nand_page_size)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_page_size.\n"); +} +*/ + +static int GLOB_SBD_init(void) +{ + int i; + + /* Set debug output level (0~3) here. 3 is most verbose */ + nand_debug_level = 0; + + printk(KERN_ALERT "Spectra: %s\n", GLOB_version); + + mutex_init(&spectra_lock); + + GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME); + if (GLOB_SBD_majornum <= 0) { + printk(KERN_ERR "Unable to get the major %d for Spectra", + GLOB_SBD_majornum); + return -EBUSY; + } + + if (PASS != GLOB_FTL_Flash_Init()) { + printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. " + "Aborting\n"); + goto out_flash_register; + } + + /* create_sysfs_entry(&dev->dev); */ + + if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) { + printk(KERN_ERR "Spectra: Unable to Read Flash Device. " + "Aborting\n"); + goto out_flash_register; + } else { + nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: " + "Num blocks=%d, pagesperblock=%d, " + "pagedatasize=%d, ECCBytesPerSector=%d\n", + (int)IdentifyDeviceData.NumBlocks, + (int)IdentifyDeviceData.PagesPerBlock, + (int)IdentifyDeviceData.PageDataSize, + (int)IdentifyDeviceData.wECCBytesPerSector); + } + + printk(KERN_ALERT "Spectra: searching block table, please wait ...\n"); + if (GLOB_FTL_Init() != PASS) { + printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. " + "Aborting\n"); + goto out_ftl_flash_register; + } + printk(KERN_ALERT "Spectra: block table has been found.\n"); + + for (i = 0; i < NUM_DEVICES; i++) + if (SBD_setup_device(&nand_device[i], i) == -ENOMEM) + goto out_ftl_flash_register; + + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra: module loaded with major number %d\n", + GLOB_SBD_majornum); + + return 0; + +out_ftl_flash_register: + GLOB_FTL_Cache_Release(); +out_flash_register: + GLOB_FTL_Flash_Release(); + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + printk(KERN_ERR "Spectra: Module load failed.\n"); + + return -ENOMEM; +} + +static void __exit GLOB_SBD_exit(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < NUM_DEVICES; i++) { + struct spectra_nand_dev *dev = &nand_device[i]; + if (dev->gd) { + del_gendisk(dev->gd); + put_disk(dev->gd); + } + if (dev->queue) + blk_cleanup_queue(dev->queue); + kfree(dev->tmp_buf); + } + + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + + mutex_lock(&spectra_lock); + force_flush_cache(); + mutex_unlock(&spectra_lock); + + GLOB_FTL_Cache_Release(); + + GLOB_FTL_Flash_Release(); + + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra FTL module (major number %d) unloaded.\n", + GLOB_SBD_majornum); +} + +static int __init setup_reserve_space_for_os_image(char *cmdline) +{ + unsigned long value; + int error; + + printk(KERN_ALERT "Spectra - cmdline: %s\n", cmdline); + if (!cmdline) + return -EINVAL; + + error = strict_strtoul((const char *)cmdline, 10, &value); + if (error) + return -EINVAL; + + reserved_mb_for_os_image = value; + + return 0; +} + +early_param("res_nand", setup_reserve_space_for_os_image); + +module_init(GLOB_SBD_init); +module_exit(GLOB_SBD_exit); diff --git a/drivers/block/spectra/ffsport.h b/drivers/block/spectra/ffsport.h new file mode 100644 index 000000000000..6c5d90c53430 --- /dev/null +++ b/drivers/block/spectra/ffsport.h @@ -0,0 +1,84 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FFSPORT_ +#define _FFSPORT_ + +#include "ffsdefs.h" + +#if defined __GNUC__ +#define PACKED +#define PACKED_GNU __attribute__ ((packed)) +#define UNALIGNED +#endif + +#include +#include /* for strcpy(), stricmp(), etc */ +#include /* for kmalloc(), kfree() */ +#include +#include +#include +#include + +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include +#include +#include +#include "flash.h" + +#define VERBOSE 1 + +#define NAND_DBG_WARN 1 +#define NAND_DBG_DEBUG 2 +#define NAND_DBG_TRACE 3 + +extern int nand_debug_level; + +#ifdef VERBOSE +#define nand_dbg_print(level, args...) \ + do { \ + if (level <= nand_debug_level) \ + printk(KERN_ALERT args); \ + } while (0) +#else +#define nand_dbg_print(level, args...) +#endif + +#ifdef SUPPORT_BIG_ENDIAN +#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \ + (u16)((u16)(w) >> 8)) + +#define INVERTUINT32(dw) (((u32)(dw) << 24) | \ + (((u32)(dw) << 8) & 0x00ff0000) | \ + (((u32)(dw) >> 8) & 0x0000ff00) | \ + ((u32)(dw) >> 24)) +#else +#define INVERTUINT16(w) w +#define INVERTUINT32(dw) dw +#endif + +extern int GLOB_Calc_Used_Bits(u32 n); +extern u64 GLOB_u64_Div(u64 addr, u32 divisor); +extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type); + +#endif /* _FFSPORT_ */ diff --git a/drivers/block/spectra/flash.c b/drivers/block/spectra/flash.c new file mode 100644 index 000000000000..134aa5166a8d --- /dev/null +++ b/drivers/block/spectra/flash.c @@ -0,0 +1,4731 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include "flash.h" +#include "ffsdefs.h" +#include "lld.h" +#include "lld_nand.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize)) +#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \ + DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize)) + +#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ + BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK)) + +#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK)) + +#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ + BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK)) + +#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK)) + +#if DEBUG_BNDRY +void debug_boundary_lineno_error(int chnl, int limit, int no, + int lineno, char *filename) +{ + if (chnl >= limit) + printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, " + "at %s:%d. Other info:%d. Aborting...\n", + chnl, limit, filename, lineno, no); +} +/* static int globalmemsize; */ +#endif + +static u16 FTL_Cache_If_Hit(u64 dwPageAddr); +static int FTL_Cache_Read(u64 dwPageAddr); +static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr, + u16 cache_blk); +static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr, + u8 cache_blk, u16 flag); +static int FTL_Cache_Write(void); +static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr); +static void FTL_Calculate_LRU(void); +static u32 FTL_Get_Block_Index(u32 wBlockNum); + +static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, + u8 BT_Tag, u16 *Page); +static int FTL_Read_Block_Table(void); +static int FTL_Write_Block_Table(int wForce); +static int FTL_Write_Block_Table_Data(void); +static int FTL_Check_Block_Table(int wOldTable); +static int FTL_Static_Wear_Leveling(void); +static u32 FTL_Replace_Block_Table(void); +static int FTL_Write_IN_Progress_Block_Table_Page(void); + +static u32 FTL_Get_Page_Num(u64 length); +static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr); + +static u32 FTL_Replace_OneBlock(u32 wBlockNum, + u32 wReplaceNum); +static u32 FTL_Replace_LWBlock(u32 wBlockNum, + int *pGarbageCollect); +static u32 FTL_Replace_MWBlock(void); +static int FTL_Replace_Block(u64 blk_addr); +static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX); + +static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr); + +struct device_info_tag DeviceInfo; +struct flash_cache_tag Cache; +static struct spectra_l2_cache_info cache_l2; + +static u8 *cache_l2_page_buf; +static u8 *cache_l2_blk_buf; + +u8 *g_pBlockTable; +u8 *g_pWearCounter; +u16 *g_pReadCounter; +u32 *g_pBTBlocks; +static u16 g_wBlockTableOffset; +static u32 g_wBlockTableIndex; +static u8 g_cBlockTableStatus; + +static u8 *g_pTempBuf; +static u8 *flag_check_blk_table; +static u8 *tmp_buf_search_bt_in_block; +static u8 *spare_buf_search_bt_in_block; +static u8 *spare_buf_bt_search_bt_in_block; +static u8 *tmp_buf1_read_blk_table; +static u8 *tmp_buf2_read_blk_table; +static u8 *flags_static_wear_leveling; +static u8 *tmp_buf_write_blk_table_data; +static u8 *tmp_buf_read_disturbance; + +u8 *buf_read_page_main_spare; +u8 *buf_write_page_main_spare; +u8 *buf_read_page_spare; +u8 *buf_get_bad_block; + +#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) +struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS]; +struct flash_cache_tag cache_start_copy; +#endif + +int g_wNumFreeBlocks; +u8 g_SBDCmdIndex; + +static u8 *g_pIPF; +static u8 bt_flag = FIRST_BT_ID; +static u8 bt_block_changed; + +static u16 cache_block_to_write; +static u8 last_erased = FIRST_BT_ID; + +static u8 GC_Called; +static u8 BT_GC_Called; + +#if CMD_DMA +#define COPY_BACK_BUF_NUM 10 + +static u8 ftl_cmd_cnt; /* Init value is 0 */ +u8 *g_pBTDelta; +u8 *g_pBTDelta_Free; +u8 *g_pBTStartingCopy; +u8 *g_pWearCounterCopy; +u16 *g_pReadCounterCopy; +u8 *g_pBlockTableCopies; +u8 *g_pNextBlockTable; +static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM]; +static int cp_back_buf_idx; + +static u8 *g_temp_buf; + +#pragma pack(push, 1) +#pragma pack(1) +struct BTableChangesDelta { + u8 ftl_cmd_cnt; + u8 ValidFields; + u16 g_wBlockTableOffset; + u32 g_wBlockTableIndex; + u32 BT_Index; + u32 BT_Entry_Value; + u32 WC_Index; + u8 WC_Entry_Value; + u32 RC_Index; + u16 RC_Entry_Value; +}; + +#pragma pack(pop) + +struct BTableChangesDelta *p_BTableChangesDelta; +#endif + + +#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK) +#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK) + +#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u32)) +#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u8)) +#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u16)) +#if SUPPORT_LARGE_BLOCKNUM +#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u8) * 3) +#else +#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u16)) +#endif +#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \ + FTL_Get_WearCounter_Table_Mem_Size_Bytes +#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \ + FTL_Get_ReadCounter_Table_Mem_Size_Bytes + +static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void) +{ + u32 byte_num; + + if (DeviceInfo.MLCDevice) { + byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + + DeviceInfo.wDataBlockNum * sizeof(u8) + + DeviceInfo.wDataBlockNum * sizeof(u16); + } else { + byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + + DeviceInfo.wDataBlockNum * sizeof(u8); + } + + byte_num += 4 * sizeof(u8); + + return byte_num; +} + +static u16 FTL_Get_Block_Table_Flash_Size_Pages(void) +{ + return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes()); +} + +static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx, + u32 sizeTxed) +{ + u32 wBytesCopied, blk_tbl_size, wBytes; + u32 *pbt = (u32 *)g_pBlockTable; + + blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); + for (wBytes = 0; + (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size); + wBytes++) { +#if SUPPORT_LARGE_BLOCKNUM + flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3] + >> (((wBytes + sizeTxed) % 3) ? + ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF; +#else + flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2] + >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; +#endif + } + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); + wBytesCopied = wBytes; + wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? + (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); + memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes); + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + + if (DeviceInfo.MLCDevice) { + blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); + wBytesCopied += wBytes; + for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) + flashBuf[wBytes + wBytesCopied] = + (g_pReadCounter[(wBytes + sizeTxed) / 2] >> + (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; + } + + return wBytesCopied + wBytes; +} + +static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf, + u32 sizeToTx, u32 sizeTxed) +{ + u32 wBytesCopied, blk_tbl_size, wBytes; + u32 *pbt = (u32 *)g_pBlockTable; + + blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); + for (wBytes = 0; (wBytes < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { +#if SUPPORT_LARGE_BLOCKNUM + if (!((wBytes + sizeTxed) % 3)) + pbt[(wBytes + sizeTxed) / 3] = 0; + pbt[(wBytes + sizeTxed) / 3] |= + (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ? + ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)); +#else + if (!((wBytes + sizeTxed) % 2)) + pbt[(wBytes + sizeTxed) / 2] = 0; + pbt[(wBytes + sizeTxed) / 2] |= + (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ? + 0 : 8)); +#endif + } + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); + wBytesCopied = wBytes; + wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? + (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); + memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes); + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + + if (DeviceInfo.MLCDevice) { + wBytesCopied += wBytes; + blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); + for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { + if (((wBytes + sizeTxed) % 2)) + g_pReadCounter[(wBytes + sizeTxed) / 2] = 0; + g_pReadCounter[(wBytes + sizeTxed) / 2] |= + (flashBuf[wBytes] << + (((wBytes + sizeTxed) % 2) ? 0 : 8)); + } + } + + return wBytesCopied+wBytes; +} + +static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag) +{ + int i; + + for (i = 0; i < BTSIG_BYTES; i++) + buf[BTSIG_OFFSET + i] = + ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) % + (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID; + + return PASS; +} + +static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray) +{ + static u8 tag[BTSIG_BYTES >> 1]; + int i, j, k, tagi, tagtemp, status; + + *tagarray = (u8 *)tag; + tagi = 0; + + for (i = 0; i < (BTSIG_BYTES - 1); i++) { + for (j = i + 1; (j < BTSIG_BYTES) && + (tagi < (BTSIG_BYTES >> 1)); j++) { + tagtemp = buf[BTSIG_OFFSET + j] - + buf[BTSIG_OFFSET + i]; + if (tagtemp && !(tagtemp % BTSIG_DELTA)) { + tagtemp = (buf[BTSIG_OFFSET + i] + + (1 + LAST_BT_ID - FIRST_BT_ID) - + (i * BTSIG_DELTA)) % + (1 + LAST_BT_ID - FIRST_BT_ID); + status = FAIL; + for (k = 0; k < tagi; k++) { + if (tagtemp == tag[k]) + status = PASS; + } + + if (status == FAIL) { + tag[tagi++] = tagtemp; + i = (j == (i + 1)) ? i + 1 : i; + j = (j == (i + 1)) ? i + 1 : i; + } + } + } + } + + return tagi; +} + + +static int FTL_Execute_SPL_Recovery(void) +{ + u32 j, block, blks; + u32 *pbt = (u32 *)g_pBlockTable; + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock; + for (j = 0; j <= blks; j++) { + block = (pbt[j]); + if (((block & BAD_BLOCK) != BAD_BLOCK) && + ((block & SPARE_BLOCK) == SPARE_BLOCK)) { + ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK); + if (FAIL == ret) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)(block & ~BAD_BLOCK)); + MARK_BLOCK_AS_BAD(pbt[j]); + } + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_IdentifyDevice +* Inputs: pointer to identify data structure +* Outputs: PASS / FAIL +* Description: the identify data structure is filled in with +* information for the block driver. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev_data->NumBlocks = DeviceInfo.wTotalBlocks; + dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock; + dev_data->PageDataSize = DeviceInfo.wPageDataSize; + dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector; + dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum; + + return PASS; +} + +/* ..... */ +static int allocate_memory(void) +{ + u32 block_table_size, page_size, block_size, mem_size; + u32 total_bytes = 0; + int i; +#if CMD_DMA + int j; +#endif + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + page_size = DeviceInfo.wPageSize; + block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; + + block_table_size = DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8) + sizeof(u16)); + block_table_size += (DeviceInfo.wPageDataSize - + (block_table_size % DeviceInfo.wPageDataSize)) % + DeviceInfo.wPageDataSize; + + /* Malloc memory for block tables */ + g_pBlockTable = kmalloc(block_table_size, GFP_ATOMIC); + if (!g_pBlockTable) + goto block_table_fail; + memset(g_pBlockTable, 0, block_table_size); + total_bytes += block_table_size; + + g_pWearCounter = (u8 *)(g_pBlockTable + + DeviceInfo.wDataBlockNum * sizeof(u32)); + + if (DeviceInfo.MLCDevice) + g_pReadCounter = (u16 *)(g_pBlockTable + + DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8))); + + /* Malloc memory and init for cache items */ + for (i = 0; i < CACHE_ITEM_NUM; i++) { + Cache.array[i].address = NAND_CACHE_INIT_ADDR; + Cache.array[i].use_cnt = 0; + Cache.array[i].changed = CLEAR; + Cache.array[i].buf = kmalloc(Cache.cache_item_size, + GFP_ATOMIC); + if (!Cache.array[i].buf) + goto cache_item_fail; + memset(Cache.array[i].buf, 0, Cache.cache_item_size); + total_bytes += Cache.cache_item_size; + } + + /* Malloc memory for IPF */ + g_pIPF = kmalloc(page_size, GFP_ATOMIC); + if (!g_pIPF) + goto ipf_fail; + memset(g_pIPF, 0, page_size); + total_bytes += page_size; + + /* Malloc memory for data merging during Level2 Cache flush */ + cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC); + if (!cache_l2_page_buf) + goto cache_l2_page_buf_fail; + memset(cache_l2_page_buf, 0xff, page_size); + total_bytes += page_size; + + cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC); + if (!cache_l2_blk_buf) + goto cache_l2_blk_buf_fail; + memset(cache_l2_blk_buf, 0xff, block_size); + total_bytes += block_size; + + /* Malloc memory for temp buffer */ + g_pTempBuf = kmalloc(Cache.cache_item_size, GFP_ATOMIC); + if (!g_pTempBuf) + goto Temp_buf_fail; + memset(g_pTempBuf, 0, Cache.cache_item_size); + total_bytes += Cache.cache_item_size; + + /* Malloc memory for block table blocks */ + mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32); + g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBTBlocks) + goto bt_blocks_fail; + memset(g_pBTBlocks, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Check_Block_Table */ + flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC); + if (!flag_check_blk_table) + goto flag_check_blk_table_fail; + total_bytes += DeviceInfo.wDataBlockNum; + + /* Malloc memory for function FTL_Search_Block_Table_IN_Block */ + tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf_search_bt_in_block) + goto tmp_buf_search_bt_in_block_fail; + memset(tmp_buf_search_bt_in_block, 0xff, page_size); + total_bytes += page_size; + + mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize; + spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); + if (!spare_buf_search_bt_in_block) + goto spare_buf_search_bt_in_block_fail; + memset(spare_buf_search_bt_in_block, 0xff, mem_size); + total_bytes += mem_size; + + spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); + if (!spare_buf_bt_search_bt_in_block) + goto spare_buf_bt_search_bt_in_block_fail; + memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Read_Block_Table */ + tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf1_read_blk_table) + goto tmp_buf1_read_blk_table_fail; + memset(tmp_buf1_read_blk_table, 0xff, page_size); + total_bytes += page_size; + + tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf2_read_blk_table) + goto tmp_buf2_read_blk_table_fail; + memset(tmp_buf2_read_blk_table, 0xff, page_size); + total_bytes += page_size; + + /* Malloc memory for function FTL_Static_Wear_Leveling */ + flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum, + GFP_ATOMIC); + if (!flags_static_wear_leveling) + goto flags_static_wear_leveling_fail; + total_bytes += DeviceInfo.wDataBlockNum; + + /* Malloc memory for function FTL_Write_Block_Table_Data */ + if (FTL_Get_Block_Table_Flash_Size_Pages() > 3) + mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() - + 2 * DeviceInfo.wPageSize; + else + mem_size = DeviceInfo.wPageSize; + tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC); + if (!tmp_buf_write_blk_table_data) + goto tmp_buf_write_blk_table_data_fail; + memset(tmp_buf_write_blk_table_data, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Read_Disturbance */ + tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC); + if (!tmp_buf_read_disturbance) + goto tmp_buf_read_disturbance_fail; + memset(tmp_buf_read_disturbance, 0xff, block_size); + total_bytes += block_size; + + /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */ + buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); + if (!buf_read_page_main_spare) + goto buf_read_page_main_spare_fail; + total_bytes += DeviceInfo.wPageSize; + + /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */ + buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); + if (!buf_write_page_main_spare) + goto buf_write_page_main_spare_fail; + total_bytes += DeviceInfo.wPageSize; + + /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */ + buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); + if (!buf_read_page_spare) + goto buf_read_page_spare_fail; + memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize); + total_bytes += DeviceInfo.wPageSpareSize; + + /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */ + buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); + if (!buf_get_bad_block) + goto buf_get_bad_block_fail; + memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize); + total_bytes += DeviceInfo.wPageSpareSize; + +#if CMD_DMA + g_temp_buf = kmalloc(block_size, GFP_ATOMIC); + if (!g_temp_buf) + goto temp_buf_fail; + memset(g_temp_buf, 0xff, block_size); + total_bytes += block_size; + + /* Malloc memory for copy of block table used in CDMA mode */ + g_pBTStartingCopy = kmalloc(block_table_size, GFP_ATOMIC); + if (!g_pBTStartingCopy) + goto bt_starting_copy; + memset(g_pBTStartingCopy, 0, block_table_size); + total_bytes += block_table_size; + + g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy + + DeviceInfo.wDataBlockNum * sizeof(u32)); + + if (DeviceInfo.MLCDevice) + g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy + + DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8))); + + /* Malloc memory for block table copies */ + mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) + + 5 * DeviceInfo.wDataBlockNum * sizeof(u8); + if (DeviceInfo.MLCDevice) + mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16); + g_pBlockTableCopies = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBlockTableCopies) + goto blk_table_copies_fail; + memset(g_pBlockTableCopies, 0, mem_size); + total_bytes += mem_size; + g_pNextBlockTable = g_pBlockTableCopies; + + /* Malloc memory for Block Table Delta */ + mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta); + g_pBTDelta = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBTDelta) + goto bt_delta_fail; + memset(g_pBTDelta, 0, mem_size); + total_bytes += mem_size; + g_pBTDelta_Free = g_pBTDelta; + + /* Malloc memory for Copy Back Buffers */ + for (j = 0; j < COPY_BACK_BUF_NUM; j++) { + cp_back_buf_copies[j] = kmalloc(block_size, GFP_ATOMIC); + if (!cp_back_buf_copies[j]) + goto cp_back_buf_copies_fail; + memset(cp_back_buf_copies[j], 0, block_size); + total_bytes += block_size; + } + cp_back_buf_idx = 0; + + /* Malloc memory for pending commands list */ + mem_size = sizeof(struct pending_cmd) * MAX_DESCS; + info.pcmds = kzalloc(mem_size, GFP_KERNEL); + if (!info.pcmds) + goto pending_cmds_buf_fail; + total_bytes += mem_size; + + /* Malloc memory for CDMA descripter table */ + mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS; + info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL); + if (!info.cdma_desc_buf) + goto cdma_desc_buf_fail; + total_bytes += mem_size; + + /* Malloc memory for Memcpy descripter table */ + mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS; + info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL); + if (!info.memcp_desc_buf) + goto memcp_desc_buf_fail; + total_bytes += mem_size; +#endif + + nand_dbg_print(NAND_DBG_WARN, + "Total memory allocated in FTL layer: %d\n", total_bytes); + + return PASS; + +#if CMD_DMA +memcp_desc_buf_fail: + kfree(info.cdma_desc_buf); +cdma_desc_buf_fail: + kfree(info.pcmds); +pending_cmds_buf_fail: +cp_back_buf_copies_fail: + j--; + for (; j >= 0; j--) + kfree(cp_back_buf_copies[j]); + kfree(g_pBTDelta); +bt_delta_fail: + kfree(g_pBlockTableCopies); +blk_table_copies_fail: + kfree(g_pBTStartingCopy); +bt_starting_copy: + kfree(g_temp_buf); +temp_buf_fail: + kfree(buf_get_bad_block); +#endif + +buf_get_bad_block_fail: + kfree(buf_read_page_spare); +buf_read_page_spare_fail: + kfree(buf_write_page_main_spare); +buf_write_page_main_spare_fail: + kfree(buf_read_page_main_spare); +buf_read_page_main_spare_fail: + kfree(tmp_buf_read_disturbance); +tmp_buf_read_disturbance_fail: + kfree(tmp_buf_write_blk_table_data); +tmp_buf_write_blk_table_data_fail: + kfree(flags_static_wear_leveling); +flags_static_wear_leveling_fail: + kfree(tmp_buf2_read_blk_table); +tmp_buf2_read_blk_table_fail: + kfree(tmp_buf1_read_blk_table); +tmp_buf1_read_blk_table_fail: + kfree(spare_buf_bt_search_bt_in_block); +spare_buf_bt_search_bt_in_block_fail: + kfree(spare_buf_search_bt_in_block); +spare_buf_search_bt_in_block_fail: + kfree(tmp_buf_search_bt_in_block); +tmp_buf_search_bt_in_block_fail: + kfree(flag_check_blk_table); +flag_check_blk_table_fail: + kfree(g_pBTBlocks); +bt_blocks_fail: + kfree(g_pTempBuf); +Temp_buf_fail: + kfree(cache_l2_blk_buf); +cache_l2_blk_buf_fail: + kfree(cache_l2_page_buf); +cache_l2_page_buf_fail: + kfree(g_pIPF); +ipf_fail: +cache_item_fail: + i--; + for (; i >= 0; i--) + kfree(Cache.array[i].buf); + kfree(g_pBlockTable); +block_table_fail: + printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n", + __FILE__, __LINE__); + + return -ENOMEM; +} + +/* .... */ +static int free_memory(void) +{ + int i; + +#if CMD_DMA + kfree(info.memcp_desc_buf); + kfree(info.cdma_desc_buf); + kfree(info.pcmds); + for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--) + kfree(cp_back_buf_copies[i]); + kfree(g_pBTDelta); + kfree(g_pBlockTableCopies); + kfree(g_pBTStartingCopy); + kfree(g_temp_buf); + kfree(buf_get_bad_block); +#endif + kfree(buf_read_page_spare); + kfree(buf_write_page_main_spare); + kfree(buf_read_page_main_spare); + kfree(tmp_buf_read_disturbance); + kfree(tmp_buf_write_blk_table_data); + kfree(flags_static_wear_leveling); + kfree(tmp_buf2_read_blk_table); + kfree(tmp_buf1_read_blk_table); + kfree(spare_buf_bt_search_bt_in_block); + kfree(spare_buf_search_bt_in_block); + kfree(tmp_buf_search_bt_in_block); + kfree(flag_check_blk_table); + kfree(g_pBTBlocks); + kfree(g_pTempBuf); + kfree(g_pIPF); + for (i = CACHE_ITEM_NUM - 1; i >= 0; i--) + kfree(Cache.array[i].buf); + kfree(g_pBlockTable); + + return 0; +} + +static void dump_cache_l2_table(void) +{ + struct list_head *p; + struct spectra_l2_cache_list *pnd; + int n, i; + + n = 0; + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num); +/* + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { + if (pnd->pages_array[i] != MAX_U32_VALUE) + nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]); + } +*/ + n++; + } +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Init +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: allocates the memory for cache array, +* important data structures +* clears the cache array +* reads the block table from flash into array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Init(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + Cache.pages_per_item = 1; + Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize; + + if (allocate_memory() != PASS) + return FAIL; + +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_CHANS + MAX_DESCS)); +#endif + ftl_cmd_cnt = 0; +#endif + + if (FTL_Read_Block_Table() != PASS) + return FAIL; + + /* Init the Level2 Cache data structure */ + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) + cache_l2.blk_array[i] = MAX_U32_VALUE; + cache_l2.cur_blk_idx = 0; + cache_l2.cur_page_num = 0; + INIT_LIST_HEAD(&cache_l2.table.list); + cache_l2.table.logical_blk_num = MAX_U32_VALUE; + + dump_cache_l2_table(); + + return 0; +} + + +#if CMD_DMA +#if 0 +static void save_blk_table_changes(u16 idx) +{ + u8 ftl_cmd; + u32 *pbt = (u32 *)g_pBTStartingCopy; + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u16 id; + u8 cache_blks; + + id = idx - MAX_CHANS; + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = + int_cache[id].cache.changed; + } +#endif + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + + while (ftl_cmd <= PendingCMD[idx].Tag) { + if (p_BTableChangesDelta->ValidFields == 0x01) { + g_wBlockTableOffset = + p_BTableChangesDelta->g_wBlockTableOffset; + } else if (p_BTableChangesDelta->ValidFields == 0x0C) { + pbt[p_BTableChangesDelta->BT_Index] = + p_BTableChangesDelta->BT_Entry_Value; + debug_boundary_error((( + p_BTableChangesDelta->BT_Index)), + DeviceInfo.wDataBlockNum, 0); + } else if (p_BTableChangesDelta->ValidFields == 0x03) { + g_wBlockTableOffset = + p_BTableChangesDelta->g_wBlockTableOffset; + g_wBlockTableIndex = + p_BTableChangesDelta->g_wBlockTableIndex; + } else if (p_BTableChangesDelta->ValidFields == 0x30) { + g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] = + p_BTableChangesDelta->WC_Entry_Value; + } else if ((DeviceInfo.MLCDevice) && + (p_BTableChangesDelta->ValidFields == 0xC0)) { + g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] = + p_BTableChangesDelta->RC_Entry_Value; + nand_dbg_print(NAND_DBG_DEBUG, + "In event status setting read counter " + "GLOB_ftl_cmd_cnt %u Count %u Index %u\n", + ftl_cmd, + p_BTableChangesDelta->RC_Entry_Value, + (unsigned int)p_BTableChangesDelta->RC_Index); + } else { + nand_dbg_print(NAND_DBG_DEBUG, + "This should never occur \n"); + } + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } +} + +static void discard_cmds(u16 n) +{ + u32 *pbt = (u32 *)g_pBTStartingCopy; + u8 ftl_cmd; + unsigned long k; +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u8 cache_blks; + u16 id; +#endif + + if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) || + (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) { + for (k = 0; k < DeviceInfo.wDataBlockNum; k++) { + if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK))) + MARK_BLK_AS_DISCARD(pbt[k]); + } + } + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[n].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + id = n - MAX_CHANS; + + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + if (PendingCMD[n].CMD == MEMCOPY_CMD) { + if ((cache_start_copy.array[cache_blks].buf <= + PendingCMD[n].DataDestAddr) && + ((cache_start_copy.array[cache_blks].buf + + Cache.cache_item_size) > + PendingCMD[n].DataDestAddr)) { + cache_start_copy.array[cache_blks].address = + NAND_CACHE_INIT_ADDR; + cache_start_copy.array[cache_blks].use_cnt = + 0; + cache_start_copy.array[cache_blks].changed = + CLEAR; + } + } else { + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = + int_cache[id].cache.changed; + } + } +#endif +} + +static void process_cmd_pass(int *first_failed_cmd, u16 idx) +{ + if (0 == *first_failed_cmd) + save_blk_table_changes(idx); + else + discard_cmds(idx); +} + +static void process_cmd_fail_abort(int *first_failed_cmd, + u16 idx, int event) +{ + u32 *pbt = (u32 *)g_pBTStartingCopy; + u8 ftl_cmd; + unsigned long i; + int erase_fail, program_fail; +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u8 cache_blks; + u16 id; +#endif + + if (0 == *first_failed_cmd) + *first_failed_cmd = PendingCMD[idx].SBDCmdIndex; + + nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occured " + "while executing %u Command %u accesing Block %u\n", + (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt, + PendingCMD[idx].CMD, + (unsigned int)PendingCMD[idx].Block); + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[idx].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + id = idx - MAX_CHANS; + + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) { + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = SET; + } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) { + cache_start_copy.array[cache_blks].address = + NAND_CACHE_INIT_ADDR; + cache_start_copy.array[cache_blks].use_cnt = 0; + cache_start_copy.array[cache_blks].changed = + CLEAR; + } else if (PendingCMD[idx].CMD == ERASE_CMD) { + /* ? */ + } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) { + /* ? */ + } + } +#endif + + erase_fail = (event == EVENT_ERASE_FAILURE) && + (PendingCMD[idx].CMD == ERASE_CMD); + + program_fail = (event == EVENT_PROGRAM_FAILURE) && + ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) || + (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD)); + + if (erase_fail || program_fail) { + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (PendingCMD[idx].Block == + (pbt[i] & (~BAD_BLOCK))) + MARK_BLOCK_AS_BAD(pbt[i]); + } + } +} + +static void process_cmd(int *first_failed_cmd, u16 idx, int event) +{ + u8 ftl_cmd; + int cmd_match = 0; + + if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag) + cmd_match = 1; + + if (PendingCMD[idx].Status == CMD_PASS) { + process_cmd_pass(first_failed_cmd, idx); + } else if ((PendingCMD[idx].Status == CMD_FAIL) || + (PendingCMD[idx].Status == CMD_ABORT)) { + process_cmd_fail_abort(first_failed_cmd, idx, event); + } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) && + PendingCMD[idx].Tag) { + nand_dbg_print(NAND_DBG_DEBUG, + " Command no. %hu is not executed\n", + (unsigned int)PendingCMD[idx].Tag); + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[idx].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + } +} +#endif + +static void process_cmd(int *first_failed_cmd, u16 idx, int event) +{ + printk(KERN_ERR "temporary workaround function. " + "Should not be called! \n"); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Event_Status +* Inputs: none +* Outputs: Event Code +* Description: It is called by SBD after hardware interrupt signalling +* completion of commands chain +* It does following things +* get event status from LLD +* analyze command chain status +* determine last command executed +* analyze results +* rebuild the block table in case of uncorrectable error +* return event code +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Event_Status(int *first_failed_cmd) +{ + int event_code = PASS; + u16 i_P; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + *first_failed_cmd = 0; + + event_code = GLOB_LLD_Event_Status(); + + switch (event_code) { + case EVENT_PASS: + nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n"); + break; + case EVENT_UNCORRECTABLE_DATA_ERROR: + nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n"); + break; + case EVENT_PROGRAM_FAILURE: + case EVENT_ERASE_FAILURE: + nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. " + "Event code: 0x%x\n", event_code); + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta; + for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS); + i_P++) + process_cmd(first_failed_cmd, i_P, event_code); + memcpy(g_pBlockTable, g_pBTStartingCopy, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memcpy(g_pWearCounter, g_pWearCounterCopy, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memcpy(g_pReadCounter, g_pReadCounterCopy, + DeviceInfo.wDataBlockNum * sizeof(u16)); + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&Cache, (void *)&cache_start_copy, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_DESCS + MAX_CHANS)); +#endif + break; + default: + nand_dbg_print(NAND_DBG_WARN, + "Handling unexpected event code - 0x%x\n", + event_code); + event_code = ERR; + break; + } + + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memcpy(g_pWearCounterCopy, g_pWearCounter, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memcpy(g_pReadCounterCopy, g_pReadCounter, + DeviceInfo.wDataBlockNum * sizeof(u16)); + + g_pBTDelta_Free = g_pBTDelta; + ftl_cmd_cnt = 0; + g_pNextBlockTable = g_pBlockTableCopies; + cp_back_buf_idx = 0; + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_DESCS + MAX_CHANS)); +#endif + + return event_code; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: glob_ftl_execute_cmds +* Inputs: none +* Outputs: none +* Description: pass thru to LLD +***************************************************************/ +u16 glob_ftl_execute_cmds(void) +{ + nand_dbg_print(NAND_DBG_TRACE, + "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n", + (unsigned int)ftl_cmd_cnt); + g_SBDCmdIndex = 0; + return glob_lld_execute_cmds(); +} + +#endif + +#if !CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Read Immediate +* Inputs: pointer to data +* address of data +* Outputs: PASS / FAIL +* Description: Reads one page of data into RAM directly from flash without +* using or disturbing cache.It is assumed this function is called +* with CMD-DMA disabled. +*****************************************************************/ +int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr) +{ + int wResult = FAIL; + u32 Block; + u16 Page; + u32 phy_blk; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + Block = BLK_FROM_ADDR(addr); + Page = PAGE_FROM_ADDR(addr, Block); + + if (!IS_SPARE_BLOCK(Block)) + return FAIL; + + phy_blk = pbt[Block]; + wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1); + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++; + if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock] + >= MAX_READ_COUNTER) + FTL_Read_Disturbance(phy_blk); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } + + return wResult; +} +#endif + +#ifdef SUPPORT_BIG_ENDIAN +/********************************************************************* +* Function: FTL_Invert_Block_Table +* Inputs: none +* Outputs: none +* Description: Re-format the block table in ram based on BIG_ENDIAN and +* LARGE_BLOCKNUM if necessary +**********************************************************************/ +static void FTL_Invert_Block_Table(void) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#ifdef SUPPORT_LARGE_BLOCKNUM + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + pbt[i] = INVERTUINT32(pbt[i]); + g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]); + } +#else + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + pbt[i] = INVERTUINT16(pbt[i]); + g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]); + } +#endif +} +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Flash_Init +* Inputs: none +* Outputs: PASS=0 / FAIL=0x01 (based on read ID) +* Description: The flash controller is initialized +* The flash device is reset +* Perform a flash READ ID command to confirm that a +* valid device is attached and active. +* The DeviceInfo structure gets filled in +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flash_Init(void) +{ + int status = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + g_SBDCmdIndex = 0; + + GLOB_LLD_Flash_Init(); + + status = GLOB_LLD_Read_Device_ID(); + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Inputs: none +* Outputs: PASS=0 / FAIL=0x01 (based on read ID) +* Description: The flash controller is released +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return GLOB_LLD_Flash_Release(); +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Cache_Release +* Inputs: none +* Outputs: none +* Description: release all allocated memory in GLOB_FTL_Init +* (allocated in GLOB_FTL_Init) +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void GLOB_FTL_Cache_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + free_memory(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_If_Hit +* Inputs: Page Address +* Outputs: Block number/UNHIT BLOCK +* Description: Determines if the addressed page is in cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u16 FTL_Cache_If_Hit(u64 page_addr) +{ + u16 item; + u64 addr; + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + item = UNHIT_CACHE_ITEM; + for (i = 0; i < CACHE_ITEM_NUM; i++) { + addr = Cache.array[i].address; + if ((page_addr >= addr) && + (page_addr < (addr + Cache.cache_item_size))) { + item = i; + break; + } + } + + return item; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Calculate_LRU +* Inputs: None +* Outputs: None +* Description: Calculate the least recently block in a cache and record its +* index in LRU field. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Calculate_LRU(void) +{ + u16 i, bCurrentLRU, bTempCount; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bCurrentLRU = 0; + bTempCount = MAX_WORD_VALUE; + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (Cache.array[i].use_cnt < bTempCount) { + bCurrentLRU = i; + bTempCount = Cache.array[i].use_cnt; + } + } + + Cache.LRU = bCurrentLRU; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read_Page +* Inputs: pointer to read buffer, logical address and cache item number +* Outputs: None +* Description: Read the page from the cached block addressed by blocknumber +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item) +{ + u8 *start_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + start_addr = Cache.array[cache_item].buf; + start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >> + DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize); + +#if CMD_DMA + GLOB_LLD_MemCopy_CMD(data_buf, start_addr, + DeviceInfo.wPageDataSize, 0); + ftl_cmd_cnt++; +#else + memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize); +#endif + + if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE) + Cache.array[cache_item].use_cnt++; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read_All +* Inputs: pointer to read buffer,block address +* Outputs: PASS=0 / FAIL =1 +* Description: It reads pages in cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr) +{ + int wResult = PASS; + u32 Block; + u32 lba; + u16 Page; + u16 PageCount; + u32 *pbt = (u32 *)g_pBlockTable; + u32 i; + + Block = BLK_FROM_ADDR(phy_addr); + Page = PAGE_FROM_ADDR(phy_addr, Block); + PageCount = Cache.pages_per_item; + + nand_dbg_print(NAND_DBG_DEBUG, + "%s, Line %d, Function: %s, Block: 0x%x\n", + __FILE__, __LINE__, __func__, Block); + + lba = 0xffffffff; + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if ((pbt[i] & (~BAD_BLOCK)) == Block) { + lba = i; + if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) || + IS_DISCARDED_BLOCK(i)) { + /* Add by yunpeng -2008.12.3 */ +#if CMD_DMA + GLOB_LLD_MemCopy_CMD(pData, g_temp_buf, + PageCount * DeviceInfo.wPageDataSize, 0); + ftl_cmd_cnt++; +#else + memset(pData, 0xFF, + PageCount * DeviceInfo.wPageDataSize); +#endif + return wResult; + } else { + continue; /* break ?? */ + } + } + } + + if (0xffffffff == lba) + printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n"); + +#if CMD_DMA + wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page, + PageCount, LLD_CMD_FLAG_MODE_CDMA); + if (DeviceInfo.MLCDevice) { + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; + nand_dbg_print(NAND_DBG_DEBUG, + "Read Counter modified in ftl_cmd_cnt %u" + " Block %u Counter%u\n", + ftl_cmd_cnt, (unsigned int)Block, + g_pReadCounter[Block - + DeviceInfo.wSpectraStartBlock]); + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->RC_Index = + Block - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->RC_Entry_Value = + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0xC0; + + ftl_cmd_cnt++; + + if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= + MAX_READ_COUNTER) + FTL_Read_Disturbance(Block); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } else { + ftl_cmd_cnt++; + } +#else + wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount); + if (wResult == FAIL) + return wResult; + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; + if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= + MAX_READ_COUNTER) + FTL_Read_Disturbance(Block); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_All +* Inputs: pointer to cache in sys memory +* address of free block in flash +* Outputs: PASS=0 / FAIL=1 +* Description: writes all the pages of the block in cache to flash +* +* NOTE:need to make sure this works ok when cache is limited +* to a partial block. This is where copy-back would be +* activated. This would require knowing which pages in the +* cached block are clean/dirty.Right now we only know if +* the whole block is clean/dirty. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr) +{ + u16 wResult = PASS; + u32 Block; + u16 Page; + u16 PageCount; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written " + "on %d\n", cache_block_to_write, + (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)); + + Block = BLK_FROM_ADDR(blk_addr); + Page = PAGE_FROM_ADDR(blk_addr, Block); + PageCount = Cache.pages_per_item; + +#if CMD_DMA + if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData, + Block, Page, PageCount)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated! " + "Need Bad Block replacing.\n", + __FILE__, __LINE__, __func__, Block); + wResult = FAIL; + } + ftl_cmd_cnt++; +#else + if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s," + " Line %d, Function %s, new Bad Block %d generated!" + "Need Bad Block replacing.\n", + __FILE__, __LINE__, __func__, Block); + wResult = FAIL; + } +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Update_Block +* Inputs: pointer to buffer,page address,block address +* Outputs: PASS=0 / FAIL=1 +* Description: It updates the cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Update_Block(u8 *pData, + u64 old_page_addr, u64 blk_addr) +{ + int i, j; + u8 *buf = pData; + int wResult = PASS; + int wFoundInCache; + u64 page_addr; + u64 addr; + u64 old_blk_addr; + u16 page_offset; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + old_blk_addr = (u64)(old_page_addr >> + DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize; + page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >> + DeviceInfo.nBitsInPageDataSize); + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { + page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize; + if (i != page_offset) { + wFoundInCache = FAIL; + for (j = 0; j < CACHE_ITEM_NUM; j++) { + addr = Cache.array[j].address; + addr = FTL_Get_Physical_Block_Addr(addr) + + GLOB_u64_Remainder(addr, 2); + if ((addr >= page_addr) && addr < + (page_addr + Cache.cache_item_size)) { + wFoundInCache = PASS; + buf = Cache.array[j].buf; + Cache.array[j].changed = SET; +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = j; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[j].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[j].changed; +#endif +#endif + break; + } + } + if (FAIL == wFoundInCache) { + if (ERR == FTL_Cache_Read_All(g_pTempBuf, + page_addr)) { + wResult = FAIL; + break; + } + buf = g_pTempBuf; + } + } else { + buf = pData; + } + + if (FAIL == FTL_Cache_Write_All(buf, + blk_addr + (page_addr - old_blk_addr))) { + wResult = FAIL; + break; + } + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Copy_Block +* Inputs: source block address +* Destination block address +* Outputs: PASS=0 / FAIL=1 +* Description: used only for static wear leveling to move the block +* containing static data to new blocks(more worn) +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr) +{ + int i, r1, r2, wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { + r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr + + i * DeviceInfo.wPageDataSize); + r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr + + i * DeviceInfo.wPageDataSize); + if ((ERR == r1) || (FAIL == r2)) { + wResult = FAIL; + break; + } + } + + return wResult; +} + +/* Search the block table to find out the least wear block and then return it */ +static u32 find_least_worn_blk_for_l2_cache(void) +{ + int i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 least_wear_cnt = MAX_BYTE_VALUE; + u32 least_wear_blk_idx = MAX_U32_VALUE; + u32 phy_idx; + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + phy_idx = (u32)((~BAD_BLOCK) & pbt[i]); + if (phy_idx > DeviceInfo.wSpectraEndBlock) + printk(KERN_ERR "find_least_worn_blk_for_l2_cache: " + "Too big phy block num (%d)\n", phy_idx); + if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) { + least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock]; + least_wear_blk_idx = i; + } + } + } + + nand_dbg_print(NAND_DBG_WARN, + "find_least_worn_blk_for_l2_cache: " + "find block %d with least worn counter (%d)\n", + least_wear_blk_idx, least_wear_cnt); + + return least_wear_blk_idx; +} + + + +/* Get blocks for Level2 Cache */ +static int get_l2_cache_blks(void) +{ + int n; + u32 blk; + u32 *pbt = (u32 *)g_pBlockTable; + + for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) { + blk = find_least_worn_blk_for_l2_cache(); + if (blk > DeviceInfo.wDataBlockNum) { + nand_dbg_print(NAND_DBG_WARN, + "find_least_worn_blk_for_l2_cache: " + "No enough free NAND blocks (n: %d) for L2 Cache!\n", n); + return FAIL; + } + /* Tag the free block as discard in block table */ + pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK; + /* Add the free block to the L2 Cache block array */ + cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK); + } + + return PASS; +} + +static int erase_l2_cache_blocks(void) +{ + int i, ret = PASS; + u32 pblk, lblk; + u64 addr; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) { + pblk = cache_l2.blk_array[i]; + + /* If the L2 cache block is invalid, then just skip it */ + if (MAX_U32_VALUE == pblk) + continue; + + BUG_ON(pblk > DeviceInfo.wSpectraEndBlock); + + addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize; + if (PASS == GLOB_FTL_Block_Erase(addr)) { + /* Get logical block number of the erased block */ + lblk = FTL_Get_Block_Index(pblk); + BUG_ON(BAD_BLOCK == lblk); + /* Tag it as free in the block table */ + pbt[lblk] &= (u32)(~DISCARD_BLOCK); + pbt[lblk] |= (u32)(SPARE_BLOCK); + } else { + MARK_BLOCK_AS_BAD(pbt[lblk]); + ret = ERR; + } + } + + return ret; +} + +/* + * Merge the valid data page in the L2 cache blocks into NAND. +*/ +static int flush_l2_cache(void) +{ + struct list_head *p; + struct spectra_l2_cache_list *pnd, *tmp_pnd; + u32 *pbt = (u32 *)g_pBlockTable; + u32 phy_blk, l2_blk; + u64 addr; + u16 l2_page; + int i, ret = PASS; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (list_empty(&cache_l2.table.list)) /* No data to flush */ + return ret; + + //dump_cache_l2_table(); + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (IS_SPARE_BLOCK(pnd->logical_blk_num) || + IS_BAD_BLOCK(pnd->logical_blk_num) || + IS_DISCARDED_BLOCK(pnd->logical_blk_num)) { + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); + memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize); + } else { + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf, + phy_blk, 0, DeviceInfo.wPagesPerBlock); + if (ret == FAIL) { + printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); + } + } + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { + if (pnd->pages_array[i] != MAX_U32_VALUE) { + l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff]; + l2_page = pnd->pages_array[i] & 0xffff; + ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1); + if (ret == FAIL) { + printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); + } + memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize); + } + } + + /* Find a free block and tag the original block as discarded */ + addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize; + ret = FTL_Replace_Block(addr); + if (ret == FAIL) { + printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__); + } + + /* Write back the updated data into NAND */ + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { + nand_dbg_print(NAND_DBG_WARN, + "Program NAND block %d fail in %s, Line %d\n", + phy_blk, __FILE__, __LINE__); + /* This may not be really a bad block. So just tag it as discarded. */ + /* Then it has a chance to be erased when garbage collection. */ + /* If it is really bad, then the erase will fail and it will be marked */ + /* as bad then. Otherwise it will be marked as free and can be used again */ + MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]); + /* Find another free block and write it again */ + FTL_Replace_Block(addr); + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { + printk(KERN_ERR "Failed to write back block %d when flush L2 cache." + "Some data will be lost!\n", phy_blk); + MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]); + } + } else { + /* tag the new free block as used block */ + pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK); + } + } + + /* Destroy the L2 Cache table and free the memory of all nodes */ + list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) { + list_del(&pnd->list); + kfree(pnd); + } + + /* Erase discard L2 cache blocks */ + if (erase_l2_cache_blocks() != PASS) + nand_dbg_print(NAND_DBG_WARN, + " Erase L2 cache blocks error in %s, Line %d\n", + __FILE__, __LINE__); + + /* Init the Level2 Cache data structure */ + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) + cache_l2.blk_array[i] = MAX_U32_VALUE; + cache_l2.cur_blk_idx = 0; + cache_l2.cur_page_num = 0; + INIT_LIST_HEAD(&cache_l2.table.list); + cache_l2.table.logical_blk_num = MAX_U32_VALUE; + + return ret; +} + +/* + * Write back a changed victim cache item to the Level2 Cache + * and update the L2 Cache table to map the change. + * If the L2 Cache is full, then start to do the L2 Cache flush. +*/ +static int write_back_to_l2_cache(u8 *buf, u64 logical_addr) +{ + u32 logical_blk_num; + u16 logical_page_num; + struct list_head *p; + struct spectra_l2_cache_list *pnd, *pnd_new; + u32 node_size; + int i, found; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* + * If Level2 Cache table is empty, then it means either: + * 1. This is the first time that the function called after FTL_init + * or + * 2. The Level2 Cache has just been flushed + * + * So, 'steal' some free blocks from NAND for L2 Cache using + * by just mask them as discard in the block table + */ + if (list_empty(&cache_l2.table.list)) { + BUG_ON(cache_l2.cur_blk_idx != 0); + BUG_ON(cache_l2.cur_page_num!= 0); + BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE); + if (FAIL == get_l2_cache_blks()) { + GLOB_FTL_Garbage_Collection(); + if (FAIL == get_l2_cache_blks()) { + printk(KERN_ALERT "Fail to get L2 cache blks!\n"); + return FAIL; + } + } + } + + logical_blk_num = BLK_FROM_ADDR(logical_addr); + logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); + BUG_ON(logical_blk_num == MAX_U32_VALUE); + + /* Write the cache item data into the current position of L2 Cache */ +#if CMD_DMA + /* + * TODO + */ +#else + if (FAIL == GLOB_LLD_Write_Page_Main(buf, + cache_l2.blk_array[cache_l2.cur_blk_idx], + cache_l2.cur_page_num, 1)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " + "%s, Line %d, new Bad Block %d generated!\n", + __FILE__, __LINE__, + cache_l2.blk_array[cache_l2.cur_blk_idx]); + + /* TODO: tag the current block as bad and try again */ + + return FAIL; + } +#endif + + /* + * Update the L2 Cache table. + * + * First seaching in the table to see whether the logical block + * has been mapped. If not, then kmalloc a new node for the + * logical block, fill data, and then insert it to the list. + * Otherwise, just update the mapped node directly. + */ + found = 0; + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (pnd->logical_blk_num == logical_blk_num) { + pnd->pages_array[logical_page_num] = + (cache_l2.cur_blk_idx << 16) | + cache_l2.cur_page_num; + found = 1; + break; + } + } + if (!found) { /* Create new node for the logical block here */ + + /* The logical pages to physical pages map array is + * located at the end of struct spectra_l2_cache_list. + */ + node_size = sizeof(struct spectra_l2_cache_list) + + sizeof(u32) * DeviceInfo.wPagesPerBlock; + pnd_new = kmalloc(node_size, GFP_ATOMIC); + if (!pnd_new) { + printk(KERN_ERR "Failed to kmalloc in %s Line %d\n", + __FILE__, __LINE__); + /* + * TODO: Need to flush all the L2 cache into NAND ASAP + * since no memory available here + */ + } + pnd_new->logical_blk_num = logical_blk_num; + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) + pnd_new->pages_array[i] = MAX_U32_VALUE; + pnd_new->pages_array[logical_page_num] = + (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num; + list_add(&pnd_new->list, &cache_l2.table.list); + } + + /* Increasing the current position pointer of the L2 Cache */ + cache_l2.cur_page_num++; + if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) { + cache_l2.cur_blk_idx++; + if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) { + /* The L2 Cache is full. Need to flush it now */ + nand_dbg_print(NAND_DBG_WARN, + "L2 Cache is full, will start to flush it\n"); + flush_l2_cache(); + } else { + cache_l2.cur_page_num = 0; + } + } + + return PASS; +} + +/* + * Seach in the Level2 Cache table to find the cache item. + * If find, read the data from the NAND page of L2 Cache, + * Otherwise, return FAIL. + */ +static int search_l2_cache(u8 *buf, u64 logical_addr) +{ + u32 logical_blk_num; + u16 logical_page_num; + struct list_head *p; + struct spectra_l2_cache_list *pnd; + u32 tmp = MAX_U32_VALUE; + u32 phy_blk; + u16 phy_page; + int ret = FAIL; + + logical_blk_num = BLK_FROM_ADDR(logical_addr); + logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); + + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (pnd->logical_blk_num == logical_blk_num) { + tmp = pnd->pages_array[logical_page_num]; + break; + } + } + + if (tmp != MAX_U32_VALUE) { /* Found valid map */ + phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF]; + phy_page = tmp & 0xFFFF; +#if CMD_DMA + /* TODO */ +#else + ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1); +#endif + } + + return ret; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_Back +* Inputs: pointer to data cached in sys memory +* address of free block in flash +* Outputs: PASS=0 / FAIL=1 +* Description: writes all the pages of Cache Block to flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr) +{ + int i, j, iErase; + u64 old_page_addr, addr, phy_addr; + u32 *pbt = (u32 *)g_pBlockTable; + u32 lba; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) + + GLOB_u64_Remainder(blk_addr, 2); + + iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL; + + pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK); + +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = (u32)(blk_addr >> + DeviceInfo.nBitsInBlockDataSize); + p_BTableChangesDelta->BT_Entry_Value = + pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + for (i = 0; i < RETRY_TIMES; i++) { + if (PASS == iErase) { + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { + lba = BLK_FROM_ADDR(blk_addr); + MARK_BLOCK_AS_BAD(pbt[lba]); + i = RETRY_TIMES; + break; + } + } + + for (j = 0; j < CACHE_ITEM_NUM; j++) { + addr = Cache.array[j].address; + if ((addr <= blk_addr) && + ((addr + Cache.cache_item_size) > blk_addr)) + cache_block_to_write = j; + } + + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + if (PASS == FTL_Cache_Update_Block(pData, + old_page_addr, phy_addr)) { + cache_block_to_write = UNHIT_CACHE_ITEM; + break; + } else { + iErase = PASS; + } + } + + if (i >= RETRY_TIMES) { + if (ERR == FTL_Flash_Error_Handle(pData, + old_page_addr, blk_addr)) + return ERR; + else + return FAIL; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_Page +* Inputs: Pointer to buffer, page address, cache block number +* Outputs: PASS=0 / FAIL=1 +* Description: It writes the data in Cache Block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr, + u8 cache_blk, u16 flag) +{ + u8 *pDest; + u64 addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + addr = Cache.array[cache_blk].address; + pDest = Cache.array[cache_blk].buf; + + pDest += (unsigned long)(page_addr - addr); + Cache.array[cache_blk].changed = SET; +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = cache_blk; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[cache_blk].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[cache_blk].changed; +#endif + GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag); + ftl_cmd_cnt++; +#else + memcpy(pDest, pData, DeviceInfo.wPageDataSize); +#endif + if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE) + Cache.array[cache_blk].use_cnt++; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: It writes least frequently used Cache block to flash if it +* has been changed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write(void) +{ + int i, bResult = PASS; + u16 bNO, least_count = 0xFFFF; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FTL_Calculate_LRU(); + + bNO = Cache.LRU; + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: " + "Least used cache block is %d\n", bNO); + + if (Cache.array[bNO].changed != SET) + return bResult; + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache" + " Block %d containing logical block %d is dirty\n", + bNO, + (u32)(Cache.array[bNO].address >> + DeviceInfo.nBitsInBlockDataSize)); +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = bNO; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[bNO].address; + int_cache[ftl_cmd_cnt].cache.changed = CLEAR; +#endif +#endif + bResult = write_back_to_l2_cache(Cache.array[bNO].buf, + Cache.array[bNO].address); + if (bResult != ERR) + Cache.array[bNO].changed = CLEAR; + + least_count = Cache.array[bNO].use_cnt; + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (i == bNO) + continue; + if (Cache.array[i].use_cnt > 0) + Cache.array[i].use_cnt -= least_count; + } + + return bResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read +* Inputs: Page address +* Outputs: PASS=0 / FAIL=1 +* Description: It reads the block from device in Cache Block +* Set the LRU count to 1 +* Mark the Cache Block as clean +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Read(u64 logical_addr) +{ + u64 item_addr, phy_addr; + u16 num; + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + num = Cache.LRU; /* The LRU cache item will be overwritten */ + + item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) * + Cache.cache_item_size; + Cache.array[num].address = item_addr; + Cache.array[num].use_cnt = 1; + Cache.array[num].changed = CLEAR; + +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = num; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[num].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[num].changed; +#endif +#endif + /* + * Search in L2 Cache. If hit, fill data into L1 Cache item buffer, + * Otherwise, read it from NAND + */ + ret = search_l2_cache(Cache.array[num].buf, logical_addr); + if (PASS == ret) /* Hit in L2 Cache */ + return ret; + + /* Compute the physical start address of NAND device according to */ + /* the logical start address of the cache item (LRU cache item) */ + phy_addr = FTL_Get_Physical_Block_Addr(item_addr) + + GLOB_u64_Remainder(item_addr, 2); + + return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Check_Block_Table +* Inputs: ? +* Outputs: PASS=0 / FAIL=1 +* Description: It checks the correctness of each block table entry +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Check_Block_Table(int wOldTable) +{ + u32 i; + int wResult = PASS; + u32 blk_idx; + u32 *pbt = (u32 *)g_pBlockTable; + u8 *pFlag = flag_check_blk_table; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (NULL != pFlag) { + memset(pFlag, FAIL, DeviceInfo.wDataBlockNum); + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + blk_idx = (u32)(pbt[i] & (~BAD_BLOCK)); + + /* + * 20081006/KBV - Changed to pFlag[i] reference + * to avoid buffer overflow + */ + + /* + * 2008-10-20 Yunpeng Note: This change avoid + * buffer overflow, but changed function of + * the code, so it should be re-write later + */ + if ((blk_idx > DeviceInfo.wSpectraEndBlock) || + PASS == pFlag[i]) { + wResult = FAIL; + break; + } else { + pFlag[i] = PASS; + } + } + } + + return wResult; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_Block_Table +* Inputs: flasg +* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to +* happen. -1 Error +* Description: It writes the block table +* Block table always mapped to LBA 0 which inturn mapped +* to any physical block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Write_Block_Table(int wForce) +{ + u32 *pbt = (u32 *)g_pBlockTable; + int wSuccess = PASS; + u32 wTempBlockTableIndex; + u16 bt_pages, new_bt_offset; + u8 blockchangeoccured = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) + return 0; + + if (PASS == wForce) { + g_wBlockTableOffset = + (u16)(DeviceInfo.wPagesPerBlock - bt_pages); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = + g_wBlockTableOffset; + p_BTableChangesDelta->ValidFields = 0x01; +#endif + } + + nand_dbg_print(NAND_DBG_DEBUG, + "Inside FTL_Write_Block_Table: block %d Page:%d\n", + g_wBlockTableIndex, g_wBlockTableOffset); + + do { + new_bt_offset = g_wBlockTableOffset + bt_pages + 1; + if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) || + (new_bt_offset > DeviceInfo.wPagesPerBlock) || + (FAIL == wSuccess)) { + wTempBlockTableIndex = FTL_Replace_Block_Table(); + if (BAD_BLOCK == wTempBlockTableIndex) + return ERR; + if (!blockchangeoccured) { + bt_block_changed = 1; + blockchangeoccured = 1; + } + + g_wBlockTableIndex = wTempBlockTableIndex; + g_wBlockTableOffset = 0; + pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = + g_wBlockTableOffset; + p_BTableChangesDelta->g_wBlockTableIndex = + g_wBlockTableIndex; + p_BTableChangesDelta->ValidFields = 0x03; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + BLOCK_TABLE_INDEX; + p_BTableChangesDelta->BT_Entry_Value = + pbt[BLOCK_TABLE_INDEX]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } + + wSuccess = FTL_Write_Block_Table_Data(); + if (FAIL == wSuccess) + MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); + } while (FAIL == wSuccess); + + g_cBlockTableStatus = CURRENT_BLOCK_TABLE; + + return 1; +} + +/****************************************************************** +* Function: GLOB_FTL_Flash_Format +* Inputs: none +* Outputs: PASS +* Description: The block table stores bad block info, including MDF+ +* blocks gone bad over the ages. Therefore, if we have a +* block table in place, then use it to scan for bad blocks +* If not, then scan for MDF. +* Now, a block table will only be found if spectra was already +* being used. For a fresh flash, we'll go thru scanning for +* MDF. If spectra was being used, then there is a chance that +* the MDF has been corrupted. Spectra avoids writing to the +* first 2 bytes of the spare area to all pages in a block. This +* covers all known flash devices. However, since flash +* manufacturers have no standard of where the MDF is stored, +* this cannot guarantee that the MDF is protected for future +* devices too. The initial scanning for the block table assures +* this. It is ok even if the block table is outdated, as all +* we're looking for are bad block markers. +* Use this when mounting a file system or starting a +* new flash. +* +*********************************************************************/ +static int FTL_Format_Flash(u8 valid_block_table) +{ + u32 i, j; + u32 *pbt = (u32 *)g_pBlockTable; + u32 tempNode; + int ret; + +#if CMD_DMA + u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy; + if (ftl_cmd_cnt) + return FAIL; +#endif + + if (FAIL == FTL_Check_Block_Table(FAIL)) + valid_block_table = 0; + + if (valid_block_table) { + u8 switched = 1; + u32 block, k; + + k = DeviceInfo.wSpectraStartBlock; + while (switched && (k < DeviceInfo.wSpectraEndBlock)) { + switched = 0; + k++; + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + block = (pbt[i] & ~BAD_BLOCK) - + DeviceInfo.wSpectraStartBlock; + if (block != i) { + switched = 1; + tempNode = pbt[i]; + pbt[i] = pbt[block]; + pbt[block] = tempNode; + } + } + } + if ((k == DeviceInfo.wSpectraEndBlock) && switched) + valid_block_table = 0; + } + + if (!valid_block_table) { + memset(g_pBlockTable, 0, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memset(g_pWearCounter, 0, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memset(g_pReadCounter, 0, + DeviceInfo.wDataBlockNum * sizeof(u16)); +#if CMD_DMA + memset(g_pBTStartingCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memset(g_pWearCounterCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memset(g_pReadCounterCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u16)); +#endif + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + if (GLOB_LLD_Get_Bad_Block((u32)j)) + pbt[i] = (u32)(BAD_BLOCK | j); + } + } + + nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n"); + + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) { + ret = GLOB_LLD_Erase_Block(j); + if (FAIL == ret) { + pbt[i] = (u32)(j); + MARK_BLOCK_AS_BAD(pbt[i]); + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, (int)j); + } else { + pbt[i] = (u32)(SPARE_BLOCK | j); + } + } +#if CMD_DMA + pbtStartingCopy[i] = pbt[i]; +#endif + } + + g_wBlockTableOffset = 0; + for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock)) + && ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++) + ; + if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) { + printk(KERN_ERR "All blocks bad!\n"); + return FAIL; + } else { + g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK; + if (i != BLOCK_TABLE_INDEX) { + tempNode = pbt[i]; + pbt[i] = pbt[BLOCK_TABLE_INDEX]; + pbt[BLOCK_TABLE_INDEX] = tempNode; + } + } + pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); + +#if CMD_DMA + pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); +#endif + + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + memset(g_pBTBlocks, 0xFF, + (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32)); + g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex; + FTL_Write_Block_Table(FAIL); + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + Cache.array[i].address = NAND_CACHE_INIT_ADDR; + Cache.array[i].use_cnt = 0; + Cache.array[i].changed = CLEAR; + } + +#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); +#endif + return PASS; +} + +static int force_format_nand(void) +{ + u32 i; + + /* Force erase the whole unprotected physical partiton of NAND */ + printk(KERN_ALERT "Start to force erase whole NAND device ...\n"); + printk(KERN_ALERT "From phyical block %d to %d\n", + DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock); + for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) { + if (GLOB_LLD_Erase_Block(i)) + printk(KERN_ERR "Failed to force erase NAND block %d\n", i); + } + printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n"); + while(1); + + return PASS; +} + +int GLOB_FTL_Flash_Format(void) +{ + //return FTL_Format_Flash(1); + return force_format_nand(); + +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Search_Block_Table_IN_Block +* Inputs: Block Number +* Pointer to page +* Outputs: PASS / FAIL +* Page contatining the block table +* Description: It searches the block table in the block +* passed as an argument. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, + u8 BT_Tag, u16 *Page) +{ + u16 i, j, k; + u16 Result = PASS; + u16 Last_IPF = 0; + u8 BT_Found = 0; + u8 *tagarray; + u8 *tempbuf = tmp_buf_search_bt_in_block; + u8 *pSpareBuf = spare_buf_search_bt_in_block; + u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block; + u8 bt_flag_last_page = 0xFF; + u8 search_in_previous_pages = 0; + u16 bt_pages; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, + "Searching block table in %u block\n", + (unsigned int)BT_Block); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + for (i = bt_pages; i < DeviceInfo.wPagesPerBlock; + i += (bt_pages + 1)) { + nand_dbg_print(NAND_DBG_DEBUG, + "Searching last IPF: %d\n", i); + Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf, + BT_Block, i, 1); + + if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) { + if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) { + continue; + } else { + search_in_previous_pages = 1; + Last_IPF = i; + } + } + + if (!search_in_previous_pages) { + if (i != bt_pages) { + i -= (bt_pages + 1); + Last_IPF = i; + } + } + + if (0 == Last_IPF) + break; + + if (!search_in_previous_pages) { + i = i + 1; + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i); + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, + BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag( + pSpareBufBTLastPage, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag_last_page = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found" + " in page after IPF " + "at block %d " + "page %d\n", + (int)BT_Block, i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + CURRENT_BLOCK_TABLE; + break; + } else { + Result = FAIL; + } + } + } + } + + if (search_in_previous_pages) + i = i - bt_pages; + else + i = i - (bt_pages + 1); + + Result = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %d Page %d", + (int)BT_Block, i); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, + &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) { + bt_flag_last_page = tagarray[k]; + } else { + Result = FAIL; + break; + } + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found " + "in page prior to IPF " + "at block %u page %d\n", + (unsigned int)BT_Block, i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + IN_PROGRESS_BLOCK_TABLE; + break; + } else { + Result = FAIL; + break; + } + } + } + } + + if (Result == FAIL) { + if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) { + BT_Found = 1; + *Page = i - (bt_pages + 1); + } + if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found)) + goto func_return; + } + + if (Last_IPF == 0) { + i = 0; + Result = PASS; + nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of " + "Block %u Page %u", (unsigned int)BT_Block, i); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, + &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag_last_page = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found " + "in page after IPF at " + "block %u page %u\n", + (unsigned int)BT_Block, + (unsigned int)i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + CURRENT_BLOCK_TABLE; + goto func_return; + } else { + Result = FAIL; + } + } + } + + if (Result == FAIL) + goto func_return; + } +func_return: + return Result; +} + +u8 *get_blk_table_start_addr(void) +{ + return g_pBlockTable; +} + +unsigned long get_blk_table_len(void) +{ + return DeviceInfo.wDataBlockNum * sizeof(u32); +} + +u8 *get_wear_leveling_table_start_addr(void) +{ + return g_pWearCounter; +} + +unsigned long get_wear_leveling_table_len(void) +{ + return DeviceInfo.wDataBlockNum * sizeof(u8); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Read_Block_Table +* Inputs: none +* Outputs: PASS / FAIL +* Description: read the flash spare area and find a block containing the +* most recent block table(having largest block_table_counter). +* Find the last written Block table in this block. +* Check the correctness of Block Table +* If CDMA is enabled, this function is called in +* polling mode. +* We don't need to store changes in Block table in this +* function as it is called only at initialization +* +* Note: Currently this function is called at initialization +* before any read/erase/write command issued to flash so, +* there is no need to wait for CDMA list to complete as of now +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Read_Block_Table(void) +{ + u16 i = 0; + int k, j; + u8 *tempBuf, *tagarray; + int wResult = FAIL; + int status = FAIL; + u8 block_table_found = 0; + int search_result; + u32 Block; + u16 Page = 0; + u16 PageCount; + u16 bt_pages; + int wBytesCopied = 0, tempvar; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + tempBuf = tmp_buf1_read_blk_table; + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + for (j = DeviceInfo.wSpectraStartBlock; + j <= (int)DeviceInfo.wSpectraEndBlock; + j++) { + status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1); + k = 0; + i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray); + if (i) { + status = GLOB_LLD_Read_Page_Main_Polling(tempBuf, + j, 0, 1); + for (; k < i; k++) { + if (tagarray[k] == tempBuf[3]) + break; + } + } + + if (k < i) + k = tagarray[k]; + else + continue; + + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is contained in Block %d %d\n", + (unsigned int)j, (unsigned int)k); + + if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) { + g_pBTBlocks[k-FIRST_BT_ID] = j; + block_table_found = 1; + } else { + printk(KERN_ERR "FTL_Read_Block_Table -" + "This should never happens. " + "Two block table have same counter %u!\n", k); + } + } + + if (block_table_found) { + if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL && + g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) { + j = LAST_BT_ID; + while ((j > FIRST_BT_ID) && + (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL)) + j--; + if (j == FIRST_BT_ID) { + j = LAST_BT_ID; + last_erased = LAST_BT_ID; + } else { + last_erased = (u8)j + 1; + while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL == + g_pBTBlocks[j - FIRST_BT_ID])) + j--; + } + } else { + j = FIRST_BT_ID; + while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL) + j++; + last_erased = (u8)j; + while ((j < LAST_BT_ID) && (BTBLOCK_INVAL != + g_pBTBlocks[j - FIRST_BT_ID])) + j++; + if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL) + j--; + } + + if (last_erased > j) + j += (1 + LAST_BT_ID - FIRST_BT_ID); + + for (; (j >= last_erased) && (FAIL == wResult); j--) { + i = (j - FIRST_BT_ID) % + (1 + LAST_BT_ID - FIRST_BT_ID); + search_result = + FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i], + i + FIRST_BT_ID, &Page); + if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) + block_table_found = 0; + + while ((search_result == PASS) && (FAIL == wResult)) { + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Read_Block_Table:" + "Block: %u Page: %u " + "contains block table\n", + (unsigned int)g_pBTBlocks[i], + (unsigned int)Page); + + tempBuf = tmp_buf2_read_blk_table; + + for (k = 0; k < bt_pages; k++) { + Block = g_pBTBlocks[i]; + PageCount = 1; + + status = + GLOB_LLD_Read_Page_Main_Polling( + tempBuf, Block, Page, PageCount); + + tempvar = k ? 0 : 4; + + wBytesCopied += + FTL_Copy_Block_Table_From_Flash( + tempBuf + tempvar, + DeviceInfo.wPageDataSize - tempvar, + wBytesCopied); + + Page++; + } + + wResult = FTL_Check_Block_Table(FAIL); + if (FAIL == wResult) { + block_table_found = 0; + if (Page > bt_pages) + Page -= ((bt_pages<<1) + 1); + else + search_result = FAIL; + } + } + } + } + + if (PASS == wResult) { + if (!block_table_found) + FTL_Execute_SPL_Recovery(); + + if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) + g_wBlockTableOffset = (u16)Page + 1; + else + g_wBlockTableOffset = (u16)Page - bt_pages; + + g_wBlockTableIndex = (u32)g_pBTBlocks[i]; + +#if CMD_DMA + if (DeviceInfo.MLCDevice) + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32) + + DeviceInfo.wDataBlockNum * sizeof(u8) + + DeviceInfo.wDataBlockNum * sizeof(u16)); + else + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32) + + DeviceInfo.wDataBlockNum * sizeof(u8)); +#endif + } + + if (FAIL == wResult) + printk(KERN_ERR "Yunpeng - " + "Can not find valid spectra block table!\n"); + +#if AUTO_FORMAT_FLASH + if (FAIL == wResult) { + nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n"); + wResult = FTL_Format_Flash(0); + } +#endif + + return wResult; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Flash_Error_Handle +* Inputs: Pointer to data +* Page address +* Block address +* Outputs: PASS=0 / FAIL=1 +* Description: It handles any error occured during Spectra operation +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, + u64 blk_addr) +{ + u32 i; + int j; + u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr); + u64 phy_addr; + int wErase = FAIL; + int wResult = FAIL; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (ERR == GLOB_FTL_Garbage_Collection()) + return ERR; + + do { + for (i = DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock; + i > 0; i--) { + if (IS_SPARE_BLOCK(i)) { + tmp_node = (u32)(BAD_BLOCK | + pbt[blk_node]); + pbt[blk_node] = (u32)(pbt[i] & + (~SPARE_BLOCK)); + pbt[i] = tmp_node; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + blk_node; + p_BTableChangesDelta->BT_Entry_Value = + pbt[blk_node]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = i; + p_BTableChangesDelta->BT_Entry_Value = pbt[i]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + wResult = PASS; + break; + } + } + + if (FAIL == wResult) { + if (FAIL == GLOB_FTL_Garbage_Collection()) + break; + else + continue; + } + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + + for (j = 0; j < RETRY_TIMES; j++) { + if (PASS == wErase) { + if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { + MARK_BLOCK_AS_BAD(pbt[blk_node]); + break; + } + } + if (PASS == FTL_Cache_Update_Block(pData, + old_page_addr, + phy_addr)) { + wResult = PASS; + break; + } else { + wResult = FAIL; + wErase = PASS; + } + } + } while (FAIL == wResult); + + FTL_Write_Block_Table(FAIL); + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Page_Num +* Inputs: Size in bytes +* Outputs: Size in pages +* Description: It calculates the pages required for the length passed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Get_Page_Num(u64 length) +{ + return (u32)((length >> DeviceInfo.nBitsInPageDataSize) + + (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0)); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Physical_Block_Addr +* Inputs: Block Address (byte format) +* Outputs: Physical address of the block. +* Description: It translates LBA to PBA by returning address stored +* at the LBA location in the block table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr) +{ + u32 *pbt; + u64 physical_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + pbt = (u32 *)g_pBlockTable; + physical_addr = (u64) DeviceInfo.wBlockDataSize * + (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK)); + + return physical_addr; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Block_Index +* Inputs: Physical Block no. +* Outputs: Logical block no. /BAD_BLOCK +* Description: It returns the logical block no. for the PBA passed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Get_Block_Index(u32 wBlockNum) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) + if (wBlockNum == (pbt[i] & (~BAD_BLOCK))) + return i; + + return BAD_BLOCK; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Wear_Leveling +* Inputs: none +* Outputs: PASS=0 +* Description: This is static wear leveling (done by explicit call) +* do complete static wear leveling +* do complete garbage collection +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Wear_Leveling(void) +{ + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FTL_Static_Wear_Leveling(); + GLOB_FTL_Garbage_Collection(); + + return PASS; +} + +static void find_least_most_worn(u8 *chg, + u32 *least_idx, u8 *least_cnt, + u32 *most_idx, u8 *most_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 idx; + u8 cnt; + int i; + + for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_BAD_BLOCK(i) || PASS == chg[i]) + continue; + + idx = (u32) ((~BAD_BLOCK) & pbt[i]); + cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock]; + + if (IS_SPARE_BLOCK(i)) { + if (cnt > *most_cnt) { + *most_cnt = cnt; + *most_idx = idx; + } + } + + if (IS_DATA_BLOCK(i)) { + if (cnt < *least_cnt) { + *least_cnt = cnt; + *least_idx = idx; + } + } + + if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) { + debug_boundary_error(*most_idx, + DeviceInfo.wDataBlockNum, 0); + debug_boundary_error(*least_idx, + DeviceInfo.wDataBlockNum, 0); + continue; + } + } +} + +static int move_blks_for_wear_leveling(u8 *chg, + u32 *least_idx, u32 *rep_blk_num, int *result) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 rep_blk; + int j, ret_cp_blk, ret_erase; + int ret = PASS; + + chg[*least_idx] = PASS; + debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0); + + rep_blk = FTL_Replace_MWBlock(); + if (rep_blk != BAD_BLOCK) { + nand_dbg_print(NAND_DBG_DEBUG, + "More than two spare blocks exist so do it\n"); + nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n", + rep_blk); + + chg[rep_blk] = PASS; + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + for (j = 0; j < RETRY_TIMES; j++) { + ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) * + DeviceInfo.wBlockDataSize, + (u64)rep_blk * DeviceInfo.wBlockDataSize); + if (FAIL == ret_cp_blk) { + ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk + * DeviceInfo.wBlockDataSize); + if (FAIL == ret_erase) + MARK_BLOCK_AS_BAD(pbt[rep_blk]); + } else { + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Copy_Block == OK\n"); + break; + } + } + + if (j < RETRY_TIMES) { + u32 tmp; + u32 old_idx = FTL_Get_Block_Index(*least_idx); + u32 rep_idx = FTL_Get_Block_Index(rep_blk); + tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]); + pbt[old_idx] = (u32)((~SPARE_BLOCK) & + pbt[rep_idx]); + pbt[rep_idx] = tmp; +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = old_idx; + p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = rep_idx; + p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } else { + pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK; +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + FTL_Get_Block_Index(rep_blk); + p_BTableChangesDelta->BT_Entry_Value = + pbt[FTL_Get_Block_Index(rep_blk)]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + *result = FAIL; + ret = FAIL; + } + + if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM) + ret = FAIL; + } else { + printk(KERN_ERR "Less than 3 spare blocks exist so quit\n"); + ret = FAIL; + } + + return ret; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Static_Wear_Leveling +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: This is static wear leveling (done by explicit call) +* search for most&least used +* if difference < GATE: +* update the block table with exhange +* mark block table in flash as IN_PROGRESS +* copy flash block +* the caller should handle GC clean up after calling this function +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Static_Wear_Leveling(void) +{ + u8 most_worn_cnt; + u8 least_worn_cnt; + u32 most_worn_idx; + u32 least_worn_idx; + int result = PASS; + int go_on = PASS; + u32 replaced_blks = 0; + u8 *chang_flag = flags_static_wear_leveling; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!chang_flag) + return FAIL; + + memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum); + while (go_on == PASS) { + nand_dbg_print(NAND_DBG_DEBUG, + "starting static wear leveling\n"); + most_worn_cnt = 0; + least_worn_cnt = 0xFF; + least_worn_idx = BLOCK_TABLE_INDEX; + most_worn_idx = BLOCK_TABLE_INDEX; + + find_least_most_worn(chang_flag, &least_worn_idx, + &least_worn_cnt, &most_worn_idx, &most_worn_cnt); + + nand_dbg_print(NAND_DBG_DEBUG, + "Used and least worn is block %u, whos count is %u\n", + (unsigned int)least_worn_idx, + (unsigned int)least_worn_cnt); + + nand_dbg_print(NAND_DBG_DEBUG, + "Free and most worn is block %u, whos count is %u\n", + (unsigned int)most_worn_idx, + (unsigned int)most_worn_cnt); + + if ((most_worn_cnt > least_worn_cnt) && + (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE)) + go_on = move_blks_for_wear_leveling(chang_flag, + &least_worn_idx, &replaced_blks, &result); + else + go_on = FAIL; + } + + return result; +} + +#if CMD_DMA +static int do_garbage_collection(u32 discard_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 pba; + u8 bt_block_erased = 0; + int i, cnt, ret = FAIL; + u64 addr; + + i = 0; + while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) && + ((ftl_cmd_cnt + 28) < 256)) { + if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[i] & DISCARD_BLOCK)) { + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + pba = BLK_FROM_ADDR(addr); + + for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { + if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase BT block %u\n", + (unsigned int)pba); + discard_cnt--; + i++; + bt_block_erased = 1; + break; + } + } + + if (bt_block_erased) { + bt_block_erased = 0; + continue; + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[i] &= (u32)(~DISCARD_BLOCK); + pbt[i] |= (u32)(SPARE_BLOCK); + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt - 1; + p_BTableChangesDelta->BT_Index = i; + p_BTableChangesDelta->BT_Entry_Value = pbt[i]; + p_BTableChangesDelta->ValidFields = 0x0C; + discard_cnt--; + ret = PASS; + } else { + MARK_BLOCK_AS_BAD(pbt[i]); + } + } + + i++; + } + + return ret; +} + +#else +static int do_garbage_collection(u32 discard_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 pba; + u8 bt_block_erased = 0; + int i, cnt, ret = FAIL; + u64 addr; + + i = 0; + while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) { + if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[i] & DISCARD_BLOCK)) { + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + pba = BLK_FROM_ADDR(addr); + + for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { + if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase BT block %d\n", + pba); + discard_cnt--; + i++; + bt_block_erased = 1; + break; + } + } + + if (bt_block_erased) { + bt_block_erased = 0; + continue; + } + + /* If the discard block is L2 cache block, then just skip it */ + for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) { + if (cache_l2.blk_array[cnt] == pba) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase L2 cache blk %d\n", + pba); + break; + } + } + if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */ + discard_cnt--; + i++; + continue; + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[i] &= (u32)(~DISCARD_BLOCK); + pbt[i] |= (u32)(SPARE_BLOCK); + discard_cnt--; + ret = PASS; + } else { + MARK_BLOCK_AS_BAD(pbt[i]); + } + } + + i++; + } + + return ret; +} +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Garbage_Collection +* Inputs: none +* Outputs: PASS / FAIL (returns the number of un-erased blocks +* Description: search the block table for all discarded blocks to erase +* for each discarded block: +* set the flash block to IN_PROGRESS +* erase the block +* update the block table +* write the block table to flash +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Garbage_Collection(void) +{ + u32 i; + u32 wDiscard = 0; + int wResult = FAIL; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (GC_Called) { + printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() " + "has been re-entered! Exit.\n"); + return PASS; + } + + GC_Called = 1; + + GLOB_FTL_BT_Garbage_Collection(); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_DISCARDED_BLOCK(i)) + wDiscard++; + } + + if (wDiscard <= 0) { + GC_Called = 0; + return wResult; + } + + nand_dbg_print(NAND_DBG_DEBUG, + "Found %d discarded blocks\n", wDiscard); + + FTL_Write_Block_Table(FAIL); + + wResult = do_garbage_collection(wDiscard); + + FTL_Write_Block_Table(FAIL); + + GC_Called = 0; + + return wResult; +} + + +#if CMD_DMA +static int do_bt_garbage_collection(void) +{ + u32 pba, lba; + u32 *pbt = (u32 *)g_pBlockTable; + u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; + u64 addr; + int i, ret = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (BT_GC_Called) + return PASS; + + BT_GC_Called = 1; + + for (i = last_erased; (i <= LAST_BT_ID) && + (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + + FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) && + ((ftl_cmd_cnt + 28)) < 256; i++) { + pba = pBTBlocksNode[i - FIRST_BT_ID]; + lba = FTL_Get_Block_Index(pba); + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection: pba %d, lba %d\n", + pba, lba); + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Entry: %d", pbt[lba]); + + if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[lba] & DISCARD_BLOCK)) { + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection_cdma: " + "Erasing Block tables present in block %d\n", + pba); + addr = FTL_Get_Physical_Block_Addr((u64)lba * + DeviceInfo.wBlockDataSize); + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[lba] &= (u32)(~DISCARD_BLOCK); + pbt[lba] |= (u32)(SPARE_BLOCK); + + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt - 1; + p_BTableChangesDelta->BT_Index = lba; + p_BTableChangesDelta->BT_Entry_Value = + pbt[lba]; + + p_BTableChangesDelta->ValidFields = 0x0C; + + ret = PASS; + pBTBlocksNode[last_erased - FIRST_BT_ID] = + BTBLOCK_INVAL; + nand_dbg_print(NAND_DBG_DEBUG, + "resetting bt entry at index %d " + "value %d\n", i, + pBTBlocksNode[i - FIRST_BT_ID]); + if (last_erased == LAST_BT_ID) + last_erased = FIRST_BT_ID; + else + last_erased++; + } else { + MARK_BLOCK_AS_BAD(pbt[lba]); + } + } + } + + BT_GC_Called = 0; + + return ret; +} + +#else +static int do_bt_garbage_collection(void) +{ + u32 pba, lba; + u32 *pbt = (u32 *)g_pBlockTable; + u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; + u64 addr; + int i, ret = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (BT_GC_Called) + return PASS; + + BT_GC_Called = 1; + + for (i = last_erased; (i <= LAST_BT_ID) && + (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + + FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) { + pba = pBTBlocksNode[i - FIRST_BT_ID]; + lba = FTL_Get_Block_Index(pba); + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection_cdma: pba %d, lba %d\n", + pba, lba); + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Entry: %d", pbt[lba]); + + if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[lba] & DISCARD_BLOCK)) { + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection: " + "Erasing Block tables present in block %d\n", + pba); + addr = FTL_Get_Physical_Block_Addr((u64)lba * + DeviceInfo.wBlockDataSize); + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[lba] &= (u32)(~DISCARD_BLOCK); + pbt[lba] |= (u32)(SPARE_BLOCK); + ret = PASS; + pBTBlocksNode[last_erased - FIRST_BT_ID] = + BTBLOCK_INVAL; + nand_dbg_print(NAND_DBG_DEBUG, + "resetting bt entry at index %d " + "value %d\n", i, + pBTBlocksNode[i - FIRST_BT_ID]); + if (last_erased == LAST_BT_ID) + last_erased = FIRST_BT_ID; + else + last_erased++; + } else { + MARK_BLOCK_AS_BAD(pbt[lba]); + } + } + } + + BT_GC_Called = 0; + + return ret; +} + +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_BT_Garbage_Collection +* Inputs: none +* Outputs: PASS / FAIL (returns the number of un-erased blocks +* Description: Erases discarded blocks containing Block table +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_BT_Garbage_Collection(void) +{ + return do_bt_garbage_collection(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_OneBlock +* Inputs: Block number 1 +* Block number 2 +* Outputs: Replaced Block Number +* Description: Interchange block table entries at wBlockNum and wReplaceNum +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk) +{ + u32 tmp_blk; + u32 replace_node = BAD_BLOCK; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (rep_blk != BAD_BLOCK) { + if (IS_BAD_BLOCK(blk)) + tmp_blk = pbt[blk]; + else + tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]); + + replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]); + pbt[blk] = replace_node; + pbt[rep_blk] = tmp_blk; + +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[blk]; + + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = rep_blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } + + return replace_node; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_Block_Table_Data +* Inputs: Block table size in pages +* Outputs: PASS=0 / FAIL=1 +* Description: Write block table data in flash +* If first page and last page +* Write data+BT flag +* else +* Write data +* BT flag is a counter. Its value is incremented for block table +* write in a new Block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Write_Block_Table_Data(void) +{ + u64 dwBlockTableAddr, pTempAddr; + u32 Block; + u16 Page, PageCount; + u8 *tempBuf = tmp_buf_write_blk_table_data; + int wBytesCopied; + u16 bt_pages; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dwBlockTableAddr = + (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize + + (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize); + pTempAddr = dwBlockTableAddr; + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: " + "page= %d BlockTableIndex= %d " + "BlockTableOffset=%d\n", bt_pages, + g_wBlockTableIndex, g_wBlockTableOffset); + + Block = BLK_FROM_ADDR(pTempAddr); + Page = PAGE_FROM_ADDR(pTempAddr, Block); + PageCount = 1; + + if (bt_block_changed) { + if (bt_flag == LAST_BT_ID) { + bt_flag = FIRST_BT_ID; + g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; + } else if (bt_flag < LAST_BT_ID) { + bt_flag++; + g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; + } + + if ((bt_flag > (LAST_BT_ID-4)) && + g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != + BTBLOCK_INVAL) { + bt_block_changed = 0; + GLOB_FTL_BT_Garbage_Collection(); + } + + bt_block_changed = 0; + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Counter is %u Block %u\n", + bt_flag, (unsigned int)Block); + } + + memset(tempBuf, 0, 3); + tempBuf[3] = bt_flag; + wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4, + DeviceInfo.wPageDataSize - 4, 0); + memset(&tempBuf[wBytesCopied + 4], 0xff, + DeviceInfo.wPageSize - (wBytesCopied + 4)); + FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize], + bt_flag); + +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + DeviceInfo.wPageSize * sizeof(u8)); + nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table " + "Block %u Page %u\n", (unsigned int)Block, Page); + if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable, + Block, Page, 1, + LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } + + ftl_cmd_cnt++; + g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8))); +#else + if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } +#endif + + if (bt_pages > 1) { + PageCount = bt_pages - 1; + if (PageCount > 1) { + wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf, + DeviceInfo.wPageDataSize * (PageCount - 1), + wBytesCopied); + +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + (PageCount - 1) * DeviceInfo.wPageDataSize); + if (FAIL == GLOB_LLD_Write_Page_Main_cdma( + g_pNextBlockTable, Block, Page + 1, + PageCount - 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)Block); + goto func_return; + } + + ftl_cmd_cnt++; + g_pNextBlockTable += (PageCount - 1) * + DeviceInfo.wPageDataSize * sizeof(u8); +#else + if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf, + Block, Page + 1, PageCount - 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)Block); + goto func_return; + } +#endif + } + + wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf, + DeviceInfo.wPageDataSize, wBytesCopied); + memset(&tempBuf[wBytesCopied], 0xff, + DeviceInfo.wPageSize-wBytesCopied); + FTL_Insert_Block_Table_Signature( + &tempBuf[DeviceInfo.wPageDataSize], bt_flag); +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + DeviceInfo.wPageSize * sizeof(u8)); + nand_dbg_print(NAND_DBG_DEBUG, + "Writing the last Page of Block Table " + "Block %u Page %u\n", + (unsigned int)Block, Page + bt_pages - 1); + if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma( + g_pNextBlockTable, Block, Page + bt_pages - 1, 1, + LLD_CMD_FLAG_MODE_CDMA | + LLD_CMD_FLAG_ORDER_BEFORE_REST)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } + ftl_cmd_cnt++; +#else + if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, + Block, Page+bt_pages - 1, 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } +#endif + } + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n"); + +func_return: + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_Block_Table +* Inputs: None +* Outputs: PASS=0 / FAIL=1 +* Description: Get a new block to write block table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_Block_Table(void) +{ + u32 blk; + int gc; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); + + if ((BAD_BLOCK == blk) && (PASS == gc)) { + GLOB_FTL_Garbage_Collection(); + blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); + } + if (BAD_BLOCK == blk) + printk(KERN_ERR "%s, %s: There is no spare block. " + "It should never happen\n", + __FILE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk); + + return blk; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_LWBlock +* Inputs: Block number +* Pointer to Garbage Collect flag +* Outputs: +* Description: Determine the least weared block by traversing +* block table +* Set Garbage collection to be called if number of spare +* block is less than Free Block Gate count +* Change Block table entry to map least worn block for current +* operation +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 wLeastWornCounter = 0xFF; + u32 wLeastWornIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + u32 wDiscardBlockNum = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (IS_SPARE_BLOCK(wBlockNum)) { + *pGarbageCollect = FAIL; + pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK)); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = (u32)(wBlockNum); + p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + return pbt[wBlockNum]; + } + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_DISCARDED_BLOCK(i)) + wDiscardBlockNum++; + + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]); + if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock) + printk(KERN_ERR "FTL_Replace_LWBlock: " + "This should never occur!\n"); + if (g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] < + wLeastWornCounter) { + wLeastWornCounter = + g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wLeastWornIndex = i; + } + wSpareBlockNum++; + } + } + + nand_dbg_print(NAND_DBG_WARN, + "FTL_Replace_LWBlock: Least Worn Counter %d\n", + (int)wLeastWornCounter); + + if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) || + (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE)) + *pGarbageCollect = PASS; + else + *pGarbageCollect = FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Replace_LWBlock: Discarded Blocks %u Spare" + " Blocks %u\n", + (unsigned int)wDiscardBlockNum, + (unsigned int)wSpareBlockNum); + + return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_MWBlock +* Inputs: None +* Outputs: most worn spare block no./BAD_BLOCK +* Description: It finds most worn spare block. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_MWBlock(void) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 wMostWornCounter = 0; + u32 wMostWornIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]); + if (g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] > + wMostWornCounter) { + wMostWornCounter = + g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wMostWornIndex = wPhysicalIndex; + } + wSpareBlockNum++; + } + } + + if (wSpareBlockNum <= 2) + return BAD_BLOCK; + + return wMostWornIndex; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_Block +* Inputs: Block Address +* Outputs: PASS=0 / FAIL=1 +* Description: If block specified by blk_addr parameter is not free, +* replace it with the least worn block. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Replace_Block(u64 blk_addr) +{ + u32 current_blk = BLK_FROM_ADDR(blk_addr); + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + int GarbageCollect = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (IS_SPARE_BLOCK(current_blk)) { + pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk]; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = current_blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk]; + p_BTableChangesDelta->ValidFields = 0x0C ; +#endif + return wResult; + } + + FTL_Replace_LWBlock(current_blk, &GarbageCollect); + + if (PASS == GarbageCollect) + wResult = GLOB_FTL_Garbage_Collection(); + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Is_BadBlock +* Inputs: block number to test +* Outputs: PASS (block is BAD) / FAIL (block is not bad) +* Description: test if this block number is flagged as bad +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Is_BadBlock(u32 wBlockNum) +{ + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (wBlockNum >= DeviceInfo.wSpectraStartBlock + && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK)) + return PASS; + else + return FAIL; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Flush_Cache +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: flush all the cache blocks to flash +* if a cache block is not dirty, don't do anything with it +* else, write the block and update the block table +* Note: This function should be called at shutdown/power down. +* to write important data into device +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flush_Cache(void) +{ + int i, ret; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (SET == Cache.array[i].changed) { +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = i; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[i].address; + int_cache[ftl_cmd_cnt].cache.changed = CLEAR; +#endif +#endif + ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address); + if (PASS == ret) { + Cache.array[i].changed = CLEAR; + } else { + printk(KERN_ALERT "Failed when write back to L2 cache!\n"); + /* TODO - How to handle this? */ + } + } + } + + flush_l2_cache(); + + return FTL_Write_Block_Table(FAIL); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Page_Read +* Inputs: pointer to data +* logical address of data (u64 is LBA * Bytes/Page) +* Outputs: PASS=0 / FAIL=1 +* Description: reads a page of data into RAM from the cache +* if the data is not already in cache, read from flash to cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr) +{ + u16 cache_item; + int res = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - " + "page_addr: %llu\n", logical_addr); + + cache_item = FTL_Cache_If_Hit(logical_addr); + + if (UNHIT_CACHE_ITEM == cache_item) { + nand_dbg_print(NAND_DBG_DEBUG, + "GLOB_FTL_Page_Read: Cache not hit\n"); + res = FTL_Cache_Write(); + if (ERR == FTL_Cache_Read(logical_addr)) + res = ERR; + cache_item = Cache.LRU; + } + + FTL_Cache_Read_Page(data, logical_addr, cache_item); + + return res; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Page_Write +* Inputs: pointer to data +* address of data (ADDRESSTYPE is LBA * Bytes/Page) +* Outputs: PASS=0 / FAIL=1 +* Description: writes a page of data from RAM to the cache +* if the data is not already in cache, write back the +* least recently used block and read the addressed block +* from flash to cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr) +{ + u16 cache_blk; + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - " + "dwPageAddr: %llu\n", dwPageAddr); + + cache_blk = FTL_Cache_If_Hit(dwPageAddr); + + if (UNHIT_CACHE_ITEM == cache_blk) { + wResult = FTL_Cache_Write(); + if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) { + wResult = FTL_Replace_Block(dwPageAddr); + pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK; + if (wResult == FAIL) + return FAIL; + } + if (ERR == FTL_Cache_Read(dwPageAddr)) + wResult = ERR; + cache_blk = Cache.LRU; + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); + } else { +#if CMD_DMA + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, + LLD_CMD_FLAG_ORDER_BEFORE_REST); +#else + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); +#endif + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Block_Erase +* Inputs: address of block to erase (now in byte format, should change to +* block format) +* Outputs: PASS=0 / FAIL=1 +* Description: erases the specified block +* increments the erase count +* If erase count reaches its upper limit,call function to +* do the ajustment as per the relative erase count values +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Block_Erase(u64 blk_addr) +{ + int status; + u32 BlkIdx; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize); + + if (BlkIdx < DeviceInfo.wSpectraStartBlock) { + printk(KERN_ERR "GLOB_FTL_Block_Erase: " + "This should never occur\n"); + return FAIL; + } + +#if CMD_DMA + status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA); + if (status == FAIL) + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, BlkIdx); +#else + status = GLOB_LLD_Erase_Block(BlkIdx); + if (status == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, BlkIdx); + return status; + } +#endif + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0; + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } + + g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++; + +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = + BlkIdx - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; + + if (DeviceInfo.MLCDevice) { + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->RC_Index = + BlkIdx - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->RC_Entry_Value = + g_pReadCounter[BlkIdx - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0xC0; + } + + ftl_cmd_cnt++; +#endif + + if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE) + FTL_Adjust_Relative_Erase_Count(BlkIdx); + + return status; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Adjust_Relative_Erase_Count +* Inputs: index to block that was just incremented and is at the max +* Outputs: PASS=0 / FAIL=1 +* Description: If any erase counts at MAX, adjusts erase count of every +* block by substracting least worn +* counter from counter value of every entry in wear table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX) +{ + u8 wLeastWornCounter = MAX_BYTE_VALUE; + u8 wWearCounter; + u32 i, wWearIndex; + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_BAD_BLOCK(i)) + continue; + wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); + + if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0) + printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:" + "This should never occur\n"); + wWearCounter = g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock]; + if (wWearCounter < wLeastWornCounter) + wLeastWornCounter = wWearCounter; + } + + if (wLeastWornCounter == 0) { + nand_dbg_print(NAND_DBG_WARN, + "Adjusting Wear Levelling Counters: Special Case\n"); + g_pWearCounter[Index_of_MAX - + DeviceInfo.wSpectraStartBlock]--; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = + Index_of_MAX - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[Index_of_MAX - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; +#endif + FTL_Static_Wear_Leveling(); + } else { + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) + if (!IS_BAD_BLOCK(i)) { + wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); + g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock] = + (u8)(g_pWearCounter + [wWearIndex - + DeviceInfo.wSpectraStartBlock] - + wLeastWornCounter); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = wWearIndex - + DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; +#endif + } + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_IN_Progress_Block_Table_Page +* Inputs: None +* Outputs: None +* Description: It writes in-progress flag page to the page next to +* block table +***********************************************************************/ +static int FTL_Write_IN_Progress_Block_Table_Page(void) +{ + int wResult = PASS; + u16 bt_pages; + u16 dwIPFPageAddr; +#if CMD_DMA +#else + u32 *pbt = (u32 *)g_pBlockTable; + u32 wTempBlockTableIndex; +#endif + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + dwIPFPageAddr = g_wBlockTableOffset + bt_pages; + + nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at " + "Block %d Page %d\n", + g_wBlockTableIndex, dwIPFPageAddr); + +#if CMD_DMA + wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF, + g_wBlockTableIndex, dwIPFPageAddr, 1, + LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + g_wBlockTableIndex); + } + g_wBlockTableOffset = dwIPFPageAddr + 1; + p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset; + p_BTableChangesDelta->ValidFields = 0x01; + ftl_cmd_cnt++; +#else + wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF, + g_wBlockTableIndex, dwIPFPageAddr, 1); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)g_wBlockTableIndex); + MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); + wTempBlockTableIndex = FTL_Replace_Block_Table(); + bt_block_changed = 1; + if (BAD_BLOCK == wTempBlockTableIndex) + return ERR; + g_wBlockTableIndex = wTempBlockTableIndex; + g_wBlockTableOffset = 0; + /* Block table tag is '00'. Means it's used one */ + pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; + return FAIL; + } + g_wBlockTableOffset = dwIPFPageAddr + 1; +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Read_Disturbance +* Inputs: block address +* Outputs: PASS=0 / FAIL=1 +* Description: used to handle read disturbance. Data in block that +* reaches its read limit is moved to new block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Read_Disturbance(u32 blk_addr) +{ + int wResult = FAIL; + u32 *pbt = (u32 *) g_pBlockTable; + u32 dwOldBlockAddr = blk_addr; + u32 wBlockNum; + u32 i; + u32 wLeastReadCounter = 0xFFFF; + u32 wLeastReadIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + u32 wTempNode; + u32 wReplacedNode; + u8 *g_pTempBuf; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#if CMD_DMA + g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx]; + cp_back_buf_idx++; + if (cp_back_buf_idx > COPY_BACK_BUF_NUM) { + printk(KERN_ERR "cp_back_buf_copies overflow! Exit." + "Maybe too many pending commands in your CDMA chain.\n"); + return FAIL; + } +#else + g_pTempBuf = tmp_buf_read_disturbance; +#endif + + wBlockNum = FTL_Get_Block_Index(blk_addr); + + do { + /* This is a bug.Here 'i' should be logical block number + * and start from 1 (0 is reserved for block table). + * Have fixed it. - Yunpeng 2008. 12. 19 + */ + for (i = 1; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = + (u32)((~SPARE_BLOCK) & pbt[i]); + if (g_pReadCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] < + wLeastReadCounter) { + wLeastReadCounter = + g_pReadCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wLeastReadIndex = i; + } + wSpareBlockNum++; + } + } + + if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) { + wResult = GLOB_FTL_Garbage_Collection(); + if (PASS == wResult) + continue; + else + break; + } else { + wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]); + wReplacedNode = (u32)((~SPARE_BLOCK) & + pbt[wLeastReadIndex]); +#if CMD_DMA + pbt[wBlockNum] = wReplacedNode; + pbt[wLeastReadIndex] = wTempNode; + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = wBlockNum; + p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = wLeastReadIndex; + p_BTableChangesDelta->BT_Entry_Value = + pbt[wLeastReadIndex]; + p_BTableChangesDelta->ValidFields = 0x0C; + + wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf, + dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock, + LLD_CMD_FLAG_MODE_CDMA); + if (wResult == FAIL) + return wResult; + + ftl_cmd_cnt++; + + if (wResult != FAIL) { + if (FAIL == GLOB_LLD_Write_Page_Main_cdma( + g_pTempBuf, pbt[wBlockNum], 0, + DeviceInfo.wPagesPerBlock)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)pbt[wBlockNum]); + wResult = FAIL; + MARK_BLOCK_AS_BAD(pbt[wBlockNum]); + } + ftl_cmd_cnt++; + } +#else + wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf, + dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock); + if (wResult == FAIL) + return wResult; + + if (wResult != FAIL) { + /* This is a bug. At this time, pbt[wBlockNum] + is still the physical address of + discard block, and should not be write. + Have fixed it as below. + -- Yunpeng 2008.12.19 + */ + wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf, + wReplacedNode, 0, + DeviceInfo.wPagesPerBlock); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)wReplacedNode); + MARK_BLOCK_AS_BAD(wReplacedNode); + } else { + pbt[wBlockNum] = wReplacedNode; + pbt[wLeastReadIndex] = wTempNode; + } + } + + if ((wResult == PASS) && (g_cBlockTableStatus != + IN_PROGRESS_BLOCK_TABLE)) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } +#endif + } + } while (wResult != PASS) + ; + +#if CMD_DMA + /* ... */ +#endif + + return wResult; +} + diff --git a/drivers/block/spectra/flash.h b/drivers/block/spectra/flash.h new file mode 100644 index 000000000000..5ed05805cf65 --- /dev/null +++ b/drivers/block/spectra/flash.h @@ -0,0 +1,198 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FLASH_INTERFACE_ +#define _FLASH_INTERFACE_ + +#include "ffsport.h" +#include "spectraswconfig.h" + +#define MAX_BYTE_VALUE 0xFF +#define MAX_WORD_VALUE 0xFFFF +#define MAX_U32_VALUE 0xFFFFFFFF + +#define MAX_BLOCKNODE_VALUE 0xFFFFFF +#define DISCARD_BLOCK 0x800000 +#define SPARE_BLOCK 0x400000 +#define BAD_BLOCK 0xC00000 + +#define UNHIT_CACHE_ITEM 0xFFFF + +#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL + +#define IN_PROGRESS_BLOCK_TABLE 0x00 +#define CURRENT_BLOCK_TABLE 0x01 + +#define BTSIG_OFFSET (0) +#define BTSIG_BYTES (5) +#define BTSIG_DELTA (3) + +#define MAX_READ_COUNTER 0x2710 + +#define FIRST_BT_ID (1) +#define LAST_BT_ID (254) +#define BTBLOCK_INVAL (u32)(0xFFFFFFFF) + +struct device_info_tag { + u16 wDeviceMaker; + u16 wDeviceID; + u32 wDeviceType; + u32 wSpectraStartBlock; + u32 wSpectraEndBlock; + u32 wTotalBlocks; + u16 wPagesPerBlock; + u16 wPageSize; + u16 wPageDataSize; + u16 wPageSpareSize; + u16 wNumPageSpareFlag; + u16 wECCBytesPerSector; + u32 wBlockSize; + u32 wBlockDataSize; + u32 wDataBlockNum; + u8 bPlaneNum; + u16 wDeviceMainAreaSize; + u16 wDeviceSpareAreaSize; + u16 wDevicesConnected; + u16 wDeviceWidth; + u16 wHWRevision; + u16 wHWFeatures; + + u16 wONFIDevFeatures; + u16 wONFIOptCommands; + u16 wONFITimingMode; + u16 wONFIPgmCacheTimingMode; + + u16 MLCDevice; + u16 wSpareSkipBytes; + + u8 nBitsInPageNumber; + u8 nBitsInPageDataSize; + u8 nBitsInBlockDataSize; +}; + +extern struct device_info_tag DeviceInfo; + +/* Cache item format */ +struct flash_cache_item_tag { + u64 address; + u16 use_cnt; + u16 changed; + u8 *buf; +}; + +struct flash_cache_tag { + u32 cache_item_size; /* Size in bytes of each cache item */ + u16 pages_per_item; /* How many NAND pages in each cache item */ + u16 LRU; /* No. of the least recently used cache item */ + struct flash_cache_item_tag array[CACHE_ITEM_NUM]; +}; + +/* + *Data structure for each list node of the managment table + * used for the Level 2 Cache. Each node maps one logical NAND block. + */ +struct spectra_l2_cache_list { + struct list_head list; + u32 logical_blk_num; /* Logical block number */ + u32 pages_array[]; /* Page map array of this logical block. + * Array index is the logical block number, + * and for every item of this arry: + * high 16 bit is index of the L2 cache block num, + * low 16 bit is the phy page num + * of the above L2 cache block. + * This array will be kmalloc during run time. + */ +}; + +struct spectra_l2_cache_info { + u32 blk_array[BLK_NUM_FOR_L2_CACHE]; + u16 cur_blk_idx; /* idx to the phy block number of current using */ + u16 cur_page_num; /* pages number of current using */ + struct spectra_l2_cache_list table; /* First node of the table */ +}; + +#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1 + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE +struct flash_cache_mod_item_tag { + u64 address; + u8 changed; +}; + +struct flash_cache_delta_list_tag { + u8 item; /* used cache item */ + struct flash_cache_mod_item_tag cache; +}; +#endif + +extern struct flash_cache_tag Cache; + +extern u8 *buf_read_page_main_spare; +extern u8 *buf_write_page_main_spare; +extern u8 *buf_read_page_spare; +extern u8 *buf_get_bad_block; +extern u8 *cdma_desc_buf; +extern u8 *memcp_desc_buf; + +/* struture used for IndentfyDevice function */ +struct spectra_indentfy_dev_tag { + u32 NumBlocks; + u16 PagesPerBlock; + u16 PageDataSize; + u16 wECCBytesPerSector; + u32 wDataBlockNum; +}; + +int GLOB_FTL_Flash_Init(void); +int GLOB_FTL_Flash_Release(void); +/*void GLOB_FTL_Erase_Flash(void);*/ +int GLOB_FTL_Block_Erase(u64 block_addr); +int GLOB_FTL_Is_BadBlock(u32 block_num); +int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data); +int GLOB_FTL_Event_Status(int *); +u16 glob_ftl_execute_cmds(void); + +/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/ +int FTL_Read_Disturbance(u32 dwBlockAddr); + +/*Flash r/w based on cache*/ +int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr); +int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr); +int GLOB_FTL_Wear_Leveling(void); +int GLOB_FTL_Flash_Format(void); +int GLOB_FTL_Init(void); +int GLOB_FTL_Flush_Cache(void); +int GLOB_FTL_Garbage_Collection(void); +int GLOB_FTL_BT_Garbage_Collection(void); +void GLOB_FTL_Cache_Release(void); +u8 *get_blk_table_start_addr(void); +u8 *get_wear_leveling_table_start_addr(void); +unsigned long get_blk_table_len(void); +unsigned long get_wear_leveling_table_len(void); + +#if DEBUG_BNDRY +void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno, + char *filename); +#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\ + limit, no, __LINE__, __FILE__) +#else +#define debug_boundary_error(chnl, limit, no) ; +#endif + +#endif /*_FLASH_INTERFACE_*/ diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c new file mode 100644 index 000000000000..3f411af4405e --- /dev/null +++ b/drivers/block/spectra/lld.c @@ -0,0 +1,258 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "spectraswconfig.h" +#include "ffsport.h" +#include "ffsdefs.h" +#include "lld.h" +#include "lld_nand.h" + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */ +#include "lld_emu.h" +#include "lld_cdma.h" + +/* common functions: */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return emu_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return emu_Read_Device_ID(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return emu_Flash_Release(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return emu_Flash_Init(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return emu_Erase_Block(block_add); +} + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Read_Page_Main(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return emu_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 Page, u16 PageCount) +{ + return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return emu_Get_Bad_Block(block); +} + +#endif /* FLASH_EMU */ + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */ +#include "lld_nand.h" +#include "lld_cdma.h" +#include "flash.h" + +/* common functions for LLD_NAND */ +void GLOB_LLD_ECC_Control(int enable) +{ + NAND_ECC_Ctrl(enable); +} + +/* common functions for LLD_NAND */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return NAND_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return NAND_Read_Device_ID(); +} + +u16 GLOB_LLD_UnlockArrayAll(void) +{ + return NAND_UnlockArrayAll(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return NAND_Flash_Init(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return nand_release(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return NAND_Erase_Block(block_add); +} + + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + if (page_count == 1) /* Using polling to improve read speed */ + return NAND_Read_Page_Main_Polling(read_data, block, page, 1); + else + return NAND_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return NAND_Read_Page_Main_Polling(read_data, + block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 page, u16 page_count) +{ + return NAND_Read_Page_Main_Spare(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return NAND_Get_Bad_Block(block); +} + +u16 GLOB_LLD_Event_Status(void) +{ + return CDMA_Event_Status(); +} + +u16 glob_lld_execute_cmds(void) +{ + return CDMA_Execute_CMDs(); +} + +u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, + u32 ByteCount, u16 flag) +{ + /* Replace the hardware memcopy with software memcpy function */ + if (CDMA_Execute_CMDs()) + return FAIL; + memcpy(dest, src, ByteCount); + return PASS; + + /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */ +} + +u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags) +{ + return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags); +} + +u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count) +{ + return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0); +} + +u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page, + u16 count, u16 flags) +{ + return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags); +} + +u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page, + u16 count, u16 flags) +{ + return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD, + data, block, page, count, flags); +} + +u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count) +{ + return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count, + LLD_CMD_FLAG_MODE_CDMA); +} + +#endif /* FLASH_NAND */ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +/* end of LLD.c */ diff --git a/drivers/block/spectra/lld.h b/drivers/block/spectra/lld.h new file mode 100644 index 000000000000..d3738e0e1fea --- /dev/null +++ b/drivers/block/spectra/lld.h @@ -0,0 +1,111 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + + +#ifndef _LLD_ +#define _LLD_ + +#include "ffsport.h" +#include "spectraswconfig.h" +#include "flash.h" + +#define GOOD_BLOCK 0 +#define DEFECTIVE_BLOCK 1 +#define READ_ERROR 2 + +#define CLK_X 5 +#define CLK_MULTI 4 + +/* Typedefs */ + +/* prototypes: API for LLD */ +/* Currently, Write_Page_Main + * MemCopy + * Read_Page_Main_Spare + * do not have flag because they were not implemented prior to this + * They are not being added to keep changes to a minimum for now. + * Currently, they are not required (only reqd for Wr_P_M_S.) + * Later on, these NEED to be changed. + */ + +extern void GLOB_LLD_ECC_Control(int enable); + +extern u16 GLOB_LLD_Flash_Reset(void); + +extern u16 GLOB_LLD_Read_Device_ID(void); + +extern u16 GLOB_LLD_UnlockArrayAll(void); + +extern u16 GLOB_LLD_Flash_Init(void); + +extern int GLOB_LLD_Flash_Release(void); + +extern u16 GLOB_LLD_Erase_Block(u32 block_add); + +extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Get_Bad_Block(u32 block); + +extern u16 GLOB_LLD_Event_Status(void); + +extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag); + +extern u16 glob_lld_execute_cmds(void); + +extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags); + +extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, + u32 block, u16 page, u16 count); + +extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, + u32 block, u16 page, u16 count, u16 flags); + +extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count, u16 flags); + +extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count); + +#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1) +#define LLD_CMD_FLAG_MODE_CDMA (0x8) + + +#endif /*_LLD_ */ + + diff --git a/drivers/block/spectra/lld_cdma.c b/drivers/block/spectra/lld_cdma.c new file mode 100644 index 000000000000..c6e76103d43c --- /dev/null +++ b/drivers/block/spectra/lld_cdma.c @@ -0,0 +1,910 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include "spectraswconfig.h" +#include "lld.h" +#include "lld_nand.h" +#include "lld_cdma.h" +#include "lld_emu.h" +#include "flash.h" +#include "nand_regs.h" + +#define MAX_PENDING_CMDS 4 +#define MODE_02 (0x2 << 26) + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Data_Cmd +* Inputs: cmd code (aligned for hw) +* data: pointer to source or destination +* block: block address +* page: page address +* num: num pages to transfer +* Outputs: PASS +* Description: This function takes the parameters and puts them +* into the "pending commands" array. +* It does not parse or validate the parameters. +* The array index is same as the tag. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags) +{ + u8 bank; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (0 == cmd) + nand_dbg_print(NAND_DBG_DEBUG, + "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__); + + /* If a command of another bank comes, then first execute */ + /* pending commands of the current bank, then set the new */ + /* bank as current bank */ + bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + if (bank != info.flash_bank) { + nand_dbg_print(NAND_DBG_WARN, + "Will access new bank. old bank: %d, new bank: %d\n", + info.flash_bank, bank); + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + info.flash_bank = bank; + } + + info.pcmds[info.pcmds_num].CMD = cmd; + info.pcmds[info.pcmds_num].DataAddr = data; + info.pcmds[info.pcmds_num].Block = block; + info.pcmds[info.pcmds_num].Page = page; + info.pcmds[info.pcmds_num].PageCount = num; + info.pcmds[info.pcmds_num].DataDestAddr = 0; + info.pcmds[info.pcmds_num].DataSrcAddr = 0; + info.pcmds[info.pcmds_num].MemCopyByteCnt = 0; + info.pcmds[info.pcmds_num].Flags = flags; + info.pcmds[info.pcmds_num].Status = 0xB0B; + + switch (cmd) { + case WRITE_MAIN_SPARE_CMD: + Conv_Main_Spare_Data_Log2Phy_Format(data, num); + break; + case WRITE_SPARE_CMD: + Conv_Spare_Data_Log2Phy_Format(data); + break; + default: + break; + } + + info.pcmds_num++; + + if (info.pcmds_num >= MAX_PENDING_CMDS) { + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_MemCopy_CMD +* Inputs: dest: pointer to destination +* src: pointer to source +* count: num bytes to transfer +* Outputs: PASS +* Description: This function takes the parameters and puts them +* into the "pending commands" array. +* It does not parse or validate the parameters. +* The array index is same as the tag. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags) +{ + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD; + info.pcmds[info.pcmds_num].DataAddr = 0; + info.pcmds[info.pcmds_num].Block = 0; + info.pcmds[info.pcmds_num].Page = 0; + info.pcmds[info.pcmds_num].PageCount = 0; + info.pcmds[info.pcmds_num].DataDestAddr = dest; + info.pcmds[info.pcmds_num].DataSrcAddr = src; + info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt; + info.pcmds[info.pcmds_num].Flags = flags; + info.pcmds[info.pcmds_num].Status = 0xB0B; + + info.pcmds_num++; + + if (info.pcmds_num >= MAX_PENDING_CMDS) { + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + } + + return PASS; +} + +#if 0 +/* Prints the PendingCMDs array */ +void print_pending_cmds(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < info.pcmds_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + switch (info.pcmds[i].CMD) { + case ERASE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Erase Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case WRITE_MAIN_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Write Main Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case WRITE_MAIN_SPARE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Write Main Spare Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case READ_MAIN_SPARE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Read Main Spare Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case READ_MAIN_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Read Main Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case MEMCOPY_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Memcopy Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case DUMMY_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Dummy Command (0x%x)\n", + info.pcmds[i].CMD); + break; + default: + nand_dbg_print(NAND_DBG_DEBUG, + "Illegal Command (0x%x)\n", + info.pcmds[i].CMD); + break; + } + + nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n", + (u32)info.pcmds[i].DataAddr); + nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n", + info.pcmds[i].Block); + nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n", + info.pcmds[i].Page); + nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n", + info.pcmds[i].PageCount); + nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n", + (u32)info.pcmds[i].DataDestAddr); + nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n", + (u32)info.pcmds[i].DataSrcAddr); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n", + info.pcmds[i].MemCopyByteCnt); + nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n", + info.pcmds[i].Flags); + nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n", + info.pcmds[i].Status); + } +} + +/* Print the CDMA descriptors */ +void print_cdma_descriptors(void) +{ + struct cdma_descriptor *pc; + int i; + + pc = (struct cdma_descriptor *)info.cdma_desc_buf; + + nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n"); + + for (i = 0; i < info.cdma_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + nand_dbg_print(NAND_DBG_DEBUG, + "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", + pc[i].NxtPointerHi, pc[i].NxtPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n", + pc[i].FlashPointerHi, pc[i].FlashPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n", + pc[i].CommandType); + nand_dbg_print(NAND_DBG_DEBUG, + "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n", + pc[i].MemAddrHi, pc[i].MemAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n", + pc[i].CommandFlags); + nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n", + pc[i].Channel, pc[i].Status); + nand_dbg_print(NAND_DBG_DEBUG, + "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n", + pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "Reserved12: 0x%x, Reserved13: 0x%x, " + "Reserved14: 0x%x, pcmd: %d\n", + pc[i].Reserved12, pc[i].Reserved13, + pc[i].Reserved14, pc[i].pcmd); + } +} + +/* Print the Memory copy descriptors */ +static void print_memcp_descriptors(void) +{ + struct memcpy_descriptor *pm; + int i; + + pm = (struct memcpy_descriptor *)info.memcp_desc_buf; + + nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n"); + + for (i = 0; i < info.cdma_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + nand_dbg_print(NAND_DBG_DEBUG, + "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", + pm[i].NxtPointerHi, pm[i].NxtPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n", + pm[i].SrcAddrHi, pm[i].SrcAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, + "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n", + pm[i].DestAddrHi, pm[i].DestAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n", + pm[i].XferSize); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n", + pm[i].MemCopyFlags); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n", + pm[i].MemCopyStatus); + nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n", + pm[i].reserved9); + nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n", + pm[i].reserved10); + nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n", + pm[i].reserved11); + nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n", + pm[i].reserved12); + nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n", + pm[i].reserved13); + nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n", + pm[i].reserved14); + nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n", + pm[i].reserved15); + } +} +#endif + +/* Reset cdma_descriptor chain to 0 */ +static void reset_cdma_desc(int i) +{ + struct cdma_descriptor *ptr; + + BUG_ON(i >= MAX_DESCS); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + ptr[i].NxtPointerHi = 0; + ptr[i].NxtPointerLo = 0; + ptr[i].FlashPointerHi = 0; + ptr[i].FlashPointerLo = 0; + ptr[i].CommandType = 0; + ptr[i].MemAddrHi = 0; + ptr[i].MemAddrLo = 0; + ptr[i].CommandFlags = 0; + ptr[i].Channel = 0; + ptr[i].Status = 0; + ptr[i].MemCopyPointerHi = 0; + ptr[i].MemCopyPointerLo = 0; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_UpdateEventStatus +* Inputs: none +* Outputs: none +* Description: This function update the event status of all the channels +* when an error condition is reported. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void CDMA_UpdateEventStatus(void) +{ + int i, j, active_chan; + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (j = 0; j < info.cdma_num; j++) { + /* Check for the descriptor with failure */ + if ((ptr[j].Status & CMD_DMA_DESC_FAIL)) + break; + + } + + /* All the previous cmd's status for this channel must be good */ + for (i = 0; i < j; i++) { + if (ptr[i].pcmd != 0xff) + info.pcmds[ptr[i].pcmd].Status = CMD_PASS; + } + + /* Abort the channel with type 0 reset command. It resets the */ + /* selected channel after the descriptor completes the flash */ + /* operation and status has been updated for the descriptor. */ + /* Memory Copy and Sync associated with this descriptor will */ + /* not be executed */ + active_chan = ioread32(FlashReg + CHNL_ACTIVE); + if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) { + iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */ + iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10); + } else { /* Should not reached here */ + printk(KERN_ERR "Error! Used bank is not set in" + " reg CHNL_ACTIVE\n"); + } +} + +static void cdma_trans(u16 chan) +{ + u32 addr; + + addr = info.cdma_desc; + + iowrite32(MODE_10 | (chan << 24), FlashMem); + iowrite32((1 << 7) | chan, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8), + FlashMem); + iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem); + iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24), FlashMem); + iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs (for use with CMD_DMA) +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor +* for each pending command, start the CDMA engine, and return. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Execute_CMDs(void) +{ + int i, ret; + u64 flash_add; + u32 ptr; + dma_addr_t map_addr, next_ptr; + u16 status = PASS; + u16 tmp_c; + struct cdma_descriptor *pc; + struct memcpy_descriptor *pm; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* No pending cmds to execute, just exit */ + if (0 == info.pcmds_num) { + nand_dbg_print(NAND_DBG_TRACE, + "No pending cmds to execute. Just exit.\n"); + return PASS; + } + + for (i = 0; i < MAX_DESCS; i++) + reset_cdma_desc(i); + + pc = (struct cdma_descriptor *)info.cdma_desc_buf; + pm = (struct memcpy_descriptor *)info.memcp_desc_buf; + + info.cdma_desc = virt_to_bus(info.cdma_desc_buf); + info.memcp_desc = virt_to_bus(info.memcp_desc_buf); + next_ptr = info.cdma_desc; + info.cdma_num = 0; + + for (i = 0; i < info.pcmds_num; i++) { + if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) { + info.pcmds[i].Status = CMD_NOT_DONE; + continue; + } + + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + + /* Use the Block offset within a bank */ + tmp_c = info.pcmds[i].Block / + (DeviceInfo.wTotalBlocks / totalUsedBanks); + flash_add = (u64)(info.pcmds[i].Block - tmp_c * + (DeviceInfo.wTotalBlocks / totalUsedBanks)) * + DeviceInfo.wBlockDataSize + + (u64)(info.pcmds[i].Page) * + DeviceInfo.wPageDataSize; + + ptr = MODE_10 | (info.flash_bank << 24) | + (u32)GLOB_u64_Div(flash_add, + DeviceInfo.wPageDataSize); + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + + if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || + (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { + /* Descriptor to set Main+Spare Access Mode */ + pc[info.cdma_num].CommandType = 0x43; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + reset_cdma_desc(info.cdma_num); + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + } + + switch (info.pcmds[i].CMD) { + case ERASE_CMD: + pc[info.cdma_num].CommandType = 1; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + break; + + case WRITE_MAIN_CMD: + pc[info.cdma_num].CommandType = + 0x2100 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case READ_MAIN_CMD: + pc[info.cdma_num].CommandType = + 0x2000 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case WRITE_MAIN_SPARE_CMD: + pc[info.cdma_num].CommandType = + 0x2100 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case READ_MAIN_SPARE_CMD: + pc[info.cdma_num].CommandType = + 0x2000 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case MEMCOPY_CMD: + pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */ + /* Set bit 11 to let the CDMA engine continue to */ + /* execute only after it has finished processing */ + /* the memcopy descriptor. */ + /* Also set bit 10 and bit 9 to 1 */ + pc[info.cdma_num].CommandFlags = 0x0E40; + map_addr = info.memcp_desc + info.cdma_num * + sizeof(struct memcpy_descriptor); + pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16; + pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff; + + pm[info.cdma_num].NxtPointerHi = 0; + pm[info.cdma_num].NxtPointerLo = 0; + + map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr); + pm[info.cdma_num].SrcAddrHi = map_addr >> 16; + pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff; + map_addr = virt_to_bus(info.pcmds[i].DataDestAddr); + pm[info.cdma_num].DestAddrHi = map_addr >> 16; + pm[info.cdma_num].DestAddrLo = map_addr & 0xffff; + + pm[info.cdma_num].XferSize = + info.pcmds[i].MemCopyByteCnt; + pm[info.cdma_num].MemCopyFlags = + (0 << 15 | 0 << 14 | 27 << 8 | 0x40); + pm[info.cdma_num].MemCopyStatus = 0; + break; + + case DUMMY_CMD: + default: + pc[info.cdma_num].CommandType = 0XFFFF; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + break; + } + + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || + (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { + /* Descriptor to set back Main Area Access Mode */ + reset_cdma_desc(info.cdma_num); + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + + pc[info.cdma_num].CommandType = 0x42; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + } + } + + /* Add a dummy descriptor at end of the CDMA chain */ + reset_cdma_desc(info.cdma_num); + ptr = MODE_10 | (info.flash_bank << 24); + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */ + /* Set Command Flags for the last CDMA descriptor: */ + /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */ + pc[info.cdma_num].CommandFlags = + (0 << 10) | (0 << 9) | (1 << 8) | 0x40; + pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */ + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + iowrite32(1, FlashReg + DMA_ENABLE); + /* Wait for DMA to be enabled before issuing the next command */ + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + cdma_trans(info.flash_bank); + + ret = wait_for_completion_timeout(&info.complete, 50 * HZ); + if (!ret) + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = info.ret; + + info.pcmds_num = 0; /* Clear the pending cmds number to 0 */ + + return status; +} + +int is_cdma_interrupt(void) +{ + u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma; + u32 int_en_mask; + u32 cdma_int_en_mask; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* Set the global Enable masks for only those interrupts + * that are supported */ + cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | + DMA_INTR__DESC_COMP_CHANNEL1 | + DMA_INTR__DESC_COMP_CHANNEL2 | + DMA_INTR__DESC_COMP_CHANNEL3 | + DMA_INTR__MEMCOPY_DESC_COMP); + + int_en_mask = (INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL); + + ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask; + ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask; + ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask; + ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask; + ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask; + + nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: " + "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n", + ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma); + + if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) { + return 1; + } else { + iowrite32(ints_b0, FlashReg + INTR_STATUS0); + iowrite32(ints_b1, FlashReg + INTR_STATUS1); + iowrite32(ints_b2, FlashReg + INTR_STATUS2); + iowrite32(ints_b3, FlashReg + INTR_STATUS3); + nand_dbg_print(NAND_DBG_DEBUG, + "Not a NAND controller interrupt! Ignore it.\n"); + return 0; + } +} + +static void update_event_status(void) +{ + int i; + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (i = 0; i < info.cdma_num; i++) { + if (ptr[i].pcmd != 0xff) + info.pcmds[ptr[i].pcmd].Status = CMD_PASS; + if ((ptr[i].CommandType == 0x41) || + (ptr[i].CommandType == 0x42) || + (ptr[i].CommandType == 0x43)) + continue; + + switch (info.pcmds[ptr[i].pcmd].CMD) { + case READ_MAIN_SPARE_CMD: + Conv_Main_Spare_Data_Phy2Log_Format( + info.pcmds[ptr[i].pcmd].DataAddr, + info.pcmds[ptr[i].pcmd].PageCount); + break; + case READ_SPARE_CMD: + Conv_Spare_Data_Phy2Log_Format( + info.pcmds[ptr[i].pcmd].DataAddr); + break; + } + } +} + +static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page) +{ + u16 event = EVENT_NONE; + u16 err_byte; + u16 err_page = 0; + u8 err_sector; + u8 err_device; + u16 ecc_correction_info; + u16 err_address; + u32 eccSectorSize; + u8 *err_pos; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + do { + if (0 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR0); + else if (1 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR1); + else if (2 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR2); + else if (3 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR3); + + err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS); + err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET; + err_sector = ((err_address & + ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); + + ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO); + err_device = ((ecc_correction_info & + ERR_CORRECTION_INFO__DEVICE_NR) >> 8); + + if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) { + event = EVENT_UNCORRECTABLE_DATA_ERROR; + } else { + event = EVENT_CORRECTABLE_DATA_ERROR_FIXED; + if (err_byte < ECC_SECTOR_SIZE) { + err_pos = buf + + (err_page - page) * + DeviceInfo.wPageDataSize + + err_sector * eccSectorSize + + err_byte * + DeviceInfo.wDevicesConnected + + err_device; + *err_pos ^= ecc_correction_info & + ERR_CORRECTION_INFO__BYTEMASK; + } + } + } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); + + return event; +} + +static u16 process_ecc_int(u32 c, u16 *p_desc_num) +{ + struct cdma_descriptor *ptr; + u16 j; + int event = EVENT_PASS; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (c != info.flash_bank) + printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n", + info.flash_bank, c); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (j = 0; j < info.cdma_num; j++) + if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP) + break; + + *p_desc_num = j; /* Pass the descripter number found here */ + + if (j >= info.cdma_num) { + printk(KERN_ERR "Can not find the correct descriptor number " + "when ecc interrupt triggered!" + "info.cdma_num: %d, j: %d\n", info.cdma_num, j); + return EVENT_UNCORRECTABLE_DATA_ERROR; + } + + event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr, + info.pcmds[ptr[j].pcmd].Page); + + if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { + printk(KERN_ERR "Uncorrectable ECC error!" + "info.cdma_num: %d, j: %d, " + "pending cmd CMD: 0x%x, " + "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n", + info.cdma_num, j, + info.pcmds[ptr[j].pcmd].CMD, + info.pcmds[ptr[j].pcmd].Block, + info.pcmds[ptr[j].pcmd].Page, + info.pcmds[ptr[j].pcmd].PageCount); + + if (ptr[j].pcmd != 0xff) + info.pcmds[ptr[j].pcmd].Status = CMD_FAIL; + CDMA_UpdateEventStatus(); + } + + return event; +} + +static void process_prog_erase_fail_int(u16 desc_num) +{ + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + if (ptr[desc_num].pcmd != 0xFF) + info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL; + + CDMA_UpdateEventStatus(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Event_Status (for use with CMD_DMA) +* Inputs: none +* Outputs: Event_Status code +* Description: This function is called after an interrupt has happened +* It reads the HW status register and ...tbd +* It returns the appropriate event status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Event_Status(void) +{ + u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0, + DMA_INTR__DESC_COMP_CHANNEL1, + DMA_INTR__DESC_COMP_CHANNEL2, + DMA_INTR__DESC_COMP_CHANNEL3}; + u32 cdma_int_status, int_status; + u32 ecc_enable = 0; + u16 event = EVENT_PASS; + u16 cur_desc = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ecc_enable = ioread32(FlashReg + ECC_ENABLE); + + while (1) { + int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); + if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) { + event = process_ecc_int(info.flash_bank, &cur_desc); + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + ints_addr[info.flash_bank]); + if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { + nand_dbg_print(NAND_DBG_WARN, + "ints_bank0 to ints_bank3: " + "0x%x, 0x%x, 0x%x, 0x%x, " + "ints_cdma: 0x%x\n", + ioread32(FlashReg + INTR_STATUS0), + ioread32(FlashReg + INTR_STATUS1), + ioread32(FlashReg + INTR_STATUS2), + ioread32(FlashReg + INTR_STATUS3), + ioread32(FlashReg + DMA_INTR)); + break; + } + } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) { + printk(KERN_ERR "NAND program fail interrupt!\n"); + process_prog_erase_fail_int(cur_desc); + event = EVENT_PROGRAM_FAILURE; + break; + } else if (int_status & INTR_STATUS0__ERASE_FAIL) { + printk(KERN_ERR "NAND erase fail interrupt!\n"); + process_prog_erase_fail_int(cur_desc); + event = EVENT_ERASE_FAILURE; + break; + } else { + cdma_int_status = ioread32(FlashReg + DMA_INTR); + if (cdma_int_status & dma_intr_bit[info.flash_bank]) { + iowrite32(dma_intr_bit[info.flash_bank], + FlashReg + DMA_INTR); + update_event_status(); + event = EVENT_PASS; + break; + } + } + } + + int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); + iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]); + cdma_int_status = ioread32(FlashReg + DMA_INTR); + iowrite32(cdma_int_status, FlashReg + DMA_INTR); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return event; +} + + + diff --git a/drivers/block/spectra/lld_cdma.h b/drivers/block/spectra/lld_cdma.h new file mode 100644 index 000000000000..854ea066f0c4 --- /dev/null +++ b/drivers/block/spectra/lld_cdma.h @@ -0,0 +1,123 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* header for LLD_CDMA.c module */ + +#ifndef _LLD_CDMA_ +#define _LLD_CDMA_ + +#include "flash.h" + +#define DEBUG_SYNC 1 + +/*/////////// CDMA specific MACRO definition */ +#define MAX_DESCS (255) +#define MAX_CHANS (4) +#define MAX_SYNC_POINTS (16) +#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2) + +#define CHANNEL_SYNC_MASK (0x000F) +#define CHANNEL_DMA_MASK (0x00F0) +#define CHANNEL_ID_MASK (0x0300) +#define CHANNEL_CONT_MASK (0x4000) +#define CHANNEL_INTR_MASK (0x8000) + +#define CHANNEL_SYNC_OFFSET (0) +#define CHANNEL_DMA_OFFSET (4) +#define CHANNEL_ID_OFFSET (8) +#define CHANNEL_CONT_OFFSET (14) +#define CHANNEL_INTR_OFFSET (15) + +u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags); +u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags); +u16 CDMA_Execute_CMDs(void); +void print_pending_cmds(void); +void print_cdma_descriptors(void); + +extern u8 g_SBDCmdIndex; +extern struct mrst_nand_info info; + + +/*/////////// prototypes: APIs for LLD_CDMA */ +int is_cdma_interrupt(void); +u16 CDMA_Event_Status(void); + +/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */ +struct cdma_descriptor { + u32 NxtPointerHi; + u32 NxtPointerLo; + u32 FlashPointerHi; + u32 FlashPointerLo; + u32 CommandType; + u32 MemAddrHi; + u32 MemAddrLo; + u32 CommandFlags; + u32 Channel; + u32 Status; + u32 MemCopyPointerHi; + u32 MemCopyPointerLo; + u32 Reserved12; + u32 Reserved13; + u32 Reserved14; + u32 pcmd; /* pending cmd num related to this descriptor */ +}; + +/* This struct holds one MemCopy descriptor as defined by the HW */ +struct memcpy_descriptor { + u32 NxtPointerHi; + u32 NxtPointerLo; + u32 SrcAddrHi; + u32 SrcAddrLo; + u32 DestAddrHi; + u32 DestAddrLo; + u32 XferSize; + u32 MemCopyFlags; + u32 MemCopyStatus; + u32 reserved9; + u32 reserved10; + u32 reserved11; + u32 reserved12; + u32 reserved13; + u32 reserved14; + u32 reserved15; +}; + +/* Pending CMD table entries (includes MemCopy parameters */ +struct pending_cmd { + u8 CMD; + u8 *DataAddr; + u32 Block; + u16 Page; + u16 PageCount; + u8 *DataDestAddr; + u8 *DataSrcAddr; + u32 MemCopyByteCnt; + u16 Flags; + u16 Status; +}; + +#if DEBUG_SYNC +extern u32 debug_sync_cnt; +#endif + +/* Definitions for CMD DMA descriptor chain fields */ +#define CMD_DMA_DESC_COMP 0x8000 +#define CMD_DMA_DESC_FAIL 0x4000 + +#endif /*_LLD_CDMA_*/ diff --git a/drivers/block/spectra/lld_emu.c b/drivers/block/spectra/lld_emu.c new file mode 100644 index 000000000000..60eb0f6fdba4 --- /dev/null +++ b/drivers/block/spectra/lld_emu.c @@ -0,0 +1,780 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include "flash.h" +#include "ffsdefs.h" +#include "lld_emu.h" +#include "lld.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define GLOB_LLD_PAGES 64 +#define GLOB_LLD_PAGE_SIZE (512+16) +#define GLOB_LLD_PAGE_DATA_SIZE 512 +#define GLOB_LLD_BLOCKS 2048 + +#if (CMD_DMA && FLASH_EMU) +#include "lld_cdma.h" +u32 totalUsedBanks; +u32 valid_banks[MAX_CHANS]; +#endif + +#if FLASH_EMU /* This is for entire module */ + +static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES]; + +/* Read nand emu file and then fill it's content to flash_memory */ +int emu_load_file_to_mem(void) +{ + mm_segment_t fs; + struct file *nef_filp = NULL; + struct inode *inode = NULL; + loff_t nef_size = 0; + loff_t tmp_file_offset, file_offset; + ssize_t nread; + int i, rc = -EINVAL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + fs = get_fs(); + set_fs(get_ds()); + + nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(nef_filp)) { + printk(KERN_ERR "filp_open error: " + "Unable to open nand emu file!\n"); + return PTR_ERR(nef_filp); + } + + if (nef_filp->f_path.dentry) { + inode = nef_filp->f_path.dentry->d_inode; + } else { + printk(KERN_ERR "Can not get valid inode!\n"); + goto out; + } + + nef_size = i_size_read(inode->i_mapping->host); + if (nef_size <= 0) { + printk(KERN_ERR "Invalid nand emu file size: " + "0x%llx\n", nef_size); + goto out; + } else { + nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n", + nef_size); + } + + file_offset = 0; + for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { + tmp_file_offset = file_offset; + nread = vfs_read(nef_filp, + (char __user *)flash_memory[i], + GLOB_LLD_PAGE_SIZE, &tmp_file_offset); + if (nread < GLOB_LLD_PAGE_SIZE) { + printk(KERN_ERR "%s, Line %d - " + "nand emu file partial read: " + "%d bytes\n", __FILE__, __LINE__, (int)nread); + goto out; + } + file_offset += GLOB_LLD_PAGE_SIZE; + } + rc = 0; + +out: + filp_close(nef_filp, current->files); + set_fs(fs); + return rc; +} + +/* Write contents of flash_memory to nand emu file */ +int emu_write_mem_to_file(void) +{ + mm_segment_t fs; + struct file *nef_filp = NULL; + struct inode *inode = NULL; + loff_t nef_size = 0; + loff_t tmp_file_offset, file_offset; + ssize_t nwritten; + int i, rc = -EINVAL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + fs = get_fs(); + set_fs(get_ds()); + + nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(nef_filp)) { + printk(KERN_ERR "filp_open error: " + "Unable to open nand emu file!\n"); + return PTR_ERR(nef_filp); + } + + if (nef_filp->f_path.dentry) { + inode = nef_filp->f_path.dentry->d_inode; + } else { + printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n"); + goto out; + } + + nef_size = i_size_read(inode->i_mapping->host); + if (nef_size <= 0) { + printk(KERN_ERR "Invalid " + "nand emu file size: 0x%llx\n", nef_size); + goto out; + } else { + nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: " + "%lld\n", nef_size); + } + + file_offset = 0; + for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { + tmp_file_offset = file_offset; + nwritten = vfs_write(nef_filp, + (char __user *)flash_memory[i], + GLOB_LLD_PAGE_SIZE, &tmp_file_offset); + if (nwritten < GLOB_LLD_PAGE_SIZE) { + printk(KERN_ERR "%s, Line %d - " + "nand emu file partial write: " + "%d bytes\n", __FILE__, __LINE__, (int)nwritten); + goto out; + } + file_offset += GLOB_LLD_PAGE_SIZE; + } + rc = 0; + +out: + filp_close(nef_filp, current->files); + set_fs(fs); + return rc; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Init +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Creates & initializes the flash RAM array. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Flash_Init(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + flash_memory[0] = (u8 *)vmalloc(GLOB_LLD_PAGE_SIZE * + GLOB_LLD_BLOCKS * + GLOB_LLD_PAGES * + sizeof(u8)); + if (!flash_memory[0]) { + printk(KERN_ERR "Fail to allocate memory " + "for nand emulator!\n"); + return ERR; + } + + memset((char *)(flash_memory[0]), 0xFF, + GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES * + sizeof(u8)); + + for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) + flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE; + + emu_load_file_to_mem(); /* Load nand emu file to mem */ + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Release +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Releases the flash. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int emu_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + emu_write_mem_to_file(); /* Write back mem to nand emu file */ + + vfree(flash_memory[0]); + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Device_ID +* Inputs: none +* Outputs: PASS=1 FAIL=0 +* Description: Reads the info from the controller registers. +* Sets up DeviceInfo structure with device parameters +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +u16 emu_Read_Device_ID(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + DeviceInfo.wDeviceMaker = 0; + DeviceInfo.wDeviceType = 8; + DeviceInfo.wSpectraStartBlock = 36; + DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1; + DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS; + DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES; + DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE; + DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE; + DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE - + GLOB_LLD_PAGE_DATA_SIZE; + DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES; + DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES; + DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + + 1); + DeviceInfo.MLCDevice = 1; /* Emulate MLC device */ + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + +#if CMD_DMA + totalUsedBanks = 4; + valid_banks[0] = 1; + valid_banks[1] = 1; + valid_banks[2] = 1; + valid_banks[3] = 1; +#endif + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Reset +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Reset the flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Flash_Reset(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Erase_Block +* Inputs: Address +* Outputs: PASS=0 (notice 0=ok here) +* Description: Erase a block +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Erase_Block(u32 block_add) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (block_add >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "emu_Erase_Block error! " + "Too big block address: %d\n", block_add); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", + (int)block_add); + + for (i = block_add * GLOB_LLD_PAGES; + i < ((block_add + 1) * GLOB_LLD_PAGES); i++) { + if (flash_memory[i]) { + memset((u8 *)(flash_memory[i]), 0xFF, + DeviceInfo.wPageSize * sizeof(u8)); + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Main +* Inputs: Write buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the data in the buffer to main area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory\n"); + return FAIL; + } + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), + write_data, DeviceInfo.wPageDataSize); + write_data += DeviceInfo.wPageDataSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Main +* Inputs: Read buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read the data from the flash main area to the buffer +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Main(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(read_data, 0xFF, DeviceInfo.wPageDataSize); + } else { + memcpy(read_data, + (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + + Page]), + DeviceInfo.wPageDataSize); + } + read_data += DeviceInfo.wPageDataSize; + Page++; + } + + return PASS; +} + +#ifndef ELDORA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Main_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read from flash main+spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)PageCount, + (unsigned int)Block, (unsigned int)Page); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(read_data, 0xFF, DeviceInfo.wPageSize); + } else { + memcpy(read_data, (u8 *) (flash_memory[Block * + GLOB_LLD_PAGES + + Page]), + DeviceInfo.wPageSize); + } + + read_data += DeviceInfo.wPageSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Main_Spare +* Inputs: Write buffer +* address +* buffer length +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer to main+spare area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 page_count) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + page_count > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)page_count, + (unsigned int)Block, (unsigned int)Page); + + for (i = 0; i < page_count; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory!\n"); + return FAIL; + } + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), + write_data, DeviceInfo.wPageSize); + write_data += DeviceInfo.wPageSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Spare +* Inputs: Write buffer +* Address +* buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer in the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare Error: " + "Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare Error: " + "Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- " + "block %u page %u\n", + (unsigned int)Block, (unsigned int)Page); + + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory!\n"); + return FAIL; + } + + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + + DeviceInfo.wPageDataSize), write_data, + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read data from the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " + "block %u page %u\n", + (unsigned int)Block, (unsigned int)Page); + + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(write_data, 0xFF, + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + } else { + memcpy(write_data, + (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + + DeviceInfo.wPageDataSize), + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Enable_Disable_Interrupts +* Inputs: enable or disable +* Outputs: none +* Description: NOP +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void emu_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); +} + +u16 emu_Get_Bad_Block(u32 block) +{ + return 0; +} + +#if CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Support for CDMA functions +************************************ +* emu_CDMA_Flash_Init +* CDMA_process_data command (use LLD_CDMA) +* CDMA_MemCopy_CMD (use LLD_CDMA) +* emu_CDMA_execute all commands +* emu_CDMA_Event_Status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Flash_Init(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = 3; + } + + return PASS; +} + +static void emu_isr(int irq, void *dev_id) +{ + /* TODO: ... */ +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: execute each command in the pending CMD array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Execute_CMDs(u16 tag_count) +{ + u16 i, j; + u8 CMD; /* cmd parameter */ + u8 *data; + u32 block; + u16 page; + u16 count; + u16 status = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " + "Tag Count %u\n", tag_count); + + for (i = 0; i < totalUsedBanks; i++) { + PendingCMD[i].CMD = DUMMY_CMD; + PendingCMD[i].Tag = 0xFF; + PendingCMD[i].Block = + (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; + + for (j = 0; j <= MAX_CHANS; j++) + PendingCMD[i].ChanSync[j] = 0; + } + + CDMA_Execute_CMDs(tag_count); + + print_pending_cmds(tag_count); + +#if DEBUG_SYNC + } + debug_sync_cnt++; +#endif + + for (i = MAX_CHANS; + i < tag_count + MAX_CHANS; i++) { + CMD = PendingCMD[i].CMD; + data = PendingCMD[i].DataAddr; + block = PendingCMD[i].Block; + page = PendingCMD[i].Page; + count = PendingCMD[i].PageCount; + + switch (CMD) { + case ERASE_CMD: + emu_Erase_Block(block); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_CMD: + emu_Write_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_SPARE_CMD: + emu_Write_Page_Main_Spare(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case READ_MAIN_CMD: + emu_Read_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case MEMCOPY_CMD: + memcpy(PendingCMD[i].DataDestAddr, + PendingCMD[i].DataSrcAddr, + PendingCMD[i].MemCopyByteCnt); + case DUMMY_CMD: + PendingCMD[i].Status = PASS; + break; + default: + PendingCMD[i].Status = FAIL; + break; + } + } + + /* + * Temperory adding code to reset PendingCMD array for basic testing. + * It should be done at the end of event status function. + */ + for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = CMD_NOT_DONE; + } + + nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); + + emu_isr(0, 0); /* This is a null isr now. Need fill it in future */ + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Event_Status +* Inputs: none +* Outputs: Event_Status code +* Description: This function can also be used to force errors +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Event_Status(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return EVENT_PASS; +} + +#endif /* CMD_DMA */ +#endif /* !ELDORA */ +#endif /* FLASH_EMU */ diff --git a/drivers/block/spectra/lld_emu.h b/drivers/block/spectra/lld_emu.h new file mode 100644 index 000000000000..63f84c38d3c1 --- /dev/null +++ b/drivers/block/spectra/lld_emu.h @@ -0,0 +1,51 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_EMU_ +#define _LLD_EMU_ + +#include "ffsport.h" +#include "ffsdefs.h" + +/* prototypes: emulator API functions */ +extern u16 emu_Flash_Reset(void); +extern u16 emu_Flash_Init(void); +extern int emu_Flash_Release(void); +extern u16 emu_Read_Device_ID(void); +extern u16 emu_Erase_Block(u32 block_addr); +extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 emu_Event_Status(void); +extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE); +extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 emu_Get_Bad_Block(u32 block); + +u16 emu_CDMA_Flash_Init(void); +u16 emu_CDMA_Execute_CMDs(u16 tag_count); +u16 emu_CDMA_Event_Status(void); +#endif /*_LLD_EMU_*/ diff --git a/drivers/block/spectra/lld_nand.c b/drivers/block/spectra/lld_nand.c new file mode 100644 index 000000000000..8c279b8a6a67 --- /dev/null +++ b/drivers/block/spectra/lld_nand.c @@ -0,0 +1,2601 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "lld.h" +#include "lld_nand.h" +#include "lld_cdma.h" + +#include "spectraswconfig.h" +#include "flash.h" +#include "ffsdefs.h" + +#include +#include +#include +#include + +#include "nand_regs.h" + +#define SPECTRA_NAND_NAME "nd" + +#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) +#define MAX_PAGES_PER_RW 128 + +#define INT_IDLE_STATE 0 +#define INT_READ_PAGE_MAIN 0x01 +#define INT_WRITE_PAGE_MAIN 0x02 +#define INT_PIPELINE_READ_AHEAD 0x04 +#define INT_PIPELINE_WRITE_AHEAD 0x08 +#define INT_MULTI_PLANE_READ 0x10 +#define INT_MULTI_PLANE_WRITE 0x11 + +static u32 enable_ecc; + +struct mrst_nand_info info; + +int totalUsedBanks; +u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; + +void __iomem *FlashReg; +void __iomem *FlashMem; + +u16 conf_parameters[] = { + 0x0000, + 0x0000, + 0x01F4, + 0x01F4, + 0x01F4, + 0x01F4, + 0x0000, + 0x0000, + 0x0001, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0040, + 0x0001, + 0x000A, + 0x000A, + 0x000A, + 0x0000, + 0x0000, + 0x0005, + 0x0012, + 0x000C +}; + +u16 NAND_Get_Bad_Block(u32 block) +{ + u32 status = PASS; + u32 flag_bytes = 0; + u32 skip_bytes = DeviceInfo.wSpareSkipBytes; + u32 page, i; + u8 *pReadSpareBuf = buf_get_bad_block; + + if (enable_ecc) + flag_bytes = DeviceInfo.wNumPageSpareFlag; + + for (page = 0; page < 2; page++) { + status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1); + if (status != PASS) + return READ_ERROR; + for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) + if (pReadSpareBuf[i] != 0xff) + return DEFECTIVE_BLOCK; + } + + for (page = 1; page < 3; page++) { + status = NAND_Read_Page_Spare(pReadSpareBuf, block, + DeviceInfo.wPagesPerBlock - page , 1); + if (status != PASS) + return READ_ERROR; + for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) + if (pReadSpareBuf[i] != 0xff) + return DEFECTIVE_BLOCK; + } + + return GOOD_BLOCK; +} + + +u16 NAND_Flash_Reset(void) +{ + u32 i; + u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP, + INTR_STATUS1__RST_COMP, + INTR_STATUS2__RST_COMP, + INTR_STATUS3__RST_COMP}; + u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT, + INTR_STATUS1__TIME_OUT, + INTR_STATUS2__TIME_OUT, + INTR_STATUS3__TIME_OUT}; + u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + u32 device_reset_banks[4] = {DEVICE_RESET__BANK0, + DEVICE_RESET__BANK1, + DEVICE_RESET__BANK2, + DEVICE_RESET__BANK3}; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) + iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], + FlashReg + intr_status[i]); + + for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { + iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET); + while (!(ioread32(FlashReg + intr_status[i]) & + (intr_status_rst_comp[i] | intr_status_time_out[i]))) + ; + if (ioread32(FlashReg + intr_status[i]) & + intr_status_time_out[i]) + nand_dbg_print(NAND_DBG_WARN, + "NAND Reset operation timed out on bank %d\n", i); + } + + for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) + iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], + FlashReg + intr_status[i]); + + return PASS; +} + +static void NAND_ONFi_Timing_Mode(u16 mode) +{ + u16 Trea[6] = {40, 30, 25, 20, 20, 16}; + u16 Trp[6] = {50, 25, 17, 15, 12, 10}; + u16 Treh[6] = {30, 15, 15, 10, 10, 7}; + u16 Trc[6] = {100, 50, 35, 30, 25, 20}; + u16 Trhoh[6] = {0, 15, 15, 15, 15, 15}; + u16 Trloh[6] = {0, 0, 0, 0, 5, 5}; + u16 Tcea[6] = {100, 45, 30, 25, 25, 25}; + u16 Tadl[6] = {200, 100, 100, 100, 70, 70}; + u16 Trhw[6] = {200, 100, 100, 100, 100, 100}; + u16 Trhz[6] = {200, 100, 100, 100, 100, 100}; + u16 Twhr[6] = {120, 80, 80, 60, 60, 60}; + u16 Tcs[6] = {70, 35, 25, 25, 20, 15}; + + u16 TclsRising = 1; + u16 data_invalid_rhoh, data_invalid_rloh, data_invalid; + u16 dv_window = 0; + u16 en_lo, en_hi; + u16 acc_clks; + u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + en_lo = CEIL_DIV(Trp[mode], CLK_X); + en_hi = CEIL_DIV(Treh[mode], CLK_X); + +#if ONFI_BLOOM_TIME + if ((en_hi * CLK_X) < (Treh[mode] + 2)) + en_hi++; +#endif + + if ((en_lo + en_hi) * CLK_X < Trc[mode]) + en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X); + + if ((en_lo + en_hi) < CLK_MULTI) + en_lo += CLK_MULTI - en_lo - en_hi; + + while (dv_window < 8) { + data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode]; + + data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode]; + + data_invalid = + data_invalid_rhoh < + data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh; + + dv_window = data_invalid - Trea[mode]; + + if (dv_window < 8) + en_lo++; + } + + acc_clks = CEIL_DIV(Trea[mode], CLK_X); + + while (((acc_clks * CLK_X) - Trea[mode]) < 3) + acc_clks++; + + if ((data_invalid - acc_clks * CLK_X) < 2) + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n", + __FILE__, __LINE__); + + addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); + re_2_we = CEIL_DIV(Trhw[mode], CLK_X); + re_2_re = CEIL_DIV(Trhz[mode], CLK_X); + we_2_re = CEIL_DIV(Twhr[mode], CLK_X); + cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X); + if (!TclsRising) + cs_cnt = CEIL_DIV(Tcs[mode], CLK_X); + if (cs_cnt == 0) + cs_cnt = 1; + + if (Tcea[mode]) { + while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode]) + cs_cnt++; + } + +#if MODE5_WORKAROUND + if (mode == 5) + acc_clks = 5; +#endif + + /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */ + if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) && + (ioread32(FlashReg + DEVICE_ID) == 0x88)) + acc_clks = 6; + + iowrite32(acc_clks, FlashReg + ACC_CLKS); + iowrite32(re_2_we, FlashReg + RE_2_WE); + iowrite32(re_2_re, FlashReg + RE_2_RE); + iowrite32(we_2_re, FlashReg + WE_2_RE); + iowrite32(addr_2_data, FlashReg + ADDR_2_DATA); + iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT); + iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT); + iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT); +} + +static void index_addr(u32 address, u32 data) +{ + iowrite32(address, FlashMem); + iowrite32(data, FlashMem + 0x10); +} + +static void index_addr_read_data(u32 address, u32 *pdata) +{ + iowrite32(address, FlashMem); + *pdata = ioread32(FlashMem + 0x10); +} + +static void set_ecc_config(void) +{ +#if SUPPORT_8BITECC + if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) || + (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128)) + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + + if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) + == 1) { + DeviceInfo.wECCBytesPerSector = 4; + DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; + DeviceInfo.wNumPageSpareFlag = + DeviceInfo.wPageSpareSize - + DeviceInfo.wPageDataSize / + (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * + DeviceInfo.wECCBytesPerSector + - DeviceInfo.wSpareSkipBytes; + } else { + DeviceInfo.wECCBytesPerSector = + (ioread32(FlashReg + ECC_CORRECTION) & + ECC_CORRECTION__VALUE) * 13 / 8; + if ((DeviceInfo.wECCBytesPerSector) % 2 == 0) + DeviceInfo.wECCBytesPerSector += 2; + else + DeviceInfo.wECCBytesPerSector += 1; + + DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; + DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize - + DeviceInfo.wPageDataSize / + (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * + DeviceInfo.wECCBytesPerSector + - DeviceInfo.wSpareSkipBytes; + } +} + +static u16 get_onfi_nand_para(void) +{ + int i; + u16 blks_lun_l, blks_lun_h, n_of_luns; + u32 blockperlun, id; + + iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET); + + while (!((ioread32(FlashReg + INTR_STATUS0) & + INTR_STATUS0__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS0) & + INTR_STATUS0__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { + iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__RST_COMP) { + iowrite32(DEVICE_RESET__BANK2, + FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__RST_COMP) { + iowrite32(DEVICE_RESET__BANK3, + FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS3) & + INTR_STATUS3__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS3) & + INTR_STATUS3__TIME_OUT))) + ; + } else { + printk(KERN_ERR "Getting a time out for bank 2!\n"); + } + } else { + printk(KERN_ERR "Getting a time out for bank 1!\n"); + } + } + + iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0); + iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1); + iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2); + iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3); + + DeviceInfo.wONFIDevFeatures = + ioread32(FlashReg + ONFI_DEVICE_FEATURES); + DeviceInfo.wONFIOptCommands = + ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS); + DeviceInfo.wONFITimingMode = + ioread32(FlashReg + ONFI_TIMING_MODE); + DeviceInfo.wONFIPgmCacheTimingMode = + ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE); + + n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & + ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; + blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); + blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); + + blockperlun = (blks_lun_h << 16) | blks_lun_l; + + DeviceInfo.wTotalBlocks = n_of_luns * blockperlun; + + if (!(ioread32(FlashReg + ONFI_TIMING_MODE) & + ONFI_TIMING_MODE__VALUE)) + return FAIL; + + for (i = 5; i > 0; i--) { + if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i)) + break; + } + + NAND_ONFi_Timing_Mode(i); + + index_addr(MODE_11 | 0, 0x90); + index_addr(MODE_11 | 1, 0); + + for (i = 0; i < 3; i++) + index_addr_read_data(MODE_11 | 2, &id); + + nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); + + DeviceInfo.MLCDevice = id & 0x0C; + + /* By now, all the ONFI devices we know support the page cache */ + /* rw feature. So here we enable the pipeline_rw_ahead feature */ + /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */ + /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */ + + return PASS; +} + +static void get_samsung_nand_para(void) +{ + u8 no_of_planes; + u32 blk_size; + u64 plane_size, capacity; + u32 id_bytes[5]; + int i; + + index_addr((u32)(MODE_11 | 0), 0x90); + index_addr((u32)(MODE_11 | 1), 0); + for (i = 0; i < 5; i++) + index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]); + + nand_dbg_print(NAND_DBG_DEBUG, + "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + id_bytes[0], id_bytes[1], id_bytes[2], + id_bytes[3], id_bytes[4]); + + if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ + /* Set timing register values according to datasheet */ + iowrite32(5, FlashReg + ACC_CLKS); + iowrite32(20, FlashReg + RE_2_WE); + iowrite32(12, FlashReg + WE_2_RE); + iowrite32(14, FlashReg + ADDR_2_DATA); + iowrite32(3, FlashReg + RDWR_EN_LO_CNT); + iowrite32(2, FlashReg + RDWR_EN_HI_CNT); + iowrite32(2, FlashReg + CS_SETUP_CNT); + } + + no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); + plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4); + blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4); + capacity = (u64)128 * plane_size * no_of_planes; + + DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size); +} + +static void get_toshiba_nand_para(void) +{ + void __iomem *scratch_reg; + u32 tmp; + + /* Workaround to fix a controller bug which reports a wrong */ + /* spare area size for some kind of Toshiba NAND device */ + if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) && + (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) { + iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE); + tmp = ioread32(FlashReg + DEVICES_CONNECTED) * + ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); + iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE); +#if SUPPORT_15BITECC + iowrite32(15, FlashReg + ECC_CORRECTION); +#elif SUPPORT_8BITECC + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + } + + /* As Toshiba NAND can not provide it's block number, */ + /* so here we need user to provide the correct block */ + /* number in a scratch register before the Linux NAND */ + /* driver is loaded. If no valid value found in the scratch */ + /* register, then we use default block number value */ + scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); + if (!scratch_reg) { + printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", + __FILE__, __LINE__); + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Spectra: ioremap reg address: 0x%p\n", scratch_reg); + DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); + if (DeviceInfo.wTotalBlocks < 512) + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + iounmap(scratch_reg); + } +} + +static void get_hynix_nand_para(void) +{ + void __iomem *scratch_reg; + u32 main_size, spare_size; + + switch (DeviceInfo.wDeviceID) { + case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ + case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ + iowrite32(128, FlashReg + PAGES_PER_BLOCK); + iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE); + iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE); + main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED); + spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED); + iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE); + iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE); + iowrite32(0, FlashReg + DEVICE_WIDTH); +#if SUPPORT_15BITECC + iowrite32(15, FlashReg + ECC_CORRECTION); +#elif SUPPORT_8BITECC + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + DeviceInfo.MLCDevice = 1; + break; + default: + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." + "Will use default parameter values instead.\n", + DeviceInfo.wDeviceID); + } + + scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); + if (!scratch_reg) { + printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", + __FILE__, __LINE__); + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Spectra: ioremap reg address: 0x%p\n", scratch_reg); + DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); + if (DeviceInfo.wTotalBlocks < 512) + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + iounmap(scratch_reg); + } +} + +static void find_valid_banks(void) +{ + u32 id[LLD_MAX_FLASH_BANKS]; + int i; + + totalUsedBanks = 0; + for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { + index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90); + index_addr((u32)(MODE_11 | (i << 24) | 1), 0); + index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]); + + nand_dbg_print(NAND_DBG_DEBUG, + "Return 1st ID for bank[%d]: %x\n", i, id[i]); + + if (i == 0) { + if (id[i] & 0x0ff) + GLOB_valid_banks[i] = 1; + } else { + if ((id[i] & 0x0ff) == (id[0] & 0x0ff)) + GLOB_valid_banks[i] = 1; + } + + totalUsedBanks += GLOB_valid_banks[i]; + } + + nand_dbg_print(NAND_DBG_DEBUG, + "totalUsedBanks: %d\n", totalUsedBanks); +} + +static void detect_partition_feature(void) +{ + if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) { + if ((ioread32(FlashReg + PERM_SRC_ID_1) & + PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { + DeviceInfo.wSpectraStartBlock = + ((ioread32(FlashReg + MIN_MAX_BANK_1) & + MIN_MAX_BANK_1__MIN_VALUE) * + DeviceInfo.wTotalBlocks) + + + (ioread32(FlashReg + MIN_BLK_ADDR_1) & + MIN_BLK_ADDR_1__VALUE); + + DeviceInfo.wSpectraEndBlock = + (((ioread32(FlashReg + MIN_MAX_BANK_1) & + MIN_MAX_BANK_1__MAX_VALUE) >> 2) * + DeviceInfo.wTotalBlocks) + + + (ioread32(FlashReg + MAX_BLK_ADDR_1) & + MAX_BLK_ADDR_1__VALUE); + + DeviceInfo.wTotalBlocks *= totalUsedBanks; + + if (DeviceInfo.wSpectraEndBlock >= + DeviceInfo.wTotalBlocks) { + DeviceInfo.wSpectraEndBlock = + DeviceInfo.wTotalBlocks - 1; + } + + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } else { + DeviceInfo.wTotalBlocks *= totalUsedBanks; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + DeviceInfo.wSpectraEndBlock = + DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } + } else { + DeviceInfo.wTotalBlocks *= totalUsedBanks; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } +} + +static void dump_device_info(void) +{ + nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n"); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", + DeviceInfo.wDeviceMaker); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", + DeviceInfo.wDeviceID); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", + DeviceInfo.wDeviceType); + nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", + DeviceInfo.wSpectraStartBlock); + nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", + DeviceInfo.wSpectraEndBlock); + nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", + DeviceInfo.wTotalBlocks); + nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", + DeviceInfo.wPagesPerBlock); + nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", + DeviceInfo.wPageSize); + nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", + DeviceInfo.wPageDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", + DeviceInfo.wPageSpareSize); + nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", + DeviceInfo.wNumPageSpareFlag); + nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", + DeviceInfo.wECCBytesPerSector); + nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", + DeviceInfo.wBlockSize); + nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", + DeviceInfo.wBlockDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", + DeviceInfo.wDataBlockNum); + nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", + DeviceInfo.bPlaneNum); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", + DeviceInfo.wDeviceMainAreaSize); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", + DeviceInfo.wDeviceSpareAreaSize); + nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", + DeviceInfo.wDevicesConnected); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", + DeviceInfo.wDeviceWidth); + nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", + DeviceInfo.wHWRevision); + nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", + DeviceInfo.wHWFeatures); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", + DeviceInfo.wONFIDevFeatures); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", + DeviceInfo.wONFIOptCommands); + nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", + DeviceInfo.wONFITimingMode); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", + DeviceInfo.wONFIPgmCacheTimingMode); + nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", + DeviceInfo.MLCDevice ? "Yes" : "No"); + nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", + DeviceInfo.wSpareSkipBytes); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", + DeviceInfo.nBitsInPageNumber); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", + DeviceInfo.nBitsInPageDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", + DeviceInfo.nBitsInBlockDataSize); +} + +u16 NAND_Read_Device_ID(void) +{ + u16 status = PASS; + u8 no_of_planes; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES); + iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER); + DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID); + DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID); + DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c; + + if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & + ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ + if (FAIL == get_onfi_nand_para()) + return FAIL; + } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */ + get_samsung_nand_para(); + } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */ + get_toshiba_nand_para(); + } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */ + get_hynix_nand_para(); + } else { + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" + "acc_clks: %d, re_2_we: %d, we_2_re: %d," + "addr_2_data: %d, rdwr_en_lo_cnt: %d, " + "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", + ioread32(FlashReg + ACC_CLKS), + ioread32(FlashReg + RE_2_WE), + ioread32(FlashReg + WE_2_RE), + ioread32(FlashReg + ADDR_2_DATA), + ioread32(FlashReg + RDWR_EN_LO_CNT), + ioread32(FlashReg + RDWR_EN_HI_CNT), + ioread32(FlashReg + CS_SETUP_CNT)); + + DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION); + DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES); + + DeviceInfo.wDeviceMainAreaSize = + ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE); + DeviceInfo.wDeviceSpareAreaSize = + ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); + + DeviceInfo.wPageDataSize = + ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE); + + /* Note: When using the Micon 4K NAND device, the controller will report + * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. + * And if force set it to 218 bytes, the controller can not work + * correctly. So just let it be. But keep in mind that this bug may + * cause + * other problems in future. - Yunpeng 2008-10-10 + */ + DeviceInfo.wPageSpareSize = + ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE); + + DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK); + + DeviceInfo.wPageSize = + DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize; + DeviceInfo.wBlockSize = + DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wBlockDataSize = + DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; + + DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH); + DeviceInfo.wDeviceType = + ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8); + + DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED); + + DeviceInfo.wSpareSkipBytes = + ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) * + DeviceInfo.wDevicesConnected; + + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + + set_ecc_config(); + + no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) & + NUMBER_OF_PLANES__VALUE; + + switch (no_of_planes) { + case 0: + case 1: + case 3: + case 7: + DeviceInfo.bPlaneNum = no_of_planes + 1; + break; + default: + status = FAIL; + break; + } + + find_valid_banks(); + + detect_partition_feature(); + + dump_device_info(); + + return status; +} + +u16 NAND_UnlockArrayAll(void) +{ + u64 start_addr, end_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + start_addr = 0; + end_addr = ((u64)DeviceInfo.wBlockSize * + (DeviceInfo.wTotalBlocks - 1)) >> + DeviceInfo.nBitsInPageDataSize; + + index_addr((u32)(MODE_10 | (u32)start_addr), 0x10); + index_addr((u32)(MODE_10 | (u32)end_addr), 0x11); + + return PASS; +} + +void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (INT_ENABLE) + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); + else + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); +} + +u16 NAND_Erase_Block(u32 block) +{ + u16 status = PASS; + u64 flash_add; + u16 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (block >= DeviceInfo.wTotalBlocks) + status = FAIL; + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, + FlashReg + intr_status); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1); + + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ERASE_FAIL) + status = FAIL; + + iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, + FlashReg + intr_status); + } + + return status; +} + +static u32 Boundary_Check_Block_Page(u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + + if (block >= DeviceInfo.wTotalBlocks) + status = FAIL; + + if (page + page_count > DeviceInfo.wPagesPerBlock) + status = FAIL; + + return status; +} + +u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 i; + u64 flash_add; + u32 PageSpareSize = DeviceInfo.wPageSpareSize; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_spare = buf_read_page_spare; + + if (block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "block too big: %d\n", (int)block); + status = FAIL; + } + + if (page >= DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "page too big: %d\n", page); + status = FAIL; + } + + if (page_count > 1) { + printk(KERN_ERR "page count too big: %d\n", page_count); + status = FAIL; + } + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x41); + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x2000 | page_count); + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__LOAD_COMP)) + ; + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + for (i = 0; i < (PageSpareSize / 4); i++) + *((u32 *)page_spare + i) = + ioread32(FlashMem + 0x10); + + if (enable_ecc) { + for (i = 0; i < spareFlagBytes; i++) + read_data[i] = + page_spare[PageSpareSize - + spareFlagBytes + i]; + for (i = 0; i < (PageSpareSize - spareFlagBytes); i++) + read_data[spareFlagBytes + i] = + page_spare[i]; + } else { + for (i = 0; i < PageSpareSize; i++) + read_data[i] = page_spare[i]; + } + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + } + + return status; +} + +/* No use function. Should be removed later */ +u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + printk(KERN_ERR + "Error! This function (NAND_Write_Page_Spare) should never" + " be called!\n"); + return ERR; +} + +/* op value: 0 - DDMA read; 1 - DDMA write */ +static void ddma_trans(u8 *data, u64 flash_add, + u32 flash_bank, int op, u32 numPages) +{ + u32 data_addr; + + /* Map virtual address to bus address for DDMA */ + data_addr = virt_to_bus(data); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + (u16)(2 << 12) | (op << 8) | numPages); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + ((u16)(0x0FFFF & (data_addr >> 16)) << 8)), + (u16)(2 << 12) | (2 << 8) | 0); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + ((u16)(0x0FFFF & data_addr) << 8)), + (u16)(2 << 12) | (3 << 8) | 0); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (1 << 16) | (0x40 << 8)), + (u16)(2 << 12) | (4 << 8) | 0); +} + +/* If data in buf are all 0xff, then return 1; otherwise return 0 */ +static int check_all_1(u8 *buf) +{ + int i, j, cnt; + + for (i = 0; i < DeviceInfo.wPageDataSize; i++) { + if (buf[i] != 0xff) { + cnt = 0; + nand_dbg_print(NAND_DBG_WARN, + "the first non-0xff data byte is: %d\n", i); + for (j = i; j < DeviceInfo.wPageDataSize; j++) { + nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]); + cnt++; + if (cnt > 8) + break; + } + nand_dbg_print(NAND_DBG_WARN, "\n"); + return 0; + } + } + + return 1; +} + +static int do_ecc_new(unsigned long bank, u8 *buf, + u32 block, u16 page) +{ + int status = PASS; + u16 err_page = 0; + u16 err_byte; + u8 err_sect; + u8 err_dev; + u16 err_fix_info; + u16 err_addr; + u32 ecc_sect_size; + u8 *err_pos; + u32 err_page_addr[4] = {ERR_PAGE_ADDR0, + ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3}; + + ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + do { + err_page = ioread32(FlashReg + err_page_addr[bank]); + err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS); + err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET; + err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); + err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO); + err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR) + >> 8); + if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) { + nand_dbg_print(NAND_DBG_WARN, + "%s, Line %d Uncorrectable ECC error " + "when read block %d page %d." + "PTN_INTR register: 0x%x " + "err_page: %d, err_sect: %d, err_byte: %d, " + "err_dev: %d, ecc_sect_size: %d, " + "err_fix_info: 0x%x\n", + __FILE__, __LINE__, block, page, + ioread32(FlashReg + PTN_INTR), + err_page, err_sect, err_byte, err_dev, + ecc_sect_size, (u32)err_fix_info); + + if (check_all_1(buf)) + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" + "All 0xff!\n", + __FILE__, __LINE__); + else + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" + "Not all 0xff!\n", + __FILE__, __LINE__); + status = FAIL; + } else { + nand_dbg_print(NAND_DBG_WARN, + "%s, Line %d Found ECC error " + "when read block %d page %d." + "err_page: %d, err_sect: %d, err_byte: %d, " + "err_dev: %d, ecc_sect_size: %d, " + "err_fix_info: 0x%x\n", + __FILE__, __LINE__, block, page, + err_page, err_sect, err_byte, err_dev, + ecc_sect_size, (u32)err_fix_info); + if (err_byte < ECC_SECTOR_SIZE) { + err_pos = buf + + (err_page - page) * + DeviceInfo.wPageDataSize + + err_sect * ecc_sect_size + + err_byte * + DeviceInfo.wDevicesConnected + + err_dev; + + *err_pos ^= err_fix_info & + ERR_CORRECTION_INFO__BYTEMASK; + } + } + } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); + + return status; +} + +u16 NAND_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *read_data_l; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + if (page_count > 1) { + read_data_l = read_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Read_Ahead_Polling( + read_data_l, block, page, + MAX_PAGES_PER_RW); + + if (status == FAIL) + return status; + + read_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Read_Ahead_Polling( + read_data_l, block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + ddma_trans(read_data, flash_add, flash_bank, 0, 1); + + if (enable_ecc) { + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, read_data, + block, page); + } + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE & + INTR_STATUS0__ECC_ERR) + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status); + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 ecc_done_OR_dma_comp; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + *DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + ecc_done_OR_dma_comp = 0; + while (1) { + if (enable_ecc) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + + } + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + } + return status; +} + +u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + u8 *read_data_l; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + if (page_count > 1) { + read_data_l = read_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Read_Ahead( + read_data_l, block, page, + MAX_PAGES_PER_RW); + + if (status == FAIL) + return status; + + read_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Read_Ahead( + read_data_l, block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + /* Fill the mrst_nand_info structure */ + info.state = INT_READ_PAGE_MAIN; + info.read_data = read_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + ddma_trans(read_data, flash_add, flash_bank, 0, 1); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +void Conv_Spare_Data_Log2Phy_Format(u8 *data) +{ + int i; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + const u32 PageSpareSize = DeviceInfo.wPageSpareSize; + + if (enable_ecc) { + for (i = spareFlagBytes - 1; i >= 0; i++) + data[PageSpareSize - spareFlagBytes + i] = data[i]; + } +} + +void Conv_Spare_Data_Phy2Log_Format(u8 *data) +{ + int i; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + const u32 PageSpareSize = DeviceInfo.wPageSpareSize; + + if (enable_ecc) { + for (i = 0; i < spareFlagBytes; i++) + data[i] = data[PageSpareSize - spareFlagBytes + i]; + } +} + + +void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count) +{ + const u32 PageSize = DeviceInfo.wPageSize; + const u32 PageDataSize = DeviceInfo.wPageDataSize; + const u32 eccBytes = DeviceInfo.wECCBytesPerSector; + const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 eccSectorSize; + u32 page_offset; + int i, j; + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + if (enable_ecc) { + while (page_count > 0) { + page_offset = (page_count - 1) * PageSize; + j = (DeviceInfo.wPageDataSize / eccSectorSize); + for (i = spareFlagBytes - 1; i >= 0; i--) + data[page_offset + + (eccSectorSize + eccBytes) * j + i] = + data[page_offset + PageDataSize + i]; + for (j--; j >= 1; j--) { + for (i = eccSectorSize - 1; i >= 0; i--) + data[page_offset + + (eccSectorSize + eccBytes) * j + i] = + data[page_offset + + eccSectorSize * j + i]; + } + for (i = (PageSize - spareSkipBytes) - 1; + i >= PageDataSize; i--) + data[page_offset + i + spareSkipBytes] = + data[page_offset + i]; + page_count--; + } + } +} + +void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count) +{ + const u32 PageSize = DeviceInfo.wPageSize; + const u32 PageDataSize = DeviceInfo.wPageDataSize; + const u32 eccBytes = DeviceInfo.wECCBytesPerSector; + const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 eccSectorSize; + u32 page_offset; + int i, j; + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + if (enable_ecc) { + while (page_count > 0) { + page_offset = (page_count - 1) * PageSize; + for (i = PageDataSize; + i < PageSize - spareSkipBytes; + i++) + data[page_offset + i] = + data[page_offset + i + + spareSkipBytes]; + for (j = 1; + j < DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + for (i = 0; i < eccSectorSize; i++) + data[page_offset + + eccSectorSize * j + i] = + data[page_offset + + (eccSectorSize + eccBytes) * j + + i]; + } + for (i = 0; i < spareFlagBytes; i++) + data[page_offset + PageDataSize + i] = + data[page_offset + + (eccSectorSize + eccBytes) * j + i]; + page_count--; + } + } +} + +/* Un-tested function */ +u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 ecc_done_OR_dma_comp; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + ecc_done_OR_dma_comp = 0; + while (1) { + if (enable_ecc) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + + } + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + MULTIPLANE_OPERATION); + } + + return status; +} + +u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, + u16 page, u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + *DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + /* Fill the mrst_nand_info structure */ + info.state = INT_PIPELINE_READ_AHEAD; + info.read_data = read_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + + +u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + u8 *write_data_l; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(INTR_STATUS0__PROGRAM_COMP | + INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status); + + if (page_count > 1) { + write_data_l = write_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Write(write_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Write_Ahead( + write_data_l, block, page, + MAX_PAGES_PER_RW); + if (status == FAIL) + return status; + + write_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Write(write_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Write_Ahead(write_data_l, + block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + /* Fill the mrst_nand_info structure */ + info.state = INT_WRITE_PAGE_MAIN; + info.write_data = write_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + ddma_trans(write_data, flash_add, flash_bank, 1, 1); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG) + ; + + return status; +} + +void NAND_ECC_Ctrl(int enable) +{ + if (enable) { + nand_dbg_print(NAND_DBG_WARN, + "Will enable ECC in %s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + iowrite32(1, FlashReg + ECC_ENABLE); + enable_ecc = 1; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Will disable ECC in %s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + iowrite32(0, FlashReg + ECC_ENABLE); + enable_ecc = 0; + } +} + +u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 page, u16 page_count) +{ + u32 status = PASS; + u32 i, j, page_num = 0; + u32 PageSize = DeviceInfo.wPageSize; + u32 PageDataSize = DeviceInfo.wPageDataSize; + u32 eccBytes = DeviceInfo.wECCBytesPerSector; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + u64 flash_add; + u32 eccSectorSize; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_main_spare = buf_write_page_main_spare; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(1, FlashReg + TRANSFER_SPARE_REG); + + while ((status != FAIL) && (page_count > 0)) { + flash_add = (u64)(block % + (DeviceInfo.wTotalBlocks / totalUsedBanks)) * + DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> + DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + if (enable_ecc) { + for (j = 0; + j < + DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + for (i = 0; i < eccSectorSize; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + + i] = + write_data[eccSectorSize * + j + i]; + + for (i = 0; i < eccBytes; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + + eccSectorSize + + i] = + write_data[PageDataSize + + spareFlagBytes + + eccBytes * j + + i]; + } + + for (i = 0; i < spareFlagBytes; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + i] = + write_data[PageDataSize + i]; + + for (i = PageSize - 1; i >= PageDataSize + + spareSkipBytes; i--) + page_main_spare[i] = page_main_spare[i - + spareSkipBytes]; + + for (i = PageDataSize; i < PageDataSize + + spareSkipBytes; i++) + page_main_spare[i] = 0xff; + + for (i = 0; i < PageSize / 4; i++) + iowrite32( + *((u32 *)page_main_spare + i), + FlashMem + 0x10); + } else { + + for (i = 0; i < PageSize / 4; i++) + iowrite32(*((u32 *)write_data + i), + FlashMem + 0x10); + } + + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__PROGRAM_COMP | + INTR_STATUS0__PROGRAM_FAIL))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) + status = FAIL; + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + page_num++; + page_count--; + write_data += PageSize; + } + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + } + + return status; +} + +u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 i, j; + u64 flash_add = 0; + u32 PageSize = DeviceInfo.wPageSize; + u32 PageDataSize = DeviceInfo.wPageDataSize; + u32 PageSpareSize = DeviceInfo.wPageSpareSize; + u32 eccBytes = DeviceInfo.wECCBytesPerSector; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + u32 eccSectorSize; + u32 flash_bank; + u32 intr_status = 0; + u8 *read_data_l = read_data; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_main_spare = buf_read_page_main_spare; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(1, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + while ((status != FAIL) && (page_count > 0)) { + flash_add = (u64)(block % + (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x43); + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x2000 | page_count); + + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__LOAD_COMP)) + ; + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> + DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + for (i = 0; i < PageSize / 4; i++) + *(((u32 *)page_main_spare) + i) = + ioread32(FlashMem + 0x10); + + if (enable_ecc) { + for (i = PageDataSize; i < PageSize - + spareSkipBytes; i++) + page_main_spare[i] = page_main_spare[i + + spareSkipBytes]; + + for (j = 0; + j < DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + + for (i = 0; i < eccSectorSize; i++) + read_data_l[eccSectorSize * j + + i] = + page_main_spare[ + (eccSectorSize + + eccBytes) * j + i]; + + for (i = 0; i < eccBytes; i++) + read_data_l[PageDataSize + + spareFlagBytes + + eccBytes * j + i] = + page_main_spare[ + (eccSectorSize + + eccBytes) * j + + eccSectorSize + i]; + } + + for (i = 0; i < spareFlagBytes; i++) + read_data_l[PageDataSize + i] = + page_main_spare[(eccSectorSize + + eccBytes) * j + i]; + } else { + for (i = 0; i < (PageDataSize + PageSpareSize); + i++) + read_data_l[i] = page_main_spare[i]; + + } + + if (enable_ecc) { + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR | + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + } + } + + page++; + page_count--; + read_data_l += PageSize; + } + } + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + return status; +} + +u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, + u16 page, u16 page_count) +{ + u16 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + /* Fill the mrst_nand_info structure */ + info.state = INT_PIPELINE_WRITE_AHEAD; + info.write_data = write_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +/* Un-tested function */ +u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + u16 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u16 status2 = PASS; + u32 t; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); + + while (1) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + status = PASS; + if (status2 == FAIL) + status = FAIL; + break; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) { + status2 = FAIL; + status = FAIL; + t = ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL; + iowrite32(t, FlashReg + intr_status); + } else { + iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + MULTIPLANE_OPERATION); + + return status; +} + + +#if CMD_DMA +static irqreturn_t cdma_isr(int irq, void *dev_id) +{ + struct mrst_nand_info *dev = dev_id; + int first_failed_cmd; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!is_cdma_interrupt()) + return IRQ_NONE; + + /* Disable controller interrupts */ + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + GLOB_FTL_Event_Status(&first_failed_cmd); + complete(&dev->complete); + + return IRQ_HANDLED; +} +#else +static void handle_nand_int_read(struct mrst_nand_info *dev) +{ + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 intr_status; + u32 ecc_done_OR_dma_comp = 0; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev->ret = PASS; + intr_status = intr_status_addresses[dev->flash_bank]; + + while (1) { + if (enable_ecc) { + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + dev->ret = do_ecc_new(dev->flash_bank, + dev->read_data, + dev->block, dev->page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + if (1 == ecc_done_OR_dma_comp) + break; + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + if (1 == ecc_done_OR_dma_comp) + break; + ecc_done_OR_dma_comp = 1; + } + } else { + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } else { + printk(KERN_ERR "Illegal INTS " + "(offset addr 0x%x) value: 0x%x\n", + intr_status, + ioread32(FlashReg + intr_status)); + } + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } +} + +static void handle_nand_int_write(struct mrst_nand_info *dev) +{ + u32 intr_status; + u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + int status = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev->ret = PASS; + intr_status = intr[dev->flash_bank]; + + while (1) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + if (FAIL == status) + dev->ret = FAIL; + break; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) { + status = FAIL; + iowrite32(INTR_STATUS0__PROGRAM_FAIL, + FlashReg + intr_status); + } else { + iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } + } +} + +static irqreturn_t ddma_isr(int irq, void *dev_id) +{ + struct mrst_nand_info *dev = dev_id; + u32 int_mask, ints0, ints1, ints2, ints3, ints_offset; + u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + + int_mask = INTR_STATUS0__DMA_CMD_COMP | + INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL; + + ints0 = ioread32(FlashReg + INTR_STATUS0); + ints1 = ioread32(FlashReg + INTR_STATUS1); + ints2 = ioread32(FlashReg + INTR_STATUS2); + ints3 = ioread32(FlashReg + INTR_STATUS3); + + ints_offset = intr[dev->flash_bank]; + + nand_dbg_print(NAND_DBG_DEBUG, + "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, " + "DMA_INTR: 0x%x, " + "dev->state: 0x%x, dev->flash_bank: %d\n", + ints0, ints1, ints2, ints3, + ioread32(FlashReg + DMA_INTR), + dev->state, dev->flash_bank); + + if (!(ioread32(FlashReg + ints_offset) & int_mask)) { + iowrite32(ints0, FlashReg + INTR_STATUS0); + iowrite32(ints1, FlashReg + INTR_STATUS1); + iowrite32(ints2, FlashReg + INTR_STATUS2); + iowrite32(ints3, FlashReg + INTR_STATUS3); + nand_dbg_print(NAND_DBG_WARN, + "ddma_isr: Invalid interrupt for NAND controller. " + "Ignore it\n"); + return IRQ_NONE; + } + + switch (dev->state) { + case INT_READ_PAGE_MAIN: + case INT_PIPELINE_READ_AHEAD: + /* Disable controller interrupts */ + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + handle_nand_int_read(dev); + break; + case INT_WRITE_PAGE_MAIN: + case INT_PIPELINE_WRITE_AHEAD: + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + handle_nand_int_write(dev); + break; + default: + printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n", + dev->state); + return IRQ_NONE; + } + + dev->state = INT_IDLE_STATE; + complete(&dev->complete); + return IRQ_HANDLED; +} +#endif + +static const struct pci_device_id nand_pci_ids[] = { + { + .vendor = 0x8086, + .device = 0x0809, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { /* end: all zeroes */ } +}; + +static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret = -ENODEV; + unsigned long csr_base; + unsigned long csr_len; + struct mrst_nand_info *pndev = &info; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ret = pci_enable_device(dev); + if (ret) { + printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); + return ret; + } + + pci_set_master(dev); + pndev->dev = dev; + + csr_base = pci_resource_start(dev, 0); + if (!csr_base) { + printk(KERN_ERR "Spectra: pci_resource_start failed!\n"); + return -ENODEV; + } + + csr_len = pci_resource_len(dev, 0); + if (!csr_len) { + printk(KERN_ERR "Spectra: pci_resource_len failed!\n"); + return -ENODEV; + } + + ret = pci_request_regions(dev, SPECTRA_NAND_NAME); + if (ret) { + printk(KERN_ERR "Spectra: Unable to request " + "memory region\n"); + goto failed_req_csr; + } + + pndev->ioaddr = ioremap_nocache(csr_base, csr_len); + if (!pndev->ioaddr) { + printk(KERN_ERR "Spectra: Unable to remap memory region\n"); + ret = -ENOMEM; + goto failed_remap_csr; + } + nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n", + csr_base, pndev->ioaddr, csr_len); + + init_completion(&pndev->complete); + nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq); + +#if CMD_DMA + if (request_irq(dev->irq, cdma_isr, IRQF_SHARED, + SPECTRA_NAND_NAME, &info)) { + printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); + ret = -ENODEV; + iounmap(pndev->ioaddr); + goto failed_remap_csr; + } +#else + if (request_irq(dev->irq, ddma_isr, IRQF_SHARED, + SPECTRA_NAND_NAME, &info)) { + printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); + ret = -ENODEV; + iounmap(pndev->ioaddr); + goto failed_remap_csr; + } +#endif + + pci_set_drvdata(dev, pndev); + + return 0; + +failed_remap_csr: + pci_release_regions(dev); +failed_req_csr: + + return ret; +} + +static void nand_pci_remove(struct pci_dev *dev) +{ + struct mrst_nand_info *pndev = pci_get_drvdata(dev); + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#if CMD_DMA + free_irq(dev->irq, pndev); +#endif + iounmap(pndev->ioaddr); + pci_release_regions(dev); + pci_disable_device(dev); +} + +MODULE_DEVICE_TABLE(pci, nand_pci_ids); + +static struct pci_driver nand_pci_driver = { + .name = SPECTRA_NAND_NAME, + .id_table = nand_pci_ids, + .probe = nand_pci_probe, + .remove = nand_pci_remove, +}; + +int NAND_Flash_Init(void) +{ + int retval; + u32 int_mask; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE, + GLOB_HWCTL_REG_SIZE); + if (!FlashReg) { + printk(KERN_ERR "Spectra: ioremap_nocache failed!"); + return -ENOMEM; + } + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Remapped reg base address: " + "0x%p, len: %d\n", + FlashReg, GLOB_HWCTL_REG_SIZE); + + FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE, + GLOB_HWCTL_MEM_SIZE); + if (!FlashMem) { + printk(KERN_ERR "Spectra: ioremap_nocache failed!"); + iounmap(FlashReg); + return -ENOMEM; + } + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Remapped flash base address: " + "0x%p, len: %d\n", + (void *)FlashMem, GLOB_HWCTL_MEM_SIZE); + + nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" + "acc_clks: %d, re_2_we: %d, we_2_re: %d," + "addr_2_data: %d, rdwr_en_lo_cnt: %d, " + "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", + ioread32(FlashReg + ACC_CLKS), + ioread32(FlashReg + RE_2_WE), + ioread32(FlashReg + WE_2_RE), + ioread32(FlashReg + ADDR_2_DATA), + ioread32(FlashReg + RDWR_EN_LO_CNT), + ioread32(FlashReg + RDWR_EN_HI_CNT), + ioread32(FlashReg + CS_SETUP_CNT)); + + NAND_Flash_Reset(); + + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + +#if CMD_DMA + info.pcmds_num = 0; + info.flash_bank = 0; + info.cdma_num = 0; + int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | + DMA_INTR__DESC_COMP_CHANNEL1 | + DMA_INTR__DESC_COMP_CHANNEL2 | + DMA_INTR__DESC_COMP_CHANNEL3 | + DMA_INTR__MEMCOPY_DESC_COMP); + iowrite32(int_mask, FlashReg + DMA_INTR_EN); + iowrite32(0xFFFF, FlashReg + DMA_INTR); + + int_mask = (INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL); +#else + int_mask = INTR_STATUS0__DMA_CMD_COMP | + INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL; +#endif + iowrite32(int_mask, FlashReg + INTR_EN0); + iowrite32(int_mask, FlashReg + INTR_EN1); + iowrite32(int_mask, FlashReg + INTR_EN2); + iowrite32(int_mask, FlashReg + INTR_EN3); + + /* Clear all status bits */ + iowrite32(0xFFFF, FlashReg + INTR_STATUS0); + iowrite32(0xFFFF, FlashReg + INTR_STATUS1); + iowrite32(0xFFFF, FlashReg + INTR_STATUS2); + iowrite32(0xFFFF, FlashReg + INTR_STATUS3); + + iowrite32(0x0F, FlashReg + RB_PIN_ENABLED); + iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE); + + /* Should set value for these registers when init */ + iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES); + iowrite32(1, FlashReg + ECC_ENABLE); + enable_ecc = 1; + + retval = pci_register_driver(&nand_pci_driver); + if (retval) + return -ENOMEM; + + return PASS; +} + +/* Free memory */ +int nand_release(void) +{ + pci_unregister_driver(&nand_pci_driver); + iounmap(FlashMem); + iounmap(FlashReg); + + return 0; +} + + + diff --git a/drivers/block/spectra/lld_nand.h b/drivers/block/spectra/lld_nand.h new file mode 100644 index 000000000000..c7d62c5151c7 --- /dev/null +++ b/drivers/block/spectra/lld_nand.h @@ -0,0 +1,131 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_NAND_ +#define _LLD_NAND_ + +#ifdef ELDORA +#include "defs.h" +#else +#include "flash.h" +#include "ffsport.h" +#endif + +#define MODE_00 0x00000000 +#define MODE_01 0x04000000 +#define MODE_10 0x08000000 +#define MODE_11 0x0C000000 + + +#define DATA_TRANSFER_MODE 0 +#define PROTECTION_PER_BLOCK 1 +#define LOAD_WAIT_COUNT 2 +#define PROGRAM_WAIT_COUNT 3 +#define ERASE_WAIT_COUNT 4 +#define INT_MONITOR_CYCLE_COUNT 5 +#define READ_BUSY_PIN_ENABLED 6 +#define MULTIPLANE_OPERATION_SUPPORT 7 +#define PRE_FETCH_MODE 8 +#define CE_DONT_CARE_SUPPORT 9 +#define COPYBACK_SUPPORT 10 +#define CACHE_WRITE_SUPPORT 11 +#define CACHE_READ_SUPPORT 12 +#define NUM_PAGES_IN_BLOCK 13 +#define ECC_ENABLE_SELECT 14 +#define WRITE_ENABLE_2_READ_ENABLE 15 +#define ADDRESS_2_DATA 16 +#define READ_ENABLE_2_WRITE_ENABLE 17 +#define TWO_ROW_ADDRESS_CYCLES 18 +#define MULTIPLANE_ADDRESS_RESTRICT 19 +#define ACC_CLOCKS 20 +#define READ_WRITE_ENABLE_LOW_COUNT 21 +#define READ_WRITE_ENABLE_HIGH_COUNT 22 + +#define ECC_SECTOR_SIZE 512 +#define LLD_MAX_FLASH_BANKS 4 + +struct mrst_nand_info { + struct pci_dev *dev; + u32 state; + u32 flash_bank; + u8 *read_data; + u8 *write_data; + u32 block; + u16 page; + u32 use_dma; + void __iomem *ioaddr; /* Mapped io reg base address */ + int ret; + u32 pcmds_num; + struct pending_cmd *pcmds; + int cdma_num; /* CDMA descriptor number in this chan */ + u8 *cdma_desc_buf; /* CDMA descriptor table */ + u8 *memcp_desc_buf; /* Memory copy descriptor table */ + dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */ + dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */ + struct completion complete; +}; + +int NAND_Flash_Init(void); +int nand_release(void); +u16 NAND_Flash_Reset(void); +u16 NAND_Read_Device_ID(void); +u16 NAND_Erase_Block(u32 flash_add); +u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_UnlockArrayAll(void); +u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 page, u16 page_count); +u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE); +u16 NAND_Get_Bad_Block(u32 block); +u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, + u16 page, u16 page_count); +u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, + u16 page_count); +void NAND_ECC_Ctrl(int enable); +u16 NAND_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); +u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); +void Conv_Spare_Data_Log2Phy_Format(u8 *data); +void Conv_Spare_Data_Phy2Log_Format(u8 *data); +void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count); +void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count); + +extern void __iomem *FlashReg; +extern void __iomem *FlashMem; + +extern int totalUsedBanks; +extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; + +#endif /*_LLD_NAND_*/ + + + diff --git a/drivers/block/spectra/nand_regs.h b/drivers/block/spectra/nand_regs.h new file mode 100644 index 000000000000..e192e4ae8c1e --- /dev/null +++ b/drivers/block/spectra/nand_regs.h @@ -0,0 +1,619 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#define DEVICE_RESET 0x0 +#define DEVICE_RESET__BANK0 0x0001 +#define DEVICE_RESET__BANK1 0x0002 +#define DEVICE_RESET__BANK2 0x0004 +#define DEVICE_RESET__BANK3 0x0008 + +#define TRANSFER_SPARE_REG 0x10 +#define TRANSFER_SPARE_REG__FLAG 0x0001 + +#define LOAD_WAIT_CNT 0x20 +#define LOAD_WAIT_CNT__VALUE 0xffff + +#define PROGRAM_WAIT_CNT 0x30 +#define PROGRAM_WAIT_CNT__VALUE 0xffff + +#define ERASE_WAIT_CNT 0x40 +#define ERASE_WAIT_CNT__VALUE 0xffff + +#define INT_MON_CYCCNT 0x50 +#define INT_MON_CYCCNT__VALUE 0xffff + +#define RB_PIN_ENABLED 0x60 +#define RB_PIN_ENABLED__BANK0 0x0001 +#define RB_PIN_ENABLED__BANK1 0x0002 +#define RB_PIN_ENABLED__BANK2 0x0004 +#define RB_PIN_ENABLED__BANK3 0x0008 + +#define MULTIPLANE_OPERATION 0x70 +#define MULTIPLANE_OPERATION__FLAG 0x0001 + +#define MULTIPLANE_READ_ENABLE 0x80 +#define MULTIPLANE_READ_ENABLE__FLAG 0x0001 + +#define COPYBACK_DISABLE 0x90 +#define COPYBACK_DISABLE__FLAG 0x0001 + +#define CACHE_WRITE_ENABLE 0xa0 +#define CACHE_WRITE_ENABLE__FLAG 0x0001 + +#define CACHE_READ_ENABLE 0xb0 +#define CACHE_READ_ENABLE__FLAG 0x0001 + +#define PREFETCH_MODE 0xc0 +#define PREFETCH_MODE__PREFETCH_EN 0x0001 +#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0 + +#define CHIP_ENABLE_DONT_CARE 0xd0 +#define CHIP_EN_DONT_CARE__FLAG 0x01 + +#define ECC_ENABLE 0xe0 +#define ECC_ENABLE__FLAG 0x0001 + +#define GLOBAL_INT_ENABLE 0xf0 +#define GLOBAL_INT_EN_FLAG 0x01 + +#define WE_2_RE 0x100 +#define WE_2_RE__VALUE 0x003f + +#define ADDR_2_DATA 0x110 +#define ADDR_2_DATA__VALUE 0x003f + +#define RE_2_WE 0x120 +#define RE_2_WE__VALUE 0x003f + +#define ACC_CLKS 0x130 +#define ACC_CLKS__VALUE 0x000f + +#define NUMBER_OF_PLANES 0x140 +#define NUMBER_OF_PLANES__VALUE 0x0007 + +#define PAGES_PER_BLOCK 0x150 +#define PAGES_PER_BLOCK__VALUE 0xffff + +#define DEVICE_WIDTH 0x160 +#define DEVICE_WIDTH__VALUE 0x0003 + +#define DEVICE_MAIN_AREA_SIZE 0x170 +#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff + +#define DEVICE_SPARE_AREA_SIZE 0x180 +#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff + +#define TWO_ROW_ADDR_CYCLES 0x190 +#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001 + +#define MULTIPLANE_ADDR_RESTRICT 0x1a0 +#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001 + +#define ECC_CORRECTION 0x1b0 +#define ECC_CORRECTION__VALUE 0x001f + +#define READ_MODE 0x1c0 +#define READ_MODE__VALUE 0x000f + +#define WRITE_MODE 0x1d0 +#define WRITE_MODE__VALUE 0x000f + +#define COPYBACK_MODE 0x1e0 +#define COPYBACK_MODE__VALUE 0x000f + +#define RDWR_EN_LO_CNT 0x1f0 +#define RDWR_EN_LO_CNT__VALUE 0x001f + +#define RDWR_EN_HI_CNT 0x200 +#define RDWR_EN_HI_CNT__VALUE 0x001f + +#define MAX_RD_DELAY 0x210 +#define MAX_RD_DELAY__VALUE 0x000f + +#define CS_SETUP_CNT 0x220 +#define CS_SETUP_CNT__VALUE 0x001f + +#define SPARE_AREA_SKIP_BYTES 0x230 +#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f + +#define SPARE_AREA_MARKER 0x240 +#define SPARE_AREA_MARKER__VALUE 0xffff + +#define DEVICES_CONNECTED 0x250 +#define DEVICES_CONNECTED__VALUE 0x0007 + +#define DIE_MASK 0x260 +#define DIE_MASK__VALUE 0x00ff + +#define FIRST_BLOCK_OF_NEXT_PLANE 0x270 +#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff + +#define WRITE_PROTECT 0x280 +#define WRITE_PROTECT__FLAG 0x0001 + +#define RE_2_RE 0x290 +#define RE_2_RE__VALUE 0x003f + +#define MANUFACTURER_ID 0x300 +#define MANUFACTURER_ID__VALUE 0x00ff + +#define DEVICE_ID 0x310 +#define DEVICE_ID__VALUE 0x00ff + +#define DEVICE_PARAM_0 0x320 +#define DEVICE_PARAM_0__VALUE 0x00ff + +#define DEVICE_PARAM_1 0x330 +#define DEVICE_PARAM_1__VALUE 0x00ff + +#define DEVICE_PARAM_2 0x340 +#define DEVICE_PARAM_2__VALUE 0x00ff + +#define LOGICAL_PAGE_DATA_SIZE 0x350 +#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff + +#define LOGICAL_PAGE_SPARE_SIZE 0x360 +#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff + +#define REVISION 0x370 +#define REVISION__VALUE 0xffff + +#define ONFI_DEVICE_FEATURES 0x380 +#define ONFI_DEVICE_FEATURES__VALUE 0x003f + +#define ONFI_OPTIONAL_COMMANDS 0x390 +#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f + +#define ONFI_TIMING_MODE 0x3a0 +#define ONFI_TIMING_MODE__VALUE 0x003f + +#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0 +#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f + +#define ONFI_DEVICE_NO_OF_LUNS 0x3c0 +#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff +#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100 + +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0 +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff + +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0 +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff + +#define FEATURES 0x3f0 +#define FEATURES__N_BANKS 0x0003 +#define FEATURES__ECC_MAX_ERR 0x003c +#define FEATURES__DMA 0x0040 +#define FEATURES__CMD_DMA 0x0080 +#define FEATURES__PARTITION 0x0100 +#define FEATURES__XDMA_SIDEBAND 0x0200 +#define FEATURES__GPREG 0x0400 +#define FEATURES__INDEX_ADDR 0x0800 + +#define TRANSFER_MODE 0x400 +#define TRANSFER_MODE__VALUE 0x0003 + +#define INTR_STATUS0 0x410 +#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS0__ECC_ERR 0x0002 +#define INTR_STATUS0__DMA_CMD_COMP 0x0004 +#define INTR_STATUS0__TIME_OUT 0x0008 +#define INTR_STATUS0__PROGRAM_FAIL 0x0010 +#define INTR_STATUS0__ERASE_FAIL 0x0020 +#define INTR_STATUS0__LOAD_COMP 0x0040 +#define INTR_STATUS0__PROGRAM_COMP 0x0080 +#define INTR_STATUS0__ERASE_COMP 0x0100 +#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS0__LOCKED_BLK 0x0400 +#define INTR_STATUS0__UNSUP_CMD 0x0800 +#define INTR_STATUS0__INT_ACT 0x1000 +#define INTR_STATUS0__RST_COMP 0x2000 +#define INTR_STATUS0__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS0__PAGE_XFER_INC 0x8000 + +#define INTR_EN0 0x420 +#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN0__ECC_ERR 0x0002 +#define INTR_EN0__DMA_CMD_COMP 0x0004 +#define INTR_EN0__TIME_OUT 0x0008 +#define INTR_EN0__PROGRAM_FAIL 0x0010 +#define INTR_EN0__ERASE_FAIL 0x0020 +#define INTR_EN0__LOAD_COMP 0x0040 +#define INTR_EN0__PROGRAM_COMP 0x0080 +#define INTR_EN0__ERASE_COMP 0x0100 +#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN0__LOCKED_BLK 0x0400 +#define INTR_EN0__UNSUP_CMD 0x0800 +#define INTR_EN0__INT_ACT 0x1000 +#define INTR_EN0__RST_COMP 0x2000 +#define INTR_EN0__PIPE_CMD_ERR 0x4000 +#define INTR_EN0__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT0 0x430 +#define PAGE_CNT0__VALUE 0x00ff + +#define ERR_PAGE_ADDR0 0x440 +#define ERR_PAGE_ADDR0__VALUE 0xffff + +#define ERR_BLOCK_ADDR0 0x450 +#define ERR_BLOCK_ADDR0__VALUE 0xffff + +#define INTR_STATUS1 0x460 +#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS1__ECC_ERR 0x0002 +#define INTR_STATUS1__DMA_CMD_COMP 0x0004 +#define INTR_STATUS1__TIME_OUT 0x0008 +#define INTR_STATUS1__PROGRAM_FAIL 0x0010 +#define INTR_STATUS1__ERASE_FAIL 0x0020 +#define INTR_STATUS1__LOAD_COMP 0x0040 +#define INTR_STATUS1__PROGRAM_COMP 0x0080 +#define INTR_STATUS1__ERASE_COMP 0x0100 +#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS1__LOCKED_BLK 0x0400 +#define INTR_STATUS1__UNSUP_CMD 0x0800 +#define INTR_STATUS1__INT_ACT 0x1000 +#define INTR_STATUS1__RST_COMP 0x2000 +#define INTR_STATUS1__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS1__PAGE_XFER_INC 0x8000 + +#define INTR_EN1 0x470 +#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN1__ECC_ERR 0x0002 +#define INTR_EN1__DMA_CMD_COMP 0x0004 +#define INTR_EN1__TIME_OUT 0x0008 +#define INTR_EN1__PROGRAM_FAIL 0x0010 +#define INTR_EN1__ERASE_FAIL 0x0020 +#define INTR_EN1__LOAD_COMP 0x0040 +#define INTR_EN1__PROGRAM_COMP 0x0080 +#define INTR_EN1__ERASE_COMP 0x0100 +#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN1__LOCKED_BLK 0x0400 +#define INTR_EN1__UNSUP_CMD 0x0800 +#define INTR_EN1__INT_ACT 0x1000 +#define INTR_EN1__RST_COMP 0x2000 +#define INTR_EN1__PIPE_CMD_ERR 0x4000 +#define INTR_EN1__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT1 0x480 +#define PAGE_CNT1__VALUE 0x00ff + +#define ERR_PAGE_ADDR1 0x490 +#define ERR_PAGE_ADDR1__VALUE 0xffff + +#define ERR_BLOCK_ADDR1 0x4a0 +#define ERR_BLOCK_ADDR1__VALUE 0xffff + +#define INTR_STATUS2 0x4b0 +#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS2__ECC_ERR 0x0002 +#define INTR_STATUS2__DMA_CMD_COMP 0x0004 +#define INTR_STATUS2__TIME_OUT 0x0008 +#define INTR_STATUS2__PROGRAM_FAIL 0x0010 +#define INTR_STATUS2__ERASE_FAIL 0x0020 +#define INTR_STATUS2__LOAD_COMP 0x0040 +#define INTR_STATUS2__PROGRAM_COMP 0x0080 +#define INTR_STATUS2__ERASE_COMP 0x0100 +#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS2__LOCKED_BLK 0x0400 +#define INTR_STATUS2__UNSUP_CMD 0x0800 +#define INTR_STATUS2__INT_ACT 0x1000 +#define INTR_STATUS2__RST_COMP 0x2000 +#define INTR_STATUS2__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS2__PAGE_XFER_INC 0x8000 + +#define INTR_EN2 0x4c0 +#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN2__ECC_ERR 0x0002 +#define INTR_EN2__DMA_CMD_COMP 0x0004 +#define INTR_EN2__TIME_OUT 0x0008 +#define INTR_EN2__PROGRAM_FAIL 0x0010 +#define INTR_EN2__ERASE_FAIL 0x0020 +#define INTR_EN2__LOAD_COMP 0x0040 +#define INTR_EN2__PROGRAM_COMP 0x0080 +#define INTR_EN2__ERASE_COMP 0x0100 +#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN2__LOCKED_BLK 0x0400 +#define INTR_EN2__UNSUP_CMD 0x0800 +#define INTR_EN2__INT_ACT 0x1000 +#define INTR_EN2__RST_COMP 0x2000 +#define INTR_EN2__PIPE_CMD_ERR 0x4000 +#define INTR_EN2__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT2 0x4d0 +#define PAGE_CNT2__VALUE 0x00ff + +#define ERR_PAGE_ADDR2 0x4e0 +#define ERR_PAGE_ADDR2__VALUE 0xffff + +#define ERR_BLOCK_ADDR2 0x4f0 +#define ERR_BLOCK_ADDR2__VALUE 0xffff + +#define INTR_STATUS3 0x500 +#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS3__ECC_ERR 0x0002 +#define INTR_STATUS3__DMA_CMD_COMP 0x0004 +#define INTR_STATUS3__TIME_OUT 0x0008 +#define INTR_STATUS3__PROGRAM_FAIL 0x0010 +#define INTR_STATUS3__ERASE_FAIL 0x0020 +#define INTR_STATUS3__LOAD_COMP 0x0040 +#define INTR_STATUS3__PROGRAM_COMP 0x0080 +#define INTR_STATUS3__ERASE_COMP 0x0100 +#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS3__LOCKED_BLK 0x0400 +#define INTR_STATUS3__UNSUP_CMD 0x0800 +#define INTR_STATUS3__INT_ACT 0x1000 +#define INTR_STATUS3__RST_COMP 0x2000 +#define INTR_STATUS3__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS3__PAGE_XFER_INC 0x8000 + +#define INTR_EN3 0x510 +#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN3__ECC_ERR 0x0002 +#define INTR_EN3__DMA_CMD_COMP 0x0004 +#define INTR_EN3__TIME_OUT 0x0008 +#define INTR_EN3__PROGRAM_FAIL 0x0010 +#define INTR_EN3__ERASE_FAIL 0x0020 +#define INTR_EN3__LOAD_COMP 0x0040 +#define INTR_EN3__PROGRAM_COMP 0x0080 +#define INTR_EN3__ERASE_COMP 0x0100 +#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN3__LOCKED_BLK 0x0400 +#define INTR_EN3__UNSUP_CMD 0x0800 +#define INTR_EN3__INT_ACT 0x1000 +#define INTR_EN3__RST_COMP 0x2000 +#define INTR_EN3__PIPE_CMD_ERR 0x4000 +#define INTR_EN3__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT3 0x520 +#define PAGE_CNT3__VALUE 0x00ff + +#define ERR_PAGE_ADDR3 0x530 +#define ERR_PAGE_ADDR3__VALUE 0xffff + +#define ERR_BLOCK_ADDR3 0x540 +#define ERR_BLOCK_ADDR3__VALUE 0xffff + +#define DATA_INTR 0x550 +#define DATA_INTR__WRITE_SPACE_AV 0x0001 +#define DATA_INTR__READ_DATA_AV 0x0002 + +#define DATA_INTR_EN 0x560 +#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001 +#define DATA_INTR_EN__READ_DATA_AV 0x0002 + +#define GPREG_0 0x570 +#define GPREG_0__VALUE 0xffff + +#define GPREG_1 0x580 +#define GPREG_1__VALUE 0xffff + +#define GPREG_2 0x590 +#define GPREG_2__VALUE 0xffff + +#define GPREG_3 0x5a0 +#define GPREG_3__VALUE 0xffff + +#define ECC_THRESHOLD 0x600 +#define ECC_THRESHOLD__VALUE 0x03ff + +#define ECC_ERROR_BLOCK_ADDRESS 0x610 +#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff + +#define ECC_ERROR_PAGE_ADDRESS 0x620 +#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff +#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000 + +#define ECC_ERROR_ADDRESS 0x630 +#define ECC_ERROR_ADDRESS__OFFSET 0x0fff +#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000 + +#define ERR_CORRECTION_INFO 0x640 +#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff +#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00 +#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000 +#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000 + +#define DMA_ENABLE 0x700 +#define DMA_ENABLE__FLAG 0x0001 + +#define IGNORE_ECC_DONE 0x710 +#define IGNORE_ECC_DONE__FLAG 0x0001 + +#define DMA_INTR 0x720 +#define DMA_INTR__TARGET_ERROR 0x0001 +#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002 +#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004 +#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008 +#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010 +#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 + +#define DMA_INTR_EN 0x730 +#define DMA_INTR_EN__TARGET_ERROR 0x0001 +#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002 +#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004 +#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008 +#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010 +#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020 + +#define TARGET_ERR_ADDR_LO 0x740 +#define TARGET_ERR_ADDR_LO__VALUE 0xffff + +#define TARGET_ERR_ADDR_HI 0x750 +#define TARGET_ERR_ADDR_HI__VALUE 0xffff + +#define CHNL_ACTIVE 0x760 +#define CHNL_ACTIVE__CHANNEL0 0x0001 +#define CHNL_ACTIVE__CHANNEL1 0x0002 +#define CHNL_ACTIVE__CHANNEL2 0x0004 +#define CHNL_ACTIVE__CHANNEL3 0x0008 + +#define ACTIVE_SRC_ID 0x800 +#define ACTIVE_SRC_ID__VALUE 0x00ff + +#define PTN_INTR 0x810 +#define PTN_INTR__CONFIG_ERROR 0x0001 +#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002 +#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004 +#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008 +#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010 +#define PTN_INTR__REG_ACCESS_ERROR 0x0020 + +#define PTN_INTR_EN 0x820 +#define PTN_INTR_EN__CONFIG_ERROR 0x0001 +#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002 +#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004 +#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008 +#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 +#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 + +#define PERM_SRC_ID_0 0x830 +#define PERM_SRC_ID_0__SRCID 0x00ff +#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_0__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_0__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_0 0x840 +#define MIN_BLK_ADDR_0__VALUE 0xffff + +#define MAX_BLK_ADDR_0 0x850 +#define MAX_BLK_ADDR_0__VALUE 0xffff + +#define MIN_MAX_BANK_0 0x860 +#define MIN_MAX_BANK_0__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_0__MAX_VALUE 0x000c + +#define PERM_SRC_ID_1 0x870 +#define PERM_SRC_ID_1__SRCID 0x00ff +#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_1__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_1__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_1 0x880 +#define MIN_BLK_ADDR_1__VALUE 0xffff + +#define MAX_BLK_ADDR_1 0x890 +#define MAX_BLK_ADDR_1__VALUE 0xffff + +#define MIN_MAX_BANK_1 0x8a0 +#define MIN_MAX_BANK_1__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_1__MAX_VALUE 0x000c + +#define PERM_SRC_ID_2 0x8b0 +#define PERM_SRC_ID_2__SRCID 0x00ff +#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_2__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_2__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_2 0x8c0 +#define MIN_BLK_ADDR_2__VALUE 0xffff + +#define MAX_BLK_ADDR_2 0x8d0 +#define MAX_BLK_ADDR_2__VALUE 0xffff + +#define MIN_MAX_BANK_2 0x8e0 +#define MIN_MAX_BANK_2__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_2__MAX_VALUE 0x000c + +#define PERM_SRC_ID_3 0x8f0 +#define PERM_SRC_ID_3__SRCID 0x00ff +#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_3__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_3__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_3 0x900 +#define MIN_BLK_ADDR_3__VALUE 0xffff + +#define MAX_BLK_ADDR_3 0x910 +#define MAX_BLK_ADDR_3__VALUE 0xffff + +#define MIN_MAX_BANK_3 0x920 +#define MIN_MAX_BANK_3__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_3__MAX_VALUE 0x000c + +#define PERM_SRC_ID_4 0x930 +#define PERM_SRC_ID_4__SRCID 0x00ff +#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_4__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_4__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_4 0x940 +#define MIN_BLK_ADDR_4__VALUE 0xffff + +#define MAX_BLK_ADDR_4 0x950 +#define MAX_BLK_ADDR_4__VALUE 0xffff + +#define MIN_MAX_BANK_4 0x960 +#define MIN_MAX_BANK_4__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_4__MAX_VALUE 0x000c + +#define PERM_SRC_ID_5 0x970 +#define PERM_SRC_ID_5__SRCID 0x00ff +#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_5__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_5__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_5 0x980 +#define MIN_BLK_ADDR_5__VALUE 0xffff + +#define MAX_BLK_ADDR_5 0x990 +#define MAX_BLK_ADDR_5__VALUE 0xffff + +#define MIN_MAX_BANK_5 0x9a0 +#define MIN_MAX_BANK_5__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_5__MAX_VALUE 0x000c + +#define PERM_SRC_ID_6 0x9b0 +#define PERM_SRC_ID_6__SRCID 0x00ff +#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_6__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_6__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_6 0x9c0 +#define MIN_BLK_ADDR_6__VALUE 0xffff + +#define MAX_BLK_ADDR_6 0x9d0 +#define MAX_BLK_ADDR_6__VALUE 0xffff + +#define MIN_MAX_BANK_6 0x9e0 +#define MIN_MAX_BANK_6__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_6__MAX_VALUE 0x000c + +#define PERM_SRC_ID_7 0x9f0 +#define PERM_SRC_ID_7__SRCID 0x00ff +#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_7__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_7__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_7 0xa00 +#define MIN_BLK_ADDR_7__VALUE 0xffff + +#define MAX_BLK_ADDR_7 0xa10 +#define MAX_BLK_ADDR_7__VALUE 0xffff + +#define MIN_MAX_BANK_7 0xa20 +#define MIN_MAX_BANK_7__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_7__MAX_VALUE 0x000c diff --git a/drivers/block/spectra/spectraswconfig.h b/drivers/block/spectra/spectraswconfig.h new file mode 100644 index 000000000000..b630f0651b31 --- /dev/null +++ b/drivers/block/spectra/spectraswconfig.h @@ -0,0 +1,81 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _SPECTRASWCONFIG_ +#define _SPECTRASWCONFIG_ + +/* NAND driver version */ +#define GLOB_VERSION "driver version 20100311" + + +/***** Common Parameters *****/ +#define RETRY_TIMES 3 + +#define READ_BADBLOCK_INFO 1 +#define READBACK_VERIFY 0 +#define AUTO_FORMAT_FLASH 0 + +/***** Cache Parameters *****/ +#define CACHE_ITEM_NUM 128 +#define BLK_NUM_FOR_L2_CACHE 16 + +/***** Block Table Parameters *****/ +#define BLOCK_TABLE_INDEX 0 + +/***** Wear Leveling Parameters *****/ +#define WEAR_LEVELING_GATE 0x10 +#define WEAR_LEVELING_BLOCK_NUM 10 + +#define DEBUG_BNDRY 0 + +/***** Product Feature Support *****/ +#define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) +#define FLASH_NAND defined(CONFIG_MRST_NAND_HW) +#define CMD_DMA 0 + +#define SPECTRA_PARTITION_ID 0 + +/* Enable this macro if the number of flash blocks is larger than 16K. */ +#define SUPPORT_LARGE_BLOCKNUM 1 + +/**** Block Table and Reserved Block Parameters *****/ +#define SPECTRA_START_BLOCK 3 +//#define NUM_FREE_BLOCKS_GATE 30 +#define NUM_FREE_BLOCKS_GATE 60 + +/**** Hardware Parameters ****/ +#define GLOB_HWCTL_REG_BASE 0xFFA40000 +#define GLOB_HWCTL_REG_SIZE 4096 + +#define GLOB_HWCTL_MEM_BASE 0xFFA48000 +#define GLOB_HWCTL_MEM_SIZE 4096 + +/* KBV - Updated to LNW scratch register address */ +#define SCRATCH_REG_ADDR 0xFF108018 +#define SCRATCH_REG_SIZE 64 + +#define GLOB_HWCTL_DEFAULT_BLKS 2048 + +#define SUPPORT_15BITECC 1 +#define SUPPORT_8BITECC 1 + +#define ONFI_BLOOM_TIME 0 +#define MODE5_WORKAROUND 1 + +#endif /*_SPECTRASWCONFIG_*/ -- cgit v1.2.3 From 90d598285cd1d2cee38ad34dbb3b305816a986aa Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 6 Oct 2009 14:23:59 +0100 Subject: spectra: Make it build as a module ... by killing the gratuitous 'res_nand' early_param() and turning it into a module_param() called 'reserved_mb' instead. Signed-off-by: David Woodhouse --- drivers/block/spectra/ffsport.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/block/spectra/ffsport.c b/drivers/block/spectra/ffsport.c index 0b3d49d2f8a5..c53face1816c 100644 --- a/drivers/block/spectra/ffsport.c +++ b/drivers/block/spectra/ffsport.c @@ -126,7 +126,9 @@ u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) #define GLOB_SBD_IOCTL_WRITE_DATA (0x7709) #define GLOB_SBD_IOCTL_READ_DATA (0x770A) -static u32 reserved_mb_for_os_image = 0; +static int reserved_mb = 0; +module_param(reserved_mb, int, 0); +MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)"); int nand_debug_level; module_param(nand_debug_level, int, 0644); @@ -262,7 +264,7 @@ static int get_res_blk_num_os(void) blk_size = IdentifyDeviceData.PageDataSize * IdentifyDeviceData.PagesPerBlock; - res_blks = (reserved_mb_for_os_image * 1024 * 1024) / blk_size; + res_blks = (reserved_mb * 1024 * 1024) / blk_size; if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum)) res_blks = 1; /* Reserved 1 block for block table */ @@ -823,25 +825,5 @@ static void __exit GLOB_SBD_exit(void) GLOB_SBD_majornum); } -static int __init setup_reserve_space_for_os_image(char *cmdline) -{ - unsigned long value; - int error; - - printk(KERN_ALERT "Spectra - cmdline: %s\n", cmdline); - if (!cmdline) - return -EINVAL; - - error = strict_strtoul((const char *)cmdline, 10, &value); - if (error) - return -EINVAL; - - reserved_mb_for_os_image = value; - - return 0; -} - -early_param("res_nand", setup_reserve_space_for_os_image); - module_init(GLOB_SBD_init); module_exit(GLOB_SBD_exit); -- cgit v1.2.3 From 4087524f3924c64791fab469b731f4e7420797a2 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 6 Oct 2009 15:08:29 +0100 Subject: spectra: Clean up emulation vs. hardware backend support Only build the parts which are actually needed, and turn the DMA support (which is currently hard-coded off) into a config option (still forced off). Signed-off-by: David Woodhouse --- drivers/block/spectra/Kconfig | 6 ++++++ drivers/block/spectra/Makefile | 5 ++++- drivers/block/spectra/lld.c | 2 ++ drivers/block/spectra/spectraswconfig.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/spectra/Kconfig b/drivers/block/spectra/Kconfig index fbece109f6c6..dae951e96e6b 100644 --- a/drivers/block/spectra/Kconfig +++ b/drivers/block/spectra/Kconfig @@ -25,3 +25,9 @@ config MRST_NAND_EMU endchoice +config MRST_NAND_HW_DMA + bool + default n + depends on MRST_NAND_HW + help + Use DMA for native hardware interface. diff --git a/drivers/block/spectra/Makefile b/drivers/block/spectra/Makefile index 261891c23577..8f5e0179250f 100644 --- a/drivers/block/spectra/Makefile +++ b/drivers/block/spectra/Makefile @@ -3,5 +3,8 @@ # obj-$(CONFIG_MRST_NAND) += spectra.o -spectra-objs := ffsport.o flash.o lld.o lld_emu.o lld_nand.o lld_cdma.o +spectra-y := ffsport.o flash.o lld.o +spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o +spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o +spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c index 3f411af4405e..c9a311213aff 100644 --- a/drivers/block/spectra/lld.c +++ b/drivers/block/spectra/lld.c @@ -199,6 +199,7 @@ u16 GLOB_LLD_Get_Bad_Block(u32 block) return NAND_Get_Bad_Block(block); } +#if CMD_DMA u16 GLOB_LLD_Event_Status(void) { return CDMA_Event_Status(); @@ -251,6 +252,7 @@ u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, LLD_CMD_FLAG_MODE_CDMA); } +#endif /* CMD_DMA */ #endif /* FLASH_NAND */ /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ diff --git a/drivers/block/spectra/spectraswconfig.h b/drivers/block/spectra/spectraswconfig.h index b630f0651b31..1e6afd372fe4 100644 --- a/drivers/block/spectra/spectraswconfig.h +++ b/drivers/block/spectra/spectraswconfig.h @@ -47,7 +47,7 @@ /***** Product Feature Support *****/ #define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) #define FLASH_NAND defined(CONFIG_MRST_NAND_HW) -#define CMD_DMA 0 +#define CMD_DMA defined(CONFIG_MRST_NAND_HW_DMA) #define SPECTRA_PARTITION_ID 0 -- cgit v1.2.3 From 44fa63fc230a3ab3b34c669cf07ae6c487087952 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 14 Oct 2009 23:07:01 +0100 Subject: spectra: Don't overwrite nand_debug_level. It's a module param Signed-off-by: David Woodhouse --- drivers/block/spectra/ffsport.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/spectra/ffsport.c b/drivers/block/spectra/ffsport.c index c53face1816c..3c3565d40545 100644 --- a/drivers/block/spectra/ffsport.c +++ b/drivers/block/spectra/ffsport.c @@ -729,8 +729,6 @@ static int GLOB_SBD_init(void) int i; /* Set debug output level (0~3) here. 3 is most verbose */ - nand_debug_level = 0; - printk(KERN_ALERT "Spectra: %s\n", GLOB_version); mutex_init(&spectra_lock); -- cgit v1.2.3 From b589aece500c16fdcfff74346efc0d4caf7ba968 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 14 Oct 2009 23:09:13 +0100 Subject: spectra: Add basic mtd support Signed-off-by: David Woodhouse --- drivers/block/spectra/Kconfig | 7 + drivers/block/spectra/Makefile | 1 + drivers/block/spectra/lld.c | 79 ++++ drivers/block/spectra/lld_mtd.c | 684 ++++++++++++++++++++++++++++++++ drivers/block/spectra/lld_mtd.h | 51 +++ drivers/block/spectra/spectraswconfig.h | 1 + 6 files changed, 823 insertions(+) create mode 100644 drivers/block/spectra/lld_mtd.c create mode 100644 drivers/block/spectra/lld_mtd.h (limited to 'drivers') diff --git a/drivers/block/spectra/Kconfig b/drivers/block/spectra/Kconfig index dae951e96e6b..4bed96f68837 100644 --- a/drivers/block/spectra/Kconfig +++ b/drivers/block/spectra/Kconfig @@ -18,6 +18,13 @@ config MRST_NAND_HW Driver communicates with the actual hardware's register interface. in DMA mode. +config MRST_NAND_MTD + bool "Linux MTD mode" + depends on MTD + help + Driver communicates with the kernel MTD subsystem instead of its own + built-in hardware driver. + config MRST_NAND_EMU bool "RAM emulator testing" help diff --git a/drivers/block/spectra/Makefile b/drivers/block/spectra/Makefile index 8f5e0179250f..2a9490385339 100644 --- a/drivers/block/spectra/Makefile +++ b/drivers/block/spectra/Makefile @@ -7,4 +7,5 @@ spectra-y := ffsport.o flash.o lld.o spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o +spectra-$(CONFIG_MRST_NAND_MTD) += lld_mtd.o diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c index c9a311213aff..ac25eea1a2aa 100644 --- a/drivers/block/spectra/lld.c +++ b/drivers/block/spectra/lld.c @@ -103,6 +103,85 @@ u16 GLOB_LLD_Get_Bad_Block(u32 block) #endif /* FLASH_EMU */ +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */ +#include "lld_mtd.h" +#include "lld_cdma.h" + +/* common functions: */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return mtd_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return mtd_Read_Device_ID(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return mtd_Flash_Release(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return mtd_Flash_Init(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return mtd_Erase_Block(block_add); +} + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Read_Page_Main(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return mtd_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 Page, u16 PageCount) +{ + return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return mtd_Get_Bad_Block(block); +} + +#endif /* FLASH_MTD */ /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ #if FLASH_NAND /* vector all the LLD calls to the NAND controller code */ diff --git a/drivers/block/spectra/lld_mtd.c b/drivers/block/spectra/lld_mtd.c new file mode 100644 index 000000000000..f5666a9792b5 --- /dev/null +++ b/drivers/block/spectra/lld_mtd.c @@ -0,0 +1,684 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include "flash.h" +#include "ffsdefs.h" +#include "lld_emu.h" +#include "lld.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define GLOB_LLD_PAGES 64 +#define GLOB_LLD_PAGE_SIZE (512+16) +#define GLOB_LLD_PAGE_DATA_SIZE 512 +#define GLOB_LLD_BLOCKS 2048 + +#if CMD_DMA +#include "lld_cdma.h" +u32 totalUsedBanks; +u32 valid_banks[MAX_CHANS]; +#endif + +static struct mtd_info *spectra_mtd; +static int mtddev = -1; +module_param(mtddev, int, 0); + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Init +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Creates & initializes the flash RAM array. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Flash_Init(void) +{ + if (mtddev == -1) { + printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n"); + return FAIL; + } + + spectra_mtd = get_mtd_device(NULL, mtddev); + if (!spectra_mtd) { + printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev); + return FAIL; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Release +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Releases the flash. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int mtd_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + if (!spectra_mtd) + return PASS; + + put_mtd_device(spectra_mtd); + spectra_mtd = NULL; + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Device_ID +* Inputs: none +* Outputs: PASS=1 FAIL=0 +* Description: Reads the info from the controller registers. +* Sets up DeviceInfo structure with device parameters +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +u16 mtd_Read_Device_ID(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!spectra_mtd) + return FAIL; + + DeviceInfo.wDeviceMaker = 0; + DeviceInfo.wDeviceType = 8; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + DeviceInfo.wTotalBlocks = spectra_mtd->size / spectra_mtd->erasesize; + DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; + DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; + DeviceInfo.wPageDataSize = spectra_mtd->writesize; + DeviceInfo.wPageSpareSize = spectra_mtd->oobsize; + DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + + 1); + DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK; + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + +#if CMD_DMA + totalUsedBanks = 4; + valid_banks[0] = 1; + valid_banks[1] = 1; + valid_banks[2] = 1; + valid_banks[3] = 1; +#endif + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Reset +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Reset the flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Flash_Reset(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +void erase_callback(struct erase_info *e) +{ + complete((void *)e->priv); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Erase_Block +* Inputs: Address +* Outputs: PASS=0 (notice 0=ok here) +* Description: Erase a block +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Erase_Block(u32 block_add) +{ + struct erase_info erase; + DECLARE_COMPLETION_ONSTACK(comp); + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (block_add >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "mtd_Erase_Block error! " + "Too big block address: %d\n", block_add); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", + (int)block_add); + + erase.mtd = spectra_mtd; + erase.callback = erase_callback; + erase.addr = block_add * spectra_mtd->erasesize; + erase.len = spectra_mtd->erasesize; + erase.priv = (unsigned long)∁ + + ret = spectra_mtd->erase(spectra_mtd, &erase); + if (!ret) { + wait_for_completion(&comp); + if (erase.state != MTD_ERASE_DONE) + ret = -EIO; + } + if (ret) { + printk(KERN_WARNING "mtd_Erase_Block error! " + "erase of region [0x%llx, 0x%llx] failed\n", + erase.addr, erase.len); + return FAIL; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Main +* Inputs: Write buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the data in the buffer to main area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + size_t retlen; + int ret = 0; + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + + while (PageCount) { + ret = spectra_mtd->write(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + DeviceInfo.wPageDataSize, &retlen, write_data); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + write_data += DeviceInfo.wPageDataSize; + Page++; + PageCount--; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Main +* Inputs: Read buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read the data from the flash main area to the buffer +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + size_t retlen; + int ret = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + + while (PageCount) { + ret = spectra_mtd->read(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + DeviceInfo.wPageDataSize, &retlen, read_data); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + read_data += DeviceInfo.wPageDataSize; + Page++; + PageCount--; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +#ifndef ELDORA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Main_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read from flash main+spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Page number %d+%d too big in block %d\n", + Page, PageCount, Block); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)PageCount, + (unsigned int)Block, (unsigned int)Page); + + + while (PageCount) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = read_data; + ops.len = DeviceInfo.wPageDataSize; + ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->read_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + read_data += DeviceInfo.wPageSize; + Page++; + PageCount--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Main_Spare +* Inputs: Write buffer +* address +* buffer length +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer to main+spare area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 page_count) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + page_count > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Page number %d+%d too big in block %d\n", + Page, page_count, Block); + WARN_ON(1); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)page_count, + (unsigned int)Block, (unsigned int)Page); + + while (page_count) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = write_data; + ops.len = DeviceInfo.wPageDataSize; + ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->write_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + write_data += DeviceInfo.wPageSize; + Page++; + page_count--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Spare +* Inputs: Write buffer +* Address +* buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer in the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + WARN_ON(1); + return FAIL; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read data from the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " + "block %u page %u (%u pages)\n", + (unsigned int)Block, (unsigned int)Page, PageCount); + + while (PageCount) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = NULL; + ops.len = 0; + ops.oobbuf = read_data; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->read_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + + read_data += DeviceInfo.wPageSize; + Page++; + PageCount--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Enable_Disable_Interrupts +* Inputs: enable or disable +* Outputs: none +* Description: NOP +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); +} + +u16 mtd_Get_Bad_Block(u32 block) +{ + return 0; +} + +#if CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Support for CDMA functions +************************************ +* mtd_CDMA_Flash_Init +* CDMA_process_data command (use LLD_CDMA) +* CDMA_MemCopy_CMD (use LLD_CDMA) +* mtd_CDMA_execute all commands +* mtd_CDMA_Event_Status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Flash_Init(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = 3; + } + + return PASS; +} + +static void mtd_isr(int irq, void *dev_id) +{ + /* TODO: ... */ +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: execute each command in the pending CMD array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Execute_CMDs(u16 tag_count) +{ + u16 i, j; + u8 CMD; /* cmd parameter */ + u8 *data; + u32 block; + u16 page; + u16 count; + u16 status = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " + "Tag Count %u\n", tag_count); + + for (i = 0; i < totalUsedBanks; i++) { + PendingCMD[i].CMD = DUMMY_CMD; + PendingCMD[i].Tag = 0xFF; + PendingCMD[i].Block = + (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; + + for (j = 0; j <= MAX_CHANS; j++) + PendingCMD[i].ChanSync[j] = 0; + } + + CDMA_Execute_CMDs(tag_count); + +#ifdef VERBOSE + print_pending_cmds(tag_count); +#endif +#if DEBUG_SYNC + } + debug_sync_cnt++; +#endif + + for (i = MAX_CHANS; + i < tag_count + MAX_CHANS; i++) { + CMD = PendingCMD[i].CMD; + data = PendingCMD[i].DataAddr; + block = PendingCMD[i].Block; + page = PendingCMD[i].Page; + count = PendingCMD[i].PageCount; + + switch (CMD) { + case ERASE_CMD: + mtd_Erase_Block(block); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_CMD: + mtd_Write_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_SPARE_CMD: + mtd_Write_Page_Main_Spare(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case READ_MAIN_CMD: + mtd_Read_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case MEMCOPY_CMD: + memcpy(PendingCMD[i].DataDestAddr, + PendingCMD[i].DataSrcAddr, + PendingCMD[i].MemCopyByteCnt); + case DUMMY_CMD: + PendingCMD[i].Status = PASS; + break; + default: + PendingCMD[i].Status = FAIL; + break; + } + } + + /* + * Temperory adding code to reset PendingCMD array for basic testing. + * It should be done at the end of event status function. + */ + for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = CMD_NOT_DONE; + } + + nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); + + mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */ + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Event_Status +* Inputs: none +* Outputs: Event_Status code +* Description: This function can also be used to force errors +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Event_Status(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return EVENT_PASS; +} + +#endif /* CMD_DMA */ +#endif /* !ELDORA */ diff --git a/drivers/block/spectra/lld_mtd.h b/drivers/block/spectra/lld_mtd.h new file mode 100644 index 000000000000..4e81ee87b53d --- /dev/null +++ b/drivers/block/spectra/lld_mtd.h @@ -0,0 +1,51 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_MTD_ +#define _LLD_MTD_ + +#include "ffsport.h" +#include "ffsdefs.h" + +/* prototypes: MTD API functions */ +extern u16 mtd_Flash_Reset(void); +extern u16 mtd_Flash_Init(void); +extern int mtd_Flash_Release(void); +extern u16 mtd_Read_Device_ID(void); +extern u16 mtd_Erase_Block(u32 block_addr); +extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 mtd_Event_Status(void); +extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE); +extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 mtd_Get_Bad_Block(u32 block); + +u16 mtd_CDMA_Flash_Init(void); +u16 mtd_CDMA_Execute_CMDs(u16 tag_count); +u16 mtd_CDMA_Event_Status(void); +#endif /*_LLD_MTD_*/ diff --git a/drivers/block/spectra/spectraswconfig.h b/drivers/block/spectra/spectraswconfig.h index 1e6afd372fe4..557c091953d7 100644 --- a/drivers/block/spectra/spectraswconfig.h +++ b/drivers/block/spectra/spectraswconfig.h @@ -47,6 +47,7 @@ /***** Product Feature Support *****/ #define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) #define FLASH_NAND defined(CONFIG_MRST_NAND_HW) +#define FLASH_MTD defined(CONFIG_MRST_NAND_MTD) #define CMD_DMA defined(CONFIG_MRST_NAND_HW_DMA) #define SPECTRA_PARTITION_ID 0 -- cgit v1.2.3 From 0dba333c9568b35c9278c98be6d7861a7a709ca9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 2 Jun 2010 15:08:37 +0200 Subject: block/spectra: rename nand_release() so it does not clash with nand_release() in mtd Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David Woodhouse --- drivers/block/spectra/lld.c | 2 +- drivers/block/spectra/lld_nand.c | 2 +- drivers/block/spectra/lld_nand.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c index ac25eea1a2aa..5c3b9762dc3e 100644 --- a/drivers/block/spectra/lld.c +++ b/drivers/block/spectra/lld.c @@ -218,7 +218,7 @@ u16 GLOB_LLD_Flash_Init(void) int GLOB_LLD_Flash_Release(void) { - return nand_release(); + return nand_release_spectra(); } u16 GLOB_LLD_Erase_Block(u32 block_add) diff --git a/drivers/block/spectra/lld_nand.c b/drivers/block/spectra/lld_nand.c index 8c279b8a6a67..13c3ad2db394 100644 --- a/drivers/block/spectra/lld_nand.c +++ b/drivers/block/spectra/lld_nand.c @@ -2588,7 +2588,7 @@ int NAND_Flash_Init(void) } /* Free memory */ -int nand_release(void) +int nand_release_spectra(void) { pci_unregister_driver(&nand_pci_driver); iounmap(FlashMem); diff --git a/drivers/block/spectra/lld_nand.h b/drivers/block/spectra/lld_nand.h index c7d62c5151c7..d08388287da8 100644 --- a/drivers/block/spectra/lld_nand.h +++ b/drivers/block/spectra/lld_nand.h @@ -82,7 +82,7 @@ struct mrst_nand_info { }; int NAND_Flash_Init(void); -int nand_release(void); +int nand_release_spectra(void); u16 NAND_Flash_Reset(void); u16 NAND_Read_Device_ID(void); u16 NAND_Erase_Block(u32 flash_add); -- cgit v1.2.3 From f39b56f6d067786b6c37c9a20776d1c0eb405a49 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 2 Jun 2010 15:08:36 +0200 Subject: block/spectra: use do_div() for 64bit divs it does not work on 32bit that way Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David Woodhouse --- drivers/block/spectra/lld_mtd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/spectra/lld_mtd.c b/drivers/block/spectra/lld_mtd.c index f5666a9792b5..0de05b1e75f7 100644 --- a/drivers/block/spectra/lld_mtd.c +++ b/drivers/block/spectra/lld_mtd.c @@ -99,6 +99,7 @@ int mtd_Flash_Release(void) u16 mtd_Read_Device_ID(void) { + uint64_t tmp; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); @@ -108,7 +109,9 @@ u16 mtd_Read_Device_ID(void) DeviceInfo.wDeviceMaker = 0; DeviceInfo.wDeviceType = 8; DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - DeviceInfo.wTotalBlocks = spectra_mtd->size / spectra_mtd->erasesize; + tmp = spectra_mtd->size; + do_div(tmp, spectra_mtd->erasesize); + DeviceInfo.wTotalBlocks = tmp; DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; -- cgit v1.2.3 From 8ae4f63623c6a6d164e28d6ac327cf8287b0a24d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 8 Jun 2010 18:08:32 +0100 Subject: spectra: Move to drivers/staging It'll take some work before this is really shippable. Signed-off-by: David Woodhouse --- drivers/block/Kconfig | 2 - drivers/block/Makefile | 2 - drivers/block/spectra/Kconfig | 40 - drivers/block/spectra/Makefile | 11 - drivers/block/spectra/README | 29 - drivers/block/spectra/ffsdefs.h | 58 - drivers/block/spectra/ffsport.c | 827 ----- drivers/block/spectra/ffsport.h | 84 - drivers/block/spectra/flash.c | 4731 ----------------------------- drivers/block/spectra/flash.h | 198 -- drivers/block/spectra/lld.c | 339 --- drivers/block/spectra/lld.h | 111 - drivers/block/spectra/lld_cdma.c | 910 ------ drivers/block/spectra/lld_cdma.h | 123 - drivers/block/spectra/lld_emu.c | 780 ----- drivers/block/spectra/lld_emu.h | 51 - drivers/block/spectra/lld_mtd.c | 687 ----- drivers/block/spectra/lld_mtd.h | 51 - drivers/block/spectra/lld_nand.c | 2601 ---------------- drivers/block/spectra/lld_nand.h | 131 - drivers/block/spectra/nand_regs.h | 619 ---- drivers/block/spectra/spectraswconfig.h | 82 - drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/spectra/Kconfig | 40 + drivers/staging/spectra/Makefile | 11 + drivers/staging/spectra/README | 29 + drivers/staging/spectra/ffsdefs.h | 58 + drivers/staging/spectra/ffsport.c | 827 +++++ drivers/staging/spectra/ffsport.h | 84 + drivers/staging/spectra/flash.c | 4731 +++++++++++++++++++++++++++++ drivers/staging/spectra/flash.h | 198 ++ drivers/staging/spectra/lld.c | 339 +++ drivers/staging/spectra/lld.h | 111 + drivers/staging/spectra/lld_cdma.c | 910 ++++++ drivers/staging/spectra/lld_cdma.h | 123 + drivers/staging/spectra/lld_emu.c | 780 +++++ drivers/staging/spectra/lld_emu.h | 51 + drivers/staging/spectra/lld_mtd.c | 687 +++++ drivers/staging/spectra/lld_mtd.h | 51 + drivers/staging/spectra/lld_nand.c | 2601 ++++++++++++++++ drivers/staging/spectra/lld_nand.h | 131 + drivers/staging/spectra/nand_regs.h | 619 ++++ drivers/staging/spectra/spectraswconfig.h | 82 + 44 files changed, 12466 insertions(+), 12467 deletions(-) delete mode 100644 drivers/block/spectra/Kconfig delete mode 100644 drivers/block/spectra/Makefile delete mode 100644 drivers/block/spectra/README delete mode 100644 drivers/block/spectra/ffsdefs.h delete mode 100644 drivers/block/spectra/ffsport.c delete mode 100644 drivers/block/spectra/ffsport.h delete mode 100644 drivers/block/spectra/flash.c delete mode 100644 drivers/block/spectra/flash.h delete mode 100644 drivers/block/spectra/lld.c delete mode 100644 drivers/block/spectra/lld.h delete mode 100644 drivers/block/spectra/lld_cdma.c delete mode 100644 drivers/block/spectra/lld_cdma.h delete mode 100644 drivers/block/spectra/lld_emu.c delete mode 100644 drivers/block/spectra/lld_emu.h delete mode 100644 drivers/block/spectra/lld_mtd.c delete mode 100644 drivers/block/spectra/lld_mtd.h delete mode 100644 drivers/block/spectra/lld_nand.c delete mode 100644 drivers/block/spectra/lld_nand.h delete mode 100644 drivers/block/spectra/nand_regs.h delete mode 100644 drivers/block/spectra/spectraswconfig.h create mode 100644 drivers/staging/spectra/Kconfig create mode 100644 drivers/staging/spectra/Makefile create mode 100644 drivers/staging/spectra/README create mode 100644 drivers/staging/spectra/ffsdefs.h create mode 100644 drivers/staging/spectra/ffsport.c create mode 100644 drivers/staging/spectra/ffsport.h create mode 100644 drivers/staging/spectra/flash.c create mode 100644 drivers/staging/spectra/flash.h create mode 100644 drivers/staging/spectra/lld.c create mode 100644 drivers/staging/spectra/lld.h create mode 100644 drivers/staging/spectra/lld_cdma.c create mode 100644 drivers/staging/spectra/lld_cdma.h create mode 100644 drivers/staging/spectra/lld_emu.c create mode 100644 drivers/staging/spectra/lld_emu.h create mode 100644 drivers/staging/spectra/lld_mtd.c create mode 100644 drivers/staging/spectra/lld_mtd.h create mode 100644 drivers/staging/spectra/lld_nand.c create mode 100644 drivers/staging/spectra/lld_nand.h create mode 100644 drivers/staging/spectra/nand_regs.h create mode 100644 drivers/staging/spectra/spectraswconfig.h (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index d62b95d2ab00..77bfce52e9ca 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -488,6 +488,4 @@ config BLK_DEV_HD If unsure, say N. -source "drivers/block/spectra/Kconfig" - endif # BLK_DEV diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 568ba651cb5e..aff5ac925c34 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -38,6 +38,4 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ -obj-$(CONFIG_MRST_NAND) += spectra/ - swim_mod-objs := swim.o swim_asm.o diff --git a/drivers/block/spectra/Kconfig b/drivers/block/spectra/Kconfig deleted file mode 100644 index 4bed96f68837..000000000000 --- a/drivers/block/spectra/Kconfig +++ /dev/null @@ -1,40 +0,0 @@ - -menuconfig MRST_NAND - tristate "Moorestown NAND Flash controller" - depends on BLOCK - default n - ---help--- - Enable the driver for the NAND Flash controller in Intel Moorestown - Platform - -choice - prompt "Compile for" - depends on MRST_NAND - default MRST_NAND_HW - -config MRST_NAND_HW - bool "Actual hardware mode" - help - Driver communicates with the actual hardware's register interface. - in DMA mode. - -config MRST_NAND_MTD - bool "Linux MTD mode" - depends on MTD - help - Driver communicates with the kernel MTD subsystem instead of its own - built-in hardware driver. - -config MRST_NAND_EMU - bool "RAM emulator testing" - help - Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer. - -endchoice - -config MRST_NAND_HW_DMA - bool - default n - depends on MRST_NAND_HW - help - Use DMA for native hardware interface. diff --git a/drivers/block/spectra/Makefile b/drivers/block/spectra/Makefile deleted file mode 100644 index 2a9490385339..000000000000 --- a/drivers/block/spectra/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile of Intel Moorestown NAND controller driver -# - -obj-$(CONFIG_MRST_NAND) += spectra.o -spectra-y := ffsport.o flash.o lld.o -spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o -spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o -spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o -spectra-$(CONFIG_MRST_NAND_MTD) += lld_mtd.o - diff --git a/drivers/block/spectra/README b/drivers/block/spectra/README deleted file mode 100644 index ecba559b899c..000000000000 --- a/drivers/block/spectra/README +++ /dev/null @@ -1,29 +0,0 @@ -This is a driver for NAND controller of Intel Moorestown platform. - -This driver is a standalone linux block device driver, it acts as if it's a normal hard disk. -It includes three layer: - block layer interface - file ffsport.c - Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on) - Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access) - -This driver can be build as modules or build-in. - -Dependency: -This driver has dependency on IA Firmware of Intel Moorestown platform. -It need the IA Firmware to create the block table for the first time. -And to validate this driver code without IA Firmware, you can change the -macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the -driver will erase the whole nand flash and create a new block table. - -TODO: - - Enable Command DMA feature support - - lower the memory footprint - - Remove most of the unnecessary global variables - - Change all the upcase variable / functions name to lowercase - - Some other misc bugs - -Please send patches to: - Greg Kroah-Hartman - -And Cc to: Gao Yunpeng - diff --git a/drivers/block/spectra/ffsdefs.h b/drivers/block/spectra/ffsdefs.h deleted file mode 100644 index a9e9cd233d2a..000000000000 --- a/drivers/block/spectra/ffsdefs.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FFSDEFS_ -#define _FFSDEFS_ - -#define CLEAR 0 /*use this to clear a field instead of "fail"*/ -#define SET 1 /*use this to set a field instead of "pass"*/ -#define FAIL 1 /*failed flag*/ -#define PASS 0 /*success flag*/ -#define ERR -1 /*error flag*/ - -#define ERASE_CMD 10 -#define WRITE_MAIN_CMD 11 -#define READ_MAIN_CMD 12 -#define WRITE_SPARE_CMD 13 -#define READ_SPARE_CMD 14 -#define WRITE_MAIN_SPARE_CMD 15 -#define READ_MAIN_SPARE_CMD 16 -#define MEMCOPY_CMD 17 -#define DUMMY_CMD 99 - -#define EVENT_PASS 0x00 -#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01 -#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02 -#define EVENT_TIME_OUT 0x03 -#define EVENT_PROGRAM_FAILURE 0x04 -#define EVENT_ERASE_FAILURE 0x05 -#define EVENT_MEMCOPY_FAILURE 0x06 -#define EVENT_FAIL 0x07 - -#define EVENT_NONE 0x22 -#define EVENT_DMA_CMD_COMP 0x77 -#define EVENT_ECC_TRANSACTION_DONE 0x88 -#define EVENT_DMA_CMD_FAIL 0x99 - -#define CMD_PASS 0 -#define CMD_FAIL 1 -#define CMD_ABORT 2 -#define CMD_NOT_DONE 3 - -#endif /* _FFSDEFS_ */ diff --git a/drivers/block/spectra/ffsport.c b/drivers/block/spectra/ffsport.c deleted file mode 100644 index 3c3565d40545..000000000000 --- a/drivers/block/spectra/ffsport.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "ffsport.h" -#include "flash.h" -#include -#include -#include -#include -#include -#include -#include -#include - -/**** Helper functions used for Div, Remainder operation on u64 ****/ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_Calc_Used_Bits -* Inputs: Power of 2 number -* Outputs: Number of Used Bits -* 0, if the argument is 0 -* Description: Calculate the number of bits used by a given power of 2 number -* Number can be upto 32 bit -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_Calc_Used_Bits(u32 n) -{ - int tot_bits = 0; - - if (n >= 1 << 16) { - n >>= 16; - tot_bits += 16; - } - - if (n >= 1 << 8) { - n >>= 8; - tot_bits += 8; - } - - if (n >= 1 << 4) { - n >>= 4; - tot_bits += 4; - } - - if (n >= 1 << 2) { - n >>= 2; - tot_bits += 2; - } - - if (n >= 1 << 1) - tot_bits += 1; - - return ((n == 0) ? (0) : tot_bits); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_u64_Div -* Inputs: Number of u64 -* A power of 2 number as Division -* Outputs: Quotient of the Divisor operation -* Description: It divides the address by divisor by using bit shift operation -* (essentially without explicitely using "/"). -* Divisor is a power of 2 number and Divided is of u64 -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u64 GLOB_u64_Div(u64 addr, u32 divisor) -{ - return (u64)(addr >> GLOB_Calc_Used_Bits(divisor)); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_u64_Remainder -* Inputs: Number of u64 -* Divisor Type (1 -PageAddress, 2- BlockAddress) -* Outputs: Remainder of the Division operation -* Description: It calculates the remainder of a number (of u64) by -* divisor(power of 2 number ) by using bit shifting and multiply -* operation(essentially without explicitely using "/"). -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) -{ - u64 result = 0; - - if (divisor_type == 1) { /* Remainder -- Page */ - result = (addr >> DeviceInfo.nBitsInPageDataSize); - result = result * DeviceInfo.wPageDataSize; - } else if (divisor_type == 2) { /* Remainder -- Block */ - result = (addr >> DeviceInfo.nBitsInBlockDataSize); - result = result * DeviceInfo.wBlockDataSize; - } - - result = addr - result; - - return result; -} - -#define NUM_DEVICES 1 -#define PARTITIONS 8 - -#define GLOB_SBD_NAME "nd" -#define GLOB_SBD_IRQ_NUM (29) -#define GLOB_VERSION "driver version 20091110" - -#define GLOB_SBD_IOCTL_GC (0x7701) -#define GLOB_SBD_IOCTL_WL (0x7702) -#define GLOB_SBD_IOCTL_FORMAT (0x7703) -#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704) -#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705) -#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706) -#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707) -#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708) -#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709) -#define GLOB_SBD_IOCTL_READ_DATA (0x770A) - -static int reserved_mb = 0; -module_param(reserved_mb, int, 0); -MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)"); - -int nand_debug_level; -module_param(nand_debug_level, int, 0644); -MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3"); - -MODULE_LICENSE("GPL"); - -struct spectra_nand_dev { - struct pci_dev *dev; - u64 size; - u16 users; - spinlock_t qlock; - void __iomem *ioaddr; /* Mapped address */ - struct request_queue *queue; - struct task_struct *thread; - struct gendisk *gd; - u8 *tmp_buf; -}; - - -static int GLOB_SBD_majornum; - -static char *GLOB_version = GLOB_VERSION; - -static struct spectra_nand_dev nand_device[NUM_DEVICES]; - -static struct mutex spectra_lock; - -static int res_blks_os = 1; - -struct spectra_indentfy_dev_tag IdentifyDeviceData; - -static int force_flush_cache(void) -{ - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (ERR == GLOB_FTL_Flush_Cache()) { - printk(KERN_ERR "Fail to Flush FTL Cache!\n"); - return -EFAULT; - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; -} - -struct ioctl_rw_page_info { - u8 *data; - unsigned int page; -}; - -static int ioctl_read_page_data(unsigned long arg) -{ - u8 *buf; - struct ioctl_rw_page_info info; - int result = PASS; - - if (copy_from_user(&info, (void __user *)arg, sizeof(info))) - return -EFAULT; - - buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); - if (!buf) { - printk(KERN_ERR "ioctl_read_page_data: " - "failed to allocate memory\n"); - return -ENOMEM; - } - - mutex_lock(&spectra_lock); - result = GLOB_FTL_Page_Read(buf, - (u64)info.page * IdentifyDeviceData.PageDataSize); - mutex_unlock(&spectra_lock); - - if (copy_to_user((void __user *)info.data, buf, - IdentifyDeviceData.PageDataSize)) { - printk(KERN_ERR "ioctl_read_page_data: " - "failed to copy user data\n"); - kfree(buf); - return -EFAULT; - } - - kfree(buf); - return result; -} - -static int ioctl_write_page_data(unsigned long arg) -{ - u8 *buf; - struct ioctl_rw_page_info info; - int result = PASS; - - if (copy_from_user(&info, (void __user *)arg, sizeof(info))) - return -EFAULT; - - buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); - if (!buf) { - printk(KERN_ERR "ioctl_write_page_data: " - "failed to allocate memory\n"); - return -ENOMEM; - } - - if (copy_from_user(buf, (void __user *)info.data, - IdentifyDeviceData.PageDataSize)) { - printk(KERN_ERR "ioctl_write_page_data: " - "failed to copy user data\n"); - kfree(buf); - return -EFAULT; - } - - mutex_lock(&spectra_lock); - result = GLOB_FTL_Page_Write(buf, - (u64)info.page * IdentifyDeviceData.PageDataSize); - mutex_unlock(&spectra_lock); - - kfree(buf); - return result; -} - -/* Return how many blocks should be reserved for bad block replacement */ -static int get_res_blk_num_bad_blk(void) -{ - return IdentifyDeviceData.wDataBlockNum / 10; -} - -/* Return how many blocks should be reserved for OS image */ -static int get_res_blk_num_os(void) -{ - u32 res_blks, blk_size; - - blk_size = IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock; - - res_blks = (reserved_mb * 1024 * 1024) / blk_size; - - if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum)) - res_blks = 1; /* Reserved 1 block for block table */ - - return res_blks; -} - -static void SBD_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_LINUX_BLOCK; - /* rq->timeout = 5 * HZ; */ - rq->cmd[0] = REQ_LB_OP_FLUSH; -} - -/* Transfer a full request. */ -static int do_transfer(struct spectra_nand_dev *tr, struct request *req) -{ - u64 start_addr, addr; - u32 logical_start_sect, hd_start_sect; - u32 nsect, hd_sects; - u32 rsect, tsect = 0; - char *buf; - u32 ratio = IdentifyDeviceData.PageDataSize >> 9; - - start_addr = (u64)(blk_rq_pos(req)) << 9; - /* Add a big enough offset to prevent the OS Image from - * being accessed or damaged by file system */ - start_addr += IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock * - res_blks_os; - - if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && - req->cmd[0] == REQ_LB_OP_FLUSH) { - if (force_flush_cache()) /* Fail to flush cache */ - return -EIO; - else - return 0; - } - - if (!blk_fs_request(req)) - return -EIO; - - if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) { - printk(KERN_ERR "Spectra error: request over the NAND " - "capacity!sector %d, current_nr_sectors %d, " - "while capacity is %d\n", - (int)blk_rq_pos(req), - blk_rq_cur_sectors(req), - (int)get_capacity(tr->gd)); - return -EIO; - } - - logical_start_sect = start_addr >> 9; - hd_start_sect = logical_start_sect / ratio; - rsect = logical_start_sect - hd_start_sect * ratio; - - addr = (u64)hd_start_sect * ratio * 512; - buf = req->buffer; - nsect = blk_rq_cur_sectors(req); - - if (rsect) - tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect; - - switch (rq_data_dir(req)) { - case READ: - /* Read the first NAND page */ - if (rsect) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9); - addr += IdentifyDeviceData.PageDataSize; - buf += tsect << 9; - nsect -= tsect; - } - - /* Read the other NAND pages */ - for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { - if (GLOB_FTL_Page_Read(buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += IdentifyDeviceData.PageDataSize; - } - - /* Read the last NAND pages */ - if (nsect % ratio) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9); - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; - - case WRITE: - /* Write the first NAND page */ - if (rsect) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9); - if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += tsect << 9; - nsect -= tsect; - } - - /* Write the other NAND pages */ - for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { - if (GLOB_FTL_Page_Write(buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += IdentifyDeviceData.PageDataSize; - } - - /* Write the last NAND pages */ - if (nsect % ratio) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9); - if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; - - default: - printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); - return -EIO; - } -} - -/* This function is copied from drivers/mtd/mtd_blkdevs.c */ -static int spectra_trans_thread(void *arg) -{ - struct spectra_nand_dev *tr = arg; - struct request_queue *rq = tr->queue; - struct request *req = NULL; - - /* we might get involved when memory gets low, so use PF_MEMALLOC */ - current->flags |= PF_MEMALLOC; - - spin_lock_irq(rq->queue_lock); - while (!kthread_should_stop()) { - int res; - - if (!req) { - req = blk_fetch_request(rq); - if (!req) { - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(rq->queue_lock); - schedule(); - spin_lock_irq(rq->queue_lock); - continue; - } - } - - spin_unlock_irq(rq->queue_lock); - - mutex_lock(&spectra_lock); - res = do_transfer(tr, req); - mutex_unlock(&spectra_lock); - - spin_lock_irq(rq->queue_lock); - - if (!__blk_end_request_cur(req, res)) - req = NULL; - } - - if (req) - __blk_end_request_all(req, -EIO); - - spin_unlock_irq(rq->queue_lock); - - return 0; -} - - -/* Request function that "handles clustering". */ -static void GLOB_SBD_request(struct request_queue *rq) -{ - struct spectra_nand_dev *pdev = rq->queuedata; - wake_up_process(pdev->thread); -} - -static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode) - -{ - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - return 0; -} - -static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode) -{ - int ret; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - mutex_lock(&spectra_lock); - ret = force_flush_cache(); - mutex_unlock(&spectra_lock); - - return 0; -} - -static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - geo->heads = 4; - geo->sectors = 16; - geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); - - nand_dbg_print(NAND_DBG_DEBUG, - "heads: %d, sectors: %d, cylinders: %d\n", - geo->heads, geo->sectors, geo->cylinders); - - return 0; -} - -int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - switch (cmd) { - case GLOB_SBD_IOCTL_GC: - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra IOCTL: Garbage Collection " - "being performed\n"); - if (PASS != GLOB_FTL_Garbage_Collection()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_WL: - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra IOCTL: Static Wear Leveling " - "being performed\n"); - if (PASS != GLOB_FTL_Wear_Leveling()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_FORMAT: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format " - "being performed\n"); - if (PASS != GLOB_FTL_Flash_Format()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_FLUSH_CACHE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush " - "being performed\n"); - mutex_lock(&spectra_lock); - ret = force_flush_cache(); - mutex_unlock(&spectra_lock); - return ret; - - case GLOB_SBD_IOCTL_COPY_BLK_TABLE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Copy block table\n"); - if (copy_to_user((void __user *)arg, - get_blk_table_start_addr(), - get_blk_table_len())) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Copy wear leveling table\n"); - if (copy_to_user((void __user *)arg, - get_wear_leveling_table_start_addr(), - get_wear_leveling_table_len())) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_GET_NAND_INFO: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Get NAND info\n"); - if (copy_to_user((void __user *)arg, &IdentifyDeviceData, - sizeof(IdentifyDeviceData))) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_WRITE_DATA: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Write one page data\n"); - return ioctl_write_page_data(arg); - - case GLOB_SBD_IOCTL_READ_DATA: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Read one page data\n"); - return ioctl_read_page_data(arg); - } - - return -ENOTTY; -} - -static struct block_device_operations GLOB_SBD_ops = { - .owner = THIS_MODULE, - .open = GLOB_SBD_open, - .release = GLOB_SBD_release, - .locked_ioctl = GLOB_SBD_ioctl, - .getgeo = GLOB_SBD_getgeo, -}; - -static int SBD_setup_device(struct spectra_nand_dev *dev, int which) -{ - int res_blks; - u32 sects; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - memset(dev, 0, sizeof(struct spectra_nand_dev)); - - nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks " - "for OS image, %d blocks for bad block replacement.\n", - get_res_blk_num_os(), - get_res_blk_num_bad_blk()); - - res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os(); - - dev->size = (u64)IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock * - (IdentifyDeviceData.wDataBlockNum - res_blks); - - res_blks_os = get_res_blk_num_os(); - - spin_lock_init(&dev->qlock); - - dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); - if (!dev->tmp_buf) { - printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n", - __FILE__, __LINE__); - goto out_vfree; - } - - dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock); - if (dev->queue == NULL) { - printk(KERN_ERR - "Spectra: Request queue could not be initialized." - " Aborting\n "); - goto out_vfree; - } - dev->queue->queuedata = dev; - - /* As Linux block layer doens't support >4KB hardware sector, */ - /* Here we force report 512 byte hardware sector size to Kernel */ - blk_queue_logical_block_size(dev->queue, 512); - - blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH, - SBD_prepare_flush); - - dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd"); - if (IS_ERR(dev->thread)) { - blk_cleanup_queue(dev->queue); - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); - return PTR_ERR(dev->thread); - } - - dev->gd = alloc_disk(PARTITIONS); - if (!dev->gd) { - printk(KERN_ERR - "Spectra: Could not allocate disk. Aborting \n "); - goto out_vfree; - } - dev->gd->major = GLOB_SBD_majornum; - dev->gd->first_minor = which * PARTITIONS; - dev->gd->fops = &GLOB_SBD_ops; - dev->gd->queue = dev->queue; - dev->gd->private_data = dev; - snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a'); - - sects = dev->size >> 9; - nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects); - set_capacity(dev->gd, sects); - - add_disk(dev->gd); - - return 0; -out_vfree: - return -ENOMEM; -} - -/* -static ssize_t show_nand_block_num(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.wDataBlockNum); -} - -static ssize_t show_nand_pages_per_block(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.PagesPerBlock); -} - -static ssize_t show_nand_page_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.PageDataSize); -} - -static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL); -static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL); -static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL); - -static void create_sysfs_entry(struct device *dev) -{ - if (device_create_file(dev, &dev_attr_nand_block_num)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_block_num.\n"); - if (device_create_file(dev, &dev_attr_nand_pages_per_block)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_pages_per_block.\n"); - if (device_create_file(dev, &dev_attr_nand_page_size)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_page_size.\n"); -} -*/ - -static int GLOB_SBD_init(void) -{ - int i; - - /* Set debug output level (0~3) here. 3 is most verbose */ - printk(KERN_ALERT "Spectra: %s\n", GLOB_version); - - mutex_init(&spectra_lock); - - GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME); - if (GLOB_SBD_majornum <= 0) { - printk(KERN_ERR "Unable to get the major %d for Spectra", - GLOB_SBD_majornum); - return -EBUSY; - } - - if (PASS != GLOB_FTL_Flash_Init()) { - printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. " - "Aborting\n"); - goto out_flash_register; - } - - /* create_sysfs_entry(&dev->dev); */ - - if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) { - printk(KERN_ERR "Spectra: Unable to Read Flash Device. " - "Aborting\n"); - goto out_flash_register; - } else { - nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: " - "Num blocks=%d, pagesperblock=%d, " - "pagedatasize=%d, ECCBytesPerSector=%d\n", - (int)IdentifyDeviceData.NumBlocks, - (int)IdentifyDeviceData.PagesPerBlock, - (int)IdentifyDeviceData.PageDataSize, - (int)IdentifyDeviceData.wECCBytesPerSector); - } - - printk(KERN_ALERT "Spectra: searching block table, please wait ...\n"); - if (GLOB_FTL_Init() != PASS) { - printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. " - "Aborting\n"); - goto out_ftl_flash_register; - } - printk(KERN_ALERT "Spectra: block table has been found.\n"); - - for (i = 0; i < NUM_DEVICES; i++) - if (SBD_setup_device(&nand_device[i], i) == -ENOMEM) - goto out_ftl_flash_register; - - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra: module loaded with major number %d\n", - GLOB_SBD_majornum); - - return 0; - -out_ftl_flash_register: - GLOB_FTL_Cache_Release(); -out_flash_register: - GLOB_FTL_Flash_Release(); - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); - printk(KERN_ERR "Spectra: Module load failed.\n"); - - return -ENOMEM; -} - -static void __exit GLOB_SBD_exit(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < NUM_DEVICES; i++) { - struct spectra_nand_dev *dev = &nand_device[i]; - if (dev->gd) { - del_gendisk(dev->gd); - put_disk(dev->gd); - } - if (dev->queue) - blk_cleanup_queue(dev->queue); - kfree(dev->tmp_buf); - } - - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); - - mutex_lock(&spectra_lock); - force_flush_cache(); - mutex_unlock(&spectra_lock); - - GLOB_FTL_Cache_Release(); - - GLOB_FTL_Flash_Release(); - - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra FTL module (major number %d) unloaded.\n", - GLOB_SBD_majornum); -} - -module_init(GLOB_SBD_init); -module_exit(GLOB_SBD_exit); diff --git a/drivers/block/spectra/ffsport.h b/drivers/block/spectra/ffsport.h deleted file mode 100644 index 6c5d90c53430..000000000000 --- a/drivers/block/spectra/ffsport.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FFSPORT_ -#define _FFSPORT_ - -#include "ffsdefs.h" - -#if defined __GNUC__ -#define PACKED -#define PACKED_GNU __attribute__ ((packed)) -#define UNALIGNED -#endif - -#include -#include /* for strcpy(), stricmp(), etc */ -#include /* for kmalloc(), kfree() */ -#include -#include -#include -#include - -#include /* printk() */ -#include /* everything... */ -#include /* error codes */ -#include /* size_t */ -#include -#include -#include -#include -#include "flash.h" - -#define VERBOSE 1 - -#define NAND_DBG_WARN 1 -#define NAND_DBG_DEBUG 2 -#define NAND_DBG_TRACE 3 - -extern int nand_debug_level; - -#ifdef VERBOSE -#define nand_dbg_print(level, args...) \ - do { \ - if (level <= nand_debug_level) \ - printk(KERN_ALERT args); \ - } while (0) -#else -#define nand_dbg_print(level, args...) -#endif - -#ifdef SUPPORT_BIG_ENDIAN -#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \ - (u16)((u16)(w) >> 8)) - -#define INVERTUINT32(dw) (((u32)(dw) << 24) | \ - (((u32)(dw) << 8) & 0x00ff0000) | \ - (((u32)(dw) >> 8) & 0x0000ff00) | \ - ((u32)(dw) >> 24)) -#else -#define INVERTUINT16(w) w -#define INVERTUINT32(dw) dw -#endif - -extern int GLOB_Calc_Used_Bits(u32 n); -extern u64 GLOB_u64_Div(u64 addr, u32 divisor); -extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type); - -#endif /* _FFSPORT_ */ diff --git a/drivers/block/spectra/flash.c b/drivers/block/spectra/flash.c deleted file mode 100644 index 134aa5166a8d..000000000000 --- a/drivers/block/spectra/flash.c +++ /dev/null @@ -1,4731 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include "flash.h" -#include "ffsdefs.h" -#include "lld.h" -#include "lld_nand.h" -#if CMD_DMA -#include "lld_cdma.h" -#endif - -#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize)) -#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \ - DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize)) - -#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ - BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK)) - -#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK)) - -#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ - BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK)) - -#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK)) - -#if DEBUG_BNDRY -void debug_boundary_lineno_error(int chnl, int limit, int no, - int lineno, char *filename) -{ - if (chnl >= limit) - printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, " - "at %s:%d. Other info:%d. Aborting...\n", - chnl, limit, filename, lineno, no); -} -/* static int globalmemsize; */ -#endif - -static u16 FTL_Cache_If_Hit(u64 dwPageAddr); -static int FTL_Cache_Read(u64 dwPageAddr); -static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr, - u16 cache_blk); -static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr, - u8 cache_blk, u16 flag); -static int FTL_Cache_Write(void); -static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr); -static void FTL_Calculate_LRU(void); -static u32 FTL_Get_Block_Index(u32 wBlockNum); - -static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, - u8 BT_Tag, u16 *Page); -static int FTL_Read_Block_Table(void); -static int FTL_Write_Block_Table(int wForce); -static int FTL_Write_Block_Table_Data(void); -static int FTL_Check_Block_Table(int wOldTable); -static int FTL_Static_Wear_Leveling(void); -static u32 FTL_Replace_Block_Table(void); -static int FTL_Write_IN_Progress_Block_Table_Page(void); - -static u32 FTL_Get_Page_Num(u64 length); -static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr); - -static u32 FTL_Replace_OneBlock(u32 wBlockNum, - u32 wReplaceNum); -static u32 FTL_Replace_LWBlock(u32 wBlockNum, - int *pGarbageCollect); -static u32 FTL_Replace_MWBlock(void); -static int FTL_Replace_Block(u64 blk_addr); -static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX); - -static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr); - -struct device_info_tag DeviceInfo; -struct flash_cache_tag Cache; -static struct spectra_l2_cache_info cache_l2; - -static u8 *cache_l2_page_buf; -static u8 *cache_l2_blk_buf; - -u8 *g_pBlockTable; -u8 *g_pWearCounter; -u16 *g_pReadCounter; -u32 *g_pBTBlocks; -static u16 g_wBlockTableOffset; -static u32 g_wBlockTableIndex; -static u8 g_cBlockTableStatus; - -static u8 *g_pTempBuf; -static u8 *flag_check_blk_table; -static u8 *tmp_buf_search_bt_in_block; -static u8 *spare_buf_search_bt_in_block; -static u8 *spare_buf_bt_search_bt_in_block; -static u8 *tmp_buf1_read_blk_table; -static u8 *tmp_buf2_read_blk_table; -static u8 *flags_static_wear_leveling; -static u8 *tmp_buf_write_blk_table_data; -static u8 *tmp_buf_read_disturbance; - -u8 *buf_read_page_main_spare; -u8 *buf_write_page_main_spare; -u8 *buf_read_page_spare; -u8 *buf_get_bad_block; - -#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) -struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS]; -struct flash_cache_tag cache_start_copy; -#endif - -int g_wNumFreeBlocks; -u8 g_SBDCmdIndex; - -static u8 *g_pIPF; -static u8 bt_flag = FIRST_BT_ID; -static u8 bt_block_changed; - -static u16 cache_block_to_write; -static u8 last_erased = FIRST_BT_ID; - -static u8 GC_Called; -static u8 BT_GC_Called; - -#if CMD_DMA -#define COPY_BACK_BUF_NUM 10 - -static u8 ftl_cmd_cnt; /* Init value is 0 */ -u8 *g_pBTDelta; -u8 *g_pBTDelta_Free; -u8 *g_pBTStartingCopy; -u8 *g_pWearCounterCopy; -u16 *g_pReadCounterCopy; -u8 *g_pBlockTableCopies; -u8 *g_pNextBlockTable; -static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM]; -static int cp_back_buf_idx; - -static u8 *g_temp_buf; - -#pragma pack(push, 1) -#pragma pack(1) -struct BTableChangesDelta { - u8 ftl_cmd_cnt; - u8 ValidFields; - u16 g_wBlockTableOffset; - u32 g_wBlockTableIndex; - u32 BT_Index; - u32 BT_Entry_Value; - u32 WC_Index; - u8 WC_Entry_Value; - u32 RC_Index; - u16 RC_Entry_Value; -}; - -#pragma pack(pop) - -struct BTableChangesDelta *p_BTableChangesDelta; -#endif - - -#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK) -#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK) - -#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u32)) -#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u8)) -#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u16)) -#if SUPPORT_LARGE_BLOCKNUM -#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u8) * 3) -#else -#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u16)) -#endif -#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \ - FTL_Get_WearCounter_Table_Mem_Size_Bytes -#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \ - FTL_Get_ReadCounter_Table_Mem_Size_Bytes - -static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void) -{ - u32 byte_num; - - if (DeviceInfo.MLCDevice) { - byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + - DeviceInfo.wDataBlockNum * sizeof(u8) + - DeviceInfo.wDataBlockNum * sizeof(u16); - } else { - byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + - DeviceInfo.wDataBlockNum * sizeof(u8); - } - - byte_num += 4 * sizeof(u8); - - return byte_num; -} - -static u16 FTL_Get_Block_Table_Flash_Size_Pages(void) -{ - return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes()); -} - -static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx, - u32 sizeTxed) -{ - u32 wBytesCopied, blk_tbl_size, wBytes; - u32 *pbt = (u32 *)g_pBlockTable; - - blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); - for (wBytes = 0; - (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size); - wBytes++) { -#if SUPPORT_LARGE_BLOCKNUM - flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3] - >> (((wBytes + sizeTxed) % 3) ? - ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF; -#else - flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2] - >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; -#endif - } - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); - wBytesCopied = wBytes; - wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? - (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); - memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes); - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - - if (DeviceInfo.MLCDevice) { - blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); - wBytesCopied += wBytes; - for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) - flashBuf[wBytes + wBytesCopied] = - (g_pReadCounter[(wBytes + sizeTxed) / 2] >> - (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; - } - - return wBytesCopied + wBytes; -} - -static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf, - u32 sizeToTx, u32 sizeTxed) -{ - u32 wBytesCopied, blk_tbl_size, wBytes; - u32 *pbt = (u32 *)g_pBlockTable; - - blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); - for (wBytes = 0; (wBytes < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { -#if SUPPORT_LARGE_BLOCKNUM - if (!((wBytes + sizeTxed) % 3)) - pbt[(wBytes + sizeTxed) / 3] = 0; - pbt[(wBytes + sizeTxed) / 3] |= - (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ? - ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)); -#else - if (!((wBytes + sizeTxed) % 2)) - pbt[(wBytes + sizeTxed) / 2] = 0; - pbt[(wBytes + sizeTxed) / 2] |= - (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ? - 0 : 8)); -#endif - } - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); - wBytesCopied = wBytes; - wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? - (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); - memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes); - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - - if (DeviceInfo.MLCDevice) { - wBytesCopied += wBytes; - blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); - for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { - if (((wBytes + sizeTxed) % 2)) - g_pReadCounter[(wBytes + sizeTxed) / 2] = 0; - g_pReadCounter[(wBytes + sizeTxed) / 2] |= - (flashBuf[wBytes] << - (((wBytes + sizeTxed) % 2) ? 0 : 8)); - } - } - - return wBytesCopied+wBytes; -} - -static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag) -{ - int i; - - for (i = 0; i < BTSIG_BYTES; i++) - buf[BTSIG_OFFSET + i] = - ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) % - (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID; - - return PASS; -} - -static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray) -{ - static u8 tag[BTSIG_BYTES >> 1]; - int i, j, k, tagi, tagtemp, status; - - *tagarray = (u8 *)tag; - tagi = 0; - - for (i = 0; i < (BTSIG_BYTES - 1); i++) { - for (j = i + 1; (j < BTSIG_BYTES) && - (tagi < (BTSIG_BYTES >> 1)); j++) { - tagtemp = buf[BTSIG_OFFSET + j] - - buf[BTSIG_OFFSET + i]; - if (tagtemp && !(tagtemp % BTSIG_DELTA)) { - tagtemp = (buf[BTSIG_OFFSET + i] + - (1 + LAST_BT_ID - FIRST_BT_ID) - - (i * BTSIG_DELTA)) % - (1 + LAST_BT_ID - FIRST_BT_ID); - status = FAIL; - for (k = 0; k < tagi; k++) { - if (tagtemp == tag[k]) - status = PASS; - } - - if (status == FAIL) { - tag[tagi++] = tagtemp; - i = (j == (i + 1)) ? i + 1 : i; - j = (j == (i + 1)) ? i + 1 : i; - } - } - } - } - - return tagi; -} - - -static int FTL_Execute_SPL_Recovery(void) -{ - u32 j, block, blks; - u32 *pbt = (u32 *)g_pBlockTable; - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock; - for (j = 0; j <= blks; j++) { - block = (pbt[j]); - if (((block & BAD_BLOCK) != BAD_BLOCK) && - ((block & SPARE_BLOCK) == SPARE_BLOCK)) { - ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK); - if (FAIL == ret) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)(block & ~BAD_BLOCK)); - MARK_BLOCK_AS_BAD(pbt[j]); - } - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_IdentifyDevice -* Inputs: pointer to identify data structure -* Outputs: PASS / FAIL -* Description: the identify data structure is filled in with -* information for the block driver. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev_data->NumBlocks = DeviceInfo.wTotalBlocks; - dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock; - dev_data->PageDataSize = DeviceInfo.wPageDataSize; - dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector; - dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum; - - return PASS; -} - -/* ..... */ -static int allocate_memory(void) -{ - u32 block_table_size, page_size, block_size, mem_size; - u32 total_bytes = 0; - int i; -#if CMD_DMA - int j; -#endif - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - page_size = DeviceInfo.wPageSize; - block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; - - block_table_size = DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8) + sizeof(u16)); - block_table_size += (DeviceInfo.wPageDataSize - - (block_table_size % DeviceInfo.wPageDataSize)) % - DeviceInfo.wPageDataSize; - - /* Malloc memory for block tables */ - g_pBlockTable = kmalloc(block_table_size, GFP_ATOMIC); - if (!g_pBlockTable) - goto block_table_fail; - memset(g_pBlockTable, 0, block_table_size); - total_bytes += block_table_size; - - g_pWearCounter = (u8 *)(g_pBlockTable + - DeviceInfo.wDataBlockNum * sizeof(u32)); - - if (DeviceInfo.MLCDevice) - g_pReadCounter = (u16 *)(g_pBlockTable + - DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8))); - - /* Malloc memory and init for cache items */ - for (i = 0; i < CACHE_ITEM_NUM; i++) { - Cache.array[i].address = NAND_CACHE_INIT_ADDR; - Cache.array[i].use_cnt = 0; - Cache.array[i].changed = CLEAR; - Cache.array[i].buf = kmalloc(Cache.cache_item_size, - GFP_ATOMIC); - if (!Cache.array[i].buf) - goto cache_item_fail; - memset(Cache.array[i].buf, 0, Cache.cache_item_size); - total_bytes += Cache.cache_item_size; - } - - /* Malloc memory for IPF */ - g_pIPF = kmalloc(page_size, GFP_ATOMIC); - if (!g_pIPF) - goto ipf_fail; - memset(g_pIPF, 0, page_size); - total_bytes += page_size; - - /* Malloc memory for data merging during Level2 Cache flush */ - cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC); - if (!cache_l2_page_buf) - goto cache_l2_page_buf_fail; - memset(cache_l2_page_buf, 0xff, page_size); - total_bytes += page_size; - - cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC); - if (!cache_l2_blk_buf) - goto cache_l2_blk_buf_fail; - memset(cache_l2_blk_buf, 0xff, block_size); - total_bytes += block_size; - - /* Malloc memory for temp buffer */ - g_pTempBuf = kmalloc(Cache.cache_item_size, GFP_ATOMIC); - if (!g_pTempBuf) - goto Temp_buf_fail; - memset(g_pTempBuf, 0, Cache.cache_item_size); - total_bytes += Cache.cache_item_size; - - /* Malloc memory for block table blocks */ - mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32); - g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC); - if (!g_pBTBlocks) - goto bt_blocks_fail; - memset(g_pBTBlocks, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Check_Block_Table */ - flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC); - if (!flag_check_blk_table) - goto flag_check_blk_table_fail; - total_bytes += DeviceInfo.wDataBlockNum; - - /* Malloc memory for function FTL_Search_Block_Table_IN_Block */ - tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf_search_bt_in_block) - goto tmp_buf_search_bt_in_block_fail; - memset(tmp_buf_search_bt_in_block, 0xff, page_size); - total_bytes += page_size; - - mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize; - spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); - if (!spare_buf_search_bt_in_block) - goto spare_buf_search_bt_in_block_fail; - memset(spare_buf_search_bt_in_block, 0xff, mem_size); - total_bytes += mem_size; - - spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); - if (!spare_buf_bt_search_bt_in_block) - goto spare_buf_bt_search_bt_in_block_fail; - memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Read_Block_Table */ - tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf1_read_blk_table) - goto tmp_buf1_read_blk_table_fail; - memset(tmp_buf1_read_blk_table, 0xff, page_size); - total_bytes += page_size; - - tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf2_read_blk_table) - goto tmp_buf2_read_blk_table_fail; - memset(tmp_buf2_read_blk_table, 0xff, page_size); - total_bytes += page_size; - - /* Malloc memory for function FTL_Static_Wear_Leveling */ - flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum, - GFP_ATOMIC); - if (!flags_static_wear_leveling) - goto flags_static_wear_leveling_fail; - total_bytes += DeviceInfo.wDataBlockNum; - - /* Malloc memory for function FTL_Write_Block_Table_Data */ - if (FTL_Get_Block_Table_Flash_Size_Pages() > 3) - mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() - - 2 * DeviceInfo.wPageSize; - else - mem_size = DeviceInfo.wPageSize; - tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC); - if (!tmp_buf_write_blk_table_data) - goto tmp_buf_write_blk_table_data_fail; - memset(tmp_buf_write_blk_table_data, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Read_Disturbance */ - tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC); - if (!tmp_buf_read_disturbance) - goto tmp_buf_read_disturbance_fail; - memset(tmp_buf_read_disturbance, 0xff, block_size); - total_bytes += block_size; - - /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */ - buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); - if (!buf_read_page_main_spare) - goto buf_read_page_main_spare_fail; - total_bytes += DeviceInfo.wPageSize; - - /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */ - buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); - if (!buf_write_page_main_spare) - goto buf_write_page_main_spare_fail; - total_bytes += DeviceInfo.wPageSize; - - /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */ - buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); - if (!buf_read_page_spare) - goto buf_read_page_spare_fail; - memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize); - total_bytes += DeviceInfo.wPageSpareSize; - - /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */ - buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); - if (!buf_get_bad_block) - goto buf_get_bad_block_fail; - memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize); - total_bytes += DeviceInfo.wPageSpareSize; - -#if CMD_DMA - g_temp_buf = kmalloc(block_size, GFP_ATOMIC); - if (!g_temp_buf) - goto temp_buf_fail; - memset(g_temp_buf, 0xff, block_size); - total_bytes += block_size; - - /* Malloc memory for copy of block table used in CDMA mode */ - g_pBTStartingCopy = kmalloc(block_table_size, GFP_ATOMIC); - if (!g_pBTStartingCopy) - goto bt_starting_copy; - memset(g_pBTStartingCopy, 0, block_table_size); - total_bytes += block_table_size; - - g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy + - DeviceInfo.wDataBlockNum * sizeof(u32)); - - if (DeviceInfo.MLCDevice) - g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy + - DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8))); - - /* Malloc memory for block table copies */ - mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) + - 5 * DeviceInfo.wDataBlockNum * sizeof(u8); - if (DeviceInfo.MLCDevice) - mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16); - g_pBlockTableCopies = kmalloc(mem_size, GFP_ATOMIC); - if (!g_pBlockTableCopies) - goto blk_table_copies_fail; - memset(g_pBlockTableCopies, 0, mem_size); - total_bytes += mem_size; - g_pNextBlockTable = g_pBlockTableCopies; - - /* Malloc memory for Block Table Delta */ - mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta); - g_pBTDelta = kmalloc(mem_size, GFP_ATOMIC); - if (!g_pBTDelta) - goto bt_delta_fail; - memset(g_pBTDelta, 0, mem_size); - total_bytes += mem_size; - g_pBTDelta_Free = g_pBTDelta; - - /* Malloc memory for Copy Back Buffers */ - for (j = 0; j < COPY_BACK_BUF_NUM; j++) { - cp_back_buf_copies[j] = kmalloc(block_size, GFP_ATOMIC); - if (!cp_back_buf_copies[j]) - goto cp_back_buf_copies_fail; - memset(cp_back_buf_copies[j], 0, block_size); - total_bytes += block_size; - } - cp_back_buf_idx = 0; - - /* Malloc memory for pending commands list */ - mem_size = sizeof(struct pending_cmd) * MAX_DESCS; - info.pcmds = kzalloc(mem_size, GFP_KERNEL); - if (!info.pcmds) - goto pending_cmds_buf_fail; - total_bytes += mem_size; - - /* Malloc memory for CDMA descripter table */ - mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS; - info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL); - if (!info.cdma_desc_buf) - goto cdma_desc_buf_fail; - total_bytes += mem_size; - - /* Malloc memory for Memcpy descripter table */ - mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS; - info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL); - if (!info.memcp_desc_buf) - goto memcp_desc_buf_fail; - total_bytes += mem_size; -#endif - - nand_dbg_print(NAND_DBG_WARN, - "Total memory allocated in FTL layer: %d\n", total_bytes); - - return PASS; - -#if CMD_DMA -memcp_desc_buf_fail: - kfree(info.cdma_desc_buf); -cdma_desc_buf_fail: - kfree(info.pcmds); -pending_cmds_buf_fail: -cp_back_buf_copies_fail: - j--; - for (; j >= 0; j--) - kfree(cp_back_buf_copies[j]); - kfree(g_pBTDelta); -bt_delta_fail: - kfree(g_pBlockTableCopies); -blk_table_copies_fail: - kfree(g_pBTStartingCopy); -bt_starting_copy: - kfree(g_temp_buf); -temp_buf_fail: - kfree(buf_get_bad_block); -#endif - -buf_get_bad_block_fail: - kfree(buf_read_page_spare); -buf_read_page_spare_fail: - kfree(buf_write_page_main_spare); -buf_write_page_main_spare_fail: - kfree(buf_read_page_main_spare); -buf_read_page_main_spare_fail: - kfree(tmp_buf_read_disturbance); -tmp_buf_read_disturbance_fail: - kfree(tmp_buf_write_blk_table_data); -tmp_buf_write_blk_table_data_fail: - kfree(flags_static_wear_leveling); -flags_static_wear_leveling_fail: - kfree(tmp_buf2_read_blk_table); -tmp_buf2_read_blk_table_fail: - kfree(tmp_buf1_read_blk_table); -tmp_buf1_read_blk_table_fail: - kfree(spare_buf_bt_search_bt_in_block); -spare_buf_bt_search_bt_in_block_fail: - kfree(spare_buf_search_bt_in_block); -spare_buf_search_bt_in_block_fail: - kfree(tmp_buf_search_bt_in_block); -tmp_buf_search_bt_in_block_fail: - kfree(flag_check_blk_table); -flag_check_blk_table_fail: - kfree(g_pBTBlocks); -bt_blocks_fail: - kfree(g_pTempBuf); -Temp_buf_fail: - kfree(cache_l2_blk_buf); -cache_l2_blk_buf_fail: - kfree(cache_l2_page_buf); -cache_l2_page_buf_fail: - kfree(g_pIPF); -ipf_fail: -cache_item_fail: - i--; - for (; i >= 0; i--) - kfree(Cache.array[i].buf); - kfree(g_pBlockTable); -block_table_fail: - printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n", - __FILE__, __LINE__); - - return -ENOMEM; -} - -/* .... */ -static int free_memory(void) -{ - int i; - -#if CMD_DMA - kfree(info.memcp_desc_buf); - kfree(info.cdma_desc_buf); - kfree(info.pcmds); - for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--) - kfree(cp_back_buf_copies[i]); - kfree(g_pBTDelta); - kfree(g_pBlockTableCopies); - kfree(g_pBTStartingCopy); - kfree(g_temp_buf); - kfree(buf_get_bad_block); -#endif - kfree(buf_read_page_spare); - kfree(buf_write_page_main_spare); - kfree(buf_read_page_main_spare); - kfree(tmp_buf_read_disturbance); - kfree(tmp_buf_write_blk_table_data); - kfree(flags_static_wear_leveling); - kfree(tmp_buf2_read_blk_table); - kfree(tmp_buf1_read_blk_table); - kfree(spare_buf_bt_search_bt_in_block); - kfree(spare_buf_search_bt_in_block); - kfree(tmp_buf_search_bt_in_block); - kfree(flag_check_blk_table); - kfree(g_pBTBlocks); - kfree(g_pTempBuf); - kfree(g_pIPF); - for (i = CACHE_ITEM_NUM - 1; i >= 0; i--) - kfree(Cache.array[i].buf); - kfree(g_pBlockTable); - - return 0; -} - -static void dump_cache_l2_table(void) -{ - struct list_head *p; - struct spectra_l2_cache_list *pnd; - int n, i; - - n = 0; - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num); -/* - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { - if (pnd->pages_array[i] != MAX_U32_VALUE) - nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]); - } -*/ - n++; - } -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Init -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: allocates the memory for cache array, -* important data structures -* clears the cache array -* reads the block table from flash into array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Init(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - Cache.pages_per_item = 1; - Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize; - - if (allocate_memory() != PASS) - return FAIL; - -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_CHANS + MAX_DESCS)); -#endif - ftl_cmd_cnt = 0; -#endif - - if (FTL_Read_Block_Table() != PASS) - return FAIL; - - /* Init the Level2 Cache data structure */ - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) - cache_l2.blk_array[i] = MAX_U32_VALUE; - cache_l2.cur_blk_idx = 0; - cache_l2.cur_page_num = 0; - INIT_LIST_HEAD(&cache_l2.table.list); - cache_l2.table.logical_blk_num = MAX_U32_VALUE; - - dump_cache_l2_table(); - - return 0; -} - - -#if CMD_DMA -#if 0 -static void save_blk_table_changes(u16 idx) -{ - u8 ftl_cmd; - u32 *pbt = (u32 *)g_pBTStartingCopy; - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u16 id; - u8 cache_blks; - - id = idx - MAX_CHANS; - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = - int_cache[id].cache.changed; - } -#endif - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - - while (ftl_cmd <= PendingCMD[idx].Tag) { - if (p_BTableChangesDelta->ValidFields == 0x01) { - g_wBlockTableOffset = - p_BTableChangesDelta->g_wBlockTableOffset; - } else if (p_BTableChangesDelta->ValidFields == 0x0C) { - pbt[p_BTableChangesDelta->BT_Index] = - p_BTableChangesDelta->BT_Entry_Value; - debug_boundary_error((( - p_BTableChangesDelta->BT_Index)), - DeviceInfo.wDataBlockNum, 0); - } else if (p_BTableChangesDelta->ValidFields == 0x03) { - g_wBlockTableOffset = - p_BTableChangesDelta->g_wBlockTableOffset; - g_wBlockTableIndex = - p_BTableChangesDelta->g_wBlockTableIndex; - } else if (p_BTableChangesDelta->ValidFields == 0x30) { - g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] = - p_BTableChangesDelta->WC_Entry_Value; - } else if ((DeviceInfo.MLCDevice) && - (p_BTableChangesDelta->ValidFields == 0xC0)) { - g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] = - p_BTableChangesDelta->RC_Entry_Value; - nand_dbg_print(NAND_DBG_DEBUG, - "In event status setting read counter " - "GLOB_ftl_cmd_cnt %u Count %u Index %u\n", - ftl_cmd, - p_BTableChangesDelta->RC_Entry_Value, - (unsigned int)p_BTableChangesDelta->RC_Index); - } else { - nand_dbg_print(NAND_DBG_DEBUG, - "This should never occur \n"); - } - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } -} - -static void discard_cmds(u16 n) -{ - u32 *pbt = (u32 *)g_pBTStartingCopy; - u8 ftl_cmd; - unsigned long k; -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u8 cache_blks; - u16 id; -#endif - - if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) || - (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) { - for (k = 0; k < DeviceInfo.wDataBlockNum; k++) { - if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK))) - MARK_BLK_AS_DISCARD(pbt[k]); - } - } - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[n].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - id = n - MAX_CHANS; - - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - if (PendingCMD[n].CMD == MEMCOPY_CMD) { - if ((cache_start_copy.array[cache_blks].buf <= - PendingCMD[n].DataDestAddr) && - ((cache_start_copy.array[cache_blks].buf + - Cache.cache_item_size) > - PendingCMD[n].DataDestAddr)) { - cache_start_copy.array[cache_blks].address = - NAND_CACHE_INIT_ADDR; - cache_start_copy.array[cache_blks].use_cnt = - 0; - cache_start_copy.array[cache_blks].changed = - CLEAR; - } - } else { - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = - int_cache[id].cache.changed; - } - } -#endif -} - -static void process_cmd_pass(int *first_failed_cmd, u16 idx) -{ - if (0 == *first_failed_cmd) - save_blk_table_changes(idx); - else - discard_cmds(idx); -} - -static void process_cmd_fail_abort(int *first_failed_cmd, - u16 idx, int event) -{ - u32 *pbt = (u32 *)g_pBTStartingCopy; - u8 ftl_cmd; - unsigned long i; - int erase_fail, program_fail; -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u8 cache_blks; - u16 id; -#endif - - if (0 == *first_failed_cmd) - *first_failed_cmd = PendingCMD[idx].SBDCmdIndex; - - nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occured " - "while executing %u Command %u accesing Block %u\n", - (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt, - PendingCMD[idx].CMD, - (unsigned int)PendingCMD[idx].Block); - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[idx].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - id = idx - MAX_CHANS; - - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) { - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = SET; - } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) { - cache_start_copy.array[cache_blks].address = - NAND_CACHE_INIT_ADDR; - cache_start_copy.array[cache_blks].use_cnt = 0; - cache_start_copy.array[cache_blks].changed = - CLEAR; - } else if (PendingCMD[idx].CMD == ERASE_CMD) { - /* ? */ - } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) { - /* ? */ - } - } -#endif - - erase_fail = (event == EVENT_ERASE_FAILURE) && - (PendingCMD[idx].CMD == ERASE_CMD); - - program_fail = (event == EVENT_PROGRAM_FAILURE) && - ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) || - (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD)); - - if (erase_fail || program_fail) { - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (PendingCMD[idx].Block == - (pbt[i] & (~BAD_BLOCK))) - MARK_BLOCK_AS_BAD(pbt[i]); - } - } -} - -static void process_cmd(int *first_failed_cmd, u16 idx, int event) -{ - u8 ftl_cmd; - int cmd_match = 0; - - if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag) - cmd_match = 1; - - if (PendingCMD[idx].Status == CMD_PASS) { - process_cmd_pass(first_failed_cmd, idx); - } else if ((PendingCMD[idx].Status == CMD_FAIL) || - (PendingCMD[idx].Status == CMD_ABORT)) { - process_cmd_fail_abort(first_failed_cmd, idx, event); - } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) && - PendingCMD[idx].Tag) { - nand_dbg_print(NAND_DBG_DEBUG, - " Command no. %hu is not executed\n", - (unsigned int)PendingCMD[idx].Tag); - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[idx].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - } -} -#endif - -static void process_cmd(int *first_failed_cmd, u16 idx, int event) -{ - printk(KERN_ERR "temporary workaround function. " - "Should not be called! \n"); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Event_Status -* Inputs: none -* Outputs: Event Code -* Description: It is called by SBD after hardware interrupt signalling -* completion of commands chain -* It does following things -* get event status from LLD -* analyze command chain status -* determine last command executed -* analyze results -* rebuild the block table in case of uncorrectable error -* return event code -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Event_Status(int *first_failed_cmd) -{ - int event_code = PASS; - u16 i_P; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - *first_failed_cmd = 0; - - event_code = GLOB_LLD_Event_Status(); - - switch (event_code) { - case EVENT_PASS: - nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n"); - break; - case EVENT_UNCORRECTABLE_DATA_ERROR: - nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n"); - break; - case EVENT_PROGRAM_FAILURE: - case EVENT_ERASE_FAILURE: - nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. " - "Event code: 0x%x\n", event_code); - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta; - for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS); - i_P++) - process_cmd(first_failed_cmd, i_P, event_code); - memcpy(g_pBlockTable, g_pBTStartingCopy, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memcpy(g_pWearCounter, g_pWearCounterCopy, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memcpy(g_pReadCounter, g_pReadCounterCopy, - DeviceInfo.wDataBlockNum * sizeof(u16)); - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&Cache, (void *)&cache_start_copy, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_DESCS + MAX_CHANS)); -#endif - break; - default: - nand_dbg_print(NAND_DBG_WARN, - "Handling unexpected event code - 0x%x\n", - event_code); - event_code = ERR; - break; - } - - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memcpy(g_pWearCounterCopy, g_pWearCounter, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memcpy(g_pReadCounterCopy, g_pReadCounter, - DeviceInfo.wDataBlockNum * sizeof(u16)); - - g_pBTDelta_Free = g_pBTDelta; - ftl_cmd_cnt = 0; - g_pNextBlockTable = g_pBlockTableCopies; - cp_back_buf_idx = 0; - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_DESCS + MAX_CHANS)); -#endif - - return event_code; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: glob_ftl_execute_cmds -* Inputs: none -* Outputs: none -* Description: pass thru to LLD -***************************************************************/ -u16 glob_ftl_execute_cmds(void) -{ - nand_dbg_print(NAND_DBG_TRACE, - "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n", - (unsigned int)ftl_cmd_cnt); - g_SBDCmdIndex = 0; - return glob_lld_execute_cmds(); -} - -#endif - -#if !CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Read Immediate -* Inputs: pointer to data -* address of data -* Outputs: PASS / FAIL -* Description: Reads one page of data into RAM directly from flash without -* using or disturbing cache.It is assumed this function is called -* with CMD-DMA disabled. -*****************************************************************/ -int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr) -{ - int wResult = FAIL; - u32 Block; - u16 Page; - u32 phy_blk; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - Block = BLK_FROM_ADDR(addr); - Page = PAGE_FROM_ADDR(addr, Block); - - if (!IS_SPARE_BLOCK(Block)) - return FAIL; - - phy_blk = pbt[Block]; - wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1); - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++; - if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock] - >= MAX_READ_COUNTER) - FTL_Read_Disturbance(phy_blk); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } - - return wResult; -} -#endif - -#ifdef SUPPORT_BIG_ENDIAN -/********************************************************************* -* Function: FTL_Invert_Block_Table -* Inputs: none -* Outputs: none -* Description: Re-format the block table in ram based on BIG_ENDIAN and -* LARGE_BLOCKNUM if necessary -**********************************************************************/ -static void FTL_Invert_Block_Table(void) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#ifdef SUPPORT_LARGE_BLOCKNUM - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - pbt[i] = INVERTUINT32(pbt[i]); - g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]); - } -#else - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - pbt[i] = INVERTUINT16(pbt[i]); - g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]); - } -#endif -} -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Flash_Init -* Inputs: none -* Outputs: PASS=0 / FAIL=0x01 (based on read ID) -* Description: The flash controller is initialized -* The flash device is reset -* Perform a flash READ ID command to confirm that a -* valid device is attached and active. -* The DeviceInfo structure gets filled in -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flash_Init(void) -{ - int status = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - g_SBDCmdIndex = 0; - - GLOB_LLD_Flash_Init(); - - status = GLOB_LLD_Read_Device_ID(); - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Inputs: none -* Outputs: PASS=0 / FAIL=0x01 (based on read ID) -* Description: The flash controller is released -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return GLOB_LLD_Flash_Release(); -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Cache_Release -* Inputs: none -* Outputs: none -* Description: release all allocated memory in GLOB_FTL_Init -* (allocated in GLOB_FTL_Init) -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void GLOB_FTL_Cache_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - free_memory(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_If_Hit -* Inputs: Page Address -* Outputs: Block number/UNHIT BLOCK -* Description: Determines if the addressed page is in cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u16 FTL_Cache_If_Hit(u64 page_addr) -{ - u16 item; - u64 addr; - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - item = UNHIT_CACHE_ITEM; - for (i = 0; i < CACHE_ITEM_NUM; i++) { - addr = Cache.array[i].address; - if ((page_addr >= addr) && - (page_addr < (addr + Cache.cache_item_size))) { - item = i; - break; - } - } - - return item; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Calculate_LRU -* Inputs: None -* Outputs: None -* Description: Calculate the least recently block in a cache and record its -* index in LRU field. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Calculate_LRU(void) -{ - u16 i, bCurrentLRU, bTempCount; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bCurrentLRU = 0; - bTempCount = MAX_WORD_VALUE; - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (Cache.array[i].use_cnt < bTempCount) { - bCurrentLRU = i; - bTempCount = Cache.array[i].use_cnt; - } - } - - Cache.LRU = bCurrentLRU; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read_Page -* Inputs: pointer to read buffer, logical address and cache item number -* Outputs: None -* Description: Read the page from the cached block addressed by blocknumber -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item) -{ - u8 *start_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - start_addr = Cache.array[cache_item].buf; - start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >> - DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize); - -#if CMD_DMA - GLOB_LLD_MemCopy_CMD(data_buf, start_addr, - DeviceInfo.wPageDataSize, 0); - ftl_cmd_cnt++; -#else - memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize); -#endif - - if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE) - Cache.array[cache_item].use_cnt++; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read_All -* Inputs: pointer to read buffer,block address -* Outputs: PASS=0 / FAIL =1 -* Description: It reads pages in cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr) -{ - int wResult = PASS; - u32 Block; - u32 lba; - u16 Page; - u16 PageCount; - u32 *pbt = (u32 *)g_pBlockTable; - u32 i; - - Block = BLK_FROM_ADDR(phy_addr); - Page = PAGE_FROM_ADDR(phy_addr, Block); - PageCount = Cache.pages_per_item; - - nand_dbg_print(NAND_DBG_DEBUG, - "%s, Line %d, Function: %s, Block: 0x%x\n", - __FILE__, __LINE__, __func__, Block); - - lba = 0xffffffff; - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if ((pbt[i] & (~BAD_BLOCK)) == Block) { - lba = i; - if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) || - IS_DISCARDED_BLOCK(i)) { - /* Add by yunpeng -2008.12.3 */ -#if CMD_DMA - GLOB_LLD_MemCopy_CMD(pData, g_temp_buf, - PageCount * DeviceInfo.wPageDataSize, 0); - ftl_cmd_cnt++; -#else - memset(pData, 0xFF, - PageCount * DeviceInfo.wPageDataSize); -#endif - return wResult; - } else { - continue; /* break ?? */ - } - } - } - - if (0xffffffff == lba) - printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n"); - -#if CMD_DMA - wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page, - PageCount, LLD_CMD_FLAG_MODE_CDMA); - if (DeviceInfo.MLCDevice) { - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; - nand_dbg_print(NAND_DBG_DEBUG, - "Read Counter modified in ftl_cmd_cnt %u" - " Block %u Counter%u\n", - ftl_cmd_cnt, (unsigned int)Block, - g_pReadCounter[Block - - DeviceInfo.wSpectraStartBlock]); - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->RC_Index = - Block - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->RC_Entry_Value = - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0xC0; - - ftl_cmd_cnt++; - - if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= - MAX_READ_COUNTER) - FTL_Read_Disturbance(Block); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } else { - ftl_cmd_cnt++; - } -#else - wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount); - if (wResult == FAIL) - return wResult; - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; - if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= - MAX_READ_COUNTER) - FTL_Read_Disturbance(Block); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_All -* Inputs: pointer to cache in sys memory -* address of free block in flash -* Outputs: PASS=0 / FAIL=1 -* Description: writes all the pages of the block in cache to flash -* -* NOTE:need to make sure this works ok when cache is limited -* to a partial block. This is where copy-back would be -* activated. This would require knowing which pages in the -* cached block are clean/dirty.Right now we only know if -* the whole block is clean/dirty. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr) -{ - u16 wResult = PASS; - u32 Block; - u16 Page; - u16 PageCount; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written " - "on %d\n", cache_block_to_write, - (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)); - - Block = BLK_FROM_ADDR(blk_addr); - Page = PAGE_FROM_ADDR(blk_addr, Block); - PageCount = Cache.pages_per_item; - -#if CMD_DMA - if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData, - Block, Page, PageCount)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated! " - "Need Bad Block replacing.\n", - __FILE__, __LINE__, __func__, Block); - wResult = FAIL; - } - ftl_cmd_cnt++; -#else - if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s," - " Line %d, Function %s, new Bad Block %d generated!" - "Need Bad Block replacing.\n", - __FILE__, __LINE__, __func__, Block); - wResult = FAIL; - } -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Update_Block -* Inputs: pointer to buffer,page address,block address -* Outputs: PASS=0 / FAIL=1 -* Description: It updates the cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Update_Block(u8 *pData, - u64 old_page_addr, u64 blk_addr) -{ - int i, j; - u8 *buf = pData; - int wResult = PASS; - int wFoundInCache; - u64 page_addr; - u64 addr; - u64 old_blk_addr; - u16 page_offset; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - old_blk_addr = (u64)(old_page_addr >> - DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize; - page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >> - DeviceInfo.nBitsInPageDataSize); - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { - page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize; - if (i != page_offset) { - wFoundInCache = FAIL; - for (j = 0; j < CACHE_ITEM_NUM; j++) { - addr = Cache.array[j].address; - addr = FTL_Get_Physical_Block_Addr(addr) + - GLOB_u64_Remainder(addr, 2); - if ((addr >= page_addr) && addr < - (page_addr + Cache.cache_item_size)) { - wFoundInCache = PASS; - buf = Cache.array[j].buf; - Cache.array[j].changed = SET; -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = j; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[j].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[j].changed; -#endif -#endif - break; - } - } - if (FAIL == wFoundInCache) { - if (ERR == FTL_Cache_Read_All(g_pTempBuf, - page_addr)) { - wResult = FAIL; - break; - } - buf = g_pTempBuf; - } - } else { - buf = pData; - } - - if (FAIL == FTL_Cache_Write_All(buf, - blk_addr + (page_addr - old_blk_addr))) { - wResult = FAIL; - break; - } - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Copy_Block -* Inputs: source block address -* Destination block address -* Outputs: PASS=0 / FAIL=1 -* Description: used only for static wear leveling to move the block -* containing static data to new blocks(more worn) -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr) -{ - int i, r1, r2, wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { - r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr + - i * DeviceInfo.wPageDataSize); - r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr + - i * DeviceInfo.wPageDataSize); - if ((ERR == r1) || (FAIL == r2)) { - wResult = FAIL; - break; - } - } - - return wResult; -} - -/* Search the block table to find out the least wear block and then return it */ -static u32 find_least_worn_blk_for_l2_cache(void) -{ - int i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 least_wear_cnt = MAX_BYTE_VALUE; - u32 least_wear_blk_idx = MAX_U32_VALUE; - u32 phy_idx; - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - phy_idx = (u32)((~BAD_BLOCK) & pbt[i]); - if (phy_idx > DeviceInfo.wSpectraEndBlock) - printk(KERN_ERR "find_least_worn_blk_for_l2_cache: " - "Too big phy block num (%d)\n", phy_idx); - if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) { - least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock]; - least_wear_blk_idx = i; - } - } - } - - nand_dbg_print(NAND_DBG_WARN, - "find_least_worn_blk_for_l2_cache: " - "find block %d with least worn counter (%d)\n", - least_wear_blk_idx, least_wear_cnt); - - return least_wear_blk_idx; -} - - - -/* Get blocks for Level2 Cache */ -static int get_l2_cache_blks(void) -{ - int n; - u32 blk; - u32 *pbt = (u32 *)g_pBlockTable; - - for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) { - blk = find_least_worn_blk_for_l2_cache(); - if (blk > DeviceInfo.wDataBlockNum) { - nand_dbg_print(NAND_DBG_WARN, - "find_least_worn_blk_for_l2_cache: " - "No enough free NAND blocks (n: %d) for L2 Cache!\n", n); - return FAIL; - } - /* Tag the free block as discard in block table */ - pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK; - /* Add the free block to the L2 Cache block array */ - cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK); - } - - return PASS; -} - -static int erase_l2_cache_blocks(void) -{ - int i, ret = PASS; - u32 pblk, lblk; - u64 addr; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) { - pblk = cache_l2.blk_array[i]; - - /* If the L2 cache block is invalid, then just skip it */ - if (MAX_U32_VALUE == pblk) - continue; - - BUG_ON(pblk > DeviceInfo.wSpectraEndBlock); - - addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize; - if (PASS == GLOB_FTL_Block_Erase(addr)) { - /* Get logical block number of the erased block */ - lblk = FTL_Get_Block_Index(pblk); - BUG_ON(BAD_BLOCK == lblk); - /* Tag it as free in the block table */ - pbt[lblk] &= (u32)(~DISCARD_BLOCK); - pbt[lblk] |= (u32)(SPARE_BLOCK); - } else { - MARK_BLOCK_AS_BAD(pbt[lblk]); - ret = ERR; - } - } - - return ret; -} - -/* - * Merge the valid data page in the L2 cache blocks into NAND. -*/ -static int flush_l2_cache(void) -{ - struct list_head *p; - struct spectra_l2_cache_list *pnd, *tmp_pnd; - u32 *pbt = (u32 *)g_pBlockTable; - u32 phy_blk, l2_blk; - u64 addr; - u16 l2_page; - int i, ret = PASS; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (list_empty(&cache_l2.table.list)) /* No data to flush */ - return ret; - - //dump_cache_l2_table(); - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (IS_SPARE_BLOCK(pnd->logical_blk_num) || - IS_BAD_BLOCK(pnd->logical_blk_num) || - IS_DISCARDED_BLOCK(pnd->logical_blk_num)) { - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); - memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize); - } else { - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf, - phy_blk, 0, DeviceInfo.wPagesPerBlock); - if (ret == FAIL) { - printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); - } - } - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { - if (pnd->pages_array[i] != MAX_U32_VALUE) { - l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff]; - l2_page = pnd->pages_array[i] & 0xffff; - ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1); - if (ret == FAIL) { - printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); - } - memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize); - } - } - - /* Find a free block and tag the original block as discarded */ - addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize; - ret = FTL_Replace_Block(addr); - if (ret == FAIL) { - printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__); - } - - /* Write back the updated data into NAND */ - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { - nand_dbg_print(NAND_DBG_WARN, - "Program NAND block %d fail in %s, Line %d\n", - phy_blk, __FILE__, __LINE__); - /* This may not be really a bad block. So just tag it as discarded. */ - /* Then it has a chance to be erased when garbage collection. */ - /* If it is really bad, then the erase will fail and it will be marked */ - /* as bad then. Otherwise it will be marked as free and can be used again */ - MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]); - /* Find another free block and write it again */ - FTL_Replace_Block(addr); - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { - printk(KERN_ERR "Failed to write back block %d when flush L2 cache." - "Some data will be lost!\n", phy_blk); - MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]); - } - } else { - /* tag the new free block as used block */ - pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK); - } - } - - /* Destroy the L2 Cache table and free the memory of all nodes */ - list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) { - list_del(&pnd->list); - kfree(pnd); - } - - /* Erase discard L2 cache blocks */ - if (erase_l2_cache_blocks() != PASS) - nand_dbg_print(NAND_DBG_WARN, - " Erase L2 cache blocks error in %s, Line %d\n", - __FILE__, __LINE__); - - /* Init the Level2 Cache data structure */ - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) - cache_l2.blk_array[i] = MAX_U32_VALUE; - cache_l2.cur_blk_idx = 0; - cache_l2.cur_page_num = 0; - INIT_LIST_HEAD(&cache_l2.table.list); - cache_l2.table.logical_blk_num = MAX_U32_VALUE; - - return ret; -} - -/* - * Write back a changed victim cache item to the Level2 Cache - * and update the L2 Cache table to map the change. - * If the L2 Cache is full, then start to do the L2 Cache flush. -*/ -static int write_back_to_l2_cache(u8 *buf, u64 logical_addr) -{ - u32 logical_blk_num; - u16 logical_page_num; - struct list_head *p; - struct spectra_l2_cache_list *pnd, *pnd_new; - u32 node_size; - int i, found; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* - * If Level2 Cache table is empty, then it means either: - * 1. This is the first time that the function called after FTL_init - * or - * 2. The Level2 Cache has just been flushed - * - * So, 'steal' some free blocks from NAND for L2 Cache using - * by just mask them as discard in the block table - */ - if (list_empty(&cache_l2.table.list)) { - BUG_ON(cache_l2.cur_blk_idx != 0); - BUG_ON(cache_l2.cur_page_num!= 0); - BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE); - if (FAIL == get_l2_cache_blks()) { - GLOB_FTL_Garbage_Collection(); - if (FAIL == get_l2_cache_blks()) { - printk(KERN_ALERT "Fail to get L2 cache blks!\n"); - return FAIL; - } - } - } - - logical_blk_num = BLK_FROM_ADDR(logical_addr); - logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); - BUG_ON(logical_blk_num == MAX_U32_VALUE); - - /* Write the cache item data into the current position of L2 Cache */ -#if CMD_DMA - /* - * TODO - */ -#else - if (FAIL == GLOB_LLD_Write_Page_Main(buf, - cache_l2.blk_array[cache_l2.cur_blk_idx], - cache_l2.cur_page_num, 1)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " - "%s, Line %d, new Bad Block %d generated!\n", - __FILE__, __LINE__, - cache_l2.blk_array[cache_l2.cur_blk_idx]); - - /* TODO: tag the current block as bad and try again */ - - return FAIL; - } -#endif - - /* - * Update the L2 Cache table. - * - * First seaching in the table to see whether the logical block - * has been mapped. If not, then kmalloc a new node for the - * logical block, fill data, and then insert it to the list. - * Otherwise, just update the mapped node directly. - */ - found = 0; - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (pnd->logical_blk_num == logical_blk_num) { - pnd->pages_array[logical_page_num] = - (cache_l2.cur_blk_idx << 16) | - cache_l2.cur_page_num; - found = 1; - break; - } - } - if (!found) { /* Create new node for the logical block here */ - - /* The logical pages to physical pages map array is - * located at the end of struct spectra_l2_cache_list. - */ - node_size = sizeof(struct spectra_l2_cache_list) + - sizeof(u32) * DeviceInfo.wPagesPerBlock; - pnd_new = kmalloc(node_size, GFP_ATOMIC); - if (!pnd_new) { - printk(KERN_ERR "Failed to kmalloc in %s Line %d\n", - __FILE__, __LINE__); - /* - * TODO: Need to flush all the L2 cache into NAND ASAP - * since no memory available here - */ - } - pnd_new->logical_blk_num = logical_blk_num; - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) - pnd_new->pages_array[i] = MAX_U32_VALUE; - pnd_new->pages_array[logical_page_num] = - (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num; - list_add(&pnd_new->list, &cache_l2.table.list); - } - - /* Increasing the current position pointer of the L2 Cache */ - cache_l2.cur_page_num++; - if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) { - cache_l2.cur_blk_idx++; - if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) { - /* The L2 Cache is full. Need to flush it now */ - nand_dbg_print(NAND_DBG_WARN, - "L2 Cache is full, will start to flush it\n"); - flush_l2_cache(); - } else { - cache_l2.cur_page_num = 0; - } - } - - return PASS; -} - -/* - * Seach in the Level2 Cache table to find the cache item. - * If find, read the data from the NAND page of L2 Cache, - * Otherwise, return FAIL. - */ -static int search_l2_cache(u8 *buf, u64 logical_addr) -{ - u32 logical_blk_num; - u16 logical_page_num; - struct list_head *p; - struct spectra_l2_cache_list *pnd; - u32 tmp = MAX_U32_VALUE; - u32 phy_blk; - u16 phy_page; - int ret = FAIL; - - logical_blk_num = BLK_FROM_ADDR(logical_addr); - logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); - - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (pnd->logical_blk_num == logical_blk_num) { - tmp = pnd->pages_array[logical_page_num]; - break; - } - } - - if (tmp != MAX_U32_VALUE) { /* Found valid map */ - phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF]; - phy_page = tmp & 0xFFFF; -#if CMD_DMA - /* TODO */ -#else - ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1); -#endif - } - - return ret; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_Back -* Inputs: pointer to data cached in sys memory -* address of free block in flash -* Outputs: PASS=0 / FAIL=1 -* Description: writes all the pages of Cache Block to flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr) -{ - int i, j, iErase; - u64 old_page_addr, addr, phy_addr; - u32 *pbt = (u32 *)g_pBlockTable; - u32 lba; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) + - GLOB_u64_Remainder(blk_addr, 2); - - iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL; - - pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK); - -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = (u32)(blk_addr >> - DeviceInfo.nBitsInBlockDataSize); - p_BTableChangesDelta->BT_Entry_Value = - pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - for (i = 0; i < RETRY_TIMES; i++) { - if (PASS == iErase) { - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { - lba = BLK_FROM_ADDR(blk_addr); - MARK_BLOCK_AS_BAD(pbt[lba]); - i = RETRY_TIMES; - break; - } - } - - for (j = 0; j < CACHE_ITEM_NUM; j++) { - addr = Cache.array[j].address; - if ((addr <= blk_addr) && - ((addr + Cache.cache_item_size) > blk_addr)) - cache_block_to_write = j; - } - - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - if (PASS == FTL_Cache_Update_Block(pData, - old_page_addr, phy_addr)) { - cache_block_to_write = UNHIT_CACHE_ITEM; - break; - } else { - iErase = PASS; - } - } - - if (i >= RETRY_TIMES) { - if (ERR == FTL_Flash_Error_Handle(pData, - old_page_addr, blk_addr)) - return ERR; - else - return FAIL; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_Page -* Inputs: Pointer to buffer, page address, cache block number -* Outputs: PASS=0 / FAIL=1 -* Description: It writes the data in Cache Block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr, - u8 cache_blk, u16 flag) -{ - u8 *pDest; - u64 addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - addr = Cache.array[cache_blk].address; - pDest = Cache.array[cache_blk].buf; - - pDest += (unsigned long)(page_addr - addr); - Cache.array[cache_blk].changed = SET; -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = cache_blk; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[cache_blk].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[cache_blk].changed; -#endif - GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag); - ftl_cmd_cnt++; -#else - memcpy(pDest, pData, DeviceInfo.wPageDataSize); -#endif - if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE) - Cache.array[cache_blk].use_cnt++; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: It writes least frequently used Cache block to flash if it -* has been changed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write(void) -{ - int i, bResult = PASS; - u16 bNO, least_count = 0xFFFF; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FTL_Calculate_LRU(); - - bNO = Cache.LRU; - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: " - "Least used cache block is %d\n", bNO); - - if (Cache.array[bNO].changed != SET) - return bResult; - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache" - " Block %d containing logical block %d is dirty\n", - bNO, - (u32)(Cache.array[bNO].address >> - DeviceInfo.nBitsInBlockDataSize)); -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = bNO; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[bNO].address; - int_cache[ftl_cmd_cnt].cache.changed = CLEAR; -#endif -#endif - bResult = write_back_to_l2_cache(Cache.array[bNO].buf, - Cache.array[bNO].address); - if (bResult != ERR) - Cache.array[bNO].changed = CLEAR; - - least_count = Cache.array[bNO].use_cnt; - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (i == bNO) - continue; - if (Cache.array[i].use_cnt > 0) - Cache.array[i].use_cnt -= least_count; - } - - return bResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read -* Inputs: Page address -* Outputs: PASS=0 / FAIL=1 -* Description: It reads the block from device in Cache Block -* Set the LRU count to 1 -* Mark the Cache Block as clean -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Read(u64 logical_addr) -{ - u64 item_addr, phy_addr; - u16 num; - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - num = Cache.LRU; /* The LRU cache item will be overwritten */ - - item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) * - Cache.cache_item_size; - Cache.array[num].address = item_addr; - Cache.array[num].use_cnt = 1; - Cache.array[num].changed = CLEAR; - -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = num; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[num].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[num].changed; -#endif -#endif - /* - * Search in L2 Cache. If hit, fill data into L1 Cache item buffer, - * Otherwise, read it from NAND - */ - ret = search_l2_cache(Cache.array[num].buf, logical_addr); - if (PASS == ret) /* Hit in L2 Cache */ - return ret; - - /* Compute the physical start address of NAND device according to */ - /* the logical start address of the cache item (LRU cache item) */ - phy_addr = FTL_Get_Physical_Block_Addr(item_addr) + - GLOB_u64_Remainder(item_addr, 2); - - return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Check_Block_Table -* Inputs: ? -* Outputs: PASS=0 / FAIL=1 -* Description: It checks the correctness of each block table entry -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Check_Block_Table(int wOldTable) -{ - u32 i; - int wResult = PASS; - u32 blk_idx; - u32 *pbt = (u32 *)g_pBlockTable; - u8 *pFlag = flag_check_blk_table; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (NULL != pFlag) { - memset(pFlag, FAIL, DeviceInfo.wDataBlockNum); - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - blk_idx = (u32)(pbt[i] & (~BAD_BLOCK)); - - /* - * 20081006/KBV - Changed to pFlag[i] reference - * to avoid buffer overflow - */ - - /* - * 2008-10-20 Yunpeng Note: This change avoid - * buffer overflow, but changed function of - * the code, so it should be re-write later - */ - if ((blk_idx > DeviceInfo.wSpectraEndBlock) || - PASS == pFlag[i]) { - wResult = FAIL; - break; - } else { - pFlag[i] = PASS; - } - } - } - - return wResult; -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_Block_Table -* Inputs: flasg -* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to -* happen. -1 Error -* Description: It writes the block table -* Block table always mapped to LBA 0 which inturn mapped -* to any physical block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Write_Block_Table(int wForce) -{ - u32 *pbt = (u32 *)g_pBlockTable; - int wSuccess = PASS; - u32 wTempBlockTableIndex; - u16 bt_pages, new_bt_offset; - u8 blockchangeoccured = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) - return 0; - - if (PASS == wForce) { - g_wBlockTableOffset = - (u16)(DeviceInfo.wPagesPerBlock - bt_pages); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = - g_wBlockTableOffset; - p_BTableChangesDelta->ValidFields = 0x01; -#endif - } - - nand_dbg_print(NAND_DBG_DEBUG, - "Inside FTL_Write_Block_Table: block %d Page:%d\n", - g_wBlockTableIndex, g_wBlockTableOffset); - - do { - new_bt_offset = g_wBlockTableOffset + bt_pages + 1; - if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) || - (new_bt_offset > DeviceInfo.wPagesPerBlock) || - (FAIL == wSuccess)) { - wTempBlockTableIndex = FTL_Replace_Block_Table(); - if (BAD_BLOCK == wTempBlockTableIndex) - return ERR; - if (!blockchangeoccured) { - bt_block_changed = 1; - blockchangeoccured = 1; - } - - g_wBlockTableIndex = wTempBlockTableIndex; - g_wBlockTableOffset = 0; - pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = - g_wBlockTableOffset; - p_BTableChangesDelta->g_wBlockTableIndex = - g_wBlockTableIndex; - p_BTableChangesDelta->ValidFields = 0x03; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - BLOCK_TABLE_INDEX; - p_BTableChangesDelta->BT_Entry_Value = - pbt[BLOCK_TABLE_INDEX]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } - - wSuccess = FTL_Write_Block_Table_Data(); - if (FAIL == wSuccess) - MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); - } while (FAIL == wSuccess); - - g_cBlockTableStatus = CURRENT_BLOCK_TABLE; - - return 1; -} - -/****************************************************************** -* Function: GLOB_FTL_Flash_Format -* Inputs: none -* Outputs: PASS -* Description: The block table stores bad block info, including MDF+ -* blocks gone bad over the ages. Therefore, if we have a -* block table in place, then use it to scan for bad blocks -* If not, then scan for MDF. -* Now, a block table will only be found if spectra was already -* being used. For a fresh flash, we'll go thru scanning for -* MDF. If spectra was being used, then there is a chance that -* the MDF has been corrupted. Spectra avoids writing to the -* first 2 bytes of the spare area to all pages in a block. This -* covers all known flash devices. However, since flash -* manufacturers have no standard of where the MDF is stored, -* this cannot guarantee that the MDF is protected for future -* devices too. The initial scanning for the block table assures -* this. It is ok even if the block table is outdated, as all -* we're looking for are bad block markers. -* Use this when mounting a file system or starting a -* new flash. -* -*********************************************************************/ -static int FTL_Format_Flash(u8 valid_block_table) -{ - u32 i, j; - u32 *pbt = (u32 *)g_pBlockTable; - u32 tempNode; - int ret; - -#if CMD_DMA - u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy; - if (ftl_cmd_cnt) - return FAIL; -#endif - - if (FAIL == FTL_Check_Block_Table(FAIL)) - valid_block_table = 0; - - if (valid_block_table) { - u8 switched = 1; - u32 block, k; - - k = DeviceInfo.wSpectraStartBlock; - while (switched && (k < DeviceInfo.wSpectraEndBlock)) { - switched = 0; - k++; - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - block = (pbt[i] & ~BAD_BLOCK) - - DeviceInfo.wSpectraStartBlock; - if (block != i) { - switched = 1; - tempNode = pbt[i]; - pbt[i] = pbt[block]; - pbt[block] = tempNode; - } - } - } - if ((k == DeviceInfo.wSpectraEndBlock) && switched) - valid_block_table = 0; - } - - if (!valid_block_table) { - memset(g_pBlockTable, 0, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memset(g_pWearCounter, 0, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memset(g_pReadCounter, 0, - DeviceInfo.wDataBlockNum * sizeof(u16)); -#if CMD_DMA - memset(g_pBTStartingCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memset(g_pWearCounterCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memset(g_pReadCounterCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u16)); -#endif - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - if (GLOB_LLD_Get_Bad_Block((u32)j)) - pbt[i] = (u32)(BAD_BLOCK | j); - } - } - - nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n"); - - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) { - ret = GLOB_LLD_Erase_Block(j); - if (FAIL == ret) { - pbt[i] = (u32)(j); - MARK_BLOCK_AS_BAD(pbt[i]); - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, (int)j); - } else { - pbt[i] = (u32)(SPARE_BLOCK | j); - } - } -#if CMD_DMA - pbtStartingCopy[i] = pbt[i]; -#endif - } - - g_wBlockTableOffset = 0; - for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock)) - && ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++) - ; - if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) { - printk(KERN_ERR "All blocks bad!\n"); - return FAIL; - } else { - g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK; - if (i != BLOCK_TABLE_INDEX) { - tempNode = pbt[i]; - pbt[i] = pbt[BLOCK_TABLE_INDEX]; - pbt[BLOCK_TABLE_INDEX] = tempNode; - } - } - pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); - -#if CMD_DMA - pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); -#endif - - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - memset(g_pBTBlocks, 0xFF, - (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32)); - g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex; - FTL_Write_Block_Table(FAIL); - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - Cache.array[i].address = NAND_CACHE_INIT_ADDR; - Cache.array[i].use_cnt = 0; - Cache.array[i].changed = CLEAR; - } - -#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); -#endif - return PASS; -} - -static int force_format_nand(void) -{ - u32 i; - - /* Force erase the whole unprotected physical partiton of NAND */ - printk(KERN_ALERT "Start to force erase whole NAND device ...\n"); - printk(KERN_ALERT "From phyical block %d to %d\n", - DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock); - for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) { - if (GLOB_LLD_Erase_Block(i)) - printk(KERN_ERR "Failed to force erase NAND block %d\n", i); - } - printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n"); - while(1); - - return PASS; -} - -int GLOB_FTL_Flash_Format(void) -{ - //return FTL_Format_Flash(1); - return force_format_nand(); - -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Search_Block_Table_IN_Block -* Inputs: Block Number -* Pointer to page -* Outputs: PASS / FAIL -* Page contatining the block table -* Description: It searches the block table in the block -* passed as an argument. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, - u8 BT_Tag, u16 *Page) -{ - u16 i, j, k; - u16 Result = PASS; - u16 Last_IPF = 0; - u8 BT_Found = 0; - u8 *tagarray; - u8 *tempbuf = tmp_buf_search_bt_in_block; - u8 *pSpareBuf = spare_buf_search_bt_in_block; - u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block; - u8 bt_flag_last_page = 0xFF; - u8 search_in_previous_pages = 0; - u16 bt_pages; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, - "Searching block table in %u block\n", - (unsigned int)BT_Block); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - for (i = bt_pages; i < DeviceInfo.wPagesPerBlock; - i += (bt_pages + 1)) { - nand_dbg_print(NAND_DBG_DEBUG, - "Searching last IPF: %d\n", i); - Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf, - BT_Block, i, 1); - - if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) { - if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) { - continue; - } else { - search_in_previous_pages = 1; - Last_IPF = i; - } - } - - if (!search_in_previous_pages) { - if (i != bt_pages) { - i -= (bt_pages + 1); - Last_IPF = i; - } - } - - if (0 == Last_IPF) - break; - - if (!search_in_previous_pages) { - i = i + 1; - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i); - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, - BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag( - pSpareBufBTLastPage, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag_last_page = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found" - " in page after IPF " - "at block %d " - "page %d\n", - (int)BT_Block, i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - CURRENT_BLOCK_TABLE; - break; - } else { - Result = FAIL; - } - } - } - } - - if (search_in_previous_pages) - i = i - bt_pages; - else - i = i - (bt_pages + 1); - - Result = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %d Page %d", - (int)BT_Block, i); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, - &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) { - bt_flag_last_page = tagarray[k]; - } else { - Result = FAIL; - break; - } - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found " - "in page prior to IPF " - "at block %u page %d\n", - (unsigned int)BT_Block, i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - IN_PROGRESS_BLOCK_TABLE; - break; - } else { - Result = FAIL; - break; - } - } - } - } - - if (Result == FAIL) { - if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) { - BT_Found = 1; - *Page = i - (bt_pages + 1); - } - if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found)) - goto func_return; - } - - if (Last_IPF == 0) { - i = 0; - Result = PASS; - nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of " - "Block %u Page %u", (unsigned int)BT_Block, i); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, - &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag_last_page = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found " - "in page after IPF at " - "block %u page %u\n", - (unsigned int)BT_Block, - (unsigned int)i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - CURRENT_BLOCK_TABLE; - goto func_return; - } else { - Result = FAIL; - } - } - } - - if (Result == FAIL) - goto func_return; - } -func_return: - return Result; -} - -u8 *get_blk_table_start_addr(void) -{ - return g_pBlockTable; -} - -unsigned long get_blk_table_len(void) -{ - return DeviceInfo.wDataBlockNum * sizeof(u32); -} - -u8 *get_wear_leveling_table_start_addr(void) -{ - return g_pWearCounter; -} - -unsigned long get_wear_leveling_table_len(void) -{ - return DeviceInfo.wDataBlockNum * sizeof(u8); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Read_Block_Table -* Inputs: none -* Outputs: PASS / FAIL -* Description: read the flash spare area and find a block containing the -* most recent block table(having largest block_table_counter). -* Find the last written Block table in this block. -* Check the correctness of Block Table -* If CDMA is enabled, this function is called in -* polling mode. -* We don't need to store changes in Block table in this -* function as it is called only at initialization -* -* Note: Currently this function is called at initialization -* before any read/erase/write command issued to flash so, -* there is no need to wait for CDMA list to complete as of now -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Read_Block_Table(void) -{ - u16 i = 0; - int k, j; - u8 *tempBuf, *tagarray; - int wResult = FAIL; - int status = FAIL; - u8 block_table_found = 0; - int search_result; - u32 Block; - u16 Page = 0; - u16 PageCount; - u16 bt_pages; - int wBytesCopied = 0, tempvar; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - tempBuf = tmp_buf1_read_blk_table; - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - for (j = DeviceInfo.wSpectraStartBlock; - j <= (int)DeviceInfo.wSpectraEndBlock; - j++) { - status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1); - k = 0; - i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray); - if (i) { - status = GLOB_LLD_Read_Page_Main_Polling(tempBuf, - j, 0, 1); - for (; k < i; k++) { - if (tagarray[k] == tempBuf[3]) - break; - } - } - - if (k < i) - k = tagarray[k]; - else - continue; - - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is contained in Block %d %d\n", - (unsigned int)j, (unsigned int)k); - - if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) { - g_pBTBlocks[k-FIRST_BT_ID] = j; - block_table_found = 1; - } else { - printk(KERN_ERR "FTL_Read_Block_Table -" - "This should never happens. " - "Two block table have same counter %u!\n", k); - } - } - - if (block_table_found) { - if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL && - g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) { - j = LAST_BT_ID; - while ((j > FIRST_BT_ID) && - (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL)) - j--; - if (j == FIRST_BT_ID) { - j = LAST_BT_ID; - last_erased = LAST_BT_ID; - } else { - last_erased = (u8)j + 1; - while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL == - g_pBTBlocks[j - FIRST_BT_ID])) - j--; - } - } else { - j = FIRST_BT_ID; - while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL) - j++; - last_erased = (u8)j; - while ((j < LAST_BT_ID) && (BTBLOCK_INVAL != - g_pBTBlocks[j - FIRST_BT_ID])) - j++; - if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL) - j--; - } - - if (last_erased > j) - j += (1 + LAST_BT_ID - FIRST_BT_ID); - - for (; (j >= last_erased) && (FAIL == wResult); j--) { - i = (j - FIRST_BT_ID) % - (1 + LAST_BT_ID - FIRST_BT_ID); - search_result = - FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i], - i + FIRST_BT_ID, &Page); - if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) - block_table_found = 0; - - while ((search_result == PASS) && (FAIL == wResult)) { - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Read_Block_Table:" - "Block: %u Page: %u " - "contains block table\n", - (unsigned int)g_pBTBlocks[i], - (unsigned int)Page); - - tempBuf = tmp_buf2_read_blk_table; - - for (k = 0; k < bt_pages; k++) { - Block = g_pBTBlocks[i]; - PageCount = 1; - - status = - GLOB_LLD_Read_Page_Main_Polling( - tempBuf, Block, Page, PageCount); - - tempvar = k ? 0 : 4; - - wBytesCopied += - FTL_Copy_Block_Table_From_Flash( - tempBuf + tempvar, - DeviceInfo.wPageDataSize - tempvar, - wBytesCopied); - - Page++; - } - - wResult = FTL_Check_Block_Table(FAIL); - if (FAIL == wResult) { - block_table_found = 0; - if (Page > bt_pages) - Page -= ((bt_pages<<1) + 1); - else - search_result = FAIL; - } - } - } - } - - if (PASS == wResult) { - if (!block_table_found) - FTL_Execute_SPL_Recovery(); - - if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) - g_wBlockTableOffset = (u16)Page + 1; - else - g_wBlockTableOffset = (u16)Page - bt_pages; - - g_wBlockTableIndex = (u32)g_pBTBlocks[i]; - -#if CMD_DMA - if (DeviceInfo.MLCDevice) - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32) - + DeviceInfo.wDataBlockNum * sizeof(u8) - + DeviceInfo.wDataBlockNum * sizeof(u16)); - else - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32) - + DeviceInfo.wDataBlockNum * sizeof(u8)); -#endif - } - - if (FAIL == wResult) - printk(KERN_ERR "Yunpeng - " - "Can not find valid spectra block table!\n"); - -#if AUTO_FORMAT_FLASH - if (FAIL == wResult) { - nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n"); - wResult = FTL_Format_Flash(0); - } -#endif - - return wResult; -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Flash_Error_Handle -* Inputs: Pointer to data -* Page address -* Block address -* Outputs: PASS=0 / FAIL=1 -* Description: It handles any error occured during Spectra operation -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, - u64 blk_addr) -{ - u32 i; - int j; - u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr); - u64 phy_addr; - int wErase = FAIL; - int wResult = FAIL; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (ERR == GLOB_FTL_Garbage_Collection()) - return ERR; - - do { - for (i = DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock; - i > 0; i--) { - if (IS_SPARE_BLOCK(i)) { - tmp_node = (u32)(BAD_BLOCK | - pbt[blk_node]); - pbt[blk_node] = (u32)(pbt[i] & - (~SPARE_BLOCK)); - pbt[i] = tmp_node; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - blk_node; - p_BTableChangesDelta->BT_Entry_Value = - pbt[blk_node]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = i; - p_BTableChangesDelta->BT_Entry_Value = pbt[i]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - wResult = PASS; - break; - } - } - - if (FAIL == wResult) { - if (FAIL == GLOB_FTL_Garbage_Collection()) - break; - else - continue; - } - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - - for (j = 0; j < RETRY_TIMES; j++) { - if (PASS == wErase) { - if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { - MARK_BLOCK_AS_BAD(pbt[blk_node]); - break; - } - } - if (PASS == FTL_Cache_Update_Block(pData, - old_page_addr, - phy_addr)) { - wResult = PASS; - break; - } else { - wResult = FAIL; - wErase = PASS; - } - } - } while (FAIL == wResult); - - FTL_Write_Block_Table(FAIL); - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Page_Num -* Inputs: Size in bytes -* Outputs: Size in pages -* Description: It calculates the pages required for the length passed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Get_Page_Num(u64 length) -{ - return (u32)((length >> DeviceInfo.nBitsInPageDataSize) + - (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0)); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Physical_Block_Addr -* Inputs: Block Address (byte format) -* Outputs: Physical address of the block. -* Description: It translates LBA to PBA by returning address stored -* at the LBA location in the block table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr) -{ - u32 *pbt; - u64 physical_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - pbt = (u32 *)g_pBlockTable; - physical_addr = (u64) DeviceInfo.wBlockDataSize * - (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK)); - - return physical_addr; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Block_Index -* Inputs: Physical Block no. -* Outputs: Logical block no. /BAD_BLOCK -* Description: It returns the logical block no. for the PBA passed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Get_Block_Index(u32 wBlockNum) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) - if (wBlockNum == (pbt[i] & (~BAD_BLOCK))) - return i; - - return BAD_BLOCK; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Wear_Leveling -* Inputs: none -* Outputs: PASS=0 -* Description: This is static wear leveling (done by explicit call) -* do complete static wear leveling -* do complete garbage collection -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Wear_Leveling(void) -{ - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FTL_Static_Wear_Leveling(); - GLOB_FTL_Garbage_Collection(); - - return PASS; -} - -static void find_least_most_worn(u8 *chg, - u32 *least_idx, u8 *least_cnt, - u32 *most_idx, u8 *most_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 idx; - u8 cnt; - int i; - - for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_BAD_BLOCK(i) || PASS == chg[i]) - continue; - - idx = (u32) ((~BAD_BLOCK) & pbt[i]); - cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock]; - - if (IS_SPARE_BLOCK(i)) { - if (cnt > *most_cnt) { - *most_cnt = cnt; - *most_idx = idx; - } - } - - if (IS_DATA_BLOCK(i)) { - if (cnt < *least_cnt) { - *least_cnt = cnt; - *least_idx = idx; - } - } - - if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) { - debug_boundary_error(*most_idx, - DeviceInfo.wDataBlockNum, 0); - debug_boundary_error(*least_idx, - DeviceInfo.wDataBlockNum, 0); - continue; - } - } -} - -static int move_blks_for_wear_leveling(u8 *chg, - u32 *least_idx, u32 *rep_blk_num, int *result) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 rep_blk; - int j, ret_cp_blk, ret_erase; - int ret = PASS; - - chg[*least_idx] = PASS; - debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0); - - rep_blk = FTL_Replace_MWBlock(); - if (rep_blk != BAD_BLOCK) { - nand_dbg_print(NAND_DBG_DEBUG, - "More than two spare blocks exist so do it\n"); - nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n", - rep_blk); - - chg[rep_blk] = PASS; - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - for (j = 0; j < RETRY_TIMES; j++) { - ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) * - DeviceInfo.wBlockDataSize, - (u64)rep_blk * DeviceInfo.wBlockDataSize); - if (FAIL == ret_cp_blk) { - ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk - * DeviceInfo.wBlockDataSize); - if (FAIL == ret_erase) - MARK_BLOCK_AS_BAD(pbt[rep_blk]); - } else { - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Copy_Block == OK\n"); - break; - } - } - - if (j < RETRY_TIMES) { - u32 tmp; - u32 old_idx = FTL_Get_Block_Index(*least_idx); - u32 rep_idx = FTL_Get_Block_Index(rep_blk); - tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]); - pbt[old_idx] = (u32)((~SPARE_BLOCK) & - pbt[rep_idx]); - pbt[rep_idx] = tmp; -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = old_idx; - p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = rep_idx; - p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } else { - pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK; -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - FTL_Get_Block_Index(rep_blk); - p_BTableChangesDelta->BT_Entry_Value = - pbt[FTL_Get_Block_Index(rep_blk)]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - *result = FAIL; - ret = FAIL; - } - - if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM) - ret = FAIL; - } else { - printk(KERN_ERR "Less than 3 spare blocks exist so quit\n"); - ret = FAIL; - } - - return ret; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Static_Wear_Leveling -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: This is static wear leveling (done by explicit call) -* search for most&least used -* if difference < GATE: -* update the block table with exhange -* mark block table in flash as IN_PROGRESS -* copy flash block -* the caller should handle GC clean up after calling this function -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Static_Wear_Leveling(void) -{ - u8 most_worn_cnt; - u8 least_worn_cnt; - u32 most_worn_idx; - u32 least_worn_idx; - int result = PASS; - int go_on = PASS; - u32 replaced_blks = 0; - u8 *chang_flag = flags_static_wear_leveling; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!chang_flag) - return FAIL; - - memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum); - while (go_on == PASS) { - nand_dbg_print(NAND_DBG_DEBUG, - "starting static wear leveling\n"); - most_worn_cnt = 0; - least_worn_cnt = 0xFF; - least_worn_idx = BLOCK_TABLE_INDEX; - most_worn_idx = BLOCK_TABLE_INDEX; - - find_least_most_worn(chang_flag, &least_worn_idx, - &least_worn_cnt, &most_worn_idx, &most_worn_cnt); - - nand_dbg_print(NAND_DBG_DEBUG, - "Used and least worn is block %u, whos count is %u\n", - (unsigned int)least_worn_idx, - (unsigned int)least_worn_cnt); - - nand_dbg_print(NAND_DBG_DEBUG, - "Free and most worn is block %u, whos count is %u\n", - (unsigned int)most_worn_idx, - (unsigned int)most_worn_cnt); - - if ((most_worn_cnt > least_worn_cnt) && - (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE)) - go_on = move_blks_for_wear_leveling(chang_flag, - &least_worn_idx, &replaced_blks, &result); - else - go_on = FAIL; - } - - return result; -} - -#if CMD_DMA -static int do_garbage_collection(u32 discard_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 pba; - u8 bt_block_erased = 0; - int i, cnt, ret = FAIL; - u64 addr; - - i = 0; - while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) && - ((ftl_cmd_cnt + 28) < 256)) { - if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[i] & DISCARD_BLOCK)) { - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - pba = BLK_FROM_ADDR(addr); - - for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { - if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase BT block %u\n", - (unsigned int)pba); - discard_cnt--; - i++; - bt_block_erased = 1; - break; - } - } - - if (bt_block_erased) { - bt_block_erased = 0; - continue; - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[i] &= (u32)(~DISCARD_BLOCK); - pbt[i] |= (u32)(SPARE_BLOCK); - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt - 1; - p_BTableChangesDelta->BT_Index = i; - p_BTableChangesDelta->BT_Entry_Value = pbt[i]; - p_BTableChangesDelta->ValidFields = 0x0C; - discard_cnt--; - ret = PASS; - } else { - MARK_BLOCK_AS_BAD(pbt[i]); - } - } - - i++; - } - - return ret; -} - -#else -static int do_garbage_collection(u32 discard_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 pba; - u8 bt_block_erased = 0; - int i, cnt, ret = FAIL; - u64 addr; - - i = 0; - while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) { - if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[i] & DISCARD_BLOCK)) { - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - pba = BLK_FROM_ADDR(addr); - - for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { - if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase BT block %d\n", - pba); - discard_cnt--; - i++; - bt_block_erased = 1; - break; - } - } - - if (bt_block_erased) { - bt_block_erased = 0; - continue; - } - - /* If the discard block is L2 cache block, then just skip it */ - for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) { - if (cache_l2.blk_array[cnt] == pba) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase L2 cache blk %d\n", - pba); - break; - } - } - if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */ - discard_cnt--; - i++; - continue; - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[i] &= (u32)(~DISCARD_BLOCK); - pbt[i] |= (u32)(SPARE_BLOCK); - discard_cnt--; - ret = PASS; - } else { - MARK_BLOCK_AS_BAD(pbt[i]); - } - } - - i++; - } - - return ret; -} -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Garbage_Collection -* Inputs: none -* Outputs: PASS / FAIL (returns the number of un-erased blocks -* Description: search the block table for all discarded blocks to erase -* for each discarded block: -* set the flash block to IN_PROGRESS -* erase the block -* update the block table -* write the block table to flash -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Garbage_Collection(void) -{ - u32 i; - u32 wDiscard = 0; - int wResult = FAIL; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (GC_Called) { - printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() " - "has been re-entered! Exit.\n"); - return PASS; - } - - GC_Called = 1; - - GLOB_FTL_BT_Garbage_Collection(); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_DISCARDED_BLOCK(i)) - wDiscard++; - } - - if (wDiscard <= 0) { - GC_Called = 0; - return wResult; - } - - nand_dbg_print(NAND_DBG_DEBUG, - "Found %d discarded blocks\n", wDiscard); - - FTL_Write_Block_Table(FAIL); - - wResult = do_garbage_collection(wDiscard); - - FTL_Write_Block_Table(FAIL); - - GC_Called = 0; - - return wResult; -} - - -#if CMD_DMA -static int do_bt_garbage_collection(void) -{ - u32 pba, lba; - u32 *pbt = (u32 *)g_pBlockTable; - u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; - u64 addr; - int i, ret = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (BT_GC_Called) - return PASS; - - BT_GC_Called = 1; - - for (i = last_erased; (i <= LAST_BT_ID) && - (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + - FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) && - ((ftl_cmd_cnt + 28)) < 256; i++) { - pba = pBTBlocksNode[i - FIRST_BT_ID]; - lba = FTL_Get_Block_Index(pba); - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection: pba %d, lba %d\n", - pba, lba); - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Entry: %d", pbt[lba]); - - if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[lba] & DISCARD_BLOCK)) { - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection_cdma: " - "Erasing Block tables present in block %d\n", - pba); - addr = FTL_Get_Physical_Block_Addr((u64)lba * - DeviceInfo.wBlockDataSize); - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[lba] &= (u32)(~DISCARD_BLOCK); - pbt[lba] |= (u32)(SPARE_BLOCK); - - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt - 1; - p_BTableChangesDelta->BT_Index = lba; - p_BTableChangesDelta->BT_Entry_Value = - pbt[lba]; - - p_BTableChangesDelta->ValidFields = 0x0C; - - ret = PASS; - pBTBlocksNode[last_erased - FIRST_BT_ID] = - BTBLOCK_INVAL; - nand_dbg_print(NAND_DBG_DEBUG, - "resetting bt entry at index %d " - "value %d\n", i, - pBTBlocksNode[i - FIRST_BT_ID]); - if (last_erased == LAST_BT_ID) - last_erased = FIRST_BT_ID; - else - last_erased++; - } else { - MARK_BLOCK_AS_BAD(pbt[lba]); - } - } - } - - BT_GC_Called = 0; - - return ret; -} - -#else -static int do_bt_garbage_collection(void) -{ - u32 pba, lba; - u32 *pbt = (u32 *)g_pBlockTable; - u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; - u64 addr; - int i, ret = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (BT_GC_Called) - return PASS; - - BT_GC_Called = 1; - - for (i = last_erased; (i <= LAST_BT_ID) && - (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + - FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) { - pba = pBTBlocksNode[i - FIRST_BT_ID]; - lba = FTL_Get_Block_Index(pba); - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection_cdma: pba %d, lba %d\n", - pba, lba); - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Entry: %d", pbt[lba]); - - if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[lba] & DISCARD_BLOCK)) { - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection: " - "Erasing Block tables present in block %d\n", - pba); - addr = FTL_Get_Physical_Block_Addr((u64)lba * - DeviceInfo.wBlockDataSize); - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[lba] &= (u32)(~DISCARD_BLOCK); - pbt[lba] |= (u32)(SPARE_BLOCK); - ret = PASS; - pBTBlocksNode[last_erased - FIRST_BT_ID] = - BTBLOCK_INVAL; - nand_dbg_print(NAND_DBG_DEBUG, - "resetting bt entry at index %d " - "value %d\n", i, - pBTBlocksNode[i - FIRST_BT_ID]); - if (last_erased == LAST_BT_ID) - last_erased = FIRST_BT_ID; - else - last_erased++; - } else { - MARK_BLOCK_AS_BAD(pbt[lba]); - } - } - } - - BT_GC_Called = 0; - - return ret; -} - -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_BT_Garbage_Collection -* Inputs: none -* Outputs: PASS / FAIL (returns the number of un-erased blocks -* Description: Erases discarded blocks containing Block table -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_BT_Garbage_Collection(void) -{ - return do_bt_garbage_collection(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_OneBlock -* Inputs: Block number 1 -* Block number 2 -* Outputs: Replaced Block Number -* Description: Interchange block table entries at wBlockNum and wReplaceNum -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk) -{ - u32 tmp_blk; - u32 replace_node = BAD_BLOCK; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (rep_blk != BAD_BLOCK) { - if (IS_BAD_BLOCK(blk)) - tmp_blk = pbt[blk]; - else - tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]); - - replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]); - pbt[blk] = replace_node; - pbt[rep_blk] = tmp_blk; - -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[blk]; - - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = rep_blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } - - return replace_node; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_Block_Table_Data -* Inputs: Block table size in pages -* Outputs: PASS=0 / FAIL=1 -* Description: Write block table data in flash -* If first page and last page -* Write data+BT flag -* else -* Write data -* BT flag is a counter. Its value is incremented for block table -* write in a new Block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Write_Block_Table_Data(void) -{ - u64 dwBlockTableAddr, pTempAddr; - u32 Block; - u16 Page, PageCount; - u8 *tempBuf = tmp_buf_write_blk_table_data; - int wBytesCopied; - u16 bt_pages; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dwBlockTableAddr = - (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize + - (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize); - pTempAddr = dwBlockTableAddr; - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: " - "page= %d BlockTableIndex= %d " - "BlockTableOffset=%d\n", bt_pages, - g_wBlockTableIndex, g_wBlockTableOffset); - - Block = BLK_FROM_ADDR(pTempAddr); - Page = PAGE_FROM_ADDR(pTempAddr, Block); - PageCount = 1; - - if (bt_block_changed) { - if (bt_flag == LAST_BT_ID) { - bt_flag = FIRST_BT_ID; - g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; - } else if (bt_flag < LAST_BT_ID) { - bt_flag++; - g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; - } - - if ((bt_flag > (LAST_BT_ID-4)) && - g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != - BTBLOCK_INVAL) { - bt_block_changed = 0; - GLOB_FTL_BT_Garbage_Collection(); - } - - bt_block_changed = 0; - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Counter is %u Block %u\n", - bt_flag, (unsigned int)Block); - } - - memset(tempBuf, 0, 3); - tempBuf[3] = bt_flag; - wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4, - DeviceInfo.wPageDataSize - 4, 0); - memset(&tempBuf[wBytesCopied + 4], 0xff, - DeviceInfo.wPageSize - (wBytesCopied + 4)); - FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize], - bt_flag); - -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - DeviceInfo.wPageSize * sizeof(u8)); - nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table " - "Block %u Page %u\n", (unsigned int)Block, Page); - if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable, - Block, Page, 1, - LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } - - ftl_cmd_cnt++; - g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8))); -#else - if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } -#endif - - if (bt_pages > 1) { - PageCount = bt_pages - 1; - if (PageCount > 1) { - wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf, - DeviceInfo.wPageDataSize * (PageCount - 1), - wBytesCopied); - -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - (PageCount - 1) * DeviceInfo.wPageDataSize); - if (FAIL == GLOB_LLD_Write_Page_Main_cdma( - g_pNextBlockTable, Block, Page + 1, - PageCount - 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)Block); - goto func_return; - } - - ftl_cmd_cnt++; - g_pNextBlockTable += (PageCount - 1) * - DeviceInfo.wPageDataSize * sizeof(u8); -#else - if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf, - Block, Page + 1, PageCount - 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)Block); - goto func_return; - } -#endif - } - - wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf, - DeviceInfo.wPageDataSize, wBytesCopied); - memset(&tempBuf[wBytesCopied], 0xff, - DeviceInfo.wPageSize-wBytesCopied); - FTL_Insert_Block_Table_Signature( - &tempBuf[DeviceInfo.wPageDataSize], bt_flag); -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - DeviceInfo.wPageSize * sizeof(u8)); - nand_dbg_print(NAND_DBG_DEBUG, - "Writing the last Page of Block Table " - "Block %u Page %u\n", - (unsigned int)Block, Page + bt_pages - 1); - if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma( - g_pNextBlockTable, Block, Page + bt_pages - 1, 1, - LLD_CMD_FLAG_MODE_CDMA | - LLD_CMD_FLAG_ORDER_BEFORE_REST)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } - ftl_cmd_cnt++; -#else - if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, - Block, Page+bt_pages - 1, 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } -#endif - } - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n"); - -func_return: - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_Block_Table -* Inputs: None -* Outputs: PASS=0 / FAIL=1 -* Description: Get a new block to write block table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_Block_Table(void) -{ - u32 blk; - int gc; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); - - if ((BAD_BLOCK == blk) && (PASS == gc)) { - GLOB_FTL_Garbage_Collection(); - blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); - } - if (BAD_BLOCK == blk) - printk(KERN_ERR "%s, %s: There is no spare block. " - "It should never happen\n", - __FILE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk); - - return blk; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_LWBlock -* Inputs: Block number -* Pointer to Garbage Collect flag -* Outputs: -* Description: Determine the least weared block by traversing -* block table -* Set Garbage collection to be called if number of spare -* block is less than Free Block Gate count -* Change Block table entry to map least worn block for current -* operation -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 wLeastWornCounter = 0xFF; - u32 wLeastWornIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - u32 wDiscardBlockNum = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (IS_SPARE_BLOCK(wBlockNum)) { - *pGarbageCollect = FAIL; - pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK)); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = (u32)(wBlockNum); - p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - return pbt[wBlockNum]; - } - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_DISCARDED_BLOCK(i)) - wDiscardBlockNum++; - - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]); - if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock) - printk(KERN_ERR "FTL_Replace_LWBlock: " - "This should never occur!\n"); - if (g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] < - wLeastWornCounter) { - wLeastWornCounter = - g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wLeastWornIndex = i; - } - wSpareBlockNum++; - } - } - - nand_dbg_print(NAND_DBG_WARN, - "FTL_Replace_LWBlock: Least Worn Counter %d\n", - (int)wLeastWornCounter); - - if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) || - (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE)) - *pGarbageCollect = PASS; - else - *pGarbageCollect = FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Replace_LWBlock: Discarded Blocks %u Spare" - " Blocks %u\n", - (unsigned int)wDiscardBlockNum, - (unsigned int)wSpareBlockNum); - - return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_MWBlock -* Inputs: None -* Outputs: most worn spare block no./BAD_BLOCK -* Description: It finds most worn spare block. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_MWBlock(void) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 wMostWornCounter = 0; - u32 wMostWornIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]); - if (g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] > - wMostWornCounter) { - wMostWornCounter = - g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wMostWornIndex = wPhysicalIndex; - } - wSpareBlockNum++; - } - } - - if (wSpareBlockNum <= 2) - return BAD_BLOCK; - - return wMostWornIndex; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_Block -* Inputs: Block Address -* Outputs: PASS=0 / FAIL=1 -* Description: If block specified by blk_addr parameter is not free, -* replace it with the least worn block. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Replace_Block(u64 blk_addr) -{ - u32 current_blk = BLK_FROM_ADDR(blk_addr); - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - int GarbageCollect = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (IS_SPARE_BLOCK(current_blk)) { - pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk]; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = current_blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk]; - p_BTableChangesDelta->ValidFields = 0x0C ; -#endif - return wResult; - } - - FTL_Replace_LWBlock(current_blk, &GarbageCollect); - - if (PASS == GarbageCollect) - wResult = GLOB_FTL_Garbage_Collection(); - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Is_BadBlock -* Inputs: block number to test -* Outputs: PASS (block is BAD) / FAIL (block is not bad) -* Description: test if this block number is flagged as bad -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Is_BadBlock(u32 wBlockNum) -{ - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (wBlockNum >= DeviceInfo.wSpectraStartBlock - && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK)) - return PASS; - else - return FAIL; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Flush_Cache -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: flush all the cache blocks to flash -* if a cache block is not dirty, don't do anything with it -* else, write the block and update the block table -* Note: This function should be called at shutdown/power down. -* to write important data into device -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flush_Cache(void) -{ - int i, ret; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (SET == Cache.array[i].changed) { -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = i; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[i].address; - int_cache[ftl_cmd_cnt].cache.changed = CLEAR; -#endif -#endif - ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address); - if (PASS == ret) { - Cache.array[i].changed = CLEAR; - } else { - printk(KERN_ALERT "Failed when write back to L2 cache!\n"); - /* TODO - How to handle this? */ - } - } - } - - flush_l2_cache(); - - return FTL_Write_Block_Table(FAIL); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Page_Read -* Inputs: pointer to data -* logical address of data (u64 is LBA * Bytes/Page) -* Outputs: PASS=0 / FAIL=1 -* Description: reads a page of data into RAM from the cache -* if the data is not already in cache, read from flash to cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr) -{ - u16 cache_item; - int res = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - " - "page_addr: %llu\n", logical_addr); - - cache_item = FTL_Cache_If_Hit(logical_addr); - - if (UNHIT_CACHE_ITEM == cache_item) { - nand_dbg_print(NAND_DBG_DEBUG, - "GLOB_FTL_Page_Read: Cache not hit\n"); - res = FTL_Cache_Write(); - if (ERR == FTL_Cache_Read(logical_addr)) - res = ERR; - cache_item = Cache.LRU; - } - - FTL_Cache_Read_Page(data, logical_addr, cache_item); - - return res; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Page_Write -* Inputs: pointer to data -* address of data (ADDRESSTYPE is LBA * Bytes/Page) -* Outputs: PASS=0 / FAIL=1 -* Description: writes a page of data from RAM to the cache -* if the data is not already in cache, write back the -* least recently used block and read the addressed block -* from flash to cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr) -{ - u16 cache_blk; - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - " - "dwPageAddr: %llu\n", dwPageAddr); - - cache_blk = FTL_Cache_If_Hit(dwPageAddr); - - if (UNHIT_CACHE_ITEM == cache_blk) { - wResult = FTL_Cache_Write(); - if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) { - wResult = FTL_Replace_Block(dwPageAddr); - pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK; - if (wResult == FAIL) - return FAIL; - } - if (ERR == FTL_Cache_Read(dwPageAddr)) - wResult = ERR; - cache_blk = Cache.LRU; - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); - } else { -#if CMD_DMA - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, - LLD_CMD_FLAG_ORDER_BEFORE_REST); -#else - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); -#endif - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Block_Erase -* Inputs: address of block to erase (now in byte format, should change to -* block format) -* Outputs: PASS=0 / FAIL=1 -* Description: erases the specified block -* increments the erase count -* If erase count reaches its upper limit,call function to -* do the ajustment as per the relative erase count values -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Block_Erase(u64 blk_addr) -{ - int status; - u32 BlkIdx; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize); - - if (BlkIdx < DeviceInfo.wSpectraStartBlock) { - printk(KERN_ERR "GLOB_FTL_Block_Erase: " - "This should never occur\n"); - return FAIL; - } - -#if CMD_DMA - status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA); - if (status == FAIL) - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, BlkIdx); -#else - status = GLOB_LLD_Erase_Block(BlkIdx); - if (status == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, BlkIdx); - return status; - } -#endif - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0; - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } - - g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++; - -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = - BlkIdx - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; - - if (DeviceInfo.MLCDevice) { - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->RC_Index = - BlkIdx - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->RC_Entry_Value = - g_pReadCounter[BlkIdx - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0xC0; - } - - ftl_cmd_cnt++; -#endif - - if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE) - FTL_Adjust_Relative_Erase_Count(BlkIdx); - - return status; -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Adjust_Relative_Erase_Count -* Inputs: index to block that was just incremented and is at the max -* Outputs: PASS=0 / FAIL=1 -* Description: If any erase counts at MAX, adjusts erase count of every -* block by substracting least worn -* counter from counter value of every entry in wear table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX) -{ - u8 wLeastWornCounter = MAX_BYTE_VALUE; - u8 wWearCounter; - u32 i, wWearIndex; - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_BAD_BLOCK(i)) - continue; - wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); - - if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0) - printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:" - "This should never occur\n"); - wWearCounter = g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock]; - if (wWearCounter < wLeastWornCounter) - wLeastWornCounter = wWearCounter; - } - - if (wLeastWornCounter == 0) { - nand_dbg_print(NAND_DBG_WARN, - "Adjusting Wear Levelling Counters: Special Case\n"); - g_pWearCounter[Index_of_MAX - - DeviceInfo.wSpectraStartBlock]--; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = - Index_of_MAX - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[Index_of_MAX - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; -#endif - FTL_Static_Wear_Leveling(); - } else { - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) - if (!IS_BAD_BLOCK(i)) { - wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); - g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock] = - (u8)(g_pWearCounter - [wWearIndex - - DeviceInfo.wSpectraStartBlock] - - wLeastWornCounter); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = wWearIndex - - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; -#endif - } - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_IN_Progress_Block_Table_Page -* Inputs: None -* Outputs: None -* Description: It writes in-progress flag page to the page next to -* block table -***********************************************************************/ -static int FTL_Write_IN_Progress_Block_Table_Page(void) -{ - int wResult = PASS; - u16 bt_pages; - u16 dwIPFPageAddr; -#if CMD_DMA -#else - u32 *pbt = (u32 *)g_pBlockTable; - u32 wTempBlockTableIndex; -#endif - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - dwIPFPageAddr = g_wBlockTableOffset + bt_pages; - - nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at " - "Block %d Page %d\n", - g_wBlockTableIndex, dwIPFPageAddr); - -#if CMD_DMA - wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF, - g_wBlockTableIndex, dwIPFPageAddr, 1, - LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - g_wBlockTableIndex); - } - g_wBlockTableOffset = dwIPFPageAddr + 1; - p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset; - p_BTableChangesDelta->ValidFields = 0x01; - ftl_cmd_cnt++; -#else - wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF, - g_wBlockTableIndex, dwIPFPageAddr, 1); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)g_wBlockTableIndex); - MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); - wTempBlockTableIndex = FTL_Replace_Block_Table(); - bt_block_changed = 1; - if (BAD_BLOCK == wTempBlockTableIndex) - return ERR; - g_wBlockTableIndex = wTempBlockTableIndex; - g_wBlockTableOffset = 0; - /* Block table tag is '00'. Means it's used one */ - pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; - return FAIL; - } - g_wBlockTableOffset = dwIPFPageAddr + 1; -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Read_Disturbance -* Inputs: block address -* Outputs: PASS=0 / FAIL=1 -* Description: used to handle read disturbance. Data in block that -* reaches its read limit is moved to new block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Read_Disturbance(u32 blk_addr) -{ - int wResult = FAIL; - u32 *pbt = (u32 *) g_pBlockTable; - u32 dwOldBlockAddr = blk_addr; - u32 wBlockNum; - u32 i; - u32 wLeastReadCounter = 0xFFFF; - u32 wLeastReadIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - u32 wTempNode; - u32 wReplacedNode; - u8 *g_pTempBuf; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#if CMD_DMA - g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx]; - cp_back_buf_idx++; - if (cp_back_buf_idx > COPY_BACK_BUF_NUM) { - printk(KERN_ERR "cp_back_buf_copies overflow! Exit." - "Maybe too many pending commands in your CDMA chain.\n"); - return FAIL; - } -#else - g_pTempBuf = tmp_buf_read_disturbance; -#endif - - wBlockNum = FTL_Get_Block_Index(blk_addr); - - do { - /* This is a bug.Here 'i' should be logical block number - * and start from 1 (0 is reserved for block table). - * Have fixed it. - Yunpeng 2008. 12. 19 - */ - for (i = 1; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = - (u32)((~SPARE_BLOCK) & pbt[i]); - if (g_pReadCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] < - wLeastReadCounter) { - wLeastReadCounter = - g_pReadCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wLeastReadIndex = i; - } - wSpareBlockNum++; - } - } - - if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) { - wResult = GLOB_FTL_Garbage_Collection(); - if (PASS == wResult) - continue; - else - break; - } else { - wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]); - wReplacedNode = (u32)((~SPARE_BLOCK) & - pbt[wLeastReadIndex]); -#if CMD_DMA - pbt[wBlockNum] = wReplacedNode; - pbt[wLeastReadIndex] = wTempNode; - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = wBlockNum; - p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = wLeastReadIndex; - p_BTableChangesDelta->BT_Entry_Value = - pbt[wLeastReadIndex]; - p_BTableChangesDelta->ValidFields = 0x0C; - - wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf, - dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock, - LLD_CMD_FLAG_MODE_CDMA); - if (wResult == FAIL) - return wResult; - - ftl_cmd_cnt++; - - if (wResult != FAIL) { - if (FAIL == GLOB_LLD_Write_Page_Main_cdma( - g_pTempBuf, pbt[wBlockNum], 0, - DeviceInfo.wPagesPerBlock)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)pbt[wBlockNum]); - wResult = FAIL; - MARK_BLOCK_AS_BAD(pbt[wBlockNum]); - } - ftl_cmd_cnt++; - } -#else - wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf, - dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock); - if (wResult == FAIL) - return wResult; - - if (wResult != FAIL) { - /* This is a bug. At this time, pbt[wBlockNum] - is still the physical address of - discard block, and should not be write. - Have fixed it as below. - -- Yunpeng 2008.12.19 - */ - wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf, - wReplacedNode, 0, - DeviceInfo.wPagesPerBlock); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)wReplacedNode); - MARK_BLOCK_AS_BAD(wReplacedNode); - } else { - pbt[wBlockNum] = wReplacedNode; - pbt[wLeastReadIndex] = wTempNode; - } - } - - if ((wResult == PASS) && (g_cBlockTableStatus != - IN_PROGRESS_BLOCK_TABLE)) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } -#endif - } - } while (wResult != PASS) - ; - -#if CMD_DMA - /* ... */ -#endif - - return wResult; -} - diff --git a/drivers/block/spectra/flash.h b/drivers/block/spectra/flash.h deleted file mode 100644 index 5ed05805cf65..000000000000 --- a/drivers/block/spectra/flash.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FLASH_INTERFACE_ -#define _FLASH_INTERFACE_ - -#include "ffsport.h" -#include "spectraswconfig.h" - -#define MAX_BYTE_VALUE 0xFF -#define MAX_WORD_VALUE 0xFFFF -#define MAX_U32_VALUE 0xFFFFFFFF - -#define MAX_BLOCKNODE_VALUE 0xFFFFFF -#define DISCARD_BLOCK 0x800000 -#define SPARE_BLOCK 0x400000 -#define BAD_BLOCK 0xC00000 - -#define UNHIT_CACHE_ITEM 0xFFFF - -#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL - -#define IN_PROGRESS_BLOCK_TABLE 0x00 -#define CURRENT_BLOCK_TABLE 0x01 - -#define BTSIG_OFFSET (0) -#define BTSIG_BYTES (5) -#define BTSIG_DELTA (3) - -#define MAX_READ_COUNTER 0x2710 - -#define FIRST_BT_ID (1) -#define LAST_BT_ID (254) -#define BTBLOCK_INVAL (u32)(0xFFFFFFFF) - -struct device_info_tag { - u16 wDeviceMaker; - u16 wDeviceID; - u32 wDeviceType; - u32 wSpectraStartBlock; - u32 wSpectraEndBlock; - u32 wTotalBlocks; - u16 wPagesPerBlock; - u16 wPageSize; - u16 wPageDataSize; - u16 wPageSpareSize; - u16 wNumPageSpareFlag; - u16 wECCBytesPerSector; - u32 wBlockSize; - u32 wBlockDataSize; - u32 wDataBlockNum; - u8 bPlaneNum; - u16 wDeviceMainAreaSize; - u16 wDeviceSpareAreaSize; - u16 wDevicesConnected; - u16 wDeviceWidth; - u16 wHWRevision; - u16 wHWFeatures; - - u16 wONFIDevFeatures; - u16 wONFIOptCommands; - u16 wONFITimingMode; - u16 wONFIPgmCacheTimingMode; - - u16 MLCDevice; - u16 wSpareSkipBytes; - - u8 nBitsInPageNumber; - u8 nBitsInPageDataSize; - u8 nBitsInBlockDataSize; -}; - -extern struct device_info_tag DeviceInfo; - -/* Cache item format */ -struct flash_cache_item_tag { - u64 address; - u16 use_cnt; - u16 changed; - u8 *buf; -}; - -struct flash_cache_tag { - u32 cache_item_size; /* Size in bytes of each cache item */ - u16 pages_per_item; /* How many NAND pages in each cache item */ - u16 LRU; /* No. of the least recently used cache item */ - struct flash_cache_item_tag array[CACHE_ITEM_NUM]; -}; - -/* - *Data structure for each list node of the managment table - * used for the Level 2 Cache. Each node maps one logical NAND block. - */ -struct spectra_l2_cache_list { - struct list_head list; - u32 logical_blk_num; /* Logical block number */ - u32 pages_array[]; /* Page map array of this logical block. - * Array index is the logical block number, - * and for every item of this arry: - * high 16 bit is index of the L2 cache block num, - * low 16 bit is the phy page num - * of the above L2 cache block. - * This array will be kmalloc during run time. - */ -}; - -struct spectra_l2_cache_info { - u32 blk_array[BLK_NUM_FOR_L2_CACHE]; - u16 cur_blk_idx; /* idx to the phy block number of current using */ - u16 cur_page_num; /* pages number of current using */ - struct spectra_l2_cache_list table; /* First node of the table */ -}; - -#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1 - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE -struct flash_cache_mod_item_tag { - u64 address; - u8 changed; -}; - -struct flash_cache_delta_list_tag { - u8 item; /* used cache item */ - struct flash_cache_mod_item_tag cache; -}; -#endif - -extern struct flash_cache_tag Cache; - -extern u8 *buf_read_page_main_spare; -extern u8 *buf_write_page_main_spare; -extern u8 *buf_read_page_spare; -extern u8 *buf_get_bad_block; -extern u8 *cdma_desc_buf; -extern u8 *memcp_desc_buf; - -/* struture used for IndentfyDevice function */ -struct spectra_indentfy_dev_tag { - u32 NumBlocks; - u16 PagesPerBlock; - u16 PageDataSize; - u16 wECCBytesPerSector; - u32 wDataBlockNum; -}; - -int GLOB_FTL_Flash_Init(void); -int GLOB_FTL_Flash_Release(void); -/*void GLOB_FTL_Erase_Flash(void);*/ -int GLOB_FTL_Block_Erase(u64 block_addr); -int GLOB_FTL_Is_BadBlock(u32 block_num); -int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data); -int GLOB_FTL_Event_Status(int *); -u16 glob_ftl_execute_cmds(void); - -/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/ -int FTL_Read_Disturbance(u32 dwBlockAddr); - -/*Flash r/w based on cache*/ -int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr); -int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr); -int GLOB_FTL_Wear_Leveling(void); -int GLOB_FTL_Flash_Format(void); -int GLOB_FTL_Init(void); -int GLOB_FTL_Flush_Cache(void); -int GLOB_FTL_Garbage_Collection(void); -int GLOB_FTL_BT_Garbage_Collection(void); -void GLOB_FTL_Cache_Release(void); -u8 *get_blk_table_start_addr(void); -u8 *get_wear_leveling_table_start_addr(void); -unsigned long get_blk_table_len(void); -unsigned long get_wear_leveling_table_len(void); - -#if DEBUG_BNDRY -void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno, - char *filename); -#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\ - limit, no, __LINE__, __FILE__) -#else -#define debug_boundary_error(chnl, limit, no) ; -#endif - -#endif /*_FLASH_INTERFACE_*/ diff --git a/drivers/block/spectra/lld.c b/drivers/block/spectra/lld.c deleted file mode 100644 index 5c3b9762dc3e..000000000000 --- a/drivers/block/spectra/lld.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "spectraswconfig.h" -#include "ffsport.h" -#include "ffsdefs.h" -#include "lld.h" -#include "lld_nand.h" - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */ -#include "lld_emu.h" -#include "lld_cdma.h" - -/* common functions: */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return emu_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return emu_Read_Device_ID(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return emu_Flash_Release(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return emu_Flash_Init(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return emu_Erase_Block(block_add); -} - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Read_Page_Main(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return emu_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 Page, u16 PageCount) -{ - return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return emu_Get_Bad_Block(block); -} - -#endif /* FLASH_EMU */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */ -#include "lld_mtd.h" -#include "lld_cdma.h" - -/* common functions: */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return mtd_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return mtd_Read_Device_ID(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return mtd_Flash_Release(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return mtd_Flash_Init(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return mtd_Erase_Block(block_add); -} - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Read_Page_Main(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return mtd_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 Page, u16 PageCount) -{ - return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return mtd_Get_Bad_Block(block); -} - -#endif /* FLASH_MTD */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */ -#include "lld_nand.h" -#include "lld_cdma.h" -#include "flash.h" - -/* common functions for LLD_NAND */ -void GLOB_LLD_ECC_Control(int enable) -{ - NAND_ECC_Ctrl(enable); -} - -/* common functions for LLD_NAND */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return NAND_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return NAND_Read_Device_ID(); -} - -u16 GLOB_LLD_UnlockArrayAll(void) -{ - return NAND_UnlockArrayAll(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return NAND_Flash_Init(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return nand_release_spectra(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return NAND_Erase_Block(block_add); -} - - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - if (page_count == 1) /* Using polling to improve read speed */ - return NAND_Read_Page_Main_Polling(read_data, block, page, 1); - else - return NAND_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return NAND_Read_Page_Main_Polling(read_data, - block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 page, u16 page_count) -{ - return NAND_Read_Page_Main_Spare(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return NAND_Get_Bad_Block(block); -} - -#if CMD_DMA -u16 GLOB_LLD_Event_Status(void) -{ - return CDMA_Event_Status(); -} - -u16 glob_lld_execute_cmds(void) -{ - return CDMA_Execute_CMDs(); -} - -u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, - u32 ByteCount, u16 flag) -{ - /* Replace the hardware memcopy with software memcpy function */ - if (CDMA_Execute_CMDs()) - return FAIL; - memcpy(dest, src, ByteCount); - return PASS; - - /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */ -} - -u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags) -{ - return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags); -} - -u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count) -{ - return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0); -} - -u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page, - u16 count, u16 flags) -{ - return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags); -} - -u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page, - u16 count, u16 flags) -{ - return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD, - data, block, page, count, flags); -} - -u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count) -{ - return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count, - LLD_CMD_FLAG_MODE_CDMA); -} - -#endif /* CMD_DMA */ -#endif /* FLASH_NAND */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -/* end of LLD.c */ diff --git a/drivers/block/spectra/lld.h b/drivers/block/spectra/lld.h deleted file mode 100644 index d3738e0e1fea..000000000000 --- a/drivers/block/spectra/lld.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - - -#ifndef _LLD_ -#define _LLD_ - -#include "ffsport.h" -#include "spectraswconfig.h" -#include "flash.h" - -#define GOOD_BLOCK 0 -#define DEFECTIVE_BLOCK 1 -#define READ_ERROR 2 - -#define CLK_X 5 -#define CLK_MULTI 4 - -/* Typedefs */ - -/* prototypes: API for LLD */ -/* Currently, Write_Page_Main - * MemCopy - * Read_Page_Main_Spare - * do not have flag because they were not implemented prior to this - * They are not being added to keep changes to a minimum for now. - * Currently, they are not required (only reqd for Wr_P_M_S.) - * Later on, these NEED to be changed. - */ - -extern void GLOB_LLD_ECC_Control(int enable); - -extern u16 GLOB_LLD_Flash_Reset(void); - -extern u16 GLOB_LLD_Read_Device_ID(void); - -extern u16 GLOB_LLD_UnlockArrayAll(void); - -extern u16 GLOB_LLD_Flash_Init(void); - -extern int GLOB_LLD_Flash_Release(void); - -extern u16 GLOB_LLD_Erase_Block(u32 block_add); - -extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Get_Bad_Block(u32 block); - -extern u16 GLOB_LLD_Event_Status(void); - -extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag); - -extern u16 glob_lld_execute_cmds(void); - -extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags); - -extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, - u32 block, u16 page, u16 count); - -extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, - u32 block, u16 page, u16 count, u16 flags); - -extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count, u16 flags); - -extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count); - -#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1) -#define LLD_CMD_FLAG_MODE_CDMA (0x8) - - -#endif /*_LLD_ */ - - diff --git a/drivers/block/spectra/lld_cdma.c b/drivers/block/spectra/lld_cdma.c deleted file mode 100644 index c6e76103d43c..000000000000 --- a/drivers/block/spectra/lld_cdma.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include "spectraswconfig.h" -#include "lld.h" -#include "lld_nand.h" -#include "lld_cdma.h" -#include "lld_emu.h" -#include "flash.h" -#include "nand_regs.h" - -#define MAX_PENDING_CMDS 4 -#define MODE_02 (0x2 << 26) - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Data_Cmd -* Inputs: cmd code (aligned for hw) -* data: pointer to source or destination -* block: block address -* page: page address -* num: num pages to transfer -* Outputs: PASS -* Description: This function takes the parameters and puts them -* into the "pending commands" array. -* It does not parse or validate the parameters. -* The array index is same as the tag. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags) -{ - u8 bank; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (0 == cmd) - nand_dbg_print(NAND_DBG_DEBUG, - "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__); - - /* If a command of another bank comes, then first execute */ - /* pending commands of the current bank, then set the new */ - /* bank as current bank */ - bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - if (bank != info.flash_bank) { - nand_dbg_print(NAND_DBG_WARN, - "Will access new bank. old bank: %d, new bank: %d\n", - info.flash_bank, bank); - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - info.flash_bank = bank; - } - - info.pcmds[info.pcmds_num].CMD = cmd; - info.pcmds[info.pcmds_num].DataAddr = data; - info.pcmds[info.pcmds_num].Block = block; - info.pcmds[info.pcmds_num].Page = page; - info.pcmds[info.pcmds_num].PageCount = num; - info.pcmds[info.pcmds_num].DataDestAddr = 0; - info.pcmds[info.pcmds_num].DataSrcAddr = 0; - info.pcmds[info.pcmds_num].MemCopyByteCnt = 0; - info.pcmds[info.pcmds_num].Flags = flags; - info.pcmds[info.pcmds_num].Status = 0xB0B; - - switch (cmd) { - case WRITE_MAIN_SPARE_CMD: - Conv_Main_Spare_Data_Log2Phy_Format(data, num); - break; - case WRITE_SPARE_CMD: - Conv_Spare_Data_Log2Phy_Format(data); - break; - default: - break; - } - - info.pcmds_num++; - - if (info.pcmds_num >= MAX_PENDING_CMDS) { - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_MemCopy_CMD -* Inputs: dest: pointer to destination -* src: pointer to source -* count: num bytes to transfer -* Outputs: PASS -* Description: This function takes the parameters and puts them -* into the "pending commands" array. -* It does not parse or validate the parameters. -* The array index is same as the tag. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags) -{ - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD; - info.pcmds[info.pcmds_num].DataAddr = 0; - info.pcmds[info.pcmds_num].Block = 0; - info.pcmds[info.pcmds_num].Page = 0; - info.pcmds[info.pcmds_num].PageCount = 0; - info.pcmds[info.pcmds_num].DataDestAddr = dest; - info.pcmds[info.pcmds_num].DataSrcAddr = src; - info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt; - info.pcmds[info.pcmds_num].Flags = flags; - info.pcmds[info.pcmds_num].Status = 0xB0B; - - info.pcmds_num++; - - if (info.pcmds_num >= MAX_PENDING_CMDS) { - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - } - - return PASS; -} - -#if 0 -/* Prints the PendingCMDs array */ -void print_pending_cmds(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < info.pcmds_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - switch (info.pcmds[i].CMD) { - case ERASE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Erase Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case WRITE_MAIN_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Write Main Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case WRITE_MAIN_SPARE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Write Main Spare Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case READ_MAIN_SPARE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Read Main Spare Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case READ_MAIN_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Read Main Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case MEMCOPY_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Memcopy Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case DUMMY_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Dummy Command (0x%x)\n", - info.pcmds[i].CMD); - break; - default: - nand_dbg_print(NAND_DBG_DEBUG, - "Illegal Command (0x%x)\n", - info.pcmds[i].CMD); - break; - } - - nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n", - (u32)info.pcmds[i].DataAddr); - nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n", - info.pcmds[i].Block); - nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n", - info.pcmds[i].Page); - nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n", - info.pcmds[i].PageCount); - nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n", - (u32)info.pcmds[i].DataDestAddr); - nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n", - (u32)info.pcmds[i].DataSrcAddr); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n", - info.pcmds[i].MemCopyByteCnt); - nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n", - info.pcmds[i].Flags); - nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n", - info.pcmds[i].Status); - } -} - -/* Print the CDMA descriptors */ -void print_cdma_descriptors(void) -{ - struct cdma_descriptor *pc; - int i; - - pc = (struct cdma_descriptor *)info.cdma_desc_buf; - - nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n"); - - for (i = 0; i < info.cdma_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - nand_dbg_print(NAND_DBG_DEBUG, - "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", - pc[i].NxtPointerHi, pc[i].NxtPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n", - pc[i].FlashPointerHi, pc[i].FlashPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n", - pc[i].CommandType); - nand_dbg_print(NAND_DBG_DEBUG, - "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n", - pc[i].MemAddrHi, pc[i].MemAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n", - pc[i].CommandFlags); - nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n", - pc[i].Channel, pc[i].Status); - nand_dbg_print(NAND_DBG_DEBUG, - "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n", - pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "Reserved12: 0x%x, Reserved13: 0x%x, " - "Reserved14: 0x%x, pcmd: %d\n", - pc[i].Reserved12, pc[i].Reserved13, - pc[i].Reserved14, pc[i].pcmd); - } -} - -/* Print the Memory copy descriptors */ -static void print_memcp_descriptors(void) -{ - struct memcpy_descriptor *pm; - int i; - - pm = (struct memcpy_descriptor *)info.memcp_desc_buf; - - nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n"); - - for (i = 0; i < info.cdma_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - nand_dbg_print(NAND_DBG_DEBUG, - "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", - pm[i].NxtPointerHi, pm[i].NxtPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n", - pm[i].SrcAddrHi, pm[i].SrcAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, - "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n", - pm[i].DestAddrHi, pm[i].DestAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n", - pm[i].XferSize); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n", - pm[i].MemCopyFlags); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n", - pm[i].MemCopyStatus); - nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n", - pm[i].reserved9); - nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n", - pm[i].reserved10); - nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n", - pm[i].reserved11); - nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n", - pm[i].reserved12); - nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n", - pm[i].reserved13); - nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n", - pm[i].reserved14); - nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n", - pm[i].reserved15); - } -} -#endif - -/* Reset cdma_descriptor chain to 0 */ -static void reset_cdma_desc(int i) -{ - struct cdma_descriptor *ptr; - - BUG_ON(i >= MAX_DESCS); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - ptr[i].NxtPointerHi = 0; - ptr[i].NxtPointerLo = 0; - ptr[i].FlashPointerHi = 0; - ptr[i].FlashPointerLo = 0; - ptr[i].CommandType = 0; - ptr[i].MemAddrHi = 0; - ptr[i].MemAddrLo = 0; - ptr[i].CommandFlags = 0; - ptr[i].Channel = 0; - ptr[i].Status = 0; - ptr[i].MemCopyPointerHi = 0; - ptr[i].MemCopyPointerLo = 0; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_UpdateEventStatus -* Inputs: none -* Outputs: none -* Description: This function update the event status of all the channels -* when an error condition is reported. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void CDMA_UpdateEventStatus(void) -{ - int i, j, active_chan; - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (j = 0; j < info.cdma_num; j++) { - /* Check for the descriptor with failure */ - if ((ptr[j].Status & CMD_DMA_DESC_FAIL)) - break; - - } - - /* All the previous cmd's status for this channel must be good */ - for (i = 0; i < j; i++) { - if (ptr[i].pcmd != 0xff) - info.pcmds[ptr[i].pcmd].Status = CMD_PASS; - } - - /* Abort the channel with type 0 reset command. It resets the */ - /* selected channel after the descriptor completes the flash */ - /* operation and status has been updated for the descriptor. */ - /* Memory Copy and Sync associated with this descriptor will */ - /* not be executed */ - active_chan = ioread32(FlashReg + CHNL_ACTIVE); - if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) { - iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */ - iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10); - } else { /* Should not reached here */ - printk(KERN_ERR "Error! Used bank is not set in" - " reg CHNL_ACTIVE\n"); - } -} - -static void cdma_trans(u16 chan) -{ - u32 addr; - - addr = info.cdma_desc; - - iowrite32(MODE_10 | (chan << 24), FlashMem); - iowrite32((1 << 7) | chan, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8), - FlashMem); - iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem); - iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24), FlashMem); - iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs (for use with CMD_DMA) -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor -* for each pending command, start the CDMA engine, and return. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Execute_CMDs(void) -{ - int i, ret; - u64 flash_add; - u32 ptr; - dma_addr_t map_addr, next_ptr; - u16 status = PASS; - u16 tmp_c; - struct cdma_descriptor *pc; - struct memcpy_descriptor *pm; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* No pending cmds to execute, just exit */ - if (0 == info.pcmds_num) { - nand_dbg_print(NAND_DBG_TRACE, - "No pending cmds to execute. Just exit.\n"); - return PASS; - } - - for (i = 0; i < MAX_DESCS; i++) - reset_cdma_desc(i); - - pc = (struct cdma_descriptor *)info.cdma_desc_buf; - pm = (struct memcpy_descriptor *)info.memcp_desc_buf; - - info.cdma_desc = virt_to_bus(info.cdma_desc_buf); - info.memcp_desc = virt_to_bus(info.memcp_desc_buf); - next_ptr = info.cdma_desc; - info.cdma_num = 0; - - for (i = 0; i < info.pcmds_num; i++) { - if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) { - info.pcmds[i].Status = CMD_NOT_DONE; - continue; - } - - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - - /* Use the Block offset within a bank */ - tmp_c = info.pcmds[i].Block / - (DeviceInfo.wTotalBlocks / totalUsedBanks); - flash_add = (u64)(info.pcmds[i].Block - tmp_c * - (DeviceInfo.wTotalBlocks / totalUsedBanks)) * - DeviceInfo.wBlockDataSize + - (u64)(info.pcmds[i].Page) * - DeviceInfo.wPageDataSize; - - ptr = MODE_10 | (info.flash_bank << 24) | - (u32)GLOB_u64_Div(flash_add, - DeviceInfo.wPageDataSize); - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - - if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || - (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { - /* Descriptor to set Main+Spare Access Mode */ - pc[info.cdma_num].CommandType = 0x43; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - reset_cdma_desc(info.cdma_num); - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - } - - switch (info.pcmds[i].CMD) { - case ERASE_CMD: - pc[info.cdma_num].CommandType = 1; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - break; - - case WRITE_MAIN_CMD: - pc[info.cdma_num].CommandType = - 0x2100 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case READ_MAIN_CMD: - pc[info.cdma_num].CommandType = - 0x2000 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case WRITE_MAIN_SPARE_CMD: - pc[info.cdma_num].CommandType = - 0x2100 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case READ_MAIN_SPARE_CMD: - pc[info.cdma_num].CommandType = - 0x2000 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case MEMCOPY_CMD: - pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */ - /* Set bit 11 to let the CDMA engine continue to */ - /* execute only after it has finished processing */ - /* the memcopy descriptor. */ - /* Also set bit 10 and bit 9 to 1 */ - pc[info.cdma_num].CommandFlags = 0x0E40; - map_addr = info.memcp_desc + info.cdma_num * - sizeof(struct memcpy_descriptor); - pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16; - pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff; - - pm[info.cdma_num].NxtPointerHi = 0; - pm[info.cdma_num].NxtPointerLo = 0; - - map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr); - pm[info.cdma_num].SrcAddrHi = map_addr >> 16; - pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff; - map_addr = virt_to_bus(info.pcmds[i].DataDestAddr); - pm[info.cdma_num].DestAddrHi = map_addr >> 16; - pm[info.cdma_num].DestAddrLo = map_addr & 0xffff; - - pm[info.cdma_num].XferSize = - info.pcmds[i].MemCopyByteCnt; - pm[info.cdma_num].MemCopyFlags = - (0 << 15 | 0 << 14 | 27 << 8 | 0x40); - pm[info.cdma_num].MemCopyStatus = 0; - break; - - case DUMMY_CMD: - default: - pc[info.cdma_num].CommandType = 0XFFFF; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - break; - } - - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || - (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { - /* Descriptor to set back Main Area Access Mode */ - reset_cdma_desc(info.cdma_num); - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - - pc[info.cdma_num].CommandType = 0x42; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - } - } - - /* Add a dummy descriptor at end of the CDMA chain */ - reset_cdma_desc(info.cdma_num); - ptr = MODE_10 | (info.flash_bank << 24); - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */ - /* Set Command Flags for the last CDMA descriptor: */ - /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */ - pc[info.cdma_num].CommandFlags = - (0 << 10) | (0 << 9) | (1 << 8) | 0x40; - pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */ - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - iowrite32(1, FlashReg + DMA_ENABLE); - /* Wait for DMA to be enabled before issuing the next command */ - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - cdma_trans(info.flash_bank); - - ret = wait_for_completion_timeout(&info.complete, 50 * HZ); - if (!ret) - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = info.ret; - - info.pcmds_num = 0; /* Clear the pending cmds number to 0 */ - - return status; -} - -int is_cdma_interrupt(void) -{ - u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma; - u32 int_en_mask; - u32 cdma_int_en_mask; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* Set the global Enable masks for only those interrupts - * that are supported */ - cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | - DMA_INTR__DESC_COMP_CHANNEL1 | - DMA_INTR__DESC_COMP_CHANNEL2 | - DMA_INTR__DESC_COMP_CHANNEL3 | - DMA_INTR__MEMCOPY_DESC_COMP); - - int_en_mask = (INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL); - - ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask; - ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask; - ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask; - ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask; - ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask; - - nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: " - "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n", - ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma); - - if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) { - return 1; - } else { - iowrite32(ints_b0, FlashReg + INTR_STATUS0); - iowrite32(ints_b1, FlashReg + INTR_STATUS1); - iowrite32(ints_b2, FlashReg + INTR_STATUS2); - iowrite32(ints_b3, FlashReg + INTR_STATUS3); - nand_dbg_print(NAND_DBG_DEBUG, - "Not a NAND controller interrupt! Ignore it.\n"); - return 0; - } -} - -static void update_event_status(void) -{ - int i; - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (i = 0; i < info.cdma_num; i++) { - if (ptr[i].pcmd != 0xff) - info.pcmds[ptr[i].pcmd].Status = CMD_PASS; - if ((ptr[i].CommandType == 0x41) || - (ptr[i].CommandType == 0x42) || - (ptr[i].CommandType == 0x43)) - continue; - - switch (info.pcmds[ptr[i].pcmd].CMD) { - case READ_MAIN_SPARE_CMD: - Conv_Main_Spare_Data_Phy2Log_Format( - info.pcmds[ptr[i].pcmd].DataAddr, - info.pcmds[ptr[i].pcmd].PageCount); - break; - case READ_SPARE_CMD: - Conv_Spare_Data_Phy2Log_Format( - info.pcmds[ptr[i].pcmd].DataAddr); - break; - } - } -} - -static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page) -{ - u16 event = EVENT_NONE; - u16 err_byte; - u16 err_page = 0; - u8 err_sector; - u8 err_device; - u16 ecc_correction_info; - u16 err_address; - u32 eccSectorSize; - u8 *err_pos; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - do { - if (0 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR0); - else if (1 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR1); - else if (2 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR2); - else if (3 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR3); - - err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS); - err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET; - err_sector = ((err_address & - ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); - - ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO); - err_device = ((ecc_correction_info & - ERR_CORRECTION_INFO__DEVICE_NR) >> 8); - - if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) { - event = EVENT_UNCORRECTABLE_DATA_ERROR; - } else { - event = EVENT_CORRECTABLE_DATA_ERROR_FIXED; - if (err_byte < ECC_SECTOR_SIZE) { - err_pos = buf + - (err_page - page) * - DeviceInfo.wPageDataSize + - err_sector * eccSectorSize + - err_byte * - DeviceInfo.wDevicesConnected + - err_device; - *err_pos ^= ecc_correction_info & - ERR_CORRECTION_INFO__BYTEMASK; - } - } - } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); - - return event; -} - -static u16 process_ecc_int(u32 c, u16 *p_desc_num) -{ - struct cdma_descriptor *ptr; - u16 j; - int event = EVENT_PASS; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (c != info.flash_bank) - printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n", - info.flash_bank, c); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (j = 0; j < info.cdma_num; j++) - if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP) - break; - - *p_desc_num = j; /* Pass the descripter number found here */ - - if (j >= info.cdma_num) { - printk(KERN_ERR "Can not find the correct descriptor number " - "when ecc interrupt triggered!" - "info.cdma_num: %d, j: %d\n", info.cdma_num, j); - return EVENT_UNCORRECTABLE_DATA_ERROR; - } - - event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr, - info.pcmds[ptr[j].pcmd].Page); - - if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { - printk(KERN_ERR "Uncorrectable ECC error!" - "info.cdma_num: %d, j: %d, " - "pending cmd CMD: 0x%x, " - "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n", - info.cdma_num, j, - info.pcmds[ptr[j].pcmd].CMD, - info.pcmds[ptr[j].pcmd].Block, - info.pcmds[ptr[j].pcmd].Page, - info.pcmds[ptr[j].pcmd].PageCount); - - if (ptr[j].pcmd != 0xff) - info.pcmds[ptr[j].pcmd].Status = CMD_FAIL; - CDMA_UpdateEventStatus(); - } - - return event; -} - -static void process_prog_erase_fail_int(u16 desc_num) -{ - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - if (ptr[desc_num].pcmd != 0xFF) - info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL; - - CDMA_UpdateEventStatus(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Event_Status (for use with CMD_DMA) -* Inputs: none -* Outputs: Event_Status code -* Description: This function is called after an interrupt has happened -* It reads the HW status register and ...tbd -* It returns the appropriate event status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Event_Status(void) -{ - u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0, - DMA_INTR__DESC_COMP_CHANNEL1, - DMA_INTR__DESC_COMP_CHANNEL2, - DMA_INTR__DESC_COMP_CHANNEL3}; - u32 cdma_int_status, int_status; - u32 ecc_enable = 0; - u16 event = EVENT_PASS; - u16 cur_desc = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ecc_enable = ioread32(FlashReg + ECC_ENABLE); - - while (1) { - int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); - if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) { - event = process_ecc_int(info.flash_bank, &cur_desc); - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + ints_addr[info.flash_bank]); - if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { - nand_dbg_print(NAND_DBG_WARN, - "ints_bank0 to ints_bank3: " - "0x%x, 0x%x, 0x%x, 0x%x, " - "ints_cdma: 0x%x\n", - ioread32(FlashReg + INTR_STATUS0), - ioread32(FlashReg + INTR_STATUS1), - ioread32(FlashReg + INTR_STATUS2), - ioread32(FlashReg + INTR_STATUS3), - ioread32(FlashReg + DMA_INTR)); - break; - } - } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) { - printk(KERN_ERR "NAND program fail interrupt!\n"); - process_prog_erase_fail_int(cur_desc); - event = EVENT_PROGRAM_FAILURE; - break; - } else if (int_status & INTR_STATUS0__ERASE_FAIL) { - printk(KERN_ERR "NAND erase fail interrupt!\n"); - process_prog_erase_fail_int(cur_desc); - event = EVENT_ERASE_FAILURE; - break; - } else { - cdma_int_status = ioread32(FlashReg + DMA_INTR); - if (cdma_int_status & dma_intr_bit[info.flash_bank]) { - iowrite32(dma_intr_bit[info.flash_bank], - FlashReg + DMA_INTR); - update_event_status(); - event = EVENT_PASS; - break; - } - } - } - - int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); - iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]); - cdma_int_status = ioread32(FlashReg + DMA_INTR); - iowrite32(cdma_int_status, FlashReg + DMA_INTR); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return event; -} - - - diff --git a/drivers/block/spectra/lld_cdma.h b/drivers/block/spectra/lld_cdma.h deleted file mode 100644 index 854ea066f0c4..000000000000 --- a/drivers/block/spectra/lld_cdma.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/* header for LLD_CDMA.c module */ - -#ifndef _LLD_CDMA_ -#define _LLD_CDMA_ - -#include "flash.h" - -#define DEBUG_SYNC 1 - -/*/////////// CDMA specific MACRO definition */ -#define MAX_DESCS (255) -#define MAX_CHANS (4) -#define MAX_SYNC_POINTS (16) -#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2) - -#define CHANNEL_SYNC_MASK (0x000F) -#define CHANNEL_DMA_MASK (0x00F0) -#define CHANNEL_ID_MASK (0x0300) -#define CHANNEL_CONT_MASK (0x4000) -#define CHANNEL_INTR_MASK (0x8000) - -#define CHANNEL_SYNC_OFFSET (0) -#define CHANNEL_DMA_OFFSET (4) -#define CHANNEL_ID_OFFSET (8) -#define CHANNEL_CONT_OFFSET (14) -#define CHANNEL_INTR_OFFSET (15) - -u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags); -u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags); -u16 CDMA_Execute_CMDs(void); -void print_pending_cmds(void); -void print_cdma_descriptors(void); - -extern u8 g_SBDCmdIndex; -extern struct mrst_nand_info info; - - -/*/////////// prototypes: APIs for LLD_CDMA */ -int is_cdma_interrupt(void); -u16 CDMA_Event_Status(void); - -/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */ -struct cdma_descriptor { - u32 NxtPointerHi; - u32 NxtPointerLo; - u32 FlashPointerHi; - u32 FlashPointerLo; - u32 CommandType; - u32 MemAddrHi; - u32 MemAddrLo; - u32 CommandFlags; - u32 Channel; - u32 Status; - u32 MemCopyPointerHi; - u32 MemCopyPointerLo; - u32 Reserved12; - u32 Reserved13; - u32 Reserved14; - u32 pcmd; /* pending cmd num related to this descriptor */ -}; - -/* This struct holds one MemCopy descriptor as defined by the HW */ -struct memcpy_descriptor { - u32 NxtPointerHi; - u32 NxtPointerLo; - u32 SrcAddrHi; - u32 SrcAddrLo; - u32 DestAddrHi; - u32 DestAddrLo; - u32 XferSize; - u32 MemCopyFlags; - u32 MemCopyStatus; - u32 reserved9; - u32 reserved10; - u32 reserved11; - u32 reserved12; - u32 reserved13; - u32 reserved14; - u32 reserved15; -}; - -/* Pending CMD table entries (includes MemCopy parameters */ -struct pending_cmd { - u8 CMD; - u8 *DataAddr; - u32 Block; - u16 Page; - u16 PageCount; - u8 *DataDestAddr; - u8 *DataSrcAddr; - u32 MemCopyByteCnt; - u16 Flags; - u16 Status; -}; - -#if DEBUG_SYNC -extern u32 debug_sync_cnt; -#endif - -/* Definitions for CMD DMA descriptor chain fields */ -#define CMD_DMA_DESC_COMP 0x8000 -#define CMD_DMA_DESC_FAIL 0x4000 - -#endif /*_LLD_CDMA_*/ diff --git a/drivers/block/spectra/lld_emu.c b/drivers/block/spectra/lld_emu.c deleted file mode 100644 index 60eb0f6fdba4..000000000000 --- a/drivers/block/spectra/lld_emu.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include "flash.h" -#include "ffsdefs.h" -#include "lld_emu.h" -#include "lld.h" -#if CMD_DMA -#include "lld_cdma.h" -#endif - -#define GLOB_LLD_PAGES 64 -#define GLOB_LLD_PAGE_SIZE (512+16) -#define GLOB_LLD_PAGE_DATA_SIZE 512 -#define GLOB_LLD_BLOCKS 2048 - -#if (CMD_DMA && FLASH_EMU) -#include "lld_cdma.h" -u32 totalUsedBanks; -u32 valid_banks[MAX_CHANS]; -#endif - -#if FLASH_EMU /* This is for entire module */ - -static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES]; - -/* Read nand emu file and then fill it's content to flash_memory */ -int emu_load_file_to_mem(void) -{ - mm_segment_t fs; - struct file *nef_filp = NULL; - struct inode *inode = NULL; - loff_t nef_size = 0; - loff_t tmp_file_offset, file_offset; - ssize_t nread; - int i, rc = -EINVAL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - fs = get_fs(); - set_fs(get_ds()); - - nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); - if (IS_ERR(nef_filp)) { - printk(KERN_ERR "filp_open error: " - "Unable to open nand emu file!\n"); - return PTR_ERR(nef_filp); - } - - if (nef_filp->f_path.dentry) { - inode = nef_filp->f_path.dentry->d_inode; - } else { - printk(KERN_ERR "Can not get valid inode!\n"); - goto out; - } - - nef_size = i_size_read(inode->i_mapping->host); - if (nef_size <= 0) { - printk(KERN_ERR "Invalid nand emu file size: " - "0x%llx\n", nef_size); - goto out; - } else { - nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n", - nef_size); - } - - file_offset = 0; - for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { - tmp_file_offset = file_offset; - nread = vfs_read(nef_filp, - (char __user *)flash_memory[i], - GLOB_LLD_PAGE_SIZE, &tmp_file_offset); - if (nread < GLOB_LLD_PAGE_SIZE) { - printk(KERN_ERR "%s, Line %d - " - "nand emu file partial read: " - "%d bytes\n", __FILE__, __LINE__, (int)nread); - goto out; - } - file_offset += GLOB_LLD_PAGE_SIZE; - } - rc = 0; - -out: - filp_close(nef_filp, current->files); - set_fs(fs); - return rc; -} - -/* Write contents of flash_memory to nand emu file */ -int emu_write_mem_to_file(void) -{ - mm_segment_t fs; - struct file *nef_filp = NULL; - struct inode *inode = NULL; - loff_t nef_size = 0; - loff_t tmp_file_offset, file_offset; - ssize_t nwritten; - int i, rc = -EINVAL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - fs = get_fs(); - set_fs(get_ds()); - - nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); - if (IS_ERR(nef_filp)) { - printk(KERN_ERR "filp_open error: " - "Unable to open nand emu file!\n"); - return PTR_ERR(nef_filp); - } - - if (nef_filp->f_path.dentry) { - inode = nef_filp->f_path.dentry->d_inode; - } else { - printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n"); - goto out; - } - - nef_size = i_size_read(inode->i_mapping->host); - if (nef_size <= 0) { - printk(KERN_ERR "Invalid " - "nand emu file size: 0x%llx\n", nef_size); - goto out; - } else { - nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: " - "%lld\n", nef_size); - } - - file_offset = 0; - for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { - tmp_file_offset = file_offset; - nwritten = vfs_write(nef_filp, - (char __user *)flash_memory[i], - GLOB_LLD_PAGE_SIZE, &tmp_file_offset); - if (nwritten < GLOB_LLD_PAGE_SIZE) { - printk(KERN_ERR "%s, Line %d - " - "nand emu file partial write: " - "%d bytes\n", __FILE__, __LINE__, (int)nwritten); - goto out; - } - file_offset += GLOB_LLD_PAGE_SIZE; - } - rc = 0; - -out: - filp_close(nef_filp, current->files); - set_fs(fs); - return rc; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Init -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Creates & initializes the flash RAM array. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Flash_Init(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - flash_memory[0] = (u8 *)vmalloc(GLOB_LLD_PAGE_SIZE * - GLOB_LLD_BLOCKS * - GLOB_LLD_PAGES * - sizeof(u8)); - if (!flash_memory[0]) { - printk(KERN_ERR "Fail to allocate memory " - "for nand emulator!\n"); - return ERR; - } - - memset((char *)(flash_memory[0]), 0xFF, - GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES * - sizeof(u8)); - - for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) - flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE; - - emu_load_file_to_mem(); /* Load nand emu file to mem */ - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Release -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Releases the flash. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int emu_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - emu_write_mem_to_file(); /* Write back mem to nand emu file */ - - vfree(flash_memory[0]); - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Device_ID -* Inputs: none -* Outputs: PASS=1 FAIL=0 -* Description: Reads the info from the controller registers. -* Sets up DeviceInfo structure with device parameters -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -u16 emu_Read_Device_ID(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - DeviceInfo.wDeviceMaker = 0; - DeviceInfo.wDeviceType = 8; - DeviceInfo.wSpectraStartBlock = 36; - DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1; - DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS; - DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES; - DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE; - DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE; - DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE - - GLOB_LLD_PAGE_DATA_SIZE; - DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES; - DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES; - DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock - + 1); - DeviceInfo.MLCDevice = 1; /* Emulate MLC device */ - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - -#if CMD_DMA - totalUsedBanks = 4; - valid_banks[0] = 1; - valid_banks[1] = 1; - valid_banks[2] = 1; - valid_banks[3] = 1; -#endif - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Reset -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Reset the flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Flash_Reset(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Erase_Block -* Inputs: Address -* Outputs: PASS=0 (notice 0=ok here) -* Description: Erase a block -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Erase_Block(u32 block_add) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (block_add >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "emu_Erase_Block error! " - "Too big block address: %d\n", block_add); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", - (int)block_add); - - for (i = block_add * GLOB_LLD_PAGES; - i < ((block_add + 1) * GLOB_LLD_PAGES); i++) { - if (flash_memory[i]) { - memset((u8 *)(flash_memory[i]), 0xFF, - DeviceInfo.wPageSize * sizeof(u8)); - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Main -* Inputs: Write buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the data in the buffer to main area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory\n"); - return FAIL; - } - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), - write_data, DeviceInfo.wPageDataSize); - write_data += DeviceInfo.wPageDataSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Main -* Inputs: Read buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read the data from the flash main area to the buffer -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Main(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(read_data, 0xFF, DeviceInfo.wPageDataSize); - } else { - memcpy(read_data, - (u8 *) (flash_memory[Block * GLOB_LLD_PAGES - + Page]), - DeviceInfo.wPageDataSize); - } - read_data += DeviceInfo.wPageDataSize; - Page++; - } - - return PASS; -} - -#ifndef ELDORA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Main_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read from flash main+spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)PageCount, - (unsigned int)Block, (unsigned int)Page); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(read_data, 0xFF, DeviceInfo.wPageSize); - } else { - memcpy(read_data, (u8 *) (flash_memory[Block * - GLOB_LLD_PAGES - + Page]), - DeviceInfo.wPageSize); - } - - read_data += DeviceInfo.wPageSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Main_Spare -* Inputs: Write buffer -* address -* buffer length -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer to main+spare area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 page_count) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + page_count > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)page_count, - (unsigned int)Block, (unsigned int)Page); - - for (i = 0; i < page_count; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory!\n"); - return FAIL; - } - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), - write_data, DeviceInfo.wPageSize); - write_data += DeviceInfo.wPageSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Spare -* Inputs: Write buffer -* Address -* buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer in the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare Error: " - "Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare Error: " - "Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- " - "block %u page %u\n", - (unsigned int)Block, (unsigned int)Page); - - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory!\n"); - return FAIL; - } - - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + - DeviceInfo.wPageDataSize), write_data, - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read data from the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " - "block %u page %u\n", - (unsigned int)Block, (unsigned int)Page); - - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(write_data, 0xFF, - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - } else { - memcpy(write_data, - (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] - + DeviceInfo.wPageDataSize), - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Enable_Disable_Interrupts -* Inputs: enable or disable -* Outputs: none -* Description: NOP -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void emu_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); -} - -u16 emu_Get_Bad_Block(u32 block) -{ - return 0; -} - -#if CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Support for CDMA functions -************************************ -* emu_CDMA_Flash_Init -* CDMA_process_data command (use LLD_CDMA) -* CDMA_MemCopy_CMD (use LLD_CDMA) -* emu_CDMA_execute all commands -* emu_CDMA_Event_Status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Flash_Init(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = 3; - } - - return PASS; -} - -static void emu_isr(int irq, void *dev_id) -{ - /* TODO: ... */ -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: execute each command in the pending CMD array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Execute_CMDs(u16 tag_count) -{ - u16 i, j; - u8 CMD; /* cmd parameter */ - u8 *data; - u32 block; - u16 page; - u16 count; - u16 status = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " - "Tag Count %u\n", tag_count); - - for (i = 0; i < totalUsedBanks; i++) { - PendingCMD[i].CMD = DUMMY_CMD; - PendingCMD[i].Tag = 0xFF; - PendingCMD[i].Block = - (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; - - for (j = 0; j <= MAX_CHANS; j++) - PendingCMD[i].ChanSync[j] = 0; - } - - CDMA_Execute_CMDs(tag_count); - - print_pending_cmds(tag_count); - -#if DEBUG_SYNC - } - debug_sync_cnt++; -#endif - - for (i = MAX_CHANS; - i < tag_count + MAX_CHANS; i++) { - CMD = PendingCMD[i].CMD; - data = PendingCMD[i].DataAddr; - block = PendingCMD[i].Block; - page = PendingCMD[i].Page; - count = PendingCMD[i].PageCount; - - switch (CMD) { - case ERASE_CMD: - emu_Erase_Block(block); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_CMD: - emu_Write_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_SPARE_CMD: - emu_Write_Page_Main_Spare(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case READ_MAIN_CMD: - emu_Read_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case MEMCOPY_CMD: - memcpy(PendingCMD[i].DataDestAddr, - PendingCMD[i].DataSrcAddr, - PendingCMD[i].MemCopyByteCnt); - case DUMMY_CMD: - PendingCMD[i].Status = PASS; - break; - default: - PendingCMD[i].Status = FAIL; - break; - } - } - - /* - * Temperory adding code to reset PendingCMD array for basic testing. - * It should be done at the end of event status function. - */ - for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = CMD_NOT_DONE; - } - - nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); - - emu_isr(0, 0); /* This is a null isr now. Need fill it in future */ - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Event_Status -* Inputs: none -* Outputs: Event_Status code -* Description: This function can also be used to force errors -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Event_Status(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return EVENT_PASS; -} - -#endif /* CMD_DMA */ -#endif /* !ELDORA */ -#endif /* FLASH_EMU */ diff --git a/drivers/block/spectra/lld_emu.h b/drivers/block/spectra/lld_emu.h deleted file mode 100644 index 63f84c38d3c1..000000000000 --- a/drivers/block/spectra/lld_emu.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_EMU_ -#define _LLD_EMU_ - -#include "ffsport.h" -#include "ffsdefs.h" - -/* prototypes: emulator API functions */ -extern u16 emu_Flash_Reset(void); -extern u16 emu_Flash_Init(void); -extern int emu_Flash_Release(void); -extern u16 emu_Read_Device_ID(void); -extern u16 emu_Erase_Block(u32 block_addr); -extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 emu_Event_Status(void); -extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE); -extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 emu_Get_Bad_Block(u32 block); - -u16 emu_CDMA_Flash_Init(void); -u16 emu_CDMA_Execute_CMDs(u16 tag_count); -u16 emu_CDMA_Event_Status(void); -#endif /*_LLD_EMU_*/ diff --git a/drivers/block/spectra/lld_mtd.c b/drivers/block/spectra/lld_mtd.c deleted file mode 100644 index 0de05b1e75f7..000000000000 --- a/drivers/block/spectra/lld_mtd.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include "flash.h" -#include "ffsdefs.h" -#include "lld_emu.h" -#include "lld.h" -#if CMD_DMA -#include "lld_cdma.h" -#endif - -#define GLOB_LLD_PAGES 64 -#define GLOB_LLD_PAGE_SIZE (512+16) -#define GLOB_LLD_PAGE_DATA_SIZE 512 -#define GLOB_LLD_BLOCKS 2048 - -#if CMD_DMA -#include "lld_cdma.h" -u32 totalUsedBanks; -u32 valid_banks[MAX_CHANS]; -#endif - -static struct mtd_info *spectra_mtd; -static int mtddev = -1; -module_param(mtddev, int, 0); - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Init -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Creates & initializes the flash RAM array. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Flash_Init(void) -{ - if (mtddev == -1) { - printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n"); - return FAIL; - } - - spectra_mtd = get_mtd_device(NULL, mtddev); - if (!spectra_mtd) { - printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev); - return FAIL; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Release -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Releases the flash. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int mtd_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - if (!spectra_mtd) - return PASS; - - put_mtd_device(spectra_mtd); - spectra_mtd = NULL; - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Device_ID -* Inputs: none -* Outputs: PASS=1 FAIL=0 -* Description: Reads the info from the controller registers. -* Sets up DeviceInfo structure with device parameters -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -u16 mtd_Read_Device_ID(void) -{ - uint64_t tmp; - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!spectra_mtd) - return FAIL; - - DeviceInfo.wDeviceMaker = 0; - DeviceInfo.wDeviceType = 8; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - tmp = spectra_mtd->size; - do_div(tmp, spectra_mtd->erasesize); - DeviceInfo.wTotalBlocks = tmp; - DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; - DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; - DeviceInfo.wPageDataSize = spectra_mtd->writesize; - DeviceInfo.wPageSpareSize = spectra_mtd->oobsize; - DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock - + 1); - DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK; - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - -#if CMD_DMA - totalUsedBanks = 4; - valid_banks[0] = 1; - valid_banks[1] = 1; - valid_banks[2] = 1; - valid_banks[3] = 1; -#endif - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Reset -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Reset the flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Flash_Reset(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -void erase_callback(struct erase_info *e) -{ - complete((void *)e->priv); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Erase_Block -* Inputs: Address -* Outputs: PASS=0 (notice 0=ok here) -* Description: Erase a block -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Erase_Block(u32 block_add) -{ - struct erase_info erase; - DECLARE_COMPLETION_ONSTACK(comp); - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (block_add >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "mtd_Erase_Block error! " - "Too big block address: %d\n", block_add); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", - (int)block_add); - - erase.mtd = spectra_mtd; - erase.callback = erase_callback; - erase.addr = block_add * spectra_mtd->erasesize; - erase.len = spectra_mtd->erasesize; - erase.priv = (unsigned long)∁ - - ret = spectra_mtd->erase(spectra_mtd, &erase); - if (!ret) { - wait_for_completion(&comp); - if (erase.state != MTD_ERASE_DONE) - ret = -EIO; - } - if (ret) { - printk(KERN_WARNING "mtd_Erase_Block error! " - "erase of region [0x%llx, 0x%llx] failed\n", - erase.addr, erase.len); - return FAIL; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Main -* Inputs: Write buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the data in the buffer to main area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - size_t retlen; - int ret = 0; - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - - while (PageCount) { - ret = spectra_mtd->write(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - DeviceInfo.wPageDataSize, &retlen, write_data); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - write_data += DeviceInfo.wPageDataSize; - Page++; - PageCount--; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Main -* Inputs: Read buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read the data from the flash main area to the buffer -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - size_t retlen; - int ret = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - - while (PageCount) { - ret = spectra_mtd->read(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - DeviceInfo.wPageDataSize, &retlen, read_data); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - read_data += DeviceInfo.wPageDataSize; - Page++; - PageCount--; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -#ifndef ELDORA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Main_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read from flash main+spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Page number %d+%d too big in block %d\n", - Page, PageCount, Block); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)PageCount, - (unsigned int)Block, (unsigned int)Page); - - - while (PageCount) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OOB_AUTO; - ops.datbuf = read_data; - ops.len = DeviceInfo.wPageDataSize; - ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->read_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - read_data += DeviceInfo.wPageSize; - Page++; - PageCount--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Main_Spare -* Inputs: Write buffer -* address -* buffer length -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer to main+spare area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 page_count) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + page_count > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Page number %d+%d too big in block %d\n", - Page, page_count, Block); - WARN_ON(1); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)page_count, - (unsigned int)Block, (unsigned int)Page); - - while (page_count) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OOB_AUTO; - ops.datbuf = write_data; - ops.len = DeviceInfo.wPageDataSize; - ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->write_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - write_data += DeviceInfo.wPageSize; - Page++; - page_count--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Spare -* Inputs: Write buffer -* Address -* buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer in the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - WARN_ON(1); - return FAIL; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read data from the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " - "block %u page %u (%u pages)\n", - (unsigned int)Block, (unsigned int)Page, PageCount); - - while (PageCount) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OOB_AUTO; - ops.datbuf = NULL; - ops.len = 0; - ops.oobbuf = read_data; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->read_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - - read_data += DeviceInfo.wPageSize; - Page++; - PageCount--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Enable_Disable_Interrupts -* Inputs: enable or disable -* Outputs: none -* Description: NOP -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); -} - -u16 mtd_Get_Bad_Block(u32 block) -{ - return 0; -} - -#if CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Support for CDMA functions -************************************ -* mtd_CDMA_Flash_Init -* CDMA_process_data command (use LLD_CDMA) -* CDMA_MemCopy_CMD (use LLD_CDMA) -* mtd_CDMA_execute all commands -* mtd_CDMA_Event_Status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Flash_Init(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = 3; - } - - return PASS; -} - -static void mtd_isr(int irq, void *dev_id) -{ - /* TODO: ... */ -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: execute each command in the pending CMD array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Execute_CMDs(u16 tag_count) -{ - u16 i, j; - u8 CMD; /* cmd parameter */ - u8 *data; - u32 block; - u16 page; - u16 count; - u16 status = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " - "Tag Count %u\n", tag_count); - - for (i = 0; i < totalUsedBanks; i++) { - PendingCMD[i].CMD = DUMMY_CMD; - PendingCMD[i].Tag = 0xFF; - PendingCMD[i].Block = - (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; - - for (j = 0; j <= MAX_CHANS; j++) - PendingCMD[i].ChanSync[j] = 0; - } - - CDMA_Execute_CMDs(tag_count); - -#ifdef VERBOSE - print_pending_cmds(tag_count); -#endif -#if DEBUG_SYNC - } - debug_sync_cnt++; -#endif - - for (i = MAX_CHANS; - i < tag_count + MAX_CHANS; i++) { - CMD = PendingCMD[i].CMD; - data = PendingCMD[i].DataAddr; - block = PendingCMD[i].Block; - page = PendingCMD[i].Page; - count = PendingCMD[i].PageCount; - - switch (CMD) { - case ERASE_CMD: - mtd_Erase_Block(block); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_CMD: - mtd_Write_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_SPARE_CMD: - mtd_Write_Page_Main_Spare(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case READ_MAIN_CMD: - mtd_Read_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case MEMCOPY_CMD: - memcpy(PendingCMD[i].DataDestAddr, - PendingCMD[i].DataSrcAddr, - PendingCMD[i].MemCopyByteCnt); - case DUMMY_CMD: - PendingCMD[i].Status = PASS; - break; - default: - PendingCMD[i].Status = FAIL; - break; - } - } - - /* - * Temperory adding code to reset PendingCMD array for basic testing. - * It should be done at the end of event status function. - */ - for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = CMD_NOT_DONE; - } - - nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); - - mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */ - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Event_Status -* Inputs: none -* Outputs: Event_Status code -* Description: This function can also be used to force errors -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Event_Status(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return EVENT_PASS; -} - -#endif /* CMD_DMA */ -#endif /* !ELDORA */ diff --git a/drivers/block/spectra/lld_mtd.h b/drivers/block/spectra/lld_mtd.h deleted file mode 100644 index 4e81ee87b53d..000000000000 --- a/drivers/block/spectra/lld_mtd.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_MTD_ -#define _LLD_MTD_ - -#include "ffsport.h" -#include "ffsdefs.h" - -/* prototypes: MTD API functions */ -extern u16 mtd_Flash_Reset(void); -extern u16 mtd_Flash_Init(void); -extern int mtd_Flash_Release(void); -extern u16 mtd_Read_Device_ID(void); -extern u16 mtd_Erase_Block(u32 block_addr); -extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 mtd_Event_Status(void); -extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE); -extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 mtd_Get_Bad_Block(u32 block); - -u16 mtd_CDMA_Flash_Init(void); -u16 mtd_CDMA_Execute_CMDs(u16 tag_count); -u16 mtd_CDMA_Event_Status(void); -#endif /*_LLD_MTD_*/ diff --git a/drivers/block/spectra/lld_nand.c b/drivers/block/spectra/lld_nand.c deleted file mode 100644 index 13c3ad2db394..000000000000 --- a/drivers/block/spectra/lld_nand.c +++ /dev/null @@ -1,2601 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "lld.h" -#include "lld_nand.h" -#include "lld_cdma.h" - -#include "spectraswconfig.h" -#include "flash.h" -#include "ffsdefs.h" - -#include -#include -#include -#include - -#include "nand_regs.h" - -#define SPECTRA_NAND_NAME "nd" - -#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) -#define MAX_PAGES_PER_RW 128 - -#define INT_IDLE_STATE 0 -#define INT_READ_PAGE_MAIN 0x01 -#define INT_WRITE_PAGE_MAIN 0x02 -#define INT_PIPELINE_READ_AHEAD 0x04 -#define INT_PIPELINE_WRITE_AHEAD 0x08 -#define INT_MULTI_PLANE_READ 0x10 -#define INT_MULTI_PLANE_WRITE 0x11 - -static u32 enable_ecc; - -struct mrst_nand_info info; - -int totalUsedBanks; -u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; - -void __iomem *FlashReg; -void __iomem *FlashMem; - -u16 conf_parameters[] = { - 0x0000, - 0x0000, - 0x01F4, - 0x01F4, - 0x01F4, - 0x01F4, - 0x0000, - 0x0000, - 0x0001, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0040, - 0x0001, - 0x000A, - 0x000A, - 0x000A, - 0x0000, - 0x0000, - 0x0005, - 0x0012, - 0x000C -}; - -u16 NAND_Get_Bad_Block(u32 block) -{ - u32 status = PASS; - u32 flag_bytes = 0; - u32 skip_bytes = DeviceInfo.wSpareSkipBytes; - u32 page, i; - u8 *pReadSpareBuf = buf_get_bad_block; - - if (enable_ecc) - flag_bytes = DeviceInfo.wNumPageSpareFlag; - - for (page = 0; page < 2; page++) { - status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1); - if (status != PASS) - return READ_ERROR; - for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) - if (pReadSpareBuf[i] != 0xff) - return DEFECTIVE_BLOCK; - } - - for (page = 1; page < 3; page++) { - status = NAND_Read_Page_Spare(pReadSpareBuf, block, - DeviceInfo.wPagesPerBlock - page , 1); - if (status != PASS) - return READ_ERROR; - for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) - if (pReadSpareBuf[i] != 0xff) - return DEFECTIVE_BLOCK; - } - - return GOOD_BLOCK; -} - - -u16 NAND_Flash_Reset(void) -{ - u32 i; - u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP, - INTR_STATUS1__RST_COMP, - INTR_STATUS2__RST_COMP, - INTR_STATUS3__RST_COMP}; - u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT, - INTR_STATUS1__TIME_OUT, - INTR_STATUS2__TIME_OUT, - INTR_STATUS3__TIME_OUT}; - u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - u32 device_reset_banks[4] = {DEVICE_RESET__BANK0, - DEVICE_RESET__BANK1, - DEVICE_RESET__BANK2, - DEVICE_RESET__BANK3}; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) - iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], - FlashReg + intr_status[i]); - - for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { - iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET); - while (!(ioread32(FlashReg + intr_status[i]) & - (intr_status_rst_comp[i] | intr_status_time_out[i]))) - ; - if (ioread32(FlashReg + intr_status[i]) & - intr_status_time_out[i]) - nand_dbg_print(NAND_DBG_WARN, - "NAND Reset operation timed out on bank %d\n", i); - } - - for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) - iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], - FlashReg + intr_status[i]); - - return PASS; -} - -static void NAND_ONFi_Timing_Mode(u16 mode) -{ - u16 Trea[6] = {40, 30, 25, 20, 20, 16}; - u16 Trp[6] = {50, 25, 17, 15, 12, 10}; - u16 Treh[6] = {30, 15, 15, 10, 10, 7}; - u16 Trc[6] = {100, 50, 35, 30, 25, 20}; - u16 Trhoh[6] = {0, 15, 15, 15, 15, 15}; - u16 Trloh[6] = {0, 0, 0, 0, 5, 5}; - u16 Tcea[6] = {100, 45, 30, 25, 25, 25}; - u16 Tadl[6] = {200, 100, 100, 100, 70, 70}; - u16 Trhw[6] = {200, 100, 100, 100, 100, 100}; - u16 Trhz[6] = {200, 100, 100, 100, 100, 100}; - u16 Twhr[6] = {120, 80, 80, 60, 60, 60}; - u16 Tcs[6] = {70, 35, 25, 25, 20, 15}; - - u16 TclsRising = 1; - u16 data_invalid_rhoh, data_invalid_rloh, data_invalid; - u16 dv_window = 0; - u16 en_lo, en_hi; - u16 acc_clks; - u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - en_lo = CEIL_DIV(Trp[mode], CLK_X); - en_hi = CEIL_DIV(Treh[mode], CLK_X); - -#if ONFI_BLOOM_TIME - if ((en_hi * CLK_X) < (Treh[mode] + 2)) - en_hi++; -#endif - - if ((en_lo + en_hi) * CLK_X < Trc[mode]) - en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X); - - if ((en_lo + en_hi) < CLK_MULTI) - en_lo += CLK_MULTI - en_lo - en_hi; - - while (dv_window < 8) { - data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode]; - - data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode]; - - data_invalid = - data_invalid_rhoh < - data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh; - - dv_window = data_invalid - Trea[mode]; - - if (dv_window < 8) - en_lo++; - } - - acc_clks = CEIL_DIV(Trea[mode], CLK_X); - - while (((acc_clks * CLK_X) - Trea[mode]) < 3) - acc_clks++; - - if ((data_invalid - acc_clks * CLK_X) < 2) - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n", - __FILE__, __LINE__); - - addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); - re_2_we = CEIL_DIV(Trhw[mode], CLK_X); - re_2_re = CEIL_DIV(Trhz[mode], CLK_X); - we_2_re = CEIL_DIV(Twhr[mode], CLK_X); - cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X); - if (!TclsRising) - cs_cnt = CEIL_DIV(Tcs[mode], CLK_X); - if (cs_cnt == 0) - cs_cnt = 1; - - if (Tcea[mode]) { - while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode]) - cs_cnt++; - } - -#if MODE5_WORKAROUND - if (mode == 5) - acc_clks = 5; -#endif - - /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */ - if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) && - (ioread32(FlashReg + DEVICE_ID) == 0x88)) - acc_clks = 6; - - iowrite32(acc_clks, FlashReg + ACC_CLKS); - iowrite32(re_2_we, FlashReg + RE_2_WE); - iowrite32(re_2_re, FlashReg + RE_2_RE); - iowrite32(we_2_re, FlashReg + WE_2_RE); - iowrite32(addr_2_data, FlashReg + ADDR_2_DATA); - iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT); - iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT); - iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT); -} - -static void index_addr(u32 address, u32 data) -{ - iowrite32(address, FlashMem); - iowrite32(data, FlashMem + 0x10); -} - -static void index_addr_read_data(u32 address, u32 *pdata) -{ - iowrite32(address, FlashMem); - *pdata = ioread32(FlashMem + 0x10); -} - -static void set_ecc_config(void) -{ -#if SUPPORT_8BITECC - if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) || - (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128)) - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - - if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) - == 1) { - DeviceInfo.wECCBytesPerSector = 4; - DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; - DeviceInfo.wNumPageSpareFlag = - DeviceInfo.wPageSpareSize - - DeviceInfo.wPageDataSize / - (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * - DeviceInfo.wECCBytesPerSector - - DeviceInfo.wSpareSkipBytes; - } else { - DeviceInfo.wECCBytesPerSector = - (ioread32(FlashReg + ECC_CORRECTION) & - ECC_CORRECTION__VALUE) * 13 / 8; - if ((DeviceInfo.wECCBytesPerSector) % 2 == 0) - DeviceInfo.wECCBytesPerSector += 2; - else - DeviceInfo.wECCBytesPerSector += 1; - - DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; - DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize - - DeviceInfo.wPageDataSize / - (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * - DeviceInfo.wECCBytesPerSector - - DeviceInfo.wSpareSkipBytes; - } -} - -static u16 get_onfi_nand_para(void) -{ - int i; - u16 blks_lun_l, blks_lun_h, n_of_luns; - u32 blockperlun, id; - - iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET); - - while (!((ioread32(FlashReg + INTR_STATUS0) & - INTR_STATUS0__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS0) & - INTR_STATUS0__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { - iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__RST_COMP) { - iowrite32(DEVICE_RESET__BANK2, - FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__RST_COMP) { - iowrite32(DEVICE_RESET__BANK3, - FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS3) & - INTR_STATUS3__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS3) & - INTR_STATUS3__TIME_OUT))) - ; - } else { - printk(KERN_ERR "Getting a time out for bank 2!\n"); - } - } else { - printk(KERN_ERR "Getting a time out for bank 1!\n"); - } - } - - iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0); - iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1); - iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2); - iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3); - - DeviceInfo.wONFIDevFeatures = - ioread32(FlashReg + ONFI_DEVICE_FEATURES); - DeviceInfo.wONFIOptCommands = - ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS); - DeviceInfo.wONFITimingMode = - ioread32(FlashReg + ONFI_TIMING_MODE); - DeviceInfo.wONFIPgmCacheTimingMode = - ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE); - - n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & - ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; - blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); - blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); - - blockperlun = (blks_lun_h << 16) | blks_lun_l; - - DeviceInfo.wTotalBlocks = n_of_luns * blockperlun; - - if (!(ioread32(FlashReg + ONFI_TIMING_MODE) & - ONFI_TIMING_MODE__VALUE)) - return FAIL; - - for (i = 5; i > 0; i--) { - if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i)) - break; - } - - NAND_ONFi_Timing_Mode(i); - - index_addr(MODE_11 | 0, 0x90); - index_addr(MODE_11 | 1, 0); - - for (i = 0; i < 3; i++) - index_addr_read_data(MODE_11 | 2, &id); - - nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); - - DeviceInfo.MLCDevice = id & 0x0C; - - /* By now, all the ONFI devices we know support the page cache */ - /* rw feature. So here we enable the pipeline_rw_ahead feature */ - /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */ - /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */ - - return PASS; -} - -static void get_samsung_nand_para(void) -{ - u8 no_of_planes; - u32 blk_size; - u64 plane_size, capacity; - u32 id_bytes[5]; - int i; - - index_addr((u32)(MODE_11 | 0), 0x90); - index_addr((u32)(MODE_11 | 1), 0); - for (i = 0; i < 5; i++) - index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]); - - nand_dbg_print(NAND_DBG_DEBUG, - "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", - id_bytes[0], id_bytes[1], id_bytes[2], - id_bytes[3], id_bytes[4]); - - if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ - /* Set timing register values according to datasheet */ - iowrite32(5, FlashReg + ACC_CLKS); - iowrite32(20, FlashReg + RE_2_WE); - iowrite32(12, FlashReg + WE_2_RE); - iowrite32(14, FlashReg + ADDR_2_DATA); - iowrite32(3, FlashReg + RDWR_EN_LO_CNT); - iowrite32(2, FlashReg + RDWR_EN_HI_CNT); - iowrite32(2, FlashReg + CS_SETUP_CNT); - } - - no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); - plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4); - blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4); - capacity = (u64)128 * plane_size * no_of_planes; - - DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size); -} - -static void get_toshiba_nand_para(void) -{ - void __iomem *scratch_reg; - u32 tmp; - - /* Workaround to fix a controller bug which reports a wrong */ - /* spare area size for some kind of Toshiba NAND device */ - if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) && - (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) { - iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE); - tmp = ioread32(FlashReg + DEVICES_CONNECTED) * - ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); - iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE); -#if SUPPORT_15BITECC - iowrite32(15, FlashReg + ECC_CORRECTION); -#elif SUPPORT_8BITECC - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - } - - /* As Toshiba NAND can not provide it's block number, */ - /* so here we need user to provide the correct block */ - /* number in a scratch register before the Linux NAND */ - /* driver is loaded. If no valid value found in the scratch */ - /* register, then we use default block number value */ - scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); - if (!scratch_reg) { - printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", - __FILE__, __LINE__); - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Spectra: ioremap reg address: 0x%p\n", scratch_reg); - DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); - if (DeviceInfo.wTotalBlocks < 512) - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - iounmap(scratch_reg); - } -} - -static void get_hynix_nand_para(void) -{ - void __iomem *scratch_reg; - u32 main_size, spare_size; - - switch (DeviceInfo.wDeviceID) { - case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ - case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ - iowrite32(128, FlashReg + PAGES_PER_BLOCK); - iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE); - iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE); - main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED); - spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED); - iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE); - iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE); - iowrite32(0, FlashReg + DEVICE_WIDTH); -#if SUPPORT_15BITECC - iowrite32(15, FlashReg + ECC_CORRECTION); -#elif SUPPORT_8BITECC - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - DeviceInfo.MLCDevice = 1; - break; - default: - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." - "Will use default parameter values instead.\n", - DeviceInfo.wDeviceID); - } - - scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); - if (!scratch_reg) { - printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", - __FILE__, __LINE__); - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Spectra: ioremap reg address: 0x%p\n", scratch_reg); - DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); - if (DeviceInfo.wTotalBlocks < 512) - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - iounmap(scratch_reg); - } -} - -static void find_valid_banks(void) -{ - u32 id[LLD_MAX_FLASH_BANKS]; - int i; - - totalUsedBanks = 0; - for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { - index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90); - index_addr((u32)(MODE_11 | (i << 24) | 1), 0); - index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]); - - nand_dbg_print(NAND_DBG_DEBUG, - "Return 1st ID for bank[%d]: %x\n", i, id[i]); - - if (i == 0) { - if (id[i] & 0x0ff) - GLOB_valid_banks[i] = 1; - } else { - if ((id[i] & 0x0ff) == (id[0] & 0x0ff)) - GLOB_valid_banks[i] = 1; - } - - totalUsedBanks += GLOB_valid_banks[i]; - } - - nand_dbg_print(NAND_DBG_DEBUG, - "totalUsedBanks: %d\n", totalUsedBanks); -} - -static void detect_partition_feature(void) -{ - if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) { - if ((ioread32(FlashReg + PERM_SRC_ID_1) & - PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { - DeviceInfo.wSpectraStartBlock = - ((ioread32(FlashReg + MIN_MAX_BANK_1) & - MIN_MAX_BANK_1__MIN_VALUE) * - DeviceInfo.wTotalBlocks) - + - (ioread32(FlashReg + MIN_BLK_ADDR_1) & - MIN_BLK_ADDR_1__VALUE); - - DeviceInfo.wSpectraEndBlock = - (((ioread32(FlashReg + MIN_MAX_BANK_1) & - MIN_MAX_BANK_1__MAX_VALUE) >> 2) * - DeviceInfo.wTotalBlocks) - + - (ioread32(FlashReg + MAX_BLK_ADDR_1) & - MAX_BLK_ADDR_1__VALUE); - - DeviceInfo.wTotalBlocks *= totalUsedBanks; - - if (DeviceInfo.wSpectraEndBlock >= - DeviceInfo.wTotalBlocks) { - DeviceInfo.wSpectraEndBlock = - DeviceInfo.wTotalBlocks - 1; - } - - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } else { - DeviceInfo.wTotalBlocks *= totalUsedBanks; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - DeviceInfo.wSpectraEndBlock = - DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } - } else { - DeviceInfo.wTotalBlocks *= totalUsedBanks; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } -} - -static void dump_device_info(void) -{ - nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n"); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", - DeviceInfo.wDeviceMaker); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", - DeviceInfo.wDeviceID); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", - DeviceInfo.wDeviceType); - nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", - DeviceInfo.wSpectraStartBlock); - nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", - DeviceInfo.wSpectraEndBlock); - nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", - DeviceInfo.wTotalBlocks); - nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", - DeviceInfo.wPagesPerBlock); - nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", - DeviceInfo.wPageSize); - nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", - DeviceInfo.wPageDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", - DeviceInfo.wPageSpareSize); - nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", - DeviceInfo.wNumPageSpareFlag); - nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", - DeviceInfo.wECCBytesPerSector); - nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", - DeviceInfo.wBlockSize); - nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", - DeviceInfo.wBlockDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", - DeviceInfo.wDataBlockNum); - nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", - DeviceInfo.bPlaneNum); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", - DeviceInfo.wDeviceMainAreaSize); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", - DeviceInfo.wDeviceSpareAreaSize); - nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", - DeviceInfo.wDevicesConnected); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", - DeviceInfo.wDeviceWidth); - nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", - DeviceInfo.wHWRevision); - nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", - DeviceInfo.wHWFeatures); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", - DeviceInfo.wONFIDevFeatures); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", - DeviceInfo.wONFIOptCommands); - nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", - DeviceInfo.wONFITimingMode); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", - DeviceInfo.wONFIPgmCacheTimingMode); - nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", - DeviceInfo.MLCDevice ? "Yes" : "No"); - nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", - DeviceInfo.wSpareSkipBytes); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", - DeviceInfo.nBitsInPageNumber); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", - DeviceInfo.nBitsInPageDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", - DeviceInfo.nBitsInBlockDataSize); -} - -u16 NAND_Read_Device_ID(void) -{ - u16 status = PASS; - u8 no_of_planes; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES); - iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER); - DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID); - DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID); - DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c; - - if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & - ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ - if (FAIL == get_onfi_nand_para()) - return FAIL; - } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */ - get_samsung_nand_para(); - } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */ - get_toshiba_nand_para(); - } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */ - get_hynix_nand_para(); - } else { - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" - "acc_clks: %d, re_2_we: %d, we_2_re: %d," - "addr_2_data: %d, rdwr_en_lo_cnt: %d, " - "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", - ioread32(FlashReg + ACC_CLKS), - ioread32(FlashReg + RE_2_WE), - ioread32(FlashReg + WE_2_RE), - ioread32(FlashReg + ADDR_2_DATA), - ioread32(FlashReg + RDWR_EN_LO_CNT), - ioread32(FlashReg + RDWR_EN_HI_CNT), - ioread32(FlashReg + CS_SETUP_CNT)); - - DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION); - DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES); - - DeviceInfo.wDeviceMainAreaSize = - ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE); - DeviceInfo.wDeviceSpareAreaSize = - ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); - - DeviceInfo.wPageDataSize = - ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE); - - /* Note: When using the Micon 4K NAND device, the controller will report - * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. - * And if force set it to 218 bytes, the controller can not work - * correctly. So just let it be. But keep in mind that this bug may - * cause - * other problems in future. - Yunpeng 2008-10-10 - */ - DeviceInfo.wPageSpareSize = - ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE); - - DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK); - - DeviceInfo.wPageSize = - DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize; - DeviceInfo.wBlockSize = - DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wBlockDataSize = - DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; - - DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH); - DeviceInfo.wDeviceType = - ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8); - - DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED); - - DeviceInfo.wSpareSkipBytes = - ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) * - DeviceInfo.wDevicesConnected; - - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - - set_ecc_config(); - - no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) & - NUMBER_OF_PLANES__VALUE; - - switch (no_of_planes) { - case 0: - case 1: - case 3: - case 7: - DeviceInfo.bPlaneNum = no_of_planes + 1; - break; - default: - status = FAIL; - break; - } - - find_valid_banks(); - - detect_partition_feature(); - - dump_device_info(); - - return status; -} - -u16 NAND_UnlockArrayAll(void) -{ - u64 start_addr, end_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - start_addr = 0; - end_addr = ((u64)DeviceInfo.wBlockSize * - (DeviceInfo.wTotalBlocks - 1)) >> - DeviceInfo.nBitsInPageDataSize; - - index_addr((u32)(MODE_10 | (u32)start_addr), 0x10); - index_addr((u32)(MODE_10 | (u32)end_addr), 0x11); - - return PASS; -} - -void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (INT_ENABLE) - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); - else - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); -} - -u16 NAND_Erase_Block(u32 block) -{ - u16 status = PASS; - u64 flash_add; - u16 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (block >= DeviceInfo.wTotalBlocks) - status = FAIL; - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, - FlashReg + intr_status); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1); - - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ERASE_FAIL) - status = FAIL; - - iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, - FlashReg + intr_status); - } - - return status; -} - -static u32 Boundary_Check_Block_Page(u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - - if (block >= DeviceInfo.wTotalBlocks) - status = FAIL; - - if (page + page_count > DeviceInfo.wPagesPerBlock) - status = FAIL; - - return status; -} - -u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 i; - u64 flash_add; - u32 PageSpareSize = DeviceInfo.wPageSpareSize; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_spare = buf_read_page_spare; - - if (block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "block too big: %d\n", (int)block); - status = FAIL; - } - - if (page >= DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "page too big: %d\n", page); - status = FAIL; - } - - if (page_count > 1) { - printk(KERN_ERR "page count too big: %d\n", page_count); - status = FAIL; - } - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x41); - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x2000 | page_count); - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__LOAD_COMP)) - ; - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - for (i = 0; i < (PageSpareSize / 4); i++) - *((u32 *)page_spare + i) = - ioread32(FlashMem + 0x10); - - if (enable_ecc) { - for (i = 0; i < spareFlagBytes; i++) - read_data[i] = - page_spare[PageSpareSize - - spareFlagBytes + i]; - for (i = 0; i < (PageSpareSize - spareFlagBytes); i++) - read_data[spareFlagBytes + i] = - page_spare[i]; - } else { - for (i = 0; i < PageSpareSize; i++) - read_data[i] = page_spare[i]; - } - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - } - - return status; -} - -/* No use function. Should be removed later */ -u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - printk(KERN_ERR - "Error! This function (NAND_Write_Page_Spare) should never" - " be called!\n"); - return ERR; -} - -/* op value: 0 - DDMA read; 1 - DDMA write */ -static void ddma_trans(u8 *data, u64 flash_add, - u32 flash_bank, int op, u32 numPages) -{ - u32 data_addr; - - /* Map virtual address to bus address for DDMA */ - data_addr = virt_to_bus(data); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - (u16)(2 << 12) | (op << 8) | numPages); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - ((u16)(0x0FFFF & (data_addr >> 16)) << 8)), - (u16)(2 << 12) | (2 << 8) | 0); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - ((u16)(0x0FFFF & data_addr) << 8)), - (u16)(2 << 12) | (3 << 8) | 0); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (1 << 16) | (0x40 << 8)), - (u16)(2 << 12) | (4 << 8) | 0); -} - -/* If data in buf are all 0xff, then return 1; otherwise return 0 */ -static int check_all_1(u8 *buf) -{ - int i, j, cnt; - - for (i = 0; i < DeviceInfo.wPageDataSize; i++) { - if (buf[i] != 0xff) { - cnt = 0; - nand_dbg_print(NAND_DBG_WARN, - "the first non-0xff data byte is: %d\n", i); - for (j = i; j < DeviceInfo.wPageDataSize; j++) { - nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]); - cnt++; - if (cnt > 8) - break; - } - nand_dbg_print(NAND_DBG_WARN, "\n"); - return 0; - } - } - - return 1; -} - -static int do_ecc_new(unsigned long bank, u8 *buf, - u32 block, u16 page) -{ - int status = PASS; - u16 err_page = 0; - u16 err_byte; - u8 err_sect; - u8 err_dev; - u16 err_fix_info; - u16 err_addr; - u32 ecc_sect_size; - u8 *err_pos; - u32 err_page_addr[4] = {ERR_PAGE_ADDR0, - ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3}; - - ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - do { - err_page = ioread32(FlashReg + err_page_addr[bank]); - err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS); - err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET; - err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); - err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO); - err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR) - >> 8); - if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) { - nand_dbg_print(NAND_DBG_WARN, - "%s, Line %d Uncorrectable ECC error " - "when read block %d page %d." - "PTN_INTR register: 0x%x " - "err_page: %d, err_sect: %d, err_byte: %d, " - "err_dev: %d, ecc_sect_size: %d, " - "err_fix_info: 0x%x\n", - __FILE__, __LINE__, block, page, - ioread32(FlashReg + PTN_INTR), - err_page, err_sect, err_byte, err_dev, - ecc_sect_size, (u32)err_fix_info); - - if (check_all_1(buf)) - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" - "All 0xff!\n", - __FILE__, __LINE__); - else - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" - "Not all 0xff!\n", - __FILE__, __LINE__); - status = FAIL; - } else { - nand_dbg_print(NAND_DBG_WARN, - "%s, Line %d Found ECC error " - "when read block %d page %d." - "err_page: %d, err_sect: %d, err_byte: %d, " - "err_dev: %d, ecc_sect_size: %d, " - "err_fix_info: 0x%x\n", - __FILE__, __LINE__, block, page, - err_page, err_sect, err_byte, err_dev, - ecc_sect_size, (u32)err_fix_info); - if (err_byte < ECC_SECTOR_SIZE) { - err_pos = buf + - (err_page - page) * - DeviceInfo.wPageDataSize + - err_sect * ecc_sect_size + - err_byte * - DeviceInfo.wDevicesConnected + - err_dev; - - *err_pos ^= err_fix_info & - ERR_CORRECTION_INFO__BYTEMASK; - } - } - } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); - - return status; -} - -u16 NAND_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *read_data_l; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - if (page_count > 1) { - read_data_l = read_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Read_Ahead_Polling( - read_data_l, block, page, - MAX_PAGES_PER_RW); - - if (status == FAIL) - return status; - - read_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Read_Ahead_Polling( - read_data_l, block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - ddma_trans(read_data, flash_add, flash_bank, 0, 1); - - if (enable_ecc) { - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, read_data, - block, page); - } - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE & - INTR_STATUS0__ECC_ERR) - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status); - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 ecc_done_OR_dma_comp; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - *DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - ecc_done_OR_dma_comp = 0; - while (1) { - if (enable_ecc) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - - } - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - } - return status; -} - -u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - u8 *read_data_l; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - if (page_count > 1) { - read_data_l = read_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Read_Ahead( - read_data_l, block, page, - MAX_PAGES_PER_RW); - - if (status == FAIL) - return status; - - read_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Read_Ahead( - read_data_l, block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - /* Fill the mrst_nand_info structure */ - info.state = INT_READ_PAGE_MAIN; - info.read_data = read_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - ddma_trans(read_data, flash_add, flash_bank, 0, 1); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -void Conv_Spare_Data_Log2Phy_Format(u8 *data) -{ - int i; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - const u32 PageSpareSize = DeviceInfo.wPageSpareSize; - - if (enable_ecc) { - for (i = spareFlagBytes - 1; i >= 0; i++) - data[PageSpareSize - spareFlagBytes + i] = data[i]; - } -} - -void Conv_Spare_Data_Phy2Log_Format(u8 *data) -{ - int i; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - const u32 PageSpareSize = DeviceInfo.wPageSpareSize; - - if (enable_ecc) { - for (i = 0; i < spareFlagBytes; i++) - data[i] = data[PageSpareSize - spareFlagBytes + i]; - } -} - - -void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count) -{ - const u32 PageSize = DeviceInfo.wPageSize; - const u32 PageDataSize = DeviceInfo.wPageDataSize; - const u32 eccBytes = DeviceInfo.wECCBytesPerSector; - const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 eccSectorSize; - u32 page_offset; - int i, j; - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - if (enable_ecc) { - while (page_count > 0) { - page_offset = (page_count - 1) * PageSize; - j = (DeviceInfo.wPageDataSize / eccSectorSize); - for (i = spareFlagBytes - 1; i >= 0; i--) - data[page_offset + - (eccSectorSize + eccBytes) * j + i] = - data[page_offset + PageDataSize + i]; - for (j--; j >= 1; j--) { - for (i = eccSectorSize - 1; i >= 0; i--) - data[page_offset + - (eccSectorSize + eccBytes) * j + i] = - data[page_offset + - eccSectorSize * j + i]; - } - for (i = (PageSize - spareSkipBytes) - 1; - i >= PageDataSize; i--) - data[page_offset + i + spareSkipBytes] = - data[page_offset + i]; - page_count--; - } - } -} - -void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count) -{ - const u32 PageSize = DeviceInfo.wPageSize; - const u32 PageDataSize = DeviceInfo.wPageDataSize; - const u32 eccBytes = DeviceInfo.wECCBytesPerSector; - const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 eccSectorSize; - u32 page_offset; - int i, j; - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - if (enable_ecc) { - while (page_count > 0) { - page_offset = (page_count - 1) * PageSize; - for (i = PageDataSize; - i < PageSize - spareSkipBytes; - i++) - data[page_offset + i] = - data[page_offset + i + - spareSkipBytes]; - for (j = 1; - j < DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - for (i = 0; i < eccSectorSize; i++) - data[page_offset + - eccSectorSize * j + i] = - data[page_offset + - (eccSectorSize + eccBytes) * j - + i]; - } - for (i = 0; i < spareFlagBytes; i++) - data[page_offset + PageDataSize + i] = - data[page_offset + - (eccSectorSize + eccBytes) * j + i]; - page_count--; - } - } -} - -/* Un-tested function */ -u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 ecc_done_OR_dma_comp; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - ecc_done_OR_dma_comp = 0; - while (1) { - if (enable_ecc) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - - } - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + MULTIPLANE_OPERATION); - } - - return status; -} - -u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, - u16 page, u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - *DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - /* Fill the mrst_nand_info structure */ - info.state = INT_PIPELINE_READ_AHEAD; - info.read_data = read_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - - -u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - u8 *write_data_l; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(INTR_STATUS0__PROGRAM_COMP | - INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status); - - if (page_count > 1) { - write_data_l = write_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Write(write_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Write_Ahead( - write_data_l, block, page, - MAX_PAGES_PER_RW); - if (status == FAIL) - return status; - - write_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Write(write_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Write_Ahead(write_data_l, - block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - /* Fill the mrst_nand_info structure */ - info.state = INT_WRITE_PAGE_MAIN; - info.write_data = write_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - ddma_trans(write_data, flash_add, flash_bank, 1, 1); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG) - ; - - return status; -} - -void NAND_ECC_Ctrl(int enable) -{ - if (enable) { - nand_dbg_print(NAND_DBG_WARN, - "Will enable ECC in %s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - iowrite32(1, FlashReg + ECC_ENABLE); - enable_ecc = 1; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Will disable ECC in %s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - iowrite32(0, FlashReg + ECC_ENABLE); - enable_ecc = 0; - } -} - -u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 page, u16 page_count) -{ - u32 status = PASS; - u32 i, j, page_num = 0; - u32 PageSize = DeviceInfo.wPageSize; - u32 PageDataSize = DeviceInfo.wPageDataSize; - u32 eccBytes = DeviceInfo.wECCBytesPerSector; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - u64 flash_add; - u32 eccSectorSize; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_main_spare = buf_write_page_main_spare; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(1, FlashReg + TRANSFER_SPARE_REG); - - while ((status != FAIL) && (page_count > 0)) { - flash_add = (u64)(block % - (DeviceInfo.wTotalBlocks / totalUsedBanks)) * - DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> - DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - if (enable_ecc) { - for (j = 0; - j < - DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - for (i = 0; i < eccSectorSize; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + - i] = - write_data[eccSectorSize * - j + i]; - - for (i = 0; i < eccBytes; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + - eccSectorSize + - i] = - write_data[PageDataSize + - spareFlagBytes + - eccBytes * j + - i]; - } - - for (i = 0; i < spareFlagBytes; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + i] = - write_data[PageDataSize + i]; - - for (i = PageSize - 1; i >= PageDataSize + - spareSkipBytes; i--) - page_main_spare[i] = page_main_spare[i - - spareSkipBytes]; - - for (i = PageDataSize; i < PageDataSize + - spareSkipBytes; i++) - page_main_spare[i] = 0xff; - - for (i = 0; i < PageSize / 4; i++) - iowrite32( - *((u32 *)page_main_spare + i), - FlashMem + 0x10); - } else { - - for (i = 0; i < PageSize / 4; i++) - iowrite32(*((u32 *)write_data + i), - FlashMem + 0x10); - } - - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__PROGRAM_COMP | - INTR_STATUS0__PROGRAM_FAIL))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) - status = FAIL; - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - page_num++; - page_count--; - write_data += PageSize; - } - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - } - - return status; -} - -u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 i, j; - u64 flash_add = 0; - u32 PageSize = DeviceInfo.wPageSize; - u32 PageDataSize = DeviceInfo.wPageDataSize; - u32 PageSpareSize = DeviceInfo.wPageSpareSize; - u32 eccBytes = DeviceInfo.wECCBytesPerSector; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - u32 eccSectorSize; - u32 flash_bank; - u32 intr_status = 0; - u8 *read_data_l = read_data; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_main_spare = buf_read_page_main_spare; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(1, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - while ((status != FAIL) && (page_count > 0)) { - flash_add = (u64)(block % - (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x43); - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x2000 | page_count); - - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__LOAD_COMP)) - ; - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> - DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - for (i = 0; i < PageSize / 4; i++) - *(((u32 *)page_main_spare) + i) = - ioread32(FlashMem + 0x10); - - if (enable_ecc) { - for (i = PageDataSize; i < PageSize - - spareSkipBytes; i++) - page_main_spare[i] = page_main_spare[i + - spareSkipBytes]; - - for (j = 0; - j < DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - - for (i = 0; i < eccSectorSize; i++) - read_data_l[eccSectorSize * j + - i] = - page_main_spare[ - (eccSectorSize + - eccBytes) * j + i]; - - for (i = 0; i < eccBytes; i++) - read_data_l[PageDataSize + - spareFlagBytes + - eccBytes * j + i] = - page_main_spare[ - (eccSectorSize + - eccBytes) * j + - eccSectorSize + i]; - } - - for (i = 0; i < spareFlagBytes; i++) - read_data_l[PageDataSize + i] = - page_main_spare[(eccSectorSize + - eccBytes) * j + i]; - } else { - for (i = 0; i < (PageDataSize + PageSpareSize); - i++) - read_data_l[i] = page_main_spare[i]; - - } - - if (enable_ecc) { - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR | - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - } - } - - page++; - page_count--; - read_data_l += PageSize; - } - } - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - return status; -} - -u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, - u16 page, u16 page_count) -{ - u16 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - /* Fill the mrst_nand_info structure */ - info.state = INT_PIPELINE_WRITE_AHEAD; - info.write_data = write_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -/* Un-tested function */ -u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - u16 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u16 status2 = PASS; - u32 t; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); - - while (1) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - status = PASS; - if (status2 == FAIL) - status = FAIL; - break; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) { - status2 = FAIL; - status = FAIL; - t = ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL; - iowrite32(t, FlashReg + intr_status); - } else { - iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + MULTIPLANE_OPERATION); - - return status; -} - - -#if CMD_DMA -static irqreturn_t cdma_isr(int irq, void *dev_id) -{ - struct mrst_nand_info *dev = dev_id; - int first_failed_cmd; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!is_cdma_interrupt()) - return IRQ_NONE; - - /* Disable controller interrupts */ - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - GLOB_FTL_Event_Status(&first_failed_cmd); - complete(&dev->complete); - - return IRQ_HANDLED; -} -#else -static void handle_nand_int_read(struct mrst_nand_info *dev) -{ - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 intr_status; - u32 ecc_done_OR_dma_comp = 0; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev->ret = PASS; - intr_status = intr_status_addresses[dev->flash_bank]; - - while (1) { - if (enable_ecc) { - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - dev->ret = do_ecc_new(dev->flash_bank, - dev->read_data, - dev->block, dev->page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - if (1 == ecc_done_OR_dma_comp) - break; - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - if (1 == ecc_done_OR_dma_comp) - break; - ecc_done_OR_dma_comp = 1; - } - } else { - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } else { - printk(KERN_ERR "Illegal INTS " - "(offset addr 0x%x) value: 0x%x\n", - intr_status, - ioread32(FlashReg + intr_status)); - } - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } -} - -static void handle_nand_int_write(struct mrst_nand_info *dev) -{ - u32 intr_status; - u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - int status = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev->ret = PASS; - intr_status = intr[dev->flash_bank]; - - while (1) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - if (FAIL == status) - dev->ret = FAIL; - break; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) { - status = FAIL; - iowrite32(INTR_STATUS0__PROGRAM_FAIL, - FlashReg + intr_status); - } else { - iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } - } -} - -static irqreturn_t ddma_isr(int irq, void *dev_id) -{ - struct mrst_nand_info *dev = dev_id; - u32 int_mask, ints0, ints1, ints2, ints3, ints_offset; - u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - - int_mask = INTR_STATUS0__DMA_CMD_COMP | - INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL; - - ints0 = ioread32(FlashReg + INTR_STATUS0); - ints1 = ioread32(FlashReg + INTR_STATUS1); - ints2 = ioread32(FlashReg + INTR_STATUS2); - ints3 = ioread32(FlashReg + INTR_STATUS3); - - ints_offset = intr[dev->flash_bank]; - - nand_dbg_print(NAND_DBG_DEBUG, - "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, " - "DMA_INTR: 0x%x, " - "dev->state: 0x%x, dev->flash_bank: %d\n", - ints0, ints1, ints2, ints3, - ioread32(FlashReg + DMA_INTR), - dev->state, dev->flash_bank); - - if (!(ioread32(FlashReg + ints_offset) & int_mask)) { - iowrite32(ints0, FlashReg + INTR_STATUS0); - iowrite32(ints1, FlashReg + INTR_STATUS1); - iowrite32(ints2, FlashReg + INTR_STATUS2); - iowrite32(ints3, FlashReg + INTR_STATUS3); - nand_dbg_print(NAND_DBG_WARN, - "ddma_isr: Invalid interrupt for NAND controller. " - "Ignore it\n"); - return IRQ_NONE; - } - - switch (dev->state) { - case INT_READ_PAGE_MAIN: - case INT_PIPELINE_READ_AHEAD: - /* Disable controller interrupts */ - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - handle_nand_int_read(dev); - break; - case INT_WRITE_PAGE_MAIN: - case INT_PIPELINE_WRITE_AHEAD: - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - handle_nand_int_write(dev); - break; - default: - printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n", - dev->state); - return IRQ_NONE; - } - - dev->state = INT_IDLE_STATE; - complete(&dev->complete); - return IRQ_HANDLED; -} -#endif - -static const struct pci_device_id nand_pci_ids[] = { - { - .vendor = 0x8086, - .device = 0x0809, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { /* end: all zeroes */ } -}; - -static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int ret = -ENODEV; - unsigned long csr_base; - unsigned long csr_len; - struct mrst_nand_info *pndev = &info; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ret = pci_enable_device(dev); - if (ret) { - printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); - return ret; - } - - pci_set_master(dev); - pndev->dev = dev; - - csr_base = pci_resource_start(dev, 0); - if (!csr_base) { - printk(KERN_ERR "Spectra: pci_resource_start failed!\n"); - return -ENODEV; - } - - csr_len = pci_resource_len(dev, 0); - if (!csr_len) { - printk(KERN_ERR "Spectra: pci_resource_len failed!\n"); - return -ENODEV; - } - - ret = pci_request_regions(dev, SPECTRA_NAND_NAME); - if (ret) { - printk(KERN_ERR "Spectra: Unable to request " - "memory region\n"); - goto failed_req_csr; - } - - pndev->ioaddr = ioremap_nocache(csr_base, csr_len); - if (!pndev->ioaddr) { - printk(KERN_ERR "Spectra: Unable to remap memory region\n"); - ret = -ENOMEM; - goto failed_remap_csr; - } - nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n", - csr_base, pndev->ioaddr, csr_len); - - init_completion(&pndev->complete); - nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq); - -#if CMD_DMA - if (request_irq(dev->irq, cdma_isr, IRQF_SHARED, - SPECTRA_NAND_NAME, &info)) { - printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); - ret = -ENODEV; - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } -#else - if (request_irq(dev->irq, ddma_isr, IRQF_SHARED, - SPECTRA_NAND_NAME, &info)) { - printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); - ret = -ENODEV; - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } -#endif - - pci_set_drvdata(dev, pndev); - - return 0; - -failed_remap_csr: - pci_release_regions(dev); -failed_req_csr: - - return ret; -} - -static void nand_pci_remove(struct pci_dev *dev) -{ - struct mrst_nand_info *pndev = pci_get_drvdata(dev); - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#if CMD_DMA - free_irq(dev->irq, pndev); -#endif - iounmap(pndev->ioaddr); - pci_release_regions(dev); - pci_disable_device(dev); -} - -MODULE_DEVICE_TABLE(pci, nand_pci_ids); - -static struct pci_driver nand_pci_driver = { - .name = SPECTRA_NAND_NAME, - .id_table = nand_pci_ids, - .probe = nand_pci_probe, - .remove = nand_pci_remove, -}; - -int NAND_Flash_Init(void) -{ - int retval; - u32 int_mask; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE, - GLOB_HWCTL_REG_SIZE); - if (!FlashReg) { - printk(KERN_ERR "Spectra: ioremap_nocache failed!"); - return -ENOMEM; - } - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Remapped reg base address: " - "0x%p, len: %d\n", - FlashReg, GLOB_HWCTL_REG_SIZE); - - FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE, - GLOB_HWCTL_MEM_SIZE); - if (!FlashMem) { - printk(KERN_ERR "Spectra: ioremap_nocache failed!"); - iounmap(FlashReg); - return -ENOMEM; - } - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Remapped flash base address: " - "0x%p, len: %d\n", - (void *)FlashMem, GLOB_HWCTL_MEM_SIZE); - - nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" - "acc_clks: %d, re_2_we: %d, we_2_re: %d," - "addr_2_data: %d, rdwr_en_lo_cnt: %d, " - "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", - ioread32(FlashReg + ACC_CLKS), - ioread32(FlashReg + RE_2_WE), - ioread32(FlashReg + WE_2_RE), - ioread32(FlashReg + ADDR_2_DATA), - ioread32(FlashReg + RDWR_EN_LO_CNT), - ioread32(FlashReg + RDWR_EN_HI_CNT), - ioread32(FlashReg + CS_SETUP_CNT)); - - NAND_Flash_Reset(); - - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - -#if CMD_DMA - info.pcmds_num = 0; - info.flash_bank = 0; - info.cdma_num = 0; - int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | - DMA_INTR__DESC_COMP_CHANNEL1 | - DMA_INTR__DESC_COMP_CHANNEL2 | - DMA_INTR__DESC_COMP_CHANNEL3 | - DMA_INTR__MEMCOPY_DESC_COMP); - iowrite32(int_mask, FlashReg + DMA_INTR_EN); - iowrite32(0xFFFF, FlashReg + DMA_INTR); - - int_mask = (INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL); -#else - int_mask = INTR_STATUS0__DMA_CMD_COMP | - INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL; -#endif - iowrite32(int_mask, FlashReg + INTR_EN0); - iowrite32(int_mask, FlashReg + INTR_EN1); - iowrite32(int_mask, FlashReg + INTR_EN2); - iowrite32(int_mask, FlashReg + INTR_EN3); - - /* Clear all status bits */ - iowrite32(0xFFFF, FlashReg + INTR_STATUS0); - iowrite32(0xFFFF, FlashReg + INTR_STATUS1); - iowrite32(0xFFFF, FlashReg + INTR_STATUS2); - iowrite32(0xFFFF, FlashReg + INTR_STATUS3); - - iowrite32(0x0F, FlashReg + RB_PIN_ENABLED); - iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE); - - /* Should set value for these registers when init */ - iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES); - iowrite32(1, FlashReg + ECC_ENABLE); - enable_ecc = 1; - - retval = pci_register_driver(&nand_pci_driver); - if (retval) - return -ENOMEM; - - return PASS; -} - -/* Free memory */ -int nand_release_spectra(void) -{ - pci_unregister_driver(&nand_pci_driver); - iounmap(FlashMem); - iounmap(FlashReg); - - return 0; -} - - - diff --git a/drivers/block/spectra/lld_nand.h b/drivers/block/spectra/lld_nand.h deleted file mode 100644 index d08388287da8..000000000000 --- a/drivers/block/spectra/lld_nand.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_NAND_ -#define _LLD_NAND_ - -#ifdef ELDORA -#include "defs.h" -#else -#include "flash.h" -#include "ffsport.h" -#endif - -#define MODE_00 0x00000000 -#define MODE_01 0x04000000 -#define MODE_10 0x08000000 -#define MODE_11 0x0C000000 - - -#define DATA_TRANSFER_MODE 0 -#define PROTECTION_PER_BLOCK 1 -#define LOAD_WAIT_COUNT 2 -#define PROGRAM_WAIT_COUNT 3 -#define ERASE_WAIT_COUNT 4 -#define INT_MONITOR_CYCLE_COUNT 5 -#define READ_BUSY_PIN_ENABLED 6 -#define MULTIPLANE_OPERATION_SUPPORT 7 -#define PRE_FETCH_MODE 8 -#define CE_DONT_CARE_SUPPORT 9 -#define COPYBACK_SUPPORT 10 -#define CACHE_WRITE_SUPPORT 11 -#define CACHE_READ_SUPPORT 12 -#define NUM_PAGES_IN_BLOCK 13 -#define ECC_ENABLE_SELECT 14 -#define WRITE_ENABLE_2_READ_ENABLE 15 -#define ADDRESS_2_DATA 16 -#define READ_ENABLE_2_WRITE_ENABLE 17 -#define TWO_ROW_ADDRESS_CYCLES 18 -#define MULTIPLANE_ADDRESS_RESTRICT 19 -#define ACC_CLOCKS 20 -#define READ_WRITE_ENABLE_LOW_COUNT 21 -#define READ_WRITE_ENABLE_HIGH_COUNT 22 - -#define ECC_SECTOR_SIZE 512 -#define LLD_MAX_FLASH_BANKS 4 - -struct mrst_nand_info { - struct pci_dev *dev; - u32 state; - u32 flash_bank; - u8 *read_data; - u8 *write_data; - u32 block; - u16 page; - u32 use_dma; - void __iomem *ioaddr; /* Mapped io reg base address */ - int ret; - u32 pcmds_num; - struct pending_cmd *pcmds; - int cdma_num; /* CDMA descriptor number in this chan */ - u8 *cdma_desc_buf; /* CDMA descriptor table */ - u8 *memcp_desc_buf; /* Memory copy descriptor table */ - dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */ - dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */ - struct completion complete; -}; - -int NAND_Flash_Init(void); -int nand_release_spectra(void); -u16 NAND_Flash_Reset(void); -u16 NAND_Read_Device_ID(void); -u16 NAND_Erase_Block(u32 flash_add); -u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_UnlockArrayAll(void); -u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 page, u16 page_count); -u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE); -u16 NAND_Get_Bad_Block(u32 block); -u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, - u16 page, u16 page_count); -u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, - u16 page_count); -void NAND_ECC_Ctrl(int enable); -u16 NAND_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); -u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); -void Conv_Spare_Data_Log2Phy_Format(u8 *data); -void Conv_Spare_Data_Phy2Log_Format(u8 *data); -void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count); -void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count); - -extern void __iomem *FlashReg; -extern void __iomem *FlashMem; - -extern int totalUsedBanks; -extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; - -#endif /*_LLD_NAND_*/ - - - diff --git a/drivers/block/spectra/nand_regs.h b/drivers/block/spectra/nand_regs.h deleted file mode 100644 index e192e4ae8c1e..000000000000 --- a/drivers/block/spectra/nand_regs.h +++ /dev/null @@ -1,619 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#define DEVICE_RESET 0x0 -#define DEVICE_RESET__BANK0 0x0001 -#define DEVICE_RESET__BANK1 0x0002 -#define DEVICE_RESET__BANK2 0x0004 -#define DEVICE_RESET__BANK3 0x0008 - -#define TRANSFER_SPARE_REG 0x10 -#define TRANSFER_SPARE_REG__FLAG 0x0001 - -#define LOAD_WAIT_CNT 0x20 -#define LOAD_WAIT_CNT__VALUE 0xffff - -#define PROGRAM_WAIT_CNT 0x30 -#define PROGRAM_WAIT_CNT__VALUE 0xffff - -#define ERASE_WAIT_CNT 0x40 -#define ERASE_WAIT_CNT__VALUE 0xffff - -#define INT_MON_CYCCNT 0x50 -#define INT_MON_CYCCNT__VALUE 0xffff - -#define RB_PIN_ENABLED 0x60 -#define RB_PIN_ENABLED__BANK0 0x0001 -#define RB_PIN_ENABLED__BANK1 0x0002 -#define RB_PIN_ENABLED__BANK2 0x0004 -#define RB_PIN_ENABLED__BANK3 0x0008 - -#define MULTIPLANE_OPERATION 0x70 -#define MULTIPLANE_OPERATION__FLAG 0x0001 - -#define MULTIPLANE_READ_ENABLE 0x80 -#define MULTIPLANE_READ_ENABLE__FLAG 0x0001 - -#define COPYBACK_DISABLE 0x90 -#define COPYBACK_DISABLE__FLAG 0x0001 - -#define CACHE_WRITE_ENABLE 0xa0 -#define CACHE_WRITE_ENABLE__FLAG 0x0001 - -#define CACHE_READ_ENABLE 0xb0 -#define CACHE_READ_ENABLE__FLAG 0x0001 - -#define PREFETCH_MODE 0xc0 -#define PREFETCH_MODE__PREFETCH_EN 0x0001 -#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0 - -#define CHIP_ENABLE_DONT_CARE 0xd0 -#define CHIP_EN_DONT_CARE__FLAG 0x01 - -#define ECC_ENABLE 0xe0 -#define ECC_ENABLE__FLAG 0x0001 - -#define GLOBAL_INT_ENABLE 0xf0 -#define GLOBAL_INT_EN_FLAG 0x01 - -#define WE_2_RE 0x100 -#define WE_2_RE__VALUE 0x003f - -#define ADDR_2_DATA 0x110 -#define ADDR_2_DATA__VALUE 0x003f - -#define RE_2_WE 0x120 -#define RE_2_WE__VALUE 0x003f - -#define ACC_CLKS 0x130 -#define ACC_CLKS__VALUE 0x000f - -#define NUMBER_OF_PLANES 0x140 -#define NUMBER_OF_PLANES__VALUE 0x0007 - -#define PAGES_PER_BLOCK 0x150 -#define PAGES_PER_BLOCK__VALUE 0xffff - -#define DEVICE_WIDTH 0x160 -#define DEVICE_WIDTH__VALUE 0x0003 - -#define DEVICE_MAIN_AREA_SIZE 0x170 -#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff - -#define DEVICE_SPARE_AREA_SIZE 0x180 -#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff - -#define TWO_ROW_ADDR_CYCLES 0x190 -#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001 - -#define MULTIPLANE_ADDR_RESTRICT 0x1a0 -#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001 - -#define ECC_CORRECTION 0x1b0 -#define ECC_CORRECTION__VALUE 0x001f - -#define READ_MODE 0x1c0 -#define READ_MODE__VALUE 0x000f - -#define WRITE_MODE 0x1d0 -#define WRITE_MODE__VALUE 0x000f - -#define COPYBACK_MODE 0x1e0 -#define COPYBACK_MODE__VALUE 0x000f - -#define RDWR_EN_LO_CNT 0x1f0 -#define RDWR_EN_LO_CNT__VALUE 0x001f - -#define RDWR_EN_HI_CNT 0x200 -#define RDWR_EN_HI_CNT__VALUE 0x001f - -#define MAX_RD_DELAY 0x210 -#define MAX_RD_DELAY__VALUE 0x000f - -#define CS_SETUP_CNT 0x220 -#define CS_SETUP_CNT__VALUE 0x001f - -#define SPARE_AREA_SKIP_BYTES 0x230 -#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f - -#define SPARE_AREA_MARKER 0x240 -#define SPARE_AREA_MARKER__VALUE 0xffff - -#define DEVICES_CONNECTED 0x250 -#define DEVICES_CONNECTED__VALUE 0x0007 - -#define DIE_MASK 0x260 -#define DIE_MASK__VALUE 0x00ff - -#define FIRST_BLOCK_OF_NEXT_PLANE 0x270 -#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff - -#define WRITE_PROTECT 0x280 -#define WRITE_PROTECT__FLAG 0x0001 - -#define RE_2_RE 0x290 -#define RE_2_RE__VALUE 0x003f - -#define MANUFACTURER_ID 0x300 -#define MANUFACTURER_ID__VALUE 0x00ff - -#define DEVICE_ID 0x310 -#define DEVICE_ID__VALUE 0x00ff - -#define DEVICE_PARAM_0 0x320 -#define DEVICE_PARAM_0__VALUE 0x00ff - -#define DEVICE_PARAM_1 0x330 -#define DEVICE_PARAM_1__VALUE 0x00ff - -#define DEVICE_PARAM_2 0x340 -#define DEVICE_PARAM_2__VALUE 0x00ff - -#define LOGICAL_PAGE_DATA_SIZE 0x350 -#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff - -#define LOGICAL_PAGE_SPARE_SIZE 0x360 -#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff - -#define REVISION 0x370 -#define REVISION__VALUE 0xffff - -#define ONFI_DEVICE_FEATURES 0x380 -#define ONFI_DEVICE_FEATURES__VALUE 0x003f - -#define ONFI_OPTIONAL_COMMANDS 0x390 -#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f - -#define ONFI_TIMING_MODE 0x3a0 -#define ONFI_TIMING_MODE__VALUE 0x003f - -#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0 -#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f - -#define ONFI_DEVICE_NO_OF_LUNS 0x3c0 -#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff -#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100 - -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff - -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff - -#define FEATURES 0x3f0 -#define FEATURES__N_BANKS 0x0003 -#define FEATURES__ECC_MAX_ERR 0x003c -#define FEATURES__DMA 0x0040 -#define FEATURES__CMD_DMA 0x0080 -#define FEATURES__PARTITION 0x0100 -#define FEATURES__XDMA_SIDEBAND 0x0200 -#define FEATURES__GPREG 0x0400 -#define FEATURES__INDEX_ADDR 0x0800 - -#define TRANSFER_MODE 0x400 -#define TRANSFER_MODE__VALUE 0x0003 - -#define INTR_STATUS0 0x410 -#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS0__ECC_ERR 0x0002 -#define INTR_STATUS0__DMA_CMD_COMP 0x0004 -#define INTR_STATUS0__TIME_OUT 0x0008 -#define INTR_STATUS0__PROGRAM_FAIL 0x0010 -#define INTR_STATUS0__ERASE_FAIL 0x0020 -#define INTR_STATUS0__LOAD_COMP 0x0040 -#define INTR_STATUS0__PROGRAM_COMP 0x0080 -#define INTR_STATUS0__ERASE_COMP 0x0100 -#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS0__LOCKED_BLK 0x0400 -#define INTR_STATUS0__UNSUP_CMD 0x0800 -#define INTR_STATUS0__INT_ACT 0x1000 -#define INTR_STATUS0__RST_COMP 0x2000 -#define INTR_STATUS0__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS0__PAGE_XFER_INC 0x8000 - -#define INTR_EN0 0x420 -#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN0__ECC_ERR 0x0002 -#define INTR_EN0__DMA_CMD_COMP 0x0004 -#define INTR_EN0__TIME_OUT 0x0008 -#define INTR_EN0__PROGRAM_FAIL 0x0010 -#define INTR_EN0__ERASE_FAIL 0x0020 -#define INTR_EN0__LOAD_COMP 0x0040 -#define INTR_EN0__PROGRAM_COMP 0x0080 -#define INTR_EN0__ERASE_COMP 0x0100 -#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN0__LOCKED_BLK 0x0400 -#define INTR_EN0__UNSUP_CMD 0x0800 -#define INTR_EN0__INT_ACT 0x1000 -#define INTR_EN0__RST_COMP 0x2000 -#define INTR_EN0__PIPE_CMD_ERR 0x4000 -#define INTR_EN0__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT0 0x430 -#define PAGE_CNT0__VALUE 0x00ff - -#define ERR_PAGE_ADDR0 0x440 -#define ERR_PAGE_ADDR0__VALUE 0xffff - -#define ERR_BLOCK_ADDR0 0x450 -#define ERR_BLOCK_ADDR0__VALUE 0xffff - -#define INTR_STATUS1 0x460 -#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS1__ECC_ERR 0x0002 -#define INTR_STATUS1__DMA_CMD_COMP 0x0004 -#define INTR_STATUS1__TIME_OUT 0x0008 -#define INTR_STATUS1__PROGRAM_FAIL 0x0010 -#define INTR_STATUS1__ERASE_FAIL 0x0020 -#define INTR_STATUS1__LOAD_COMP 0x0040 -#define INTR_STATUS1__PROGRAM_COMP 0x0080 -#define INTR_STATUS1__ERASE_COMP 0x0100 -#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS1__LOCKED_BLK 0x0400 -#define INTR_STATUS1__UNSUP_CMD 0x0800 -#define INTR_STATUS1__INT_ACT 0x1000 -#define INTR_STATUS1__RST_COMP 0x2000 -#define INTR_STATUS1__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS1__PAGE_XFER_INC 0x8000 - -#define INTR_EN1 0x470 -#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN1__ECC_ERR 0x0002 -#define INTR_EN1__DMA_CMD_COMP 0x0004 -#define INTR_EN1__TIME_OUT 0x0008 -#define INTR_EN1__PROGRAM_FAIL 0x0010 -#define INTR_EN1__ERASE_FAIL 0x0020 -#define INTR_EN1__LOAD_COMP 0x0040 -#define INTR_EN1__PROGRAM_COMP 0x0080 -#define INTR_EN1__ERASE_COMP 0x0100 -#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN1__LOCKED_BLK 0x0400 -#define INTR_EN1__UNSUP_CMD 0x0800 -#define INTR_EN1__INT_ACT 0x1000 -#define INTR_EN1__RST_COMP 0x2000 -#define INTR_EN1__PIPE_CMD_ERR 0x4000 -#define INTR_EN1__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT1 0x480 -#define PAGE_CNT1__VALUE 0x00ff - -#define ERR_PAGE_ADDR1 0x490 -#define ERR_PAGE_ADDR1__VALUE 0xffff - -#define ERR_BLOCK_ADDR1 0x4a0 -#define ERR_BLOCK_ADDR1__VALUE 0xffff - -#define INTR_STATUS2 0x4b0 -#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS2__ECC_ERR 0x0002 -#define INTR_STATUS2__DMA_CMD_COMP 0x0004 -#define INTR_STATUS2__TIME_OUT 0x0008 -#define INTR_STATUS2__PROGRAM_FAIL 0x0010 -#define INTR_STATUS2__ERASE_FAIL 0x0020 -#define INTR_STATUS2__LOAD_COMP 0x0040 -#define INTR_STATUS2__PROGRAM_COMP 0x0080 -#define INTR_STATUS2__ERASE_COMP 0x0100 -#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS2__LOCKED_BLK 0x0400 -#define INTR_STATUS2__UNSUP_CMD 0x0800 -#define INTR_STATUS2__INT_ACT 0x1000 -#define INTR_STATUS2__RST_COMP 0x2000 -#define INTR_STATUS2__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS2__PAGE_XFER_INC 0x8000 - -#define INTR_EN2 0x4c0 -#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN2__ECC_ERR 0x0002 -#define INTR_EN2__DMA_CMD_COMP 0x0004 -#define INTR_EN2__TIME_OUT 0x0008 -#define INTR_EN2__PROGRAM_FAIL 0x0010 -#define INTR_EN2__ERASE_FAIL 0x0020 -#define INTR_EN2__LOAD_COMP 0x0040 -#define INTR_EN2__PROGRAM_COMP 0x0080 -#define INTR_EN2__ERASE_COMP 0x0100 -#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN2__LOCKED_BLK 0x0400 -#define INTR_EN2__UNSUP_CMD 0x0800 -#define INTR_EN2__INT_ACT 0x1000 -#define INTR_EN2__RST_COMP 0x2000 -#define INTR_EN2__PIPE_CMD_ERR 0x4000 -#define INTR_EN2__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT2 0x4d0 -#define PAGE_CNT2__VALUE 0x00ff - -#define ERR_PAGE_ADDR2 0x4e0 -#define ERR_PAGE_ADDR2__VALUE 0xffff - -#define ERR_BLOCK_ADDR2 0x4f0 -#define ERR_BLOCK_ADDR2__VALUE 0xffff - -#define INTR_STATUS3 0x500 -#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS3__ECC_ERR 0x0002 -#define INTR_STATUS3__DMA_CMD_COMP 0x0004 -#define INTR_STATUS3__TIME_OUT 0x0008 -#define INTR_STATUS3__PROGRAM_FAIL 0x0010 -#define INTR_STATUS3__ERASE_FAIL 0x0020 -#define INTR_STATUS3__LOAD_COMP 0x0040 -#define INTR_STATUS3__PROGRAM_COMP 0x0080 -#define INTR_STATUS3__ERASE_COMP 0x0100 -#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS3__LOCKED_BLK 0x0400 -#define INTR_STATUS3__UNSUP_CMD 0x0800 -#define INTR_STATUS3__INT_ACT 0x1000 -#define INTR_STATUS3__RST_COMP 0x2000 -#define INTR_STATUS3__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS3__PAGE_XFER_INC 0x8000 - -#define INTR_EN3 0x510 -#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN3__ECC_ERR 0x0002 -#define INTR_EN3__DMA_CMD_COMP 0x0004 -#define INTR_EN3__TIME_OUT 0x0008 -#define INTR_EN3__PROGRAM_FAIL 0x0010 -#define INTR_EN3__ERASE_FAIL 0x0020 -#define INTR_EN3__LOAD_COMP 0x0040 -#define INTR_EN3__PROGRAM_COMP 0x0080 -#define INTR_EN3__ERASE_COMP 0x0100 -#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN3__LOCKED_BLK 0x0400 -#define INTR_EN3__UNSUP_CMD 0x0800 -#define INTR_EN3__INT_ACT 0x1000 -#define INTR_EN3__RST_COMP 0x2000 -#define INTR_EN3__PIPE_CMD_ERR 0x4000 -#define INTR_EN3__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT3 0x520 -#define PAGE_CNT3__VALUE 0x00ff - -#define ERR_PAGE_ADDR3 0x530 -#define ERR_PAGE_ADDR3__VALUE 0xffff - -#define ERR_BLOCK_ADDR3 0x540 -#define ERR_BLOCK_ADDR3__VALUE 0xffff - -#define DATA_INTR 0x550 -#define DATA_INTR__WRITE_SPACE_AV 0x0001 -#define DATA_INTR__READ_DATA_AV 0x0002 - -#define DATA_INTR_EN 0x560 -#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001 -#define DATA_INTR_EN__READ_DATA_AV 0x0002 - -#define GPREG_0 0x570 -#define GPREG_0__VALUE 0xffff - -#define GPREG_1 0x580 -#define GPREG_1__VALUE 0xffff - -#define GPREG_2 0x590 -#define GPREG_2__VALUE 0xffff - -#define GPREG_3 0x5a0 -#define GPREG_3__VALUE 0xffff - -#define ECC_THRESHOLD 0x600 -#define ECC_THRESHOLD__VALUE 0x03ff - -#define ECC_ERROR_BLOCK_ADDRESS 0x610 -#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff - -#define ECC_ERROR_PAGE_ADDRESS 0x620 -#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff -#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000 - -#define ECC_ERROR_ADDRESS 0x630 -#define ECC_ERROR_ADDRESS__OFFSET 0x0fff -#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000 - -#define ERR_CORRECTION_INFO 0x640 -#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff -#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00 -#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000 -#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000 - -#define DMA_ENABLE 0x700 -#define DMA_ENABLE__FLAG 0x0001 - -#define IGNORE_ECC_DONE 0x710 -#define IGNORE_ECC_DONE__FLAG 0x0001 - -#define DMA_INTR 0x720 -#define DMA_INTR__TARGET_ERROR 0x0001 -#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002 -#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004 -#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008 -#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 - -#define DMA_INTR_EN 0x730 -#define DMA_INTR_EN__TARGET_ERROR 0x0001 -#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002 -#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004 -#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008 -#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020 - -#define TARGET_ERR_ADDR_LO 0x740 -#define TARGET_ERR_ADDR_LO__VALUE 0xffff - -#define TARGET_ERR_ADDR_HI 0x750 -#define TARGET_ERR_ADDR_HI__VALUE 0xffff - -#define CHNL_ACTIVE 0x760 -#define CHNL_ACTIVE__CHANNEL0 0x0001 -#define CHNL_ACTIVE__CHANNEL1 0x0002 -#define CHNL_ACTIVE__CHANNEL2 0x0004 -#define CHNL_ACTIVE__CHANNEL3 0x0008 - -#define ACTIVE_SRC_ID 0x800 -#define ACTIVE_SRC_ID__VALUE 0x00ff - -#define PTN_INTR 0x810 -#define PTN_INTR__CONFIG_ERROR 0x0001 -#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002 -#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004 -#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008 -#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010 -#define PTN_INTR__REG_ACCESS_ERROR 0x0020 - -#define PTN_INTR_EN 0x820 -#define PTN_INTR_EN__CONFIG_ERROR 0x0001 -#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002 -#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004 -#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008 -#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 -#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 - -#define PERM_SRC_ID_0 0x830 -#define PERM_SRC_ID_0__SRCID 0x00ff -#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_0__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_0__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_0 0x840 -#define MIN_BLK_ADDR_0__VALUE 0xffff - -#define MAX_BLK_ADDR_0 0x850 -#define MAX_BLK_ADDR_0__VALUE 0xffff - -#define MIN_MAX_BANK_0 0x860 -#define MIN_MAX_BANK_0__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_0__MAX_VALUE 0x000c - -#define PERM_SRC_ID_1 0x870 -#define PERM_SRC_ID_1__SRCID 0x00ff -#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_1__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_1__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_1 0x880 -#define MIN_BLK_ADDR_1__VALUE 0xffff - -#define MAX_BLK_ADDR_1 0x890 -#define MAX_BLK_ADDR_1__VALUE 0xffff - -#define MIN_MAX_BANK_1 0x8a0 -#define MIN_MAX_BANK_1__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_1__MAX_VALUE 0x000c - -#define PERM_SRC_ID_2 0x8b0 -#define PERM_SRC_ID_2__SRCID 0x00ff -#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_2__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_2__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_2 0x8c0 -#define MIN_BLK_ADDR_2__VALUE 0xffff - -#define MAX_BLK_ADDR_2 0x8d0 -#define MAX_BLK_ADDR_2__VALUE 0xffff - -#define MIN_MAX_BANK_2 0x8e0 -#define MIN_MAX_BANK_2__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_2__MAX_VALUE 0x000c - -#define PERM_SRC_ID_3 0x8f0 -#define PERM_SRC_ID_3__SRCID 0x00ff -#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_3__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_3__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_3 0x900 -#define MIN_BLK_ADDR_3__VALUE 0xffff - -#define MAX_BLK_ADDR_3 0x910 -#define MAX_BLK_ADDR_3__VALUE 0xffff - -#define MIN_MAX_BANK_3 0x920 -#define MIN_MAX_BANK_3__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_3__MAX_VALUE 0x000c - -#define PERM_SRC_ID_4 0x930 -#define PERM_SRC_ID_4__SRCID 0x00ff -#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_4__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_4__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_4 0x940 -#define MIN_BLK_ADDR_4__VALUE 0xffff - -#define MAX_BLK_ADDR_4 0x950 -#define MAX_BLK_ADDR_4__VALUE 0xffff - -#define MIN_MAX_BANK_4 0x960 -#define MIN_MAX_BANK_4__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_4__MAX_VALUE 0x000c - -#define PERM_SRC_ID_5 0x970 -#define PERM_SRC_ID_5__SRCID 0x00ff -#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_5__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_5__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_5 0x980 -#define MIN_BLK_ADDR_5__VALUE 0xffff - -#define MAX_BLK_ADDR_5 0x990 -#define MAX_BLK_ADDR_5__VALUE 0xffff - -#define MIN_MAX_BANK_5 0x9a0 -#define MIN_MAX_BANK_5__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_5__MAX_VALUE 0x000c - -#define PERM_SRC_ID_6 0x9b0 -#define PERM_SRC_ID_6__SRCID 0x00ff -#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_6__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_6__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_6 0x9c0 -#define MIN_BLK_ADDR_6__VALUE 0xffff - -#define MAX_BLK_ADDR_6 0x9d0 -#define MAX_BLK_ADDR_6__VALUE 0xffff - -#define MIN_MAX_BANK_6 0x9e0 -#define MIN_MAX_BANK_6__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_6__MAX_VALUE 0x000c - -#define PERM_SRC_ID_7 0x9f0 -#define PERM_SRC_ID_7__SRCID 0x00ff -#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_7__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_7__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_7 0xa00 -#define MIN_BLK_ADDR_7__VALUE 0xffff - -#define MAX_BLK_ADDR_7 0xa10 -#define MAX_BLK_ADDR_7__VALUE 0xffff - -#define MIN_MAX_BANK_7 0xa20 -#define MIN_MAX_BANK_7__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_7__MAX_VALUE 0x000c diff --git a/drivers/block/spectra/spectraswconfig.h b/drivers/block/spectra/spectraswconfig.h deleted file mode 100644 index 557c091953d7..000000000000 --- a/drivers/block/spectra/spectraswconfig.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _SPECTRASWCONFIG_ -#define _SPECTRASWCONFIG_ - -/* NAND driver version */ -#define GLOB_VERSION "driver version 20100311" - - -/***** Common Parameters *****/ -#define RETRY_TIMES 3 - -#define READ_BADBLOCK_INFO 1 -#define READBACK_VERIFY 0 -#define AUTO_FORMAT_FLASH 0 - -/***** Cache Parameters *****/ -#define CACHE_ITEM_NUM 128 -#define BLK_NUM_FOR_L2_CACHE 16 - -/***** Block Table Parameters *****/ -#define BLOCK_TABLE_INDEX 0 - -/***** Wear Leveling Parameters *****/ -#define WEAR_LEVELING_GATE 0x10 -#define WEAR_LEVELING_BLOCK_NUM 10 - -#define DEBUG_BNDRY 0 - -/***** Product Feature Support *****/ -#define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) -#define FLASH_NAND defined(CONFIG_MRST_NAND_HW) -#define FLASH_MTD defined(CONFIG_MRST_NAND_MTD) -#define CMD_DMA defined(CONFIG_MRST_NAND_HW_DMA) - -#define SPECTRA_PARTITION_ID 0 - -/* Enable this macro if the number of flash blocks is larger than 16K. */ -#define SUPPORT_LARGE_BLOCKNUM 1 - -/**** Block Table and Reserved Block Parameters *****/ -#define SPECTRA_START_BLOCK 3 -//#define NUM_FREE_BLOCKS_GATE 30 -#define NUM_FREE_BLOCKS_GATE 60 - -/**** Hardware Parameters ****/ -#define GLOB_HWCTL_REG_BASE 0xFFA40000 -#define GLOB_HWCTL_REG_SIZE 4096 - -#define GLOB_HWCTL_MEM_BASE 0xFFA48000 -#define GLOB_HWCTL_MEM_SIZE 4096 - -/* KBV - Updated to LNW scratch register address */ -#define SCRATCH_REG_ADDR 0xFF108018 -#define SCRATCH_REG_SIZE 64 - -#define GLOB_HWCTL_DEFAULT_BLKS 2048 - -#define SUPPORT_15BITECC 1 -#define SUPPORT_8BITECC 1 - -#define ONFI_BLOOM_TIME 0 -#define MODE5_WORKAROUND 1 - -#endif /*_SPECTRASWCONFIG_*/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7696a664f8a5..79cf5f720952 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -97,6 +97,8 @@ source "drivers/staging/octeon/Kconfig" source "drivers/staging/serqt_usb2/Kconfig" +source "drivers/staging/spectra/Kconfig" + source "drivers/staging/quatech_usb2/Kconfig" source "drivers/staging/vt6655/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ea2e70e2fed4..401049ef01d1 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192SU) += rtl8192su/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ +obj-$(CONFIG_MRST_NAND) += spectra/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_DREAM) += dream/ obj-$(CONFIG_POHMELFS) += pohmelfs/ diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig new file mode 100644 index 000000000000..4bed96f68837 --- /dev/null +++ b/drivers/staging/spectra/Kconfig @@ -0,0 +1,40 @@ + +menuconfig MRST_NAND + tristate "Moorestown NAND Flash controller" + depends on BLOCK + default n + ---help--- + Enable the driver for the NAND Flash controller in Intel Moorestown + Platform + +choice + prompt "Compile for" + depends on MRST_NAND + default MRST_NAND_HW + +config MRST_NAND_HW + bool "Actual hardware mode" + help + Driver communicates with the actual hardware's register interface. + in DMA mode. + +config MRST_NAND_MTD + bool "Linux MTD mode" + depends on MTD + help + Driver communicates with the kernel MTD subsystem instead of its own + built-in hardware driver. + +config MRST_NAND_EMU + bool "RAM emulator testing" + help + Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer. + +endchoice + +config MRST_NAND_HW_DMA + bool + default n + depends on MRST_NAND_HW + help + Use DMA for native hardware interface. diff --git a/drivers/staging/spectra/Makefile b/drivers/staging/spectra/Makefile new file mode 100644 index 000000000000..2a9490385339 --- /dev/null +++ b/drivers/staging/spectra/Makefile @@ -0,0 +1,11 @@ +# +# Makefile of Intel Moorestown NAND controller driver +# + +obj-$(CONFIG_MRST_NAND) += spectra.o +spectra-y := ffsport.o flash.o lld.o +spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o +spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o +spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o +spectra-$(CONFIG_MRST_NAND_MTD) += lld_mtd.o + diff --git a/drivers/staging/spectra/README b/drivers/staging/spectra/README new file mode 100644 index 000000000000..ecba559b899c --- /dev/null +++ b/drivers/staging/spectra/README @@ -0,0 +1,29 @@ +This is a driver for NAND controller of Intel Moorestown platform. + +This driver is a standalone linux block device driver, it acts as if it's a normal hard disk. +It includes three layer: + block layer interface - file ffsport.c + Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on) + Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access) + +This driver can be build as modules or build-in. + +Dependency: +This driver has dependency on IA Firmware of Intel Moorestown platform. +It need the IA Firmware to create the block table for the first time. +And to validate this driver code without IA Firmware, you can change the +macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the +driver will erase the whole nand flash and create a new block table. + +TODO: + - Enable Command DMA feature support + - lower the memory footprint + - Remove most of the unnecessary global variables + - Change all the upcase variable / functions name to lowercase + - Some other misc bugs + +Please send patches to: + Greg Kroah-Hartman + +And Cc to: Gao Yunpeng + diff --git a/drivers/staging/spectra/ffsdefs.h b/drivers/staging/spectra/ffsdefs.h new file mode 100644 index 000000000000..a9e9cd233d2a --- /dev/null +++ b/drivers/staging/spectra/ffsdefs.h @@ -0,0 +1,58 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FFSDEFS_ +#define _FFSDEFS_ + +#define CLEAR 0 /*use this to clear a field instead of "fail"*/ +#define SET 1 /*use this to set a field instead of "pass"*/ +#define FAIL 1 /*failed flag*/ +#define PASS 0 /*success flag*/ +#define ERR -1 /*error flag*/ + +#define ERASE_CMD 10 +#define WRITE_MAIN_CMD 11 +#define READ_MAIN_CMD 12 +#define WRITE_SPARE_CMD 13 +#define READ_SPARE_CMD 14 +#define WRITE_MAIN_SPARE_CMD 15 +#define READ_MAIN_SPARE_CMD 16 +#define MEMCOPY_CMD 17 +#define DUMMY_CMD 99 + +#define EVENT_PASS 0x00 +#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01 +#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02 +#define EVENT_TIME_OUT 0x03 +#define EVENT_PROGRAM_FAILURE 0x04 +#define EVENT_ERASE_FAILURE 0x05 +#define EVENT_MEMCOPY_FAILURE 0x06 +#define EVENT_FAIL 0x07 + +#define EVENT_NONE 0x22 +#define EVENT_DMA_CMD_COMP 0x77 +#define EVENT_ECC_TRANSACTION_DONE 0x88 +#define EVENT_DMA_CMD_FAIL 0x99 + +#define CMD_PASS 0 +#define CMD_FAIL 1 +#define CMD_ABORT 2 +#define CMD_NOT_DONE 3 + +#endif /* _FFSDEFS_ */ diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c new file mode 100644 index 000000000000..3c3565d40545 --- /dev/null +++ b/drivers/staging/spectra/ffsport.c @@ -0,0 +1,827 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "ffsport.h" +#include "flash.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/**** Helper functions used for Div, Remainder operation on u64 ****/ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_Calc_Used_Bits +* Inputs: Power of 2 number +* Outputs: Number of Used Bits +* 0, if the argument is 0 +* Description: Calculate the number of bits used by a given power of 2 number +* Number can be upto 32 bit +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_Calc_Used_Bits(u32 n) +{ + int tot_bits = 0; + + if (n >= 1 << 16) { + n >>= 16; + tot_bits += 16; + } + + if (n >= 1 << 8) { + n >>= 8; + tot_bits += 8; + } + + if (n >= 1 << 4) { + n >>= 4; + tot_bits += 4; + } + + if (n >= 1 << 2) { + n >>= 2; + tot_bits += 2; + } + + if (n >= 1 << 1) + tot_bits += 1; + + return ((n == 0) ? (0) : tot_bits); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_u64_Div +* Inputs: Number of u64 +* A power of 2 number as Division +* Outputs: Quotient of the Divisor operation +* Description: It divides the address by divisor by using bit shift operation +* (essentially without explicitely using "/"). +* Divisor is a power of 2 number and Divided is of u64 +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u64 GLOB_u64_Div(u64 addr, u32 divisor) +{ + return (u64)(addr >> GLOB_Calc_Used_Bits(divisor)); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_u64_Remainder +* Inputs: Number of u64 +* Divisor Type (1 -PageAddress, 2- BlockAddress) +* Outputs: Remainder of the Division operation +* Description: It calculates the remainder of a number (of u64) by +* divisor(power of 2 number ) by using bit shifting and multiply +* operation(essentially without explicitely using "/"). +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) +{ + u64 result = 0; + + if (divisor_type == 1) { /* Remainder -- Page */ + result = (addr >> DeviceInfo.nBitsInPageDataSize); + result = result * DeviceInfo.wPageDataSize; + } else if (divisor_type == 2) { /* Remainder -- Block */ + result = (addr >> DeviceInfo.nBitsInBlockDataSize); + result = result * DeviceInfo.wBlockDataSize; + } + + result = addr - result; + + return result; +} + +#define NUM_DEVICES 1 +#define PARTITIONS 8 + +#define GLOB_SBD_NAME "nd" +#define GLOB_SBD_IRQ_NUM (29) +#define GLOB_VERSION "driver version 20091110" + +#define GLOB_SBD_IOCTL_GC (0x7701) +#define GLOB_SBD_IOCTL_WL (0x7702) +#define GLOB_SBD_IOCTL_FORMAT (0x7703) +#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704) +#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705) +#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706) +#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707) +#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708) +#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709) +#define GLOB_SBD_IOCTL_READ_DATA (0x770A) + +static int reserved_mb = 0; +module_param(reserved_mb, int, 0); +MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)"); + +int nand_debug_level; +module_param(nand_debug_level, int, 0644); +MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3"); + +MODULE_LICENSE("GPL"); + +struct spectra_nand_dev { + struct pci_dev *dev; + u64 size; + u16 users; + spinlock_t qlock; + void __iomem *ioaddr; /* Mapped address */ + struct request_queue *queue; + struct task_struct *thread; + struct gendisk *gd; + u8 *tmp_buf; +}; + + +static int GLOB_SBD_majornum; + +static char *GLOB_version = GLOB_VERSION; + +static struct spectra_nand_dev nand_device[NUM_DEVICES]; + +static struct mutex spectra_lock; + +static int res_blks_os = 1; + +struct spectra_indentfy_dev_tag IdentifyDeviceData; + +static int force_flush_cache(void) +{ + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (ERR == GLOB_FTL_Flush_Cache()) { + printk(KERN_ERR "Fail to Flush FTL Cache!\n"); + return -EFAULT; + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; +} + +struct ioctl_rw_page_info { + u8 *data; + unsigned int page; +}; + +static int ioctl_read_page_data(unsigned long arg) +{ + u8 *buf; + struct ioctl_rw_page_info info; + int result = PASS; + + if (copy_from_user(&info, (void __user *)arg, sizeof(info))) + return -EFAULT; + + buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!buf) { + printk(KERN_ERR "ioctl_read_page_data: " + "failed to allocate memory\n"); + return -ENOMEM; + } + + mutex_lock(&spectra_lock); + result = GLOB_FTL_Page_Read(buf, + (u64)info.page * IdentifyDeviceData.PageDataSize); + mutex_unlock(&spectra_lock); + + if (copy_to_user((void __user *)info.data, buf, + IdentifyDeviceData.PageDataSize)) { + printk(KERN_ERR "ioctl_read_page_data: " + "failed to copy user data\n"); + kfree(buf); + return -EFAULT; + } + + kfree(buf); + return result; +} + +static int ioctl_write_page_data(unsigned long arg) +{ + u8 *buf; + struct ioctl_rw_page_info info; + int result = PASS; + + if (copy_from_user(&info, (void __user *)arg, sizeof(info))) + return -EFAULT; + + buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!buf) { + printk(KERN_ERR "ioctl_write_page_data: " + "failed to allocate memory\n"); + return -ENOMEM; + } + + if (copy_from_user(buf, (void __user *)info.data, + IdentifyDeviceData.PageDataSize)) { + printk(KERN_ERR "ioctl_write_page_data: " + "failed to copy user data\n"); + kfree(buf); + return -EFAULT; + } + + mutex_lock(&spectra_lock); + result = GLOB_FTL_Page_Write(buf, + (u64)info.page * IdentifyDeviceData.PageDataSize); + mutex_unlock(&spectra_lock); + + kfree(buf); + return result; +} + +/* Return how many blocks should be reserved for bad block replacement */ +static int get_res_blk_num_bad_blk(void) +{ + return IdentifyDeviceData.wDataBlockNum / 10; +} + +/* Return how many blocks should be reserved for OS image */ +static int get_res_blk_num_os(void) +{ + u32 res_blks, blk_size; + + blk_size = IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock; + + res_blks = (reserved_mb * 1024 * 1024) / blk_size; + + if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum)) + res_blks = 1; /* Reserved 1 block for block table */ + + return res_blks; +} + +static void SBD_prepare_flush(struct request_queue *q, struct request *rq) +{ + rq->cmd_type = REQ_TYPE_LINUX_BLOCK; + /* rq->timeout = 5 * HZ; */ + rq->cmd[0] = REQ_LB_OP_FLUSH; +} + +/* Transfer a full request. */ +static int do_transfer(struct spectra_nand_dev *tr, struct request *req) +{ + u64 start_addr, addr; + u32 logical_start_sect, hd_start_sect; + u32 nsect, hd_sects; + u32 rsect, tsect = 0; + char *buf; + u32 ratio = IdentifyDeviceData.PageDataSize >> 9; + + start_addr = (u64)(blk_rq_pos(req)) << 9; + /* Add a big enough offset to prevent the OS Image from + * being accessed or damaged by file system */ + start_addr += IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock * + res_blks_os; + + if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && + req->cmd[0] == REQ_LB_OP_FLUSH) { + if (force_flush_cache()) /* Fail to flush cache */ + return -EIO; + else + return 0; + } + + if (!blk_fs_request(req)) + return -EIO; + + if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) { + printk(KERN_ERR "Spectra error: request over the NAND " + "capacity!sector %d, current_nr_sectors %d, " + "while capacity is %d\n", + (int)blk_rq_pos(req), + blk_rq_cur_sectors(req), + (int)get_capacity(tr->gd)); + return -EIO; + } + + logical_start_sect = start_addr >> 9; + hd_start_sect = logical_start_sect / ratio; + rsect = logical_start_sect - hd_start_sect * ratio; + + addr = (u64)hd_start_sect * ratio * 512; + buf = req->buffer; + nsect = blk_rq_cur_sectors(req); + + if (rsect) + tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect; + + switch (rq_data_dir(req)) { + case READ: + /* Read the first NAND page */ + if (rsect) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9); + addr += IdentifyDeviceData.PageDataSize; + buf += tsect << 9; + nsect -= tsect; + } + + /* Read the other NAND pages */ + for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { + if (GLOB_FTL_Page_Read(buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += IdentifyDeviceData.PageDataSize; + } + + /* Read the last NAND pages */ + if (nsect % ratio) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9); + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; + + case WRITE: + /* Write the first NAND page */ + if (rsect) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9); + if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += tsect << 9; + nsect -= tsect; + } + + /* Write the other NAND pages */ + for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { + if (GLOB_FTL_Page_Write(buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + addr += IdentifyDeviceData.PageDataSize; + buf += IdentifyDeviceData.PageDataSize; + } + + /* Write the last NAND pages */ + if (nsect % ratio) { + if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9); + if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { + printk(KERN_ERR "Error in %s, Line %d\n", + __FILE__, __LINE__); + return -EIO; + } + } +#if CMD_DMA + if (glob_ftl_execute_cmds()) + return -EIO; + else + return 0; +#endif + return 0; + + default: + printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); + return -EIO; + } +} + +/* This function is copied from drivers/mtd/mtd_blkdevs.c */ +static int spectra_trans_thread(void *arg) +{ + struct spectra_nand_dev *tr = arg; + struct request_queue *rq = tr->queue; + struct request *req = NULL; + + /* we might get involved when memory gets low, so use PF_MEMALLOC */ + current->flags |= PF_MEMALLOC; + + spin_lock_irq(rq->queue_lock); + while (!kthread_should_stop()) { + int res; + + if (!req) { + req = blk_fetch_request(rq); + if (!req) { + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(rq->queue_lock); + schedule(); + spin_lock_irq(rq->queue_lock); + continue; + } + } + + spin_unlock_irq(rq->queue_lock); + + mutex_lock(&spectra_lock); + res = do_transfer(tr, req); + mutex_unlock(&spectra_lock); + + spin_lock_irq(rq->queue_lock); + + if (!__blk_end_request_cur(req, res)) + req = NULL; + } + + if (req) + __blk_end_request_all(req, -EIO); + + spin_unlock_irq(rq->queue_lock); + + return 0; +} + + +/* Request function that "handles clustering". */ +static void GLOB_SBD_request(struct request_queue *rq) +{ + struct spectra_nand_dev *pdev = rq->queuedata; + wake_up_process(pdev->thread); +} + +static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode) + +{ + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + return 0; +} + +static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode) +{ + int ret; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + mutex_lock(&spectra_lock); + ret = force_flush_cache(); + mutex_unlock(&spectra_lock); + + return 0; +} + +static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + geo->heads = 4; + geo->sectors = 16; + geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); + + nand_dbg_print(NAND_DBG_DEBUG, + "heads: %d, sectors: %d, cylinders: %d\n", + geo->heads, geo->sectors, geo->cylinders); + + return 0; +} + +int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + switch (cmd) { + case GLOB_SBD_IOCTL_GC: + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra IOCTL: Garbage Collection " + "being performed\n"); + if (PASS != GLOB_FTL_Garbage_Collection()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_WL: + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra IOCTL: Static Wear Leveling " + "being performed\n"); + if (PASS != GLOB_FTL_Wear_Leveling()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_FORMAT: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format " + "being performed\n"); + if (PASS != GLOB_FTL_Flash_Format()) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_FLUSH_CACHE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush " + "being performed\n"); + mutex_lock(&spectra_lock); + ret = force_flush_cache(); + mutex_unlock(&spectra_lock); + return ret; + + case GLOB_SBD_IOCTL_COPY_BLK_TABLE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Copy block table\n"); + if (copy_to_user((void __user *)arg, + get_blk_table_start_addr(), + get_blk_table_len())) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Copy wear leveling table\n"); + if (copy_to_user((void __user *)arg, + get_wear_leveling_table_start_addr(), + get_wear_leveling_table_len())) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_GET_NAND_INFO: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Get NAND info\n"); + if (copy_to_user((void __user *)arg, &IdentifyDeviceData, + sizeof(IdentifyDeviceData))) + return -EFAULT; + return 0; + + case GLOB_SBD_IOCTL_WRITE_DATA: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Write one page data\n"); + return ioctl_write_page_data(arg); + + case GLOB_SBD_IOCTL_READ_DATA: + nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " + "Read one page data\n"); + return ioctl_read_page_data(arg); + } + + return -ENOTTY; +} + +static struct block_device_operations GLOB_SBD_ops = { + .owner = THIS_MODULE, + .open = GLOB_SBD_open, + .release = GLOB_SBD_release, + .locked_ioctl = GLOB_SBD_ioctl, + .getgeo = GLOB_SBD_getgeo, +}; + +static int SBD_setup_device(struct spectra_nand_dev *dev, int which) +{ + int res_blks; + u32 sects; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + memset(dev, 0, sizeof(struct spectra_nand_dev)); + + nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks " + "for OS image, %d blocks for bad block replacement.\n", + get_res_blk_num_os(), + get_res_blk_num_bad_blk()); + + res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os(); + + dev->size = (u64)IdentifyDeviceData.PageDataSize * + IdentifyDeviceData.PagesPerBlock * + (IdentifyDeviceData.wDataBlockNum - res_blks); + + res_blks_os = get_res_blk_num_os(); + + spin_lock_init(&dev->qlock); + + dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!dev->tmp_buf) { + printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n", + __FILE__, __LINE__); + goto out_vfree; + } + + dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock); + if (dev->queue == NULL) { + printk(KERN_ERR + "Spectra: Request queue could not be initialized." + " Aborting\n "); + goto out_vfree; + } + dev->queue->queuedata = dev; + + /* As Linux block layer doens't support >4KB hardware sector, */ + /* Here we force report 512 byte hardware sector size to Kernel */ + blk_queue_logical_block_size(dev->queue, 512); + + blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH, + SBD_prepare_flush); + + dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd"); + if (IS_ERR(dev->thread)) { + blk_cleanup_queue(dev->queue); + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + return PTR_ERR(dev->thread); + } + + dev->gd = alloc_disk(PARTITIONS); + if (!dev->gd) { + printk(KERN_ERR + "Spectra: Could not allocate disk. Aborting \n "); + goto out_vfree; + } + dev->gd->major = GLOB_SBD_majornum; + dev->gd->first_minor = which * PARTITIONS; + dev->gd->fops = &GLOB_SBD_ops; + dev->gd->queue = dev->queue; + dev->gd->private_data = dev; + snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a'); + + sects = dev->size >> 9; + nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects); + set_capacity(dev->gd, sects); + + add_disk(dev->gd); + + return 0; +out_vfree: + return -ENOMEM; +} + +/* +static ssize_t show_nand_block_num(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.wDataBlockNum); +} + +static ssize_t show_nand_pages_per_block(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.PagesPerBlock); +} + +static ssize_t show_nand_page_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + (int)IdentifyDeviceData.PageDataSize); +} + +static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL); +static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL); +static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL); + +static void create_sysfs_entry(struct device *dev) +{ + if (device_create_file(dev, &dev_attr_nand_block_num)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_block_num.\n"); + if (device_create_file(dev, &dev_attr_nand_pages_per_block)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_pages_per_block.\n"); + if (device_create_file(dev, &dev_attr_nand_page_size)) + printk(KERN_ERR "Spectra: " + "failed to create sysfs entry nand_page_size.\n"); +} +*/ + +static int GLOB_SBD_init(void) +{ + int i; + + /* Set debug output level (0~3) here. 3 is most verbose */ + printk(KERN_ALERT "Spectra: %s\n", GLOB_version); + + mutex_init(&spectra_lock); + + GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME); + if (GLOB_SBD_majornum <= 0) { + printk(KERN_ERR "Unable to get the major %d for Spectra", + GLOB_SBD_majornum); + return -EBUSY; + } + + if (PASS != GLOB_FTL_Flash_Init()) { + printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. " + "Aborting\n"); + goto out_flash_register; + } + + /* create_sysfs_entry(&dev->dev); */ + + if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) { + printk(KERN_ERR "Spectra: Unable to Read Flash Device. " + "Aborting\n"); + goto out_flash_register; + } else { + nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: " + "Num blocks=%d, pagesperblock=%d, " + "pagedatasize=%d, ECCBytesPerSector=%d\n", + (int)IdentifyDeviceData.NumBlocks, + (int)IdentifyDeviceData.PagesPerBlock, + (int)IdentifyDeviceData.PageDataSize, + (int)IdentifyDeviceData.wECCBytesPerSector); + } + + printk(KERN_ALERT "Spectra: searching block table, please wait ...\n"); + if (GLOB_FTL_Init() != PASS) { + printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. " + "Aborting\n"); + goto out_ftl_flash_register; + } + printk(KERN_ALERT "Spectra: block table has been found.\n"); + + for (i = 0; i < NUM_DEVICES; i++) + if (SBD_setup_device(&nand_device[i], i) == -ENOMEM) + goto out_ftl_flash_register; + + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra: module loaded with major number %d\n", + GLOB_SBD_majornum); + + return 0; + +out_ftl_flash_register: + GLOB_FTL_Cache_Release(); +out_flash_register: + GLOB_FTL_Flash_Release(); + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + printk(KERN_ERR "Spectra: Module load failed.\n"); + + return -ENOMEM; +} + +static void __exit GLOB_SBD_exit(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < NUM_DEVICES; i++) { + struct spectra_nand_dev *dev = &nand_device[i]; + if (dev->gd) { + del_gendisk(dev->gd); + put_disk(dev->gd); + } + if (dev->queue) + blk_cleanup_queue(dev->queue); + kfree(dev->tmp_buf); + } + + unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); + + mutex_lock(&spectra_lock); + force_flush_cache(); + mutex_unlock(&spectra_lock); + + GLOB_FTL_Cache_Release(); + + GLOB_FTL_Flash_Release(); + + nand_dbg_print(NAND_DBG_DEBUG, + "Spectra FTL module (major number %d) unloaded.\n", + GLOB_SBD_majornum); +} + +module_init(GLOB_SBD_init); +module_exit(GLOB_SBD_exit); diff --git a/drivers/staging/spectra/ffsport.h b/drivers/staging/spectra/ffsport.h new file mode 100644 index 000000000000..6c5d90c53430 --- /dev/null +++ b/drivers/staging/spectra/ffsport.h @@ -0,0 +1,84 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FFSPORT_ +#define _FFSPORT_ + +#include "ffsdefs.h" + +#if defined __GNUC__ +#define PACKED +#define PACKED_GNU __attribute__ ((packed)) +#define UNALIGNED +#endif + +#include +#include /* for strcpy(), stricmp(), etc */ +#include /* for kmalloc(), kfree() */ +#include +#include +#include +#include + +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include +#include +#include +#include "flash.h" + +#define VERBOSE 1 + +#define NAND_DBG_WARN 1 +#define NAND_DBG_DEBUG 2 +#define NAND_DBG_TRACE 3 + +extern int nand_debug_level; + +#ifdef VERBOSE +#define nand_dbg_print(level, args...) \ + do { \ + if (level <= nand_debug_level) \ + printk(KERN_ALERT args); \ + } while (0) +#else +#define nand_dbg_print(level, args...) +#endif + +#ifdef SUPPORT_BIG_ENDIAN +#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \ + (u16)((u16)(w) >> 8)) + +#define INVERTUINT32(dw) (((u32)(dw) << 24) | \ + (((u32)(dw) << 8) & 0x00ff0000) | \ + (((u32)(dw) >> 8) & 0x0000ff00) | \ + ((u32)(dw) >> 24)) +#else +#define INVERTUINT16(w) w +#define INVERTUINT32(dw) dw +#endif + +extern int GLOB_Calc_Used_Bits(u32 n); +extern u64 GLOB_u64_Div(u64 addr, u32 divisor); +extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type); + +#endif /* _FFSPORT_ */ diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c new file mode 100644 index 000000000000..134aa5166a8d --- /dev/null +++ b/drivers/staging/spectra/flash.c @@ -0,0 +1,4731 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include "flash.h" +#include "ffsdefs.h" +#include "lld.h" +#include "lld_nand.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize)) +#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \ + DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize)) + +#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ + BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK)) + +#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK)) + +#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ + BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK)) + +#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK)) + +#if DEBUG_BNDRY +void debug_boundary_lineno_error(int chnl, int limit, int no, + int lineno, char *filename) +{ + if (chnl >= limit) + printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, " + "at %s:%d. Other info:%d. Aborting...\n", + chnl, limit, filename, lineno, no); +} +/* static int globalmemsize; */ +#endif + +static u16 FTL_Cache_If_Hit(u64 dwPageAddr); +static int FTL_Cache_Read(u64 dwPageAddr); +static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr, + u16 cache_blk); +static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr, + u8 cache_blk, u16 flag); +static int FTL_Cache_Write(void); +static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr); +static void FTL_Calculate_LRU(void); +static u32 FTL_Get_Block_Index(u32 wBlockNum); + +static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, + u8 BT_Tag, u16 *Page); +static int FTL_Read_Block_Table(void); +static int FTL_Write_Block_Table(int wForce); +static int FTL_Write_Block_Table_Data(void); +static int FTL_Check_Block_Table(int wOldTable); +static int FTL_Static_Wear_Leveling(void); +static u32 FTL_Replace_Block_Table(void); +static int FTL_Write_IN_Progress_Block_Table_Page(void); + +static u32 FTL_Get_Page_Num(u64 length); +static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr); + +static u32 FTL_Replace_OneBlock(u32 wBlockNum, + u32 wReplaceNum); +static u32 FTL_Replace_LWBlock(u32 wBlockNum, + int *pGarbageCollect); +static u32 FTL_Replace_MWBlock(void); +static int FTL_Replace_Block(u64 blk_addr); +static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX); + +static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr); + +struct device_info_tag DeviceInfo; +struct flash_cache_tag Cache; +static struct spectra_l2_cache_info cache_l2; + +static u8 *cache_l2_page_buf; +static u8 *cache_l2_blk_buf; + +u8 *g_pBlockTable; +u8 *g_pWearCounter; +u16 *g_pReadCounter; +u32 *g_pBTBlocks; +static u16 g_wBlockTableOffset; +static u32 g_wBlockTableIndex; +static u8 g_cBlockTableStatus; + +static u8 *g_pTempBuf; +static u8 *flag_check_blk_table; +static u8 *tmp_buf_search_bt_in_block; +static u8 *spare_buf_search_bt_in_block; +static u8 *spare_buf_bt_search_bt_in_block; +static u8 *tmp_buf1_read_blk_table; +static u8 *tmp_buf2_read_blk_table; +static u8 *flags_static_wear_leveling; +static u8 *tmp_buf_write_blk_table_data; +static u8 *tmp_buf_read_disturbance; + +u8 *buf_read_page_main_spare; +u8 *buf_write_page_main_spare; +u8 *buf_read_page_spare; +u8 *buf_get_bad_block; + +#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) +struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS]; +struct flash_cache_tag cache_start_copy; +#endif + +int g_wNumFreeBlocks; +u8 g_SBDCmdIndex; + +static u8 *g_pIPF; +static u8 bt_flag = FIRST_BT_ID; +static u8 bt_block_changed; + +static u16 cache_block_to_write; +static u8 last_erased = FIRST_BT_ID; + +static u8 GC_Called; +static u8 BT_GC_Called; + +#if CMD_DMA +#define COPY_BACK_BUF_NUM 10 + +static u8 ftl_cmd_cnt; /* Init value is 0 */ +u8 *g_pBTDelta; +u8 *g_pBTDelta_Free; +u8 *g_pBTStartingCopy; +u8 *g_pWearCounterCopy; +u16 *g_pReadCounterCopy; +u8 *g_pBlockTableCopies; +u8 *g_pNextBlockTable; +static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM]; +static int cp_back_buf_idx; + +static u8 *g_temp_buf; + +#pragma pack(push, 1) +#pragma pack(1) +struct BTableChangesDelta { + u8 ftl_cmd_cnt; + u8 ValidFields; + u16 g_wBlockTableOffset; + u32 g_wBlockTableIndex; + u32 BT_Index; + u32 BT_Entry_Value; + u32 WC_Index; + u8 WC_Entry_Value; + u32 RC_Index; + u16 RC_Entry_Value; +}; + +#pragma pack(pop) + +struct BTableChangesDelta *p_BTableChangesDelta; +#endif + + +#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK) +#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK) + +#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u32)) +#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u8)) +#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u16)) +#if SUPPORT_LARGE_BLOCKNUM +#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u8) * 3) +#else +#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ + sizeof(u16)) +#endif +#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \ + FTL_Get_WearCounter_Table_Mem_Size_Bytes +#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \ + FTL_Get_ReadCounter_Table_Mem_Size_Bytes + +static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void) +{ + u32 byte_num; + + if (DeviceInfo.MLCDevice) { + byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + + DeviceInfo.wDataBlockNum * sizeof(u8) + + DeviceInfo.wDataBlockNum * sizeof(u16); + } else { + byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + + DeviceInfo.wDataBlockNum * sizeof(u8); + } + + byte_num += 4 * sizeof(u8); + + return byte_num; +} + +static u16 FTL_Get_Block_Table_Flash_Size_Pages(void) +{ + return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes()); +} + +static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx, + u32 sizeTxed) +{ + u32 wBytesCopied, blk_tbl_size, wBytes; + u32 *pbt = (u32 *)g_pBlockTable; + + blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); + for (wBytes = 0; + (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size); + wBytes++) { +#if SUPPORT_LARGE_BLOCKNUM + flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3] + >> (((wBytes + sizeTxed) % 3) ? + ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF; +#else + flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2] + >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; +#endif + } + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); + wBytesCopied = wBytes; + wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? + (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); + memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes); + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + + if (DeviceInfo.MLCDevice) { + blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); + wBytesCopied += wBytes; + for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) + flashBuf[wBytes + wBytesCopied] = + (g_pReadCounter[(wBytes + sizeTxed) / 2] >> + (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; + } + + return wBytesCopied + wBytes; +} + +static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf, + u32 sizeToTx, u32 sizeTxed) +{ + u32 wBytesCopied, blk_tbl_size, wBytes; + u32 *pbt = (u32 *)g_pBlockTable; + + blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); + for (wBytes = 0; (wBytes < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { +#if SUPPORT_LARGE_BLOCKNUM + if (!((wBytes + sizeTxed) % 3)) + pbt[(wBytes + sizeTxed) / 3] = 0; + pbt[(wBytes + sizeTxed) / 3] |= + (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ? + ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)); +#else + if (!((wBytes + sizeTxed) % 2)) + pbt[(wBytes + sizeTxed) / 2] = 0; + pbt[(wBytes + sizeTxed) / 2] |= + (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ? + 0 : 8)); +#endif + } + + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); + wBytesCopied = wBytes; + wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? + (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); + memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes); + sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; + + if (DeviceInfo.MLCDevice) { + wBytesCopied += wBytes; + blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); + for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && + ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { + if (((wBytes + sizeTxed) % 2)) + g_pReadCounter[(wBytes + sizeTxed) / 2] = 0; + g_pReadCounter[(wBytes + sizeTxed) / 2] |= + (flashBuf[wBytes] << + (((wBytes + sizeTxed) % 2) ? 0 : 8)); + } + } + + return wBytesCopied+wBytes; +} + +static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag) +{ + int i; + + for (i = 0; i < BTSIG_BYTES; i++) + buf[BTSIG_OFFSET + i] = + ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) % + (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID; + + return PASS; +} + +static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray) +{ + static u8 tag[BTSIG_BYTES >> 1]; + int i, j, k, tagi, tagtemp, status; + + *tagarray = (u8 *)tag; + tagi = 0; + + for (i = 0; i < (BTSIG_BYTES - 1); i++) { + for (j = i + 1; (j < BTSIG_BYTES) && + (tagi < (BTSIG_BYTES >> 1)); j++) { + tagtemp = buf[BTSIG_OFFSET + j] - + buf[BTSIG_OFFSET + i]; + if (tagtemp && !(tagtemp % BTSIG_DELTA)) { + tagtemp = (buf[BTSIG_OFFSET + i] + + (1 + LAST_BT_ID - FIRST_BT_ID) - + (i * BTSIG_DELTA)) % + (1 + LAST_BT_ID - FIRST_BT_ID); + status = FAIL; + for (k = 0; k < tagi; k++) { + if (tagtemp == tag[k]) + status = PASS; + } + + if (status == FAIL) { + tag[tagi++] = tagtemp; + i = (j == (i + 1)) ? i + 1 : i; + j = (j == (i + 1)) ? i + 1 : i; + } + } + } + } + + return tagi; +} + + +static int FTL_Execute_SPL_Recovery(void) +{ + u32 j, block, blks; + u32 *pbt = (u32 *)g_pBlockTable; + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock; + for (j = 0; j <= blks; j++) { + block = (pbt[j]); + if (((block & BAD_BLOCK) != BAD_BLOCK) && + ((block & SPARE_BLOCK) == SPARE_BLOCK)) { + ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK); + if (FAIL == ret) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)(block & ~BAD_BLOCK)); + MARK_BLOCK_AS_BAD(pbt[j]); + } + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_IdentifyDevice +* Inputs: pointer to identify data structure +* Outputs: PASS / FAIL +* Description: the identify data structure is filled in with +* information for the block driver. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev_data->NumBlocks = DeviceInfo.wTotalBlocks; + dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock; + dev_data->PageDataSize = DeviceInfo.wPageDataSize; + dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector; + dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum; + + return PASS; +} + +/* ..... */ +static int allocate_memory(void) +{ + u32 block_table_size, page_size, block_size, mem_size; + u32 total_bytes = 0; + int i; +#if CMD_DMA + int j; +#endif + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + page_size = DeviceInfo.wPageSize; + block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; + + block_table_size = DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8) + sizeof(u16)); + block_table_size += (DeviceInfo.wPageDataSize - + (block_table_size % DeviceInfo.wPageDataSize)) % + DeviceInfo.wPageDataSize; + + /* Malloc memory for block tables */ + g_pBlockTable = kmalloc(block_table_size, GFP_ATOMIC); + if (!g_pBlockTable) + goto block_table_fail; + memset(g_pBlockTable, 0, block_table_size); + total_bytes += block_table_size; + + g_pWearCounter = (u8 *)(g_pBlockTable + + DeviceInfo.wDataBlockNum * sizeof(u32)); + + if (DeviceInfo.MLCDevice) + g_pReadCounter = (u16 *)(g_pBlockTable + + DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8))); + + /* Malloc memory and init for cache items */ + for (i = 0; i < CACHE_ITEM_NUM; i++) { + Cache.array[i].address = NAND_CACHE_INIT_ADDR; + Cache.array[i].use_cnt = 0; + Cache.array[i].changed = CLEAR; + Cache.array[i].buf = kmalloc(Cache.cache_item_size, + GFP_ATOMIC); + if (!Cache.array[i].buf) + goto cache_item_fail; + memset(Cache.array[i].buf, 0, Cache.cache_item_size); + total_bytes += Cache.cache_item_size; + } + + /* Malloc memory for IPF */ + g_pIPF = kmalloc(page_size, GFP_ATOMIC); + if (!g_pIPF) + goto ipf_fail; + memset(g_pIPF, 0, page_size); + total_bytes += page_size; + + /* Malloc memory for data merging during Level2 Cache flush */ + cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC); + if (!cache_l2_page_buf) + goto cache_l2_page_buf_fail; + memset(cache_l2_page_buf, 0xff, page_size); + total_bytes += page_size; + + cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC); + if (!cache_l2_blk_buf) + goto cache_l2_blk_buf_fail; + memset(cache_l2_blk_buf, 0xff, block_size); + total_bytes += block_size; + + /* Malloc memory for temp buffer */ + g_pTempBuf = kmalloc(Cache.cache_item_size, GFP_ATOMIC); + if (!g_pTempBuf) + goto Temp_buf_fail; + memset(g_pTempBuf, 0, Cache.cache_item_size); + total_bytes += Cache.cache_item_size; + + /* Malloc memory for block table blocks */ + mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32); + g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBTBlocks) + goto bt_blocks_fail; + memset(g_pBTBlocks, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Check_Block_Table */ + flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC); + if (!flag_check_blk_table) + goto flag_check_blk_table_fail; + total_bytes += DeviceInfo.wDataBlockNum; + + /* Malloc memory for function FTL_Search_Block_Table_IN_Block */ + tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf_search_bt_in_block) + goto tmp_buf_search_bt_in_block_fail; + memset(tmp_buf_search_bt_in_block, 0xff, page_size); + total_bytes += page_size; + + mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize; + spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); + if (!spare_buf_search_bt_in_block) + goto spare_buf_search_bt_in_block_fail; + memset(spare_buf_search_bt_in_block, 0xff, mem_size); + total_bytes += mem_size; + + spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); + if (!spare_buf_bt_search_bt_in_block) + goto spare_buf_bt_search_bt_in_block_fail; + memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Read_Block_Table */ + tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf1_read_blk_table) + goto tmp_buf1_read_blk_table_fail; + memset(tmp_buf1_read_blk_table, 0xff, page_size); + total_bytes += page_size; + + tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC); + if (!tmp_buf2_read_blk_table) + goto tmp_buf2_read_blk_table_fail; + memset(tmp_buf2_read_blk_table, 0xff, page_size); + total_bytes += page_size; + + /* Malloc memory for function FTL_Static_Wear_Leveling */ + flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum, + GFP_ATOMIC); + if (!flags_static_wear_leveling) + goto flags_static_wear_leveling_fail; + total_bytes += DeviceInfo.wDataBlockNum; + + /* Malloc memory for function FTL_Write_Block_Table_Data */ + if (FTL_Get_Block_Table_Flash_Size_Pages() > 3) + mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() - + 2 * DeviceInfo.wPageSize; + else + mem_size = DeviceInfo.wPageSize; + tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC); + if (!tmp_buf_write_blk_table_data) + goto tmp_buf_write_blk_table_data_fail; + memset(tmp_buf_write_blk_table_data, 0xff, mem_size); + total_bytes += mem_size; + + /* Malloc memory for function FTL_Read_Disturbance */ + tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC); + if (!tmp_buf_read_disturbance) + goto tmp_buf_read_disturbance_fail; + memset(tmp_buf_read_disturbance, 0xff, block_size); + total_bytes += block_size; + + /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */ + buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); + if (!buf_read_page_main_spare) + goto buf_read_page_main_spare_fail; + total_bytes += DeviceInfo.wPageSize; + + /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */ + buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); + if (!buf_write_page_main_spare) + goto buf_write_page_main_spare_fail; + total_bytes += DeviceInfo.wPageSize; + + /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */ + buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); + if (!buf_read_page_spare) + goto buf_read_page_spare_fail; + memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize); + total_bytes += DeviceInfo.wPageSpareSize; + + /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */ + buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); + if (!buf_get_bad_block) + goto buf_get_bad_block_fail; + memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize); + total_bytes += DeviceInfo.wPageSpareSize; + +#if CMD_DMA + g_temp_buf = kmalloc(block_size, GFP_ATOMIC); + if (!g_temp_buf) + goto temp_buf_fail; + memset(g_temp_buf, 0xff, block_size); + total_bytes += block_size; + + /* Malloc memory for copy of block table used in CDMA mode */ + g_pBTStartingCopy = kmalloc(block_table_size, GFP_ATOMIC); + if (!g_pBTStartingCopy) + goto bt_starting_copy; + memset(g_pBTStartingCopy, 0, block_table_size); + total_bytes += block_table_size; + + g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy + + DeviceInfo.wDataBlockNum * sizeof(u32)); + + if (DeviceInfo.MLCDevice) + g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy + + DeviceInfo.wDataBlockNum * + (sizeof(u32) + sizeof(u8))); + + /* Malloc memory for block table copies */ + mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) + + 5 * DeviceInfo.wDataBlockNum * sizeof(u8); + if (DeviceInfo.MLCDevice) + mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16); + g_pBlockTableCopies = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBlockTableCopies) + goto blk_table_copies_fail; + memset(g_pBlockTableCopies, 0, mem_size); + total_bytes += mem_size; + g_pNextBlockTable = g_pBlockTableCopies; + + /* Malloc memory for Block Table Delta */ + mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta); + g_pBTDelta = kmalloc(mem_size, GFP_ATOMIC); + if (!g_pBTDelta) + goto bt_delta_fail; + memset(g_pBTDelta, 0, mem_size); + total_bytes += mem_size; + g_pBTDelta_Free = g_pBTDelta; + + /* Malloc memory for Copy Back Buffers */ + for (j = 0; j < COPY_BACK_BUF_NUM; j++) { + cp_back_buf_copies[j] = kmalloc(block_size, GFP_ATOMIC); + if (!cp_back_buf_copies[j]) + goto cp_back_buf_copies_fail; + memset(cp_back_buf_copies[j], 0, block_size); + total_bytes += block_size; + } + cp_back_buf_idx = 0; + + /* Malloc memory for pending commands list */ + mem_size = sizeof(struct pending_cmd) * MAX_DESCS; + info.pcmds = kzalloc(mem_size, GFP_KERNEL); + if (!info.pcmds) + goto pending_cmds_buf_fail; + total_bytes += mem_size; + + /* Malloc memory for CDMA descripter table */ + mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS; + info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL); + if (!info.cdma_desc_buf) + goto cdma_desc_buf_fail; + total_bytes += mem_size; + + /* Malloc memory for Memcpy descripter table */ + mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS; + info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL); + if (!info.memcp_desc_buf) + goto memcp_desc_buf_fail; + total_bytes += mem_size; +#endif + + nand_dbg_print(NAND_DBG_WARN, + "Total memory allocated in FTL layer: %d\n", total_bytes); + + return PASS; + +#if CMD_DMA +memcp_desc_buf_fail: + kfree(info.cdma_desc_buf); +cdma_desc_buf_fail: + kfree(info.pcmds); +pending_cmds_buf_fail: +cp_back_buf_copies_fail: + j--; + for (; j >= 0; j--) + kfree(cp_back_buf_copies[j]); + kfree(g_pBTDelta); +bt_delta_fail: + kfree(g_pBlockTableCopies); +blk_table_copies_fail: + kfree(g_pBTStartingCopy); +bt_starting_copy: + kfree(g_temp_buf); +temp_buf_fail: + kfree(buf_get_bad_block); +#endif + +buf_get_bad_block_fail: + kfree(buf_read_page_spare); +buf_read_page_spare_fail: + kfree(buf_write_page_main_spare); +buf_write_page_main_spare_fail: + kfree(buf_read_page_main_spare); +buf_read_page_main_spare_fail: + kfree(tmp_buf_read_disturbance); +tmp_buf_read_disturbance_fail: + kfree(tmp_buf_write_blk_table_data); +tmp_buf_write_blk_table_data_fail: + kfree(flags_static_wear_leveling); +flags_static_wear_leveling_fail: + kfree(tmp_buf2_read_blk_table); +tmp_buf2_read_blk_table_fail: + kfree(tmp_buf1_read_blk_table); +tmp_buf1_read_blk_table_fail: + kfree(spare_buf_bt_search_bt_in_block); +spare_buf_bt_search_bt_in_block_fail: + kfree(spare_buf_search_bt_in_block); +spare_buf_search_bt_in_block_fail: + kfree(tmp_buf_search_bt_in_block); +tmp_buf_search_bt_in_block_fail: + kfree(flag_check_blk_table); +flag_check_blk_table_fail: + kfree(g_pBTBlocks); +bt_blocks_fail: + kfree(g_pTempBuf); +Temp_buf_fail: + kfree(cache_l2_blk_buf); +cache_l2_blk_buf_fail: + kfree(cache_l2_page_buf); +cache_l2_page_buf_fail: + kfree(g_pIPF); +ipf_fail: +cache_item_fail: + i--; + for (; i >= 0; i--) + kfree(Cache.array[i].buf); + kfree(g_pBlockTable); +block_table_fail: + printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n", + __FILE__, __LINE__); + + return -ENOMEM; +} + +/* .... */ +static int free_memory(void) +{ + int i; + +#if CMD_DMA + kfree(info.memcp_desc_buf); + kfree(info.cdma_desc_buf); + kfree(info.pcmds); + for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--) + kfree(cp_back_buf_copies[i]); + kfree(g_pBTDelta); + kfree(g_pBlockTableCopies); + kfree(g_pBTStartingCopy); + kfree(g_temp_buf); + kfree(buf_get_bad_block); +#endif + kfree(buf_read_page_spare); + kfree(buf_write_page_main_spare); + kfree(buf_read_page_main_spare); + kfree(tmp_buf_read_disturbance); + kfree(tmp_buf_write_blk_table_data); + kfree(flags_static_wear_leveling); + kfree(tmp_buf2_read_blk_table); + kfree(tmp_buf1_read_blk_table); + kfree(spare_buf_bt_search_bt_in_block); + kfree(spare_buf_search_bt_in_block); + kfree(tmp_buf_search_bt_in_block); + kfree(flag_check_blk_table); + kfree(g_pBTBlocks); + kfree(g_pTempBuf); + kfree(g_pIPF); + for (i = CACHE_ITEM_NUM - 1; i >= 0; i--) + kfree(Cache.array[i].buf); + kfree(g_pBlockTable); + + return 0; +} + +static void dump_cache_l2_table(void) +{ + struct list_head *p; + struct spectra_l2_cache_list *pnd; + int n, i; + + n = 0; + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num); +/* + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { + if (pnd->pages_array[i] != MAX_U32_VALUE) + nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]); + } +*/ + n++; + } +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Init +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: allocates the memory for cache array, +* important data structures +* clears the cache array +* reads the block table from flash into array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Init(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + Cache.pages_per_item = 1; + Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize; + + if (allocate_memory() != PASS) + return FAIL; + +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_CHANS + MAX_DESCS)); +#endif + ftl_cmd_cnt = 0; +#endif + + if (FTL_Read_Block_Table() != PASS) + return FAIL; + + /* Init the Level2 Cache data structure */ + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) + cache_l2.blk_array[i] = MAX_U32_VALUE; + cache_l2.cur_blk_idx = 0; + cache_l2.cur_page_num = 0; + INIT_LIST_HEAD(&cache_l2.table.list); + cache_l2.table.logical_blk_num = MAX_U32_VALUE; + + dump_cache_l2_table(); + + return 0; +} + + +#if CMD_DMA +#if 0 +static void save_blk_table_changes(u16 idx) +{ + u8 ftl_cmd; + u32 *pbt = (u32 *)g_pBTStartingCopy; + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u16 id; + u8 cache_blks; + + id = idx - MAX_CHANS; + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = + int_cache[id].cache.changed; + } +#endif + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + + while (ftl_cmd <= PendingCMD[idx].Tag) { + if (p_BTableChangesDelta->ValidFields == 0x01) { + g_wBlockTableOffset = + p_BTableChangesDelta->g_wBlockTableOffset; + } else if (p_BTableChangesDelta->ValidFields == 0x0C) { + pbt[p_BTableChangesDelta->BT_Index] = + p_BTableChangesDelta->BT_Entry_Value; + debug_boundary_error((( + p_BTableChangesDelta->BT_Index)), + DeviceInfo.wDataBlockNum, 0); + } else if (p_BTableChangesDelta->ValidFields == 0x03) { + g_wBlockTableOffset = + p_BTableChangesDelta->g_wBlockTableOffset; + g_wBlockTableIndex = + p_BTableChangesDelta->g_wBlockTableIndex; + } else if (p_BTableChangesDelta->ValidFields == 0x30) { + g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] = + p_BTableChangesDelta->WC_Entry_Value; + } else if ((DeviceInfo.MLCDevice) && + (p_BTableChangesDelta->ValidFields == 0xC0)) { + g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] = + p_BTableChangesDelta->RC_Entry_Value; + nand_dbg_print(NAND_DBG_DEBUG, + "In event status setting read counter " + "GLOB_ftl_cmd_cnt %u Count %u Index %u\n", + ftl_cmd, + p_BTableChangesDelta->RC_Entry_Value, + (unsigned int)p_BTableChangesDelta->RC_Index); + } else { + nand_dbg_print(NAND_DBG_DEBUG, + "This should never occur \n"); + } + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } +} + +static void discard_cmds(u16 n) +{ + u32 *pbt = (u32 *)g_pBTStartingCopy; + u8 ftl_cmd; + unsigned long k; +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u8 cache_blks; + u16 id; +#endif + + if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) || + (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) { + for (k = 0; k < DeviceInfo.wDataBlockNum; k++) { + if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK))) + MARK_BLK_AS_DISCARD(pbt[k]); + } + } + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[n].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + id = n - MAX_CHANS; + + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + if (PendingCMD[n].CMD == MEMCOPY_CMD) { + if ((cache_start_copy.array[cache_blks].buf <= + PendingCMD[n].DataDestAddr) && + ((cache_start_copy.array[cache_blks].buf + + Cache.cache_item_size) > + PendingCMD[n].DataDestAddr)) { + cache_start_copy.array[cache_blks].address = + NAND_CACHE_INIT_ADDR; + cache_start_copy.array[cache_blks].use_cnt = + 0; + cache_start_copy.array[cache_blks].changed = + CLEAR; + } + } else { + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = + int_cache[id].cache.changed; + } + } +#endif +} + +static void process_cmd_pass(int *first_failed_cmd, u16 idx) +{ + if (0 == *first_failed_cmd) + save_blk_table_changes(idx); + else + discard_cmds(idx); +} + +static void process_cmd_fail_abort(int *first_failed_cmd, + u16 idx, int event) +{ + u32 *pbt = (u32 *)g_pBTStartingCopy; + u8 ftl_cmd; + unsigned long i; + int erase_fail, program_fail; +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + u8 cache_blks; + u16 id; +#endif + + if (0 == *first_failed_cmd) + *first_failed_cmd = PendingCMD[idx].SBDCmdIndex; + + nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occured " + "while executing %u Command %u accesing Block %u\n", + (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt, + PendingCMD[idx].CMD, + (unsigned int)PendingCMD[idx].Block); + + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[idx].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + id = idx - MAX_CHANS; + + if (int_cache[id].item != -1) { + cache_blks = int_cache[id].item; + if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) { + cache_start_copy.array[cache_blks].address = + int_cache[id].cache.address; + cache_start_copy.array[cache_blks].changed = SET; + } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) { + cache_start_copy.array[cache_blks].address = + NAND_CACHE_INIT_ADDR; + cache_start_copy.array[cache_blks].use_cnt = 0; + cache_start_copy.array[cache_blks].changed = + CLEAR; + } else if (PendingCMD[idx].CMD == ERASE_CMD) { + /* ? */ + } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) { + /* ? */ + } + } +#endif + + erase_fail = (event == EVENT_ERASE_FAILURE) && + (PendingCMD[idx].CMD == ERASE_CMD); + + program_fail = (event == EVENT_PROGRAM_FAILURE) && + ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) || + (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD)); + + if (erase_fail || program_fail) { + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (PendingCMD[idx].Block == + (pbt[i] & (~BAD_BLOCK))) + MARK_BLOCK_AS_BAD(pbt[i]); + } + } +} + +static void process_cmd(int *first_failed_cmd, u16 idx, int event) +{ + u8 ftl_cmd; + int cmd_match = 0; + + if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag) + cmd_match = 1; + + if (PendingCMD[idx].Status == CMD_PASS) { + process_cmd_pass(first_failed_cmd, idx); + } else if ((PendingCMD[idx].Status == CMD_FAIL) || + (PendingCMD[idx].Status == CMD_ABORT)) { + process_cmd_fail_abort(first_failed_cmd, idx, event); + } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) && + PendingCMD[idx].Tag) { + nand_dbg_print(NAND_DBG_DEBUG, + " Command no. %hu is not executed\n", + (unsigned int)PendingCMD[idx].Tag); + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + while (ftl_cmd <= PendingCMD[idx].Tag) { + p_BTableChangesDelta += 1; + ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; + } + } +} +#endif + +static void process_cmd(int *first_failed_cmd, u16 idx, int event) +{ + printk(KERN_ERR "temporary workaround function. " + "Should not be called! \n"); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Event_Status +* Inputs: none +* Outputs: Event Code +* Description: It is called by SBD after hardware interrupt signalling +* completion of commands chain +* It does following things +* get event status from LLD +* analyze command chain status +* determine last command executed +* analyze results +* rebuild the block table in case of uncorrectable error +* return event code +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Event_Status(int *first_failed_cmd) +{ + int event_code = PASS; + u16 i_P; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + *first_failed_cmd = 0; + + event_code = GLOB_LLD_Event_Status(); + + switch (event_code) { + case EVENT_PASS: + nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n"); + break; + case EVENT_UNCORRECTABLE_DATA_ERROR: + nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n"); + break; + case EVENT_PROGRAM_FAILURE: + case EVENT_ERASE_FAILURE: + nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. " + "Event code: 0x%x\n", event_code); + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta; + for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS); + i_P++) + process_cmd(first_failed_cmd, i_P, event_code); + memcpy(g_pBlockTable, g_pBTStartingCopy, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memcpy(g_pWearCounter, g_pWearCounterCopy, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memcpy(g_pReadCounter, g_pReadCounterCopy, + DeviceInfo.wDataBlockNum * sizeof(u16)); + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&Cache, (void *)&cache_start_copy, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_DESCS + MAX_CHANS)); +#endif + break; + default: + nand_dbg_print(NAND_DBG_WARN, + "Handling unexpected event code - 0x%x\n", + event_code); + event_code = ERR; + break; + } + + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memcpy(g_pWearCounterCopy, g_pWearCounter, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memcpy(g_pReadCounterCopy, g_pReadCounter, + DeviceInfo.wDataBlockNum * sizeof(u16)); + + g_pBTDelta_Free = g_pBTDelta; + ftl_cmd_cnt = 0; + g_pNextBlockTable = g_pBlockTableCopies; + cp_back_buf_idx = 0; + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); + memset((void *)&int_cache, -1, + sizeof(struct flash_cache_delta_list_tag) * + (MAX_DESCS + MAX_CHANS)); +#endif + + return event_code; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: glob_ftl_execute_cmds +* Inputs: none +* Outputs: none +* Description: pass thru to LLD +***************************************************************/ +u16 glob_ftl_execute_cmds(void) +{ + nand_dbg_print(NAND_DBG_TRACE, + "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n", + (unsigned int)ftl_cmd_cnt); + g_SBDCmdIndex = 0; + return glob_lld_execute_cmds(); +} + +#endif + +#if !CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Read Immediate +* Inputs: pointer to data +* address of data +* Outputs: PASS / FAIL +* Description: Reads one page of data into RAM directly from flash without +* using or disturbing cache.It is assumed this function is called +* with CMD-DMA disabled. +*****************************************************************/ +int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr) +{ + int wResult = FAIL; + u32 Block; + u16 Page; + u32 phy_blk; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + Block = BLK_FROM_ADDR(addr); + Page = PAGE_FROM_ADDR(addr, Block); + + if (!IS_SPARE_BLOCK(Block)) + return FAIL; + + phy_blk = pbt[Block]; + wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1); + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++; + if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock] + >= MAX_READ_COUNTER) + FTL_Read_Disturbance(phy_blk); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } + + return wResult; +} +#endif + +#ifdef SUPPORT_BIG_ENDIAN +/********************************************************************* +* Function: FTL_Invert_Block_Table +* Inputs: none +* Outputs: none +* Description: Re-format the block table in ram based on BIG_ENDIAN and +* LARGE_BLOCKNUM if necessary +**********************************************************************/ +static void FTL_Invert_Block_Table(void) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#ifdef SUPPORT_LARGE_BLOCKNUM + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + pbt[i] = INVERTUINT32(pbt[i]); + g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]); + } +#else + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + pbt[i] = INVERTUINT16(pbt[i]); + g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]); + } +#endif +} +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Flash_Init +* Inputs: none +* Outputs: PASS=0 / FAIL=0x01 (based on read ID) +* Description: The flash controller is initialized +* The flash device is reset +* Perform a flash READ ID command to confirm that a +* valid device is attached and active. +* The DeviceInfo structure gets filled in +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flash_Init(void) +{ + int status = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + g_SBDCmdIndex = 0; + + GLOB_LLD_Flash_Init(); + + status = GLOB_LLD_Read_Device_ID(); + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Inputs: none +* Outputs: PASS=0 / FAIL=0x01 (based on read ID) +* Description: The flash controller is released +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return GLOB_LLD_Flash_Release(); +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Cache_Release +* Inputs: none +* Outputs: none +* Description: release all allocated memory in GLOB_FTL_Init +* (allocated in GLOB_FTL_Init) +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void GLOB_FTL_Cache_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + free_memory(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_If_Hit +* Inputs: Page Address +* Outputs: Block number/UNHIT BLOCK +* Description: Determines if the addressed page is in cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u16 FTL_Cache_If_Hit(u64 page_addr) +{ + u16 item; + u64 addr; + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + item = UNHIT_CACHE_ITEM; + for (i = 0; i < CACHE_ITEM_NUM; i++) { + addr = Cache.array[i].address; + if ((page_addr >= addr) && + (page_addr < (addr + Cache.cache_item_size))) { + item = i; + break; + } + } + + return item; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Calculate_LRU +* Inputs: None +* Outputs: None +* Description: Calculate the least recently block in a cache and record its +* index in LRU field. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Calculate_LRU(void) +{ + u16 i, bCurrentLRU, bTempCount; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bCurrentLRU = 0; + bTempCount = MAX_WORD_VALUE; + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (Cache.array[i].use_cnt < bTempCount) { + bCurrentLRU = i; + bTempCount = Cache.array[i].use_cnt; + } + } + + Cache.LRU = bCurrentLRU; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read_Page +* Inputs: pointer to read buffer, logical address and cache item number +* Outputs: None +* Description: Read the page from the cached block addressed by blocknumber +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item) +{ + u8 *start_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + start_addr = Cache.array[cache_item].buf; + start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >> + DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize); + +#if CMD_DMA + GLOB_LLD_MemCopy_CMD(data_buf, start_addr, + DeviceInfo.wPageDataSize, 0); + ftl_cmd_cnt++; +#else + memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize); +#endif + + if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE) + Cache.array[cache_item].use_cnt++; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read_All +* Inputs: pointer to read buffer,block address +* Outputs: PASS=0 / FAIL =1 +* Description: It reads pages in cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr) +{ + int wResult = PASS; + u32 Block; + u32 lba; + u16 Page; + u16 PageCount; + u32 *pbt = (u32 *)g_pBlockTable; + u32 i; + + Block = BLK_FROM_ADDR(phy_addr); + Page = PAGE_FROM_ADDR(phy_addr, Block); + PageCount = Cache.pages_per_item; + + nand_dbg_print(NAND_DBG_DEBUG, + "%s, Line %d, Function: %s, Block: 0x%x\n", + __FILE__, __LINE__, __func__, Block); + + lba = 0xffffffff; + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if ((pbt[i] & (~BAD_BLOCK)) == Block) { + lba = i; + if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) || + IS_DISCARDED_BLOCK(i)) { + /* Add by yunpeng -2008.12.3 */ +#if CMD_DMA + GLOB_LLD_MemCopy_CMD(pData, g_temp_buf, + PageCount * DeviceInfo.wPageDataSize, 0); + ftl_cmd_cnt++; +#else + memset(pData, 0xFF, + PageCount * DeviceInfo.wPageDataSize); +#endif + return wResult; + } else { + continue; /* break ?? */ + } + } + } + + if (0xffffffff == lba) + printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n"); + +#if CMD_DMA + wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page, + PageCount, LLD_CMD_FLAG_MODE_CDMA); + if (DeviceInfo.MLCDevice) { + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; + nand_dbg_print(NAND_DBG_DEBUG, + "Read Counter modified in ftl_cmd_cnt %u" + " Block %u Counter%u\n", + ftl_cmd_cnt, (unsigned int)Block, + g_pReadCounter[Block - + DeviceInfo.wSpectraStartBlock]); + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->RC_Index = + Block - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->RC_Entry_Value = + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0xC0; + + ftl_cmd_cnt++; + + if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= + MAX_READ_COUNTER) + FTL_Read_Disturbance(Block); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } else { + ftl_cmd_cnt++; + } +#else + wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount); + if (wResult == FAIL) + return wResult; + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; + if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= + MAX_READ_COUNTER) + FTL_Read_Disturbance(Block); + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_All +* Inputs: pointer to cache in sys memory +* address of free block in flash +* Outputs: PASS=0 / FAIL=1 +* Description: writes all the pages of the block in cache to flash +* +* NOTE:need to make sure this works ok when cache is limited +* to a partial block. This is where copy-back would be +* activated. This would require knowing which pages in the +* cached block are clean/dirty.Right now we only know if +* the whole block is clean/dirty. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr) +{ + u16 wResult = PASS; + u32 Block; + u16 Page; + u16 PageCount; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written " + "on %d\n", cache_block_to_write, + (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)); + + Block = BLK_FROM_ADDR(blk_addr); + Page = PAGE_FROM_ADDR(blk_addr, Block); + PageCount = Cache.pages_per_item; + +#if CMD_DMA + if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData, + Block, Page, PageCount)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated! " + "Need Bad Block replacing.\n", + __FILE__, __LINE__, __func__, Block); + wResult = FAIL; + } + ftl_cmd_cnt++; +#else + if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s," + " Line %d, Function %s, new Bad Block %d generated!" + "Need Bad Block replacing.\n", + __FILE__, __LINE__, __func__, Block); + wResult = FAIL; + } +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Update_Block +* Inputs: pointer to buffer,page address,block address +* Outputs: PASS=0 / FAIL=1 +* Description: It updates the cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Update_Block(u8 *pData, + u64 old_page_addr, u64 blk_addr) +{ + int i, j; + u8 *buf = pData; + int wResult = PASS; + int wFoundInCache; + u64 page_addr; + u64 addr; + u64 old_blk_addr; + u16 page_offset; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + old_blk_addr = (u64)(old_page_addr >> + DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize; + page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >> + DeviceInfo.nBitsInPageDataSize); + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { + page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize; + if (i != page_offset) { + wFoundInCache = FAIL; + for (j = 0; j < CACHE_ITEM_NUM; j++) { + addr = Cache.array[j].address; + addr = FTL_Get_Physical_Block_Addr(addr) + + GLOB_u64_Remainder(addr, 2); + if ((addr >= page_addr) && addr < + (page_addr + Cache.cache_item_size)) { + wFoundInCache = PASS; + buf = Cache.array[j].buf; + Cache.array[j].changed = SET; +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = j; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[j].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[j].changed; +#endif +#endif + break; + } + } + if (FAIL == wFoundInCache) { + if (ERR == FTL_Cache_Read_All(g_pTempBuf, + page_addr)) { + wResult = FAIL; + break; + } + buf = g_pTempBuf; + } + } else { + buf = pData; + } + + if (FAIL == FTL_Cache_Write_All(buf, + blk_addr + (page_addr - old_blk_addr))) { + wResult = FAIL; + break; + } + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Copy_Block +* Inputs: source block address +* Destination block address +* Outputs: PASS=0 / FAIL=1 +* Description: used only for static wear leveling to move the block +* containing static data to new blocks(more worn) +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr) +{ + int i, r1, r2, wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { + r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr + + i * DeviceInfo.wPageDataSize); + r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr + + i * DeviceInfo.wPageDataSize); + if ((ERR == r1) || (FAIL == r2)) { + wResult = FAIL; + break; + } + } + + return wResult; +} + +/* Search the block table to find out the least wear block and then return it */ +static u32 find_least_worn_blk_for_l2_cache(void) +{ + int i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 least_wear_cnt = MAX_BYTE_VALUE; + u32 least_wear_blk_idx = MAX_U32_VALUE; + u32 phy_idx; + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + phy_idx = (u32)((~BAD_BLOCK) & pbt[i]); + if (phy_idx > DeviceInfo.wSpectraEndBlock) + printk(KERN_ERR "find_least_worn_blk_for_l2_cache: " + "Too big phy block num (%d)\n", phy_idx); + if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) { + least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock]; + least_wear_blk_idx = i; + } + } + } + + nand_dbg_print(NAND_DBG_WARN, + "find_least_worn_blk_for_l2_cache: " + "find block %d with least worn counter (%d)\n", + least_wear_blk_idx, least_wear_cnt); + + return least_wear_blk_idx; +} + + + +/* Get blocks for Level2 Cache */ +static int get_l2_cache_blks(void) +{ + int n; + u32 blk; + u32 *pbt = (u32 *)g_pBlockTable; + + for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) { + blk = find_least_worn_blk_for_l2_cache(); + if (blk > DeviceInfo.wDataBlockNum) { + nand_dbg_print(NAND_DBG_WARN, + "find_least_worn_blk_for_l2_cache: " + "No enough free NAND blocks (n: %d) for L2 Cache!\n", n); + return FAIL; + } + /* Tag the free block as discard in block table */ + pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK; + /* Add the free block to the L2 Cache block array */ + cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK); + } + + return PASS; +} + +static int erase_l2_cache_blocks(void) +{ + int i, ret = PASS; + u32 pblk, lblk; + u64 addr; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) { + pblk = cache_l2.blk_array[i]; + + /* If the L2 cache block is invalid, then just skip it */ + if (MAX_U32_VALUE == pblk) + continue; + + BUG_ON(pblk > DeviceInfo.wSpectraEndBlock); + + addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize; + if (PASS == GLOB_FTL_Block_Erase(addr)) { + /* Get logical block number of the erased block */ + lblk = FTL_Get_Block_Index(pblk); + BUG_ON(BAD_BLOCK == lblk); + /* Tag it as free in the block table */ + pbt[lblk] &= (u32)(~DISCARD_BLOCK); + pbt[lblk] |= (u32)(SPARE_BLOCK); + } else { + MARK_BLOCK_AS_BAD(pbt[lblk]); + ret = ERR; + } + } + + return ret; +} + +/* + * Merge the valid data page in the L2 cache blocks into NAND. +*/ +static int flush_l2_cache(void) +{ + struct list_head *p; + struct spectra_l2_cache_list *pnd, *tmp_pnd; + u32 *pbt = (u32 *)g_pBlockTable; + u32 phy_blk, l2_blk; + u64 addr; + u16 l2_page; + int i, ret = PASS; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (list_empty(&cache_l2.table.list)) /* No data to flush */ + return ret; + + //dump_cache_l2_table(); + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (IS_SPARE_BLOCK(pnd->logical_blk_num) || + IS_BAD_BLOCK(pnd->logical_blk_num) || + IS_DISCARDED_BLOCK(pnd->logical_blk_num)) { + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); + memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize); + } else { + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf, + phy_blk, 0, DeviceInfo.wPagesPerBlock); + if (ret == FAIL) { + printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); + } + } + + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { + if (pnd->pages_array[i] != MAX_U32_VALUE) { + l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff]; + l2_page = pnd->pages_array[i] & 0xffff; + ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1); + if (ret == FAIL) { + printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); + } + memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize); + } + } + + /* Find a free block and tag the original block as discarded */ + addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize; + ret = FTL_Replace_Block(addr); + if (ret == FAIL) { + printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__); + } + + /* Write back the updated data into NAND */ + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { + nand_dbg_print(NAND_DBG_WARN, + "Program NAND block %d fail in %s, Line %d\n", + phy_blk, __FILE__, __LINE__); + /* This may not be really a bad block. So just tag it as discarded. */ + /* Then it has a chance to be erased when garbage collection. */ + /* If it is really bad, then the erase will fail and it will be marked */ + /* as bad then. Otherwise it will be marked as free and can be used again */ + MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]); + /* Find another free block and write it again */ + FTL_Replace_Block(addr); + phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); + if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { + printk(KERN_ERR "Failed to write back block %d when flush L2 cache." + "Some data will be lost!\n", phy_blk); + MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]); + } + } else { + /* tag the new free block as used block */ + pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK); + } + } + + /* Destroy the L2 Cache table and free the memory of all nodes */ + list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) { + list_del(&pnd->list); + kfree(pnd); + } + + /* Erase discard L2 cache blocks */ + if (erase_l2_cache_blocks() != PASS) + nand_dbg_print(NAND_DBG_WARN, + " Erase L2 cache blocks error in %s, Line %d\n", + __FILE__, __LINE__); + + /* Init the Level2 Cache data structure */ + for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) + cache_l2.blk_array[i] = MAX_U32_VALUE; + cache_l2.cur_blk_idx = 0; + cache_l2.cur_page_num = 0; + INIT_LIST_HEAD(&cache_l2.table.list); + cache_l2.table.logical_blk_num = MAX_U32_VALUE; + + return ret; +} + +/* + * Write back a changed victim cache item to the Level2 Cache + * and update the L2 Cache table to map the change. + * If the L2 Cache is full, then start to do the L2 Cache flush. +*/ +static int write_back_to_l2_cache(u8 *buf, u64 logical_addr) +{ + u32 logical_blk_num; + u16 logical_page_num; + struct list_head *p; + struct spectra_l2_cache_list *pnd, *pnd_new; + u32 node_size; + int i, found; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* + * If Level2 Cache table is empty, then it means either: + * 1. This is the first time that the function called after FTL_init + * or + * 2. The Level2 Cache has just been flushed + * + * So, 'steal' some free blocks from NAND for L2 Cache using + * by just mask them as discard in the block table + */ + if (list_empty(&cache_l2.table.list)) { + BUG_ON(cache_l2.cur_blk_idx != 0); + BUG_ON(cache_l2.cur_page_num!= 0); + BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE); + if (FAIL == get_l2_cache_blks()) { + GLOB_FTL_Garbage_Collection(); + if (FAIL == get_l2_cache_blks()) { + printk(KERN_ALERT "Fail to get L2 cache blks!\n"); + return FAIL; + } + } + } + + logical_blk_num = BLK_FROM_ADDR(logical_addr); + logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); + BUG_ON(logical_blk_num == MAX_U32_VALUE); + + /* Write the cache item data into the current position of L2 Cache */ +#if CMD_DMA + /* + * TODO + */ +#else + if (FAIL == GLOB_LLD_Write_Page_Main(buf, + cache_l2.blk_array[cache_l2.cur_blk_idx], + cache_l2.cur_page_num, 1)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " + "%s, Line %d, new Bad Block %d generated!\n", + __FILE__, __LINE__, + cache_l2.blk_array[cache_l2.cur_blk_idx]); + + /* TODO: tag the current block as bad and try again */ + + return FAIL; + } +#endif + + /* + * Update the L2 Cache table. + * + * First seaching in the table to see whether the logical block + * has been mapped. If not, then kmalloc a new node for the + * logical block, fill data, and then insert it to the list. + * Otherwise, just update the mapped node directly. + */ + found = 0; + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (pnd->logical_blk_num == logical_blk_num) { + pnd->pages_array[logical_page_num] = + (cache_l2.cur_blk_idx << 16) | + cache_l2.cur_page_num; + found = 1; + break; + } + } + if (!found) { /* Create new node for the logical block here */ + + /* The logical pages to physical pages map array is + * located at the end of struct spectra_l2_cache_list. + */ + node_size = sizeof(struct spectra_l2_cache_list) + + sizeof(u32) * DeviceInfo.wPagesPerBlock; + pnd_new = kmalloc(node_size, GFP_ATOMIC); + if (!pnd_new) { + printk(KERN_ERR "Failed to kmalloc in %s Line %d\n", + __FILE__, __LINE__); + /* + * TODO: Need to flush all the L2 cache into NAND ASAP + * since no memory available here + */ + } + pnd_new->logical_blk_num = logical_blk_num; + for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) + pnd_new->pages_array[i] = MAX_U32_VALUE; + pnd_new->pages_array[logical_page_num] = + (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num; + list_add(&pnd_new->list, &cache_l2.table.list); + } + + /* Increasing the current position pointer of the L2 Cache */ + cache_l2.cur_page_num++; + if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) { + cache_l2.cur_blk_idx++; + if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) { + /* The L2 Cache is full. Need to flush it now */ + nand_dbg_print(NAND_DBG_WARN, + "L2 Cache is full, will start to flush it\n"); + flush_l2_cache(); + } else { + cache_l2.cur_page_num = 0; + } + } + + return PASS; +} + +/* + * Seach in the Level2 Cache table to find the cache item. + * If find, read the data from the NAND page of L2 Cache, + * Otherwise, return FAIL. + */ +static int search_l2_cache(u8 *buf, u64 logical_addr) +{ + u32 logical_blk_num; + u16 logical_page_num; + struct list_head *p; + struct spectra_l2_cache_list *pnd; + u32 tmp = MAX_U32_VALUE; + u32 phy_blk; + u16 phy_page; + int ret = FAIL; + + logical_blk_num = BLK_FROM_ADDR(logical_addr); + logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); + + list_for_each(p, &cache_l2.table.list) { + pnd = list_entry(p, struct spectra_l2_cache_list, list); + if (pnd->logical_blk_num == logical_blk_num) { + tmp = pnd->pages_array[logical_page_num]; + break; + } + } + + if (tmp != MAX_U32_VALUE) { /* Found valid map */ + phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF]; + phy_page = tmp & 0xFFFF; +#if CMD_DMA + /* TODO */ +#else + ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1); +#endif + } + + return ret; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_Back +* Inputs: pointer to data cached in sys memory +* address of free block in flash +* Outputs: PASS=0 / FAIL=1 +* Description: writes all the pages of Cache Block to flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr) +{ + int i, j, iErase; + u64 old_page_addr, addr, phy_addr; + u32 *pbt = (u32 *)g_pBlockTable; + u32 lba; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) + + GLOB_u64_Remainder(blk_addr, 2); + + iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL; + + pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK); + +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = (u32)(blk_addr >> + DeviceInfo.nBitsInBlockDataSize); + p_BTableChangesDelta->BT_Entry_Value = + pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + for (i = 0; i < RETRY_TIMES; i++) { + if (PASS == iErase) { + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { + lba = BLK_FROM_ADDR(blk_addr); + MARK_BLOCK_AS_BAD(pbt[lba]); + i = RETRY_TIMES; + break; + } + } + + for (j = 0; j < CACHE_ITEM_NUM; j++) { + addr = Cache.array[j].address; + if ((addr <= blk_addr) && + ((addr + Cache.cache_item_size) > blk_addr)) + cache_block_to_write = j; + } + + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + if (PASS == FTL_Cache_Update_Block(pData, + old_page_addr, phy_addr)) { + cache_block_to_write = UNHIT_CACHE_ITEM; + break; + } else { + iErase = PASS; + } + } + + if (i >= RETRY_TIMES) { + if (ERR == FTL_Flash_Error_Handle(pData, + old_page_addr, blk_addr)) + return ERR; + else + return FAIL; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write_Page +* Inputs: Pointer to buffer, page address, cache block number +* Outputs: PASS=0 / FAIL=1 +* Description: It writes the data in Cache Block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr, + u8 cache_blk, u16 flag) +{ + u8 *pDest; + u64 addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + addr = Cache.array[cache_blk].address; + pDest = Cache.array[cache_blk].buf; + + pDest += (unsigned long)(page_addr - addr); + Cache.array[cache_blk].changed = SET; +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = cache_blk; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[cache_blk].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[cache_blk].changed; +#endif + GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag); + ftl_cmd_cnt++; +#else + memcpy(pDest, pData, DeviceInfo.wPageDataSize); +#endif + if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE) + Cache.array[cache_blk].use_cnt++; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Write +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: It writes least frequently used Cache block to flash if it +* has been changed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Write(void) +{ + int i, bResult = PASS; + u16 bNO, least_count = 0xFFFF; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FTL_Calculate_LRU(); + + bNO = Cache.LRU; + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: " + "Least used cache block is %d\n", bNO); + + if (Cache.array[bNO].changed != SET) + return bResult; + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache" + " Block %d containing logical block %d is dirty\n", + bNO, + (u32)(Cache.array[bNO].address >> + DeviceInfo.nBitsInBlockDataSize)); +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = bNO; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[bNO].address; + int_cache[ftl_cmd_cnt].cache.changed = CLEAR; +#endif +#endif + bResult = write_back_to_l2_cache(Cache.array[bNO].buf, + Cache.array[bNO].address); + if (bResult != ERR) + Cache.array[bNO].changed = CLEAR; + + least_count = Cache.array[bNO].use_cnt; + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (i == bNO) + continue; + if (Cache.array[i].use_cnt > 0) + Cache.array[i].use_cnt -= least_count; + } + + return bResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Cache_Read +* Inputs: Page address +* Outputs: PASS=0 / FAIL=1 +* Description: It reads the block from device in Cache Block +* Set the LRU count to 1 +* Mark the Cache Block as clean +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Cache_Read(u64 logical_addr) +{ + u64 item_addr, phy_addr; + u16 num; + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + num = Cache.LRU; /* The LRU cache item will be overwritten */ + + item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) * + Cache.cache_item_size; + Cache.array[num].address = item_addr; + Cache.array[num].use_cnt = 1; + Cache.array[num].changed = CLEAR; + +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = num; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[num].address; + int_cache[ftl_cmd_cnt].cache.changed = + Cache.array[num].changed; +#endif +#endif + /* + * Search in L2 Cache. If hit, fill data into L1 Cache item buffer, + * Otherwise, read it from NAND + */ + ret = search_l2_cache(Cache.array[num].buf, logical_addr); + if (PASS == ret) /* Hit in L2 Cache */ + return ret; + + /* Compute the physical start address of NAND device according to */ + /* the logical start address of the cache item (LRU cache item) */ + phy_addr = FTL_Get_Physical_Block_Addr(item_addr) + + GLOB_u64_Remainder(item_addr, 2); + + return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Check_Block_Table +* Inputs: ? +* Outputs: PASS=0 / FAIL=1 +* Description: It checks the correctness of each block table entry +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Check_Block_Table(int wOldTable) +{ + u32 i; + int wResult = PASS; + u32 blk_idx; + u32 *pbt = (u32 *)g_pBlockTable; + u8 *pFlag = flag_check_blk_table; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (NULL != pFlag) { + memset(pFlag, FAIL, DeviceInfo.wDataBlockNum); + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + blk_idx = (u32)(pbt[i] & (~BAD_BLOCK)); + + /* + * 20081006/KBV - Changed to pFlag[i] reference + * to avoid buffer overflow + */ + + /* + * 2008-10-20 Yunpeng Note: This change avoid + * buffer overflow, but changed function of + * the code, so it should be re-write later + */ + if ((blk_idx > DeviceInfo.wSpectraEndBlock) || + PASS == pFlag[i]) { + wResult = FAIL; + break; + } else { + pFlag[i] = PASS; + } + } + } + + return wResult; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_Block_Table +* Inputs: flasg +* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to +* happen. -1 Error +* Description: It writes the block table +* Block table always mapped to LBA 0 which inturn mapped +* to any physical block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Write_Block_Table(int wForce) +{ + u32 *pbt = (u32 *)g_pBlockTable; + int wSuccess = PASS; + u32 wTempBlockTableIndex; + u16 bt_pages, new_bt_offset; + u8 blockchangeoccured = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) + return 0; + + if (PASS == wForce) { + g_wBlockTableOffset = + (u16)(DeviceInfo.wPagesPerBlock - bt_pages); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = + g_wBlockTableOffset; + p_BTableChangesDelta->ValidFields = 0x01; +#endif + } + + nand_dbg_print(NAND_DBG_DEBUG, + "Inside FTL_Write_Block_Table: block %d Page:%d\n", + g_wBlockTableIndex, g_wBlockTableOffset); + + do { + new_bt_offset = g_wBlockTableOffset + bt_pages + 1; + if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) || + (new_bt_offset > DeviceInfo.wPagesPerBlock) || + (FAIL == wSuccess)) { + wTempBlockTableIndex = FTL_Replace_Block_Table(); + if (BAD_BLOCK == wTempBlockTableIndex) + return ERR; + if (!blockchangeoccured) { + bt_block_changed = 1; + blockchangeoccured = 1; + } + + g_wBlockTableIndex = wTempBlockTableIndex; + g_wBlockTableOffset = 0; + pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = + g_wBlockTableOffset; + p_BTableChangesDelta->g_wBlockTableIndex = + g_wBlockTableIndex; + p_BTableChangesDelta->ValidFields = 0x03; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + BLOCK_TABLE_INDEX; + p_BTableChangesDelta->BT_Entry_Value = + pbt[BLOCK_TABLE_INDEX]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } + + wSuccess = FTL_Write_Block_Table_Data(); + if (FAIL == wSuccess) + MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); + } while (FAIL == wSuccess); + + g_cBlockTableStatus = CURRENT_BLOCK_TABLE; + + return 1; +} + +/****************************************************************** +* Function: GLOB_FTL_Flash_Format +* Inputs: none +* Outputs: PASS +* Description: The block table stores bad block info, including MDF+ +* blocks gone bad over the ages. Therefore, if we have a +* block table in place, then use it to scan for bad blocks +* If not, then scan for MDF. +* Now, a block table will only be found if spectra was already +* being used. For a fresh flash, we'll go thru scanning for +* MDF. If spectra was being used, then there is a chance that +* the MDF has been corrupted. Spectra avoids writing to the +* first 2 bytes of the spare area to all pages in a block. This +* covers all known flash devices. However, since flash +* manufacturers have no standard of where the MDF is stored, +* this cannot guarantee that the MDF is protected for future +* devices too. The initial scanning for the block table assures +* this. It is ok even if the block table is outdated, as all +* we're looking for are bad block markers. +* Use this when mounting a file system or starting a +* new flash. +* +*********************************************************************/ +static int FTL_Format_Flash(u8 valid_block_table) +{ + u32 i, j; + u32 *pbt = (u32 *)g_pBlockTable; + u32 tempNode; + int ret; + +#if CMD_DMA + u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy; + if (ftl_cmd_cnt) + return FAIL; +#endif + + if (FAIL == FTL_Check_Block_Table(FAIL)) + valid_block_table = 0; + + if (valid_block_table) { + u8 switched = 1; + u32 block, k; + + k = DeviceInfo.wSpectraStartBlock; + while (switched && (k < DeviceInfo.wSpectraEndBlock)) { + switched = 0; + k++; + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + block = (pbt[i] & ~BAD_BLOCK) - + DeviceInfo.wSpectraStartBlock; + if (block != i) { + switched = 1; + tempNode = pbt[i]; + pbt[i] = pbt[block]; + pbt[block] = tempNode; + } + } + } + if ((k == DeviceInfo.wSpectraEndBlock) && switched) + valid_block_table = 0; + } + + if (!valid_block_table) { + memset(g_pBlockTable, 0, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memset(g_pWearCounter, 0, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memset(g_pReadCounter, 0, + DeviceInfo.wDataBlockNum * sizeof(u16)); +#if CMD_DMA + memset(g_pBTStartingCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u32)); + memset(g_pWearCounterCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u8)); + if (DeviceInfo.MLCDevice) + memset(g_pReadCounterCopy, 0, + DeviceInfo.wDataBlockNum * sizeof(u16)); +#endif + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + if (GLOB_LLD_Get_Bad_Block((u32)j)) + pbt[i] = (u32)(BAD_BLOCK | j); + } + } + + nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n"); + + for (j = DeviceInfo.wSpectraStartBlock, i = 0; + j <= DeviceInfo.wSpectraEndBlock; + j++, i++) { + if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) { + ret = GLOB_LLD_Erase_Block(j); + if (FAIL == ret) { + pbt[i] = (u32)(j); + MARK_BLOCK_AS_BAD(pbt[i]); + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, (int)j); + } else { + pbt[i] = (u32)(SPARE_BLOCK | j); + } + } +#if CMD_DMA + pbtStartingCopy[i] = pbt[i]; +#endif + } + + g_wBlockTableOffset = 0; + for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock)) + && ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++) + ; + if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) { + printk(KERN_ERR "All blocks bad!\n"); + return FAIL; + } else { + g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK; + if (i != BLOCK_TABLE_INDEX) { + tempNode = pbt[i]; + pbt[i] = pbt[BLOCK_TABLE_INDEX]; + pbt[BLOCK_TABLE_INDEX] = tempNode; + } + } + pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); + +#if CMD_DMA + pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); +#endif + + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + memset(g_pBTBlocks, 0xFF, + (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32)); + g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex; + FTL_Write_Block_Table(FAIL); + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + Cache.array[i].address = NAND_CACHE_INIT_ADDR; + Cache.array[i].use_cnt = 0; + Cache.array[i].changed = CLEAR; + } + +#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) + memcpy((void *)&cache_start_copy, (void *)&Cache, + sizeof(struct flash_cache_tag)); +#endif + return PASS; +} + +static int force_format_nand(void) +{ + u32 i; + + /* Force erase the whole unprotected physical partiton of NAND */ + printk(KERN_ALERT "Start to force erase whole NAND device ...\n"); + printk(KERN_ALERT "From phyical block %d to %d\n", + DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock); + for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) { + if (GLOB_LLD_Erase_Block(i)) + printk(KERN_ERR "Failed to force erase NAND block %d\n", i); + } + printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n"); + while(1); + + return PASS; +} + +int GLOB_FTL_Flash_Format(void) +{ + //return FTL_Format_Flash(1); + return force_format_nand(); + +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Search_Block_Table_IN_Block +* Inputs: Block Number +* Pointer to page +* Outputs: PASS / FAIL +* Page contatining the block table +* Description: It searches the block table in the block +* passed as an argument. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, + u8 BT_Tag, u16 *Page) +{ + u16 i, j, k; + u16 Result = PASS; + u16 Last_IPF = 0; + u8 BT_Found = 0; + u8 *tagarray; + u8 *tempbuf = tmp_buf_search_bt_in_block; + u8 *pSpareBuf = spare_buf_search_bt_in_block; + u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block; + u8 bt_flag_last_page = 0xFF; + u8 search_in_previous_pages = 0; + u16 bt_pages; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, + "Searching block table in %u block\n", + (unsigned int)BT_Block); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + for (i = bt_pages; i < DeviceInfo.wPagesPerBlock; + i += (bt_pages + 1)) { + nand_dbg_print(NAND_DBG_DEBUG, + "Searching last IPF: %d\n", i); + Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf, + BT_Block, i, 1); + + if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) { + if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) { + continue; + } else { + search_in_previous_pages = 1; + Last_IPF = i; + } + } + + if (!search_in_previous_pages) { + if (i != bt_pages) { + i -= (bt_pages + 1); + Last_IPF = i; + } + } + + if (0 == Last_IPF) + break; + + if (!search_in_previous_pages) { + i = i + 1; + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i); + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, + BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag( + pSpareBufBTLastPage, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag_last_page = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found" + " in page after IPF " + "at block %d " + "page %d\n", + (int)BT_Block, i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + CURRENT_BLOCK_TABLE; + break; + } else { + Result = FAIL; + } + } + } + } + + if (search_in_previous_pages) + i = i - bt_pages; + else + i = i - (bt_pages + 1); + + Result = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %d Page %d", + (int)BT_Block, i); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, + &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) { + bt_flag_last_page = tagarray[k]; + } else { + Result = FAIL; + break; + } + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found " + "in page prior to IPF " + "at block %u page %d\n", + (unsigned int)BT_Block, i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + IN_PROGRESS_BLOCK_TABLE; + break; + } else { + Result = FAIL; + break; + } + } + } + } + + if (Result == FAIL) { + if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) { + BT_Found = 1; + *Page = i - (bt_pages + 1); + } + if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found)) + goto func_return; + } + + if (Last_IPF == 0) { + i = 0; + Result = PASS; + nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of " + "Block %u Page %u", (unsigned int)BT_Block, i); + + Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); + nand_dbg_print(NAND_DBG_DEBUG, + "Reading the spare area of Block %u Page %u", + (unsigned int)BT_Block, i + bt_pages - 1); + Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, + BT_Block, i + bt_pages - 1, 1); + + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + k = 0; + j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, + &tagarray); + if (j) { + for (; k < j; k++) { + if (tagarray[k] == BT_Tag) + break; + } + } + + if (k < j) + bt_flag_last_page = tagarray[k]; + else + Result = FAIL; + + if (Result == PASS) { + if (bt_flag == bt_flag_last_page) { + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is found " + "in page after IPF at " + "block %u page %u\n", + (unsigned int)BT_Block, + (unsigned int)i); + BT_Found = 1; + *Page = i; + g_cBlockTableStatus = + CURRENT_BLOCK_TABLE; + goto func_return; + } else { + Result = FAIL; + } + } + } + + if (Result == FAIL) + goto func_return; + } +func_return: + return Result; +} + +u8 *get_blk_table_start_addr(void) +{ + return g_pBlockTable; +} + +unsigned long get_blk_table_len(void) +{ + return DeviceInfo.wDataBlockNum * sizeof(u32); +} + +u8 *get_wear_leveling_table_start_addr(void) +{ + return g_pWearCounter; +} + +unsigned long get_wear_leveling_table_len(void) +{ + return DeviceInfo.wDataBlockNum * sizeof(u8); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Read_Block_Table +* Inputs: none +* Outputs: PASS / FAIL +* Description: read the flash spare area and find a block containing the +* most recent block table(having largest block_table_counter). +* Find the last written Block table in this block. +* Check the correctness of Block Table +* If CDMA is enabled, this function is called in +* polling mode. +* We don't need to store changes in Block table in this +* function as it is called only at initialization +* +* Note: Currently this function is called at initialization +* before any read/erase/write command issued to flash so, +* there is no need to wait for CDMA list to complete as of now +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Read_Block_Table(void) +{ + u16 i = 0; + int k, j; + u8 *tempBuf, *tagarray; + int wResult = FAIL; + int status = FAIL; + u8 block_table_found = 0; + int search_result; + u32 Block; + u16 Page = 0; + u16 PageCount; + u16 bt_pages; + int wBytesCopied = 0, tempvar; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + tempBuf = tmp_buf1_read_blk_table; + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + for (j = DeviceInfo.wSpectraStartBlock; + j <= (int)DeviceInfo.wSpectraEndBlock; + j++) { + status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1); + k = 0; + i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray); + if (i) { + status = GLOB_LLD_Read_Page_Main_Polling(tempBuf, + j, 0, 1); + for (; k < i; k++) { + if (tagarray[k] == tempBuf[3]) + break; + } + } + + if (k < i) + k = tagarray[k]; + else + continue; + + nand_dbg_print(NAND_DBG_DEBUG, + "Block table is contained in Block %d %d\n", + (unsigned int)j, (unsigned int)k); + + if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) { + g_pBTBlocks[k-FIRST_BT_ID] = j; + block_table_found = 1; + } else { + printk(KERN_ERR "FTL_Read_Block_Table -" + "This should never happens. " + "Two block table have same counter %u!\n", k); + } + } + + if (block_table_found) { + if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL && + g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) { + j = LAST_BT_ID; + while ((j > FIRST_BT_ID) && + (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL)) + j--; + if (j == FIRST_BT_ID) { + j = LAST_BT_ID; + last_erased = LAST_BT_ID; + } else { + last_erased = (u8)j + 1; + while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL == + g_pBTBlocks[j - FIRST_BT_ID])) + j--; + } + } else { + j = FIRST_BT_ID; + while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL) + j++; + last_erased = (u8)j; + while ((j < LAST_BT_ID) && (BTBLOCK_INVAL != + g_pBTBlocks[j - FIRST_BT_ID])) + j++; + if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL) + j--; + } + + if (last_erased > j) + j += (1 + LAST_BT_ID - FIRST_BT_ID); + + for (; (j >= last_erased) && (FAIL == wResult); j--) { + i = (j - FIRST_BT_ID) % + (1 + LAST_BT_ID - FIRST_BT_ID); + search_result = + FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i], + i + FIRST_BT_ID, &Page); + if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) + block_table_found = 0; + + while ((search_result == PASS) && (FAIL == wResult)) { + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Read_Block_Table:" + "Block: %u Page: %u " + "contains block table\n", + (unsigned int)g_pBTBlocks[i], + (unsigned int)Page); + + tempBuf = tmp_buf2_read_blk_table; + + for (k = 0; k < bt_pages; k++) { + Block = g_pBTBlocks[i]; + PageCount = 1; + + status = + GLOB_LLD_Read_Page_Main_Polling( + tempBuf, Block, Page, PageCount); + + tempvar = k ? 0 : 4; + + wBytesCopied += + FTL_Copy_Block_Table_From_Flash( + tempBuf + tempvar, + DeviceInfo.wPageDataSize - tempvar, + wBytesCopied); + + Page++; + } + + wResult = FTL_Check_Block_Table(FAIL); + if (FAIL == wResult) { + block_table_found = 0; + if (Page > bt_pages) + Page -= ((bt_pages<<1) + 1); + else + search_result = FAIL; + } + } + } + } + + if (PASS == wResult) { + if (!block_table_found) + FTL_Execute_SPL_Recovery(); + + if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) + g_wBlockTableOffset = (u16)Page + 1; + else + g_wBlockTableOffset = (u16)Page - bt_pages; + + g_wBlockTableIndex = (u32)g_pBTBlocks[i]; + +#if CMD_DMA + if (DeviceInfo.MLCDevice) + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32) + + DeviceInfo.wDataBlockNum * sizeof(u8) + + DeviceInfo.wDataBlockNum * sizeof(u16)); + else + memcpy(g_pBTStartingCopy, g_pBlockTable, + DeviceInfo.wDataBlockNum * sizeof(u32) + + DeviceInfo.wDataBlockNum * sizeof(u8)); +#endif + } + + if (FAIL == wResult) + printk(KERN_ERR "Yunpeng - " + "Can not find valid spectra block table!\n"); + +#if AUTO_FORMAT_FLASH + if (FAIL == wResult) { + nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n"); + wResult = FTL_Format_Flash(0); + } +#endif + + return wResult; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Flash_Error_Handle +* Inputs: Pointer to data +* Page address +* Block address +* Outputs: PASS=0 / FAIL=1 +* Description: It handles any error occured during Spectra operation +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, + u64 blk_addr) +{ + u32 i; + int j; + u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr); + u64 phy_addr; + int wErase = FAIL; + int wResult = FAIL; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (ERR == GLOB_FTL_Garbage_Collection()) + return ERR; + + do { + for (i = DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock; + i > 0; i--) { + if (IS_SPARE_BLOCK(i)) { + tmp_node = (u32)(BAD_BLOCK | + pbt[blk_node]); + pbt[blk_node] = (u32)(pbt[i] & + (~SPARE_BLOCK)); + pbt[i] = tmp_node; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + blk_node; + p_BTableChangesDelta->BT_Entry_Value = + pbt[blk_node]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = i; + p_BTableChangesDelta->BT_Entry_Value = pbt[i]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + wResult = PASS; + break; + } + } + + if (FAIL == wResult) { + if (FAIL == GLOB_FTL_Garbage_Collection()) + break; + else + continue; + } + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); + + for (j = 0; j < RETRY_TIMES; j++) { + if (PASS == wErase) { + if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { + MARK_BLOCK_AS_BAD(pbt[blk_node]); + break; + } + } + if (PASS == FTL_Cache_Update_Block(pData, + old_page_addr, + phy_addr)) { + wResult = PASS; + break; + } else { + wResult = FAIL; + wErase = PASS; + } + } + } while (FAIL == wResult); + + FTL_Write_Block_Table(FAIL); + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Page_Num +* Inputs: Size in bytes +* Outputs: Size in pages +* Description: It calculates the pages required for the length passed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Get_Page_Num(u64 length) +{ + return (u32)((length >> DeviceInfo.nBitsInPageDataSize) + + (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0)); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Physical_Block_Addr +* Inputs: Block Address (byte format) +* Outputs: Physical address of the block. +* Description: It translates LBA to PBA by returning address stored +* at the LBA location in the block table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr) +{ + u32 *pbt; + u64 physical_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + pbt = (u32 *)g_pBlockTable; + physical_addr = (u64) DeviceInfo.wBlockDataSize * + (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK)); + + return physical_addr; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Get_Block_Index +* Inputs: Physical Block no. +* Outputs: Logical block no. /BAD_BLOCK +* Description: It returns the logical block no. for the PBA passed +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Get_Block_Index(u32 wBlockNum) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) + if (wBlockNum == (pbt[i] & (~BAD_BLOCK))) + return i; + + return BAD_BLOCK; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Wear_Leveling +* Inputs: none +* Outputs: PASS=0 +* Description: This is static wear leveling (done by explicit call) +* do complete static wear leveling +* do complete garbage collection +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Wear_Leveling(void) +{ + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FTL_Static_Wear_Leveling(); + GLOB_FTL_Garbage_Collection(); + + return PASS; +} + +static void find_least_most_worn(u8 *chg, + u32 *least_idx, u8 *least_cnt, + u32 *most_idx, u8 *most_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 idx; + u8 cnt; + int i; + + for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_BAD_BLOCK(i) || PASS == chg[i]) + continue; + + idx = (u32) ((~BAD_BLOCK) & pbt[i]); + cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock]; + + if (IS_SPARE_BLOCK(i)) { + if (cnt > *most_cnt) { + *most_cnt = cnt; + *most_idx = idx; + } + } + + if (IS_DATA_BLOCK(i)) { + if (cnt < *least_cnt) { + *least_cnt = cnt; + *least_idx = idx; + } + } + + if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) { + debug_boundary_error(*most_idx, + DeviceInfo.wDataBlockNum, 0); + debug_boundary_error(*least_idx, + DeviceInfo.wDataBlockNum, 0); + continue; + } + } +} + +static int move_blks_for_wear_leveling(u8 *chg, + u32 *least_idx, u32 *rep_blk_num, int *result) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 rep_blk; + int j, ret_cp_blk, ret_erase; + int ret = PASS; + + chg[*least_idx] = PASS; + debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0); + + rep_blk = FTL_Replace_MWBlock(); + if (rep_blk != BAD_BLOCK) { + nand_dbg_print(NAND_DBG_DEBUG, + "More than two spare blocks exist so do it\n"); + nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n", + rep_blk); + + chg[rep_blk] = PASS; + + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + for (j = 0; j < RETRY_TIMES; j++) { + ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) * + DeviceInfo.wBlockDataSize, + (u64)rep_blk * DeviceInfo.wBlockDataSize); + if (FAIL == ret_cp_blk) { + ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk + * DeviceInfo.wBlockDataSize); + if (FAIL == ret_erase) + MARK_BLOCK_AS_BAD(pbt[rep_blk]); + } else { + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Copy_Block == OK\n"); + break; + } + } + + if (j < RETRY_TIMES) { + u32 tmp; + u32 old_idx = FTL_Get_Block_Index(*least_idx); + u32 rep_idx = FTL_Get_Block_Index(rep_blk); + tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]); + pbt[old_idx] = (u32)((~SPARE_BLOCK) & + pbt[rep_idx]); + pbt[rep_idx] = tmp; +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = old_idx; + p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = rep_idx; + p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } else { + pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK; +#if CMD_DMA + p_BTableChangesDelta = (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = + FTL_Get_Block_Index(rep_blk); + p_BTableChangesDelta->BT_Entry_Value = + pbt[FTL_Get_Block_Index(rep_blk)]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + *result = FAIL; + ret = FAIL; + } + + if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM) + ret = FAIL; + } else { + printk(KERN_ERR "Less than 3 spare blocks exist so quit\n"); + ret = FAIL; + } + + return ret; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Static_Wear_Leveling +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: This is static wear leveling (done by explicit call) +* search for most&least used +* if difference < GATE: +* update the block table with exhange +* mark block table in flash as IN_PROGRESS +* copy flash block +* the caller should handle GC clean up after calling this function +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Static_Wear_Leveling(void) +{ + u8 most_worn_cnt; + u8 least_worn_cnt; + u32 most_worn_idx; + u32 least_worn_idx; + int result = PASS; + int go_on = PASS; + u32 replaced_blks = 0; + u8 *chang_flag = flags_static_wear_leveling; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!chang_flag) + return FAIL; + + memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum); + while (go_on == PASS) { + nand_dbg_print(NAND_DBG_DEBUG, + "starting static wear leveling\n"); + most_worn_cnt = 0; + least_worn_cnt = 0xFF; + least_worn_idx = BLOCK_TABLE_INDEX; + most_worn_idx = BLOCK_TABLE_INDEX; + + find_least_most_worn(chang_flag, &least_worn_idx, + &least_worn_cnt, &most_worn_idx, &most_worn_cnt); + + nand_dbg_print(NAND_DBG_DEBUG, + "Used and least worn is block %u, whos count is %u\n", + (unsigned int)least_worn_idx, + (unsigned int)least_worn_cnt); + + nand_dbg_print(NAND_DBG_DEBUG, + "Free and most worn is block %u, whos count is %u\n", + (unsigned int)most_worn_idx, + (unsigned int)most_worn_cnt); + + if ((most_worn_cnt > least_worn_cnt) && + (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE)) + go_on = move_blks_for_wear_leveling(chang_flag, + &least_worn_idx, &replaced_blks, &result); + else + go_on = FAIL; + } + + return result; +} + +#if CMD_DMA +static int do_garbage_collection(u32 discard_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 pba; + u8 bt_block_erased = 0; + int i, cnt, ret = FAIL; + u64 addr; + + i = 0; + while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) && + ((ftl_cmd_cnt + 28) < 256)) { + if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[i] & DISCARD_BLOCK)) { + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + pba = BLK_FROM_ADDR(addr); + + for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { + if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase BT block %u\n", + (unsigned int)pba); + discard_cnt--; + i++; + bt_block_erased = 1; + break; + } + } + + if (bt_block_erased) { + bt_block_erased = 0; + continue; + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[i] &= (u32)(~DISCARD_BLOCK); + pbt[i] |= (u32)(SPARE_BLOCK); + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt - 1; + p_BTableChangesDelta->BT_Index = i; + p_BTableChangesDelta->BT_Entry_Value = pbt[i]; + p_BTableChangesDelta->ValidFields = 0x0C; + discard_cnt--; + ret = PASS; + } else { + MARK_BLOCK_AS_BAD(pbt[i]); + } + } + + i++; + } + + return ret; +} + +#else +static int do_garbage_collection(u32 discard_cnt) +{ + u32 *pbt = (u32 *)g_pBlockTable; + u32 pba; + u8 bt_block_erased = 0; + int i, cnt, ret = FAIL; + u64 addr; + + i = 0; + while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) { + if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[i] & DISCARD_BLOCK)) { + if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + pba = BLK_FROM_ADDR(addr); + + for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { + if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase BT block %d\n", + pba); + discard_cnt--; + i++; + bt_block_erased = 1; + break; + } + } + + if (bt_block_erased) { + bt_block_erased = 0; + continue; + } + + /* If the discard block is L2 cache block, then just skip it */ + for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) { + if (cache_l2.blk_array[cnt] == pba) { + nand_dbg_print(NAND_DBG_DEBUG, + "GC will erase L2 cache blk %d\n", + pba); + break; + } + } + if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */ + discard_cnt--; + i++; + continue; + } + + addr = FTL_Get_Physical_Block_Addr((u64)i * + DeviceInfo.wBlockDataSize); + + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[i] &= (u32)(~DISCARD_BLOCK); + pbt[i] |= (u32)(SPARE_BLOCK); + discard_cnt--; + ret = PASS; + } else { + MARK_BLOCK_AS_BAD(pbt[i]); + } + } + + i++; + } + + return ret; +} +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Garbage_Collection +* Inputs: none +* Outputs: PASS / FAIL (returns the number of un-erased blocks +* Description: search the block table for all discarded blocks to erase +* for each discarded block: +* set the flash block to IN_PROGRESS +* erase the block +* update the block table +* write the block table to flash +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Garbage_Collection(void) +{ + u32 i; + u32 wDiscard = 0; + int wResult = FAIL; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (GC_Called) { + printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() " + "has been re-entered! Exit.\n"); + return PASS; + } + + GC_Called = 1; + + GLOB_FTL_BT_Garbage_Collection(); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_DISCARDED_BLOCK(i)) + wDiscard++; + } + + if (wDiscard <= 0) { + GC_Called = 0; + return wResult; + } + + nand_dbg_print(NAND_DBG_DEBUG, + "Found %d discarded blocks\n", wDiscard); + + FTL_Write_Block_Table(FAIL); + + wResult = do_garbage_collection(wDiscard); + + FTL_Write_Block_Table(FAIL); + + GC_Called = 0; + + return wResult; +} + + +#if CMD_DMA +static int do_bt_garbage_collection(void) +{ + u32 pba, lba; + u32 *pbt = (u32 *)g_pBlockTable; + u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; + u64 addr; + int i, ret = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (BT_GC_Called) + return PASS; + + BT_GC_Called = 1; + + for (i = last_erased; (i <= LAST_BT_ID) && + (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + + FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) && + ((ftl_cmd_cnt + 28)) < 256; i++) { + pba = pBTBlocksNode[i - FIRST_BT_ID]; + lba = FTL_Get_Block_Index(pba); + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection: pba %d, lba %d\n", + pba, lba); + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Entry: %d", pbt[lba]); + + if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[lba] & DISCARD_BLOCK)) { + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection_cdma: " + "Erasing Block tables present in block %d\n", + pba); + addr = FTL_Get_Physical_Block_Addr((u64)lba * + DeviceInfo.wBlockDataSize); + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[lba] &= (u32)(~DISCARD_BLOCK); + pbt[lba] |= (u32)(SPARE_BLOCK); + + p_BTableChangesDelta = + (struct BTableChangesDelta *) + g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt - 1; + p_BTableChangesDelta->BT_Index = lba; + p_BTableChangesDelta->BT_Entry_Value = + pbt[lba]; + + p_BTableChangesDelta->ValidFields = 0x0C; + + ret = PASS; + pBTBlocksNode[last_erased - FIRST_BT_ID] = + BTBLOCK_INVAL; + nand_dbg_print(NAND_DBG_DEBUG, + "resetting bt entry at index %d " + "value %d\n", i, + pBTBlocksNode[i - FIRST_BT_ID]); + if (last_erased == LAST_BT_ID) + last_erased = FIRST_BT_ID; + else + last_erased++; + } else { + MARK_BLOCK_AS_BAD(pbt[lba]); + } + } + } + + BT_GC_Called = 0; + + return ret; +} + +#else +static int do_bt_garbage_collection(void) +{ + u32 pba, lba; + u32 *pbt = (u32 *)g_pBlockTable; + u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; + u64 addr; + int i, ret = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (BT_GC_Called) + return PASS; + + BT_GC_Called = 1; + + for (i = last_erased; (i <= LAST_BT_ID) && + (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + + FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) { + pba = pBTBlocksNode[i - FIRST_BT_ID]; + lba = FTL_Get_Block_Index(pba); + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection_cdma: pba %d, lba %d\n", + pba, lba); + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Entry: %d", pbt[lba]); + + if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && + (pbt[lba] & DISCARD_BLOCK)) { + nand_dbg_print(NAND_DBG_DEBUG, + "do_bt_garbage_collection: " + "Erasing Block tables present in block %d\n", + pba); + addr = FTL_Get_Physical_Block_Addr((u64)lba * + DeviceInfo.wBlockDataSize); + if (PASS == GLOB_FTL_Block_Erase(addr)) { + pbt[lba] &= (u32)(~DISCARD_BLOCK); + pbt[lba] |= (u32)(SPARE_BLOCK); + ret = PASS; + pBTBlocksNode[last_erased - FIRST_BT_ID] = + BTBLOCK_INVAL; + nand_dbg_print(NAND_DBG_DEBUG, + "resetting bt entry at index %d " + "value %d\n", i, + pBTBlocksNode[i - FIRST_BT_ID]); + if (last_erased == LAST_BT_ID) + last_erased = FIRST_BT_ID; + else + last_erased++; + } else { + MARK_BLOCK_AS_BAD(pbt[lba]); + } + } + } + + BT_GC_Called = 0; + + return ret; +} + +#endif + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_BT_Garbage_Collection +* Inputs: none +* Outputs: PASS / FAIL (returns the number of un-erased blocks +* Description: Erases discarded blocks containing Block table +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_BT_Garbage_Collection(void) +{ + return do_bt_garbage_collection(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_OneBlock +* Inputs: Block number 1 +* Block number 2 +* Outputs: Replaced Block Number +* Description: Interchange block table entries at wBlockNum and wReplaceNum +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk) +{ + u32 tmp_blk; + u32 replace_node = BAD_BLOCK; + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (rep_blk != BAD_BLOCK) { + if (IS_BAD_BLOCK(blk)) + tmp_blk = pbt[blk]; + else + tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]); + + replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]); + pbt[blk] = replace_node; + pbt[rep_blk] = tmp_blk; + +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[blk]; + + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = rep_blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + } + + return replace_node; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_Block_Table_Data +* Inputs: Block table size in pages +* Outputs: PASS=0 / FAIL=1 +* Description: Write block table data in flash +* If first page and last page +* Write data+BT flag +* else +* Write data +* BT flag is a counter. Its value is incremented for block table +* write in a new Block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Write_Block_Table_Data(void) +{ + u64 dwBlockTableAddr, pTempAddr; + u32 Block; + u16 Page, PageCount; + u8 *tempBuf = tmp_buf_write_blk_table_data; + int wBytesCopied; + u16 bt_pages; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dwBlockTableAddr = + (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize + + (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize); + pTempAddr = dwBlockTableAddr; + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: " + "page= %d BlockTableIndex= %d " + "BlockTableOffset=%d\n", bt_pages, + g_wBlockTableIndex, g_wBlockTableOffset); + + Block = BLK_FROM_ADDR(pTempAddr); + Page = PAGE_FROM_ADDR(pTempAddr, Block); + PageCount = 1; + + if (bt_block_changed) { + if (bt_flag == LAST_BT_ID) { + bt_flag = FIRST_BT_ID; + g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; + } else if (bt_flag < LAST_BT_ID) { + bt_flag++; + g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; + } + + if ((bt_flag > (LAST_BT_ID-4)) && + g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != + BTBLOCK_INVAL) { + bt_block_changed = 0; + GLOB_FTL_BT_Garbage_Collection(); + } + + bt_block_changed = 0; + nand_dbg_print(NAND_DBG_DEBUG, + "Block Table Counter is %u Block %u\n", + bt_flag, (unsigned int)Block); + } + + memset(tempBuf, 0, 3); + tempBuf[3] = bt_flag; + wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4, + DeviceInfo.wPageDataSize - 4, 0); + memset(&tempBuf[wBytesCopied + 4], 0xff, + DeviceInfo.wPageSize - (wBytesCopied + 4)); + FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize], + bt_flag); + +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + DeviceInfo.wPageSize * sizeof(u8)); + nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table " + "Block %u Page %u\n", (unsigned int)Block, Page); + if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable, + Block, Page, 1, + LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) { + nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } + + ftl_cmd_cnt++; + g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8))); +#else + if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } +#endif + + if (bt_pages > 1) { + PageCount = bt_pages - 1; + if (PageCount > 1) { + wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf, + DeviceInfo.wPageDataSize * (PageCount - 1), + wBytesCopied); + +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + (PageCount - 1) * DeviceInfo.wPageDataSize); + if (FAIL == GLOB_LLD_Write_Page_Main_cdma( + g_pNextBlockTable, Block, Page + 1, + PageCount - 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)Block); + goto func_return; + } + + ftl_cmd_cnt++; + g_pNextBlockTable += (PageCount - 1) * + DeviceInfo.wPageDataSize * sizeof(u8); +#else + if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf, + Block, Page + 1, PageCount - 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)Block); + goto func_return; + } +#endif + } + + wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf, + DeviceInfo.wPageDataSize, wBytesCopied); + memset(&tempBuf[wBytesCopied], 0xff, + DeviceInfo.wPageSize-wBytesCopied); + FTL_Insert_Block_Table_Signature( + &tempBuf[DeviceInfo.wPageDataSize], bt_flag); +#if CMD_DMA + memcpy(g_pNextBlockTable, tempBuf, + DeviceInfo.wPageSize * sizeof(u8)); + nand_dbg_print(NAND_DBG_DEBUG, + "Writing the last Page of Block Table " + "Block %u Page %u\n", + (unsigned int)Block, Page + bt_pages - 1); + if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma( + g_pNextBlockTable, Block, Page + bt_pages - 1, 1, + LLD_CMD_FLAG_MODE_CDMA | + LLD_CMD_FLAG_ORDER_BEFORE_REST)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } + ftl_cmd_cnt++; +#else + if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, + Block, Page+bt_pages - 1, 1)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, " + "new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, Block); + goto func_return; + } +#endif + } + + nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n"); + +func_return: + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_Block_Table +* Inputs: None +* Outputs: PASS=0 / FAIL=1 +* Description: Get a new block to write block table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_Block_Table(void) +{ + u32 blk; + int gc; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); + + if ((BAD_BLOCK == blk) && (PASS == gc)) { + GLOB_FTL_Garbage_Collection(); + blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); + } + if (BAD_BLOCK == blk) + printk(KERN_ERR "%s, %s: There is no spare block. " + "It should never happen\n", + __FILE__, __func__); + + nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk); + + return blk; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_LWBlock +* Inputs: Block number +* Pointer to Garbage Collect flag +* Outputs: +* Description: Determine the least weared block by traversing +* block table +* Set Garbage collection to be called if number of spare +* block is less than Free Block Gate count +* Change Block table entry to map least worn block for current +* operation +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 wLeastWornCounter = 0xFF; + u32 wLeastWornIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + u32 wDiscardBlockNum = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (IS_SPARE_BLOCK(wBlockNum)) { + *pGarbageCollect = FAIL; + pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK)); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = (u32)(wBlockNum); + p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; + p_BTableChangesDelta->ValidFields = 0x0C; +#endif + return pbt[wBlockNum]; + } + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_DISCARDED_BLOCK(i)) + wDiscardBlockNum++; + + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]); + if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock) + printk(KERN_ERR "FTL_Replace_LWBlock: " + "This should never occur!\n"); + if (g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] < + wLeastWornCounter) { + wLeastWornCounter = + g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wLeastWornIndex = i; + } + wSpareBlockNum++; + } + } + + nand_dbg_print(NAND_DBG_WARN, + "FTL_Replace_LWBlock: Least Worn Counter %d\n", + (int)wLeastWornCounter); + + if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) || + (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE)) + *pGarbageCollect = PASS; + else + *pGarbageCollect = FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, + "FTL_Replace_LWBlock: Discarded Blocks %u Spare" + " Blocks %u\n", + (unsigned int)wDiscardBlockNum, + (unsigned int)wSpareBlockNum); + + return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_MWBlock +* Inputs: None +* Outputs: most worn spare block no./BAD_BLOCK +* Description: It finds most worn spare block. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static u32 FTL_Replace_MWBlock(void) +{ + u32 i; + u32 *pbt = (u32 *)g_pBlockTable; + u8 wMostWornCounter = 0; + u32 wMostWornIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]); + if (g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] > + wMostWornCounter) { + wMostWornCounter = + g_pWearCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wMostWornIndex = wPhysicalIndex; + } + wSpareBlockNum++; + } + } + + if (wSpareBlockNum <= 2) + return BAD_BLOCK; + + return wMostWornIndex; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Replace_Block +* Inputs: Block Address +* Outputs: PASS=0 / FAIL=1 +* Description: If block specified by blk_addr parameter is not free, +* replace it with the least worn block. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Replace_Block(u64 blk_addr) +{ + u32 current_blk = BLK_FROM_ADDR(blk_addr); + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + int GarbageCollect = FAIL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (IS_SPARE_BLOCK(current_blk)) { + pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk]; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = current_blk; + p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk]; + p_BTableChangesDelta->ValidFields = 0x0C ; +#endif + return wResult; + } + + FTL_Replace_LWBlock(current_blk, &GarbageCollect); + + if (PASS == GarbageCollect) + wResult = GLOB_FTL_Garbage_Collection(); + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Is_BadBlock +* Inputs: block number to test +* Outputs: PASS (block is BAD) / FAIL (block is not bad) +* Description: test if this block number is flagged as bad +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Is_BadBlock(u32 wBlockNum) +{ + u32 *pbt = (u32 *)g_pBlockTable; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (wBlockNum >= DeviceInfo.wSpectraStartBlock + && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK)) + return PASS; + else + return FAIL; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Flush_Cache +* Inputs: none +* Outputs: PASS=0 / FAIL=1 +* Description: flush all the cache blocks to flash +* if a cache block is not dirty, don't do anything with it +* else, write the block and update the block table +* Note: This function should be called at shutdown/power down. +* to write important data into device +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Flush_Cache(void) +{ + int i, ret; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < CACHE_ITEM_NUM; i++) { + if (SET == Cache.array[i].changed) { +#if CMD_DMA +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE + int_cache[ftl_cmd_cnt].item = i; + int_cache[ftl_cmd_cnt].cache.address = + Cache.array[i].address; + int_cache[ftl_cmd_cnt].cache.changed = CLEAR; +#endif +#endif + ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address); + if (PASS == ret) { + Cache.array[i].changed = CLEAR; + } else { + printk(KERN_ALERT "Failed when write back to L2 cache!\n"); + /* TODO - How to handle this? */ + } + } + } + + flush_l2_cache(); + + return FTL_Write_Block_Table(FAIL); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Page_Read +* Inputs: pointer to data +* logical address of data (u64 is LBA * Bytes/Page) +* Outputs: PASS=0 / FAIL=1 +* Description: reads a page of data into RAM from the cache +* if the data is not already in cache, read from flash to cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr) +{ + u16 cache_item; + int res = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - " + "page_addr: %llu\n", logical_addr); + + cache_item = FTL_Cache_If_Hit(logical_addr); + + if (UNHIT_CACHE_ITEM == cache_item) { + nand_dbg_print(NAND_DBG_DEBUG, + "GLOB_FTL_Page_Read: Cache not hit\n"); + res = FTL_Cache_Write(); + if (ERR == FTL_Cache_Read(logical_addr)) + res = ERR; + cache_item = Cache.LRU; + } + + FTL_Cache_Read_Page(data, logical_addr, cache_item); + + return res; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Page_Write +* Inputs: pointer to data +* address of data (ADDRESSTYPE is LBA * Bytes/Page) +* Outputs: PASS=0 / FAIL=1 +* Description: writes a page of data from RAM to the cache +* if the data is not already in cache, write back the +* least recently used block and read the addressed block +* from flash to cache +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr) +{ + u16 cache_blk; + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - " + "dwPageAddr: %llu\n", dwPageAddr); + + cache_blk = FTL_Cache_If_Hit(dwPageAddr); + + if (UNHIT_CACHE_ITEM == cache_blk) { + wResult = FTL_Cache_Write(); + if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) { + wResult = FTL_Replace_Block(dwPageAddr); + pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK; + if (wResult == FAIL) + return FAIL; + } + if (ERR == FTL_Cache_Read(dwPageAddr)) + wResult = ERR; + cache_blk = Cache.LRU; + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); + } else { +#if CMD_DMA + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, + LLD_CMD_FLAG_ORDER_BEFORE_REST); +#else + FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); +#endif + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: GLOB_FTL_Block_Erase +* Inputs: address of block to erase (now in byte format, should change to +* block format) +* Outputs: PASS=0 / FAIL=1 +* Description: erases the specified block +* increments the erase count +* If erase count reaches its upper limit,call function to +* do the ajustment as per the relative erase count values +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int GLOB_FTL_Block_Erase(u64 blk_addr) +{ + int status; + u32 BlkIdx; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize); + + if (BlkIdx < DeviceInfo.wSpectraStartBlock) { + printk(KERN_ERR "GLOB_FTL_Block_Erase: " + "This should never occur\n"); + return FAIL; + } + +#if CMD_DMA + status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA); + if (status == FAIL) + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, BlkIdx); +#else + status = GLOB_LLD_Erase_Block(BlkIdx); + if (status == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, BlkIdx); + return status; + } +#endif + + if (DeviceInfo.MLCDevice) { + g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0; + if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } + } + + g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++; + +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = + BlkIdx - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; + + if (DeviceInfo.MLCDevice) { + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->RC_Index = + BlkIdx - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->RC_Entry_Value = + g_pReadCounter[BlkIdx - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0xC0; + } + + ftl_cmd_cnt++; +#endif + + if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE) + FTL_Adjust_Relative_Erase_Count(BlkIdx); + + return status; +} + + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Adjust_Relative_Erase_Count +* Inputs: index to block that was just incremented and is at the max +* Outputs: PASS=0 / FAIL=1 +* Description: If any erase counts at MAX, adjusts erase count of every +* block by substracting least worn +* counter from counter value of every entry in wear table +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX) +{ + u8 wLeastWornCounter = MAX_BYTE_VALUE; + u8 wWearCounter; + u32 i, wWearIndex; + u32 *pbt = (u32 *)g_pBlockTable; + int wResult = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_BAD_BLOCK(i)) + continue; + wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); + + if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0) + printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:" + "This should never occur\n"); + wWearCounter = g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock]; + if (wWearCounter < wLeastWornCounter) + wLeastWornCounter = wWearCounter; + } + + if (wLeastWornCounter == 0) { + nand_dbg_print(NAND_DBG_WARN, + "Adjusting Wear Levelling Counters: Special Case\n"); + g_pWearCounter[Index_of_MAX - + DeviceInfo.wSpectraStartBlock]--; +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = + Index_of_MAX - DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[Index_of_MAX - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; +#endif + FTL_Static_Wear_Leveling(); + } else { + for (i = 0; i < DeviceInfo.wDataBlockNum; i++) + if (!IS_BAD_BLOCK(i)) { + wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); + g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock] = + (u8)(g_pWearCounter + [wWearIndex - + DeviceInfo.wSpectraStartBlock] - + wLeastWornCounter); +#if CMD_DMA + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += + sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->WC_Index = wWearIndex - + DeviceInfo.wSpectraStartBlock; + p_BTableChangesDelta->WC_Entry_Value = + g_pWearCounter[wWearIndex - + DeviceInfo.wSpectraStartBlock]; + p_BTableChangesDelta->ValidFields = 0x30; +#endif + } + } + + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Write_IN_Progress_Block_Table_Page +* Inputs: None +* Outputs: None +* Description: It writes in-progress flag page to the page next to +* block table +***********************************************************************/ +static int FTL_Write_IN_Progress_Block_Table_Page(void) +{ + int wResult = PASS; + u16 bt_pages; + u16 dwIPFPageAddr; +#if CMD_DMA +#else + u32 *pbt = (u32 *)g_pBlockTable; + u32 wTempBlockTableIndex; +#endif + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); + + dwIPFPageAddr = g_wBlockTableOffset + bt_pages; + + nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at " + "Block %d Page %d\n", + g_wBlockTableIndex, dwIPFPageAddr); + +#if CMD_DMA + wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF, + g_wBlockTableIndex, dwIPFPageAddr, 1, + LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + g_wBlockTableIndex); + } + g_wBlockTableOffset = dwIPFPageAddr + 1; + p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; + p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset; + p_BTableChangesDelta->ValidFields = 0x01; + ftl_cmd_cnt++; +#else + wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF, + g_wBlockTableIndex, dwIPFPageAddr, 1); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in %s, Line %d, " + "Function: %s, new Bad Block %d generated!\n", + __FILE__, __LINE__, __func__, + (int)g_wBlockTableIndex); + MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); + wTempBlockTableIndex = FTL_Replace_Block_Table(); + bt_block_changed = 1; + if (BAD_BLOCK == wTempBlockTableIndex) + return ERR; + g_wBlockTableIndex = wTempBlockTableIndex; + g_wBlockTableOffset = 0; + /* Block table tag is '00'. Means it's used one */ + pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; + return FAIL; + } + g_wBlockTableOffset = dwIPFPageAddr + 1; +#endif + return wResult; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: FTL_Read_Disturbance +* Inputs: block address +* Outputs: PASS=0 / FAIL=1 +* Description: used to handle read disturbance. Data in block that +* reaches its read limit is moved to new block +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int FTL_Read_Disturbance(u32 blk_addr) +{ + int wResult = FAIL; + u32 *pbt = (u32 *) g_pBlockTable; + u32 dwOldBlockAddr = blk_addr; + u32 wBlockNum; + u32 i; + u32 wLeastReadCounter = 0xFFFF; + u32 wLeastReadIndex = BAD_BLOCK; + u32 wSpareBlockNum = 0; + u32 wTempNode; + u32 wReplacedNode; + u8 *g_pTempBuf; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#if CMD_DMA + g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx]; + cp_back_buf_idx++; + if (cp_back_buf_idx > COPY_BACK_BUF_NUM) { + printk(KERN_ERR "cp_back_buf_copies overflow! Exit." + "Maybe too many pending commands in your CDMA chain.\n"); + return FAIL; + } +#else + g_pTempBuf = tmp_buf_read_disturbance; +#endif + + wBlockNum = FTL_Get_Block_Index(blk_addr); + + do { + /* This is a bug.Here 'i' should be logical block number + * and start from 1 (0 is reserved for block table). + * Have fixed it. - Yunpeng 2008. 12. 19 + */ + for (i = 1; i < DeviceInfo.wDataBlockNum; i++) { + if (IS_SPARE_BLOCK(i)) { + u32 wPhysicalIndex = + (u32)((~SPARE_BLOCK) & pbt[i]); + if (g_pReadCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock] < + wLeastReadCounter) { + wLeastReadCounter = + g_pReadCounter[wPhysicalIndex - + DeviceInfo.wSpectraStartBlock]; + wLeastReadIndex = i; + } + wSpareBlockNum++; + } + } + + if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) { + wResult = GLOB_FTL_Garbage_Collection(); + if (PASS == wResult) + continue; + else + break; + } else { + wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]); + wReplacedNode = (u32)((~SPARE_BLOCK) & + pbt[wLeastReadIndex]); +#if CMD_DMA + pbt[wBlockNum] = wReplacedNode; + pbt[wLeastReadIndex] = wTempNode; + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = wBlockNum; + p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; + p_BTableChangesDelta->ValidFields = 0x0C; + + p_BTableChangesDelta = + (struct BTableChangesDelta *)g_pBTDelta_Free; + g_pBTDelta_Free += sizeof(struct BTableChangesDelta); + + p_BTableChangesDelta->ftl_cmd_cnt = + ftl_cmd_cnt; + p_BTableChangesDelta->BT_Index = wLeastReadIndex; + p_BTableChangesDelta->BT_Entry_Value = + pbt[wLeastReadIndex]; + p_BTableChangesDelta->ValidFields = 0x0C; + + wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf, + dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock, + LLD_CMD_FLAG_MODE_CDMA); + if (wResult == FAIL) + return wResult; + + ftl_cmd_cnt++; + + if (wResult != FAIL) { + if (FAIL == GLOB_LLD_Write_Page_Main_cdma( + g_pTempBuf, pbt[wBlockNum], 0, + DeviceInfo.wPagesPerBlock)) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)pbt[wBlockNum]); + wResult = FAIL; + MARK_BLOCK_AS_BAD(pbt[wBlockNum]); + } + ftl_cmd_cnt++; + } +#else + wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf, + dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock); + if (wResult == FAIL) + return wResult; + + if (wResult != FAIL) { + /* This is a bug. At this time, pbt[wBlockNum] + is still the physical address of + discard block, and should not be write. + Have fixed it as below. + -- Yunpeng 2008.12.19 + */ + wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf, + wReplacedNode, 0, + DeviceInfo.wPagesPerBlock); + if (wResult == FAIL) { + nand_dbg_print(NAND_DBG_WARN, + "NAND Program fail in " + "%s, Line %d, Function: %s, " + "new Bad Block %d " + "generated!\n", + __FILE__, __LINE__, __func__, + (int)wReplacedNode); + MARK_BLOCK_AS_BAD(wReplacedNode); + } else { + pbt[wBlockNum] = wReplacedNode; + pbt[wLeastReadIndex] = wTempNode; + } + } + + if ((wResult == PASS) && (g_cBlockTableStatus != + IN_PROGRESS_BLOCK_TABLE)) { + g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; + FTL_Write_IN_Progress_Block_Table_Page(); + } +#endif + } + } while (wResult != PASS) + ; + +#if CMD_DMA + /* ... */ +#endif + + return wResult; +} + diff --git a/drivers/staging/spectra/flash.h b/drivers/staging/spectra/flash.h new file mode 100644 index 000000000000..5ed05805cf65 --- /dev/null +++ b/drivers/staging/spectra/flash.h @@ -0,0 +1,198 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FLASH_INTERFACE_ +#define _FLASH_INTERFACE_ + +#include "ffsport.h" +#include "spectraswconfig.h" + +#define MAX_BYTE_VALUE 0xFF +#define MAX_WORD_VALUE 0xFFFF +#define MAX_U32_VALUE 0xFFFFFFFF + +#define MAX_BLOCKNODE_VALUE 0xFFFFFF +#define DISCARD_BLOCK 0x800000 +#define SPARE_BLOCK 0x400000 +#define BAD_BLOCK 0xC00000 + +#define UNHIT_CACHE_ITEM 0xFFFF + +#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL + +#define IN_PROGRESS_BLOCK_TABLE 0x00 +#define CURRENT_BLOCK_TABLE 0x01 + +#define BTSIG_OFFSET (0) +#define BTSIG_BYTES (5) +#define BTSIG_DELTA (3) + +#define MAX_READ_COUNTER 0x2710 + +#define FIRST_BT_ID (1) +#define LAST_BT_ID (254) +#define BTBLOCK_INVAL (u32)(0xFFFFFFFF) + +struct device_info_tag { + u16 wDeviceMaker; + u16 wDeviceID; + u32 wDeviceType; + u32 wSpectraStartBlock; + u32 wSpectraEndBlock; + u32 wTotalBlocks; + u16 wPagesPerBlock; + u16 wPageSize; + u16 wPageDataSize; + u16 wPageSpareSize; + u16 wNumPageSpareFlag; + u16 wECCBytesPerSector; + u32 wBlockSize; + u32 wBlockDataSize; + u32 wDataBlockNum; + u8 bPlaneNum; + u16 wDeviceMainAreaSize; + u16 wDeviceSpareAreaSize; + u16 wDevicesConnected; + u16 wDeviceWidth; + u16 wHWRevision; + u16 wHWFeatures; + + u16 wONFIDevFeatures; + u16 wONFIOptCommands; + u16 wONFITimingMode; + u16 wONFIPgmCacheTimingMode; + + u16 MLCDevice; + u16 wSpareSkipBytes; + + u8 nBitsInPageNumber; + u8 nBitsInPageDataSize; + u8 nBitsInBlockDataSize; +}; + +extern struct device_info_tag DeviceInfo; + +/* Cache item format */ +struct flash_cache_item_tag { + u64 address; + u16 use_cnt; + u16 changed; + u8 *buf; +}; + +struct flash_cache_tag { + u32 cache_item_size; /* Size in bytes of each cache item */ + u16 pages_per_item; /* How many NAND pages in each cache item */ + u16 LRU; /* No. of the least recently used cache item */ + struct flash_cache_item_tag array[CACHE_ITEM_NUM]; +}; + +/* + *Data structure for each list node of the managment table + * used for the Level 2 Cache. Each node maps one logical NAND block. + */ +struct spectra_l2_cache_list { + struct list_head list; + u32 logical_blk_num; /* Logical block number */ + u32 pages_array[]; /* Page map array of this logical block. + * Array index is the logical block number, + * and for every item of this arry: + * high 16 bit is index of the L2 cache block num, + * low 16 bit is the phy page num + * of the above L2 cache block. + * This array will be kmalloc during run time. + */ +}; + +struct spectra_l2_cache_info { + u32 blk_array[BLK_NUM_FOR_L2_CACHE]; + u16 cur_blk_idx; /* idx to the phy block number of current using */ + u16 cur_page_num; /* pages number of current using */ + struct spectra_l2_cache_list table; /* First node of the table */ +}; + +#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1 + +#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE +struct flash_cache_mod_item_tag { + u64 address; + u8 changed; +}; + +struct flash_cache_delta_list_tag { + u8 item; /* used cache item */ + struct flash_cache_mod_item_tag cache; +}; +#endif + +extern struct flash_cache_tag Cache; + +extern u8 *buf_read_page_main_spare; +extern u8 *buf_write_page_main_spare; +extern u8 *buf_read_page_spare; +extern u8 *buf_get_bad_block; +extern u8 *cdma_desc_buf; +extern u8 *memcp_desc_buf; + +/* struture used for IndentfyDevice function */ +struct spectra_indentfy_dev_tag { + u32 NumBlocks; + u16 PagesPerBlock; + u16 PageDataSize; + u16 wECCBytesPerSector; + u32 wDataBlockNum; +}; + +int GLOB_FTL_Flash_Init(void); +int GLOB_FTL_Flash_Release(void); +/*void GLOB_FTL_Erase_Flash(void);*/ +int GLOB_FTL_Block_Erase(u64 block_addr); +int GLOB_FTL_Is_BadBlock(u32 block_num); +int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data); +int GLOB_FTL_Event_Status(int *); +u16 glob_ftl_execute_cmds(void); + +/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/ +int FTL_Read_Disturbance(u32 dwBlockAddr); + +/*Flash r/w based on cache*/ +int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr); +int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr); +int GLOB_FTL_Wear_Leveling(void); +int GLOB_FTL_Flash_Format(void); +int GLOB_FTL_Init(void); +int GLOB_FTL_Flush_Cache(void); +int GLOB_FTL_Garbage_Collection(void); +int GLOB_FTL_BT_Garbage_Collection(void); +void GLOB_FTL_Cache_Release(void); +u8 *get_blk_table_start_addr(void); +u8 *get_wear_leveling_table_start_addr(void); +unsigned long get_blk_table_len(void); +unsigned long get_wear_leveling_table_len(void); + +#if DEBUG_BNDRY +void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno, + char *filename); +#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\ + limit, no, __LINE__, __FILE__) +#else +#define debug_boundary_error(chnl, limit, no) ; +#endif + +#endif /*_FLASH_INTERFACE_*/ diff --git a/drivers/staging/spectra/lld.c b/drivers/staging/spectra/lld.c new file mode 100644 index 000000000000..5c3b9762dc3e --- /dev/null +++ b/drivers/staging/spectra/lld.c @@ -0,0 +1,339 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "spectraswconfig.h" +#include "ffsport.h" +#include "ffsdefs.h" +#include "lld.h" +#include "lld_nand.h" + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */ +#include "lld_emu.h" +#include "lld_cdma.h" + +/* common functions: */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return emu_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return emu_Read_Device_ID(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return emu_Flash_Release(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return emu_Flash_Init(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return emu_Erase_Block(block_add); +} + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Read_Page_Main(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return emu_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 Page, u16 PageCount) +{ + return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return emu_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return emu_Get_Bad_Block(block); +} + +#endif /* FLASH_EMU */ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */ +#include "lld_mtd.h" +#include "lld_cdma.h" + +/* common functions: */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return mtd_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return mtd_Read_Device_ID(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return mtd_Flash_Release(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return mtd_Flash_Init(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return mtd_Erase_Block(block_add); +} + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Read_Page_Main(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return mtd_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 Page, u16 PageCount) +{ + return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return mtd_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return mtd_Get_Bad_Block(block); +} + +#endif /* FLASH_MTD */ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */ +#include "lld_nand.h" +#include "lld_cdma.h" +#include "flash.h" + +/* common functions for LLD_NAND */ +void GLOB_LLD_ECC_Control(int enable) +{ + NAND_ECC_Ctrl(enable); +} + +/* common functions for LLD_NAND */ +u16 GLOB_LLD_Flash_Reset(void) +{ + return NAND_Flash_Reset(); +} + +u16 GLOB_LLD_Read_Device_ID(void) +{ + return NAND_Read_Device_ID(); +} + +u16 GLOB_LLD_UnlockArrayAll(void) +{ + return NAND_UnlockArrayAll(); +} + +u16 GLOB_LLD_Flash_Init(void) +{ + return NAND_Flash_Init(); +} + +int GLOB_LLD_Flash_Release(void) +{ + return nand_release_spectra(); +} + +u16 GLOB_LLD_Erase_Block(u32 block_add) +{ + return NAND_Erase_Block(block_add); +} + + +u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Write_Page_Main(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + if (page_count == 1) /* Using polling to improve read speed */ + return NAND_Read_Page_Main_Polling(read_data, block, page, 1); + else + return NAND_Read_Page_Main(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + return NAND_Read_Page_Main_Polling(read_data, + block, page, page_count); +} + +u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 Page, u16 PageCount) +{ + return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Write_Page_Spare(write_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, + u16 page, u16 page_count) +{ + return NAND_Read_Page_Main_Spare(read_data, block, page, page_count); +} + +u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, + u16 PageCount) +{ + return NAND_Read_Page_Spare(read_data, block, Page, PageCount); +} + +u16 GLOB_LLD_Get_Bad_Block(u32 block) +{ + return NAND_Get_Bad_Block(block); +} + +#if CMD_DMA +u16 GLOB_LLD_Event_Status(void) +{ + return CDMA_Event_Status(); +} + +u16 glob_lld_execute_cmds(void) +{ + return CDMA_Execute_CMDs(); +} + +u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, + u32 ByteCount, u16 flag) +{ + /* Replace the hardware memcopy with software memcpy function */ + if (CDMA_Execute_CMDs()) + return FAIL; + memcpy(dest, src, ByteCount); + return PASS; + + /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */ +} + +u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags) +{ + return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags); +} + +u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count) +{ + return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0); +} + +u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page, + u16 count, u16 flags) +{ + return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags); +} + +u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page, + u16 count, u16 flags) +{ + return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD, + data, block, page, count, flags); +} + +u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count) +{ + return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count, + LLD_CMD_FLAG_MODE_CDMA); +} + +#endif /* CMD_DMA */ +#endif /* FLASH_NAND */ + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +/* end of LLD.c */ diff --git a/drivers/staging/spectra/lld.h b/drivers/staging/spectra/lld.h new file mode 100644 index 000000000000..d3738e0e1fea --- /dev/null +++ b/drivers/staging/spectra/lld.h @@ -0,0 +1,111 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + + +#ifndef _LLD_ +#define _LLD_ + +#include "ffsport.h" +#include "spectraswconfig.h" +#include "flash.h" + +#define GOOD_BLOCK 0 +#define DEFECTIVE_BLOCK 1 +#define READ_ERROR 2 + +#define CLK_X 5 +#define CLK_MULTI 4 + +/* Typedefs */ + +/* prototypes: API for LLD */ +/* Currently, Write_Page_Main + * MemCopy + * Read_Page_Main_Spare + * do not have flag because they were not implemented prior to this + * They are not being added to keep changes to a minimum for now. + * Currently, they are not required (only reqd for Wr_P_M_S.) + * Later on, these NEED to be changed. + */ + +extern void GLOB_LLD_ECC_Control(int enable); + +extern u16 GLOB_LLD_Flash_Reset(void); + +extern u16 GLOB_LLD_Read_Device_ID(void); + +extern u16 GLOB_LLD_UnlockArrayAll(void); + +extern u16 GLOB_LLD_Flash_Init(void); + +extern int GLOB_LLD_Flash_Release(void); + +extern u16 GLOB_LLD_Erase_Block(u32 block_add); + +extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, + u32 block, u16 page, u16 page_count); + +extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, + u32 block, u16 Page, u16 PageCount); + +extern u16 GLOB_LLD_Get_Bad_Block(u32 block); + +extern u16 GLOB_LLD_Event_Status(void); + +extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag); + +extern u16 glob_lld_execute_cmds(void); + +extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags); + +extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, + u32 block, u16 page, u16 count); + +extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, + u32 block, u16 page, u16 count, u16 flags); + +extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count, u16 flags); + +extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, + u32 block, u16 page, u16 count); + +#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1) +#define LLD_CMD_FLAG_MODE_CDMA (0x8) + + +#endif /*_LLD_ */ + + diff --git a/drivers/staging/spectra/lld_cdma.c b/drivers/staging/spectra/lld_cdma.c new file mode 100644 index 000000000000..c6e76103d43c --- /dev/null +++ b/drivers/staging/spectra/lld_cdma.c @@ -0,0 +1,910 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include "spectraswconfig.h" +#include "lld.h" +#include "lld_nand.h" +#include "lld_cdma.h" +#include "lld_emu.h" +#include "flash.h" +#include "nand_regs.h" + +#define MAX_PENDING_CMDS 4 +#define MODE_02 (0x2 << 26) + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Data_Cmd +* Inputs: cmd code (aligned for hw) +* data: pointer to source or destination +* block: block address +* page: page address +* num: num pages to transfer +* Outputs: PASS +* Description: This function takes the parameters and puts them +* into the "pending commands" array. +* It does not parse or validate the parameters. +* The array index is same as the tag. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags) +{ + u8 bank; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (0 == cmd) + nand_dbg_print(NAND_DBG_DEBUG, + "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__); + + /* If a command of another bank comes, then first execute */ + /* pending commands of the current bank, then set the new */ + /* bank as current bank */ + bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + if (bank != info.flash_bank) { + nand_dbg_print(NAND_DBG_WARN, + "Will access new bank. old bank: %d, new bank: %d\n", + info.flash_bank, bank); + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + info.flash_bank = bank; + } + + info.pcmds[info.pcmds_num].CMD = cmd; + info.pcmds[info.pcmds_num].DataAddr = data; + info.pcmds[info.pcmds_num].Block = block; + info.pcmds[info.pcmds_num].Page = page; + info.pcmds[info.pcmds_num].PageCount = num; + info.pcmds[info.pcmds_num].DataDestAddr = 0; + info.pcmds[info.pcmds_num].DataSrcAddr = 0; + info.pcmds[info.pcmds_num].MemCopyByteCnt = 0; + info.pcmds[info.pcmds_num].Flags = flags; + info.pcmds[info.pcmds_num].Status = 0xB0B; + + switch (cmd) { + case WRITE_MAIN_SPARE_CMD: + Conv_Main_Spare_Data_Log2Phy_Format(data, num); + break; + case WRITE_SPARE_CMD: + Conv_Spare_Data_Log2Phy_Format(data); + break; + default: + break; + } + + info.pcmds_num++; + + if (info.pcmds_num >= MAX_PENDING_CMDS) { + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_MemCopy_CMD +* Inputs: dest: pointer to destination +* src: pointer to source +* count: num bytes to transfer +* Outputs: PASS +* Description: This function takes the parameters and puts them +* into the "pending commands" array. +* It does not parse or validate the parameters. +* The array index is same as the tag. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags) +{ + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD; + info.pcmds[info.pcmds_num].DataAddr = 0; + info.pcmds[info.pcmds_num].Block = 0; + info.pcmds[info.pcmds_num].Page = 0; + info.pcmds[info.pcmds_num].PageCount = 0; + info.pcmds[info.pcmds_num].DataDestAddr = dest; + info.pcmds[info.pcmds_num].DataSrcAddr = src; + info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt; + info.pcmds[info.pcmds_num].Flags = flags; + info.pcmds[info.pcmds_num].Status = 0xB0B; + + info.pcmds_num++; + + if (info.pcmds_num >= MAX_PENDING_CMDS) { + if (CDMA_Execute_CMDs()) { + printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); + return FAIL; + } + } + + return PASS; +} + +#if 0 +/* Prints the PendingCMDs array */ +void print_pending_cmds(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < info.pcmds_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + switch (info.pcmds[i].CMD) { + case ERASE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Erase Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case WRITE_MAIN_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Write Main Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case WRITE_MAIN_SPARE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Write Main Spare Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case READ_MAIN_SPARE_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Read Main Spare Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case READ_MAIN_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Read Main Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case MEMCOPY_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Memcopy Command (0x%x)\n", + info.pcmds[i].CMD); + break; + case DUMMY_CMD: + nand_dbg_print(NAND_DBG_DEBUG, + "Dummy Command (0x%x)\n", + info.pcmds[i].CMD); + break; + default: + nand_dbg_print(NAND_DBG_DEBUG, + "Illegal Command (0x%x)\n", + info.pcmds[i].CMD); + break; + } + + nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n", + (u32)info.pcmds[i].DataAddr); + nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n", + info.pcmds[i].Block); + nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n", + info.pcmds[i].Page); + nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n", + info.pcmds[i].PageCount); + nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n", + (u32)info.pcmds[i].DataDestAddr); + nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n", + (u32)info.pcmds[i].DataSrcAddr); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n", + info.pcmds[i].MemCopyByteCnt); + nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n", + info.pcmds[i].Flags); + nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n", + info.pcmds[i].Status); + } +} + +/* Print the CDMA descriptors */ +void print_cdma_descriptors(void) +{ + struct cdma_descriptor *pc; + int i; + + pc = (struct cdma_descriptor *)info.cdma_desc_buf; + + nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n"); + + for (i = 0; i < info.cdma_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + nand_dbg_print(NAND_DBG_DEBUG, + "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", + pc[i].NxtPointerHi, pc[i].NxtPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n", + pc[i].FlashPointerHi, pc[i].FlashPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n", + pc[i].CommandType); + nand_dbg_print(NAND_DBG_DEBUG, + "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n", + pc[i].MemAddrHi, pc[i].MemAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n", + pc[i].CommandFlags); + nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n", + pc[i].Channel, pc[i].Status); + nand_dbg_print(NAND_DBG_DEBUG, + "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n", + pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "Reserved12: 0x%x, Reserved13: 0x%x, " + "Reserved14: 0x%x, pcmd: %d\n", + pc[i].Reserved12, pc[i].Reserved13, + pc[i].Reserved14, pc[i].pcmd); + } +} + +/* Print the Memory copy descriptors */ +static void print_memcp_descriptors(void) +{ + struct memcpy_descriptor *pm; + int i; + + pm = (struct memcpy_descriptor *)info.memcp_desc_buf; + + nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n"); + + for (i = 0; i < info.cdma_num; i++) { + nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); + nand_dbg_print(NAND_DBG_DEBUG, + "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", + pm[i].NxtPointerHi, pm[i].NxtPointerLo); + nand_dbg_print(NAND_DBG_DEBUG, + "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n", + pm[i].SrcAddrHi, pm[i].SrcAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, + "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n", + pm[i].DestAddrHi, pm[i].DestAddrLo); + nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n", + pm[i].XferSize); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n", + pm[i].MemCopyFlags); + nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n", + pm[i].MemCopyStatus); + nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n", + pm[i].reserved9); + nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n", + pm[i].reserved10); + nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n", + pm[i].reserved11); + nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n", + pm[i].reserved12); + nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n", + pm[i].reserved13); + nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n", + pm[i].reserved14); + nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n", + pm[i].reserved15); + } +} +#endif + +/* Reset cdma_descriptor chain to 0 */ +static void reset_cdma_desc(int i) +{ + struct cdma_descriptor *ptr; + + BUG_ON(i >= MAX_DESCS); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + ptr[i].NxtPointerHi = 0; + ptr[i].NxtPointerLo = 0; + ptr[i].FlashPointerHi = 0; + ptr[i].FlashPointerLo = 0; + ptr[i].CommandType = 0; + ptr[i].MemAddrHi = 0; + ptr[i].MemAddrLo = 0; + ptr[i].CommandFlags = 0; + ptr[i].Channel = 0; + ptr[i].Status = 0; + ptr[i].MemCopyPointerHi = 0; + ptr[i].MemCopyPointerLo = 0; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_UpdateEventStatus +* Inputs: none +* Outputs: none +* Description: This function update the event status of all the channels +* when an error condition is reported. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void CDMA_UpdateEventStatus(void) +{ + int i, j, active_chan; + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (j = 0; j < info.cdma_num; j++) { + /* Check for the descriptor with failure */ + if ((ptr[j].Status & CMD_DMA_DESC_FAIL)) + break; + + } + + /* All the previous cmd's status for this channel must be good */ + for (i = 0; i < j; i++) { + if (ptr[i].pcmd != 0xff) + info.pcmds[ptr[i].pcmd].Status = CMD_PASS; + } + + /* Abort the channel with type 0 reset command. It resets the */ + /* selected channel after the descriptor completes the flash */ + /* operation and status has been updated for the descriptor. */ + /* Memory Copy and Sync associated with this descriptor will */ + /* not be executed */ + active_chan = ioread32(FlashReg + CHNL_ACTIVE); + if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) { + iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */ + iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10); + } else { /* Should not reached here */ + printk(KERN_ERR "Error! Used bank is not set in" + " reg CHNL_ACTIVE\n"); + } +} + +static void cdma_trans(u16 chan) +{ + u32 addr; + + addr = info.cdma_desc; + + iowrite32(MODE_10 | (chan << 24), FlashMem); + iowrite32((1 << 7) | chan, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8), + FlashMem); + iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem); + iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10); + + iowrite32(MODE_10 | (chan << 24), FlashMem); + iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs (for use with CMD_DMA) +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor +* for each pending command, start the CDMA engine, and return. +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Execute_CMDs(void) +{ + int i, ret; + u64 flash_add; + u32 ptr; + dma_addr_t map_addr, next_ptr; + u16 status = PASS; + u16 tmp_c; + struct cdma_descriptor *pc; + struct memcpy_descriptor *pm; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* No pending cmds to execute, just exit */ + if (0 == info.pcmds_num) { + nand_dbg_print(NAND_DBG_TRACE, + "No pending cmds to execute. Just exit.\n"); + return PASS; + } + + for (i = 0; i < MAX_DESCS; i++) + reset_cdma_desc(i); + + pc = (struct cdma_descriptor *)info.cdma_desc_buf; + pm = (struct memcpy_descriptor *)info.memcp_desc_buf; + + info.cdma_desc = virt_to_bus(info.cdma_desc_buf); + info.memcp_desc = virt_to_bus(info.memcp_desc_buf); + next_ptr = info.cdma_desc; + info.cdma_num = 0; + + for (i = 0; i < info.pcmds_num; i++) { + if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) { + info.pcmds[i].Status = CMD_NOT_DONE; + continue; + } + + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + + /* Use the Block offset within a bank */ + tmp_c = info.pcmds[i].Block / + (DeviceInfo.wTotalBlocks / totalUsedBanks); + flash_add = (u64)(info.pcmds[i].Block - tmp_c * + (DeviceInfo.wTotalBlocks / totalUsedBanks)) * + DeviceInfo.wBlockDataSize + + (u64)(info.pcmds[i].Page) * + DeviceInfo.wPageDataSize; + + ptr = MODE_10 | (info.flash_bank << 24) | + (u32)GLOB_u64_Div(flash_add, + DeviceInfo.wPageDataSize); + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + + if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || + (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { + /* Descriptor to set Main+Spare Access Mode */ + pc[info.cdma_num].CommandType = 0x43; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + reset_cdma_desc(info.cdma_num); + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + } + + switch (info.pcmds[i].CMD) { + case ERASE_CMD: + pc[info.cdma_num].CommandType = 1; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + break; + + case WRITE_MAIN_CMD: + pc[info.cdma_num].CommandType = + 0x2100 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case READ_MAIN_CMD: + pc[info.cdma_num].CommandType = + 0x2000 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case WRITE_MAIN_SPARE_CMD: + pc[info.cdma_num].CommandType = + 0x2100 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case READ_MAIN_SPARE_CMD: + pc[info.cdma_num].CommandType = + 0x2000 | info.pcmds[i].PageCount; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + map_addr = virt_to_bus(info.pcmds[i].DataAddr); + pc[info.cdma_num].MemAddrHi = map_addr >> 16; + pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; + break; + + case MEMCOPY_CMD: + pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */ + /* Set bit 11 to let the CDMA engine continue to */ + /* execute only after it has finished processing */ + /* the memcopy descriptor. */ + /* Also set bit 10 and bit 9 to 1 */ + pc[info.cdma_num].CommandFlags = 0x0E40; + map_addr = info.memcp_desc + info.cdma_num * + sizeof(struct memcpy_descriptor); + pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16; + pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff; + + pm[info.cdma_num].NxtPointerHi = 0; + pm[info.cdma_num].NxtPointerLo = 0; + + map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr); + pm[info.cdma_num].SrcAddrHi = map_addr >> 16; + pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff; + map_addr = virt_to_bus(info.pcmds[i].DataDestAddr); + pm[info.cdma_num].DestAddrHi = map_addr >> 16; + pm[info.cdma_num].DestAddrLo = map_addr & 0xffff; + + pm[info.cdma_num].XferSize = + info.pcmds[i].MemCopyByteCnt; + pm[info.cdma_num].MemCopyFlags = + (0 << 15 | 0 << 14 | 27 << 8 | 0x40); + pm[info.cdma_num].MemCopyStatus = 0; + break; + + case DUMMY_CMD: + default: + pc[info.cdma_num].CommandType = 0XFFFF; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + break; + } + + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || + (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { + /* Descriptor to set back Main Area Access Mode */ + reset_cdma_desc(info.cdma_num); + next_ptr += sizeof(struct cdma_descriptor); + pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; + pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; + + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + + pc[info.cdma_num].CommandType = 0x42; + pc[info.cdma_num].CommandFlags = + (0 << 10) | (1 << 9) | (0 << 8) | 0x40; + pc[info.cdma_num].MemAddrHi = 0; + pc[info.cdma_num].MemAddrLo = 0; + + pc[info.cdma_num].Channel = 0; + pc[info.cdma_num].Status = 0; + pc[info.cdma_num].pcmd = i; + + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + } + } + + /* Add a dummy descriptor at end of the CDMA chain */ + reset_cdma_desc(info.cdma_num); + ptr = MODE_10 | (info.flash_bank << 24); + pc[info.cdma_num].FlashPointerHi = ptr >> 16; + pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; + pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */ + /* Set Command Flags for the last CDMA descriptor: */ + /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */ + pc[info.cdma_num].CommandFlags = + (0 << 10) | (0 << 9) | (1 << 8) | 0x40; + pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */ + info.cdma_num++; + BUG_ON(info.cdma_num >= MAX_DESCS); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + iowrite32(1, FlashReg + DMA_ENABLE); + /* Wait for DMA to be enabled before issuing the next command */ + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + cdma_trans(info.flash_bank); + + ret = wait_for_completion_timeout(&info.complete, 50 * HZ); + if (!ret) + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = info.ret; + + info.pcmds_num = 0; /* Clear the pending cmds number to 0 */ + + return status; +} + +int is_cdma_interrupt(void) +{ + u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma; + u32 int_en_mask; + u32 cdma_int_en_mask; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + /* Set the global Enable masks for only those interrupts + * that are supported */ + cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | + DMA_INTR__DESC_COMP_CHANNEL1 | + DMA_INTR__DESC_COMP_CHANNEL2 | + DMA_INTR__DESC_COMP_CHANNEL3 | + DMA_INTR__MEMCOPY_DESC_COMP); + + int_en_mask = (INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL); + + ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask; + ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask; + ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask; + ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask; + ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask; + + nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: " + "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n", + ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma); + + if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) { + return 1; + } else { + iowrite32(ints_b0, FlashReg + INTR_STATUS0); + iowrite32(ints_b1, FlashReg + INTR_STATUS1); + iowrite32(ints_b2, FlashReg + INTR_STATUS2); + iowrite32(ints_b3, FlashReg + INTR_STATUS3); + nand_dbg_print(NAND_DBG_DEBUG, + "Not a NAND controller interrupt! Ignore it.\n"); + return 0; + } +} + +static void update_event_status(void) +{ + int i; + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (i = 0; i < info.cdma_num; i++) { + if (ptr[i].pcmd != 0xff) + info.pcmds[ptr[i].pcmd].Status = CMD_PASS; + if ((ptr[i].CommandType == 0x41) || + (ptr[i].CommandType == 0x42) || + (ptr[i].CommandType == 0x43)) + continue; + + switch (info.pcmds[ptr[i].pcmd].CMD) { + case READ_MAIN_SPARE_CMD: + Conv_Main_Spare_Data_Phy2Log_Format( + info.pcmds[ptr[i].pcmd].DataAddr, + info.pcmds[ptr[i].pcmd].PageCount); + break; + case READ_SPARE_CMD: + Conv_Spare_Data_Phy2Log_Format( + info.pcmds[ptr[i].pcmd].DataAddr); + break; + } + } +} + +static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page) +{ + u16 event = EVENT_NONE; + u16 err_byte; + u16 err_page = 0; + u8 err_sector; + u8 err_device; + u16 ecc_correction_info; + u16 err_address; + u32 eccSectorSize; + u8 *err_pos; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + do { + if (0 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR0); + else if (1 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR1); + else if (2 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR2); + else if (3 == ch) + err_page = ioread32(FlashReg + ERR_PAGE_ADDR3); + + err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS); + err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET; + err_sector = ((err_address & + ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); + + ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO); + err_device = ((ecc_correction_info & + ERR_CORRECTION_INFO__DEVICE_NR) >> 8); + + if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) { + event = EVENT_UNCORRECTABLE_DATA_ERROR; + } else { + event = EVENT_CORRECTABLE_DATA_ERROR_FIXED; + if (err_byte < ECC_SECTOR_SIZE) { + err_pos = buf + + (err_page - page) * + DeviceInfo.wPageDataSize + + err_sector * eccSectorSize + + err_byte * + DeviceInfo.wDevicesConnected + + err_device; + *err_pos ^= ecc_correction_info & + ERR_CORRECTION_INFO__BYTEMASK; + } + } + } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); + + return event; +} + +static u16 process_ecc_int(u32 c, u16 *p_desc_num) +{ + struct cdma_descriptor *ptr; + u16 j; + int event = EVENT_PASS; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (c != info.flash_bank) + printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n", + info.flash_bank, c); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + for (j = 0; j < info.cdma_num; j++) + if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP) + break; + + *p_desc_num = j; /* Pass the descripter number found here */ + + if (j >= info.cdma_num) { + printk(KERN_ERR "Can not find the correct descriptor number " + "when ecc interrupt triggered!" + "info.cdma_num: %d, j: %d\n", info.cdma_num, j); + return EVENT_UNCORRECTABLE_DATA_ERROR; + } + + event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr, + info.pcmds[ptr[j].pcmd].Page); + + if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { + printk(KERN_ERR "Uncorrectable ECC error!" + "info.cdma_num: %d, j: %d, " + "pending cmd CMD: 0x%x, " + "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n", + info.cdma_num, j, + info.pcmds[ptr[j].pcmd].CMD, + info.pcmds[ptr[j].pcmd].Block, + info.pcmds[ptr[j].pcmd].Page, + info.pcmds[ptr[j].pcmd].PageCount); + + if (ptr[j].pcmd != 0xff) + info.pcmds[ptr[j].pcmd].Status = CMD_FAIL; + CDMA_UpdateEventStatus(); + } + + return event; +} + +static void process_prog_erase_fail_int(u16 desc_num) +{ + struct cdma_descriptor *ptr; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ptr = (struct cdma_descriptor *)info.cdma_desc_buf; + + if (ptr[desc_num].pcmd != 0xFF) + info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL; + + CDMA_UpdateEventStatus(); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Event_Status (for use with CMD_DMA) +* Inputs: none +* Outputs: Event_Status code +* Description: This function is called after an interrupt has happened +* It reads the HW status register and ...tbd +* It returns the appropriate event status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 CDMA_Event_Status(void) +{ + u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0, + DMA_INTR__DESC_COMP_CHANNEL1, + DMA_INTR__DESC_COMP_CHANNEL2, + DMA_INTR__DESC_COMP_CHANNEL3}; + u32 cdma_int_status, int_status; + u32 ecc_enable = 0; + u16 event = EVENT_PASS; + u16 cur_desc = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ecc_enable = ioread32(FlashReg + ECC_ENABLE); + + while (1) { + int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); + if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) { + event = process_ecc_int(info.flash_bank, &cur_desc); + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + ints_addr[info.flash_bank]); + if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { + nand_dbg_print(NAND_DBG_WARN, + "ints_bank0 to ints_bank3: " + "0x%x, 0x%x, 0x%x, 0x%x, " + "ints_cdma: 0x%x\n", + ioread32(FlashReg + INTR_STATUS0), + ioread32(FlashReg + INTR_STATUS1), + ioread32(FlashReg + INTR_STATUS2), + ioread32(FlashReg + INTR_STATUS3), + ioread32(FlashReg + DMA_INTR)); + break; + } + } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) { + printk(KERN_ERR "NAND program fail interrupt!\n"); + process_prog_erase_fail_int(cur_desc); + event = EVENT_PROGRAM_FAILURE; + break; + } else if (int_status & INTR_STATUS0__ERASE_FAIL) { + printk(KERN_ERR "NAND erase fail interrupt!\n"); + process_prog_erase_fail_int(cur_desc); + event = EVENT_ERASE_FAILURE; + break; + } else { + cdma_int_status = ioread32(FlashReg + DMA_INTR); + if (cdma_int_status & dma_intr_bit[info.flash_bank]) { + iowrite32(dma_intr_bit[info.flash_bank], + FlashReg + DMA_INTR); + update_event_status(); + event = EVENT_PASS; + break; + } + } + } + + int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); + iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]); + cdma_int_status = ioread32(FlashReg + DMA_INTR); + iowrite32(cdma_int_status, FlashReg + DMA_INTR); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return event; +} + + + diff --git a/drivers/staging/spectra/lld_cdma.h b/drivers/staging/spectra/lld_cdma.h new file mode 100644 index 000000000000..854ea066f0c4 --- /dev/null +++ b/drivers/staging/spectra/lld_cdma.h @@ -0,0 +1,123 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* header for LLD_CDMA.c module */ + +#ifndef _LLD_CDMA_ +#define _LLD_CDMA_ + +#include "flash.h" + +#define DEBUG_SYNC 1 + +/*/////////// CDMA specific MACRO definition */ +#define MAX_DESCS (255) +#define MAX_CHANS (4) +#define MAX_SYNC_POINTS (16) +#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2) + +#define CHANNEL_SYNC_MASK (0x000F) +#define CHANNEL_DMA_MASK (0x00F0) +#define CHANNEL_ID_MASK (0x0300) +#define CHANNEL_CONT_MASK (0x4000) +#define CHANNEL_INTR_MASK (0x8000) + +#define CHANNEL_SYNC_OFFSET (0) +#define CHANNEL_DMA_OFFSET (4) +#define CHANNEL_ID_OFFSET (8) +#define CHANNEL_CONT_OFFSET (14) +#define CHANNEL_INTR_OFFSET (15) + +u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags); +u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags); +u16 CDMA_Execute_CMDs(void); +void print_pending_cmds(void); +void print_cdma_descriptors(void); + +extern u8 g_SBDCmdIndex; +extern struct mrst_nand_info info; + + +/*/////////// prototypes: APIs for LLD_CDMA */ +int is_cdma_interrupt(void); +u16 CDMA_Event_Status(void); + +/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */ +struct cdma_descriptor { + u32 NxtPointerHi; + u32 NxtPointerLo; + u32 FlashPointerHi; + u32 FlashPointerLo; + u32 CommandType; + u32 MemAddrHi; + u32 MemAddrLo; + u32 CommandFlags; + u32 Channel; + u32 Status; + u32 MemCopyPointerHi; + u32 MemCopyPointerLo; + u32 Reserved12; + u32 Reserved13; + u32 Reserved14; + u32 pcmd; /* pending cmd num related to this descriptor */ +}; + +/* This struct holds one MemCopy descriptor as defined by the HW */ +struct memcpy_descriptor { + u32 NxtPointerHi; + u32 NxtPointerLo; + u32 SrcAddrHi; + u32 SrcAddrLo; + u32 DestAddrHi; + u32 DestAddrLo; + u32 XferSize; + u32 MemCopyFlags; + u32 MemCopyStatus; + u32 reserved9; + u32 reserved10; + u32 reserved11; + u32 reserved12; + u32 reserved13; + u32 reserved14; + u32 reserved15; +}; + +/* Pending CMD table entries (includes MemCopy parameters */ +struct pending_cmd { + u8 CMD; + u8 *DataAddr; + u32 Block; + u16 Page; + u16 PageCount; + u8 *DataDestAddr; + u8 *DataSrcAddr; + u32 MemCopyByteCnt; + u16 Flags; + u16 Status; +}; + +#if DEBUG_SYNC +extern u32 debug_sync_cnt; +#endif + +/* Definitions for CMD DMA descriptor chain fields */ +#define CMD_DMA_DESC_COMP 0x8000 +#define CMD_DMA_DESC_FAIL 0x4000 + +#endif /*_LLD_CDMA_*/ diff --git a/drivers/staging/spectra/lld_emu.c b/drivers/staging/spectra/lld_emu.c new file mode 100644 index 000000000000..60eb0f6fdba4 --- /dev/null +++ b/drivers/staging/spectra/lld_emu.c @@ -0,0 +1,780 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include "flash.h" +#include "ffsdefs.h" +#include "lld_emu.h" +#include "lld.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define GLOB_LLD_PAGES 64 +#define GLOB_LLD_PAGE_SIZE (512+16) +#define GLOB_LLD_PAGE_DATA_SIZE 512 +#define GLOB_LLD_BLOCKS 2048 + +#if (CMD_DMA && FLASH_EMU) +#include "lld_cdma.h" +u32 totalUsedBanks; +u32 valid_banks[MAX_CHANS]; +#endif + +#if FLASH_EMU /* This is for entire module */ + +static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES]; + +/* Read nand emu file and then fill it's content to flash_memory */ +int emu_load_file_to_mem(void) +{ + mm_segment_t fs; + struct file *nef_filp = NULL; + struct inode *inode = NULL; + loff_t nef_size = 0; + loff_t tmp_file_offset, file_offset; + ssize_t nread; + int i, rc = -EINVAL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + fs = get_fs(); + set_fs(get_ds()); + + nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(nef_filp)) { + printk(KERN_ERR "filp_open error: " + "Unable to open nand emu file!\n"); + return PTR_ERR(nef_filp); + } + + if (nef_filp->f_path.dentry) { + inode = nef_filp->f_path.dentry->d_inode; + } else { + printk(KERN_ERR "Can not get valid inode!\n"); + goto out; + } + + nef_size = i_size_read(inode->i_mapping->host); + if (nef_size <= 0) { + printk(KERN_ERR "Invalid nand emu file size: " + "0x%llx\n", nef_size); + goto out; + } else { + nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n", + nef_size); + } + + file_offset = 0; + for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { + tmp_file_offset = file_offset; + nread = vfs_read(nef_filp, + (char __user *)flash_memory[i], + GLOB_LLD_PAGE_SIZE, &tmp_file_offset); + if (nread < GLOB_LLD_PAGE_SIZE) { + printk(KERN_ERR "%s, Line %d - " + "nand emu file partial read: " + "%d bytes\n", __FILE__, __LINE__, (int)nread); + goto out; + } + file_offset += GLOB_LLD_PAGE_SIZE; + } + rc = 0; + +out: + filp_close(nef_filp, current->files); + set_fs(fs); + return rc; +} + +/* Write contents of flash_memory to nand emu file */ +int emu_write_mem_to_file(void) +{ + mm_segment_t fs; + struct file *nef_filp = NULL; + struct inode *inode = NULL; + loff_t nef_size = 0; + loff_t tmp_file_offset, file_offset; + ssize_t nwritten; + int i, rc = -EINVAL; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + fs = get_fs(); + set_fs(get_ds()); + + nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(nef_filp)) { + printk(KERN_ERR "filp_open error: " + "Unable to open nand emu file!\n"); + return PTR_ERR(nef_filp); + } + + if (nef_filp->f_path.dentry) { + inode = nef_filp->f_path.dentry->d_inode; + } else { + printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n"); + goto out; + } + + nef_size = i_size_read(inode->i_mapping->host); + if (nef_size <= 0) { + printk(KERN_ERR "Invalid " + "nand emu file size: 0x%llx\n", nef_size); + goto out; + } else { + nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: " + "%lld\n", nef_size); + } + + file_offset = 0; + for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { + tmp_file_offset = file_offset; + nwritten = vfs_write(nef_filp, + (char __user *)flash_memory[i], + GLOB_LLD_PAGE_SIZE, &tmp_file_offset); + if (nwritten < GLOB_LLD_PAGE_SIZE) { + printk(KERN_ERR "%s, Line %d - " + "nand emu file partial write: " + "%d bytes\n", __FILE__, __LINE__, (int)nwritten); + goto out; + } + file_offset += GLOB_LLD_PAGE_SIZE; + } + rc = 0; + +out: + filp_close(nef_filp, current->files); + set_fs(fs); + return rc; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Init +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Creates & initializes the flash RAM array. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Flash_Init(void) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + flash_memory[0] = (u8 *)vmalloc(GLOB_LLD_PAGE_SIZE * + GLOB_LLD_BLOCKS * + GLOB_LLD_PAGES * + sizeof(u8)); + if (!flash_memory[0]) { + printk(KERN_ERR "Fail to allocate memory " + "for nand emulator!\n"); + return ERR; + } + + memset((char *)(flash_memory[0]), 0xFF, + GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES * + sizeof(u8)); + + for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) + flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE; + + emu_load_file_to_mem(); /* Load nand emu file to mem */ + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Release +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Releases the flash. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int emu_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + emu_write_mem_to_file(); /* Write back mem to nand emu file */ + + vfree(flash_memory[0]); + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Device_ID +* Inputs: none +* Outputs: PASS=1 FAIL=0 +* Description: Reads the info from the controller registers. +* Sets up DeviceInfo structure with device parameters +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +u16 emu_Read_Device_ID(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + DeviceInfo.wDeviceMaker = 0; + DeviceInfo.wDeviceType = 8; + DeviceInfo.wSpectraStartBlock = 36; + DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1; + DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS; + DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES; + DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE; + DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE; + DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE - + GLOB_LLD_PAGE_DATA_SIZE; + DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES; + DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES; + DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + + 1); + DeviceInfo.MLCDevice = 1; /* Emulate MLC device */ + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + +#if CMD_DMA + totalUsedBanks = 4; + valid_banks[0] = 1; + valid_banks[1] = 1; + valid_banks[2] = 1; + valid_banks[3] = 1; +#endif + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Flash_Reset +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Reset the flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Flash_Reset(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Erase_Block +* Inputs: Address +* Outputs: PASS=0 (notice 0=ok here) +* Description: Erase a block +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Erase_Block(u32 block_add) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (block_add >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "emu_Erase_Block error! " + "Too big block address: %d\n", block_add); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", + (int)block_add); + + for (i = block_add * GLOB_LLD_PAGES; + i < ((block_add + 1) * GLOB_LLD_PAGES); i++) { + if (flash_memory[i]) { + memset((u8 *)(flash_memory[i]), 0xFF, + DeviceInfo.wPageSize * sizeof(u8)); + } + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Main +* Inputs: Write buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the data in the buffer to main area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory\n"); + return FAIL; + } + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), + write_data, DeviceInfo.wPageDataSize); + write_data += DeviceInfo.wPageDataSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Main +* Inputs: Read buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read the data from the flash main area to the buffer +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Main(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(read_data, 0xFF, DeviceInfo.wPageDataSize); + } else { + memcpy(read_data, + (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + + Page]), + DeviceInfo.wPageDataSize); + } + read_data += DeviceInfo.wPageDataSize; + Page++; + } + + return PASS; +} + +#ifndef ELDORA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Main_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read from flash main+spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + int i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)PageCount, + (unsigned int)Block, (unsigned int)Page); + + for (i = 0; i < PageCount; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(read_data, 0xFF, DeviceInfo.wPageSize); + } else { + memcpy(read_data, (u8 *) (flash_memory[Block * + GLOB_LLD_PAGES + + Page]), + DeviceInfo.wPageSize); + } + + read_data += DeviceInfo.wPageSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Main_Spare +* Inputs: Write buffer +* address +* buffer length +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer to main+spare area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 page_count) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + page_count > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)page_count, + (unsigned int)Block, (unsigned int)Page); + + for (i = 0; i < page_count; i++) { + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory!\n"); + return FAIL; + } + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), + write_data, DeviceInfo.wPageSize); + write_data += DeviceInfo.wPageSize; + Page++; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Write_Page_Spare +* Inputs: Write buffer +* Address +* buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer in the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare Error: " + "Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare Error: " + "Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- " + "block %u page %u\n", + (unsigned int)Block, (unsigned int)Page); + + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + printk(KERN_ERR "Run out of memory!\n"); + return FAIL; + } + + memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + + DeviceInfo.wPageDataSize), write_data, + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Read_Page_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read data from the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_Read_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " + "block %u page %u\n", + (unsigned int)Block, (unsigned int)Page); + + if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { + memset(write_data, 0xFF, + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + } else { + memcpy(write_data, + (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + + DeviceInfo.wPageDataSize), + (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Enable_Disable_Interrupts +* Inputs: enable or disable +* Outputs: none +* Description: NOP +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void emu_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); +} + +u16 emu_Get_Bad_Block(u32 block) +{ + return 0; +} + +#if CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Support for CDMA functions +************************************ +* emu_CDMA_Flash_Init +* CDMA_process_data command (use LLD_CDMA) +* CDMA_MemCopy_CMD (use LLD_CDMA) +* emu_CDMA_execute all commands +* emu_CDMA_Event_Status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Flash_Init(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = 3; + } + + return PASS; +} + +static void emu_isr(int irq, void *dev_id) +{ + /* TODO: ... */ +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: execute each command in the pending CMD array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Execute_CMDs(u16 tag_count) +{ + u16 i, j; + u8 CMD; /* cmd parameter */ + u8 *data; + u32 block; + u16 page; + u16 count; + u16 status = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " + "Tag Count %u\n", tag_count); + + for (i = 0; i < totalUsedBanks; i++) { + PendingCMD[i].CMD = DUMMY_CMD; + PendingCMD[i].Tag = 0xFF; + PendingCMD[i].Block = + (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; + + for (j = 0; j <= MAX_CHANS; j++) + PendingCMD[i].ChanSync[j] = 0; + } + + CDMA_Execute_CMDs(tag_count); + + print_pending_cmds(tag_count); + +#if DEBUG_SYNC + } + debug_sync_cnt++; +#endif + + for (i = MAX_CHANS; + i < tag_count + MAX_CHANS; i++) { + CMD = PendingCMD[i].CMD; + data = PendingCMD[i].DataAddr; + block = PendingCMD[i].Block; + page = PendingCMD[i].Page; + count = PendingCMD[i].PageCount; + + switch (CMD) { + case ERASE_CMD: + emu_Erase_Block(block); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_CMD: + emu_Write_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_SPARE_CMD: + emu_Write_Page_Main_Spare(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case READ_MAIN_CMD: + emu_Read_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case MEMCOPY_CMD: + memcpy(PendingCMD[i].DataDestAddr, + PendingCMD[i].DataSrcAddr, + PendingCMD[i].MemCopyByteCnt); + case DUMMY_CMD: + PendingCMD[i].Status = PASS; + break; + default: + PendingCMD[i].Status = FAIL; + break; + } + } + + /* + * Temperory adding code to reset PendingCMD array for basic testing. + * It should be done at the end of event status function. + */ + for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = CMD_NOT_DONE; + } + + nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); + + emu_isr(0, 0); /* This is a null isr now. Need fill it in future */ + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: emu_Event_Status +* Inputs: none +* Outputs: Event_Status code +* Description: This function can also be used to force errors +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 emu_CDMA_Event_Status(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return EVENT_PASS; +} + +#endif /* CMD_DMA */ +#endif /* !ELDORA */ +#endif /* FLASH_EMU */ diff --git a/drivers/staging/spectra/lld_emu.h b/drivers/staging/spectra/lld_emu.h new file mode 100644 index 000000000000..63f84c38d3c1 --- /dev/null +++ b/drivers/staging/spectra/lld_emu.h @@ -0,0 +1,51 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_EMU_ +#define _LLD_EMU_ + +#include "ffsport.h" +#include "ffsdefs.h" + +/* prototypes: emulator API functions */ +extern u16 emu_Flash_Reset(void); +extern u16 emu_Flash_Init(void); +extern int emu_Flash_Release(void); +extern u16 emu_Read_Device_ID(void); +extern u16 emu_Erase_Block(u32 block_addr); +extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 emu_Event_Status(void); +extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE); +extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 emu_Get_Bad_Block(u32 block); + +u16 emu_CDMA_Flash_Init(void); +u16 emu_CDMA_Execute_CMDs(u16 tag_count); +u16 emu_CDMA_Event_Status(void); +#endif /*_LLD_EMU_*/ diff --git a/drivers/staging/spectra/lld_mtd.c b/drivers/staging/spectra/lld_mtd.c new file mode 100644 index 000000000000..0de05b1e75f7 --- /dev/null +++ b/drivers/staging/spectra/lld_mtd.c @@ -0,0 +1,687 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include "flash.h" +#include "ffsdefs.h" +#include "lld_emu.h" +#include "lld.h" +#if CMD_DMA +#include "lld_cdma.h" +#endif + +#define GLOB_LLD_PAGES 64 +#define GLOB_LLD_PAGE_SIZE (512+16) +#define GLOB_LLD_PAGE_DATA_SIZE 512 +#define GLOB_LLD_BLOCKS 2048 + +#if CMD_DMA +#include "lld_cdma.h" +u32 totalUsedBanks; +u32 valid_banks[MAX_CHANS]; +#endif + +static struct mtd_info *spectra_mtd; +static int mtddev = -1; +module_param(mtddev, int, 0); + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Init +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Creates & initializes the flash RAM array. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Flash_Init(void) +{ + if (mtddev == -1) { + printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n"); + return FAIL; + } + + spectra_mtd = get_mtd_device(NULL, mtddev); + if (!spectra_mtd) { + printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev); + return FAIL; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Release +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Releases the flash. +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +int mtd_Flash_Release(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + if (!spectra_mtd) + return PASS; + + put_mtd_device(spectra_mtd); + spectra_mtd = NULL; + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Device_ID +* Inputs: none +* Outputs: PASS=1 FAIL=0 +* Description: Reads the info from the controller registers. +* Sets up DeviceInfo structure with device parameters +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ + +u16 mtd_Read_Device_ID(void) +{ + uint64_t tmp; + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!spectra_mtd) + return FAIL; + + DeviceInfo.wDeviceMaker = 0; + DeviceInfo.wDeviceType = 8; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + tmp = spectra_mtd->size; + do_div(tmp, spectra_mtd->erasesize); + DeviceInfo.wTotalBlocks = tmp; + DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; + DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; + DeviceInfo.wPageDataSize = spectra_mtd->writesize; + DeviceInfo.wPageSpareSize = spectra_mtd->oobsize; + DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + + 1); + DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK; + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + +#if CMD_DMA + totalUsedBanks = 4; + valid_banks[0] = 1; + valid_banks[1] = 1; + valid_banks[2] = 1; + valid_banks[3] = 1; +#endif + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Flash_Reset +* Inputs: none +* Outputs: PASS=0 (notice 0=ok here) +* Description: Reset the flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Flash_Reset(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +void erase_callback(struct erase_info *e) +{ + complete((void *)e->priv); +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Erase_Block +* Inputs: Address +* Outputs: PASS=0 (notice 0=ok here) +* Description: Erase a block +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Erase_Block(u32 block_add) +{ + struct erase_info erase; + DECLARE_COMPLETION_ONSTACK(comp); + int ret; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (block_add >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "mtd_Erase_Block error! " + "Too big block address: %d\n", block_add); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", + (int)block_add); + + erase.mtd = spectra_mtd; + erase.callback = erase_callback; + erase.addr = block_add * spectra_mtd->erasesize; + erase.len = spectra_mtd->erasesize; + erase.priv = (unsigned long)∁ + + ret = spectra_mtd->erase(spectra_mtd, &erase); + if (!ret) { + wait_for_completion(&comp); + if (erase.state != MTD_ERASE_DONE) + ret = -EIO; + } + if (ret) { + printk(KERN_WARNING "mtd_Erase_Block error! " + "erase of region [0x%llx, 0x%llx] failed\n", + erase.addr, erase.len); + return FAIL; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Main +* Inputs: Write buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the data in the buffer to main area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + size_t retlen; + int ret = 0; + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + + while (PageCount) { + ret = spectra_mtd->write(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + DeviceInfo.wPageDataSize, &retlen, write_data); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + write_data += DeviceInfo.wPageDataSize; + Page++; + PageCount--; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Main +* Inputs: Read buffer address pointer +* Block number +* Page number +* Number of pages to process +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read the data from the flash main area to the buffer +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + size_t retlen; + int ret = 0; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) + return FAIL; + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) + return FAIL; + + nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: " + "lba %u Page %u PageCount %u\n", + (unsigned int)Block, + (unsigned int)Page, (unsigned int)PageCount); + + + while (PageCount) { + ret = spectra_mtd->read(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + DeviceInfo.wPageDataSize, &retlen, read_data); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + read_data += DeviceInfo.wPageDataSize; + Page++; + PageCount--; + } + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return PASS; +} + +#ifndef ELDORA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Main_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read from flash main+spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Main+Spare " + "Error: Page number %d+%d too big in block %d\n", + Page, PageCount, Block); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)PageCount, + (unsigned int)Block, (unsigned int)Page); + + + while (PageCount) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = read_data; + ops.len = DeviceInfo.wPageDataSize; + ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->read_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + read_data += DeviceInfo.wPageSize; + Page++; + PageCount--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Main_Spare +* Inputs: Write buffer +* address +* buffer length +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer to main+spare area of flash +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 page_count) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + page_count > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Write Page Main + Spare " + "Error: Page number %d+%d too big in block %d\n", + Page, page_count, Block); + WARN_ON(1); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " + "No. of pages %u block %u start page %u\n", + (unsigned int)page_count, + (unsigned int)Block, (unsigned int)Page); + + while (page_count) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = write_data; + ops.len = DeviceInfo.wPageDataSize; + ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->write_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + write_data += DeviceInfo.wPageSize; + Page++; + page_count--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Write_Page_Spare +* Inputs: Write buffer +* Address +* buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Write the buffer in the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount) +{ + WARN_ON(1); + return FAIL; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Read_Page_Spare +* Inputs: Write Buffer +* Address +* Buffer size +* Outputs: PASS=0 (notice 0=ok here) +* Description: Read data from the spare area +* +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (Block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "Read Page Spare " + "Error: Block Address too big\n"); + return FAIL; + } + + if (Page + PageCount > DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "Read Page Spare " + "Error: Page number too big\n"); + return FAIL; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " + "block %u page %u (%u pages)\n", + (unsigned int)Block, (unsigned int)Page, PageCount); + + while (PageCount) { + struct mtd_oob_ops ops; + int ret; + + ops.mode = MTD_OOB_AUTO; + ops.datbuf = NULL; + ops.len = 0; + ops.oobbuf = read_data; + ops.ooblen = BTSIG_BYTES; + ops.ooboffs = 0; + + ret = spectra_mtd->read_oob(spectra_mtd, + (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), + &ops); + if (ret) { + printk(KERN_ERR "%s failed %d\n", __func__, ret); + return FAIL; + } + + read_data += DeviceInfo.wPageSize; + Page++; + PageCount--; + } + + return PASS; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Enable_Disable_Interrupts +* Inputs: enable or disable +* Outputs: none +* Description: NOP +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); +} + +u16 mtd_Get_Bad_Block(u32 block) +{ + return 0; +} + +#if CMD_DMA +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Support for CDMA functions +************************************ +* mtd_CDMA_Flash_Init +* CDMA_process_data command (use LLD_CDMA) +* CDMA_MemCopy_CMD (use LLD_CDMA) +* mtd_CDMA_execute all commands +* mtd_CDMA_Event_Status +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Flash_Init(void) +{ + u16 i; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = 3; + } + + return PASS; +} + +static void mtd_isr(int irq, void *dev_id) +{ + /* TODO: ... */ +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: CDMA_Execute_CMDs +* Inputs: tag_count: the number of pending cmds to do +* Outputs: PASS/FAIL +* Description: execute each command in the pending CMD array +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Execute_CMDs(u16 tag_count) +{ + u16 i, j; + u8 CMD; /* cmd parameter */ + u8 *data; + u32 block; + u16 page; + u16 count; + u16 status = PASS; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " + "Tag Count %u\n", tag_count); + + for (i = 0; i < totalUsedBanks; i++) { + PendingCMD[i].CMD = DUMMY_CMD; + PendingCMD[i].Tag = 0xFF; + PendingCMD[i].Block = + (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; + + for (j = 0; j <= MAX_CHANS; j++) + PendingCMD[i].ChanSync[j] = 0; + } + + CDMA_Execute_CMDs(tag_count); + +#ifdef VERBOSE + print_pending_cmds(tag_count); +#endif +#if DEBUG_SYNC + } + debug_sync_cnt++; +#endif + + for (i = MAX_CHANS; + i < tag_count + MAX_CHANS; i++) { + CMD = PendingCMD[i].CMD; + data = PendingCMD[i].DataAddr; + block = PendingCMD[i].Block; + page = PendingCMD[i].Page; + count = PendingCMD[i].PageCount; + + switch (CMD) { + case ERASE_CMD: + mtd_Erase_Block(block); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_CMD: + mtd_Write_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case WRITE_MAIN_SPARE_CMD: + mtd_Write_Page_Main_Spare(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case READ_MAIN_CMD: + mtd_Read_Page_Main(data, block, page, count); + PendingCMD[i].Status = PASS; + break; + case MEMCOPY_CMD: + memcpy(PendingCMD[i].DataDestAddr, + PendingCMD[i].DataSrcAddr, + PendingCMD[i].MemCopyByteCnt); + case DUMMY_CMD: + PendingCMD[i].Status = PASS; + break; + default: + PendingCMD[i].Status = FAIL; + break; + } + } + + /* + * Temperory adding code to reset PendingCMD array for basic testing. + * It should be done at the end of event status function. + */ + for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { + PendingCMD[i].CMD = 0; + PendingCMD[i].Tag = 0; + PendingCMD[i].DataAddr = 0; + PendingCMD[i].Block = 0; + PendingCMD[i].Page = 0; + PendingCMD[i].PageCount = 0; + PendingCMD[i].DataDestAddr = 0; + PendingCMD[i].DataSrcAddr = 0; + PendingCMD[i].MemCopyByteCnt = 0; + PendingCMD[i].ChanSync[0] = 0; + PendingCMD[i].ChanSync[1] = 0; + PendingCMD[i].ChanSync[2] = 0; + PendingCMD[i].ChanSync[3] = 0; + PendingCMD[i].ChanSync[4] = 0; + PendingCMD[i].Status = CMD_NOT_DONE; + } + + nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); + + mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */ + + return status; +} + +/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +* Function: mtd_Event_Status +* Inputs: none +* Outputs: Event_Status code +* Description: This function can also be used to force errors +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ +u16 mtd_CDMA_Event_Status(void) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + return EVENT_PASS; +} + +#endif /* CMD_DMA */ +#endif /* !ELDORA */ diff --git a/drivers/staging/spectra/lld_mtd.h b/drivers/staging/spectra/lld_mtd.h new file mode 100644 index 000000000000..4e81ee87b53d --- /dev/null +++ b/drivers/staging/spectra/lld_mtd.h @@ -0,0 +1,51 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_MTD_ +#define _LLD_MTD_ + +#include "ffsport.h" +#include "ffsdefs.h" + +/* prototypes: MTD API functions */ +extern u16 mtd_Flash_Reset(void); +extern u16 mtd_Flash_Init(void); +extern int mtd_Flash_Release(void); +extern u16 mtd_Read_Device_ID(void); +extern u16 mtd_Erase_Block(u32 block_addr); +extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 mtd_Event_Status(void); +extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE); +extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, + u16 Page, u16 PageCount); +extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, + u16 PageCount); +extern u16 mtd_Get_Bad_Block(u32 block); + +u16 mtd_CDMA_Flash_Init(void); +u16 mtd_CDMA_Execute_CMDs(u16 tag_count); +u16 mtd_CDMA_Event_Status(void); +#endif /*_LLD_MTD_*/ diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c new file mode 100644 index 000000000000..13c3ad2db394 --- /dev/null +++ b/drivers/staging/spectra/lld_nand.c @@ -0,0 +1,2601 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "lld.h" +#include "lld_nand.h" +#include "lld_cdma.h" + +#include "spectraswconfig.h" +#include "flash.h" +#include "ffsdefs.h" + +#include +#include +#include +#include + +#include "nand_regs.h" + +#define SPECTRA_NAND_NAME "nd" + +#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) +#define MAX_PAGES_PER_RW 128 + +#define INT_IDLE_STATE 0 +#define INT_READ_PAGE_MAIN 0x01 +#define INT_WRITE_PAGE_MAIN 0x02 +#define INT_PIPELINE_READ_AHEAD 0x04 +#define INT_PIPELINE_WRITE_AHEAD 0x08 +#define INT_MULTI_PLANE_READ 0x10 +#define INT_MULTI_PLANE_WRITE 0x11 + +static u32 enable_ecc; + +struct mrst_nand_info info; + +int totalUsedBanks; +u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; + +void __iomem *FlashReg; +void __iomem *FlashMem; + +u16 conf_parameters[] = { + 0x0000, + 0x0000, + 0x01F4, + 0x01F4, + 0x01F4, + 0x01F4, + 0x0000, + 0x0000, + 0x0001, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0040, + 0x0001, + 0x000A, + 0x000A, + 0x000A, + 0x0000, + 0x0000, + 0x0005, + 0x0012, + 0x000C +}; + +u16 NAND_Get_Bad_Block(u32 block) +{ + u32 status = PASS; + u32 flag_bytes = 0; + u32 skip_bytes = DeviceInfo.wSpareSkipBytes; + u32 page, i; + u8 *pReadSpareBuf = buf_get_bad_block; + + if (enable_ecc) + flag_bytes = DeviceInfo.wNumPageSpareFlag; + + for (page = 0; page < 2; page++) { + status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1); + if (status != PASS) + return READ_ERROR; + for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) + if (pReadSpareBuf[i] != 0xff) + return DEFECTIVE_BLOCK; + } + + for (page = 1; page < 3; page++) { + status = NAND_Read_Page_Spare(pReadSpareBuf, block, + DeviceInfo.wPagesPerBlock - page , 1); + if (status != PASS) + return READ_ERROR; + for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) + if (pReadSpareBuf[i] != 0xff) + return DEFECTIVE_BLOCK; + } + + return GOOD_BLOCK; +} + + +u16 NAND_Flash_Reset(void) +{ + u32 i; + u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP, + INTR_STATUS1__RST_COMP, + INTR_STATUS2__RST_COMP, + INTR_STATUS3__RST_COMP}; + u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT, + INTR_STATUS1__TIME_OUT, + INTR_STATUS2__TIME_OUT, + INTR_STATUS3__TIME_OUT}; + u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + u32 device_reset_banks[4] = {DEVICE_RESET__BANK0, + DEVICE_RESET__BANK1, + DEVICE_RESET__BANK2, + DEVICE_RESET__BANK3}; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) + iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], + FlashReg + intr_status[i]); + + for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { + iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET); + while (!(ioread32(FlashReg + intr_status[i]) & + (intr_status_rst_comp[i] | intr_status_time_out[i]))) + ; + if (ioread32(FlashReg + intr_status[i]) & + intr_status_time_out[i]) + nand_dbg_print(NAND_DBG_WARN, + "NAND Reset operation timed out on bank %d\n", i); + } + + for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) + iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], + FlashReg + intr_status[i]); + + return PASS; +} + +static void NAND_ONFi_Timing_Mode(u16 mode) +{ + u16 Trea[6] = {40, 30, 25, 20, 20, 16}; + u16 Trp[6] = {50, 25, 17, 15, 12, 10}; + u16 Treh[6] = {30, 15, 15, 10, 10, 7}; + u16 Trc[6] = {100, 50, 35, 30, 25, 20}; + u16 Trhoh[6] = {0, 15, 15, 15, 15, 15}; + u16 Trloh[6] = {0, 0, 0, 0, 5, 5}; + u16 Tcea[6] = {100, 45, 30, 25, 25, 25}; + u16 Tadl[6] = {200, 100, 100, 100, 70, 70}; + u16 Trhw[6] = {200, 100, 100, 100, 100, 100}; + u16 Trhz[6] = {200, 100, 100, 100, 100, 100}; + u16 Twhr[6] = {120, 80, 80, 60, 60, 60}; + u16 Tcs[6] = {70, 35, 25, 25, 20, 15}; + + u16 TclsRising = 1; + u16 data_invalid_rhoh, data_invalid_rloh, data_invalid; + u16 dv_window = 0; + u16 en_lo, en_hi; + u16 acc_clks; + u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + en_lo = CEIL_DIV(Trp[mode], CLK_X); + en_hi = CEIL_DIV(Treh[mode], CLK_X); + +#if ONFI_BLOOM_TIME + if ((en_hi * CLK_X) < (Treh[mode] + 2)) + en_hi++; +#endif + + if ((en_lo + en_hi) * CLK_X < Trc[mode]) + en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X); + + if ((en_lo + en_hi) < CLK_MULTI) + en_lo += CLK_MULTI - en_lo - en_hi; + + while (dv_window < 8) { + data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode]; + + data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode]; + + data_invalid = + data_invalid_rhoh < + data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh; + + dv_window = data_invalid - Trea[mode]; + + if (dv_window < 8) + en_lo++; + } + + acc_clks = CEIL_DIV(Trea[mode], CLK_X); + + while (((acc_clks * CLK_X) - Trea[mode]) < 3) + acc_clks++; + + if ((data_invalid - acc_clks * CLK_X) < 2) + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n", + __FILE__, __LINE__); + + addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); + re_2_we = CEIL_DIV(Trhw[mode], CLK_X); + re_2_re = CEIL_DIV(Trhz[mode], CLK_X); + we_2_re = CEIL_DIV(Twhr[mode], CLK_X); + cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X); + if (!TclsRising) + cs_cnt = CEIL_DIV(Tcs[mode], CLK_X); + if (cs_cnt == 0) + cs_cnt = 1; + + if (Tcea[mode]) { + while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode]) + cs_cnt++; + } + +#if MODE5_WORKAROUND + if (mode == 5) + acc_clks = 5; +#endif + + /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */ + if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) && + (ioread32(FlashReg + DEVICE_ID) == 0x88)) + acc_clks = 6; + + iowrite32(acc_clks, FlashReg + ACC_CLKS); + iowrite32(re_2_we, FlashReg + RE_2_WE); + iowrite32(re_2_re, FlashReg + RE_2_RE); + iowrite32(we_2_re, FlashReg + WE_2_RE); + iowrite32(addr_2_data, FlashReg + ADDR_2_DATA); + iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT); + iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT); + iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT); +} + +static void index_addr(u32 address, u32 data) +{ + iowrite32(address, FlashMem); + iowrite32(data, FlashMem + 0x10); +} + +static void index_addr_read_data(u32 address, u32 *pdata) +{ + iowrite32(address, FlashMem); + *pdata = ioread32(FlashMem + 0x10); +} + +static void set_ecc_config(void) +{ +#if SUPPORT_8BITECC + if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) || + (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128)) + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + + if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) + == 1) { + DeviceInfo.wECCBytesPerSector = 4; + DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; + DeviceInfo.wNumPageSpareFlag = + DeviceInfo.wPageSpareSize - + DeviceInfo.wPageDataSize / + (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * + DeviceInfo.wECCBytesPerSector + - DeviceInfo.wSpareSkipBytes; + } else { + DeviceInfo.wECCBytesPerSector = + (ioread32(FlashReg + ECC_CORRECTION) & + ECC_CORRECTION__VALUE) * 13 / 8; + if ((DeviceInfo.wECCBytesPerSector) % 2 == 0) + DeviceInfo.wECCBytesPerSector += 2; + else + DeviceInfo.wECCBytesPerSector += 1; + + DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; + DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize - + DeviceInfo.wPageDataSize / + (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * + DeviceInfo.wECCBytesPerSector + - DeviceInfo.wSpareSkipBytes; + } +} + +static u16 get_onfi_nand_para(void) +{ + int i; + u16 blks_lun_l, blks_lun_h, n_of_luns; + u32 blockperlun, id; + + iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET); + + while (!((ioread32(FlashReg + INTR_STATUS0) & + INTR_STATUS0__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS0) & + INTR_STATUS0__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { + iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS1) & + INTR_STATUS1__RST_COMP) { + iowrite32(DEVICE_RESET__BANK2, + FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__TIME_OUT))) + ; + + if (ioread32(FlashReg + INTR_STATUS2) & + INTR_STATUS2__RST_COMP) { + iowrite32(DEVICE_RESET__BANK3, + FlashReg + DEVICE_RESET); + while (!((ioread32(FlashReg + INTR_STATUS3) & + INTR_STATUS3__RST_COMP) | + (ioread32(FlashReg + INTR_STATUS3) & + INTR_STATUS3__TIME_OUT))) + ; + } else { + printk(KERN_ERR "Getting a time out for bank 2!\n"); + } + } else { + printk(KERN_ERR "Getting a time out for bank 1!\n"); + } + } + + iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0); + iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1); + iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2); + iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3); + + DeviceInfo.wONFIDevFeatures = + ioread32(FlashReg + ONFI_DEVICE_FEATURES); + DeviceInfo.wONFIOptCommands = + ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS); + DeviceInfo.wONFITimingMode = + ioread32(FlashReg + ONFI_TIMING_MODE); + DeviceInfo.wONFIPgmCacheTimingMode = + ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE); + + n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & + ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; + blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); + blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); + + blockperlun = (blks_lun_h << 16) | blks_lun_l; + + DeviceInfo.wTotalBlocks = n_of_luns * blockperlun; + + if (!(ioread32(FlashReg + ONFI_TIMING_MODE) & + ONFI_TIMING_MODE__VALUE)) + return FAIL; + + for (i = 5; i > 0; i--) { + if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i)) + break; + } + + NAND_ONFi_Timing_Mode(i); + + index_addr(MODE_11 | 0, 0x90); + index_addr(MODE_11 | 1, 0); + + for (i = 0; i < 3; i++) + index_addr_read_data(MODE_11 | 2, &id); + + nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); + + DeviceInfo.MLCDevice = id & 0x0C; + + /* By now, all the ONFI devices we know support the page cache */ + /* rw feature. So here we enable the pipeline_rw_ahead feature */ + /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */ + /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */ + + return PASS; +} + +static void get_samsung_nand_para(void) +{ + u8 no_of_planes; + u32 blk_size; + u64 plane_size, capacity; + u32 id_bytes[5]; + int i; + + index_addr((u32)(MODE_11 | 0), 0x90); + index_addr((u32)(MODE_11 | 1), 0); + for (i = 0; i < 5; i++) + index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]); + + nand_dbg_print(NAND_DBG_DEBUG, + "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + id_bytes[0], id_bytes[1], id_bytes[2], + id_bytes[3], id_bytes[4]); + + if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ + /* Set timing register values according to datasheet */ + iowrite32(5, FlashReg + ACC_CLKS); + iowrite32(20, FlashReg + RE_2_WE); + iowrite32(12, FlashReg + WE_2_RE); + iowrite32(14, FlashReg + ADDR_2_DATA); + iowrite32(3, FlashReg + RDWR_EN_LO_CNT); + iowrite32(2, FlashReg + RDWR_EN_HI_CNT); + iowrite32(2, FlashReg + CS_SETUP_CNT); + } + + no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); + plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4); + blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4); + capacity = (u64)128 * plane_size * no_of_planes; + + DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size); +} + +static void get_toshiba_nand_para(void) +{ + void __iomem *scratch_reg; + u32 tmp; + + /* Workaround to fix a controller bug which reports a wrong */ + /* spare area size for some kind of Toshiba NAND device */ + if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) && + (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) { + iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE); + tmp = ioread32(FlashReg + DEVICES_CONNECTED) * + ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); + iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE); +#if SUPPORT_15BITECC + iowrite32(15, FlashReg + ECC_CORRECTION); +#elif SUPPORT_8BITECC + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + } + + /* As Toshiba NAND can not provide it's block number, */ + /* so here we need user to provide the correct block */ + /* number in a scratch register before the Linux NAND */ + /* driver is loaded. If no valid value found in the scratch */ + /* register, then we use default block number value */ + scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); + if (!scratch_reg) { + printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", + __FILE__, __LINE__); + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Spectra: ioremap reg address: 0x%p\n", scratch_reg); + DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); + if (DeviceInfo.wTotalBlocks < 512) + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + iounmap(scratch_reg); + } +} + +static void get_hynix_nand_para(void) +{ + void __iomem *scratch_reg; + u32 main_size, spare_size; + + switch (DeviceInfo.wDeviceID) { + case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ + case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ + iowrite32(128, FlashReg + PAGES_PER_BLOCK); + iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE); + iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE); + main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED); + spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED); + iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE); + iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE); + iowrite32(0, FlashReg + DEVICE_WIDTH); +#if SUPPORT_15BITECC + iowrite32(15, FlashReg + ECC_CORRECTION); +#elif SUPPORT_8BITECC + iowrite32(8, FlashReg + ECC_CORRECTION); +#endif + DeviceInfo.MLCDevice = 1; + break; + default: + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." + "Will use default parameter values instead.\n", + DeviceInfo.wDeviceID); + } + + scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); + if (!scratch_reg) { + printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", + __FILE__, __LINE__); + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Spectra: ioremap reg address: 0x%p\n", scratch_reg); + DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); + if (DeviceInfo.wTotalBlocks < 512) + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + iounmap(scratch_reg); + } +} + +static void find_valid_banks(void) +{ + u32 id[LLD_MAX_FLASH_BANKS]; + int i; + + totalUsedBanks = 0; + for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { + index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90); + index_addr((u32)(MODE_11 | (i << 24) | 1), 0); + index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]); + + nand_dbg_print(NAND_DBG_DEBUG, + "Return 1st ID for bank[%d]: %x\n", i, id[i]); + + if (i == 0) { + if (id[i] & 0x0ff) + GLOB_valid_banks[i] = 1; + } else { + if ((id[i] & 0x0ff) == (id[0] & 0x0ff)) + GLOB_valid_banks[i] = 1; + } + + totalUsedBanks += GLOB_valid_banks[i]; + } + + nand_dbg_print(NAND_DBG_DEBUG, + "totalUsedBanks: %d\n", totalUsedBanks); +} + +static void detect_partition_feature(void) +{ + if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) { + if ((ioread32(FlashReg + PERM_SRC_ID_1) & + PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { + DeviceInfo.wSpectraStartBlock = + ((ioread32(FlashReg + MIN_MAX_BANK_1) & + MIN_MAX_BANK_1__MIN_VALUE) * + DeviceInfo.wTotalBlocks) + + + (ioread32(FlashReg + MIN_BLK_ADDR_1) & + MIN_BLK_ADDR_1__VALUE); + + DeviceInfo.wSpectraEndBlock = + (((ioread32(FlashReg + MIN_MAX_BANK_1) & + MIN_MAX_BANK_1__MAX_VALUE) >> 2) * + DeviceInfo.wTotalBlocks) + + + (ioread32(FlashReg + MAX_BLK_ADDR_1) & + MAX_BLK_ADDR_1__VALUE); + + DeviceInfo.wTotalBlocks *= totalUsedBanks; + + if (DeviceInfo.wSpectraEndBlock >= + DeviceInfo.wTotalBlocks) { + DeviceInfo.wSpectraEndBlock = + DeviceInfo.wTotalBlocks - 1; + } + + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } else { + DeviceInfo.wTotalBlocks *= totalUsedBanks; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + DeviceInfo.wSpectraEndBlock = + DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } + } else { + DeviceInfo.wTotalBlocks *= totalUsedBanks; + DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; + DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; + DeviceInfo.wDataBlockNum = + DeviceInfo.wSpectraEndBlock - + DeviceInfo.wSpectraStartBlock + 1; + } +} + +static void dump_device_info(void) +{ + nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n"); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", + DeviceInfo.wDeviceMaker); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", + DeviceInfo.wDeviceID); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", + DeviceInfo.wDeviceType); + nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", + DeviceInfo.wSpectraStartBlock); + nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", + DeviceInfo.wSpectraEndBlock); + nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", + DeviceInfo.wTotalBlocks); + nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", + DeviceInfo.wPagesPerBlock); + nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", + DeviceInfo.wPageSize); + nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", + DeviceInfo.wPageDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", + DeviceInfo.wPageSpareSize); + nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", + DeviceInfo.wNumPageSpareFlag); + nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", + DeviceInfo.wECCBytesPerSector); + nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", + DeviceInfo.wBlockSize); + nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", + DeviceInfo.wBlockDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", + DeviceInfo.wDataBlockNum); + nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", + DeviceInfo.bPlaneNum); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", + DeviceInfo.wDeviceMainAreaSize); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", + DeviceInfo.wDeviceSpareAreaSize); + nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", + DeviceInfo.wDevicesConnected); + nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", + DeviceInfo.wDeviceWidth); + nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", + DeviceInfo.wHWRevision); + nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", + DeviceInfo.wHWFeatures); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", + DeviceInfo.wONFIDevFeatures); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", + DeviceInfo.wONFIOptCommands); + nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", + DeviceInfo.wONFITimingMode); + nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", + DeviceInfo.wONFIPgmCacheTimingMode); + nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", + DeviceInfo.MLCDevice ? "Yes" : "No"); + nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", + DeviceInfo.wSpareSkipBytes); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", + DeviceInfo.nBitsInPageNumber); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", + DeviceInfo.nBitsInPageDataSize); + nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", + DeviceInfo.nBitsInBlockDataSize); +} + +u16 NAND_Read_Device_ID(void) +{ + u16 status = PASS; + u8 no_of_planes; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES); + iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER); + DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID); + DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID); + DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c; + + if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & + ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ + if (FAIL == get_onfi_nand_para()) + return FAIL; + } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */ + get_samsung_nand_para(); + } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */ + get_toshiba_nand_para(); + } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */ + get_hynix_nand_para(); + } else { + DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; + } + + nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" + "acc_clks: %d, re_2_we: %d, we_2_re: %d," + "addr_2_data: %d, rdwr_en_lo_cnt: %d, " + "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", + ioread32(FlashReg + ACC_CLKS), + ioread32(FlashReg + RE_2_WE), + ioread32(FlashReg + WE_2_RE), + ioread32(FlashReg + ADDR_2_DATA), + ioread32(FlashReg + RDWR_EN_LO_CNT), + ioread32(FlashReg + RDWR_EN_HI_CNT), + ioread32(FlashReg + CS_SETUP_CNT)); + + DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION); + DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES); + + DeviceInfo.wDeviceMainAreaSize = + ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE); + DeviceInfo.wDeviceSpareAreaSize = + ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); + + DeviceInfo.wPageDataSize = + ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE); + + /* Note: When using the Micon 4K NAND device, the controller will report + * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. + * And if force set it to 218 bytes, the controller can not work + * correctly. So just let it be. But keep in mind that this bug may + * cause + * other problems in future. - Yunpeng 2008-10-10 + */ + DeviceInfo.wPageSpareSize = + ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE); + + DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK); + + DeviceInfo.wPageSize = + DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize; + DeviceInfo.wBlockSize = + DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; + DeviceInfo.wBlockDataSize = + DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; + + DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH); + DeviceInfo.wDeviceType = + ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8); + + DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED); + + DeviceInfo.wSpareSkipBytes = + ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) * + DeviceInfo.wDevicesConnected; + + DeviceInfo.nBitsInPageNumber = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); + DeviceInfo.nBitsInPageDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); + DeviceInfo.nBitsInBlockDataSize = + (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); + + set_ecc_config(); + + no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) & + NUMBER_OF_PLANES__VALUE; + + switch (no_of_planes) { + case 0: + case 1: + case 3: + case 7: + DeviceInfo.bPlaneNum = no_of_planes + 1; + break; + default: + status = FAIL; + break; + } + + find_valid_banks(); + + detect_partition_feature(); + + dump_device_info(); + + return status; +} + +u16 NAND_UnlockArrayAll(void) +{ + u64 start_addr, end_addr; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + start_addr = 0; + end_addr = ((u64)DeviceInfo.wBlockSize * + (DeviceInfo.wTotalBlocks - 1)) >> + DeviceInfo.nBitsInPageDataSize; + + index_addr((u32)(MODE_10 | (u32)start_addr), 0x10); + index_addr((u32)(MODE_10 | (u32)end_addr), 0x11); + + return PASS; +} + +void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE) +{ + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (INT_ENABLE) + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); + else + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); +} + +u16 NAND_Erase_Block(u32 block) +{ + u16 status = PASS; + u64 flash_add; + u16 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (block >= DeviceInfo.wTotalBlocks) + status = FAIL; + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, + FlashReg + intr_status); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1); + + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ERASE_FAIL) + status = FAIL; + + iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, + FlashReg + intr_status); + } + + return status; +} + +static u32 Boundary_Check_Block_Page(u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + + if (block >= DeviceInfo.wTotalBlocks) + status = FAIL; + + if (page + page_count > DeviceInfo.wPagesPerBlock) + status = FAIL; + + return status; +} + +u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 i; + u64 flash_add; + u32 PageSpareSize = DeviceInfo.wPageSpareSize; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_spare = buf_read_page_spare; + + if (block >= DeviceInfo.wTotalBlocks) { + printk(KERN_ERR "block too big: %d\n", (int)block); + status = FAIL; + } + + if (page >= DeviceInfo.wPagesPerBlock) { + printk(KERN_ERR "page too big: %d\n", page); + status = FAIL; + } + + if (page_count > 1) { + printk(KERN_ERR "page count too big: %d\n", page_count); + status = FAIL; + } + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x41); + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x2000 | page_count); + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__LOAD_COMP)) + ; + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + for (i = 0; i < (PageSpareSize / 4); i++) + *((u32 *)page_spare + i) = + ioread32(FlashMem + 0x10); + + if (enable_ecc) { + for (i = 0; i < spareFlagBytes; i++) + read_data[i] = + page_spare[PageSpareSize - + spareFlagBytes + i]; + for (i = 0; i < (PageSpareSize - spareFlagBytes); i++) + read_data[spareFlagBytes + i] = + page_spare[i]; + } else { + for (i = 0; i < PageSpareSize; i++) + read_data[i] = page_spare[i]; + } + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + } + + return status; +} + +/* No use function. Should be removed later */ +u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + printk(KERN_ERR + "Error! This function (NAND_Write_Page_Spare) should never" + " be called!\n"); + return ERR; +} + +/* op value: 0 - DDMA read; 1 - DDMA write */ +static void ddma_trans(u8 *data, u64 flash_add, + u32 flash_bank, int op, u32 numPages) +{ + u32 data_addr; + + /* Map virtual address to bus address for DDMA */ + data_addr = virt_to_bus(data); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + (u16)(2 << 12) | (op << 8) | numPages); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + ((u16)(0x0FFFF & (data_addr >> 16)) << 8)), + (u16)(2 << 12) | (2 << 8) | 0); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + ((u16)(0x0FFFF & data_addr) << 8)), + (u16)(2 << 12) | (3 << 8) | 0); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (1 << 16) | (0x40 << 8)), + (u16)(2 << 12) | (4 << 8) | 0); +} + +/* If data in buf are all 0xff, then return 1; otherwise return 0 */ +static int check_all_1(u8 *buf) +{ + int i, j, cnt; + + for (i = 0; i < DeviceInfo.wPageDataSize; i++) { + if (buf[i] != 0xff) { + cnt = 0; + nand_dbg_print(NAND_DBG_WARN, + "the first non-0xff data byte is: %d\n", i); + for (j = i; j < DeviceInfo.wPageDataSize; j++) { + nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]); + cnt++; + if (cnt > 8) + break; + } + nand_dbg_print(NAND_DBG_WARN, "\n"); + return 0; + } + } + + return 1; +} + +static int do_ecc_new(unsigned long bank, u8 *buf, + u32 block, u16 page) +{ + int status = PASS; + u16 err_page = 0; + u16 err_byte; + u8 err_sect; + u8 err_dev; + u16 err_fix_info; + u16 err_addr; + u32 ecc_sect_size; + u8 *err_pos; + u32 err_page_addr[4] = {ERR_PAGE_ADDR0, + ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3}; + + ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + do { + err_page = ioread32(FlashReg + err_page_addr[bank]); + err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS); + err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET; + err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); + err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO); + err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR) + >> 8); + if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) { + nand_dbg_print(NAND_DBG_WARN, + "%s, Line %d Uncorrectable ECC error " + "when read block %d page %d." + "PTN_INTR register: 0x%x " + "err_page: %d, err_sect: %d, err_byte: %d, " + "err_dev: %d, ecc_sect_size: %d, " + "err_fix_info: 0x%x\n", + __FILE__, __LINE__, block, page, + ioread32(FlashReg + PTN_INTR), + err_page, err_sect, err_byte, err_dev, + ecc_sect_size, (u32)err_fix_info); + + if (check_all_1(buf)) + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" + "All 0xff!\n", + __FILE__, __LINE__); + else + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" + "Not all 0xff!\n", + __FILE__, __LINE__); + status = FAIL; + } else { + nand_dbg_print(NAND_DBG_WARN, + "%s, Line %d Found ECC error " + "when read block %d page %d." + "err_page: %d, err_sect: %d, err_byte: %d, " + "err_dev: %d, ecc_sect_size: %d, " + "err_fix_info: 0x%x\n", + __FILE__, __LINE__, block, page, + err_page, err_sect, err_byte, err_dev, + ecc_sect_size, (u32)err_fix_info); + if (err_byte < ECC_SECTOR_SIZE) { + err_pos = buf + + (err_page - page) * + DeviceInfo.wPageDataSize + + err_sect * ecc_sect_size + + err_byte * + DeviceInfo.wDevicesConnected + + err_dev; + + *err_pos ^= err_fix_info & + ERR_CORRECTION_INFO__BYTEMASK; + } + } + } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); + + return status; +} + +u16 NAND_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *read_data_l; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + if (page_count > 1) { + read_data_l = read_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Read_Ahead_Polling( + read_data_l, block, page, + MAX_PAGES_PER_RW); + + if (status == FAIL) + return status; + + read_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Read_Ahead_Polling( + read_data_l, block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + ddma_trans(read_data, flash_add, flash_bank, 0, 1); + + if (enable_ecc) { + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, read_data, + block, page); + } + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE & + INTR_STATUS0__ECC_ERR) + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status); + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 ecc_done_OR_dma_comp; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + *DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + ecc_done_OR_dma_comp = 0; + while (1) { + if (enable_ecc) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + + } + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + } + return status; +} + +u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + u8 *read_data_l; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + if (page_count > 1) { + read_data_l = read_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Read_Ahead( + read_data_l, block, page, + MAX_PAGES_PER_RW); + + if (status == FAIL) + return status; + + read_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Read(read_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Read_Ahead( + read_data_l, block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + /* Fill the mrst_nand_info structure */ + info.state = INT_READ_PAGE_MAIN; + info.read_data = read_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + ddma_trans(read_data, flash_add, flash_bank, 0, 1); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +void Conv_Spare_Data_Log2Phy_Format(u8 *data) +{ + int i; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + const u32 PageSpareSize = DeviceInfo.wPageSpareSize; + + if (enable_ecc) { + for (i = spareFlagBytes - 1; i >= 0; i++) + data[PageSpareSize - spareFlagBytes + i] = data[i]; + } +} + +void Conv_Spare_Data_Phy2Log_Format(u8 *data) +{ + int i; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + const u32 PageSpareSize = DeviceInfo.wPageSpareSize; + + if (enable_ecc) { + for (i = 0; i < spareFlagBytes; i++) + data[i] = data[PageSpareSize - spareFlagBytes + i]; + } +} + + +void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count) +{ + const u32 PageSize = DeviceInfo.wPageSize; + const u32 PageDataSize = DeviceInfo.wPageDataSize; + const u32 eccBytes = DeviceInfo.wECCBytesPerSector; + const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 eccSectorSize; + u32 page_offset; + int i, j; + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + if (enable_ecc) { + while (page_count > 0) { + page_offset = (page_count - 1) * PageSize; + j = (DeviceInfo.wPageDataSize / eccSectorSize); + for (i = spareFlagBytes - 1; i >= 0; i--) + data[page_offset + + (eccSectorSize + eccBytes) * j + i] = + data[page_offset + PageDataSize + i]; + for (j--; j >= 1; j--) { + for (i = eccSectorSize - 1; i >= 0; i--) + data[page_offset + + (eccSectorSize + eccBytes) * j + i] = + data[page_offset + + eccSectorSize * j + i]; + } + for (i = (PageSize - spareSkipBytes) - 1; + i >= PageDataSize; i--) + data[page_offset + i + spareSkipBytes] = + data[page_offset + i]; + page_count--; + } + } +} + +void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count) +{ + const u32 PageSize = DeviceInfo.wPageSize; + const u32 PageDataSize = DeviceInfo.wPageDataSize; + const u32 eccBytes = DeviceInfo.wECCBytesPerSector; + const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 eccSectorSize; + u32 page_offset; + int i, j; + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + if (enable_ecc) { + while (page_count > 0) { + page_offset = (page_count - 1) * PageSize; + for (i = PageDataSize; + i < PageSize - spareSkipBytes; + i++) + data[page_offset + i] = + data[page_offset + i + + spareSkipBytes]; + for (j = 1; + j < DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + for (i = 0; i < eccSectorSize; i++) + data[page_offset + + eccSectorSize * j + i] = + data[page_offset + + (eccSectorSize + eccBytes) * j + + i]; + } + for (i = 0; i < spareFlagBytes; i++) + data[page_offset + PageDataSize + i] = + data[page_offset + + (eccSectorSize + eccBytes) * j + i]; + page_count--; + } + } +} + +/* Un-tested function */ +u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 ecc_done_OR_dma_comp; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + ecc_done_OR_dma_comp = 0; + while (1) { + if (enable_ecc) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + + if (1 == ecc_done_OR_dma_comp) + break; + + ecc_done_OR_dma_comp = 1; + } + } else { + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP)) + ; + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + + } + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + MULTIPLANE_OPERATION); + } + + return status; +} + +u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, + u16 page, u16 page_count) +{ + u32 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + *DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + /* Fill the mrst_nand_info structure */ + info.state = INT_PIPELINE_READ_AHEAD; + info.read_data = read_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + + +u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u64 flash_add; + u32 intr_status = 0; + u32 flash_bank; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + u8 *write_data_l; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(INTR_STATUS0__PROGRAM_COMP | + INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status); + + if (page_count > 1) { + write_data_l = write_data; + while (page_count > MAX_PAGES_PER_RW) { + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Write(write_data_l, + block, page, MAX_PAGES_PER_RW); + else + status = NAND_Pipeline_Write_Ahead( + write_data_l, block, page, + MAX_PAGES_PER_RW); + if (status == FAIL) + return status; + + write_data_l += DeviceInfo.wPageDataSize * + MAX_PAGES_PER_RW; + page_count -= MAX_PAGES_PER_RW; + page += MAX_PAGES_PER_RW; + } + if (ioread32(FlashReg + MULTIPLANE_OPERATION)) + status = NAND_Multiplane_Write(write_data_l, + block, page, page_count); + else + status = NAND_Pipeline_Write_Ahead(write_data_l, + block, page, page_count); + + return status; + } + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + /* Fill the mrst_nand_info structure */ + info.state = INT_WRITE_PAGE_MAIN; + info.write_data = write_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + ddma_trans(write_data, flash_add, flash_bank, 1, 1); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG) + ; + + return status; +} + +void NAND_ECC_Ctrl(int enable) +{ + if (enable) { + nand_dbg_print(NAND_DBG_WARN, + "Will enable ECC in %s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + iowrite32(1, FlashReg + ECC_ENABLE); + enable_ecc = 1; + } else { + nand_dbg_print(NAND_DBG_WARN, + "Will disable ECC in %s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + iowrite32(0, FlashReg + ECC_ENABLE); + enable_ecc = 0; + } +} + +u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 page, u16 page_count) +{ + u32 status = PASS; + u32 i, j, page_num = 0; + u32 PageSize = DeviceInfo.wPageSize; + u32 PageDataSize = DeviceInfo.wPageDataSize; + u32 eccBytes = DeviceInfo.wECCBytesPerSector; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + u64 flash_add; + u32 eccSectorSize; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_main_spare = buf_write_page_main_spare; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(1, FlashReg + TRANSFER_SPARE_REG); + + while ((status != FAIL) && (page_count > 0)) { + flash_add = (u64)(block % + (DeviceInfo.wTotalBlocks / totalUsedBanks)) * + DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> + DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + if (enable_ecc) { + for (j = 0; + j < + DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + for (i = 0; i < eccSectorSize; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + + i] = + write_data[eccSectorSize * + j + i]; + + for (i = 0; i < eccBytes; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + + eccSectorSize + + i] = + write_data[PageDataSize + + spareFlagBytes + + eccBytes * j + + i]; + } + + for (i = 0; i < spareFlagBytes; i++) + page_main_spare[(eccSectorSize + + eccBytes) * j + i] = + write_data[PageDataSize + i]; + + for (i = PageSize - 1; i >= PageDataSize + + spareSkipBytes; i--) + page_main_spare[i] = page_main_spare[i - + spareSkipBytes]; + + for (i = PageDataSize; i < PageDataSize + + spareSkipBytes; i++) + page_main_spare[i] = 0xff; + + for (i = 0; i < PageSize / 4; i++) + iowrite32( + *((u32 *)page_main_spare + i), + FlashMem + 0x10); + } else { + + for (i = 0; i < PageSize / 4; i++) + iowrite32(*((u32 *)write_data + i), + FlashMem + 0x10); + } + + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__PROGRAM_COMP | + INTR_STATUS0__PROGRAM_FAIL))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) + status = FAIL; + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + page_num++; + page_count--; + write_data += PageSize; + } + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + } + + return status; +} + +u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count) +{ + u32 status = PASS; + u32 i, j; + u64 flash_add = 0; + u32 PageSize = DeviceInfo.wPageSize; + u32 PageDataSize = DeviceInfo.wPageDataSize; + u32 PageSpareSize = DeviceInfo.wPageSpareSize; + u32 eccBytes = DeviceInfo.wECCBytesPerSector; + u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; + u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; + u32 eccSectorSize; + u32 flash_bank; + u32 intr_status = 0; + u8 *read_data_l = read_data; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u8 *page_main_spare = buf_read_page_main_spare; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); + + status = Boundary_Check_Block_Page(block, page, page_count); + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + if (status == PASS) { + intr_status = intr_status_addresses[flash_bank]; + + iowrite32(1, FlashReg + TRANSFER_SPARE_REG); + + iowrite32(ioread32(FlashReg + intr_status), + FlashReg + intr_status); + + while ((status != FAIL) && (page_count > 0)) { + flash_add = (u64)(block % + (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x43); + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), + 0x2000 | page_count); + + while (!(ioread32(FlashReg + intr_status) & + INTR_STATUS0__LOAD_COMP)) + ; + + iowrite32((u32)(MODE_01 | (flash_bank << 24) | + (flash_add >> + DeviceInfo.nBitsInPageDataSize)), + FlashMem); + + for (i = 0; i < PageSize / 4; i++) + *(((u32 *)page_main_spare) + i) = + ioread32(FlashMem + 0x10); + + if (enable_ecc) { + for (i = PageDataSize; i < PageSize - + spareSkipBytes; i++) + page_main_spare[i] = page_main_spare[i + + spareSkipBytes]; + + for (j = 0; + j < DeviceInfo.wPageDataSize / eccSectorSize; + j++) { + + for (i = 0; i < eccSectorSize; i++) + read_data_l[eccSectorSize * j + + i] = + page_main_spare[ + (eccSectorSize + + eccBytes) * j + i]; + + for (i = 0; i < eccBytes; i++) + read_data_l[PageDataSize + + spareFlagBytes + + eccBytes * j + i] = + page_main_spare[ + (eccSectorSize + + eccBytes) * j + + eccSectorSize + i]; + } + + for (i = 0; i < spareFlagBytes; i++) + read_data_l[PageDataSize + i] = + page_main_spare[(eccSectorSize + + eccBytes) * j + i]; + } else { + for (i = 0; i < (PageDataSize + PageSpareSize); + i++) + read_data_l[i] = page_main_spare[i]; + + } + + if (enable_ecc) { + while (!(ioread32(FlashReg + intr_status) & + (INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR))) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + status = do_ecc_new(flash_bank, + read_data, block, page); + } + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR | + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32( + INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + } + } + + page++; + page_count--; + read_data_l += PageSize; + } + } + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + return status; +} + +u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, + u16 page, u16 page_count) +{ + u16 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + int ret; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + + if (page_count < 2) + status = FAIL; + + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + /* Fill the mrst_nand_info structure */ + info.state = INT_PIPELINE_WRITE_AHEAD; + info.write_data = write_data; + info.flash_bank = flash_bank; + info.block = block; + info.page = page; + info.ret = PASS; + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); + + iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ + + ret = wait_for_completion_timeout(&info.complete, 10 * HZ); + if (!ret) { + printk(KERN_ERR "Wait for completion timeout " + "in %s, Line %d\n", __FILE__, __LINE__); + status = ERR; + } else { + status = info.ret; + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + return status; +} + +/* Un-tested function */ +u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, + u16 page_count) +{ + u16 status = PASS; + u32 NumPages = page_count; + u64 flash_add; + u32 flash_bank; + u32 intr_status = 0; + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u16 status2 = PASS; + u32 t; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + status = Boundary_Check_Block_Page(block, page, page_count); + if (status != PASS) + return status; + + flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) + * DeviceInfo.wBlockDataSize + + (u64)page * DeviceInfo.wPageDataSize; + + flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); + + intr_status = intr_status_addresses[flash_bank]; + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); + + iowrite32(1, FlashReg + DMA_ENABLE); + while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + TRANSFER_SPARE_REG); + + index_addr((u32)(MODE_10 | (flash_bank << 24) | + (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); + + ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); + + while (1) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + status = PASS; + if (status2 == FAIL) + status = FAIL; + break; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) { + status2 = FAIL; + status = FAIL; + t = ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL; + iowrite32(t, FlashReg + intr_status); + } else { + iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } + } + + iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); + + iowrite32(0, FlashReg + DMA_ENABLE); + + while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) + ; + + iowrite32(0, FlashReg + MULTIPLANE_OPERATION); + + return status; +} + + +#if CMD_DMA +static irqreturn_t cdma_isr(int irq, void *dev_id) +{ + struct mrst_nand_info *dev = dev_id; + int first_failed_cmd; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + if (!is_cdma_interrupt()) + return IRQ_NONE; + + /* Disable controller interrupts */ + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + GLOB_FTL_Event_Status(&first_failed_cmd); + complete(&dev->complete); + + return IRQ_HANDLED; +} +#else +static void handle_nand_int_read(struct mrst_nand_info *dev) +{ + u32 intr_status_addresses[4] = {INTR_STATUS0, + INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; + u32 intr_status; + u32 ecc_done_OR_dma_comp = 0; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev->ret = PASS; + intr_status = intr_status_addresses[dev->flash_bank]; + + while (1) { + if (enable_ecc) { + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_ERR) { + iowrite32(INTR_STATUS0__ECC_ERR, + FlashReg + intr_status); + dev->ret = do_ecc_new(dev->flash_bank, + dev->read_data, + dev->block, dev->page); + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + if (1 == ecc_done_OR_dma_comp) + break; + ecc_done_OR_dma_comp = 1; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__ECC_TRANSACTION_DONE) { + iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, + FlashReg + intr_status); + if (1 == ecc_done_OR_dma_comp) + break; + ecc_done_OR_dma_comp = 1; + } + } else { + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + break; + } else { + printk(KERN_ERR "Illegal INTS " + "(offset addr 0x%x) value: 0x%x\n", + intr_status, + ioread32(FlashReg + intr_status)); + } + } + + iowrite32((~INTR_STATUS0__ECC_ERR) & + (~INTR_STATUS0__ECC_TRANSACTION_DONE) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } +} + +static void handle_nand_int_write(struct mrst_nand_info *dev) +{ + u32 intr_status; + u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + int status = PASS; + + nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + dev->ret = PASS; + intr_status = intr[dev->flash_bank]; + + while (1) { + while (!ioread32(FlashReg + intr_status)) + ; + + if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__DMA_CMD_COMP) { + iowrite32(INTR_STATUS0__DMA_CMD_COMP, + FlashReg + intr_status); + if (FAIL == status) + dev->ret = FAIL; + break; + } else if (ioread32(FlashReg + intr_status) & + INTR_STATUS0__PROGRAM_FAIL) { + status = FAIL; + iowrite32(INTR_STATUS0__PROGRAM_FAIL, + FlashReg + intr_status); + } else { + iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & + (~INTR_STATUS0__DMA_CMD_COMP), + FlashReg + intr_status); + } + } +} + +static irqreturn_t ddma_isr(int irq, void *dev_id) +{ + struct mrst_nand_info *dev = dev_id; + u32 int_mask, ints0, ints1, ints2, ints3, ints_offset; + u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, + INTR_STATUS2, INTR_STATUS3}; + + int_mask = INTR_STATUS0__DMA_CMD_COMP | + INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL; + + ints0 = ioread32(FlashReg + INTR_STATUS0); + ints1 = ioread32(FlashReg + INTR_STATUS1); + ints2 = ioread32(FlashReg + INTR_STATUS2); + ints3 = ioread32(FlashReg + INTR_STATUS3); + + ints_offset = intr[dev->flash_bank]; + + nand_dbg_print(NAND_DBG_DEBUG, + "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, " + "DMA_INTR: 0x%x, " + "dev->state: 0x%x, dev->flash_bank: %d\n", + ints0, ints1, ints2, ints3, + ioread32(FlashReg + DMA_INTR), + dev->state, dev->flash_bank); + + if (!(ioread32(FlashReg + ints_offset) & int_mask)) { + iowrite32(ints0, FlashReg + INTR_STATUS0); + iowrite32(ints1, FlashReg + INTR_STATUS1); + iowrite32(ints2, FlashReg + INTR_STATUS2); + iowrite32(ints3, FlashReg + INTR_STATUS3); + nand_dbg_print(NAND_DBG_WARN, + "ddma_isr: Invalid interrupt for NAND controller. " + "Ignore it\n"); + return IRQ_NONE; + } + + switch (dev->state) { + case INT_READ_PAGE_MAIN: + case INT_PIPELINE_READ_AHEAD: + /* Disable controller interrupts */ + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + handle_nand_int_read(dev); + break; + case INT_WRITE_PAGE_MAIN: + case INT_PIPELINE_WRITE_AHEAD: + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + handle_nand_int_write(dev); + break; + default: + printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n", + dev->state); + return IRQ_NONE; + } + + dev->state = INT_IDLE_STATE; + complete(&dev->complete); + return IRQ_HANDLED; +} +#endif + +static const struct pci_device_id nand_pci_ids[] = { + { + .vendor = 0x8086, + .device = 0x0809, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { /* end: all zeroes */ } +}; + +static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret = -ENODEV; + unsigned long csr_base; + unsigned long csr_len; + struct mrst_nand_info *pndev = &info; + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + ret = pci_enable_device(dev); + if (ret) { + printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); + return ret; + } + + pci_set_master(dev); + pndev->dev = dev; + + csr_base = pci_resource_start(dev, 0); + if (!csr_base) { + printk(KERN_ERR "Spectra: pci_resource_start failed!\n"); + return -ENODEV; + } + + csr_len = pci_resource_len(dev, 0); + if (!csr_len) { + printk(KERN_ERR "Spectra: pci_resource_len failed!\n"); + return -ENODEV; + } + + ret = pci_request_regions(dev, SPECTRA_NAND_NAME); + if (ret) { + printk(KERN_ERR "Spectra: Unable to request " + "memory region\n"); + goto failed_req_csr; + } + + pndev->ioaddr = ioremap_nocache(csr_base, csr_len); + if (!pndev->ioaddr) { + printk(KERN_ERR "Spectra: Unable to remap memory region\n"); + ret = -ENOMEM; + goto failed_remap_csr; + } + nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n", + csr_base, pndev->ioaddr, csr_len); + + init_completion(&pndev->complete); + nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq); + +#if CMD_DMA + if (request_irq(dev->irq, cdma_isr, IRQF_SHARED, + SPECTRA_NAND_NAME, &info)) { + printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); + ret = -ENODEV; + iounmap(pndev->ioaddr); + goto failed_remap_csr; + } +#else + if (request_irq(dev->irq, ddma_isr, IRQF_SHARED, + SPECTRA_NAND_NAME, &info)) { + printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); + ret = -ENODEV; + iounmap(pndev->ioaddr); + goto failed_remap_csr; + } +#endif + + pci_set_drvdata(dev, pndev); + + return 0; + +failed_remap_csr: + pci_release_regions(dev); +failed_req_csr: + + return ret; +} + +static void nand_pci_remove(struct pci_dev *dev) +{ + struct mrst_nand_info *pndev = pci_get_drvdata(dev); + + nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + +#if CMD_DMA + free_irq(dev->irq, pndev); +#endif + iounmap(pndev->ioaddr); + pci_release_regions(dev); + pci_disable_device(dev); +} + +MODULE_DEVICE_TABLE(pci, nand_pci_ids); + +static struct pci_driver nand_pci_driver = { + .name = SPECTRA_NAND_NAME, + .id_table = nand_pci_ids, + .probe = nand_pci_probe, + .remove = nand_pci_remove, +}; + +int NAND_Flash_Init(void) +{ + int retval; + u32 int_mask; + + nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", + __FILE__, __LINE__, __func__); + + FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE, + GLOB_HWCTL_REG_SIZE); + if (!FlashReg) { + printk(KERN_ERR "Spectra: ioremap_nocache failed!"); + return -ENOMEM; + } + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Remapped reg base address: " + "0x%p, len: %d\n", + FlashReg, GLOB_HWCTL_REG_SIZE); + + FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE, + GLOB_HWCTL_MEM_SIZE); + if (!FlashMem) { + printk(KERN_ERR "Spectra: ioremap_nocache failed!"); + iounmap(FlashReg); + return -ENOMEM; + } + nand_dbg_print(NAND_DBG_WARN, + "Spectra: Remapped flash base address: " + "0x%p, len: %d\n", + (void *)FlashMem, GLOB_HWCTL_MEM_SIZE); + + nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" + "acc_clks: %d, re_2_we: %d, we_2_re: %d," + "addr_2_data: %d, rdwr_en_lo_cnt: %d, " + "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", + ioread32(FlashReg + ACC_CLKS), + ioread32(FlashReg + RE_2_WE), + ioread32(FlashReg + WE_2_RE), + ioread32(FlashReg + ADDR_2_DATA), + ioread32(FlashReg + RDWR_EN_LO_CNT), + ioread32(FlashReg + RDWR_EN_HI_CNT), + ioread32(FlashReg + CS_SETUP_CNT)); + + NAND_Flash_Reset(); + + iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); + +#if CMD_DMA + info.pcmds_num = 0; + info.flash_bank = 0; + info.cdma_num = 0; + int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | + DMA_INTR__DESC_COMP_CHANNEL1 | + DMA_INTR__DESC_COMP_CHANNEL2 | + DMA_INTR__DESC_COMP_CHANNEL3 | + DMA_INTR__MEMCOPY_DESC_COMP); + iowrite32(int_mask, FlashReg + DMA_INTR_EN); + iowrite32(0xFFFF, FlashReg + DMA_INTR); + + int_mask = (INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL); +#else + int_mask = INTR_STATUS0__DMA_CMD_COMP | + INTR_STATUS0__ECC_TRANSACTION_DONE | + INTR_STATUS0__ECC_ERR | + INTR_STATUS0__PROGRAM_FAIL | + INTR_STATUS0__ERASE_FAIL; +#endif + iowrite32(int_mask, FlashReg + INTR_EN0); + iowrite32(int_mask, FlashReg + INTR_EN1); + iowrite32(int_mask, FlashReg + INTR_EN2); + iowrite32(int_mask, FlashReg + INTR_EN3); + + /* Clear all status bits */ + iowrite32(0xFFFF, FlashReg + INTR_STATUS0); + iowrite32(0xFFFF, FlashReg + INTR_STATUS1); + iowrite32(0xFFFF, FlashReg + INTR_STATUS2); + iowrite32(0xFFFF, FlashReg + INTR_STATUS3); + + iowrite32(0x0F, FlashReg + RB_PIN_ENABLED); + iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE); + + /* Should set value for these registers when init */ + iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES); + iowrite32(1, FlashReg + ECC_ENABLE); + enable_ecc = 1; + + retval = pci_register_driver(&nand_pci_driver); + if (retval) + return -ENOMEM; + + return PASS; +} + +/* Free memory */ +int nand_release_spectra(void) +{ + pci_unregister_driver(&nand_pci_driver); + iounmap(FlashMem); + iounmap(FlashReg); + + return 0; +} + + + diff --git a/drivers/staging/spectra/lld_nand.h b/drivers/staging/spectra/lld_nand.h new file mode 100644 index 000000000000..d08388287da8 --- /dev/null +++ b/drivers/staging/spectra/lld_nand.h @@ -0,0 +1,131 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _LLD_NAND_ +#define _LLD_NAND_ + +#ifdef ELDORA +#include "defs.h" +#else +#include "flash.h" +#include "ffsport.h" +#endif + +#define MODE_00 0x00000000 +#define MODE_01 0x04000000 +#define MODE_10 0x08000000 +#define MODE_11 0x0C000000 + + +#define DATA_TRANSFER_MODE 0 +#define PROTECTION_PER_BLOCK 1 +#define LOAD_WAIT_COUNT 2 +#define PROGRAM_WAIT_COUNT 3 +#define ERASE_WAIT_COUNT 4 +#define INT_MONITOR_CYCLE_COUNT 5 +#define READ_BUSY_PIN_ENABLED 6 +#define MULTIPLANE_OPERATION_SUPPORT 7 +#define PRE_FETCH_MODE 8 +#define CE_DONT_CARE_SUPPORT 9 +#define COPYBACK_SUPPORT 10 +#define CACHE_WRITE_SUPPORT 11 +#define CACHE_READ_SUPPORT 12 +#define NUM_PAGES_IN_BLOCK 13 +#define ECC_ENABLE_SELECT 14 +#define WRITE_ENABLE_2_READ_ENABLE 15 +#define ADDRESS_2_DATA 16 +#define READ_ENABLE_2_WRITE_ENABLE 17 +#define TWO_ROW_ADDRESS_CYCLES 18 +#define MULTIPLANE_ADDRESS_RESTRICT 19 +#define ACC_CLOCKS 20 +#define READ_WRITE_ENABLE_LOW_COUNT 21 +#define READ_WRITE_ENABLE_HIGH_COUNT 22 + +#define ECC_SECTOR_SIZE 512 +#define LLD_MAX_FLASH_BANKS 4 + +struct mrst_nand_info { + struct pci_dev *dev; + u32 state; + u32 flash_bank; + u8 *read_data; + u8 *write_data; + u32 block; + u16 page; + u32 use_dma; + void __iomem *ioaddr; /* Mapped io reg base address */ + int ret; + u32 pcmds_num; + struct pending_cmd *pcmds; + int cdma_num; /* CDMA descriptor number in this chan */ + u8 *cdma_desc_buf; /* CDMA descriptor table */ + u8 *memcp_desc_buf; /* Memory copy descriptor table */ + dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */ + dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */ + struct completion complete; +}; + +int NAND_Flash_Init(void); +int nand_release_spectra(void); +u16 NAND_Flash_Reset(void); +u16 NAND_Read_Device_ID(void); +u16 NAND_Erase_Block(u32 flash_add); +u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_UnlockArrayAll(void); +u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, + u16 page, u16 page_count); +u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, + u16 page_count); +void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE); +u16 NAND_Get_Bad_Block(u32 block); +u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, + u16 page, u16 page_count); +u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, + u16 page_count); +u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, + u16 page_count); +void NAND_ECC_Ctrl(int enable); +u16 NAND_Read_Page_Main_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); +u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, + u32 block, u16 page, u16 page_count); +void Conv_Spare_Data_Log2Phy_Format(u8 *data); +void Conv_Spare_Data_Phy2Log_Format(u8 *data); +void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count); +void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count); + +extern void __iomem *FlashReg; +extern void __iomem *FlashMem; + +extern int totalUsedBanks; +extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; + +#endif /*_LLD_NAND_*/ + + + diff --git a/drivers/staging/spectra/nand_regs.h b/drivers/staging/spectra/nand_regs.h new file mode 100644 index 000000000000..e192e4ae8c1e --- /dev/null +++ b/drivers/staging/spectra/nand_regs.h @@ -0,0 +1,619 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#define DEVICE_RESET 0x0 +#define DEVICE_RESET__BANK0 0x0001 +#define DEVICE_RESET__BANK1 0x0002 +#define DEVICE_RESET__BANK2 0x0004 +#define DEVICE_RESET__BANK3 0x0008 + +#define TRANSFER_SPARE_REG 0x10 +#define TRANSFER_SPARE_REG__FLAG 0x0001 + +#define LOAD_WAIT_CNT 0x20 +#define LOAD_WAIT_CNT__VALUE 0xffff + +#define PROGRAM_WAIT_CNT 0x30 +#define PROGRAM_WAIT_CNT__VALUE 0xffff + +#define ERASE_WAIT_CNT 0x40 +#define ERASE_WAIT_CNT__VALUE 0xffff + +#define INT_MON_CYCCNT 0x50 +#define INT_MON_CYCCNT__VALUE 0xffff + +#define RB_PIN_ENABLED 0x60 +#define RB_PIN_ENABLED__BANK0 0x0001 +#define RB_PIN_ENABLED__BANK1 0x0002 +#define RB_PIN_ENABLED__BANK2 0x0004 +#define RB_PIN_ENABLED__BANK3 0x0008 + +#define MULTIPLANE_OPERATION 0x70 +#define MULTIPLANE_OPERATION__FLAG 0x0001 + +#define MULTIPLANE_READ_ENABLE 0x80 +#define MULTIPLANE_READ_ENABLE__FLAG 0x0001 + +#define COPYBACK_DISABLE 0x90 +#define COPYBACK_DISABLE__FLAG 0x0001 + +#define CACHE_WRITE_ENABLE 0xa0 +#define CACHE_WRITE_ENABLE__FLAG 0x0001 + +#define CACHE_READ_ENABLE 0xb0 +#define CACHE_READ_ENABLE__FLAG 0x0001 + +#define PREFETCH_MODE 0xc0 +#define PREFETCH_MODE__PREFETCH_EN 0x0001 +#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0 + +#define CHIP_ENABLE_DONT_CARE 0xd0 +#define CHIP_EN_DONT_CARE__FLAG 0x01 + +#define ECC_ENABLE 0xe0 +#define ECC_ENABLE__FLAG 0x0001 + +#define GLOBAL_INT_ENABLE 0xf0 +#define GLOBAL_INT_EN_FLAG 0x01 + +#define WE_2_RE 0x100 +#define WE_2_RE__VALUE 0x003f + +#define ADDR_2_DATA 0x110 +#define ADDR_2_DATA__VALUE 0x003f + +#define RE_2_WE 0x120 +#define RE_2_WE__VALUE 0x003f + +#define ACC_CLKS 0x130 +#define ACC_CLKS__VALUE 0x000f + +#define NUMBER_OF_PLANES 0x140 +#define NUMBER_OF_PLANES__VALUE 0x0007 + +#define PAGES_PER_BLOCK 0x150 +#define PAGES_PER_BLOCK__VALUE 0xffff + +#define DEVICE_WIDTH 0x160 +#define DEVICE_WIDTH__VALUE 0x0003 + +#define DEVICE_MAIN_AREA_SIZE 0x170 +#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff + +#define DEVICE_SPARE_AREA_SIZE 0x180 +#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff + +#define TWO_ROW_ADDR_CYCLES 0x190 +#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001 + +#define MULTIPLANE_ADDR_RESTRICT 0x1a0 +#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001 + +#define ECC_CORRECTION 0x1b0 +#define ECC_CORRECTION__VALUE 0x001f + +#define READ_MODE 0x1c0 +#define READ_MODE__VALUE 0x000f + +#define WRITE_MODE 0x1d0 +#define WRITE_MODE__VALUE 0x000f + +#define COPYBACK_MODE 0x1e0 +#define COPYBACK_MODE__VALUE 0x000f + +#define RDWR_EN_LO_CNT 0x1f0 +#define RDWR_EN_LO_CNT__VALUE 0x001f + +#define RDWR_EN_HI_CNT 0x200 +#define RDWR_EN_HI_CNT__VALUE 0x001f + +#define MAX_RD_DELAY 0x210 +#define MAX_RD_DELAY__VALUE 0x000f + +#define CS_SETUP_CNT 0x220 +#define CS_SETUP_CNT__VALUE 0x001f + +#define SPARE_AREA_SKIP_BYTES 0x230 +#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f + +#define SPARE_AREA_MARKER 0x240 +#define SPARE_AREA_MARKER__VALUE 0xffff + +#define DEVICES_CONNECTED 0x250 +#define DEVICES_CONNECTED__VALUE 0x0007 + +#define DIE_MASK 0x260 +#define DIE_MASK__VALUE 0x00ff + +#define FIRST_BLOCK_OF_NEXT_PLANE 0x270 +#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff + +#define WRITE_PROTECT 0x280 +#define WRITE_PROTECT__FLAG 0x0001 + +#define RE_2_RE 0x290 +#define RE_2_RE__VALUE 0x003f + +#define MANUFACTURER_ID 0x300 +#define MANUFACTURER_ID__VALUE 0x00ff + +#define DEVICE_ID 0x310 +#define DEVICE_ID__VALUE 0x00ff + +#define DEVICE_PARAM_0 0x320 +#define DEVICE_PARAM_0__VALUE 0x00ff + +#define DEVICE_PARAM_1 0x330 +#define DEVICE_PARAM_1__VALUE 0x00ff + +#define DEVICE_PARAM_2 0x340 +#define DEVICE_PARAM_2__VALUE 0x00ff + +#define LOGICAL_PAGE_DATA_SIZE 0x350 +#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff + +#define LOGICAL_PAGE_SPARE_SIZE 0x360 +#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff + +#define REVISION 0x370 +#define REVISION__VALUE 0xffff + +#define ONFI_DEVICE_FEATURES 0x380 +#define ONFI_DEVICE_FEATURES__VALUE 0x003f + +#define ONFI_OPTIONAL_COMMANDS 0x390 +#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f + +#define ONFI_TIMING_MODE 0x3a0 +#define ONFI_TIMING_MODE__VALUE 0x003f + +#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0 +#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f + +#define ONFI_DEVICE_NO_OF_LUNS 0x3c0 +#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff +#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100 + +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0 +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff + +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0 +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff + +#define FEATURES 0x3f0 +#define FEATURES__N_BANKS 0x0003 +#define FEATURES__ECC_MAX_ERR 0x003c +#define FEATURES__DMA 0x0040 +#define FEATURES__CMD_DMA 0x0080 +#define FEATURES__PARTITION 0x0100 +#define FEATURES__XDMA_SIDEBAND 0x0200 +#define FEATURES__GPREG 0x0400 +#define FEATURES__INDEX_ADDR 0x0800 + +#define TRANSFER_MODE 0x400 +#define TRANSFER_MODE__VALUE 0x0003 + +#define INTR_STATUS0 0x410 +#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS0__ECC_ERR 0x0002 +#define INTR_STATUS0__DMA_CMD_COMP 0x0004 +#define INTR_STATUS0__TIME_OUT 0x0008 +#define INTR_STATUS0__PROGRAM_FAIL 0x0010 +#define INTR_STATUS0__ERASE_FAIL 0x0020 +#define INTR_STATUS0__LOAD_COMP 0x0040 +#define INTR_STATUS0__PROGRAM_COMP 0x0080 +#define INTR_STATUS0__ERASE_COMP 0x0100 +#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS0__LOCKED_BLK 0x0400 +#define INTR_STATUS0__UNSUP_CMD 0x0800 +#define INTR_STATUS0__INT_ACT 0x1000 +#define INTR_STATUS0__RST_COMP 0x2000 +#define INTR_STATUS0__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS0__PAGE_XFER_INC 0x8000 + +#define INTR_EN0 0x420 +#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN0__ECC_ERR 0x0002 +#define INTR_EN0__DMA_CMD_COMP 0x0004 +#define INTR_EN0__TIME_OUT 0x0008 +#define INTR_EN0__PROGRAM_FAIL 0x0010 +#define INTR_EN0__ERASE_FAIL 0x0020 +#define INTR_EN0__LOAD_COMP 0x0040 +#define INTR_EN0__PROGRAM_COMP 0x0080 +#define INTR_EN0__ERASE_COMP 0x0100 +#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN0__LOCKED_BLK 0x0400 +#define INTR_EN0__UNSUP_CMD 0x0800 +#define INTR_EN0__INT_ACT 0x1000 +#define INTR_EN0__RST_COMP 0x2000 +#define INTR_EN0__PIPE_CMD_ERR 0x4000 +#define INTR_EN0__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT0 0x430 +#define PAGE_CNT0__VALUE 0x00ff + +#define ERR_PAGE_ADDR0 0x440 +#define ERR_PAGE_ADDR0__VALUE 0xffff + +#define ERR_BLOCK_ADDR0 0x450 +#define ERR_BLOCK_ADDR0__VALUE 0xffff + +#define INTR_STATUS1 0x460 +#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS1__ECC_ERR 0x0002 +#define INTR_STATUS1__DMA_CMD_COMP 0x0004 +#define INTR_STATUS1__TIME_OUT 0x0008 +#define INTR_STATUS1__PROGRAM_FAIL 0x0010 +#define INTR_STATUS1__ERASE_FAIL 0x0020 +#define INTR_STATUS1__LOAD_COMP 0x0040 +#define INTR_STATUS1__PROGRAM_COMP 0x0080 +#define INTR_STATUS1__ERASE_COMP 0x0100 +#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS1__LOCKED_BLK 0x0400 +#define INTR_STATUS1__UNSUP_CMD 0x0800 +#define INTR_STATUS1__INT_ACT 0x1000 +#define INTR_STATUS1__RST_COMP 0x2000 +#define INTR_STATUS1__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS1__PAGE_XFER_INC 0x8000 + +#define INTR_EN1 0x470 +#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN1__ECC_ERR 0x0002 +#define INTR_EN1__DMA_CMD_COMP 0x0004 +#define INTR_EN1__TIME_OUT 0x0008 +#define INTR_EN1__PROGRAM_FAIL 0x0010 +#define INTR_EN1__ERASE_FAIL 0x0020 +#define INTR_EN1__LOAD_COMP 0x0040 +#define INTR_EN1__PROGRAM_COMP 0x0080 +#define INTR_EN1__ERASE_COMP 0x0100 +#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN1__LOCKED_BLK 0x0400 +#define INTR_EN1__UNSUP_CMD 0x0800 +#define INTR_EN1__INT_ACT 0x1000 +#define INTR_EN1__RST_COMP 0x2000 +#define INTR_EN1__PIPE_CMD_ERR 0x4000 +#define INTR_EN1__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT1 0x480 +#define PAGE_CNT1__VALUE 0x00ff + +#define ERR_PAGE_ADDR1 0x490 +#define ERR_PAGE_ADDR1__VALUE 0xffff + +#define ERR_BLOCK_ADDR1 0x4a0 +#define ERR_BLOCK_ADDR1__VALUE 0xffff + +#define INTR_STATUS2 0x4b0 +#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS2__ECC_ERR 0x0002 +#define INTR_STATUS2__DMA_CMD_COMP 0x0004 +#define INTR_STATUS2__TIME_OUT 0x0008 +#define INTR_STATUS2__PROGRAM_FAIL 0x0010 +#define INTR_STATUS2__ERASE_FAIL 0x0020 +#define INTR_STATUS2__LOAD_COMP 0x0040 +#define INTR_STATUS2__PROGRAM_COMP 0x0080 +#define INTR_STATUS2__ERASE_COMP 0x0100 +#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS2__LOCKED_BLK 0x0400 +#define INTR_STATUS2__UNSUP_CMD 0x0800 +#define INTR_STATUS2__INT_ACT 0x1000 +#define INTR_STATUS2__RST_COMP 0x2000 +#define INTR_STATUS2__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS2__PAGE_XFER_INC 0x8000 + +#define INTR_EN2 0x4c0 +#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN2__ECC_ERR 0x0002 +#define INTR_EN2__DMA_CMD_COMP 0x0004 +#define INTR_EN2__TIME_OUT 0x0008 +#define INTR_EN2__PROGRAM_FAIL 0x0010 +#define INTR_EN2__ERASE_FAIL 0x0020 +#define INTR_EN2__LOAD_COMP 0x0040 +#define INTR_EN2__PROGRAM_COMP 0x0080 +#define INTR_EN2__ERASE_COMP 0x0100 +#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN2__LOCKED_BLK 0x0400 +#define INTR_EN2__UNSUP_CMD 0x0800 +#define INTR_EN2__INT_ACT 0x1000 +#define INTR_EN2__RST_COMP 0x2000 +#define INTR_EN2__PIPE_CMD_ERR 0x4000 +#define INTR_EN2__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT2 0x4d0 +#define PAGE_CNT2__VALUE 0x00ff + +#define ERR_PAGE_ADDR2 0x4e0 +#define ERR_PAGE_ADDR2__VALUE 0xffff + +#define ERR_BLOCK_ADDR2 0x4f0 +#define ERR_BLOCK_ADDR2__VALUE 0xffff + +#define INTR_STATUS3 0x500 +#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001 +#define INTR_STATUS3__ECC_ERR 0x0002 +#define INTR_STATUS3__DMA_CMD_COMP 0x0004 +#define INTR_STATUS3__TIME_OUT 0x0008 +#define INTR_STATUS3__PROGRAM_FAIL 0x0010 +#define INTR_STATUS3__ERASE_FAIL 0x0020 +#define INTR_STATUS3__LOAD_COMP 0x0040 +#define INTR_STATUS3__PROGRAM_COMP 0x0080 +#define INTR_STATUS3__ERASE_COMP 0x0100 +#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_STATUS3__LOCKED_BLK 0x0400 +#define INTR_STATUS3__UNSUP_CMD 0x0800 +#define INTR_STATUS3__INT_ACT 0x1000 +#define INTR_STATUS3__RST_COMP 0x2000 +#define INTR_STATUS3__PIPE_CMD_ERR 0x4000 +#define INTR_STATUS3__PAGE_XFER_INC 0x8000 + +#define INTR_EN3 0x510 +#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001 +#define INTR_EN3__ECC_ERR 0x0002 +#define INTR_EN3__DMA_CMD_COMP 0x0004 +#define INTR_EN3__TIME_OUT 0x0008 +#define INTR_EN3__PROGRAM_FAIL 0x0010 +#define INTR_EN3__ERASE_FAIL 0x0020 +#define INTR_EN3__LOAD_COMP 0x0040 +#define INTR_EN3__PROGRAM_COMP 0x0080 +#define INTR_EN3__ERASE_COMP 0x0100 +#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR_EN3__LOCKED_BLK 0x0400 +#define INTR_EN3__UNSUP_CMD 0x0800 +#define INTR_EN3__INT_ACT 0x1000 +#define INTR_EN3__RST_COMP 0x2000 +#define INTR_EN3__PIPE_CMD_ERR 0x4000 +#define INTR_EN3__PAGE_XFER_INC 0x8000 + +#define PAGE_CNT3 0x520 +#define PAGE_CNT3__VALUE 0x00ff + +#define ERR_PAGE_ADDR3 0x530 +#define ERR_PAGE_ADDR3__VALUE 0xffff + +#define ERR_BLOCK_ADDR3 0x540 +#define ERR_BLOCK_ADDR3__VALUE 0xffff + +#define DATA_INTR 0x550 +#define DATA_INTR__WRITE_SPACE_AV 0x0001 +#define DATA_INTR__READ_DATA_AV 0x0002 + +#define DATA_INTR_EN 0x560 +#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001 +#define DATA_INTR_EN__READ_DATA_AV 0x0002 + +#define GPREG_0 0x570 +#define GPREG_0__VALUE 0xffff + +#define GPREG_1 0x580 +#define GPREG_1__VALUE 0xffff + +#define GPREG_2 0x590 +#define GPREG_2__VALUE 0xffff + +#define GPREG_3 0x5a0 +#define GPREG_3__VALUE 0xffff + +#define ECC_THRESHOLD 0x600 +#define ECC_THRESHOLD__VALUE 0x03ff + +#define ECC_ERROR_BLOCK_ADDRESS 0x610 +#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff + +#define ECC_ERROR_PAGE_ADDRESS 0x620 +#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff +#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000 + +#define ECC_ERROR_ADDRESS 0x630 +#define ECC_ERROR_ADDRESS__OFFSET 0x0fff +#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000 + +#define ERR_CORRECTION_INFO 0x640 +#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff +#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00 +#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000 +#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000 + +#define DMA_ENABLE 0x700 +#define DMA_ENABLE__FLAG 0x0001 + +#define IGNORE_ECC_DONE 0x710 +#define IGNORE_ECC_DONE__FLAG 0x0001 + +#define DMA_INTR 0x720 +#define DMA_INTR__TARGET_ERROR 0x0001 +#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002 +#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004 +#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008 +#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010 +#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 + +#define DMA_INTR_EN 0x730 +#define DMA_INTR_EN__TARGET_ERROR 0x0001 +#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002 +#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004 +#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008 +#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010 +#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020 + +#define TARGET_ERR_ADDR_LO 0x740 +#define TARGET_ERR_ADDR_LO__VALUE 0xffff + +#define TARGET_ERR_ADDR_HI 0x750 +#define TARGET_ERR_ADDR_HI__VALUE 0xffff + +#define CHNL_ACTIVE 0x760 +#define CHNL_ACTIVE__CHANNEL0 0x0001 +#define CHNL_ACTIVE__CHANNEL1 0x0002 +#define CHNL_ACTIVE__CHANNEL2 0x0004 +#define CHNL_ACTIVE__CHANNEL3 0x0008 + +#define ACTIVE_SRC_ID 0x800 +#define ACTIVE_SRC_ID__VALUE 0x00ff + +#define PTN_INTR 0x810 +#define PTN_INTR__CONFIG_ERROR 0x0001 +#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002 +#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004 +#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008 +#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010 +#define PTN_INTR__REG_ACCESS_ERROR 0x0020 + +#define PTN_INTR_EN 0x820 +#define PTN_INTR_EN__CONFIG_ERROR 0x0001 +#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002 +#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004 +#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008 +#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 +#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 + +#define PERM_SRC_ID_0 0x830 +#define PERM_SRC_ID_0__SRCID 0x00ff +#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_0__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_0__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_0 0x840 +#define MIN_BLK_ADDR_0__VALUE 0xffff + +#define MAX_BLK_ADDR_0 0x850 +#define MAX_BLK_ADDR_0__VALUE 0xffff + +#define MIN_MAX_BANK_0 0x860 +#define MIN_MAX_BANK_0__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_0__MAX_VALUE 0x000c + +#define PERM_SRC_ID_1 0x870 +#define PERM_SRC_ID_1__SRCID 0x00ff +#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_1__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_1__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_1 0x880 +#define MIN_BLK_ADDR_1__VALUE 0xffff + +#define MAX_BLK_ADDR_1 0x890 +#define MAX_BLK_ADDR_1__VALUE 0xffff + +#define MIN_MAX_BANK_1 0x8a0 +#define MIN_MAX_BANK_1__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_1__MAX_VALUE 0x000c + +#define PERM_SRC_ID_2 0x8b0 +#define PERM_SRC_ID_2__SRCID 0x00ff +#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_2__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_2__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_2 0x8c0 +#define MIN_BLK_ADDR_2__VALUE 0xffff + +#define MAX_BLK_ADDR_2 0x8d0 +#define MAX_BLK_ADDR_2__VALUE 0xffff + +#define MIN_MAX_BANK_2 0x8e0 +#define MIN_MAX_BANK_2__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_2__MAX_VALUE 0x000c + +#define PERM_SRC_ID_3 0x8f0 +#define PERM_SRC_ID_3__SRCID 0x00ff +#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_3__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_3__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_3 0x900 +#define MIN_BLK_ADDR_3__VALUE 0xffff + +#define MAX_BLK_ADDR_3 0x910 +#define MAX_BLK_ADDR_3__VALUE 0xffff + +#define MIN_MAX_BANK_3 0x920 +#define MIN_MAX_BANK_3__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_3__MAX_VALUE 0x000c + +#define PERM_SRC_ID_4 0x930 +#define PERM_SRC_ID_4__SRCID 0x00ff +#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_4__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_4__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_4 0x940 +#define MIN_BLK_ADDR_4__VALUE 0xffff + +#define MAX_BLK_ADDR_4 0x950 +#define MAX_BLK_ADDR_4__VALUE 0xffff + +#define MIN_MAX_BANK_4 0x960 +#define MIN_MAX_BANK_4__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_4__MAX_VALUE 0x000c + +#define PERM_SRC_ID_5 0x970 +#define PERM_SRC_ID_5__SRCID 0x00ff +#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_5__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_5__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_5 0x980 +#define MIN_BLK_ADDR_5__VALUE 0xffff + +#define MAX_BLK_ADDR_5 0x990 +#define MAX_BLK_ADDR_5__VALUE 0xffff + +#define MIN_MAX_BANK_5 0x9a0 +#define MIN_MAX_BANK_5__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_5__MAX_VALUE 0x000c + +#define PERM_SRC_ID_6 0x9b0 +#define PERM_SRC_ID_6__SRCID 0x00ff +#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_6__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_6__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_6 0x9c0 +#define MIN_BLK_ADDR_6__VALUE 0xffff + +#define MAX_BLK_ADDR_6 0x9d0 +#define MAX_BLK_ADDR_6__VALUE 0xffff + +#define MIN_MAX_BANK_6 0x9e0 +#define MIN_MAX_BANK_6__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_6__MAX_VALUE 0x000c + +#define PERM_SRC_ID_7 0x9f0 +#define PERM_SRC_ID_7__SRCID 0x00ff +#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 +#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 +#define PERM_SRC_ID_7__READ_ACTIVE 0x4000 +#define PERM_SRC_ID_7__PARTITION_VALID 0x8000 + +#define MIN_BLK_ADDR_7 0xa00 +#define MIN_BLK_ADDR_7__VALUE 0xffff + +#define MAX_BLK_ADDR_7 0xa10 +#define MAX_BLK_ADDR_7__VALUE 0xffff + +#define MIN_MAX_BANK_7 0xa20 +#define MIN_MAX_BANK_7__MIN_VALUE 0x0003 +#define MIN_MAX_BANK_7__MAX_VALUE 0x000c diff --git a/drivers/staging/spectra/spectraswconfig.h b/drivers/staging/spectra/spectraswconfig.h new file mode 100644 index 000000000000..557c091953d7 --- /dev/null +++ b/drivers/staging/spectra/spectraswconfig.h @@ -0,0 +1,82 @@ +/* + * NAND Flash Controller Device Driver + * Copyright (c) 2009, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _SPECTRASWCONFIG_ +#define _SPECTRASWCONFIG_ + +/* NAND driver version */ +#define GLOB_VERSION "driver version 20100311" + + +/***** Common Parameters *****/ +#define RETRY_TIMES 3 + +#define READ_BADBLOCK_INFO 1 +#define READBACK_VERIFY 0 +#define AUTO_FORMAT_FLASH 0 + +/***** Cache Parameters *****/ +#define CACHE_ITEM_NUM 128 +#define BLK_NUM_FOR_L2_CACHE 16 + +/***** Block Table Parameters *****/ +#define BLOCK_TABLE_INDEX 0 + +/***** Wear Leveling Parameters *****/ +#define WEAR_LEVELING_GATE 0x10 +#define WEAR_LEVELING_BLOCK_NUM 10 + +#define DEBUG_BNDRY 0 + +/***** Product Feature Support *****/ +#define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) +#define FLASH_NAND defined(CONFIG_MRST_NAND_HW) +#define FLASH_MTD defined(CONFIG_MRST_NAND_MTD) +#define CMD_DMA defined(CONFIG_MRST_NAND_HW_DMA) + +#define SPECTRA_PARTITION_ID 0 + +/* Enable this macro if the number of flash blocks is larger than 16K. */ +#define SUPPORT_LARGE_BLOCKNUM 1 + +/**** Block Table and Reserved Block Parameters *****/ +#define SPECTRA_START_BLOCK 3 +//#define NUM_FREE_BLOCKS_GATE 30 +#define NUM_FREE_BLOCKS_GATE 60 + +/**** Hardware Parameters ****/ +#define GLOB_HWCTL_REG_BASE 0xFFA40000 +#define GLOB_HWCTL_REG_SIZE 4096 + +#define GLOB_HWCTL_MEM_BASE 0xFFA48000 +#define GLOB_HWCTL_MEM_SIZE 4096 + +/* KBV - Updated to LNW scratch register address */ +#define SCRATCH_REG_ADDR 0xFF108018 +#define SCRATCH_REG_SIZE 64 + +#define GLOB_HWCTL_DEFAULT_BLKS 2048 + +#define SUPPORT_15BITECC 1 +#define SUPPORT_8BITECC 1 + +#define ONFI_BLOOM_TIME 0 +#define MODE5_WORKAROUND 1 + +#endif /*_SPECTRASWCONFIG_*/ -- cgit v1.2.3 From bf46b9a92e45044d0b41beed61ae118e560dd3e4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 8 Jun 2010 18:27:31 +0100 Subject: spectra: Rename config options This is the Spectra driver, so use CONFIG_SPECTRA. Signed-off-by: David Woodhouse --- drivers/staging/Makefile | 2 +- drivers/staging/spectra/Kconfig | 26 +++++++++++++------------- drivers/staging/spectra/Makefile | 10 +++++----- drivers/staging/spectra/spectraswconfig.h | 8 ++++---- 4 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 401049ef01d1..2e2f96ee2c80 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192SU) += rtl8192su/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ -obj-$(CONFIG_MRST_NAND) += spectra/ +obj-$(CONFIG_SPECTRA) += spectra/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_DREAM) += dream/ obj-$(CONFIG_POHMELFS) += pohmelfs/ diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig index 4bed96f68837..5e2ffefb60af 100644 --- a/drivers/staging/spectra/Kconfig +++ b/drivers/staging/spectra/Kconfig @@ -1,40 +1,40 @@ -menuconfig MRST_NAND - tristate "Moorestown NAND Flash controller" +menuconfig SPECTRA + tristate "Denali Spectra Flash Translation Layer" depends on BLOCK default n ---help--- - Enable the driver for the NAND Flash controller in Intel Moorestown - Platform + Enable the FTL pseudo-filesystem used with the NAND Flash + controller on Intel Moorestown Platform to pretend to be a disk choice prompt "Compile for" - depends on MRST_NAND - default MRST_NAND_HW + depends on SPECTRA + default SPECTRA_MRST_HW -config MRST_NAND_HW - bool "Actual hardware mode" +config SPECTRA_MRST_HW + bool "Moorestown hardware mode" help - Driver communicates with the actual hardware's register interface. + Driver communicates with the Moorestown hardware's register interface. in DMA mode. -config MRST_NAND_MTD +config SPECTRA_MTD bool "Linux MTD mode" depends on MTD help Driver communicates with the kernel MTD subsystem instead of its own built-in hardware driver. -config MRST_NAND_EMU +config SPECTRA_EMU bool "RAM emulator testing" help Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer. endchoice -config MRST_NAND_HW_DMA +config SPECTRA_MRST_HW_DMA bool default n - depends on MRST_NAND_HW + depends on SPECTRA_MRST_HW help Use DMA for native hardware interface. diff --git a/drivers/staging/spectra/Makefile b/drivers/staging/spectra/Makefile index 2a9490385339..f777dfba05a5 100644 --- a/drivers/staging/spectra/Makefile +++ b/drivers/staging/spectra/Makefile @@ -2,10 +2,10 @@ # Makefile of Intel Moorestown NAND controller driver # -obj-$(CONFIG_MRST_NAND) += spectra.o +obj-$(CONFIG_SPECTRA) += spectra.o spectra-y := ffsport.o flash.o lld.o -spectra-$(CONFIG_MRST_NAND_HW) += lld_nand.o -spectra-$(CONFIG_MRST_NAND_HW_DMA) += lld_cdma.o -spectra-$(CONFIG_MRST_NAND_EMU) += lld_emu.o -spectra-$(CONFIG_MRST_NAND_MTD) += lld_mtd.o +spectra-$(CONFIG_SPECTRA_MRST_HW) += lld_nand.o +spectra-$(CONFIG_SPECTRA_MRST_HW_DMA) += lld_cdma.o +spectra-$(CONFIG_SPECTRA_EMU) += lld_emu.o +spectra-$(CONFIG_SPECTRA_MTD) += lld_mtd.o diff --git a/drivers/staging/spectra/spectraswconfig.h b/drivers/staging/spectra/spectraswconfig.h index 557c091953d7..17259469e955 100644 --- a/drivers/staging/spectra/spectraswconfig.h +++ b/drivers/staging/spectra/spectraswconfig.h @@ -45,10 +45,10 @@ #define DEBUG_BNDRY 0 /***** Product Feature Support *****/ -#define FLASH_EMU defined(CONFIG_MRST_NAND_EMU) -#define FLASH_NAND defined(CONFIG_MRST_NAND_HW) -#define FLASH_MTD defined(CONFIG_MRST_NAND_MTD) -#define CMD_DMA defined(CONFIG_MRST_NAND_HW_DMA) +#define FLASH_EMU defined(CONFIG_SPECTRA_EMU) +#define FLASH_NAND defined(CONFIG_SPECTRA_MRST_HW) +#define FLASH_MTD defined(CONFIG_SPECTRA_MTD) +#define CMD_DMA defined(CONFIG_SPECTRA_MRST_HW_DMA) #define SPECTRA_PARTITION_ID 0 -- cgit v1.2.3 From 148c7866c31d93f8c79366189075f5a26ad4556c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 5 Jun 2010 11:46:49 +0200 Subject: firewire: ohci: do not enable interrupts without the handler On 26 Apr 2010, Clemens Ladisch wrote: > In theory, none of the interrupts should occur before the link is > enabled. In practice, I'd rather make sure to not set the master > interrupt enable bit until we have installed the interrupt handler. and proposed to move OHCI1394_masterIntEnable out of the present reg_write() into a new one before the HCControl.linkEnable reg_write(). Why not defer setting /all/ of the bits until right before linkEnable? Reviewed-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 07deac77bc13..9743a405e69c 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1594,7 +1594,7 @@ static int ohci_enable(struct fw_card *card, { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - u32 lps; + u32 lps, irqs; int i, ret; if (software_reset(ohci)) { @@ -1648,16 +1648,6 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); reg_write(ohci, OHCI1394_IntEventClear, ~0); reg_write(ohci, OHCI1394_IntMaskClear, ~0); - reg_write(ohci, OHCI1394_IntMaskSet, - OHCI1394_selfIDComplete | - OHCI1394_RQPkt | OHCI1394_RSPkt | - OHCI1394_reqTxComplete | OHCI1394_respTxComplete | - OHCI1394_isochRx | OHCI1394_isochTx | - OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | - OHCI1394_cycleInconsistent | OHCI1394_regAccessFail | - OHCI1394_masterIntEnable); - if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) - reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); ret = configure_1394a_enhancements(ohci); if (ret < 0) @@ -1723,6 +1713,18 @@ static int ohci_enable(struct fw_card *card, return -EIO; } + irqs = OHCI1394_reqTxComplete | OHCI1394_respTxComplete | + OHCI1394_RQPkt | OHCI1394_RSPkt | + OHCI1394_isochTx | OHCI1394_isochRx | + OHCI1394_postedWriteErr | + OHCI1394_selfIDComplete | + OHCI1394_regAccessFail | + OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong | + OHCI1394_masterIntEnable; + if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) + irqs |= OHCI1394_busReset; + reg_write(ohci, OHCI1394_IntMaskSet, irqs); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable | OHCI1394_HCControl_BIBimageValid); -- cgit v1.2.3 From 262444eecce40950af19ea4d75a3dc03b3c07283 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 5 Jun 2010 12:31:25 +0200 Subject: firewire: ohci: add MSI support This patch adds support for message-signaled interrupts. Any native PCI-Express OHCI controller should support MSI, but most are just PCI cores behind a PCI-E/PCI bridge. The only chips that are known to claim to support MSI are the Lucent/Agere/LSI FW643 and the VIA VT6315, none of which I have been able to test. Due to the high level of trust I have in the competence of these and any future chip makers, I thought it a good idea to add a disable-MSI quirk. Signed-off-by: Clemens Ladisch Tested Agere FW643 rev 07 [11c1:5901] and JMicron JMB381 [197b:2380]. Added a quirks list entry for JMB38X since it kept its count of MSI events consistently at zero. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9743a405e69c..de5ff376231c 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -231,12 +231,14 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; +#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 #define QUIRK_CYCLE_TIMER 1 #define QUIRK_RESET_PACKET 2 #define QUIRK_BE_HEADERS 4 #define QUIRK_NO_1394A 8 +#define QUIRK_NO_MSI 16 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { @@ -247,6 +249,7 @@ static const struct { QUIRK_NO_1394A}, {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, + {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI}, {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS}, @@ -260,6 +263,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) + ", disable MSI = " __stringify(QUIRK_NO_MSI) ")"); #define OHCI_PARAM_DEBUG_AT_AR 1 @@ -1704,10 +1708,13 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); + if (!(ohci->quirks & QUIRK_NO_MSI)) + pci_enable_msi(dev); if (request_irq(dev->irq, irq_handler, - IRQF_SHARED, ohci_driver_name, ohci)) { - fw_error("Failed to allocate shared interrupt %d.\n", - dev->irq); + pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, + ohci_driver_name, ohci)) { + fw_error("Failed to allocate interrupt %d.\n", dev->irq); + pci_disable_msi(dev); dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, ohci->config_rom, ohci->config_rom_bus); return -EIO; @@ -2622,6 +2629,7 @@ static void pci_remove(struct pci_dev *dev) context_release(&ohci->at_response_ctx); kfree(ohci->it_context_list); kfree(ohci->ir_context_list); + pci_disable_msi(dev); pci_iounmap(dev, ohci->registers); pci_release_region(dev, 0); pci_disable_device(dev); @@ -2639,6 +2647,7 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state) software_reset(ohci); free_irq(dev->irq, ohci); + pci_disable_msi(dev); err = pci_save_state(dev); if (err) { fw_error("pci_save_state failed\n"); -- cgit v1.2.3 From a10c0ce76098857b899505d05de9f2e13ddf7a7a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 19 May 2010 08:28:32 +0200 Subject: firewire: check cdev response length Add a check that the data length in the SEND_RESPONSE ioctl is correct. Incidentally, this also fixes the previously wrong response length of software-handled lock requests. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 9 ++++++--- drivers/firewire/core-transaction.c | 38 ++++++++++++++++++++++++++++++++++++- drivers/firewire/core.h | 1 + 3 files changed, 44 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 9d1a1a1a83c9..50332b84f49a 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -756,9 +756,12 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg) if (is_fcp_request(r->request)) goto out; - if (a->length < r->length) - r->length = a->length; - if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) { + if (a->length != fw_get_response_length(r->request)) { + ret = -EINVAL; + kfree(r->request); + goto out; + } + if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) { ret = -EFAULT; kfree(r->request); goto out; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index fdc33ff06dc1..4fd5c3b2128e 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -580,6 +580,41 @@ static void free_response_callback(struct fw_packet *packet, kfree(request); } +int fw_get_response_length(struct fw_request *r) +{ + int tcode, ext_tcode, data_length; + + tcode = HEADER_GET_TCODE(r->request_header[0]); + + switch (tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + return 0; + + case TCODE_READ_QUADLET_REQUEST: + return 4; + + case TCODE_READ_BLOCK_REQUEST: + data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]); + return data_length; + + case TCODE_LOCK_REQUEST: + ext_tcode = HEADER_GET_EXTENDED_TCODE(r->request_header[3]); + data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]); + switch (ext_tcode) { + case EXTCODE_FETCH_ADD: + case EXTCODE_LITTLE_ADD: + return data_length; + default: + return data_length / 2; + } + + default: + WARN(1, KERN_ERR "wrong tcode %d", tcode); + return 0; + } +} + void fw_fill_response(struct fw_packet *response, u32 *request_header, int rcode, void *payload, size_t length) { @@ -713,7 +748,8 @@ void fw_send_response(struct fw_card *card, if (rcode == RCODE_COMPLETE) fw_fill_response(&request->response, request->request_header, - rcode, request->data, request->length); + rcode, request->data, + fw_get_response_length(request)); else fw_fill_response(&request->response, request->request_header, rcode, NULL, 0); diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 0ecfcd95f4c5..25a72e57a0cd 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -218,6 +218,7 @@ static inline bool is_next_generation(int new_generation, int old_generation) void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); +int fw_get_response_length(struct fw_request *request); void fw_fill_response(struct fw_packet *response, u32 *request_header, int rcode, void *payload, size_t length); void fw_send_phy_config(struct fw_card *card, -- cgit v1.2.3 From f9c70f9129f2d88645c3a26711302a7f6ba9afd0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 5 Jun 2010 20:32:50 +0200 Subject: firewire: core: trivial fix for warning strings WARN's format string argument should not carry a printk level prefix. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 4fd5c3b2128e..f33a629c8379 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -246,7 +246,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, break; default: - WARN(1, KERN_ERR "wrong tcode %d", tcode); + WARN(1, "wrong tcode %d", tcode); } common: packet->speed = speed; @@ -610,7 +610,7 @@ int fw_get_response_length(struct fw_request *r) } default: - WARN(1, KERN_ERR "wrong tcode %d", tcode); + WARN(1, "wrong tcode %d", tcode); return 0; } } @@ -666,7 +666,7 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, break; default: - WARN(1, KERN_ERR "wrong tcode %d", tcode); + WARN(1, "wrong tcode %d", tcode); } response->payload_mapped = false; -- cgit v1.2.3 From 153e3979201b76dbd5788f032fb683e95121e159 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:22:07 +0200 Subject: firewire: ohci: speed up PHY register accesses Most PHY chips, when idle, can complete a register access in the time needed for two or three PCI read transactions; bigger delays occur only when data is currently being moved over the link/PHY interface. So if we busy-wait a few times when waiting for the register access to finish, it is likely that we can finish without having to sleep. Signed-off-by: Clemens Ladisch --- drivers/firewire/ohci.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index de5ff376231c..65b9bdb8541a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -474,12 +474,17 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr) int i; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); - for (i = 0; i < 10; i++) { + for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); if (val & OHCI1394_PhyControl_ReadDone) return OHCI1394_PhyControl_ReadData(val); - msleep(1); + /* + * Try a few times without waiting. Sleeping is necessary + * only when the link/PHY interface is busy. + */ + if (i >= 3) + msleep(1); } fw_error("failed to read phy reg\n"); @@ -492,12 +497,13 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Write(addr, val)); - for (i = 0; i < 100; i++) { + for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); if (!(val & OHCI1394_PhyControl_WritePending)) return 0; - msleep(1); + if (i >= 3) + msleep(1); } fw_error("failed to write phy reg\n"); -- cgit v1.2.3 From bda3b8a1faf209a98063ccd77d6833a2bb0fc77e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:23:28 +0200 Subject: firewire: core: retry on local errors in bus manager election When the candidate bus manager fails to do the lock request with which it tries to become bus manager, it assumes that the current IRM is not actually IRM capable and forces itself to become root. However, if that lock request failed because the local node itself was not able to send it, then we cannot blame the current IRM and should not steal its rootness. In this case, RCODE_SEND_ERROR is likely to indicate a temporary error condition such as exhausted tlabels or low memory, so we better try again later. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 9dcb30466ec0..901435cdd5c2 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -306,6 +306,16 @@ static void fw_card_bm_work(struct work_struct *work) goto out; } + if (rcode == RCODE_SEND_ERROR) { + /* + * We have been unable to send the lock request due to + * some local problem. Let's try again later and hope + * that the problem has gone away by then. + */ + fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); + goto out; + } + spin_lock_irqsave(&card->lock, flags); if (rcode != RCODE_COMPLETE) { -- cgit v1.2.3 From 3e07ec0eee1662f89e57f84aff625065beb2b209 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:24:03 +0200 Subject: firewire: core: add CSR STATE_CLEAR/STATE_SET support The state registers are zero and read-only in this implementation, so they are not of much use. However, the specification requires that they are present for transaction capable nodes, and the Base 1394 Test Suite tests for them, so we better implement them. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index f33a629c8379..6971400b6354 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -969,6 +969,30 @@ static const struct fw_address_region registers_region = { .start = CSR_REGISTER_BASE, .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; +static u32 read_state_register(struct fw_card *card) +{ + /* + * Fixed bits (IEEE 1394-2008 8.3.2.2.1): + * Bits 0-1 (state) always read 00=running. + * Bits 2,3 (off, atn) are not implemented as per the spec. + * Bit 4 (elog) is not implemented because there is no error log. + * Bit 6 (dreq) cannot be set. It is intended to "disable requests + * from unreliable nodes"; however, IEEE 1212 states that devices + * may "clear their own dreq bit when it has been improperly set". + * Our implementation might be seen as an improperly extensive + * interpretation of "improperly", but the 1212-2001 revision + * dropped this bit altogether, so we're in the clear. :o) + * Bit 7 (lost) always reads 0 because a power reset has never occurred + * during normal operation. + * Bit 9 (linkoff) is not implemented because the PC is not powered + * from the FireWire cable. + * Bit 15 (gone) always reads 0. It must be set at a power/command/bus + * reset, but then cleared when the units are ready again, which + * happens immediately for us. + */ + return 0; +} + static void handle_registers(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, int speed, unsigned long long offset, @@ -979,6 +1003,26 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, int rcode = RCODE_COMPLETE; switch (reg) { + case CSR_STATE_CLEAR: + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(read_state_register(card)); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + } else { + rcode = RCODE_TYPE_ERROR; + } + break; + + case CSR_STATE_SET: + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(read_state_register(card)); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + /* FIXME: implement cmstr */ + /* FIXME: implement abdicate */ + } else { + rcode = RCODE_TYPE_ERROR; + } + break; + case CSR_CYCLE_TIME: if (TCODE_IS_READ_REQUEST(tcode) && length == 4) *data = cpu_to_be32(card->driver->get_cycle_time(card)); -- cgit v1.2.3 From 60d32970c5a32e8c4f340a9e41993759ad658ef2 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:24:35 +0200 Subject: firewire: add read_csr_reg driver callback To prepare for the following additions of more OHCI-implemented CSR registers, replace the get_cycle_time driver callback with a generic CSR register callback. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-cdev.c | 2 +- drivers/firewire/core-transaction.c | 3 ++- drivers/firewire/core.h | 2 +- drivers/firewire/ohci.c | 19 ++++++++++++++++--- 4 files changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 50332b84f49a..2e62516a4b15 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1044,7 +1044,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) local_irq_disable(); - cycle_time = card->driver->get_cycle_time(card); + cycle_time = card->driver->read_csr_reg(card, CSR_CYCLE_TIME); switch (a->clk_id) { case CLOCK_REALTIME: getnstimeofday(&ts); break; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 6971400b6354..a4d8109edec2 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1025,7 +1025,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, case CSR_CYCLE_TIME: if (TCODE_IS_READ_REQUEST(tcode) && length == 4) - *data = cpu_to_be32(card->driver->get_cycle_time(card)); + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_CYCLE_TIME)); else rcode = RCODE_TYPE_ERROR; break; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 25a72e57a0cd..c19e9873e433 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -75,7 +75,7 @@ struct fw_card_driver { int (*enable_phys_dma)(struct fw_card *card, int node_id, int generation); - u32 (*get_cycle_time)(struct fw_card *card); + u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 65b9bdb8541a..a8093a9a3fc8 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1939,9 +1939,8 @@ static u32 cycle_timer_ticks(u32 cycle_timer) * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to * execute, so we have enough precision to compute the ratio of the differences.) */ -static u32 ohci_get_cycle_time(struct fw_card *card) +static u32 get_cycle_time(struct fw_ohci *ohci) { - struct fw_ohci *ohci = fw_ohci(card); u32 c0, c1, c2; u32 t0, t1, t2; s32 diff01, diff12; @@ -1970,6 +1969,20 @@ static u32 ohci_get_cycle_time(struct fw_card *card) return c2; } +static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) +{ + struct fw_ohci *ohci = fw_ohci(card); + + switch (csr_offset) { + case CSR_CYCLE_TIME: + return get_cycle_time(ohci); + + default: + WARN_ON(1); + return 0; + } +} + static void copy_iso_headers(struct iso_context *ctx, void *p) { int i = ctx->header_length; @@ -2407,7 +2420,7 @@ static const struct fw_card_driver ohci_driver = { .send_response = ohci_send_response, .cancel_packet = ohci_cancel_packet, .enable_phys_dma = ohci_enable_phys_dma, - .get_cycle_time = ohci_get_cycle_time, + .read_csr_reg = ohci_read_csr_reg, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, -- cgit v1.2.3 From 506f1a31932747f56a5029d5b3c14b1b68f41ccc Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:25:19 +0200 Subject: firewire: add CSR NODE_IDS support The NODE_IDS register, and especially its bus_id field, is quite useless because 1394.1 requires that the bus_id field always stays 0x3ff. However, the 1394 specification requires this register on all transaction capable nodes, and the Base 1394 Test Suite tests for it, so we better implement it. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 11 +++++++++++ drivers/firewire/core.h | 1 + drivers/firewire/ohci.c | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index a4d8109edec2..16ffa27d23b7 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1023,6 +1023,17 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, } break; + case CSR_NODE_IDS: + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_NODE_IDS)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->driver->write_csr_reg(card, CSR_NODE_IDS, + be32_to_cpu(*data)); + else + rcode = RCODE_TYPE_ERROR; + break; + case CSR_CYCLE_TIME: if (TCODE_IS_READ_REQUEST(tcode) && length == 4) *data = cpu_to_be32(card->driver-> diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c19e9873e433..efcdeb2e31e6 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -76,6 +76,7 @@ struct fw_card_driver { int node_id, int generation); u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); + void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index a8093a9a3fc8..a55fbbce9e79 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1974,6 +1974,9 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) struct fw_ohci *ohci = fw_ohci(card); switch (csr_offset) { + case CSR_NODE_IDS: + return reg_read(ohci, OHCI1394_NodeID) << 16; + case CSR_CYCLE_TIME: return get_cycle_time(ohci); @@ -1983,6 +1986,22 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) } } +static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) +{ + struct fw_ohci *ohci = fw_ohci(card); + + switch (csr_offset) { + case CSR_NODE_IDS: + reg_write(ohci, OHCI1394_NodeID, value >> 16); + flush_writes(ohci); + break; + + default: + WARN_ON(1); + break; + } +} + static void copy_iso_headers(struct iso_context *ctx, void *p) { int i = ctx->header_length; @@ -2421,6 +2440,7 @@ static const struct fw_card_driver ohci_driver = { .cancel_packet = ohci_cancel_packet, .enable_phys_dma = ohci_enable_phys_dma, .read_csr_reg = ohci_read_csr_reg, + .write_csr_reg = ohci_write_csr_reg, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, -- cgit v1.2.3 From 446eba0d6896787b2f02f7a665838d32aa7b9d3f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:25:46 +0200 Subject: firewire: core: add CSR RESET_START support This implements the RESET_START register (as a dummy) to make the Base 1394 Test Suite happy. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 16ffa27d23b7..0034229dfd14 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1034,6 +1034,11 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_RESET_START: + if (tcode != TCODE_WRITE_QUADLET_REQUEST) + rcode = RCODE_TYPE_ERROR; + break; + case CSR_CYCLE_TIME: if (TCODE_IS_READ_REQUEST(tcode) && length == 4) *data = cpu_to_be32(card->driver-> -- cgit v1.2.3 From 8e4b50f94e8c1435a3e0ece42b7f97bc857d0145 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:26:28 +0200 Subject: firewire: core: add CSR SPLIT_TIMEOUT support Implement the SPLIT_TIMEOUT registers. Besides being required by the spec, this is desirable for some IIDC devices and necessary for many audio devices to be able to increase the timeout from userspace. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 4 ++ drivers/firewire/core-transaction.c | 76 +++++++++++++++++++++++++++++++------ include/linux/firewire.h | 5 +++ 3 files changed, 74 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 901435cdd5c2..d0f15c2f1e1d 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -428,6 +428,10 @@ void fw_card_initialize(struct fw_card *card, card->device = device; card->current_tlabel = 0; card->tlabel_mask = 0; + card->split_timeout_hi = 0; + card->split_timeout_lo = 800 << 19; + card->split_timeout_cycles = 800; + card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10); card->color = 0; card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 0034229dfd14..9a7d3ec23f2b 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -339,7 +339,8 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, setup_timer(&t->split_timeout_timer, split_transaction_timeout_callback, (unsigned long)t); /* FIXME: start this timer later, relative to t->timestamp */ - mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10)); + mod_timer(&t->split_timeout_timer, + jiffies + card->split_timeout_jiffies); t->callback = callback; t->callback_data = callback_data; @@ -673,11 +674,28 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, } EXPORT_SYMBOL(fw_fill_response); -static struct fw_request *allocate_request(struct fw_packet *p) +static u32 compute_split_timeout_timestamp(struct fw_card *card, + u32 request_timestamp) +{ + unsigned int cycles; + u32 timestamp; + + cycles = card->split_timeout_cycles; + cycles += request_timestamp & 0x1fff; + + timestamp = request_timestamp & ~0x1fff; + timestamp += (cycles / 8000) << 13; + timestamp |= cycles % 8000; + + return timestamp; +} + +static struct fw_request *allocate_request(struct fw_card *card, + struct fw_packet *p) { struct fw_request *request; u32 *data, length; - int request_tcode, t; + int request_tcode; request_tcode = HEADER_GET_TCODE(p->header[0]); switch (request_tcode) { @@ -712,14 +730,9 @@ static struct fw_request *allocate_request(struct fw_packet *p) if (request == NULL) return NULL; - t = (p->timestamp & 0x1fff) + 4000; - if (t >= 8000) - t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; - else - t = (p->timestamp & ~0x1fff) + t; - request->response.speed = p->speed; - request->response.timestamp = t; + request->response.timestamp = + compute_split_timeout_timestamp(card, p->timestamp); request->response.generation = p->generation; request->response.ack = 0; request->response.callback = free_response_callback; @@ -845,7 +858,7 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) return; - request = allocate_request(p); + request = allocate_request(card, p); if (request == NULL) { /* FIXME: send statically allocated busy packet. */ return; @@ -993,6 +1006,19 @@ static u32 read_state_register(struct fw_card *card) return 0; } +static void update_split_timeout(struct fw_card *card) +{ + unsigned int cycles; + + cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19); + + cycles = max(cycles, 800u); /* minimum as per the spec */ + cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */ + + card->split_timeout_cycles = cycles; + card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000); +} + static void handle_registers(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, int speed, unsigned long long offset, @@ -1001,6 +1027,7 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, int reg = offset & ~CSR_REGISTER_BASE; __be32 *data = payload; int rcode = RCODE_COMPLETE; + unsigned long flags; switch (reg) { case CSR_STATE_CLEAR: @@ -1039,6 +1066,33 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_SPLIT_TIMEOUT_HI: + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(card->split_timeout_hi); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + spin_lock_irqsave(&card->lock, flags); + card->split_timeout_hi = be32_to_cpu(*data) & 7; + update_split_timeout(card); + spin_unlock_irqrestore(&card->lock, flags); + } else { + rcode = RCODE_TYPE_ERROR; + } + break; + + case CSR_SPLIT_TIMEOUT_LO: + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(card->split_timeout_lo); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + spin_lock_irqsave(&card->lock, flags); + card->split_timeout_lo = + be32_to_cpu(*data) & 0xfff80000; + update_split_timeout(card); + spin_unlock_irqrestore(&card->lock, flags); + } else { + rcode = RCODE_TYPE_ERROR; + } + break; + case CSR_CYCLE_TIME: if (TCODE_IS_READ_REQUEST(tcode) && length == 4) *data = cpu_to_be32(card->driver-> diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 72e2b8ac2a5a..cdf8213c68ca 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -89,6 +89,11 @@ struct fw_card { struct list_head transaction_list; unsigned long reset_jiffies; + u32 split_timeout_hi; + u32 split_timeout_lo; + unsigned int split_timeout_cycles; + unsigned int split_timeout_jiffies; + unsigned long long guid; unsigned max_receive; int link_speed; -- cgit v1.2.3 From 9ab5071cd4a16001e4ba790172a7da5e4172462b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:26:48 +0200 Subject: firewire: add CSR CYCLE_TIME write support The specification requires that CYCLE_TIME is writable so that it can be initialized, so we better implement it. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 3 +++ drivers/firewire/ohci.c | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 9a7d3ec23f2b..e3925f67ec12 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1097,6 +1097,9 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, if (TCODE_IS_READ_REQUEST(tcode) && length == 4) *data = cpu_to_be32(card->driver-> read_csr_reg(card, CSR_CYCLE_TIME)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->driver->write_csr_reg(card, CSR_CYCLE_TIME, + be32_to_cpu(*data)); else rcode = RCODE_TYPE_ERROR; break; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index a55fbbce9e79..777811a736b2 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1996,6 +1996,13 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) flush_writes(ohci); break; + case CSR_CYCLE_TIME: + reg_write(ohci, OHCI1394_IsochronousCycleTimer, value); + reg_write(ohci, OHCI1394_IntEventSet, + OHCI1394_cycleInconsistent); + flush_writes(ohci); + break; + default: WARN_ON(1); break; -- cgit v1.2.3 From a48777e03ad53777ed119a5f86dd22a6c5a378ad Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:33:07 +0200 Subject: firewire: add CSR BUS_TIME support Implement the BUS_TIME register, which is required for cycle master capable nodes and tested for by the Base 1393 Test Suite. Even when there is not yet bus master initialization support, this register allows us to work together with other bus masters. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 14 ++- drivers/firewire/ohci.c | 168 +++++++++++++++++++++++------------- 2 files changed, 120 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index e3925f67ec12..2a390726fa76 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1104,6 +1104,17 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_BUS_TIME: + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_BUS_TIME)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->driver->write_csr_reg(card, CSR_BUS_TIME, + be32_to_cpu(*data)); + else + rcode = RCODE_TYPE_ERROR; + break; + case CSR_BROADCAST_CHANNEL: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->broadcast_channel); @@ -1132,9 +1143,6 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, case CSR_BUSY_TIMEOUT: /* FIXME: Implement this. */ - case CSR_BUS_TIME: - /* Useless without initialization by the bus manager. */ - default: rcode = RCODE_ADDRESS_ERROR; break; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 777811a736b2..3d4badb7c79b 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -170,6 +170,7 @@ struct fw_ohci { int generation; int request_generation; /* for timestamping incoming requests */ unsigned quirks; + u32 bus_time; /* * Spinlock for accessing fw_ohci data. Never call out of @@ -292,7 +293,7 @@ static void log_irqs(u32 evt) !(evt & OHCI1394_busReset)) return; - fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, + fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, evt & OHCI1394_selfIDComplete ? " selfID" : "", evt & OHCI1394_RQPkt ? " AR_req" : "", evt & OHCI1394_RSPkt ? " AR_resp" : "", @@ -302,6 +303,7 @@ static void log_irqs(u32 evt) evt & OHCI1394_isochTx ? " IT" : "", evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", + evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", evt & OHCI1394_regAccessFail ? " regAccessFail" : "", evt & OHCI1394_busReset ? " busReset" : "", @@ -309,7 +311,8 @@ static void log_irqs(u32 evt) OHCI1394_RSPkt | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | OHCI1394_postedWriteErr | - OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent | + OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds | + OHCI1394_cycleInconsistent | OHCI1394_regAccessFail | OHCI1394_busReset) ? " ?" : ""); } @@ -1316,6 +1319,78 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet) } +static u32 cycle_timer_ticks(u32 cycle_timer) +{ + u32 ticks; + + ticks = cycle_timer & 0xfff; + ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); + ticks += (3072 * 8000) * (cycle_timer >> 25); + + return ticks; +} + +/* + * Some controllers exhibit one or more of the following bugs when updating the + * iso cycle timer register: + * - When the lowest six bits are wrapping around to zero, a read that happens + * at the same time will return garbage in the lowest ten bits. + * - When the cycleOffset field wraps around to zero, the cycleCount field is + * not incremented for about 60 ns. + * - Occasionally, the entire register reads zero. + * + * To catch these, we read the register three times and ensure that the + * difference between each two consecutive reads is approximately the same, i.e. + * less than twice the other. Furthermore, any negative difference indicates an + * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to + * execute, so we have enough precision to compute the ratio of the differences.) + */ +static u32 get_cycle_time(struct fw_ohci *ohci) +{ + u32 c0, c1, c2; + u32 t0, t1, t2; + s32 diff01, diff12; + int i; + + c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + + if (ohci->quirks & QUIRK_CYCLE_TIMER) { + i = 0; + c1 = c2; + c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + do { + c0 = c1; + c1 = c2; + c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + t0 = cycle_timer_ticks(c0); + t1 = cycle_timer_ticks(c1); + t2 = cycle_timer_ticks(c2); + diff01 = t1 - t0; + diff12 = t2 - t1; + } while ((diff01 <= 0 || diff12 <= 0 || + diff01 / diff12 >= 2 || diff12 / diff01 >= 2) + && i++ < 20); + } + + return c2; +} + +/* + * This function has to be called at least every 64 seconds. The bus_time + * field stores not only the upper 25 bits of the BUS_TIME register but also + * the most significant bit of the cycle timer in bit 6 so that we can detect + * changes in this bit. + */ +static u32 update_bus_time(struct fw_ohci *ohci) +{ + u32 cycle_time_seconds = get_cycle_time(ohci) >> 25; + + if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40)) + ohci->bus_time += 0x40; + + return ohci->bus_time | cycle_time_seconds; +} + static void bus_reset_tasklet(unsigned long data) { struct fw_ohci *ohci = (struct fw_ohci *)data; @@ -1520,6 +1595,12 @@ static irqreturn_t irq_handler(int irq, void *data) fw_notify("isochronous cycle inconsistent\n"); } + if (event & OHCI1394_cycle64Seconds) { + spin_lock(&ohci->lock); + update_bus_time(ohci); + spin_unlock(&ohci->lock); + } + return IRQ_HANDLED; } @@ -1604,7 +1685,7 @@ static int ohci_enable(struct fw_card *card, { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - u32 lps, irqs; + u32 lps, seconds, irqs; int i, ret; if (software_reset(ohci)) { @@ -1652,6 +1733,10 @@ static int ohci_enable(struct fw_card *card, (OHCI1394_MAX_AT_RESP_RETRIES << 4) | (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); + seconds = lower_32_bits(get_seconds()); + reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); + ohci->bus_time = seconds & ~0x3f; + ar_context_run(&ohci->ar_request_ctx); ar_context_run(&ohci->ar_response_ctx); @@ -1732,6 +1817,7 @@ static int ohci_enable(struct fw_card *card, OHCI1394_postedWriteErr | OHCI1394_selfIDComplete | OHCI1394_regAccessFail | + OHCI1394_cycle64Seconds | OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong | OHCI1394_masterIntEnable; if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) @@ -1913,65 +1999,11 @@ static int ohci_enable_phys_dma(struct fw_card *card, #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } -static u32 cycle_timer_ticks(u32 cycle_timer) -{ - u32 ticks; - - ticks = cycle_timer & 0xfff; - ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); - ticks += (3072 * 8000) * (cycle_timer >> 25); - - return ticks; -} - -/* - * Some controllers exhibit one or more of the following bugs when updating the - * iso cycle timer register: - * - When the lowest six bits are wrapping around to zero, a read that happens - * at the same time will return garbage in the lowest ten bits. - * - When the cycleOffset field wraps around to zero, the cycleCount field is - * not incremented for about 60 ns. - * - Occasionally, the entire register reads zero. - * - * To catch these, we read the register three times and ensure that the - * difference between each two consecutive reads is approximately the same, i.e. - * less than twice the other. Furthermore, any negative difference indicates an - * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to - * execute, so we have enough precision to compute the ratio of the differences.) - */ -static u32 get_cycle_time(struct fw_ohci *ohci) -{ - u32 c0, c1, c2; - u32 t0, t1, t2; - s32 diff01, diff12; - int i; - - c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - - if (ohci->quirks & QUIRK_CYCLE_TIMER) { - i = 0; - c1 = c2; - c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - do { - c0 = c1; - c1 = c2; - c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - t0 = cycle_timer_ticks(c0); - t1 = cycle_timer_ticks(c1); - t2 = cycle_timer_ticks(c2); - diff01 = t1 - t0; - diff12 = t2 - t1; - } while ((diff01 <= 0 || diff12 <= 0 || - diff01 / diff12 >= 2 || diff12 / diff01 >= 2) - && i++ < 20); - } - - return c2; -} - static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) { struct fw_ohci *ohci = fw_ohci(card); + unsigned long flags; + u32 value; switch (csr_offset) { case CSR_NODE_IDS: @@ -1980,6 +2012,17 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) case CSR_CYCLE_TIME: return get_cycle_time(ohci); + case CSR_BUS_TIME: + /* + * We might be called just after the cycle timer has wrapped + * around but just before the cycle64Seconds handler, so we + * better check here, too, if the bus time needs to be updated. + */ + spin_lock_irqsave(&ohci->lock, flags); + value = update_bus_time(ohci); + spin_unlock_irqrestore(&ohci->lock, flags); + return value; + default: WARN_ON(1); return 0; @@ -1989,6 +2032,7 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) { struct fw_ohci *ohci = fw_ohci(card); + unsigned long flags; switch (csr_offset) { case CSR_NODE_IDS: @@ -2003,6 +2047,12 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) flush_writes(ohci); break; + case CSR_BUS_TIME: + spin_lock_irqsave(&ohci->lock, flags); + ohci->bus_time = (ohci->bus_time & 0x7f) | (value & ~0x7f); + spin_unlock_irqrestore(&ohci->lock, flags); + break; + default: WARN_ON(1); break; -- cgit v1.2.3 From 27a2329f8235d6ce637463f5d83e98d760ef006e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:34:13 +0200 Subject: firewire: add CSR BUSY_TIMEOUT support Implement the BUSY_TIMEOUT register, which is required for nodes that support retries. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 14 +++++++++++--- drivers/firewire/ohci.c | 14 +++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 2a390726fa76..8146133818dc 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1115,6 +1115,17 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_BUSY_TIMEOUT: + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_BUSY_TIMEOUT)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->driver->write_csr_reg(card, CSR_BUSY_TIMEOUT, + be32_to_cpu(*data)); + else + rcode = RCODE_TYPE_ERROR; + break; + case CSR_BROADCAST_CHANNEL: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->broadcast_channel); @@ -1140,9 +1151,6 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, BUG(); break; - case CSR_BUSY_TIMEOUT: - /* FIXME: Implement this. */ - default: rcode = RCODE_ADDRESS_ERROR; break; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 3d4badb7c79b..9c588fd01250 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1731,7 +1731,8 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_ATRetries, OHCI1394_MAX_AT_REQ_RETRIES | (OHCI1394_MAX_AT_RESP_RETRIES << 4) | - (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); + (OHCI1394_MAX_PHYS_RESP_RETRIES << 8) | + (200 << 16)); seconds = lower_32_bits(get_seconds()); reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); @@ -2023,6 +2024,10 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) spin_unlock_irqrestore(&ohci->lock, flags); return value; + case CSR_BUSY_TIMEOUT: + value = reg_read(ohci, OHCI1394_ATRetries); + return (value >> 4) & 0x0ffff00f; + default: WARN_ON(1); return 0; @@ -2053,6 +2058,13 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) spin_unlock_irqrestore(&ohci->lock, flags); break; + case CSR_BUSY_TIMEOUT: + value = (value & 0xf) | ((value & 0xf) << 4) | + ((value & 0xf) << 8) | ((value & 0x0ffff000) << 4); + reg_write(ohci, OHCI1394_ATRetries, value); + flush_writes(ohci); + break; + default: WARN_ON(1); break; -- cgit v1.2.3 From a1a1132bd83d0aea51d4f19be4b4a58a064a0131 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:35:06 +0200 Subject: firewire: add CSR PRIORITY_BUDGET support If supported by the OHCI controller, implement the PRIORITY_BUDGET register, which is required for nodes that can use asynchronous priority arbitration. To allow the core to determine what features the lowlevel device supports, add a new card driver callback. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 14 ++++++++++++++ drivers/firewire/core.h | 4 ++++ drivers/firewire/ohci.c | 27 +++++++++++++++++++++++++++ include/linux/firewire.h | 1 + 4 files changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 8146133818dc..a61eb3fb9573 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1126,6 +1126,20 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_PRIORITY_BUDGET: + if (!(card->driver->get_features(card) & + FEATURE_PRIORITY_BUDGET)) + rcode = RCODE_ADDRESS_ERROR; + else if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_PRIORITY_BUDGET)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->driver->write_csr_reg(card, CSR_PRIORITY_BUDGET, + be32_to_cpu(*data)); + else + rcode = RCODE_TYPE_ERROR; + break; + case CSR_BROADCAST_CHANNEL: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->broadcast_channel); diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index efcdeb2e31e6..3b8c0f042f49 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -38,6 +38,8 @@ struct fw_packet; #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) #define BROADCAST_CHANNEL_VALID (1 << 30) +#define FEATURE_PRIORITY_BUDGET 0x01 + struct fw_card_driver { /* * Enable the given card with the given initial config rom. @@ -78,6 +80,8 @@ struct fw_card_driver { u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); + unsigned int (*get_features)(struct fw_card *card); + struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, int type, int channel, size_t header_size); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9c588fd01250..0e5413531785 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -170,6 +170,7 @@ struct fw_ohci { int generation; int request_generation; /* for timestamping incoming requests */ unsigned quirks; + unsigned int pri_req_max; u32 bus_time; /* @@ -1738,6 +1739,11 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); ohci->bus_time = seconds & ~0x3f; + /* Get implemented bits of the priority arbitration request counter. */ + reg_write(ohci, OHCI1394_FairnessControl, 0x3f); + ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; + reg_write(ohci, OHCI1394_FairnessControl, 0); + ar_context_run(&ohci->ar_request_ctx); ar_context_run(&ohci->ar_response_ctx); @@ -2028,6 +2034,10 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) value = reg_read(ohci, OHCI1394_ATRetries); return (value >> 4) & 0x0ffff00f; + case CSR_PRIORITY_BUDGET: + return (reg_read(ohci, OHCI1394_FairnessControl) & 0x3f) | + (ohci->pri_req_max << 8); + default: WARN_ON(1); return 0; @@ -2065,12 +2075,28 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) flush_writes(ohci); break; + case CSR_PRIORITY_BUDGET: + reg_write(ohci, OHCI1394_FairnessControl, value & 0x3f); + flush_writes(ohci); + break; + default: WARN_ON(1); break; } } +static unsigned int ohci_get_features(struct fw_card *card) +{ + struct fw_ohci *ohci = fw_ohci(card); + unsigned int features = 0; + + if (ohci->pri_req_max != 0) + features |= FEATURE_PRIORITY_BUDGET; + + return features; +} + static void copy_iso_headers(struct iso_context *ctx, void *p) { int i = ctx->header_length; @@ -2510,6 +2536,7 @@ static const struct fw_card_driver ohci_driver = { .enable_phys_dma = ohci_enable_phys_dma, .read_csr_reg = ohci_read_csr_reg, .write_csr_reg = ohci_write_csr_reg, + .get_features = ohci_get_features, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, diff --git a/include/linux/firewire.h b/include/linux/firewire.h index cdf8213c68ca..a50377d91254 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -32,6 +32,7 @@ #define CSR_CYCLE_TIME 0x200 #define CSR_BUS_TIME 0x204 #define CSR_BUSY_TIMEOUT 0x210 +#define CSR_PRIORITY_BUDGET 0x218 #define CSR_BUS_MANAGER_ID 0x21c #define CSR_BANDWIDTH_AVAILABLE 0x220 #define CSR_CHANNELS_AVAILABLE 0x224 -- cgit v1.2.3 From 3d1f46eb60b155c705e389ecdf313f11b4b91976 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:35:37 +0200 Subject: firewire: core: add CSR MAINT_UTILITY support Implement the MAIN_UTILITY register, which is utterly optional but useful as a safe target for diagnostic read/write/broadcast transactions. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 9 +++++++++ include/linux/firewire.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index a61eb3fb9573..dd8ef650a7cb 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1140,6 +1140,15 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_TYPE_ERROR; break; + case CSR_MAINT_UTILITY: + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = card->maint_utility_register; + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->maint_utility_register = *data; + else + rcode = RCODE_TYPE_ERROR; + break; + case CSR_BROADCAST_CHANNEL: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->broadcast_channel); diff --git a/include/linux/firewire.h b/include/linux/firewire.h index a50377d91254..f1160e831dad 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -38,6 +38,7 @@ #define CSR_CHANNELS_AVAILABLE 0x224 #define CSR_CHANNELS_AVAILABLE_HI 0x224 #define CSR_CHANNELS_AVAILABLE_LO 0x228 +#define CSR_MAINT_UTILITY 0x230 #define CSR_BROADCAST_CHANNEL 0x234 #define CSR_CONFIG_ROM 0x400 #define CSR_CONFIG_ROM_END 0x800 @@ -122,6 +123,8 @@ struct fw_card { bool broadcast_channel_allocated; u32 broadcast_channel; __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; + + __be32 maint_utility_register; }; struct fw_attribute_group { -- cgit v1.2.3 From 4ffb7a6a066e4be4577976d1c08e237c7479770a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:36:37 +0200 Subject: firewire: add CSR cmstr support Implement the cmstr bit, which is required for cycle master capable nodes and tested for by the Base 1394 Test Suite. This bit allows the bus master to disable cycle start packets; there are bus master implementations that actually do this. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-transaction.c | 12 ++++++++++-- drivers/firewire/core.h | 2 ++ drivers/firewire/ohci.c | 35 +++++++++++++++++++++++++++++++++++ drivers/firewire/ohci.h | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index dd8ef650a7cb..e0c6cce894cf 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1003,7 +1003,12 @@ static u32 read_state_register(struct fw_card *card) * reset, but then cleared when the units are ready again, which * happens immediately for us. */ - return 0; + u32 value = 0x0000; + + /* Bit 8 (cmstr): */ + value |= card->driver->read_csr_reg(card, CSR_STATE_CLEAR); + + return value; } static void update_split_timeout(struct fw_card *card) @@ -1034,6 +1039,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, if (tcode == TCODE_READ_QUADLET_REQUEST) { *data = cpu_to_be32(read_state_register(card)); } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + card->driver->write_csr_reg(card, CSR_STATE_CLEAR, + be32_to_cpu(*data)); } else { rcode = RCODE_TYPE_ERROR; } @@ -1043,7 +1050,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, if (tcode == TCODE_READ_QUADLET_REQUEST) { *data = cpu_to_be32(read_state_register(card)); } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { - /* FIXME: implement cmstr */ + card->driver->write_csr_reg(card, CSR_STATE_SET, + be32_to_cpu(*data)); /* FIXME: implement abdicate */ } else { rcode = RCODE_TYPE_ERROR; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 3b8c0f042f49..aaecdd1c1767 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -40,6 +40,8 @@ struct fw_packet; #define FEATURE_PRIORITY_BUDGET 0x01 +#define CSR_STATE_BIT_CMSTR (1 << 8) + struct fw_card_driver { /* * Enable the given card with the given initial config rom. diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 0e5413531785..1dcc2e427eb1 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -172,6 +172,7 @@ struct fw_ohci { unsigned quirks; unsigned int pri_req_max; u32 bus_time; + bool is_root; /* * Spinlock for accessing fw_ohci data. Never call out of @@ -1400,6 +1401,7 @@ static void bus_reset_tasklet(unsigned long data) unsigned long flags; void *free_rom = NULL; dma_addr_t free_rom_bus = 0; + bool is_new_root; reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { @@ -1413,6 +1415,12 @@ static void bus_reset_tasklet(unsigned long data) ohci->node_id = reg & (OHCI1394_NodeID_busNumber | OHCI1394_NodeID_nodeNumber); + is_new_root = (reg & OHCI1394_NodeID_root) != 0; + if (!(ohci->is_root && is_new_root)) + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_cycleMaster); + ohci->is_root = is_new_root; + reg = reg_read(ohci, OHCI1394_SelfIDCount); if (reg & OHCI1394_SelfIDCount_selfIDError) { fw_notify("inconsistent self IDs\n"); @@ -2013,6 +2021,16 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) u32 value; switch (csr_offset) { + case CSR_STATE_CLEAR: + case CSR_STATE_SET: + /* the controller driver handles only the cmstr bit */ + if (ohci->is_root && + (reg_read(ohci, OHCI1394_LinkControlSet) & + OHCI1394_LinkControl_cycleMaster)) + return CSR_STATE_BIT_CMSTR; + else + return 0; + case CSR_NODE_IDS: return reg_read(ohci, OHCI1394_NodeID) << 16; @@ -2050,6 +2068,23 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) unsigned long flags; switch (csr_offset) { + case CSR_STATE_CLEAR: + /* the controller driver handles only the cmstr bit */ + if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) { + reg_write(ohci, OHCI1394_LinkControlClear, + OHCI1394_LinkControl_cycleMaster); + flush_writes(ohci); + } + break; + + case CSR_STATE_SET: + if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) { + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_cycleMaster); + flush_writes(ohci); + } + break; + case CSR_NODE_IDS: reg_write(ohci, OHCI1394_NodeID, value >> 16); flush_writes(ohci); diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index 3bc9a5d744eb..0e6c5a466908 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h @@ -60,6 +60,7 @@ #define OHCI1394_LinkControl_cycleSource (1 << 22) #define OHCI1394_NodeID 0x0E8 #define OHCI1394_NodeID_idValid 0x80000000 +#define OHCI1394_NodeID_root 0x40000000 #define OHCI1394_NodeID_nodeNumber 0x0000003f #define OHCI1394_NodeID_busNumber 0x0000ffc0 #define OHCI1394_PhyControl 0x0EC -- cgit v1.2.3 From 7e0e314f198d5048b74c8f0ef9f4c1c02e5ecfc9 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:37:15 +0200 Subject: firewire: core: add CSR abdicate support Implement the abdicate bit, which is required for bus manager capable nodes and tested by the Base 1394 Test Suite. Finally, something to do at a command reset! :-) Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 3 ++- drivers/firewire/core-topology.c | 2 ++ drivers/firewire/core-transaction.c | 13 +++++++++++-- drivers/firewire/core.h | 1 + include/linux/firewire.h | 2 ++ 5 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index d0f15c2f1e1d..7c4cf6cfa746 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -260,7 +260,8 @@ static void fw_card_bm_work(struct work_struct *work) grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); - if (is_next_generation(generation, card->bm_generation) || + if ((is_next_generation(generation, card->bm_generation) && + !card->bm_abdicate) || (card->bm_generation != generation && grace)) { /* * This first step is to figure out who is IRM and diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 93ec64cdeef7..ca3c65318165 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -552,6 +552,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, smp_wmb(); card->generation = generation; card->reset_jiffies = jiffies; + card->bm_abdicate = card->csr_abdicate; + card->csr_abdicate = false; fw_schedule_bm_work(card, 0); local_node = build_tree(card, self_ids, self_id_count); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index e0c6cce894cf..85a54da243e2 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1008,6 +1008,10 @@ static u32 read_state_register(struct fw_card *card) /* Bit 8 (cmstr): */ value |= card->driver->read_csr_reg(card, CSR_STATE_CLEAR); + /* Bit 10 (abdicate): */ + if (card->csr_abdicate) + value |= CSR_STATE_BIT_ABDICATE; + return value; } @@ -1041,6 +1045,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { card->driver->write_csr_reg(card, CSR_STATE_CLEAR, be32_to_cpu(*data)); + if (*data & cpu_to_be32(CSR_STATE_BIT_ABDICATE)) + card->csr_abdicate = false; } else { rcode = RCODE_TYPE_ERROR; } @@ -1052,7 +1058,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { card->driver->write_csr_reg(card, CSR_STATE_SET, be32_to_cpu(*data)); - /* FIXME: implement abdicate */ + if (*data & cpu_to_be32(CSR_STATE_BIT_ABDICATE)) + card->csr_abdicate = true; } else { rcode = RCODE_TYPE_ERROR; } @@ -1070,7 +1077,9 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, break; case CSR_RESET_START: - if (tcode != TCODE_WRITE_QUADLET_REQUEST) + if (tcode == TCODE_WRITE_QUADLET_REQUEST) + card->csr_abdicate = false; + else rcode = RCODE_TYPE_ERROR; break; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index aaecdd1c1767..a9ace1f8dc3f 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -41,6 +41,7 @@ struct fw_packet; #define FEATURE_PRIORITY_BUDGET 0x01 #define CSR_STATE_BIT_CMSTR (1 << 8) +#define CSR_STATE_BIT_ABDICATE (1 << 10) struct fw_card_driver { /* diff --git a/include/linux/firewire.h b/include/linux/firewire.h index f1160e831dad..4d22643215ef 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -119,6 +119,8 @@ struct fw_card { int bm_retries; int bm_generation; __be32 bm_transaction_data[2]; + bool bm_abdicate; /* value of csr_abdicate before last bus reset */ + bool csr_abdicate; /* visible in CSR STATE_CLEAR/SET registers */ bool broadcast_channel_allocated; u32 broadcast_channel; -- cgit v1.2.3 From e91b2787d0a2e4719b016e8dec0afd2d5ab6c30f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:40:49 +0200 Subject: firewire: allocate broadcast channel in hardware On OHCI 1.1 controllers, let the hardware allocate the broadcast channel automatically. This removes a theoretical race condition directly after a bus reset where it could be possible to read the channel allocation register with channel 31 still being unallocated. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 16 +++++++++++----- drivers/firewire/core-topology.c | 3 ++- drivers/firewire/core.h | 1 + drivers/firewire/ohci.c | 18 ++++++++++++------ 4 files changed, 26 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 7c4cf6cfa746..faf2eee473b9 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -208,13 +208,19 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) { int channel, bandwidth = 0; - fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, - &bandwidth, true, card->bm_transaction_data); - if (channel == 31) { + if (!card->broadcast_channel_allocated) { + fw_iso_resource_manage(card, generation, 1ULL << 31, + &channel, &bandwidth, true, + card->bm_transaction_data); + if (channel != 31) { + fw_notify("failed to allocate broadcast channel\n"); + return; + } card->broadcast_channel_allocated = true; - device_for_each_child(card->device, (void *)(long)generation, - fw_device_set_broadcast_channel); } + + device_for_each_child(card->device, (void *)(long)generation, + fw_device_set_broadcast_channel); } static const char gap_count_table[] = { diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index ca3c65318165..00a556f3a585 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -543,7 +543,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, spin_lock_irqsave(&card->lock, flags); - card->broadcast_channel_allocated = false; + card->broadcast_channel_allocated = (card->driver->get_features(card) & + FEATURE_CHANNEL_31_ALLOCATED) != 0; card->node_id = node_id; /* * Update node_id before generation to prevent anybody from using diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index a9ace1f8dc3f..3f9e39b60bca 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -39,6 +39,7 @@ struct fw_packet; #define BROADCAST_CHANNEL_VALID (1 << 30) #define FEATURE_PRIORITY_BUDGET 0x01 +#define FEATURE_CHANNEL_31_ALLOCATED 0x02 #define CSR_STATE_BIT_CMSTR (1 << 8) #define CSR_STATE_BIT_ABDICATE (1 << 10) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 1dcc2e427eb1..51a55808d88a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -171,6 +171,7 @@ struct fw_ohci { int request_generation; /* for timestamping incoming requests */ unsigned quirks; unsigned int pri_req_max; + unsigned int features; u32 bus_time; bool is_root; @@ -1694,7 +1695,7 @@ static int ohci_enable(struct fw_card *card, { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - u32 lps, seconds, irqs; + u32 lps, seconds, version, irqs; int i, ret; if (software_reset(ohci)) { @@ -1747,10 +1748,19 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); ohci->bus_time = seconds & ~0x3f; + version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; + if (version >= OHCI_VERSION_1_1) { + reg_write(ohci, OHCI1394_InitialChannelsAvailableHi, + 0xfffffffe); + ohci->features |= FEATURE_CHANNEL_31_ALLOCATED; + } + /* Get implemented bits of the priority arbitration request counter. */ reg_write(ohci, OHCI1394_FairnessControl, 0x3f); ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; reg_write(ohci, OHCI1394_FairnessControl, 0); + if (ohci->pri_req_max != 0) + ohci->features |= FEATURE_PRIORITY_BUDGET; ar_context_run(&ohci->ar_request_ctx); ar_context_run(&ohci->ar_response_ctx); @@ -2124,12 +2134,8 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) static unsigned int ohci_get_features(struct fw_card *card) { struct fw_ohci *ohci = fw_ohci(card); - unsigned int features = 0; - - if (ohci->pri_req_max != 0) - features |= FEATURE_PRIORITY_BUDGET; - return features; + return ohci->features; } static void copy_iso_headers(struct iso_context *ctx, void *p) -- cgit v1.2.3 From c374ab424249b6ab91b1aee7460419d3f2c321df Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:41:51 +0200 Subject: firewire: core: always enable cycle master packets As part of the bus manager responsibilities, make sure that the cycle master sends cycle start packets. This is needed when the old bus manager disabled the cycle master's cmstr bit and there are iso-capable nodes on the new bus. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index faf2eee473b9..ef6f2616cac7 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -369,10 +369,8 @@ static void fw_card_bm_work(struct work_struct *work) goto out; } else if (root_device_is_cmc) { /* - * FIXME: I suppose we should set the cmstr bit in the - * STATE_CLEAR register of this node, as described in - * 1394-1995, 8.4.2.6. Also, send out a force root - * packet for this node. + * We will send out a force root packet for this + * node as part of the gap count optimization. */ new_root_id = root_id; } else { @@ -413,11 +411,25 @@ static void fw_card_bm_work(struct work_struct *work) fw_send_phy_config(card, new_root_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); /* Will allocate broadcast channel after the reset. */ - } else { - if (local_id == irm_id) - allocate_broadcast_channel(card, generation); + goto out; } + if (root_device_is_cmc) { + /* + * Make sure that the cycle master sends cycle start packets. + */ + card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); + rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, + root_id, generation, SCODE_100, + CSR_REGISTER_BASE + CSR_STATE_SET, + card->bm_transaction_data, sizeof(u32)); + if (rcode == RCODE_GENERATION) + goto out; + } + + if (local_id == irm_id) + allocate_broadcast_channel(card, generation); + out: fw_node_put(root_node); out_put_card: -- cgit v1.2.3 From 091b4242ebb789e826cbde573a0fee9f60fe998b Mon Sep 17 00:00:00 2001 From: Samuel Richardson Date: Mon, 17 May 2010 19:08:18 +0100 Subject: Staging: comedi: fixed brace coding style issue in ni_tio.c This is a patch to the ni_tio.c file that fixes a brace warning found by the checkpatch.pl tool Signed-off-by: Samuel Richardson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 13e5b264ff0d..6621e940c308 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1688,11 +1688,10 @@ static unsigned ni_tio_next_load_register(struct ni_gpct *counter) NITIO_Gxx_Status_Reg(counter-> counter_index)); - if (bits & Gi_Next_Load_Source_Bit(counter->counter_index)) { + if (bits & Gi_Next_Load_Source_Bit(counter->counter_index)) return NITIO_Gi_LoadB_Reg(counter->counter_index); - } else { + else return NITIO_Gi_LoadA_Reg(counter->counter_index); - } } int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn *insn, -- cgit v1.2.3 From 3d34023a99d35440d6a22fb0b4547fc9817b7b40 Mon Sep 17 00:00:00 2001 From: Cody Harmon Date: Tue, 18 May 2010 23:03:40 -0700 Subject: Staging: comedi: ni_tio: fixed brace coding style issues and a few errors Fixed code style and placed KERN_ERR in printk statement. Signed-off-by: Cody Harmon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 49 +++++++++++++-------------------- 1 file changed, 19 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 6621e940c308..a9bb6b13dfc4 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -302,7 +302,7 @@ struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device *dev, ni_gpct_register reg), unsigned (*read_register) - (struct ni_gpct * counter, + (struct ni_gpct *counter, enum ni_gpct_register reg), enum ni_gpct_variant variant, unsigned num_counters) @@ -332,6 +332,7 @@ struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device *dev, counter_dev->num_counters = num_counters; return counter_dev; } +EXPORT_SYMBOL_GPL(ni_gpct_device_construct); void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) { @@ -340,6 +341,7 @@ void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) kfree(counter_dev->counters); kfree(counter_dev); } +EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); static int ni_tio_second_gate_registers_present(const struct ni_gpct_device *counter_dev) @@ -418,6 +420,7 @@ void ni_tio_init_counter(struct ni_gpct *counter) NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), ~0, 0x0); } +EXPORT_SYMBOL_GPL(ni_tio_init_counter); static unsigned int ni_tio_counter_status(struct ni_gpct *counter) { @@ -446,9 +449,7 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) if (ni_tio_counting_mode_registers_present(counter_dev) == 0) return; - switch (ni_tio_get_soft_copy(counter, - counting_mode_reg) & Gi_Counting_Mode_Mask) - { + switch (ni_tio_get_soft_copy(counter, counting_mode_reg) & Gi_Counting_Mode_Mask) { case Gi_Counting_Mode_QuadratureX1_Bits: case Gi_Counting_Mode_QuadratureX2_Bits: case Gi_Counting_Mode_QuadratureX4_Bits: @@ -513,9 +514,8 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) counting_mode_bits |= ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) << Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask; - if (mode & NI_GPCT_INDEX_ENABLE_BIT) { + if (mode & NI_GPCT_INDEX_ENABLE_BIT) counting_mode_bits |= Gi_Index_Mode_Bit; - } ni_tio_set_bits(counter, NITIO_Gi_Counting_Mode_Reg(counter-> counter_index), @@ -529,12 +529,10 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) (mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) << Gi_Up_Down_Shift); - if (mode & NI_GPCT_OR_GATE_BIT) { + if (mode & NI_GPCT_OR_GATE_BIT) input_select_bits |= Gi_Or_Gate_Bit; - } - if (mode & NI_GPCT_INVERT_OUTPUT_BIT) { + if (mode & NI_GPCT_INVERT_OUTPUT_BIT) input_select_bits |= Gi_Output_Polarity_Bit; - } ni_tio_set_bits(counter, NITIO_Gi_Input_Select_Reg(counter->counter_index), Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit | @@ -600,6 +598,7 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) 0, 0, command_transient_bits); return 0; } +EXPORT_SYMBOL_GPL(ni_tio_arm); static unsigned ni_660x_source_select_bits(unsigned int clock_source) { @@ -706,7 +705,7 @@ static unsigned ni_m_series_source_select_bits(unsigned int clock_source) } if (i <= ni_m_series_max_pfi_channel) break; - printk("invalid clock source 0x%lx\n", + printk(KERN_ERR "invalid clock source 0x%lx\n", (unsigned long)clock_source); BUG(); ni_m_series_clock = 0; @@ -1026,14 +1025,12 @@ static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter, const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask; unsigned mode_values = 0; - if (gate_source & CR_INVERT) { + if (gate_source & CR_INVERT) mode_values |= Gi_Gate_Polarity_Bit; - } - if (gate_source & CR_EDGE) { + if (gate_source & CR_EDGE) mode_values |= Gi_Rising_Edge_Gating_Bits; - } else { + else mode_values |= Gi_Level_Gating_Bits; - } ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), mode_mask, mode_values); } @@ -1290,6 +1287,7 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, } return 0; } +EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, unsigned int source) @@ -1531,12 +1529,10 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, BUG(); break; } - if (mode_bits & Gi_Gate_Polarity_Bit) { + if (mode_bits & Gi_Gate_Polarity_Bit) *gate_source |= CR_INVERT; - } - if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) { + if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) *gate_source |= CR_EDGE; - } break; case 1: if ((mode_bits & Gi_Gating_Mode_Mask) == Gi_Gating_Disabled_Bits @@ -1572,9 +1568,8 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, *gate_source |= CR_INVERT; } /* second gate can't have edge/level mode set independently */ - if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) { + if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) *gate_source |= CR_EDGE; - } break; default: return -EINVAL; @@ -1627,6 +1622,7 @@ int ni_tio_insn_config(struct ni_gpct *counter, } return -EINVAL; } +EXPORT_SYMBOL_GPL(ni_tio_insn_config); int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn *insn, unsigned int *data) @@ -1681,6 +1677,7 @@ int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn *insn, }; return 0; } +EXPORT_SYMBOL_GPL(ni_tio_rinsn); static unsigned ni_tio_next_load_register(struct ni_gpct *counter) { @@ -1734,12 +1731,4 @@ int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn *insn, } return 0; } - -EXPORT_SYMBOL_GPL(ni_tio_rinsn); EXPORT_SYMBOL_GPL(ni_tio_winsn); -EXPORT_SYMBOL_GPL(ni_tio_insn_config); -EXPORT_SYMBOL_GPL(ni_tio_init_counter); -EXPORT_SYMBOL_GPL(ni_tio_arm); -EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); -EXPORT_SYMBOL_GPL(ni_gpct_device_construct); -EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); -- cgit v1.2.3 From 3c17ba0743d75f9888d905ddf9f8551c7dd36493 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 May 2010 14:10:00 +0100 Subject: Staging: comedi: Allow 'open' driver method to fail Some comedi drivers should return an error from their 'open' method when something goes wrong. Change the prototype of the 'open' method in 'struct comedi_device' to allow this, and change the drivers that use it. Propagate any error to the 'open' file operation. The corresponding 'close' method won't be called when the 'open' method fails, so drivers failing the 'open' need to clean up any mess they created. The dt9812 and serial2002 drivers can now return an error on 'open'. The jr3_pci driver also uses the 'open' method but doesn't fail it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 11 +++++++++-- drivers/staging/comedi/comedidev.h | 2 +- drivers/staging/comedi/drivers/dt9812.c | 6 +++++- drivers/staging/comedi/drivers/jr3_pci.c | 3 ++- drivers/staging/comedi/drivers/serial2002.c | 9 ++++++--- 5 files changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index aeb2c00875cd..14091313cebb 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1845,8 +1845,15 @@ ok: } } - if (dev->attached && dev->use_count == 0 && dev->open) - dev->open(dev); + if (dev->attached && dev->use_count == 0 && dev->open) { + int rc = dev->open(dev); + if (rc < 0) { + module_put(dev->driver->module); + module_put(THIS_MODULE); + mutex_unlock(&dev->mutex); + return rc; + } + } dev->use_count++; diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 4eb2b77f56dc..41ef9207f99c 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -285,7 +285,7 @@ struct comedi_device { struct fasync_struct *async_queue; - void (*open) (struct comedi_device *dev); + int (*open) (struct comedi_device *dev); void (*close) (struct comedi_device *dev); }; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 96caae36279c..d01d2dc79112 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -890,8 +890,10 @@ static struct usb_driver dt9812_usb_driver = { * Comedi functions */ -static void dt9812_comedi_open(struct comedi_device *dev) +static int dt9812_comedi_open(struct comedi_device *dev) { + int result = -ENODEV; + down(&devpriv->slot->mutex); if (devpriv->slot->usb) { /* We have an attached device, fill in current range info */ @@ -934,8 +936,10 @@ static void dt9812_comedi_open(struct comedi_device *dev) } break; } + result = 0; } up(&devpriv->slot->mutex); + return result; } static int dt9812_di_rinsn(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index d330b1886846..4683a0b90f22 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -373,7 +373,7 @@ static int jr3_pci_ai_insn_read(struct comedi_device *dev, return result; } -static void jr3_pci_open(struct comedi_device *dev) +static int jr3_pci_open(struct comedi_device *dev) { int i; struct jr3_pci_dev_private *devpriv = dev->private; @@ -388,6 +388,7 @@ static void jr3_pci_open(struct comedi_device *dev) p->channel_no); } } + return 0; } int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val) diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 0792617ebc35..a4a99b870369 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -393,15 +393,16 @@ static void serial_write(struct file *f, struct serial_data data) } } -static void serial_2002_open(struct comedi_device *dev) +static int serial_2002_open(struct comedi_device *dev) { + int result; char port[20]; sprintf(port, "/dev/ttyS%d", devpriv->port); devpriv->tty = filp_open(port, O_RDWR, 0); if (IS_ERR(devpriv->tty)) { - printk("serial_2002: file open error = %ld\n", - PTR_ERR(devpriv->tty)); + result = (int)PTR_ERR(devpriv->tty); + printk("serial_2002: file open error = %d\n", result); } else { struct config_t { @@ -673,7 +674,9 @@ static void serial_2002_open(struct comedi_device *dev) } } } + result = 0; } + return result; } static void serial_2002_close(struct comedi_device *dev) -- cgit v1.2.3 From 9e7f2256883c954691e5d395d471e0f125f6b30b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 May 2010 14:10:01 +0100 Subject: Staging: comedi: serial2002: handle allocation failures on 'open' The comedi device 'open' method for the serial2002 driver frees any old 'maxdata_list' and 'range_table_list' arrays belonging to a subdevice and allocates them again, but was missing checks for allocation failure. If an allocation fails, free the 'maxdata_list' and 'range_table_list' arrays for all subdevices and return an error. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 37 ++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index a4a99b870369..880fe89e866f 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -418,6 +418,7 @@ static int serial_2002_open(struct comedi_device *dev) struct config_t chan_out_config[32]; int i; + result = 0; for (i = 0; i < 32; i++) { dig_in_config[i].kind = 0; dig_in_config[i].bits = 0; @@ -633,22 +634,23 @@ static int serial_2002_open(struct comedi_device *dev) s = &dev->subdevices[i]; s->n_chan = chan; s->maxdata = 0; - if (s->maxdata_list) { - kfree(s->maxdata_list); - } + kfree(s->maxdata_list); s->maxdata_list = maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL); - if (s->range_table_list) { - kfree(s->range_table_list); - } + if (!s->maxdata_list) + break; /* error handled below */ + kfree(s->range_table_list); + s->range_table = NULL; + s->range_table_list = NULL; if (range) { - s->range_table = 0; s->range_table_list = range_table_list = kmalloc(sizeof (struct serial2002_range_table_t) * s->n_chan, GFP_KERNEL); + if (!s->range_table_list) + break; /* err handled below */ } for (chan = 0, j = 0; j < 32; j++) { if (c[j].kind == kind) { @@ -674,7 +676,26 @@ static int serial_2002_open(struct comedi_device *dev) } } } - result = 0; + if (i <= 4) { + /* Failed to allocate maxdata_list or range_table_list + * for a subdevice that needed it. */ + result = -ENOMEM; + for (i = 0; i <= 4; i++) { + struct comedi_subdevice *s; + + s = &dev->subdevices[i]; + kfree(s->maxdata_list); + s->maxdata_list = NULL; + kfree(s->range_table_list); + s->range_table_list = NULL; + } + } + if (result) { + if (devpriv->tty) { + filp_close(devpriv->tty, 0); + devpriv->tty = NULL; + } + } } return result; } -- cgit v1.2.3 From fa3b5d9ab0487f58b45d55a37070aa0d417f59d5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 May 2010 14:10:02 +0100 Subject: Staging: comedi: serial2002: Fix memory leak on detach The comedi device 'detach' method for the serial2002 driver has an off-by-one error in its loop for freeing data belonging to its subdevices. Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 880fe89e866f..6813e3465f6e 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -903,7 +903,7 @@ static int serial2002_detach(struct comedi_device *dev) int i; printk("comedi%d: serial2002: remove\n", dev->minor); - for (i = 0; i < 4; i++) { + for (i = 0; i < 5; i++) { s = &dev->subdevices[i]; if (s->maxdata_list) { kfree(s->maxdata_list); -- cgit v1.2.3 From 668f272e57e80ece987bed273096f8e3a707123c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 May 2010 14:10:03 +0100 Subject: Staging: comedi: serial2002: Reduce stack usage on 'open' Reduce stack usage in serial_2002_open() by allocating dig_in_config, dig_out_config, chan_in_config, and chan_out_config temporary arrays using kcalloc() and freeing them when done with. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 44 +++++++++++++++-------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 6813e3465f6e..c929f986118c 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -412,30 +412,25 @@ static int serial_2002_open(struct comedi_device *dev) int max; }; - struct config_t dig_in_config[32]; - struct config_t dig_out_config[32]; - struct config_t chan_in_config[32]; - struct config_t chan_out_config[32]; + struct config_t *dig_in_config; + struct config_t *dig_out_config; + struct config_t *chan_in_config; + struct config_t *chan_out_config; int i; result = 0; - for (i = 0; i < 32; i++) { - dig_in_config[i].kind = 0; - dig_in_config[i].bits = 0; - dig_in_config[i].min = 0; - dig_in_config[i].max = 0; - dig_out_config[i].kind = 0; - dig_out_config[i].bits = 0; - dig_out_config[i].min = 0; - dig_out_config[i].max = 0; - chan_in_config[i].kind = 0; - chan_in_config[i].bits = 0; - chan_in_config[i].min = 0; - chan_in_config[i].max = 0; - chan_out_config[i].kind = 0; - chan_out_config[i].bits = 0; - chan_out_config[i].min = 0; - chan_out_config[i].max = 0; + dig_in_config = kcalloc(32, sizeof(struct config_t), + GFP_KERNEL); + dig_out_config = kcalloc(32, sizeof(struct config_t), + GFP_KERNEL); + chan_in_config = kcalloc(32, sizeof(struct config_t), + GFP_KERNEL); + chan_out_config = kcalloc(32, sizeof(struct config_t), + GFP_KERNEL); + if (!dig_in_config || !dig_out_config + || !chan_in_config || !chan_out_config) { + result = -ENOMEM; + goto err_alloc_configs; } tty_setspeed(devpriv->tty, devpriv->speed); @@ -690,6 +685,13 @@ static int serial_2002_open(struct comedi_device *dev) s->range_table_list = NULL; } } + +err_alloc_configs: + kfree(dig_in_config); + kfree(dig_out_config); + kfree(chan_in_config); + kfree(chan_out_config); + if (result) { if (devpriv->tty) { filp_close(devpriv->tty, 0); -- cgit v1.2.3 From c5da20905c8ce21a73a9b443e5d7ef0dc623cff0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 May 2010 14:10:04 +0100 Subject: Staging: comedi: serial2002: Use NULL instead of 0 for pointers Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index c929f986118c..5886ebfd043a 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -444,7 +444,7 @@ static int serial_2002_open(struct comedi_device *dev) break; } else { int command, channel, kind; - struct config_t *cur_config = 0; + struct config_t *cur_config = NULL; channel = data.value & 0x1f; kind = (data.value >> 5) & 0x7; @@ -571,8 +571,8 @@ static int serial_2002_open(struct comedi_device *dev) for (i = 0; i <= 4; i++) { /* Fill in subdev data */ struct config_t *c; - unsigned char *mapping = 0; - struct serial2002_range_table_t *range = 0; + unsigned char *mapping = NULL; + struct serial2002_range_table_t *range = NULL; int kind = 0; switch (i) { @@ -610,7 +610,7 @@ static int serial_2002_open(struct comedi_device *dev) } break; default:{ - c = 0; + c = NULL; } break; } -- cgit v1.2.3 From f25bd6bfdf9bccd8164c151b027f9c14ec07960b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 22 May 2010 22:42:38 +0200 Subject: Staging: comedi: cleanup: remove unneeded null checks These checks are obviously pointless because kfree() can handle null dereferences. But really the main problem is that if the pointers were null that would cause problems on the ealier lines. The dereferences would cause an oops and the _release() functions use ->priv to determine which IRQ to free. I looked into it and quite a few of the detach functions assume link->priv is non-null. It seems like we can remove these checks. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_das16_cs.c | 3 +-- drivers/staging/comedi/drivers/das08_cs.c | 3 +-- drivers/staging/comedi/drivers/ni_daq_700.c | 3 +-- drivers/staging/comedi/drivers/ni_daq_dio24.c | 3 +-- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index cfeb11f443e3..d8d4ed6de35c 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -719,8 +719,7 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link) ((struct local_info_t *)link->priv)->stop = 1; das16cs_pcmcia_release(link); /* This points to the parent struct local_info_t struct */ - if (link->priv) - kfree(link->priv); + kfree(link->priv); } /* das16cs_pcmcia_detach */ diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 8761a6d285dc..fb561ab7f07c 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -206,8 +206,7 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) das08_pcmcia_release(link); /* This points to the parent struct local_info_t struct */ - if (link->priv) - kfree(link->priv); + kfree(link->priv); } /* das08_pcmcia_detach */ diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 6ec77bf88c63..701abd9eabe6 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -537,8 +537,7 @@ static void dio700_cs_detach(struct pcmcia_device *link) dio700_release(link); /* This points to the parent struct local_info_t struct */ - if (link->priv) - kfree(link->priv); + kfree(link->priv); } /* dio700_cs_detach */ diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index e4865b1c2310..0b65f247d5dd 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -289,8 +289,7 @@ static void dio24_cs_detach(struct pcmcia_device *link) dio24_release(link); /* This points to the parent local_info_t struct */ - if (link->priv) - kfree(link->priv); + kfree(link->priv); } /* dio24_cs_detach */ diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index a91db6c42028..78eb254bd619 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -1076,8 +1076,7 @@ static void daqp_cs_detach(struct pcmcia_device *link) /* Unlink device structure, and free it */ dev_table[dev->table_index] = NULL; - if (dev) - kfree(dev); + kfree(dev); } /* daqp_cs_detach */ -- cgit v1.2.3 From 2f6df34cd3455245c44b420d7c3fb11d1137df79 Mon Sep 17 00:00:00 2001 From: Mark Rankilor Date: Mon, 24 May 2010 17:59:10 +0800 Subject: Staging: comedi: Checkpatch cleanups in adl_pci9111.c This patch cleans up some various warnings generated from checkpatch.pl Signed-off-by: Mark Rankilor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9111.c | 105 +++++++++++++++------------ 1 file changed, 59 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 36a254cd4413..595689d5f17f 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -68,8 +68,9 @@ CHANGELOG: TODO: - Really test implemented functionality. - - Add support for the PCI-9111DG with a probe routine to identify the card type - (perhaps with the help of the channel number readback of the A/D Data register). + - Add support for the PCI-9111DG with a probe routine to identify the card + type (perhaps with the help of the channel number readback of the A/D Data + register). - Add external multiplexer support. */ @@ -83,12 +84,12 @@ TODO: #include "comedi_pci.h" #include "comedi_fc.h" -#define PCI9111_DRIVER_NAME "adl_pci9111" -#define PCI9111_HR_DEVICE_ID 0x9111 +#define PCI9111_DRIVER_NAME "adl_pci9111" +#define PCI9111_HR_DEVICE_ID 0x9111 /* TODO: Add other pci9111 board id */ -#define PCI9111_IO_RANGE 0x0100 +#define PCI9111_IO_RANGE 0x0100 #define PCI9111_FIFO_HALF_SIZE 512 @@ -134,27 +135,29 @@ TODO: /* IO address map */ -#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored in FIFO */ -#define PCI9111_REGISTER_DA_OUTPUT 0x00 -#define PCI9111_REGISTER_DIGITAL_IO 0x02 -#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 -#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel selection */ -#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 -#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 -#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 -#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A -#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A -#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E -#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C +#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored + in FIFO */ +#define PCI9111_REGISTER_DA_OUTPUT 0x00 +#define PCI9111_REGISTER_DIGITAL_IO 0x02 +#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 +#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel + selection */ +#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 +#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 +#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 +#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A +#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A +#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E +#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C #define PCI9111_REGISTER_8254_COUNTER_0 0x40 #define PCI9111_REGISTER_8254_COUNTER_1 0x42 -#define PCI9111_REGISTER_8254_COUNTER_2 0X44 +#define PCI9111_REGISTER_8254_COUNTER_2 0X44 #define PCI9111_REGISTER_8254_CONTROL 0x46 -#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48 +#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48 -#define PCI9111_TRIGGER_MASK 0x0F -#define PCI9111_PTRG_OFF (0 << 3) -#define PCI9111_PTRG_ON (1 << 3) +#define PCI9111_TRIGGER_MASK 0x0F +#define PCI9111_PTRG_OFF (0 << 3) +#define PCI9111_PTRG_ON (1 << 3) #define PCI9111_EITS_EXTERNAL (1 << 2) #define PCI9111_EITS_INTERNAL (0 << 2) #define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1) @@ -164,9 +167,9 @@ TODO: #define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0) #define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0) -#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1) -#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1) -#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2) +#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1) +#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1) +#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2) #define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2) #define PCI9111_CHANNEL_MASK 0x0F @@ -177,7 +180,7 @@ TODO: #define PCI9111_FIFO_FULL_MASK 0x40 #define PCI9111_AD_BUSY_MASK 0x80 -#define PCI9111_IO_BASE dev->iobase +#define PCI9111_IO_BASE (dev->iobase) /* * Define inlined function @@ -189,8 +192,9 @@ TODO: #define pci9111_trigger_and_autoscan_set(flags) \ outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL) -#define pci9111_interrupt_and_fifo_get() \ - ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03) +#define pci9111_interrupt_and_fifo_get() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \ + &0x03) #define pci9111_interrupt_and_fifo_set(flags) \ outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) @@ -201,38 +205,47 @@ TODO: #define pci9111_software_trigger() \ outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER) -#define pci9111_fifo_reset() \ - outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ - outb(PCI9111_FFEN_SET_FIFO_DISABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ - outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) +#define pci9111_fifo_reset() do { \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_DISABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + } while (0) #define pci9111_is_fifo_full() \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ - PCI9111_FIFO_FULL_MASK)==0) + PCI9111_FIFO_FULL_MASK) == 0) #define pci9111_is_fifo_half_full() \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ - PCI9111_FIFO_HALF_FULL_MASK)==0) + PCI9111_FIFO_HALF_FULL_MASK) == 0) #define pci9111_is_fifo_empty() \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ - PCI9111_FIFO_EMPTY_MASK)==0) + PCI9111_FIFO_EMPTY_MASK) == 0) -#define pci9111_ai_channel_set(channel) \ - outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) +#define pci9111_ai_channel_set(channel) \ + outb((channel)&PCI9111_CHANNEL_MASK, \ + PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) -#define pci9111_ai_channel_get() \ - inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK +#define pci9111_ai_channel_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \ + &PCI9111_CHANNEL_MASK) -#define pci9111_ai_range_set(range) \ - outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) +#define pci9111_ai_range_set(range) \ + outb((range)&PCI9111_RANGE_MASK, \ + PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) -#define pci9111_ai_range_get() \ - inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK +#define pci9111_ai_range_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \ + &PCI9111_RANGE_MASK) -#define pci9111_ai_get_data() \ - ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \ - ^ PCI9111_AI_RESOLUTION_2_CMP_BIT +#define pci9111_ai_get_data() \ + (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \ + &PCI9111_AI_RESOLUTION_MASK) \ + ^ PCI9111_AI_RESOLUTION_2_CMP_BIT) #define pci9111_hr_ai_get_data() \ (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \ -- cgit v1.2.3 From 4c67da06f0248fc0ee0fcbf65afd887b023b4591 Mon Sep 17 00:00:00 2001 From: Mark Rankilor Date: Thu, 27 May 2010 17:39:15 +0800 Subject: Staging: comedi: Fixed long lines in gsc_hpdi.c This patch fixes some long line lengths in gsc_hpdi.c as found by the checkpatch.pl tool Signed-off-by: Mark Rankilor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/gsc_hpdi.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 51f12bf45cf1..17c4f1f8117d 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -311,17 +311,25 @@ struct hpdi_private { void *plx9080_iobase; void *hpdi_iobase; uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ - dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; /* physical addresses of dma buffers */ - struct plx_dma_desc *dma_desc; /* array of dma descriptors read by plx9080, allocated to get proper alignment */ - dma_addr_t dma_desc_phys_addr; /* physical address of dma descriptor array */ + /* physical addresses of dma buffers */ + dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; + /* array of dma descriptors read by plx9080, allocated to get proper + * alignment */ + struct plx_dma_desc *dma_desc; + /* physical address of dma descriptor array */ + dma_addr_t dma_desc_phys_addr; unsigned int num_dma_descriptors; - uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS]; /* pointer to start of buffers indexed by descriptor */ - volatile unsigned int dma_desc_index; /* index of the dma descriptor that is currently being used */ + /* pointer to start of buffers indexed by descriptor */ + uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS]; + /* index of the dma descriptor that is currently being used */ + volatile unsigned int dma_desc_index; unsigned int tx_fifo_size; unsigned int rx_fifo_size; volatile unsigned long dio_count; - volatile uint32_t bits[24]; /* software copies of values written to hpdi registers */ - volatile unsigned int block_size; /* number of bytes at which to generate COMEDI_CB_BLOCK events */ + /* software copies of values written to hpdi registers */ + volatile uint32_t bits[24]; + /* number of bytes at which to generate COMEDI_CB_BLOCK events */ + volatile unsigned int block_size; unsigned dio_config_output:1; }; @@ -570,7 +578,8 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; pcidev = NULL; - for (i = 0; i < ARRAY_SIZE(hpdi_boards) && dev->board_ptr == NULL; i++) { + for (i = 0; i < ARRAY_SIZE(hpdi_boards) && + dev->board_ptr == NULL; i++) { do { pcidev = pci_get_subsys(PCI_VENDOR_ID_PLX, hpdi_boards[i].device_id, @@ -618,7 +627,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* remap, won't work with 2.0 kernels but who cares */ priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase, pci_resource_len(pcidev, - PLX9080_BADDRINDEX)); + PLX9080_BADDRINDEX)); priv(dev)->hpdi_iobase = ioremap(priv(dev)->hpdi_phys_iobase, pci_resource_len(pcidev, HPDI_BADDRINDEX)); @@ -769,7 +778,8 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* step 2: make sure trigger sources are unique and mutually + * compatible */ /* uniqueness check */ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) -- cgit v1.2.3 From 6fd071cccf4127f1e81767a819720d8915b2a800 Mon Sep 17 00:00:00 2001 From: John Sheehan Date: Thu, 27 May 2010 12:41:38 +0100 Subject: Staging: comedi: fix code style errors in unioxx5.c A patch for unioxx5.c which fixes "trailing statements should be on next line" errors raised by the chechpatch.pl tool Signed-off-by: John Sheehan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 16d4c9f69165..d5f6d758a8be 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -302,7 +302,8 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, __unioxx5_analog_config(usp, i * 2); outb(i + 1, subdev_iobase + 5); /* sends channel number to card */ outb('H', subdev_iobase + 6); /* requests EEPROM world */ - while (!(inb(subdev_iobase + 0) & TxBE)) ; /* waits while writting will be allowed */ + while (!(inb(subdev_iobase + 0) & TxBE)) + ; /* waits while writting will be allowed */ outb(0, subdev_iobase + 6); /* waits while reading of two bytes will be allowed */ @@ -437,7 +438,8 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp, /* sending for bytes to module(one byte per cycle iteration) */ for (i = 0; i < 4; i++) { - while (!((inb(usp->usp_iobase + 0)) & TxBE)) ; /* waits while writting will be allowed */ + while (!((inb(usp->usp_iobase + 0)) & TxBE)) + ; /* waits while writting will be allowed */ outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6); } @@ -467,7 +469,8 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp, control = inb(usp->usp_iobase); /* get control register byte */ /* waits while reading four bytes will be allowed */ - while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA)) ; + while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA)) + ; /* if four bytes readding error occurs - return 0(false) */ if ((control & Rx4CA_ERR_MASK)) { -- cgit v1.2.3 From daca497d8035cdb649b37ef1c962f1f0de8f16d9 Mon Sep 17 00:00:00 2001 From: John Sheehan Date: Fri, 28 May 2010 16:33:25 +0100 Subject: Staging: comedi: fix code warnings in s626.c A patch for s626.c to fix some of the warnings reported by the checkpatch.pl tool, namely, printk() should include KERN_ facility level unnecessary whitespace before a quoted newline Signed-off-by: John Sheehan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index a3cc93362ec2..febb62e86ec3 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -543,13 +543,13 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->pdev = pdev; if (pdev == NULL) { - printk("s626_attach: Board not present!!!\n"); + printk(KERN_ERR "s626_attach: Board not present!!!\n"); return -ENODEV; } result = comedi_pci_enable(pdev, "s626"); if (result < 0) { - printk("s626_attach: comedi_pci_enable fails\n"); + printk(KERN_ERR "s626_attach: comedi_pci_enable fails\n"); return -ENODEV; } devpriv->got_regions = 1; @@ -558,7 +558,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE); if (devpriv->base_addr == NULL) { - printk("s626_attach: IOREMAP failed\n"); + printk(KERN_ERR "s626_attach: IOREMAP failed\n"); return -ENODEV; } @@ -579,7 +579,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); if (devpriv->ANABuf.LogicalBase == NULL) { - printk("s626_attach: DMA Memory mapping error\n"); + printk(KERN_ERR "s626_attach: DMA Memory mapping error\n"); return -ENOMEM; } @@ -596,7 +596,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); if (devpriv->RPSBuf.LogicalBase == NULL) { - printk("s626_attach: DMA Memory mapping error\n"); + printk(KERN_ERR "s626_attach: DMA Memory mapping error\n"); return -ENOMEM; } @@ -622,18 +622,18 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* set up interrupt handler */ if (dev->irq == 0) { - printk(" unknown irq (bad)\n"); + printk(KERN_ERR " unknown irq (bad)\n"); } else { ret = request_irq(dev->irq, s626_irq_handler, IRQF_SHARED, "s626", dev); if (ret < 0) { - printk(" irq not available\n"); + printk(KERN_ERR " irq not available\n"); dev->irq = 0; } } - DEBUG("s626_attach: -- it opts %d,%d -- \n", + DEBUG("s626_attach: -- it opts %d,%d --\n", it->options[0], it->options[1]); s = dev->subdevices + 0; @@ -1513,7 +1513,7 @@ void ResetADC(struct comedi_device *dev, uint8_t * ppl) break; /* Exit poll list processing loop. */ } } - DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems); + DEBUG("ResetADC: ADC items %d\n", devpriv->AdcItems); /* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the * ADC to stabilize for 2 microseconds before starting the final @@ -1574,7 +1574,7 @@ static int s626_ai_insn_config(struct comedi_device *dev, /* register uint8_t i; */ /* register int32_t *readaddr; */ -/* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */ +/* DEBUG("as626_ai_rinsn: ai_rinsn enter\n"); */ /* Trigger ADC scan loop start by setting RPS Signal 0. */ /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ @@ -1591,11 +1591,11 @@ static int s626_ai_insn_config(struct comedi_device *dev, /* Convert ADC data to 16-bit integer values and copy to application buffer. */ /* for ( i = 0; i < devpriv->AdcItems; i++ ) { */ /* *data = s626_ai_reg_to_uint( *readaddr++ ); */ -/* DEBUG("s626_ai_rinsn: data %d \n",*data); */ +/* DEBUG("s626_ai_rinsn: data %d\n",*data); */ /* data++; */ /* } */ -/* DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */ +/* DEBUG("s626_ai_rinsn: ai_rinsn escape\n"); */ /* return i; */ /* } */ @@ -1743,7 +1743,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) DEBUG("s626_ai_cmd: entering command function\n"); if (devpriv->ai_cmd_running) { - printk("s626_ai_cmd: Another ai_cmd is running %d\n", + printk(KERN_ERR "s626_ai_cmd: Another ai_cmd is running %d\n", dev->minor); return -EBUSY; } @@ -2147,7 +2147,7 @@ static void s626_dio_init(struct comedi_device *dev) DEBIwrite(dev, diopriv->WRDOut, 0); /* Program all outputs */ /* to inactive state. */ } - DEBUG("s626_dio_init: DIO initialized \n"); + DEBUG("s626_dio_init: DIO initialized\n"); } /* DIO devices are slightly special. Although it is possible to @@ -2346,7 +2346,7 @@ static int s626_enc_insn_read(struct comedi_device *dev, int n; struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; - DEBUG("s626_enc_insn_read: encoder read channel %d \n", + DEBUG("s626_enc_insn_read: encoder read channel %d\n", CR_CHAN(insn->chanspec)); for (n = 0; n < insn->n; n++) @@ -2364,7 +2364,7 @@ static int s626_enc_insn_write(struct comedi_device *dev, struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; - DEBUG("s626_enc_insn_write: encoder write channel %d \n", + DEBUG("s626_enc_insn_write: encoder write channel %d\n", CR_CHAN(insn->chanspec)); /* Set the preload register */ @@ -3099,12 +3099,12 @@ static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k) static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, uint16_t value) { - DEBUG("SetLatchSource: SetLatchSource enter 3550 \n"); + DEBUG("SetLatchSource: SetLatchSource enter 3550\n"); DEBIreplace(dev, k->MyCRB, (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)), (uint16_t) (value << CRBBIT_LATCHSRC)); - DEBUG("SetLatchSource: SetLatchSource exit \n"); + DEBUG("SetLatchSource: SetLatchSource exit\n"); } /* @@ -3317,6 +3317,6 @@ static void CountersInit(struct comedi_device *dev) k->ResetCapFlags(dev, k); k->SetEnable(dev, k, CLKENAB_ALWAYS); } - DEBUG("CountersInit: counters initialized \n"); + DEBUG("CountersInit: counters initialized\n"); } -- cgit v1.2.3 From 0c55484dcae163aa28736a0da7e33fe747f3e302 Mon Sep 17 00:00:00 2001 From: Bob Beattie Date: Fri, 4 Jun 2010 00:19:02 +0100 Subject: Staging: comedi: drivers: fix space coding style in am9513.h This is a patch to the file am9513.h that fixes missing space warnings found by the checkpatch.pl tool. Signed-off-by: Bob Beattie Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/am9513.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/am9513.h b/drivers/staging/comedi/drivers/am9513.h index 73367d6afffe..0bb839e51493 100644 --- a/drivers/staging/comedi/drivers/am9513.h +++ b/drivers/staging/comedi/drivers/am9513.h @@ -47,32 +47,32 @@ #ifdef Am9513_8BITBUS #define Am9513_write_register(reg, val) \ - do{ \ + do { \ Am9513_output_control(reg); \ Am9513_output_data(val>>8); \ Am9513_output_data(val&0xff); \ - }while (0) + } while (0) #define Am9513_read_register(reg, val) \ - do{ \ + do { \ Am9513_output_control(reg); \ - val=Am9513_input_data()<<8; \ - val|=Am9513_input_data(); \ - }while (0) + val = Am9513_input_data()<<8; \ + val |= Am9513_input_data(); \ + } while (0) #else /* Am9513_16BITBUS */ #define Am9513_write_register(reg, val) \ - do{ \ + do { \ Am9513_output_control(reg); \ Am9513_output_data(val); \ - }while (0) + } while (0) #define Am9513_read_register(reg, val) \ - do{ \ + do { \ Am9513_output_control(reg); \ - val=Am9513_input_data(); \ - }while (0) + val = Am9513_input_data(); \ + } while (0) #endif -- cgit v1.2.3 From 88d8ed4b643d2064a663b2f07426963289def676 Mon Sep 17 00:00:00 2001 From: Maurice Dawson Date: Fri, 4 Jun 2010 13:07:06 +0100 Subject: Staging: comedi: fix printk() coding style issue in ni_labpc.c This is a patch to the ni_labpc.c file that fixes all, printk() should include KERN-facility level, warnings found by the checkpatch.pl tool Signed-off-by: Maurice Dawson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 67c8a538802c..0e3ac5a5b050 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -526,7 +526,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, unsigned long dma_flags, isr_flags; short lsb, msb; - printk("comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, thisboard->name, + printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, + thisboard->name, iobase); if (irq) printk(", irq %u", irq); @@ -543,7 +544,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, /* check if io addresses are available */ if (!request_region(iobase, LABPC_SIZE, driver_labpc.driver_name)) { - printk("I/O port conflict\n"); + printk(KERN_ERR "I/O port conflict\n"); return -EIO; } } @@ -575,7 +576,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, isr_flags |= IRQF_SHARED; if (request_irq(irq, labpc_interrupt, isr_flags, driver_labpc.driver_name, dev)) { - printk("unable to allocate irq %u\n", irq); + printk(KERN_ERR "unable to allocate irq %u\n", irq); return -EINVAL; } } @@ -583,18 +584,18 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, /* grab dma channel */ if (dma_chan > 3) { - printk(" invalid dma channel %u\n", dma_chan); + printk(KERN_ERR " invalid dma channel %u\n", dma_chan); return -EINVAL; } else if (dma_chan) { /* allocate dma buffer */ devpriv->dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); if (devpriv->dma_buffer == NULL) { - printk(" failed to allocate dma buffer\n"); + printk(KERN_ERR " failed to allocate dma buffer\n"); return -ENOMEM; } if (request_dma(dma_chan, driver_labpc.driver_name)) { - printk(" failed to allocate dma channel %u\n", + printk(KERN_ERR " failed to allocate dma channel %u\n", dma_chan); return -EINVAL; } @@ -690,7 +691,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, for (i = 0; i < EEPROM_SIZE; i++) devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); #ifdef LABPC_DEBUG - printk(" eeprom:"); + printk(KERN_ERR " eeprom:"); for (i = 0; i < EEPROM_SIZE; i++) printk(" %i:0x%x ", i, devpriv->eeprom_data[i]); printk("\n"); @@ -732,7 +733,8 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) iobase = (unsigned long)devpriv->mite->daq_io_addr; irq = mite_irq(devpriv->mite); #else - printk(" this driver has not been built with PCI support.\n"); + printk(KERN_ERR " this driver has not been built with PCI " + "support.\n"); return -EINVAL; #endif break; @@ -742,7 +744,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EINVAL; break; default: - printk("bug! couldn't determine board type\n"); + printk(KERN_ERR "bug! couldn't determine board type\n"); return -EINVAL; break; } @@ -776,7 +778,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot) } } } - printk("no device found\n"); + printk(KERN_ERR "no device found\n"); mite_list_devices(); return -EIO; } @@ -784,7 +786,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot) int labpc_common_detach(struct comedi_device *dev) { - printk("comedi%d: ni_labpc: detach\n", dev->minor); + printk(KERN_ERR "comedi%d: ni_labpc: detach\n", dev->minor); if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 2); @@ -846,7 +848,7 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1])) return MODE_MULT_CHAN_DOWN; - printk("ni_labpc: bug! this should never happen\n"); + printk(KERN_ERR "ni_labpc: bug! this should never happen\n"); return 0; } @@ -902,7 +904,7 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, } break; default: - printk("ni_labpc: bug! in chanlist check\n"); + printk(KERN_ERR "ni_labpc: bug! in chanlist check\n"); return 1; break; } -- cgit v1.2.3 From 90f703d30dd3e0c16ff80f35e34e511385a05ad5 Mon Sep 17 00:00:00 2001 From: Arun Thomas Date: Sun, 6 Jun 2010 22:23:29 +0200 Subject: Staging: comedi: Remove COMEDI_MODULES_MACRO Add MODULE_AUTHOR, MODULE_LICENSE, and MODULE_DESCRIPTION calls to the respective C source files instead of calling COMEDI_MODULES_MACRO Signed-off-by: Arun Thomas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 7 ------- drivers/staging/comedi/drivers/8255.c | 4 ++++ drivers/staging/comedi/drivers/acl7225b.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_035.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_1032.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_1500.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_1516.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_1564.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_16xx.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_2016.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_2032.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_2200.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_3001.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_3120.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_3501.c | 4 ++++ drivers/staging/comedi/drivers/addi_apci_3xxx.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci6208.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci7230.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci7296.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci7432.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci8164.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci9111.c | 4 ++++ drivers/staging/comedi/drivers/adl_pci9118.c | 4 ++++ drivers/staging/comedi/drivers/adq12b.c | 4 ++++ drivers/staging/comedi/drivers/adv_pci1710.c | 4 ++++ drivers/staging/comedi/drivers/adv_pci1723.c | 4 ++++ drivers/staging/comedi/drivers/adv_pci_dio.c | 4 ++++ drivers/staging/comedi/drivers/aio_aio12_8.c | 4 ++++ drivers/staging/comedi/drivers/aio_iiro_16.c | 4 ++++ drivers/staging/comedi/drivers/amplc_dio200.c | 4 ++++ drivers/staging/comedi/drivers/amplc_pc236.c | 4 ++++ drivers/staging/comedi/drivers/amplc_pc263.c | 4 ++++ drivers/staging/comedi/drivers/amplc_pci224.c | 4 ++++ drivers/staging/comedi/drivers/amplc_pci230.c | 4 ++++ drivers/staging/comedi/drivers/c6xdigio.c | 4 ++++ drivers/staging/comedi/drivers/cb_pcidas.c | 4 ++++ drivers/staging/comedi/drivers/cb_pcidas64.c | 4 ++++ drivers/staging/comedi/drivers/cb_pcidda.c | 4 ++++ drivers/staging/comedi/drivers/cb_pcidio.c | 4 ++++ drivers/staging/comedi/drivers/cb_pcimdas.c | 4 ++++ drivers/staging/comedi/drivers/comedi_parport.c | 4 ++++ drivers/staging/comedi/drivers/comedi_test.c | 4 ++++ drivers/staging/comedi/drivers/contec_pci_dio.c | 4 ++++ drivers/staging/comedi/drivers/daqboard2000.c | 4 ++++ drivers/staging/comedi/drivers/das08.c | 4 ++++ drivers/staging/comedi/drivers/das16.c | 4 ++++ drivers/staging/comedi/drivers/das16m1.c | 4 ++++ drivers/staging/comedi/drivers/das1800.c | 4 ++++ drivers/staging/comedi/drivers/das6402.c | 4 ++++ drivers/staging/comedi/drivers/das800.c | 4 ++++ drivers/staging/comedi/drivers/dmm32at.c | 4 ++++ drivers/staging/comedi/drivers/dt2801.c | 4 ++++ drivers/staging/comedi/drivers/dt2811.c | 4 ++++ drivers/staging/comedi/drivers/dt2814.c | 4 ++++ drivers/staging/comedi/drivers/dt2815.c | 4 ++++ drivers/staging/comedi/drivers/dt2817.c | 4 ++++ drivers/staging/comedi/drivers/dt282x.c | 4 ++++ drivers/staging/comedi/drivers/dt3000.c | 4 ++++ drivers/staging/comedi/drivers/fl512.c | 4 ++++ drivers/staging/comedi/drivers/gsc_hpdi.c | 4 ++++ drivers/staging/comedi/drivers/icp_multi.c | 4 ++++ drivers/staging/comedi/drivers/ii_pci20kc.c | 4 ++++ drivers/staging/comedi/drivers/jr3_pci.c | 4 ++++ drivers/staging/comedi/drivers/ke_counter.c | 4 ++++ drivers/staging/comedi/drivers/me4000.c | 4 ++++ drivers/staging/comedi/drivers/me_daq.c | 4 ++++ drivers/staging/comedi/drivers/mite.c | 4 ++++ drivers/staging/comedi/drivers/mpc624.c | 4 ++++ drivers/staging/comedi/drivers/multiq3.c | 4 ++++ drivers/staging/comedi/drivers/ni_at_a2150.c | 4 ++++ drivers/staging/comedi/drivers/ni_at_ao.c | 4 ++++ drivers/staging/comedi/drivers/ni_atmio16d.c | 4 ++++ drivers/staging/comedi/drivers/ni_labpc.c | 4 ++++ drivers/staging/comedi/drivers/pcl711.c | 4 ++++ drivers/staging/comedi/drivers/pcl724.c | 4 ++++ drivers/staging/comedi/drivers/pcl725.c | 4 ++++ drivers/staging/comedi/drivers/pcl726.c | 4 ++++ drivers/staging/comedi/drivers/pcl730.c | 4 ++++ drivers/staging/comedi/drivers/pcl812.c | 4 ++++ drivers/staging/comedi/drivers/pcl816.c | 4 ++++ drivers/staging/comedi/drivers/pcl818.c | 4 ++++ drivers/staging/comedi/drivers/pcm3724.c | 4 ++++ drivers/staging/comedi/drivers/pcm3730.c | 4 ++++ drivers/staging/comedi/drivers/pcm_common.c | 4 ++++ drivers/staging/comedi/drivers/pcmad.c | 4 ++++ drivers/staging/comedi/drivers/pcmda12.c | 4 ++++ drivers/staging/comedi/drivers/pcmmio.c | 4 ++++ drivers/staging/comedi/drivers/pcmuio.c | 4 ++++ drivers/staging/comedi/drivers/poc.c | 4 ++++ drivers/staging/comedi/drivers/rtd520.c | 4 ++++ drivers/staging/comedi/drivers/rti800.c | 4 ++++ drivers/staging/comedi/drivers/rti802.c | 4 ++++ drivers/staging/comedi/drivers/s526.c | 4 ++++ drivers/staging/comedi/drivers/serial2002.c | 4 ++++ drivers/staging/comedi/drivers/skel.c | 4 ++++ drivers/staging/comedi/drivers/ssv_dnp.c | 4 ++++ drivers/staging/comedi/drivers/unioxx5.c | 4 ++++ 97 files changed, 384 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 41ef9207f99c..8daff9464fb4 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -61,13 +61,7 @@ module_init(x ## _init_module); \ module_exit(x ## _cleanup_module); -#define COMEDI_MODULE_MACROS \ - MODULE_AUTHOR("Comedi http://www.comedi.org"); \ - MODULE_DESCRIPTION("Comedi low-level driver"); \ - MODULE_LICENSE("GPL"); - #define COMEDI_INITCLEANUP(x) \ - COMEDI_MODULE_MACROS \ COMEDI_INITCLEANUP_NOMODULE(x) #define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \ @@ -106,7 +100,6 @@ module_exit(comedi_driver ## _cleanup_module); #define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \ - COMEDI_MODULE_MACROS \ COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) #define PCI_VENDOR_ID_ADLINK 0x144a diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index fe63830bd850..0f83090488d5 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -457,3 +457,7 @@ static int dev_8255_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index e20c3542c069..1d0a8ea77950 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -150,3 +150,7 @@ static int acl7225b_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index 6dfcbe803f2d..4c00df4bc153 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -5,3 +5,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_035" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index 4722ec834f7b..7831ce33b02e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_1032" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index db3dafdcf691..bfd84f66d9c0 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_1500" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index f591baff6a0b..a12e2f421370 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_1516" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 6f5c923ac226..1b9d598fb6ca 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_1564" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 1d926add9e6d..d54218d59c58 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_16xx" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c index 7266e412f0a6..fa50c7bb7ade 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2016.c +++ b/drivers/staging/comedi/drivers/addi_apci_2016.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_2016" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index f67da94119e8..073a8a56dbe4 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_2032" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index bc7f7d653503..adfbb5d410ef 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_2200" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c index d86c4209cb90..00ac762965c1 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3001.c +++ b/drivers/staging/comedi/drivers/addi_apci_3001.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_3001" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 0b22cf10415d..c35515845cf3 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_3120" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index d8a01b154e35..dd2c1d3bc18b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_3501" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 942bc9e259a8..03161c88eac2 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -3,3 +3,7 @@ #define ADDIDATA_DRIVER_NAME "addi_apci_3xxx" #include "addi-data/addi_common.c" + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 712b9e0788b6..3816115b18ce 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -408,3 +408,7 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index 24a82eb9d153..46b5c5c27621 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -204,3 +204,7 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev, } COMEDI_PCI_INITCLEANUP(driver_adl_pci7230, adl_pci7230_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index 8602865ae6b7..e7c5d66ccd95 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -178,3 +178,7 @@ static int adl_pci7296_detach(struct comedi_device *dev) } COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index b5a9499e438c..d68fbe2bdad6 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -211,3 +211,7 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, } COMEDI_PCI_INITCLEANUP(driver_adl_pci7432, adl_pci7432_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index da256a1e0b4d..5fafaf0ff999 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -390,3 +390,7 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev, } COMEDI_PCI_INITCLEANUP(driver_adl_pci8164, adl_pci8164_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 595689d5f17f..429a551bd5dd 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1409,3 +1409,7 @@ static int pci9111_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index ccef549778e4..d6c17e268ccd 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2432,3 +2432,7 @@ static int pci9118_detach(struct comedi_device *dev) /* ============================================================================== */ + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index f3ba645bf63b..f318a01dd57a 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -403,3 +403,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, * as necessary. */ COMEDI_INITCLEANUP(driver_adq12b); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 67c4f11a36ab..dbb50cf7e83c 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1613,3 +1613,7 @@ COMEDI_PCI_INITCLEANUP(driver_pci1710, pci1710_pci_table); /* ============================================================================== */ + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 9fe8fcc7f1d6..b973249fb224 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -497,3 +497,7 @@ static int pci1723_detach(struct comedi_device *dev) * as necessary. */ COMEDI_PCI_INITCLEANUP(driver_pci1723, pci1723_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index e424a0c7d34f..e7ba1f0b4e68 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1257,3 +1257,7 @@ COMEDI_PCI_INITCLEANUP(driver_pci_dio, pci_dio_pci_table); /* ============================================================================== */ + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 7a1c636df5be..dc00c4b4a155 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -228,3 +228,7 @@ static struct comedi_driver driver_aio_aio12_8 = { }; COMEDI_INITCLEANUP(driver_aio_aio12_8); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 4baef9ff932a..ad5e75babdd1 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -185,3 +185,7 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, } COMEDI_INITCLEANUP(driver_aio_iiro_16); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index bf27617aa62d..9a60c214373e 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1501,3 +1501,7 @@ static int dio200_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index a307d68d79c6..e94fb3e3d0e8 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -664,3 +664,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d) } return IRQ_RETVAL(handled); } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 15808e95ceab..14855e37476d 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -436,3 +436,7 @@ COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table); #else COMEDI_INITCLEANUP(driver_amplc_pc263); #endif + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index c486a878e180..a27e27f5b7b8 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1557,3 +1557,7 @@ static int pci224_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 7fffd967d47e..53d34147813b 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -3014,3 +3014,7 @@ static int pci230_ai_cancel(struct comedi_device *dev, pci230_ai_stop(dev, s); return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index fb0d5fa71765..d830176bbd02 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -518,3 +518,7 @@ static int c6xdigio_detach(struct comedi_device *dev) } COMEDI_INITCLEANUP(driver_c6xdigio); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 434591de37c5..04c71704507f 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1872,3 +1872,7 @@ static int nvram_read(struct comedi_device *dev, unsigned int address, * as necessary. */ COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 79aa286e9bb4..168a33511648 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4303,3 +4303,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, } i2c_stop(dev); } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 81829d6fd287..3c2a84e2065b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -858,3 +858,7 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, * as necessary. */ COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 38ccd105fa35..3afba5fd85d6 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -301,3 +301,7 @@ static int pcidio_detach(struct comedi_device *dev) * as necessary. */ COMEDI_PCI_INITCLEANUP(driver_cb_pcidio, pcidio_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 49dccbbd713f..bb5553d6b360 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -492,3 +492,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, * as necessary. */ COMEDI_PCI_INITCLEANUP(driver_cb_pcimdas, cb_pcimdas_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index fcd7721c5537..9cf76fdd7cb1 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -396,3 +396,7 @@ static int parport_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index ef83a1a445ba..a21fe2e47a4e 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -549,3 +549,7 @@ static int waveform_ao_insn_write(struct comedi_device *dev, return insn->n; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 9511814e6413..a3d55f46f0fb 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -233,3 +233,7 @@ static int contec_di_insn_bits(struct comedi_device *dev, } COMEDI_PCI_INITCLEANUP(driver_contec, contec_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 078ec273b277..83cde27ab725 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -888,3 +888,7 @@ static int daqboard2000_detach(struct comedi_device *dev) } COMEDI_PCI_INITCLEANUP(driver_daqboard2000, daqboard2000_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 9cb144f7e70c..3a52a0c0f926 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1090,3 +1090,7 @@ COMEDI_INITCLEANUP(driver_das08); #ifdef CONFIG_COMEDI_PCMCIA EXPORT_SYMBOL_GPL(das08_cs_boards); #endif + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index ccee4f1802d6..407d011a7606 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1776,3 +1776,7 @@ static void das16_ai_munge(struct comedi_device *dev, } } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index c403d8827434..387a8cbe855d 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -777,3 +777,7 @@ static int das16m1_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index de5e82fec878..a68a1e47db82 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1800,3 +1800,7 @@ static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) return size; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index a404a1831911..3aac876869dd 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -360,3 +360,7 @@ static int das6402_attach(struct comedi_device *dev, return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index aadc4971c909..b4083af4a66a 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -905,3 +905,7 @@ static int das800_set_frequency(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index d5cbd515c370..572b7a9e8673 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -1096,3 +1096,7 @@ void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) * as necessary. */ COMEDI_INITCLEANUP(driver_dmm32at); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 83fb6e56c3e9..a6f1546b39e5 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -720,3 +720,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev, return 1; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index ea9bfb7fd88e..2d103eb1ebc8 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -625,3 +625,7 @@ static int dt2811_do_insn_bits(struct comedi_device *dev, return 2; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 16fde066d266..0871fe0dc46f 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -387,3 +387,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) comedi_event(dev, s); return IRQ_HANDLED; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index d1a4f7822433..8ff420eda1b1 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -255,3 +255,7 @@ static int dt2815_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 54e0dea0fc59..019aa4dfeeb3 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -180,3 +180,7 @@ static int dt2817_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index fd8728c83669..58a2fdfcd340 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1502,3 +1502,7 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index ca687890fc12..79ea24d2ce5a 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -991,3 +991,7 @@ static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board) *board = -1; return from; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index a10a2b070a24..19f018438612 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -205,3 +205,7 @@ static int fl512_detach(struct comedi_device *dev) printk(KERN_INFO "comedi%d: fl512: dummy i detach\n", dev->minor); return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 17c4f1f8117d..a24d0994a195 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -1076,3 +1076,7 @@ static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index fa0e48173bd4..ba42478e6e1c 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -1125,3 +1125,7 @@ static int icp_multi_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index e26c1b88ebeb..0951f0e28a64 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -641,3 +641,7 @@ static unsigned int pci20xxx_di(struct comedi_device *dev, #endif COMEDI_INITCLEANUP(driver_pci20xxx); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 4683a0b90f22..35a789226997 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -988,3 +988,7 @@ static int jr3_pci_detach(struct comedi_device *dev) } COMEDI_PCI_INITCLEANUP(driver_jr3_pci, jr3_pci_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 73b0445e310f..35d9869884db 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -259,3 +259,7 @@ static int cnt_detach(struct comedi_device *dev) dev->minor); return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 8b9fa0f9f1f6..58df32676e41 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2384,3 +2384,7 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, } COMEDI_PCI_INITCLEANUP(driver_me4000, me4000_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index c8484aec657d..d03c0f79ce45 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -857,3 +857,7 @@ static int me_detach(struct comedi_device *dev) } return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 99d9985c5b37..4b7d207ab14d 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -829,3 +829,7 @@ void __exit cleanup_module(void) mite_cleanup(); } #endif + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 9874ac3749c3..df001e1738a0 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -407,3 +407,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, } COMEDI_INITCLEANUP(driver_mpc624); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 6b22f0f8f06a..41bc51da388c 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -338,3 +338,7 @@ static int multiq3_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 9bff34cf06d1..709fc85ac703 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -910,3 +910,7 @@ static int a2150_set_chanlist(struct comedi_device *dev, return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index ce60224bb7bf..be1ddf28a549 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -459,3 +459,7 @@ static int atao_calib_insn_write(struct comedi_device *dev, return insn->n; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index cf4f241f210a..78fdf7bfb33a 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -887,3 +887,7 @@ static int atmio16d_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 0e3ac5a5b050..4966c8e496d5 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -2088,3 +2088,7 @@ EXPORT_SYMBOL_GPL(labpc_common_detach); EXPORT_SYMBOL_GPL(range_labpc_1200_ai); EXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits); EXPORT_SYMBOL_GPL(labpc_1200_is_unipolar); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index a499f7070f72..870c40a75463 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -628,3 +628,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 0f103c328064..2811060b424b 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -221,3 +221,7 @@ static int pcl724_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index 60261f4ba5b4..cab4c13fff99 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -110,3 +110,7 @@ static int pcl725_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 6a1a9790a907..e54463136cc8 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -381,3 +381,7 @@ static int pcl726_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index e5e7bed21de0..7d4f29a71423 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -166,3 +166,7 @@ static int pcl730_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 1ddc19c705a6..b82c37c5d167 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1660,3 +1660,7 @@ static int pcl812_detach(struct comedi_device *dev) free_resources(dev); return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 71c2a3aa379e..c26dfad2c897 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -1285,3 +1285,7 @@ static int pcl816_detach(struct comedi_device *dev) #endif return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 9d6aa393ef13..887f1c37aa6b 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -2036,3 +2036,7 @@ static int pcl818_detach(struct comedi_device *dev) free_resources(dev); return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index ed6103079232..972cd2bdf454 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -307,3 +307,7 @@ static int pcm3724_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index 22b7aae63add..3c826b7b8e75 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -154,3 +154,7 @@ static int pcm3730_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c index 52c2a6698214..474af7bc6c8b 100644 --- a/drivers/staging/comedi/drivers/pcm_common.c +++ b/drivers/staging/comedi/drivers/pcm_common.c @@ -109,3 +109,7 @@ int comedi_pcm_cmdtest(struct comedi_device *dev, return 0; } EXPORT_SYMBOL(comedi_pcm_cmdtest); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index fab8092bd7aa..9f63a6cacfca 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -176,3 +176,7 @@ static int pcmad_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 7133eb0352bc..b09c0da8690c 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -304,3 +304,7 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, * as necessary. */ COMEDI_INITCLEANUP(driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 025a52e8981d..3e80da04277f 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1334,3 +1334,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, * as necessary. */ COMEDI_INITCLEANUP(driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 5af4c8448a3a..785b3ec8fec8 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -1019,3 +1019,7 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, * as necessary. */ COMEDI_INITCLEANUP(driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 1ebc356ce40e..9270b9f15823 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -249,3 +249,7 @@ static int pcl734_insn_bits(struct comedi_device *dev, } COMEDI_INITCLEANUP(driver_poc); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 8626658e778c..1ca92f949362 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -2357,3 +2357,7 @@ static int rtd_dio_insn_config(struct comedi_device *dev, * as necessary. */ COMEDI_PCI_INITCLEANUP(rtd520Driver, rtd520_pci_table); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 028ed6f89c4c..4add63328508 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -475,3 +475,7 @@ static int rti800_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 2157edcf7997..132415b2d005 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -150,3 +150,7 @@ static int rti802_detach(struct comedi_device *dev) return 0; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 07c21e686f27..8afed1307bdd 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -1003,3 +1003,7 @@ static int s526_dio_insn_config(struct comedi_device *dev, * as necessary. */ COMEDI_INITCLEANUP(driver_s526); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 5886ebfd043a..85d127fb7eb1 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -918,3 +918,7 @@ static int serial2002_detach(struct comedi_device *dev) } COMEDI_INITCLEANUP(driver_serial2002); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 490753b3d904..5a0767333bbc 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -629,3 +629,7 @@ COMEDI_INITCLEANUP(driver_skel); * instead. */ /* COMEDI_PCI_INITCLEANUP(driver_skel, skel_pci_table) */ + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 18b0a83c4bbc..ce0cbb4c37bf 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -314,3 +314,7 @@ static int dnp_dio_insn_config(struct comedi_device *dev, return 1; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index d5f6d758a8be..1aca98895f83 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -529,3 +529,7 @@ static int __unioxx5_define_chan_offset(int chan_num) return (chan_num >> 3) + 1; } + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7114a28011f9d5f3d981731ad341177c21f9d948 Mon Sep 17 00:00:00 2001 From: Arun Thomas Date: Sun, 6 Jun 2010 22:23:30 +0200 Subject: Staging: comedi: Remove COMEDI_INITCLEANUP macro Move the init/exit routines to the respective C source files instead of calling COMEDI_INITCLEANUP Signed-off-by: Arun Thomas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 11 ----------- drivers/staging/comedi/drivers/8255.c | 13 ++++++++++++- drivers/staging/comedi/drivers/acl7225b.c | 13 ++++++++++++- drivers/staging/comedi/drivers/adq12b.c | 13 ++++++++++++- drivers/staging/comedi/drivers/aio_aio12_8.c | 13 ++++++++++++- drivers/staging/comedi/drivers/aio_iiro_16.c | 13 ++++++++++++- drivers/staging/comedi/drivers/amplc_dio200.c | 13 ++++++++++++- drivers/staging/comedi/drivers/amplc_pc236.c | 13 ++++++++++++- drivers/staging/comedi/drivers/amplc_pc263.c | 13 ++++++++++++- drivers/staging/comedi/drivers/c6xdigio.c | 13 ++++++++++++- drivers/staging/comedi/drivers/cb_das16_cs.c | 13 ++++++++++++- drivers/staging/comedi/drivers/comedi_parport.c | 13 ++++++++++++- drivers/staging/comedi/drivers/comedi_test.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das08.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das16.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das16m1.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das1800.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das6402.c | 13 ++++++++++++- drivers/staging/comedi/drivers/das800.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dmm32at.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt2801.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt2811.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt2814.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt2815.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt2817.c | 13 ++++++++++++- drivers/staging/comedi/drivers/dt282x.c | 13 ++++++++++++- drivers/staging/comedi/drivers/fl512.c | 13 ++++++++++++- drivers/staging/comedi/drivers/icp_multi.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ii_pci20kc.c | 13 ++++++++++++- drivers/staging/comedi/drivers/mpc624.c | 13 ++++++++++++- drivers/staging/comedi/drivers/mpc8260cpm.c | 13 ++++++++++++- drivers/staging/comedi/drivers/multiq3.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ni_at_a2150.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ni_at_ao.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ni_atmio.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ni_atmio16d.c | 13 ++++++++++++- drivers/staging/comedi/drivers/ni_labpc.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl711.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl724.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl725.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl726.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl730.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl812.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl816.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcl818.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcm3724.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcm3730.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcmad.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcmda12.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcmmio.c | 13 ++++++++++++- drivers/staging/comedi/drivers/pcmuio.c | 13 ++++++++++++- drivers/staging/comedi/drivers/poc.c | 13 ++++++++++++- drivers/staging/comedi/drivers/rti800.c | 13 ++++++++++++- drivers/staging/comedi/drivers/rti802.c | 13 ++++++++++++- drivers/staging/comedi/drivers/s526.c | 13 ++++++++++++- drivers/staging/comedi/drivers/serial2002.c | 13 ++++++++++++- drivers/staging/comedi/drivers/skel.c | 17 ++++++++++++----- drivers/staging/comedi/drivers/ssv_dnp.c | 13 ++++++++++++- drivers/staging/comedi/drivers/unioxx5.c | 13 ++++++++++++- 59 files changed, 696 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 8daff9464fb4..8e0106520c2f 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -53,17 +53,6 @@ COMEDI_MINORVERSION, COMEDI_MICROVERSION) #define COMEDI_RELEASE VERSION -#define COMEDI_INITCLEANUP_NOMODULE(x) \ - static int __init x ## _init_module(void) \ - {return comedi_driver_register(&(x)); } \ - static void __exit x ## _cleanup_module(void) \ - {comedi_driver_unregister(&(x)); } \ - module_init(x ## _init_module); \ - module_exit(x ## _cleanup_module); - -#define COMEDI_INITCLEANUP(x) \ - COMEDI_INITCLEANUP_NOMODULE(x) - #define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \ static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \ const struct pci_device_id *ent) \ diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 0f83090488d5..95049a8d3b38 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -117,7 +117,18 @@ static struct comedi_driver driver_8255 = { .detach = dev_8255_detach, }; -COMEDI_INITCLEANUP(driver_8255); +static int __init driver_8255_init_module(void) +{ + return comedi_driver_register(&driver_8255); +} + +static void __exit driver_8255_cleanup_module(void) +{ + comedi_driver_unregister(&driver_8255); +} + +module_init(driver_8255_init_module); +module_exit(driver_8255_cleanup_module); static void do_config(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index 1d0a8ea77950..9def2250bb80 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -49,7 +49,18 @@ static struct comedi_driver driver_acl7225b = { .offset = sizeof(struct boardtype), }; -COMEDI_INITCLEANUP(driver_acl7225b); +static int __init driver_acl7225b_init_module(void) +{ + return comedi_driver_register(&driver_acl7225b); +} + +static void __exit driver_acl7225b_cleanup_module(void) +{ + comedi_driver_unregister(&driver_acl7225b); +} + +module_init(driver_acl7225b_init_module); +module_exit(driver_acl7225b_cleanup_module); static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index f318a01dd57a..4b470000b69c 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -402,7 +402,18 @@ static int adq12b_do_insn_bits(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_adq12b); +static int __init driver_adq12b_init_module(void) +{ + return comedi_driver_register(&driver_adq12b); +} + +static void __exit driver_adq12b_cleanup_module(void) +{ + comedi_driver_unregister(&driver_adq12b); +} + +module_init(driver_adq12b_init_module); +module_exit(driver_adq12b_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index dc00c4b4a155..1728cc013d16 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -227,7 +227,18 @@ static struct comedi_driver driver_aio_aio12_8 = { .offset = sizeof(struct aio12_8_boardtype), }; -COMEDI_INITCLEANUP(driver_aio_aio12_8); +static int __init driver_aio_aio12_8_init_module(void) +{ + return comedi_driver_register(&driver_aio_aio12_8); +} + +static void __exit driver_aio_aio12_8_cleanup_module(void) +{ + comedi_driver_unregister(&driver_aio_aio12_8); +} + +module_init(driver_aio_aio12_8_init_module); +module_exit(driver_aio_aio12_8_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index ad5e75babdd1..487599531fed 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -184,7 +184,18 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, return 2; } -COMEDI_INITCLEANUP(driver_aio_iiro_16); +static int __init driver_aio_iiro_16_init_module(void) +{ + return comedi_driver_register(&driver_aio_iiro_16); +} + +static void __exit driver_aio_iiro_16_cleanup_module(void) +{ + comedi_driver_unregister(&driver_aio_iiro_16); +} + +module_init(driver_aio_iiro_16_init_module); +module_exit(driver_aio_iiro_16_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 9a60c214373e..674cf1df7e2c 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -496,7 +496,18 @@ static struct comedi_driver driver_amplc_dio200 = { #ifdef CONFIG_COMEDI_PCI COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table); #else -COMEDI_INITCLEANUP(driver_amplc_dio200); +static int __init driver_amplc_dio200_init_module(void) +{ + return comedi_driver_register(&driver_amplc_dio200); +} + +static void __exit driver_amplc_dio200_cleanup_module(void) +{ + comedi_driver_unregister(&driver_amplc_dio200); +} + +module_init(driver_amplc_dio200_init_module); +module_exit(driver_amplc_dio200_cleanup_module); #endif /* diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index e94fb3e3d0e8..5ffee055c9a9 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -184,7 +184,18 @@ static struct comedi_driver driver_amplc_pc236 = { #ifdef CONFIG_COMEDI_PCI COMEDI_PCI_INITCLEANUP(driver_amplc_pc236, pc236_pci_table); #else -COMEDI_INITCLEANUP(driver_amplc_pc236); +static int __init driver_amplc_pc236_init_module(void) +{ + return comedi_driver_register(&driver_amplc_pc236); +} + +static void __exit driver_amplc_pc236_cleanup_module(void) +{ + comedi_driver_unregister(&driver_amplc_pc236); +} + +module_init(driver_amplc_pc236_init_module); +module_exit(driver_amplc_pc236_cleanup_module); #endif static int pc236_request_region(unsigned minor, unsigned long from, diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 14855e37476d..83af437eb436 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -434,7 +434,18 @@ static int pc263_dio_insn_config(struct comedi_device *dev, #ifdef CONFIG_COMEDI_PCI COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table); #else -COMEDI_INITCLEANUP(driver_amplc_pc263); +static int __init driver_amplc_pc263_init_module(void) +{ + return comedi_driver_register(&driver_amplc_pc263); +} + +static void __exit driver_amplc_pc263_cleanup_module(void) +{ + comedi_driver_unregister(&driver_amplc_pc263); +} + +module_init(driver_amplc_pc263_init_module); +module_exit(driver_amplc_pc263_cleanup_module); #endif MODULE_AUTHOR("Comedi http://www.comedi.org"); diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index d830176bbd02..e0ac825ea58a 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -517,7 +517,18 @@ static int c6xdigio_detach(struct comedi_device *dev) return 0; } -COMEDI_INITCLEANUP(driver_c6xdigio); +static int __init driver_c6xdigio_init_module(void) +{ + return comedi_driver_register(&driver_c6xdigio); +} + +static void __exit driver_c6xdigio_cleanup_module(void) +{ + comedi_driver_unregister(&driver_c6xdigio); +} + +module_init(driver_c6xdigio_init_module); +module_exit(driver_c6xdigio_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index d8d4ed6de35c..6d893c65adc8 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -880,5 +880,16 @@ void __exit cleanup_module(void) } #else -COMEDI_INITCLEANUP(driver_das16cs); +static int __init driver_das16cs_init_module(void) +{ + return comedi_driver_register(&driver_das16cs); +} + +static void __exit driver_das16cs_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das16cs); +} + +module_init(driver_das16cs_init_module); +module_exit(driver_das16cs_cleanup_module); #endif /* CONFIG_PCMCIA */ diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 9cf76fdd7cb1..21d834dd92b6 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -101,7 +101,18 @@ static struct comedi_driver driver_parport = { .detach = parport_detach, }; -COMEDI_INITCLEANUP(driver_parport); +static int __init driver_parport_init_module(void) +{ + return comedi_driver_register(&driver_parport); +} + +static void __exit driver_parport_cleanup_module(void) +{ + comedi_driver_unregister(&driver_parport); +} + +module_init(driver_parport_init_module); +module_exit(driver_parport_cleanup_module); struct parport_private { unsigned int a_data; diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index a21fe2e47a4e..b220b3055412 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -107,7 +107,18 @@ static struct comedi_driver driver_waveform = { .num_names = ARRAY_SIZE(waveform_boards), }; -COMEDI_INITCLEANUP(driver_waveform); +static int __init driver_waveform_init_module(void) +{ + return comedi_driver_register(&driver_waveform); +} + +static void __exit driver_waveform_cleanup_module(void) +{ + comedi_driver_unregister(&driver_waveform); +} + +module_init(driver_waveform_init_module); +module_exit(driver_waveform_cleanup_module); static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 3a52a0c0f926..c3f1fedc6eb7 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1084,7 +1084,18 @@ EXPORT_SYMBOL_GPL(das08_common_detach); #ifdef CONFIG_COMEDI_PCI COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table); #else -COMEDI_INITCLEANUP(driver_das08); +static int __init driver_das08_init_module(void) +{ + return comedi_driver_register(&driver_das08); +} + +static void __exit driver_das08_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das08); +} + +module_init(driver_das08_init_module); +module_exit(driver_das08_cleanup_module); #endif #ifdef CONFIG_COMEDI_PCMCIA diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 407d011a7606..0af1b4659088 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1717,7 +1717,18 @@ static int das16_detach(struct comedi_device *dev) return 0; } -COMEDI_INITCLEANUP(driver_das16); +static int __init driver_das16_init_module(void) +{ + return comedi_driver_register(&driver_das16); +} + +static void __exit driver_das16_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das16); +} + +module_init(driver_das16_init_module); +module_exit(driver_das16_cleanup_module); /* utility function that suggests a dma transfer size in bytes */ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 387a8cbe855d..a5ce3b2abe4a 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -198,7 +198,18 @@ struct das16m1_private_struct { #define devpriv ((struct das16m1_private_struct *)(dev->private)) #define thisboard ((const struct das16m1_board *)(dev->board_ptr)) -COMEDI_INITCLEANUP(driver_das16m1); +static int __init driver_das16m1_init_module(void) +{ + return comedi_driver_register(&driver_das16m1); +} + +static void __exit driver_das16m1_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das16m1); +} + +module_init(driver_das16m1_init_module); +module_exit(driver_das16m1_cleanup_module); static inline short munge_sample(short data) { diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index a68a1e47db82..6ea93f9c0b48 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -531,7 +531,18 @@ static struct comedi_driver driver_das1800 = { * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_das1800); +static int __init driver_das1800_init_module(void) +{ + return comedi_driver_register(&driver_das1800); +} + +static void __exit driver_das1800_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das1800); +} + +module_init(driver_das1800_init_module); +module_exit(driver_das1800_cleanup_module); static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, unsigned int dma1) diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 3aac876869dd..6328f5280b66 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -109,7 +109,18 @@ static struct comedi_driver driver_das6402 = { .detach = das6402_detach, }; -COMEDI_INITCLEANUP(driver_das6402); +static int __init driver_das6402_init_module(void) +{ + return comedi_driver_register(&driver_das6402); +} + +static void __exit driver_das6402_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das6402); +} + +module_init(driver_das6402_init_module); +module_exit(driver_das6402_cleanup_module); struct das6402_private { int ai_bytes_to_read; diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index b4083af4a66a..aecaedc5027e 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -347,7 +347,18 @@ static int das800_probe(struct comedi_device *dev) * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_das800); +static int __init driver_das800_init_module(void) +{ + return comedi_driver_register(&driver_das800); +} + +static void __exit driver_das800_cleanup_module(void) +{ + comedi_driver_unregister(&driver_das800); +} + +module_init(driver_das800_init_module); +module_exit(driver_das800_cleanup_module); /* interrupt service routine */ static irqreturn_t das800_interrupt(int irq, void *d) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 572b7a9e8673..dcde8d8dd406 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -1095,7 +1095,18 @@ void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_dmm32at); +static int __init driver_dmm32at_init_module(void) +{ + return comedi_driver_register(&driver_dmm32at); +} + +static void __exit driver_dmm32at_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dmm32at); +} + +module_init(driver_dmm32at_init_module); +module_exit(driver_dmm32at_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index a6f1546b39e5..5cce1b5f4484 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -98,7 +98,18 @@ static struct comedi_driver driver_dt2801 = { .detach = dt2801_detach, }; -COMEDI_INITCLEANUP(driver_dt2801); +static int __init driver_dt2801_init_module(void) +{ + return comedi_driver_register(&driver_dt2801); +} + +static void __exit driver_dt2801_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt2801); +} + +module_init(driver_dt2801_init_module); +module_exit(driver_dt2801_cleanup_module); #if 0 /* ignore 'defined but not used' warning */ diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 2d103eb1ebc8..a1664caa1d96 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -239,7 +239,18 @@ static struct comedi_driver driver_dt2811 = { .offset = sizeof(struct dt2811_board), }; -COMEDI_INITCLEANUP(driver_dt2811); +static int __init driver_dt2811_init_module(void) +{ + return comedi_driver_register(&driver_dt2811); +} + +static void __exit driver_dt2811_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt2811); +} + +module_init(driver_dt2811_init_module); +module_exit(driver_dt2811_cleanup_module); static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 0871fe0dc46f..1c6248cf5928 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -70,7 +70,18 @@ static struct comedi_driver driver_dt2814 = { .detach = dt2814_detach, }; -COMEDI_INITCLEANUP(driver_dt2814); +static int __init driver_dt2814_init_module(void) +{ + return comedi_driver_register(&driver_dt2814); +} + +static void __exit driver_dt2814_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt2814); +} + +module_init(driver_dt2814_init_module); +module_exit(driver_dt2814_cleanup_module); static irqreturn_t dt2814_interrupt(int irq, void *dev); diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 8ff420eda1b1..4155da43fd51 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -82,7 +82,18 @@ static struct comedi_driver driver_dt2815 = { .detach = dt2815_detach, }; -COMEDI_INITCLEANUP(driver_dt2815); +static int __init driver_dt2815_init_module(void) +{ + return comedi_driver_register(&driver_dt2815); +} + +static void __exit driver_dt2815_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt2815); +} + +module_init(driver_dt2815_init_module); +module_exit(driver_dt2815_cleanup_module); static void dt2815_free_resources(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 019aa4dfeeb3..651fe050d029 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -57,7 +57,18 @@ static struct comedi_driver driver_dt2817 = { .detach = dt2817_detach, }; -COMEDI_INITCLEANUP(driver_dt2817); +static int __init driver_dt2817_init_module(void) +{ + return comedi_driver_register(&driver_dt2817); +} + +static void __exit driver_dt2817_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt2817); +} + +module_init(driver_dt2817_init_module); +module_exit(driver_dt2817_cleanup_module); static int dt2817_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 58a2fdfcd340..8cea9dca3d7e 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -423,7 +423,18 @@ static struct comedi_driver driver_dt282x = { .offset = sizeof(struct dt282x_board), }; -COMEDI_INITCLEANUP(driver_dt282x); +static int __init driver_dt282x_init_module(void) +{ + return comedi_driver_register(&driver_dt282x); +} + +static void __exit driver_dt282x_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dt282x); +} + +module_init(driver_dt282x_init_module); +module_exit(driver_dt282x_cleanup_module); static void free_resources(struct comedi_device *dev); static int prep_ai_dma(struct comedi_device *dev, int chan, int size); diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 19f018438612..7f49add60b21 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -52,7 +52,18 @@ static struct comedi_driver driver_fl512 = { .detach = fl512_detach, }; -COMEDI_INITCLEANUP(driver_fl512); +static int __init driver_fl512_init_module(void) +{ + return comedi_driver_register(&driver_fl512); +} + +static void __exit driver_fl512_cleanup_module(void) +{ + comedi_driver_unregister(&driver_fl512); +} + +module_init(driver_fl512_init_module); +module_exit(driver_fl512_cleanup_module); static int fl512_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index ba42478e6e1c..809d17efd5b3 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -185,7 +185,18 @@ board_name : &boardtypes[0].name, offset : sizeof(struct boardtype), }; -COMEDI_INITCLEANUP(driver_icp_multi); +static int __init driver_icp_multi_init_module(void) +{ + return comedi_driver_register(&driver_icp_multi); +} + +static void __exit driver_icp_multi_cleanup_module(void) +{ + comedi_driver_unregister(&driver_icp_multi); +} + +module_init(driver_icp_multi_init_module); +module_exit(driver_icp_multi_cleanup_module); struct icp_multi_private { struct pcilst_struct *card; /* pointer to card */ diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 0951f0e28a64..39a6a850d63c 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -640,7 +640,18 @@ static unsigned int pci20xxx_di(struct comedi_device *dev, } #endif -COMEDI_INITCLEANUP(driver_pci20xxx); +static int __init driver_pci20xxx_init_module(void) +{ + return comedi_driver_register(&driver_pci20xxx); +} + +static void __exit driver_pci20xxx_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pci20xxx); +} + +module_init(driver_pci20xxx_init_module); +module_exit(driver_pci20xxx_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index df001e1738a0..a89eebd23f65 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -406,7 +406,18 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, return n; } -COMEDI_INITCLEANUP(driver_mpc624); +static int __init driver_mpc624_init_module(void) +{ + return comedi_driver_register(&driver_mpc624); +} + +static void __exit driver_mpc624_cleanup_module(void) +{ + comedi_driver_unregister(&driver_mpc624); +} + +module_init(driver_mpc624_init_module); +module_exit(driver_mpc624_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c index 440a144a037e..5f6816a3fe8c 100644 --- a/drivers/staging/comedi/drivers/mpc8260cpm.c +++ b/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -56,7 +56,18 @@ static struct comedi_driver driver_mpc8260cpm = { .detach = mpc8260cpm_detach, }; -COMEDI_INITCLEANUP(driver_mpc8260cpm); +static int __init driver_mpc8260cpm_init_module(void) +{ + return comedi_driver_register(&driver_mpc8260cpm); +} + +static void __exit driver_mpc8260cpm_cleanup_module(void) +{ + comedi_driver_unregister(&driver_mpc8260cpm); +} + +module_init(driver_mpc8260cpm_init_module); +module_exit(driver_mpc8260cpm_cleanup_module); static int mpc8260cpm_dio_config(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 41bc51da388c..dace902d3bce 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -93,7 +93,18 @@ static struct comedi_driver driver_multiq3 = { .detach = multiq3_detach, }; -COMEDI_INITCLEANUP(driver_multiq3); +static int __init driver_multiq3_init_module(void) +{ + return comedi_driver_register(&driver_multiq3); +} + +static void __exit driver_multiq3_cleanup_module(void) +{ + comedi_driver_unregister(&driver_multiq3); +} + +module_init(driver_multiq3_init_module); +module_exit(driver_multiq3_cleanup_module); struct multiq3_private { unsigned int ao_readback[2]; diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 709fc85ac703..e46d62b75fc0 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -197,7 +197,18 @@ static int a2150_set_chanlist(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_a2150); +static int __init driver_a2150_init_module(void) +{ + return comedi_driver_register(&driver_a2150); +} + +static void __exit driver_a2150_cleanup_module(void) +{ + comedi_driver_unregister(&driver_a2150); +} + +module_init(driver_a2150_init_module); +module_exit(driver_a2150_cleanup_module); #ifdef A2150_DEBUG diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index be1ddf28a549..138dcc2275ab 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -194,7 +194,18 @@ static struct comedi_driver driver_atao = { .num_names = ARRAY_SIZE(atao_boards), }; -COMEDI_INITCLEANUP(driver_atao); +static int __init driver_atao_init_module(void) +{ + return comedi_driver_register(&driver_atao); +} + +static void __exit driver_atao_cleanup_module(void) +{ + comedi_driver_unregister(&driver_atao); +} + +module_init(driver_atao_init_module); +module_exit(driver_atao_cleanup_module); static void atao_reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 003d00b595b0..3330b3d53e8d 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -349,7 +349,18 @@ static struct comedi_driver driver_atmio = { .detach = ni_atmio_detach, }; -COMEDI_INITCLEANUP(driver_atmio); +static int __init driver_atmio_init_module(void) +{ + return comedi_driver_register(&driver_atmio); +} + +static void __exit driver_atmio_cleanup_module(void) +{ + comedi_driver_unregister(&driver_atmio); +} + +module_init(driver_atmio_init_module); +module_exit(driver_atmio_cleanup_module); #include "ni_mio_common.c" diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 78fdf7bfb33a..285b933551ab 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -151,7 +151,18 @@ static struct comedi_driver driver_atmio16d = { .offset = sizeof(struct atmio16_board_t), }; -COMEDI_INITCLEANUP(driver_atmio16d); +static int __init driver_atmio16d_init_module(void) +{ + return comedi_driver_register(&driver_atmio16d); +} + +static void __exit driver_atmio16d_cleanup_module(void) +{ + comedi_driver_unregister(&driver_atmio16d); +} + +module_init(driver_atmio16d_init_module); +module_exit(driver_atmio16d_cleanup_module); /* range structs */ static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { 4, { diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 4966c8e496d5..383ee1024ad3 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -2080,7 +2080,18 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, #ifdef CONFIG_COMEDI_PCI COMEDI_PCI_INITCLEANUP(driver_labpc, labpc_pci_table); #else -COMEDI_INITCLEANUP(driver_labpc); +static int __init driver_labpc_init_module(void) +{ + return comedi_driver_register(&driver_labpc); +} + +static void __exit driver_labpc_cleanup_module(void) +{ + comedi_driver_unregister(&driver_labpc); +} + +module_init(driver_labpc_init_module); +module_exit(driver_labpc_cleanup_module); #endif EXPORT_SYMBOL_GPL(labpc_common_attach); diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 870c40a75463..22d14fb3121b 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -171,7 +171,18 @@ static struct comedi_driver driver_pcl711 = { .offset = sizeof(struct pcl711_board), }; -COMEDI_INITCLEANUP(driver_pcl711); +static int __init driver_pcl711_init_module(void) +{ + return comedi_driver_register(&driver_pcl711); +} + +static void __exit driver_pcl711_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl711); +} + +module_init(driver_pcl711_init_module); +module_exit(driver_pcl711_cleanup_module); struct pcl711_private { diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 2811060b424b..396a058bb67d 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -93,7 +93,18 @@ static struct comedi_driver driver_pcl724 = { .offset = sizeof(struct pcl724_board), }; -COMEDI_INITCLEANUP(driver_pcl724); +static int __init driver_pcl724_init_module(void) +{ + return comedi_driver_register(&driver_pcl724); +} + +static void __exit driver_pcl724_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl724); +} + +module_init(driver_pcl724_init_module); +module_exit(driver_pcl724_cleanup_module); static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) { diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index cab4c13fff99..24b223ca4399 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -30,7 +30,18 @@ static struct comedi_driver driver_pcl725 = { .detach = pcl725_detach, }; -COMEDI_INITCLEANUP(driver_pcl725); +static int __init driver_pcl725_init_module(void) +{ + return comedi_driver_register(&driver_pcl725); +} + +static void __exit driver_pcl725_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl725); +} + +module_init(driver_pcl725_init_module); +module_exit(driver_pcl725_cleanup_module); static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index e54463136cc8..897cd808eeb7 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -162,7 +162,18 @@ static struct comedi_driver driver_pcl726 = { .offset = sizeof(struct pcl726_board), }; -COMEDI_INITCLEANUP(driver_pcl726); +static int __init driver_pcl726_init_module(void) +{ + return comedi_driver_register(&driver_pcl726); +} + +static void __exit driver_pcl726_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl726); +} + +module_init(driver_pcl726_init_module); +module_exit(driver_pcl726_cleanup_module); struct pcl726_private { diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 7d4f29a71423..c9682d614e0e 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -55,7 +55,18 @@ static struct comedi_driver driver_pcl730 = { .offset = sizeof(struct pcl730_board), }; -COMEDI_INITCLEANUP(driver_pcl730); +static int __init driver_pcl730_init_module(void) +{ + return comedi_driver_register(&driver_pcl730); +} + +static void __exit driver_pcl730_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl730); +} + +module_init(driver_pcl730_init_module); +module_exit(driver_pcl730_cleanup_module); static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index b82c37c5d167..943fb713bd7d 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -407,7 +407,18 @@ static struct comedi_driver driver_pcl812 = { .offset = sizeof(struct pcl812_board), }; -COMEDI_INITCLEANUP(driver_pcl812); +static int __init driver_pcl812_init_module(void) +{ + return comedi_driver_register(&driver_pcl812); +} + +static void __exit driver_pcl812_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl812); +} + +module_init(driver_pcl812_init_module); +module_exit(driver_pcl812_cleanup_module); struct pcl812_private { diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index c26dfad2c897..a84b942c5a93 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -168,7 +168,18 @@ static struct comedi_driver driver_pcl816 = { .offset = sizeof(struct pcl816_board), }; -COMEDI_INITCLEANUP(driver_pcl816); +static int __init driver_pcl816_init_module(void) +{ + return comedi_driver_register(&driver_pcl816); +} + +static void __exit driver_pcl816_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl816); +} + +module_init(driver_pcl816_init_module); +module_exit(driver_pcl816_cleanup_module); struct pcl816_private { diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 887f1c37aa6b..d2bd6f82b830 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -313,7 +313,18 @@ static struct comedi_driver driver_pcl818 = { .offset = sizeof(struct pcl818_board), }; -COMEDI_INITCLEANUP(driver_pcl818); +static int __init driver_pcl818_init_module(void) +{ + return comedi_driver_register(&driver_pcl818); +} + +static void __exit driver_pcl818_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcl818); +} + +module_init(driver_pcl818_init_module); +module_exit(driver_pcl818_cleanup_module); struct pcl818_private { diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 972cd2bdf454..26850954442f 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -97,7 +97,18 @@ static struct comedi_driver driver_pcm3724 = { .offset = sizeof(struct pcm3724_board), }; -COMEDI_INITCLEANUP(driver_pcm3724); +static int __init driver_pcm3724_init_module(void) +{ + return comedi_driver_register(&driver_pcm3724); +} + +static void __exit driver_pcm3724_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcm3724); +} + +module_init(driver_pcm3724_init_module); +module_exit(driver_pcm3724_cleanup_module); /* (setq c-basic-offset 8) */ diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index 3c826b7b8e75..bada6b236ff1 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -38,7 +38,18 @@ static struct comedi_driver driver_pcm3730 = { .detach = pcm3730_detach, }; -COMEDI_INITCLEANUP(driver_pcm3730); +static int __init driver_pcm3730_init_module(void) +{ + return comedi_driver_register(&driver_pcm3730); +} + +static void __exit driver_pcm3730_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcm3730); +} + +module_init(driver_pcm3730_init_module); +module_exit(driver_pcm3730_cleanup_module); static int pcm3730_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 9f63a6cacfca..23b3d777340c 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -89,7 +89,18 @@ static struct comedi_driver driver_pcmad = { .offset = sizeof(pcmad_boards[0]), }; -COMEDI_INITCLEANUP(driver_pcmad); +static int __init driver_pcmad_init_module(void) +{ + return comedi_driver_register(&driver_pcmad); +} + +static void __exit driver_pcmad_cleanup_module(void) +{ + comedi_driver_unregister(&driver_pcmad); +} + +module_init(driver_pcmad_init_module); +module_exit(driver_pcmad_cleanup_module); #define TIMEOUT 100 diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index b09c0da8690c..6d6b86ad817d 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -303,7 +303,18 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver); +static int __init driver_init_module(void) +{ + return comedi_driver_register(&driver); +} + +static void __exit driver_cleanup_module(void) +{ + comedi_driver_unregister(&driver); +} + +module_init(driver_init_module); +module_exit(driver_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 3e80da04277f..f0df9d1e4fec 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1333,7 +1333,18 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver); +static int __init driver_init_module(void) +{ + return comedi_driver_register(&driver); +} + +static void __exit driver_cleanup_module(void) +{ + comedi_driver_unregister(&driver); +} + +module_init(driver_init_module); +module_exit(driver_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 785b3ec8fec8..7a9287433b2e 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -1018,7 +1018,18 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver); +static int __init driver_init_module(void) +{ + return comedi_driver_register(&driver); +} + +static void __exit driver_cleanup_module(void) +{ + comedi_driver_unregister(&driver); +} + +module_init(driver_init_module); +module_exit(driver_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 9270b9f15823..831a576c24aa 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -248,7 +248,18 @@ static int pcl734_insn_bits(struct comedi_device *dev, return 2; } -COMEDI_INITCLEANUP(driver_poc); +static int __init driver_poc_init_module(void) +{ + return comedi_driver_register(&driver_poc); +} + +static void __exit driver_poc_cleanup_module(void) +{ + comedi_driver_unregister(&driver_poc); +} + +module_init(driver_poc_init_module); +module_exit(driver_poc_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 4add63328508..72042b818310 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -158,7 +158,18 @@ static struct comedi_driver driver_rti800 = { .offset = sizeof(struct rti800_board), }; -COMEDI_INITCLEANUP(driver_rti800); +static int __init driver_rti800_init_module(void) +{ + return comedi_driver_register(&driver_rti800); +} + +static void __exit driver_rti800_cleanup_module(void) +{ + comedi_driver_unregister(&driver_rti800); +} + +module_init(driver_rti800_init_module); +module_exit(driver_rti800_cleanup_module); static irqreturn_t rti800_interrupt(int irq, void *dev); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 132415b2d005..f59cb11590f6 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -57,7 +57,18 @@ static struct comedi_driver driver_rti802 = { .detach = rti802_detach, }; -COMEDI_INITCLEANUP(driver_rti802); +static int __init driver_rti802_init_module(void) +{ + return comedi_driver_register(&driver_rti802); +} + +static void __exit driver_rti802_cleanup_module(void) +{ + comedi_driver_unregister(&driver_rti802); +} + +module_init(driver_rti802_init_module); +module_exit(driver_rti802_cleanup_module); struct rti802_private { enum { diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 8afed1307bdd..3607aaee4af6 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -1002,7 +1002,18 @@ static int s526_dio_insn_config(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_INITCLEANUP(driver_s526); +static int __init driver_s526_init_module(void) +{ + return comedi_driver_register(&driver_s526); +} + +static void __exit driver_s526_cleanup_module(void) +{ + comedi_driver_unregister(&driver_s526); +} + +module_init(driver_s526_init_module); +module_exit(driver_s526_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 85d127fb7eb1..c9be9e05f028 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -917,7 +917,18 @@ static int serial2002_detach(struct comedi_device *dev) return 0; } -COMEDI_INITCLEANUP(driver_serial2002); +static int __init driver_serial2002_init_module(void) +{ + return comedi_driver_register(&driver_serial2002); +} + +static void __exit driver_serial2002_cleanup_module(void) +{ + comedi_driver_unregister(&driver_serial2002); +} + +module_init(driver_serial2002_init_module); +module_exit(driver_serial2002_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 5a0767333bbc..d1d5437c5995 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -620,11 +620,18 @@ static int skel_dio_insn_config(struct comedi_device *dev, return insn->n; } -/* - * A convenient macro that defines init_module() and cleanup_module(), - * as necessary. - */ -COMEDI_INITCLEANUP(driver_skel); +static int __init driver_skel_init_module(void) +{ + return comedi_driver_register(&driver_skel); +} + +static void __exit driver_skel_cleanup_module(void) +{ + comedi_driver_unregister(&driver_skel); +} + +module_init(driver_skel_init_module); +module_exit(driver_skel_cleanup_module); /* If you are writing a PCI driver you should use COMEDI_PCI_INITCLEANUP * instead. */ diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index ce0cbb4c37bf..526de2efa125 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -102,7 +102,18 @@ static struct comedi_driver driver_dnp = { .num_names = ARRAY_SIZE(dnp_boards), }; -COMEDI_INITCLEANUP(driver_dnp); +static int __init driver_dnp_init_module(void) +{ + return comedi_driver_register(&driver_dnp); +} + +static void __exit driver_dnp_cleanup_module(void) +{ + comedi_driver_unregister(&driver_dnp); +} + +module_init(driver_dnp_init_module); +module_exit(driver_dnp_cleanup_module); static int dnp_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 1aca98895f83..598884ec3ede 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -114,7 +114,18 @@ static struct comedi_driver unioxx5_driver = { .detach = unioxx5_detach }; -COMEDI_INITCLEANUP(unioxx5_driver); +static int __init unioxx5_driver_init_module(void) +{ + return comedi_driver_register(&unioxx5_driver); +} + +static void __exit unioxx5_driver_cleanup_module(void) +{ + comedi_driver_unregister(&unioxx5_driver); +} + +module_init(unioxx5_driver_init_module); +module_exit(unioxx5_driver_cleanup_module); static int unioxx5_attach(struct comedi_device *dev, struct comedi_devconfig *it) -- cgit v1.2.3 From 727b286b44ea359d66f47d241cc2cdad36ed7bdc Mon Sep 17 00:00:00 2001 From: Arun Thomas Date: Sun, 6 Jun 2010 22:23:31 +0200 Subject: Staging: comedi: Remove COMEDI_PCI_INITCLEANUP macro Move the PCI devinit/devexit routines to the respective C source files instead of calling COMEDI_PCI_INITCLEANUP Signed-off-by: Arun Thomas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 38 ------------------- .../staging/comedi/drivers/addi-data/addi_common.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci6208.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci7230.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci7296.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci7432.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci8164.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci9111.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adl_pci9118.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adv_pci1710.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adv_pci1723.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/adv_pci_dio.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/amplc_dio200.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/amplc_pc236.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/amplc_pc263.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/amplc_pci224.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/amplc_pci230.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcidas.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcidas64.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcidda.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcidio.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcimdas.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/cb_pcimdda.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/contec_pci_dio.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/daqboard2000.c | 40 +++++++++++++++++++- drivers/staging/comedi/drivers/das08.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/dt3000.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/gsc_hpdi.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/jr3_pci.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ke_counter.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/me4000.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/me_daq.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_6527.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_65xx.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_660x.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_670x.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_labpc.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_pcidio.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/ni_pcimio.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/rtd520.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/s626.c | 38 ++++++++++++++++++- drivers/staging/comedi/drivers/skel.c | 44 ++++++++++++++++++++-- 42 files changed, 1544 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 8e0106520c2f..68aa9176d249 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -53,44 +53,6 @@ COMEDI_MINORVERSION, COMEDI_MICROVERSION) #define COMEDI_RELEASE VERSION -#define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \ - static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \ - const struct pci_device_id *ent) \ - { \ - return comedi_pci_auto_config(dev, comedi_driver.driver_name); \ - } \ - static void __devexit comedi_driver ## _pci_remove(\ - struct pci_dev *dev) \ - { \ - comedi_pci_auto_unconfig(dev); \ - } \ - static struct pci_driver comedi_driver ## _pci_driver = \ - { \ - .id_table = pci_id_table, \ - .probe = &comedi_driver ## _pci_probe, \ - .remove = __devexit_p(&comedi_driver ## _pci_remove) \ - }; \ - static int __init comedi_driver ## _init_module(void) \ - { \ - int retval; \ - retval = comedi_driver_register(&comedi_driver); \ - if (retval < 0) \ - return retval; \ - comedi_driver ## _pci_driver.name = \ - (char *)comedi_driver.driver_name; \ - return pci_register_driver(&comedi_driver ## _pci_driver); \ - } \ - static void __exit comedi_driver ## _cleanup_module(void) \ - { \ - pci_unregister_driver(&comedi_driver ## _pci_driver); \ - comedi_driver_unregister(&comedi_driver); \ - } \ - module_init(comedi_driver ## _init_module); \ - module_exit(comedi_driver ## _cleanup_module); - -#define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \ - COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) - #define PCI_VENDOR_ID_ADLINK 0x144a #define PCI_VENDOR_ID_ICP 0x104c #define PCI_VENDOR_ID_CONTEC 0x1221 diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index b18e81d8cf8a..5ed4b9451f28 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -2541,7 +2541,43 @@ static struct comedi_driver driver_addi = { .offset = sizeof(struct addi_board), }; -COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl); +static int __devinit driver_addi_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_addi.driver_name); +} + +static void __devexit driver_addi_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_addi_pci_driver = { + .id_table = addi_apci_tbl, + .probe = &driver_addi_pci_probe, + .remove = __devexit_p(&driver_addi_pci_remove) +}; + +static int __init driver_addi_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_addi); + if (retval < 0) + return retval; + + driver_addi_pci_driver.name = (char *)driver_addi.driver_name; + return pci_register_driver(&driver_addi_pci_driver); +} + +static void __exit driver_addi_cleanup_module(void) +{ + pci_unregister_driver(&driver_addi_pci_driver); + comedi_driver_unregister(&driver_addi); +} + +module_init(driver_addi_init_module); +module_exit(driver_addi_cleanup_module); /* +----------------------------------------------------------------------------+ diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 3816115b18ce..0bc6ac2b6424 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -119,7 +119,43 @@ static struct comedi_driver driver_pci6208 = { .detach = pci6208_detach, }; -COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table); +static int __devinit driver_pci6208_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pci6208.driver_name); +} + +static void __devexit driver_pci6208_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pci6208_pci_driver = { + .id_table = pci6208_pci_table, + .probe = &driver_pci6208_pci_probe, + .remove = __devexit_p(&driver_pci6208_pci_remove) +}; + +static int __init driver_pci6208_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pci6208); + if (retval < 0) + return retval; + + driver_pci6208_pci_driver.name = (char *)driver_pci6208.driver_name; + return pci_register_driver(&driver_pci6208_pci_driver); +} + +static void __exit driver_pci6208_cleanup_module(void) +{ + pci_unregister_driver(&driver_pci6208_pci_driver); + comedi_driver_unregister(&driver_pci6208); +} + +module_init(driver_pci6208_init_module); +module_exit(driver_pci6208_cleanup_module); static int pci6208_find_device(struct comedi_device *dev, int bus, int slot); static int diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c index 46b5c5c27621..caeb4e11ac59 100644 --- a/drivers/staging/comedi/drivers/adl_pci7230.c +++ b/drivers/staging/comedi/drivers/adl_pci7230.c @@ -203,7 +203,45 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev, return 2; } -COMEDI_PCI_INITCLEANUP(driver_adl_pci7230, adl_pci7230_pci_table); +static int __devinit driver_adl_pci7230_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_adl_pci7230.driver_name); +} + +static void __devexit driver_adl_pci7230_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_adl_pci7230_pci_driver = { + .id_table = adl_pci7230_pci_table, + .probe = &driver_adl_pci7230_pci_probe, + .remove = __devexit_p(&driver_adl_pci7230_pci_remove) +}; + +static int __init driver_adl_pci7230_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_adl_pci7230); + if (retval < 0) + return retval; + + driver_adl_pci7230_pci_driver.name = + (char *)driver_adl_pci7230.driver_name; + return pci_register_driver(&driver_adl_pci7230_pci_driver); +} + +static void __exit driver_adl_pci7230_cleanup_module(void) +{ + pci_unregister_driver(&driver_adl_pci7230_pci_driver); + comedi_driver_unregister(&driver_adl_pci7230); +} + +module_init(driver_adl_pci7230_init_module); +module_exit(driver_adl_pci7230_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c index e7c5d66ccd95..947fae5adb94 100644 --- a/drivers/staging/comedi/drivers/adl_pci7296.c +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -177,7 +177,45 @@ static int adl_pci7296_detach(struct comedi_device *dev) return 0; } -COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table); +static int __devinit driver_adl_pci7296_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_adl_pci7296.driver_name); +} + +static void __devexit driver_adl_pci7296_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_adl_pci7296_pci_driver = { + .id_table = adl_pci7296_pci_table, + .probe = &driver_adl_pci7296_pci_probe, + .remove = __devexit_p(&driver_adl_pci7296_pci_remove) +}; + +static int __init driver_adl_pci7296_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_adl_pci7296); + if (retval < 0) + return retval; + + driver_adl_pci7296_pci_driver.name = + (char *)driver_adl_pci7296.driver_name; + return pci_register_driver(&driver_adl_pci7296_pci_driver); +} + +static void __exit driver_adl_pci7296_cleanup_module(void) +{ + pci_unregister_driver(&driver_adl_pci7296_pci_driver); + comedi_driver_unregister(&driver_adl_pci7296); +} + +module_init(driver_adl_pci7296_init_module); +module_exit(driver_adl_pci7296_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c index d68fbe2bdad6..3b2f8e3fccd2 100644 --- a/drivers/staging/comedi/drivers/adl_pci7432.c +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -210,7 +210,45 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev, return 2; } -COMEDI_PCI_INITCLEANUP(driver_adl_pci7432, adl_pci7432_pci_table); +static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name); +} + +static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_adl_pci7432_pci_driver = { + .id_table = adl_pci7432_pci_table, + .probe = &driver_adl_pci7432_pci_probe, + .remove = __devexit_p(&driver_adl_pci7432_pci_remove) +}; + +static int __init driver_adl_pci7432_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_adl_pci7432); + if (retval < 0) + return retval; + + driver_adl_pci7432_pci_driver.name = + (char *)driver_adl_pci7432.driver_name; + return pci_register_driver(&driver_adl_pci7432_pci_driver); +} + +static void __exit driver_adl_pci7432_cleanup_module(void) +{ + pci_unregister_driver(&driver_adl_pci7432_pci_driver); + comedi_driver_unregister(&driver_adl_pci7432); +} + +module_init(driver_adl_pci7432_init_module); +module_exit(driver_adl_pci7432_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 5fafaf0ff999..1b7155e4895e 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -389,7 +389,45 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev, return 2; } -COMEDI_PCI_INITCLEANUP(driver_adl_pci8164, adl_pci8164_pci_table); +static int __devinit driver_adl_pci8164_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_adl_pci8164.driver_name); +} + +static void __devexit driver_adl_pci8164_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_adl_pci8164_pci_driver = { + .id_table = adl_pci8164_pci_table, + .probe = &driver_adl_pci8164_pci_probe, + .remove = __devexit_p(&driver_adl_pci8164_pci_remove) +}; + +static int __init driver_adl_pci8164_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_adl_pci8164); + if (retval < 0) + return retval; + + driver_adl_pci8164_pci_driver.name = + (char *)driver_adl_pci8164.driver_name; + return pci_register_driver(&driver_adl_pci8164_pci_driver); +} + +static void __exit driver_adl_pci8164_cleanup_module(void) +{ + pci_unregister_driver(&driver_adl_pci8164_pci_driver); + comedi_driver_unregister(&driver_adl_pci8164); +} + +module_init(driver_adl_pci8164_init_module); +module_exit(driver_adl_pci8164_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 429a551bd5dd..38a5752bc4fc 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -350,7 +350,43 @@ static struct comedi_driver pci9111_driver = { .detach = pci9111_detach, }; -COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table); +static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, pci9111_driver.driver_name); +} + +static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver pci9111_driver_pci_driver = { + .id_table = pci9111_pci_table, + .probe = &pci9111_driver_pci_probe, + .remove = __devexit_p(&pci9111_driver_pci_remove) +}; + +static int __init pci9111_driver_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&pci9111_driver); + if (retval < 0) + return retval; + + pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name; + return pci_register_driver(&pci9111_driver_pci_driver); +} + +static void __exit pci9111_driver_cleanup_module(void) +{ + pci_unregister_driver(&pci9111_driver_pci_driver); + comedi_driver_unregister(&pci9111_driver); +} + +module_init(pci9111_driver_init_module); +module_exit(pci9111_driver_cleanup_module); /* Private data structure */ diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index d6c17e268ccd..b0e39cb74774 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -289,7 +289,43 @@ static struct comedi_driver driver_pci9118 = { .offset = sizeof(struct boardtype), }; -COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table); +static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pci9118.driver_name); +} + +static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pci9118_pci_driver = { + .id_table = pci9118_pci_table, + .probe = &driver_pci9118_pci_probe, + .remove = __devexit_p(&driver_pci9118_pci_remove) +}; + +static int __init driver_pci9118_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pci9118); + if (retval < 0) + return retval; + + driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name; + return pci_register_driver(&driver_pci9118_pci_driver); +} + +static void __exit driver_pci9118_cleanup_module(void) +{ + pci_unregister_driver(&driver_pci9118_pci_driver); + comedi_driver_unregister(&driver_pci9118); +} + +module_init(driver_pci9118_init_module); +module_exit(driver_pci9118_cleanup_module); struct pci9118_private { unsigned long iobase_a; /* base+size for AMCC chip */ diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index dbb50cf7e83c..2791f9037b98 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1609,7 +1609,43 @@ static int pci1710_detach(struct comedi_device *dev) /* ============================================================================== */ -COMEDI_PCI_INITCLEANUP(driver_pci1710, pci1710_pci_table); +static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pci1710.driver_name); +} + +static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pci1710_pci_driver = { + .id_table = pci1710_pci_table, + .probe = &driver_pci1710_pci_probe, + .remove = __devexit_p(&driver_pci1710_pci_remove) +}; + +static int __init driver_pci1710_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pci1710); + if (retval < 0) + return retval; + + driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name; + return pci_register_driver(&driver_pci1710_pci_driver); +} + +static void __exit driver_pci1710_cleanup_module(void) +{ + pci_unregister_driver(&driver_pci1710_pci_driver); + comedi_driver_unregister(&driver_pci1710); +} + +module_init(driver_pci1710_init_module); +module_exit(driver_pci1710_cleanup_module); /* ============================================================================== */ diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index b973249fb224..b133bb84c4fe 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -496,7 +496,43 @@ static int pci1723_detach(struct comedi_device *dev) * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(driver_pci1723, pci1723_pci_table); +static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pci1723.driver_name); +} + +static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pci1723_pci_driver = { + .id_table = pci1723_pci_table, + .probe = &driver_pci1723_pci_probe, + .remove = __devexit_p(&driver_pci1723_pci_remove) +}; + +static int __init driver_pci1723_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pci1723); + if (retval < 0) + return retval; + + driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name; + return pci_register_driver(&driver_pci1723_pci_driver); +} + +static void __exit driver_pci1723_cleanup_module(void) +{ + pci_unregister_driver(&driver_pci1723_pci_driver); + comedi_driver_unregister(&driver_pci1723); +} + +module_init(driver_pci1723_init_module); +module_exit(driver_pci1723_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index e7ba1f0b4e68..d81bbfac695a 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1253,7 +1253,43 @@ static int pci_dio_detach(struct comedi_device *dev) /* ============================================================================== */ -COMEDI_PCI_INITCLEANUP(driver_pci_dio, pci_dio_pci_table); +static int __devinit driver_pci_dio_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pci_dio.driver_name); +} + +static void __devexit driver_pci_dio_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pci_dio_pci_driver = { + .id_table = pci_dio_pci_table, + .probe = &driver_pci_dio_pci_probe, + .remove = __devexit_p(&driver_pci_dio_pci_remove) +}; + +static int __init driver_pci_dio_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pci_dio); + if (retval < 0) + return retval; + + driver_pci_dio_pci_driver.name = (char *)driver_pci_dio.driver_name; + return pci_register_driver(&driver_pci_dio_pci_driver); +} + +static void __exit driver_pci_dio_cleanup_module(void) +{ + pci_unregister_driver(&driver_pci_dio_pci_driver); + comedi_driver_unregister(&driver_pci_dio); +} + +module_init(driver_pci_dio_init_module); +module_exit(driver_pci_dio_cleanup_module); /* ============================================================================== */ diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 674cf1df7e2c..93bbe4ec318d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -494,7 +494,45 @@ static struct comedi_driver driver_amplc_dio200 = { }; #ifdef CONFIG_COMEDI_PCI -COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table); +static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name); +} + +static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_amplc_dio200_pci_driver = { + .id_table = dio200_pci_table, + .probe = &driver_amplc_dio200_pci_probe, + .remove = __devexit_p(&driver_amplc_dio200_pci_remove) +}; + +static int __init driver_amplc_dio200_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_amplc_dio200); + if (retval < 0) + return retval; + + driver_amplc_dio200_pci_driver.name = + (char *)driver_amplc_dio200.driver_name; + return pci_register_driver(&driver_amplc_dio200_pci_driver); +} + +static void __exit driver_amplc_dio200_cleanup_module(void) +{ + pci_unregister_driver(&driver_amplc_dio200_pci_driver); + comedi_driver_unregister(&driver_amplc_dio200); +} + +module_init(driver_amplc_dio200_init_module); +module_exit(driver_amplc_dio200_cleanup_module); #else static int __init driver_amplc_dio200_init_module(void) { diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 5ffee055c9a9..48246cd50d47 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -182,7 +182,45 @@ static struct comedi_driver driver_amplc_pc236 = { }; #ifdef CONFIG_COMEDI_PCI -COMEDI_PCI_INITCLEANUP(driver_amplc_pc236, pc236_pci_table); +static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name); +} + +static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_amplc_pc236_pci_driver = { + .id_table = pc236_pci_table, + .probe = &driver_amplc_pc236_pci_probe, + .remove = __devexit_p(&driver_amplc_pc236_pci_remove) +}; + +static int __init driver_amplc_pc236_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_amplc_pc236); + if (retval < 0) + return retval; + + driver_amplc_pc236_pci_driver.name = + (char *)driver_amplc_pc236.driver_name; + return pci_register_driver(&driver_amplc_pc236_pci_driver); +} + +static void __exit driver_amplc_pc236_cleanup_module(void) +{ + pci_unregister_driver(&driver_amplc_pc236_pci_driver); + comedi_driver_unregister(&driver_amplc_pc236); +} + +module_init(driver_amplc_pc236_init_module); +module_exit(driver_amplc_pc236_cleanup_module); #else static int __init driver_amplc_pc236_init_module(void) { diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 83af437eb436..8a3388079094 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -432,7 +432,45 @@ static int pc263_dio_insn_config(struct comedi_device *dev, * as necessary. */ #ifdef CONFIG_COMEDI_PCI -COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table); +static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_amplc_pc263.driver_name); +} + +static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_amplc_pc263_pci_driver = { + .id_table = pc263_pci_table, + .probe = &driver_amplc_pc263_pci_probe, + .remove = __devexit_p(&driver_amplc_pc263_pci_remove) +}; + +static int __init driver_amplc_pc263_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_amplc_pc263); + if (retval < 0) + return retval; + + driver_amplc_pc263_pci_driver.name = + (char *)driver_amplc_pc263.driver_name; + return pci_register_driver(&driver_amplc_pc263_pci_driver); +} + +static void __exit driver_amplc_pc263_cleanup_module(void) +{ + pci_unregister_driver(&driver_amplc_pc263_pci_driver); + comedi_driver_unregister(&driver_amplc_pc263); +} + +module_init(driver_amplc_pc263_init_module); +module_exit(driver_amplc_pc263_cleanup_module); #else static int __init driver_amplc_pc263_init_module(void) { diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index a27e27f5b7b8..1b5ba1c27259 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -443,7 +443,45 @@ static struct comedi_driver driver_amplc_pci224 = { .num_names = ARRAY_SIZE(pci224_boards), }; -COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table); +static int __devinit driver_amplc_pci224_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_amplc_pci224.driver_name); +} + +static void __devexit driver_amplc_pci224_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_amplc_pci224_pci_driver = { + .id_table = pci224_pci_table, + .probe = &driver_amplc_pci224_pci_probe, + .remove = __devexit_p(&driver_amplc_pci224_pci_remove) +}; + +static int __init driver_amplc_pci224_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_amplc_pci224); + if (retval < 0) + return retval; + + driver_amplc_pci224_pci_driver.name = + (char *)driver_amplc_pci224.driver_name; + return pci_register_driver(&driver_amplc_pci224_pci_driver); +} + +static void __exit driver_amplc_pci224_cleanup_module(void) +{ + pci_unregister_driver(&driver_amplc_pci224_pci_driver); + comedi_driver_unregister(&driver_amplc_pci224); +} + +module_init(driver_amplc_pci224_init_module); +module_exit(driver_amplc_pci224_cleanup_module); /* * Called from the 'insn_write' function to perform a single write. diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 53d34147813b..b572df718f21 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -617,7 +617,45 @@ static struct comedi_driver driver_amplc_pci230 = { .num_names = ARRAY_SIZE(pci230_boards), }; -COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table); +static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name); +} + +static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_amplc_pci230_pci_driver = { + .id_table = pci230_pci_table, + .probe = &driver_amplc_pci230_pci_probe, + .remove = __devexit_p(&driver_amplc_pci230_pci_remove) +}; + +static int __init driver_amplc_pci230_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_amplc_pci230); + if (retval < 0) + return retval; + + driver_amplc_pci230_pci_driver.name = + (char *)driver_amplc_pci230.driver_name; + return pci_register_driver(&driver_amplc_pci230_pci_driver); +} + +static void __exit driver_amplc_pci230_cleanup_module(void) +{ + pci_unregister_driver(&driver_amplc_pci230_pci_driver); + comedi_driver_unregister(&driver_amplc_pci230); +} + +module_init(driver_amplc_pci230_init_module); +module_exit(driver_amplc_pci230_cleanup_module); static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 04c71704507f..2d9ad537793e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1871,7 +1871,43 @@ static int nvram_read(struct comedi_device *dev, unsigned int address, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table); +static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name); +} + +static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_cb_pcidas_pci_driver = { + .id_table = cb_pcidas_pci_table, + .probe = &driver_cb_pcidas_pci_probe, + .remove = __devexit_p(&driver_cb_pcidas_pci_remove) +}; + +static int __init driver_cb_pcidas_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_cb_pcidas); + if (retval < 0) + return retval; + + driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name; + return pci_register_driver(&driver_cb_pcidas_pci_driver); +} + +static void __exit driver_cb_pcidas_cleanup_module(void) +{ + pci_unregister_driver(&driver_cb_pcidas_pci_driver); + comedi_driver_unregister(&driver_cb_pcidas); +} + +module_init(driver_cb_pcidas_init_module); +module_exit(driver_cb_pcidas_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 168a33511648..ba7c48ab6d92 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1237,7 +1237,43 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags); static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd); -COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table); +static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name); +} + +static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_cb_pcidas_pci_driver = { + .id_table = pcidas64_pci_table, + .probe = &driver_cb_pcidas_pci_probe, + .remove = __devexit_p(&driver_cb_pcidas_pci_remove) +}; + +static int __init driver_cb_pcidas_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_cb_pcidas); + if (retval < 0) + return retval; + + driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name; + return pci_register_driver(&driver_cb_pcidas_pci_driver); +} + +static void __exit driver_cb_pcidas_cleanup_module(void) +{ + pci_unregister_driver(&driver_cb_pcidas_pci_driver); + comedi_driver_unregister(&driver_cb_pcidas); +} + +module_init(driver_cb_pcidas_init_module); +module_exit(driver_cb_pcidas_cleanup_module); static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, unsigned int range_index) diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 3c2a84e2065b..349c7a61763a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -857,7 +857,43 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table); +static int __devinit driver_cb_pcidda_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_cb_pcidda.driver_name); +} + +static void __devexit driver_cb_pcidda_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_cb_pcidda_pci_driver = { + .id_table = cb_pcidda_pci_table, + .probe = &driver_cb_pcidda_pci_probe, + .remove = __devexit_p(&driver_cb_pcidda_pci_remove) +}; + +static int __init driver_cb_pcidda_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_cb_pcidda); + if (retval < 0) + return retval; + + driver_cb_pcidda_pci_driver.name = (char *)driver_cb_pcidda.driver_name; + return pci_register_driver(&driver_cb_pcidda_pci_driver); +} + +static void __exit driver_cb_pcidda_cleanup_module(void) +{ + pci_unregister_driver(&driver_cb_pcidda_pci_driver); + comedi_driver_unregister(&driver_cb_pcidda); +} + +module_init(driver_cb_pcidda_init_module); +module_exit(driver_cb_pcidda_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 3afba5fd85d6..a9d902f418a1 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -300,7 +300,43 @@ static int pcidio_detach(struct comedi_device *dev) * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(driver_cb_pcidio, pcidio_pci_table); +static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name); +} + +static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_cb_pcidio_pci_driver = { + .id_table = pcidio_pci_table, + .probe = &driver_cb_pcidio_pci_probe, + .remove = __devexit_p(&driver_cb_pcidio_pci_remove) +}; + +static int __init driver_cb_pcidio_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_cb_pcidio); + if (retval < 0) + return retval; + + driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name; + return pci_register_driver(&driver_cb_pcidio_pci_driver); +} + +static void __exit driver_cb_pcidio_cleanup_module(void) +{ + pci_unregister_driver(&driver_cb_pcidio_pci_driver); + comedi_driver_unregister(&driver_cb_pcidio); +} + +module_init(driver_cb_pcidio_init_module); +module_exit(driver_cb_pcidio_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index bb5553d6b360..e50b8c259e2c 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -491,7 +491,45 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(driver_cb_pcimdas, cb_pcimdas_pci_table); +static int __devinit driver_cb_pcimdas_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_cb_pcimdas.driver_name); +} + +static void __devexit driver_cb_pcimdas_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_cb_pcimdas_pci_driver = { + .id_table = cb_pcimdas_pci_table, + .probe = &driver_cb_pcimdas_pci_probe, + .remove = __devexit_p(&driver_cb_pcimdas_pci_remove) +}; + +static int __init driver_cb_pcimdas_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_cb_pcimdas); + if (retval < 0) + return retval; + + driver_cb_pcimdas_pci_driver.name = + (char *)driver_cb_pcimdas.driver_name; + return pci_register_driver(&driver_cb_pcimdas_pci_driver); +} + +static void __exit driver_cb_pcimdas_cleanup_module(void) +{ + pci_unregister_driver(&driver_cb_pcimdas_pci_driver); + comedi_driver_unregister(&driver_cb_pcimdas); +} + +module_init(driver_cb_pcimdas_init_module); +module_exit(driver_cb_pcimdas_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index f404ec7723e5..3160330b1d9e 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -195,7 +195,45 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA " "series. Currently only supports PCIM-DDA06-16 (which " "also happens to be the only board in this series. :) ) "); MODULE_LICENSE("GPL"); -COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table); +static int __devinit cb_pcimdda_driver_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, cb_pcimdda_driver.driver_name); +} + +static void __devexit cb_pcimdda_driver_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver cb_pcimdda_driver_pci_driver = { + .id_table = pci_table, + .probe = &cb_pcimdda_driver_pci_probe, + .remove = __devexit_p(&cb_pcimdda_driver_pci_remove) +}; + +static int __init cb_pcimdda_driver_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&cb_pcimdda_driver); + if (retval < 0) + return retval; + + cb_pcimdda_driver_pci_driver.name = + (char *)cb_pcimdda_driver.driver_name; + return pci_register_driver(&cb_pcimdda_driver_pci_driver); +} + +static void __exit cb_pcimdda_driver_cleanup_module(void) +{ + pci_unregister_driver(&cb_pcimdda_driver_pci_driver); + comedi_driver_unregister(&cb_pcimdda_driver); +} + +module_init(cb_pcimdda_driver_init_module); +module_exit(cb_pcimdda_driver_cleanup_module); static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index a3d55f46f0fb..24ac10ce0bae 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -232,7 +232,43 @@ static int contec_di_insn_bits(struct comedi_device *dev, return 2; } -COMEDI_PCI_INITCLEANUP(driver_contec, contec_pci_table); +static int __devinit driver_contec_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_contec.driver_name); +} + +static void __devexit driver_contec_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_contec_pci_driver = { + .id_table = contec_pci_table, + .probe = &driver_contec_pci_probe, + .remove = __devexit_p(&driver_contec_pci_remove) +}; + +static int __init driver_contec_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_contec); + if (retval < 0) + return retval; + + driver_contec_pci_driver.name = (char *)driver_contec.driver_name; + return pci_register_driver(&driver_contec_pci_driver); +} + +static void __exit driver_contec_cleanup_module(void) +{ + pci_unregister_driver(&driver_contec_pci_driver); + comedi_driver_unregister(&driver_contec); +} + +module_init(driver_contec_init_module); +module_exit(driver_contec_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 83cde27ab725..6af6c8323d56 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -887,7 +887,45 @@ static int daqboard2000_detach(struct comedi_device *dev) return 0; } -COMEDI_PCI_INITCLEANUP(driver_daqboard2000, daqboard2000_pci_table); +static int __devinit driver_daqboard2000_pci_probe(struct pci_dev *dev, + const struct pci_device_id + *ent) +{ + return comedi_pci_auto_config(dev, driver_daqboard2000.driver_name); +} + +static void __devexit driver_daqboard2000_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_daqboard2000_pci_driver = { + .id_table = daqboard2000_pci_table, + .probe = &driver_daqboard2000_pci_probe, + .remove = __devexit_p(&driver_daqboard2000_pci_remove) +}; + +static int __init driver_daqboard2000_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_daqboard2000); + if (retval < 0) + return retval; + + driver_daqboard2000_pci_driver.name = + (char *)driver_daqboard2000.driver_name; + return pci_register_driver(&driver_daqboard2000_pci_driver); +} + +static void __exit driver_daqboard2000_cleanup_module(void) +{ + pci_unregister_driver(&driver_daqboard2000_pci_driver); + comedi_driver_unregister(&driver_daqboard2000); +} + +module_init(driver_daqboard2000_init_module); +module_exit(driver_daqboard2000_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c3f1fedc6eb7..7e7b1a7d3fe5 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1082,7 +1082,43 @@ int das08_common_detach(struct comedi_device *dev) EXPORT_SYMBOL_GPL(das08_common_detach); #ifdef CONFIG_COMEDI_PCI -COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table); +static int __devinit driver_das08_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_das08.driver_name); +} + +static void __devexit driver_das08_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_das08_pci_driver = { + .id_table = das08_pci_table, + .probe = &driver_das08_pci_probe, + .remove = __devexit_p(&driver_das08_pci_remove) +}; + +static int __init driver_das08_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_das08); + if (retval < 0) + return retval; + + driver_das08_pci_driver.name = (char *)driver_das08.driver_name; + return pci_register_driver(&driver_das08_pci_driver); +} + +static void __exit driver_das08_cleanup_module(void) +{ + pci_unregister_driver(&driver_das08_pci_driver); + comedi_driver_unregister(&driver_das08); +} + +module_init(driver_das08_init_module); +module_exit(driver_das08_cleanup_module); #else static int __init driver_das08_init_module(void) { diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 79ea24d2ce5a..656e7bbf2fcb 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -287,7 +287,43 @@ static struct comedi_driver driver_dt3000 = { .detach = dt3000_detach, }; -COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table); +static int __devinit driver_dt3000_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_dt3000.driver_name); +} + +static void __devexit driver_dt3000_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_dt3000_pci_driver = { + .id_table = dt3k_pci_table, + .probe = &driver_dt3000_pci_probe, + .remove = __devexit_p(&driver_dt3000_pci_remove) +}; + +static int __init driver_dt3000_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_dt3000); + if (retval < 0) + return retval; + + driver_dt3000_pci_driver.name = (char *)driver_dt3000.driver_name; + return pci_register_driver(&driver_dt3000_pci_driver); +} + +static void __exit driver_dt3000_cleanup_module(void) +{ + pci_unregister_driver(&driver_dt3000_pci_driver); + comedi_driver_unregister(&driver_dt3000); +} + +module_init(driver_dt3000_init_module); +module_exit(driver_dt3000_cleanup_module); static void dt3k_ai_empty_fifo(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index a24d0994a195..1661b57ca2ad 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -345,7 +345,43 @@ static struct comedi_driver driver_hpdi = { .detach = hpdi_detach, }; -COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table); +static int __devinit driver_hpdi_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_hpdi.driver_name); +} + +static void __devexit driver_hpdi_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_hpdi_pci_driver = { + .id_table = hpdi_pci_table, + .probe = &driver_hpdi_pci_probe, + .remove = __devexit_p(&driver_hpdi_pci_remove) +}; + +static int __init driver_hpdi_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_hpdi); + if (retval < 0) + return retval; + + driver_hpdi_pci_driver.name = (char *)driver_hpdi.driver_name; + return pci_register_driver(&driver_hpdi_pci_driver); +} + +static void __exit driver_hpdi_cleanup_module(void) +{ + pci_unregister_driver(&driver_hpdi_pci_driver); + comedi_driver_unregister(&driver_hpdi); +} + +module_init(driver_hpdi_init_module); +module_exit(driver_hpdi_cleanup_module); static int dio_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 35a789226997..788a01b11d28 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -987,7 +987,43 @@ static int jr3_pci_detach(struct comedi_device *dev) return 0; } -COMEDI_PCI_INITCLEANUP(driver_jr3_pci, jr3_pci_pci_table); +static int __devinit driver_jr3_pci_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_jr3_pci.driver_name); +} + +static void __devexit driver_jr3_pci_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_jr3_pci_pci_driver = { + .id_table = jr3_pci_pci_table, + .probe = &driver_jr3_pci_pci_probe, + .remove = __devexit_p(&driver_jr3_pci_pci_remove) +}; + +static int __init driver_jr3_pci_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_jr3_pci); + if (retval < 0) + return retval; + + driver_jr3_pci_pci_driver.name = (char *)driver_jr3_pci.driver_name; + return pci_register_driver(&driver_jr3_pci_pci_driver); +} + +static void __exit driver_jr3_pci_cleanup_module(void) +{ + pci_unregister_driver(&driver_jr3_pci_pci_driver); + comedi_driver_unregister(&driver_jr3_pci); +} + +module_init(driver_jr3_pci_init_module); +module_exit(driver_jr3_pci_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 35d9869884db..e30aa0123692 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -96,7 +96,43 @@ static struct comedi_driver cnt_driver = { .detach = cnt_detach, }; -COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table); +static int __devinit cnt_driver_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, cnt_driver.driver_name); +} + +static void __devexit cnt_driver_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver cnt_driver_pci_driver = { + .id_table = cnt_pci_table, + .probe = &cnt_driver_pci_probe, + .remove = __devexit_p(&cnt_driver_pci_remove) +}; + +static int __init cnt_driver_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&cnt_driver); + if (retval < 0) + return retval; + + cnt_driver_pci_driver.name = (char *)cnt_driver.driver_name; + return pci_register_driver(&cnt_driver_pci_driver); +} + +static void __exit cnt_driver_cleanup_module(void) +{ + pci_unregister_driver(&cnt_driver_pci_driver); + comedi_driver_unregister(&cnt_driver); +} + +module_init(cnt_driver_init_module); +module_exit(cnt_driver_cleanup_module); /*-- counter write ----------------------------------------------------------*/ diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 58df32676e41..29e04819769e 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2383,7 +2383,43 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, return 1; } -COMEDI_PCI_INITCLEANUP(driver_me4000, me4000_pci_table); +static int __devinit driver_me4000_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_me4000.driver_name); +} + +static void __devexit driver_me4000_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_me4000_pci_driver = { + .id_table = me4000_pci_table, + .probe = &driver_me4000_pci_probe, + .remove = __devexit_p(&driver_me4000_pci_remove) +}; + +static int __init driver_me4000_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_me4000); + if (retval < 0) + return retval; + + driver_me4000_pci_driver.name = (char *)driver_me4000.driver_name; + return pci_register_driver(&driver_me4000_pci_driver); +} + +static void __exit driver_me4000_cleanup_module(void) +{ + pci_unregister_driver(&driver_me4000_pci_driver); + comedi_driver_unregister(&driver_me4000); +} + +module_init(driver_me4000_init_module); +module_exit(driver_me4000_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index d03c0f79ce45..579e6a571800 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -257,7 +257,43 @@ static struct comedi_driver me_driver = { .detach = me_detach, }; -COMEDI_PCI_INITCLEANUP(me_driver, me_pci_table); +static int __devinit me_driver_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, me_driver.driver_name); +} + +static void __devexit me_driver_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver me_driver_pci_driver = { + .id_table = me_pci_table, + .probe = &me_driver_pci_probe, + .remove = __devexit_p(&me_driver_pci_remove) +}; + +static int __init me_driver_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&me_driver); + if (retval < 0) + return retval; + + me_driver_pci_driver.name = (char *)me_driver.driver_name; + return pci_register_driver(&me_driver_pci_driver); +} + +static void __exit me_driver_cleanup_module(void) +{ + pci_unregister_driver(&me_driver_pci_driver); + comedi_driver_unregister(&me_driver); +} + +module_init(me_driver_init_module); +module_exit(me_driver_cleanup_module); /* Private data structure */ struct me_private_data { diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 1fc76cc6a28e..14e716e99a5c 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -490,4 +490,40 @@ static int ni6527_find_device(struct comedi_device *dev, int bus, int slot) return -EIO; } -COMEDI_PCI_INITCLEANUP(driver_ni6527, ni6527_pci_table); +static int __devinit driver_ni6527_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_ni6527.driver_name); +} + +static void __devexit driver_ni6527_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_ni6527_pci_driver = { + .id_table = ni6527_pci_table, + .probe = &driver_ni6527_pci_probe, + .remove = __devexit_p(&driver_ni6527_pci_remove) +}; + +static int __init driver_ni6527_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni6527); + if (retval < 0) + return retval; + + driver_ni6527_pci_driver.name = (char *)driver_ni6527.driver_name; + return pci_register_driver(&driver_ni6527_pci_driver); +} + +static void __exit driver_ni6527_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni6527_pci_driver); + comedi_driver_unregister(&driver_ni6527); +} + +module_init(driver_ni6527_init_module); +module_exit(driver_ni6527_cleanup_module); diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index d793f5a4ac98..8b8e2aaf77fb 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -834,4 +834,40 @@ static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot) return -EIO; } -COMEDI_PCI_INITCLEANUP(driver_ni_65xx, ni_65xx_pci_table); +static int __devinit driver_ni_65xx_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_ni_65xx.driver_name); +} + +static void __devexit driver_ni_65xx_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_ni_65xx_pci_driver = { + .id_table = ni_65xx_pci_table, + .probe = &driver_ni_65xx_pci_probe, + .remove = __devexit_p(&driver_ni_65xx_pci_remove) +}; + +static int __init driver_ni_65xx_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni_65xx); + if (retval < 0) + return retval; + + driver_ni_65xx_pci_driver.name = (char *)driver_ni_65xx.driver_name; + return pci_register_driver(&driver_ni_65xx_pci_driver); +} + +static void __exit driver_ni_65xx_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni_65xx_pci_driver); + comedi_driver_unregister(&driver_ni_65xx); +} + +module_init(driver_ni_65xx_init_module); +module_exit(driver_ni_65xx_cleanup_module); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6a6fae53ea0b..523cb2973373 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -471,7 +471,43 @@ static struct comedi_driver driver_ni_660x = { .detach = ni_660x_detach, }; -COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table); +static int __devinit driver_ni_660x_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_ni_660x.driver_name); +} + +static void __devexit driver_ni_660x_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_ni_660x_pci_driver = { + .id_table = ni_660x_pci_table, + .probe = &driver_ni_660x_pci_probe, + .remove = __devexit_p(&driver_ni_660x_pci_remove) +}; + +static int __init driver_ni_660x_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni_660x); + if (retval < 0) + return retval; + + driver_ni_660x_pci_driver.name = (char *)driver_ni_660x.driver_name; + return pci_register_driver(&driver_ni_660x_pci_driver); +} + +static void __exit driver_ni_660x_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni_660x_pci_driver); + comedi_driver_unregister(&driver_ni_660x); +} + +module_init(driver_ni_660x_init_module); +module_exit(driver_ni_660x_cleanup_module); static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot); static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 44ae8368454d..e9f034efdc6f 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -120,7 +120,43 @@ static struct comedi_driver driver_ni_670x = { .detach = ni_670x_detach, }; -COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table); +static int __devinit driver_ni_670x_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_ni_670x.driver_name); +} + +static void __devexit driver_ni_670x_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_ni_670x_pci_driver = { + .id_table = ni_670x_pci_table, + .probe = &driver_ni_670x_pci_probe, + .remove = __devexit_p(&driver_ni_670x_pci_remove) +}; + +static int __init driver_ni_670x_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_ni_670x); + if (retval < 0) + return retval; + + driver_ni_670x_pci_driver.name = (char *)driver_ni_670x.driver_name; + return pci_register_driver(&driver_ni_670x_pci_driver); +} + +static void __exit driver_ni_670x_cleanup_module(void) +{ + pci_unregister_driver(&driver_ni_670x_pci_driver); + comedi_driver_unregister(&driver_ni_670x); +} + +module_init(driver_ni_670x_init_module); +module_exit(driver_ni_670x_cleanup_module); static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 383ee1024ad3..170bab60555a 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -2078,7 +2078,43 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, } #ifdef CONFIG_COMEDI_PCI -COMEDI_PCI_INITCLEANUP(driver_labpc, labpc_pci_table); +static int __devinit driver_labpc_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_labpc.driver_name); +} + +static void __devexit driver_labpc_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_labpc_pci_driver = { + .id_table = labpc_pci_table, + .probe = &driver_labpc_pci_probe, + .remove = __devexit_p(&driver_labpc_pci_remove) +}; + +static int __init driver_labpc_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_labpc); + if (retval < 0) + return retval; + + driver_labpc_pci_driver.name = (char *)driver_labpc.driver_name; + return pci_register_driver(&driver_labpc_pci_driver); +} + +static void __exit driver_labpc_cleanup_module(void) +{ + pci_unregister_driver(&driver_labpc_pci_driver); + comedi_driver_unregister(&driver_labpc); +} + +module_init(driver_labpc_init_module); +module_exit(driver_labpc_cleanup_module); #else static int __init driver_labpc_init_module(void) { diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b126638d33b2..84a15c34e484 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1317,4 +1317,40 @@ static int nidio_find_device(struct comedi_device *dev, int bus, int slot) return -EIO; } -COMEDI_PCI_INITCLEANUP(driver_pcidio, ni_pcidio_pci_table); +static int __devinit driver_pcidio_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pcidio.driver_name); +} + +static void __devexit driver_pcidio_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pcidio_pci_driver = { + .id_table = ni_pcidio_pci_table, + .probe = &driver_pcidio_pci_probe, + .remove = __devexit_p(&driver_pcidio_pci_remove) +}; + +static int __init driver_pcidio_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pcidio); + if (retval < 0) + return retval; + + driver_pcidio_pci_driver.name = (char *)driver_pcidio.driver_name; + return pci_register_driver(&driver_pcidio_pci_driver); +} + +static void __exit driver_pcidio_cleanup_module(void) +{ + pci_unregister_driver(&driver_pcidio_pci_driver); + comedi_driver_unregister(&driver_pcidio); +} + +module_init(driver_pcidio_init_module); +module_exit(driver_pcidio_cleanup_module); diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 577fda84190d..23a381247285 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1239,7 +1239,43 @@ static struct comedi_driver driver_pcimio = { .detach = pcimio_detach, }; -COMEDI_PCI_INITCLEANUP(driver_pcimio, ni_pci_table) +static int __devinit driver_pcimio_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_pcimio.driver_name); +} + +static void __devexit driver_pcimio_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_pcimio_pci_driver = { + .id_table = ni_pci_table, + .probe = &driver_pcimio_pci_probe, + .remove = __devexit_p(&driver_pcimio_pci_remove) +}; + +static int __init driver_pcimio_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_pcimio); + if (retval < 0) + return retval; + + driver_pcimio_pci_driver.name = (char *)driver_pcimio.driver_name; + return pci_register_driver(&driver_pcimio_pci_driver); +} + +static void __exit driver_pcimio_cleanup_module(void) +{ + pci_unregister_driver(&driver_pcimio_pci_driver); + comedi_driver_unregister(&driver_pcimio); +} + +module_init(driver_pcimio_init_module); +module_exit(driver_pcimio_cleanup_module); struct ni_private { NI_PRIVATE_COMMON}; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 1ca92f949362..0367d2b9e2fa 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -2356,7 +2356,43 @@ static int rtd_dio_insn_config(struct comedi_device *dev, * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */ -COMEDI_PCI_INITCLEANUP(rtd520Driver, rtd520_pci_table); +static int __devinit rtd520Driver_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, rtd520Driver.driver_name); +} + +static void __devexit rtd520Driver_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver rtd520Driver_pci_driver = { + .id_table = rtd520_pci_table, + .probe = &rtd520Driver_pci_probe, + .remove = __devexit_p(&rtd520Driver_pci_remove) +}; + +static int __init rtd520Driver_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&rtd520Driver); + if (retval < 0) + return retval; + + rtd520Driver_pci_driver.name = (char *)rtd520Driver.driver_name; + return pci_register_driver(&rtd520Driver_pci_driver); +} + +static void __exit rtd520Driver_cleanup_module(void) +{ + pci_unregister_driver(&rtd520Driver_pci_driver); + comedi_driver_unregister(&rtd520Driver); +} + +module_init(rtd520Driver_init_module); +module_exit(rtd520Driver_cleanup_module); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index febb62e86ec3..f775ee6171ab 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -224,7 +224,43 @@ static struct dio_private *dio_private_word[]={ #define devpriv ((struct s626_private *)dev->private) #define diopriv ((struct dio_private *)s->private) -COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table); +static int __devinit driver_s626_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_s626.driver_name); +} + +static void __devexit driver_s626_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_s626_pci_driver = { + .id_table = s626_pci_table, + .probe = &driver_s626_pci_probe, + .remove = __devexit_p(&driver_s626_pci_remove) +}; + +static int __init driver_s626_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_s626); + if (retval < 0) + return retval; + + driver_s626_pci_driver.name = (char *)driver_s626.driver_name; + return pci_register_driver(&driver_s626_pci_driver); +} + +static void __exit driver_s626_cleanup_module(void) +{ + pci_unregister_driver(&driver_s626_pci_driver); + comedi_driver_unregister(&driver_s626); +} + +module_init(driver_s626_init_module); +module_exit(driver_s626_cleanup_module); /* ioctl routines */ static int s626_ai_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index d1d5437c5995..732a323ab710 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -620,6 +620,45 @@ static int skel_dio_insn_config(struct comedi_device *dev, return insn->n; } +#ifdef CONFIG_COMEDI_PCI +static int __devinit driver_skel_pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + return comedi_pci_auto_config(dev, driver_skel.driver_name); +} + +static void __devexit driver_skel_pci_remove(struct pci_dev *dev) +{ + comedi_pci_auto_unconfig(dev); +} + +static struct pci_driver driver_skel_pci_driver = { + .id_table = skel_pci_table, + .probe = &driver_skel_pci_probe, + .remove = __devexit_p(&driver_skel_pci_remove) +}; + +static int __init driver_skel_init_module(void) +{ + int retval; + + retval = comedi_driver_register(&driver_skel); + if (retval < 0) + return retval; + + driver_skel_pci_driver.name = (char *)driver_skel.driver_name; + return pci_register_driver(&driver_skel_pci_driver); +} + +static void __exit driver_skel_cleanup_module(void) +{ + pci_unregister_driver(&driver_skel_pci_driver); + comedi_driver_unregister(&driver_skel); +} + +module_init(driver_skel_init_module); +module_exit(driver_skel_cleanup_module); +#else static int __init driver_skel_init_module(void) { return comedi_driver_register(&driver_skel); @@ -632,10 +671,7 @@ static void __exit driver_skel_cleanup_module(void) module_init(driver_skel_init_module); module_exit(driver_skel_cleanup_module); -/* If you are writing a PCI driver you should use COMEDI_PCI_INITCLEANUP - * instead. - */ -/* COMEDI_PCI_INITCLEANUP(driver_skel, skel_pci_table) */ +#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); -- cgit v1.2.3 From 56b8421ceef7f2dae95b882034ebf6958bad58f6 Mon Sep 17 00:00:00 2001 From: Arun Thomas Date: Thu, 10 Jun 2010 23:38:29 +0200 Subject: Staging: comedi: Remove typedefs Remove all remaining typedefs from comedi drivers Signed-off-by: Arun Thomas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/TODO | 1 - drivers/staging/comedi/drivers/addi-data/addi_eeprom.c | 10 +++++----- drivers/staging/comedi/drivers/jr3_pci.c | 7 ++----- drivers/staging/comedi/drivers/pcmmio.c | 17 ++++++++++++----- drivers/staging/comedi/drivers/s626.h | 9 --------- 5 files changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO index 15c9348fb938..b10f739b7e3e 100644 --- a/drivers/staging/comedi/TODO +++ b/drivers/staging/comedi/TODO @@ -2,7 +2,6 @@ TODO: - checkpatch.pl cleanups - Lindent - remove all wrappers - - remove typedefs - audit userspace interface - reserve major number - cleanup the individual comedi drivers as well diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c index bea329f44d80..8fef6f4ea6a0 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c @@ -101,10 +101,10 @@ struct str_TimerMainHeader { }; -typedef struct { +struct str_AnalogOutputHeader { unsigned short w_Nchannel; unsigned char b_Resolution; -} str_AnalogOutputHeader; +}; struct str_AnalogInputHeader { unsigned short w_Nchannel; @@ -136,7 +136,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation, unsigned short w_Address, - str_AnalogOutputHeader *s_Header); + struct str_AnalogOutputHeader *s_Header); int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation, unsigned short w_Address, @@ -811,7 +811,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress, struct str_DigitalInputHeader s_DigitalInputHeader; struct str_DigitalOutputHeader s_DigitalOutputHeader; /* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */ - str_AnalogOutputHeader s_AnalogOutputHeader; + struct str_AnalogOutputHeader s_AnalogOutputHeader; struct str_AnalogInputHeader s_AnalogInputHeader; /* Read size */ @@ -1081,7 +1081,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation, unsigned short w_Address, - str_AnalogOutputHeader *s_Header) + struct str_AnalogOutputHeader *s_Header) { unsigned short w_Temp; /* No of channels for 1st hard component */ diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 788a01b11d28..ba900a80a470 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -123,12 +123,9 @@ struct jr3_pci_subdev_private { }; /* Hotplug firmware loading stuff */ - -typedef int comedi_firmware_callback(struct comedi_device *dev, - const u8 * data, size_t size); - static int comedi_load_firmware(struct comedi_device *dev, char *name, - comedi_firmware_callback cb) + int (*cb)(struct comedi_device *dev, + const u8 *data, size_t size)) { int result = 0; const struct firmware *fw; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index f0df9d1e4fec..5c832d7ed45d 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -145,10 +145,6 @@ Configuration Options: #define PAGE_ENAB 2 #define PAGE_INT_ID 3 -typedef int (*comedi_insn_fn_t) (struct comedi_device *, - struct comedi_subdevice *, - struct comedi_insn *, unsigned int *); - static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, unsigned int *); static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, @@ -171,7 +167,18 @@ struct pcmmio_board { const int n_ai_chans; const int n_ao_chans; const struct comedi_lrange *ai_range_table, *ao_range_table; - comedi_insn_fn_t ai_rinsn, ao_rinsn, ao_winsn; + int (*ai_rinsn) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*ao_rinsn) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*ao_winsn) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); }; static const struct comedi_lrange ranges_ai = { diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index d02742a95294..2d1afecbbb60 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -720,15 +720,6 @@ #define STDMSK_CLKMULT ((uint16_t)(3 << STDBIT_CLKMULT)) #define STDMSK_CLKENAB ((uint16_t)(1 << STDBIT_CLKENAB)) -/* typedef struct indexCounter */ -/* { */ -/* unsigned int ao; */ -/* unsigned int ai; */ -/* unsigned int digout; */ -/* unsigned int digin; */ -/* unsigned int enc; */ -/* }CallCounter; */ - struct bufferDMA { dma_addr_t PhysicalBase; void *LogicalBase; -- cgit v1.2.3 From b6241fda0a25062cecc88cefd43658460cfe26a4 Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Sat, 12 Jun 2010 16:39:18 -0500 Subject: Staging: comedi: drivers: fix coding style issues in me4000.c This is a patch to the me4000.c file that fixes up the following issues: ERROR: space required after that close brace '}' x 13 ERROR: spaces required around that ':' (ctx:VxV) x 3 WARNING: line over 80 characters x 96 WARNING: braces {} are not necessary for any arm of this statement x 2 Signed-off-by: Gustavo Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 416 +++++++++++++++++--------------- 1 file changed, 227 insertions(+), 189 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 29e04819769e..56c9279c700e 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -91,22 +91,22 @@ static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = { MODULE_DEVICE_TABLE(pci, me4000_pci_table); static const struct me4000_board me4000_boards[] = { - {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}}, + {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} }, - {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}}, - {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3}}, - {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3}}, - {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3}}, + {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} }, + {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} }, + {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} }, + {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} }, - {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}}, - {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}}, - {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}}, - {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}}, + {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} }, + {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} }, - {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}}, - {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}}, - {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}}, - {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}}, + {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} }, + {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} }, + {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} }, {0}, }; @@ -120,10 +120,10 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it); static int me4000_detach(struct comedi_device *dev); static struct comedi_driver driver_me4000 = { -driver_name:"me4000", -module:THIS_MODULE, -attach:me4000_attach, -detach:me4000_detach, +driver_name: "me4000", +module : THIS_MODULE, +attach : me4000_attach, +detach : me4000_detach, }; /*----------------------------------------------------------------------------- @@ -302,8 +302,8 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (request_irq(info->irq, me4000_ai_isr, IRQF_SHARED, "ME-4000", dev)) { printk - ("comedi%d: me4000: me4000_attach(): Unable to allocate irq\n", - dev->minor); + ("comedi%d: me4000: me4000_attach(): " + "Unable to allocate irq\n", dev->minor); } else { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; @@ -313,8 +313,8 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } else { printk(KERN_WARNING - "comedi%d: me4000: me4000_attach(): No interrupt available\n", - dev->minor); + "comedi%d: me4000: me4000_attach(): " + "No interrupt available\n", dev->minor); } } else { s->type = COMEDI_SUBD_UNUSED; @@ -409,10 +409,16 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it) for (i = 0; i < ME4000_BOARD_VERSIONS; i++) { if (me4000_boards[i].device_id == pci_device->device) { - /* Was a particular bus/slot requested? */ + /* + * Was a particular + * bus/slot requested? + */ if ((it->options[0] != 0) || (it->options[1] != 0)) { - /* Are we on the wrong bus/slot? */ + /* + * Are we on the wrong + * bus/slot? + */ if (pci_device->bus->number != it->options[0] || @@ -433,14 +439,16 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it) } printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): No supported board found (req. bus/slot : %d/%d)\n", + "comedi%d: me4000: me4000_probe(): " + "No supported board found (req. bus/slot : %d/%d)\n", dev->minor, it->options[0], it->options[1]); return -ENODEV; found: printk(KERN_INFO - "comedi%d: me4000: me4000_probe(): Found %s at PCI bus %d, slot %d\n", + "comedi%d: me4000: me4000_probe(): " + "Found %s at PCI bus %d, slot %d\n", dev->minor, me4000_boards[i].name, pci_device->bus->number, PCI_SLOT(pci_device->devfn)); @@ -451,8 +459,8 @@ found: result = comedi_pci_enable(pci_device, dev->board_name); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot enable PCI device and request I/O regions\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): Cannot enable PCI " + "device and request I/O regions\n", dev->minor); return result; } @@ -460,16 +468,16 @@ found: result = get_registers(dev, pci_device); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot get registers\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot get registers\n", dev->minor); return result; } /* Initialize board info */ result = init_board_info(dev, pci_device); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot init baord info\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot init baord info\n", dev->minor); return result; } @@ -477,8 +485,8 @@ found: result = init_ao_context(dev); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot init ao context\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot init ao context\n", dev->minor); return result; } @@ -486,8 +494,8 @@ found: result = init_ai_context(dev); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot init ai context\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot init ai context\n", dev->minor); return result; } @@ -495,8 +503,8 @@ found: result = init_dio_context(dev); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot init dio context\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot init dio context\n", dev->minor); return result; } @@ -504,8 +512,8 @@ found: result = init_cnt_context(dev); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Cannot init cnt context\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Cannot init cnt context\n", dev->minor); return result; } @@ -513,8 +521,8 @@ found: result = xilinx_download(dev); if (result) { printk(KERN_ERR - "comedi%d: me4000: me4000_probe(): Can't download firmware\n", - dev->minor); + "comedi%d: me4000: me4000_probe(): " + "Can't download firmware\n", dev->minor); return result; } @@ -535,24 +543,24 @@ static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p) CALL_PDEBUG("In get_registers()\n"); - /*--------------------------- plx regbase ---------------------------------*/ + /*--------------------------- plx regbase -------------------------------*/ info->plx_regbase = pci_resource_start(pci_dev_p, 1); if (info->plx_regbase == 0) { printk(KERN_ERR - "comedi%d: me4000: get_registers(): PCI base address 1 is not available\n", - dev->minor); + "comedi%d: me4000: get_registers(): " + "PCI base address 1 is not available\n", dev->minor); return -ENODEV; } info->plx_regbase_size = pci_resource_len(pci_dev_p, 1); - /*--------------------------- me4000 regbase ------------------------------*/ + /*--------------------------- me4000 regbase ----------------------------*/ info->me4000_regbase = pci_resource_start(pci_dev_p, 2); if (info->me4000_regbase == 0) { printk(KERN_ERR - "comedi%d: me4000: get_registers(): PCI base address 2 is not available\n", - dev->minor); + "comedi%d: me4000: get_registers(): " + "PCI base address 2 is not available\n", dev->minor); return -ENODEV; } info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2); @@ -562,19 +570,19 @@ static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p) info->timer_regbase = pci_resource_start(pci_dev_p, 3); if (info->timer_regbase == 0) { printk(KERN_ERR - "comedi%d: me4000: get_registers(): PCI base address 3 is not available\n", - dev->minor); + "comedi%d: me4000: get_registers(): " + "PCI base address 3 is not available\n", dev->minor); return -ENODEV; } info->timer_regbase_size = pci_resource_len(pci_dev_p, 3); - /*--------------------------- program regbase ------------------------------*/ + /*--------------------------- program regbase ----------------------------*/ info->program_regbase = pci_resource_start(pci_dev_p, 5); if (info->program_regbase == 0) { printk(KERN_ERR - "comedi%d: me4000: get_registers(): PCI base address 5 is not available\n", - dev->minor); + "comedi%d: me4000: get_registers(): " + "PCI base address 5 is not available\n", dev->minor); return -ENODEV; } info->program_regbase_size = pci_resource_len(pci_dev_p, 5); @@ -800,8 +808,8 @@ static int xilinx_download(struct comedi_device *dev) udelay(20); if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) { printk(KERN_ERR - "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n", - dev->minor); + "comedi%d: me4000: xilinx_download(): " + "Can't init Xilinx\n", dev->minor); return -EIO; } @@ -810,8 +818,8 @@ static int xilinx_download(struct comedi_device *dev) value &= ~0x100; outl(value, info->plx_regbase + PLX_ICR); if (FIRMWARE_NOT_AVAILABLE) { - comedi_error(dev, - "xilinx firmware unavailable due to licensing, aborting"); + comedi_error(dev, "xilinx firmware unavailable " + "due to licensing, aborting"); return -EIO; } else { /* Download Xilinx firmware */ @@ -826,7 +834,8 @@ static int xilinx_download(struct comedi_device *dev) /* Check if BUSY flag is low */ if (inl(info->plx_regbase + PLX_ICR) & 0x20) { printk(KERN_ERR - "comedi%d: me4000: xilinx_download(): Xilinx is still busy (idx = %d)\n", + "comedi%d: me4000: xilinx_download(): " + "Xilinx is still busy (idx = %d)\n", dev->minor, idx); return -EIO; } @@ -837,11 +846,11 @@ static int xilinx_download(struct comedi_device *dev) if (inl(info->plx_regbase + PLX_ICR) & 0x4) { } else { printk(KERN_ERR - "comedi%d: me4000: xilinx_download(): DONE flag is not set\n", - dev->minor); + "comedi%d: me4000: xilinx_download(): " + "DONE flag is not set\n", dev->minor); printk(KERN_ERR - "comedi%d: me4000: xilinx_download(): Download not successful\n", - dev->minor); + "comedi%d: me4000: xilinx_download(): " + "Download not successful\n", dev->minor); return -EIO; } @@ -902,7 +911,10 @@ static int reset_board(struct comedi_device *dev) me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE, info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG); - /* Set digital I/O direction for port 0 to output on isolated versions */ + /* + * Set digital I/O direction for port 0 + * to output on isolated versions + */ if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) { me4000_outl(dev, 0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG); @@ -950,8 +962,8 @@ static int me4000_ai_insn_read(struct comedi_device *dev, return 0; } else if (insn->n > 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Invalid instruction length %d\n", - dev->minor, insn->n); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } @@ -970,8 +982,8 @@ static int me4000_ai_insn_read(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Invalid range specified\n", - dev->minor); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid range specified\n", dev->minor); return -EINVAL; } @@ -980,8 +992,8 @@ static int me4000_ai_insn_read(struct comedi_device *dev, case AREF_COMMON: if (chan >= thisboard->ai.count) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n", - dev->minor); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Analog input is not available\n", dev->minor); return -EINVAL; } entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan; @@ -990,23 +1002,24 @@ static int me4000_ai_insn_read(struct comedi_device *dev, case AREF_DIFF: if (rang == 0 || rang == 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Range must be bipolar when aref = diff\n", + "comedi%d: me4000: me4000_ai_insn_read(): " + "Range must be bipolar when aref = diff\n", dev->minor); return -EINVAL; } if (chan >= thisboard->ai.diff_count) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n", - dev->minor); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Analog input is not available\n", dev->minor); return -EINVAL; } entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan; break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Invalid aref specified\n", - dev->minor); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Invalid aref specified\n", dev->minor); return -EINVAL; } @@ -1045,8 +1058,8 @@ static int me4000_ai_insn_read(struct comedi_device *dev, (me4000_inl(dev, info->ai_context.status_reg) & ME4000_AI_STATUS_BIT_EF_DATA)) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_insn_read(): Value not available after wait\n", - dev->minor); + "comedi%d: me4000: me4000_ai_insn_read(): " + "Value not available after wait\n", dev->minor); return -EIO; } @@ -1086,24 +1099,24 @@ static int ai_check_chanlist(struct comedi_device *dev, /* Check whether a channel list is available */ if (!cmd->chanlist_len) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): No channel list available\n", - dev->minor); + "comedi%d: me4000: ai_check_chanlist(): " + "No channel list available\n", dev->minor); return -EINVAL; } /* Check the channel list size */ if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): Channel list is to large\n", - dev->minor); + "comedi%d: me4000: ai_check_chanlist(): " + "Channel list is to large\n", dev->minor); return -EINVAL; } /* Check the pointer */ if (!cmd->chanlist) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): NULL pointer to channel list\n", - dev->minor); + "comedi%d: me4000: ai_check_chanlist(): " + "NULL pointer to channel list\n", dev->minor); return -EFAULT; } @@ -1112,7 +1125,8 @@ static int ai_check_chanlist(struct comedi_device *dev, for (i = 0; i < cmd->chanlist_len; i++) { if (CR_AREF(cmd->chanlist[i]) != aref) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): Mode is not equal for all entries\n", + "comedi%d: me4000: ai_check_chanlist(): " + "Mode is not equal for all entries\n", dev->minor); return -EINVAL; } @@ -1124,8 +1138,8 @@ static int ai_check_chanlist(struct comedi_device *dev, if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.diff_count) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n", - dev->minor); + "comedi%d: me4000: ai_check_chanlist():" + " Channel number to high\n", dev->minor); return -EINVAL; } } @@ -1133,8 +1147,8 @@ static int ai_check_chanlist(struct comedi_device *dev, for (i = 0; i < cmd->chanlist_len; i++) { if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n", - dev->minor); + "comedi%d: me4000: ai_check_chanlist(): " + "Channel number to high\n", dev->minor); return -EINVAL; } } @@ -1146,7 +1160,9 @@ static int ai_check_chanlist(struct comedi_device *dev, if (CR_RANGE(cmd->chanlist[i]) != 1 && CR_RANGE(cmd->chanlist[i]) != 2) { printk(KERN_ERR - "comedi%d: me4000: ai_check_chanlist(): Bipolar is not selected in differential mode\n", + "comedi%d: me4000: ai_check_chanlist(): " + "Bipolar is not selected in " + "differential mode\n", dev->minor); return -EINVAL; } @@ -1330,21 +1346,19 @@ static int ai_write_chanlist(struct comedi_device *dev, entry = chan; - if (rang == 0) { + if (rang == 0) entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - } else if (rang == 1) { + else if (rang == 1) entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - } else if (rang == 2) { + else if (rang == 2) entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - } else { + else entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; - } - if (aref == SDF_DIFF) { + if (aref == SDF_DIFF) entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; - } else { + else entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; - } me4000_outl(dev, entry, info->ai_context.channel_list_reg); } @@ -1454,8 +1468,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start source\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start source\n", dev->minor); cmd->start_src = TRIG_NOW; err++; } @@ -1470,8 +1484,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan begin source\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan begin source\n", dev->minor); cmd->scan_begin_src = TRIG_FOLLOW; err++; } @@ -1485,8 +1499,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert source\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert source\n", dev->minor); cmd->convert_src = TRIG_TIMER; err++; } @@ -1500,8 +1514,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end source\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end source\n", dev->minor); cmd->scan_end_src = TRIG_NONE; err++; } @@ -1515,8 +1529,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop source\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop source\n", dev->minor); cmd->stop_src = TRIG_NONE; err++; } @@ -1546,8 +1560,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->convert_src == TRIG_EXT) { } else { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start trigger combination\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start trigger combination\n", dev->minor); cmd->start_src = TRIG_NOW; cmd->scan_begin_src = TRIG_FOLLOW; cmd->convert_src = TRIG_TIMER; @@ -1563,8 +1577,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_end_src == TRIG_COUNT) { } else { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop trigger combination\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop trigger combination\n", dev->minor); cmd->stop_src = TRIG_NONE; cmd->scan_end_src = TRIG_NONE; err++; @@ -1577,29 +1591,29 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, */ if (cmd->chanlist_len < 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): No channel list\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "No channel list\n", dev->minor); cmd->chanlist_len = 1; err++; } if (init_ticks < 66) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Start arg to low\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Start arg to low\n", dev->minor); cmd->start_arg = 2000; err++; } if (scan_ticks && scan_ticks < 67) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Scan begin arg to low\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Scan begin arg to low\n", dev->minor); cmd->scan_begin_arg = 2031; err++; } if (chan_ticks < 66) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Convert arg to low\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Convert arg to low\n", dev->minor); cmd->convert_arg = 2000; err++; } @@ -1617,23 +1631,25 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n", - dev->minor); - cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */ + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); + + /* At least one tick more */ + cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; err++; } } else if (cmd->start_src == TRIG_NOW && @@ -1643,15 +1659,15 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1662,23 +1678,25 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n", - dev->minor); - cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */ + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); + + /* At least one tick more */ + cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; err++; } } else if (cmd->start_src == TRIG_EXT && @@ -1688,15 +1706,15 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1707,15 +1725,15 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid convert arg\n", dev->minor); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } @@ -1726,8 +1744,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, /* Check timer arguments */ if (init_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid start arg\n", dev->minor); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } @@ -1735,8 +1753,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT) { if (cmd->stop_arg == 0) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid stop arg\n", dev->minor); cmd->stop_arg = 1; err++; } @@ -1744,8 +1762,8 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, if (cmd->scan_end_src == TRIG_COUNT) { if (cmd->scan_end_arg == 0) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n", - dev->minor); + "comedi%d: me4000: me4000_ai_do_cmd_test(): " + "Invalid scan end arg\n", dev->minor); cmd->scan_end_arg = 1; err++; } @@ -1786,8 +1804,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) /* Check if irq number is right */ if (irq != ai_context->irq) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): Incorrect interrupt num: %d\n", - dev->minor, irq); + "comedi%d: me4000: me4000_ai_isr(): " + "Incorrect interrupt num: %d\n", dev->minor, irq); return IRQ_HANDLED; } @@ -1806,7 +1824,10 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ISR_PDEBUG("me4000_ai_isr(): Fifo full\n"); c = ME4000_AI_FIFO_COUNT; - /* FIFO overflow, so stop conversion and disable all interrupts */ + /* + * FIFO overflow, so stop conversion + * and disable all interrupts + */ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); @@ -1815,8 +1836,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): FIFO overflow\n", - dev->minor); + "comedi%d: me4000: me4000_ai_isr(): " + "FIFO overflow\n", dev->minor); } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { @@ -1827,11 +1848,14 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) c = ME4000_AI_FIFO_COUNT / 2; } else { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): Can't determine state of fifo\n", - dev->minor); + "comedi%d: me4000: me4000_ai_isr(): " + "Can't determine state of fifo\n", dev->minor); c = 0; - /* Undefined state, so stop conversion and disable all interrupts */ + /* + * Undefined state, so stop conversion + * and disable all interrupts + */ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); @@ -1840,8 +1864,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): Undefined FIFO state\n", - dev->minor); + "comedi%d: me4000: me4000_ai_isr(): " + "Undefined FIFO state\n", dev->minor); } ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c); @@ -1852,7 +1876,10 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) lval ^= 0x8000; if (!comedi_buf_put(s->async, lval)) { - /* Buffer overflow, so stop conversion and disable all interrupts */ + /* + * Buffer overflow, so stop conversion + * and disable all interrupts + */ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); @@ -1861,8 +1888,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) s->async->events |= COMEDI_CB_OVERFLOW; printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n", - dev->minor); + "comedi%d: me4000: me4000_ai_isr(): " + "Buffer overflow\n", dev->minor); break; } @@ -1883,7 +1910,10 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA; - /* Acquisition is complete, so stop conversion and disable all interrupts */ + /* + * Acquisition is complete, so stop + * conversion and disable all interrupts + */ tmp = me4000_inl(dev, ai_context->ctrl_reg); tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); @@ -1897,8 +1927,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) if (!comedi_buf_put(s->async, lval)) { printk(KERN_ERR - "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n", - dev->minor); + "comedi%d: me4000: me4000_ai_isr(): " + "Buffer overflow\n", dev->minor); s->async->events |= COMEDI_CB_OVERFLOW; break; } @@ -1941,29 +1971,29 @@ static int me4000_ao_insn_write(struct comedi_device *dev, return 0; } else if (insn->n > 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_ao_insn_write(): Invalid instruction length %d\n", - dev->minor, insn->n); + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } if (chan >= thisboard->ao.count) { printk(KERN_ERR - "comedi%d: me4000: me4000_ao_insn_write(): Invalid channel %d\n", - dev->minor, insn->n); + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid channel %d\n", dev->minor, insn->n); return -EINVAL; } if (rang != 0) { printk(KERN_ERR - "comedi%d: me4000: me4000_ao_insn_write(): Invalid range %d\n", - dev->minor, insn->n); + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid range %d\n", dev->minor, insn->n); return -EINVAL; } if (aref != AREF_GROUND && aref != AREF_COMMON) { printk(KERN_ERR - "comedi%d: me4000: me4000_ao_insn_write(): Invalid aref %d\n", - dev->minor, insn->n); + "comedi%d: me4000: me4000_ao_insn_write(): " + "Invalid aref %d\n", dev->minor, insn->n); return -EINVAL; } @@ -1994,8 +2024,8 @@ static int me4000_ao_insn_read(struct comedi_device *dev, return 0; } else if (insn->n > 1) { printk - ("comedi%d: me4000: me4000_ao_insn_read(): Invalid instruction length\n", - dev->minor); + ("comedi%d: me4000: me4000_ao_insn_read(): " + "Invalid instruction length\n", dev->minor); return -EINVAL; } @@ -2021,8 +2051,8 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, if (insn->n != 2) { printk - ("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", - dev->minor); + ("comedi%d: me4000: me4000_dio_insn_bits(): " + "Invalid instruction length\n", dev->minor); return -EINVAL; } @@ -2095,8 +2125,9 @@ static int me4000_dio_insn_config(struct comedi_device *dev, tmp |= ME4000_DIO_CTRL_BIT_MODE_0; } else if (chan < 16) { /* - * Chech for optoisolated ME-4000 version. If one the first - * port is a fixed output port and the second is a fixed input port. + * Chech for optoisolated ME-4000 version. + * If one the first port is a fixed output + * port and the second is a fixed input port. */ if (!me4000_inl(dev, info->dio_context.dir_reg)) return -ENODEV; @@ -2121,8 +2152,9 @@ static int me4000_dio_insn_config(struct comedi_device *dev, } else { if (chan < 8) { /* - * Chech for optoisolated ME-4000 version. If one the first - * port is a fixed output port and the second is a fixed input port. + * Chech for optoisolated ME-4000 version. + * If one the first port is a fixed output + * port and the second is a fixed input port. */ if (!me4000_inl(dev, info->dio_context.dir_reg)) return -ENODEV; @@ -2257,7 +2289,8 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, case GPCT_RESET: if (insn->n != 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n", + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction length%d\n", dev->minor, insn->n); return -EINVAL; } @@ -2269,7 +2302,8 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, case GPCT_SET_OPERATION: if (insn->n != 2) { printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n", + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction length%d\n", dev->minor, insn->n); return -EINVAL; } @@ -2280,8 +2314,8 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction\n", - dev->minor); + "comedi%d: me4000: me4000_cnt_insn_config(): " + "Invalid instruction\n", dev->minor); return -EINVAL; } @@ -2302,7 +2336,8 @@ static int me4000_cnt_insn_read(struct comedi_device *dev, if (insn->n > 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n", + "comedi%d: me4000: me4000_cnt_insn_read(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } @@ -2328,7 +2363,8 @@ static int me4000_cnt_insn_read(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_read(): Invalid channel %d\n", + "comedi%d: me4000: me4000_cnt_insn_read(): " + "Invalid channel %d\n", dev->minor, insn->chanspec); return -EINVAL; } @@ -2349,7 +2385,8 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, return 0; } else if (insn->n > 1) { printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_write(): Invalid instruction length %d\n", + "comedi%d: me4000: me4000_cnt_insn_write(): " + "Invalid instruction length %d\n", dev->minor, insn->n); return -EINVAL; } @@ -2375,7 +2412,8 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, break; default: printk(KERN_ERR - "comedi%d: me4000: me4000_cnt_insn_write(): Invalid channel %d\n", + "comedi%d: me4000: me4000_cnt_insn_write(): " + "Invalid channel %d\n", dev->minor, insn->chanspec); return -EINVAL; } -- cgit v1.2.3 From 8f4e80af3aa509902bd2319c3b5512580f64868f Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Sat, 12 Jun 2010 19:15:22 -0500 Subject: Staging: comedi: drivers: Fix coding style issues in pcl711.c This is a patch to the pcl711.c file that fixes up printk() warning issues. Signed-off-by: Gustavo Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl711.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 22d14fb3121b..b44386a6b636 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -281,7 +281,7 @@ static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, goto ok; udelay(1); } - printk("comedi%d: pcl711: A/D timeout\n", dev->minor); + printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor); return -ETIME; ok: @@ -516,7 +516,7 @@ static int pcl711_do_insn_bits(struct comedi_device *dev, /* Free any resources that we have claimed */ static int pcl711_detach(struct comedi_device *dev) { - printk("comedi%d: pcl711: remove\n", dev->minor); + printk(KERN_INFO "comedi%d: pcl711: remove\n", dev->minor); if (dev->irq) free_irq(dev->irq, dev); @@ -538,7 +538,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* claim our I/O space */ iobase = it->options[0]; - printk("comedi%d: pcl711: 0x%04lx ", dev->minor, iobase); + printk(KERN_INFO "comedi%d: pcl711: 0x%04lx ", dev->minor, iobase); if (!request_region(iobase, PCL711_SIZE, "pcl711")) { printk("I/O port conflict\n"); return -EIO; @@ -553,15 +553,15 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* grab our IRQ */ irq = it->options[1]; if (irq > this_board->maxirq) { - printk("irq out of range\n"); + printk(KERN_ERR "irq out of range\n"); return -EINVAL; } if (irq) { if (request_irq(irq, pcl711_interrupt, 0, "pcl711", dev)) { - printk("unable to allocate irq %u\n", irq); + printk(KERN_ERR "unable to allocate irq %u\n", irq); return -EINVAL; } else { - printk("( irq = %u )\n", irq); + printk(KERN_INFO "( irq = %u )\n", irq); } } dev->irq = irq; @@ -635,7 +635,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(0, dev->iobase + PCL711_DA1_LO); outb(0, dev->iobase + PCL711_DA1_HI); - printk("\n"); + printk(KERN_INFO "\n"); return 0; } -- cgit v1.2.3 From 4c68fb42c2a39b89daca2b7175eb93ffe6860da4 Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Wed, 16 Jun 2010 00:17:52 -0500 Subject: Staging: comedi: drivers: fix coding style issues in pcl816.c This is a patch to the pcl816.c file that fixes up the following issues: ERROR: code indent should use tabs where possible x 2 WARNING: line over 80 characters x 34 WARNING: please, no space before tabs x 1 WARNING: braces {} are not necessary for single statement blocks x 6 WARNING: printk() should include KERN_ facility level x 15 WARNING: braces {} are not necessary for any arm of this statement x 1 Signed-off-by: Gustavo Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 223 ++++++++++++++++++++------------ 1 file changed, 140 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index a84b942c5a93..3d0f018faa6b 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -2,7 +2,7 @@ comedi/drivers/pcl816.c Author: Juan Grigera - based on pcl818 by Michal Dobes and bits of pcl812 + based on pcl818 by Michal Dobes and bits of pcl812 hardware driver for Advantech cards: card: PCL-816, PCL814B @@ -28,7 +28,7 @@ Configuration Options: [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) [2] - DMA (0=disable, 1, 3) [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 + 1= 1MHz clock for 8254 */ @@ -85,7 +85,7 @@ Configuration Options: #define INT_TYPE_AI3_DMA_RTC 10 /* RTC stuff... */ -#define RTC_IRQ 8 +#define RTC_IRQ 8 #define RTC_IO_EXTENT 0x10 #endif @@ -264,7 +264,8 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, /* Set the input channel */ outb(CR_CHAN(insn->chanspec) & 0xf, dev->iobase + PCL816_MUX); - outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE); /* select gain */ + /* select gain */ + outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE); for (n = 0; n < insn->n; n++) { @@ -279,8 +280,8 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, ((inb(dev->iobase + PCL816_AD_HI) << 8) | (inb(dev->iobase + PCL816_AD_LO))); - - outb(0, dev->iobase + PCL816_CLRINT); /* clear INT (conversion end) flag */ + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL816_CLRINT); break; } udelay(1); @@ -289,7 +290,8 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, if (!timeout) { comedi_error(dev, "A/D insn timeout\n"); data[0] = 0; - outb(0, dev->iobase + PCL816_CLRINT); /* clear INT (conversion end) flag */ + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL816_CLRINT); return -EIO; } @@ -343,7 +345,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) } if (!devpriv->ai_neverending) - if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + /* all data sampled */ + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ pcl816_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA; @@ -380,7 +383,8 @@ static void transfer_from_dma_buf(struct comedi_device *dev, } if (!devpriv->ai_neverending) - if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + /* all data sampled */ + if (devpriv->ai_act_scan >= devpriv->ai_scans) { pcl816_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_BLOCK; @@ -402,7 +406,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) disable_dma(devpriv->dma); this_dma_buf = devpriv->next_dma_buf; - if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) { /* switch dma bufs */ + /* switch dma bufs */ + if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) { devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; set_dma_mode(devpriv->dma, DMA_MODE_READ); @@ -478,14 +483,14 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) */ static void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd) { - printk("pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + printk(KERN_INFO "pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, cmd->start_src, cmd->scan_begin_src, cmd->convert_src); - printk("pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + printk(KERN_INFO "pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e, cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); - printk("pcl816 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, - cmd->scan_end_src); - printk("pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", e, - cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); + printk(KERN_INFO "pcl816 e=%d stopsrc=%x scanend=%x\n", e, + cmd->stop_src, cmd->scan_end_src); + printk(KERN_INFO "pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", + e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); } /* @@ -497,8 +502,9 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp, divisor1 = 0, divisor2 = 0; - DEBUG(printk("pcl816 pcl812_ai_cmdtest\n"); pcl816_cmdtest_out(-1, cmd); - ); + DEBUG(printk(KERN_INFO "pcl816 pcl812_ai_cmdtest\n"); + pcl816_cmdtest_out(-1, cmd); + ); /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; @@ -526,11 +532,14 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, if (!cmd->stop_src || tmp != cmd->stop_src) err++; - if (err) { + if (err) return 1; - } - /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* + * step 2: make sure trigger sources + * are unique and mutually compatible + */ if (cmd->start_src != TRIG_NOW) { cmd->start_src = TRIG_NOW; @@ -555,9 +564,9 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) err++; - if (err) { + if (err) return 2; - } + /* step 3: make sure arguments are trivially compatible */ if (cmd->start_arg != 0) { @@ -597,9 +606,9 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, } } - if (err) { + if (err) return 3; - } + /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { @@ -614,9 +623,9 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, err++; } - if (err) { + if (err) return 4; - } + /* step 5: complain about special chanlist considerations */ @@ -654,7 +663,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, &divisor2, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - if (divisor1 == 1) { /* PCL816 crash if any divisor is set to 1 */ + + /* PCL816 crash if any divisor is set to 1 */ + if (divisor1 == 1) { divisor1 = 2; divisor2 /= 2; } @@ -687,8 +698,10 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_neverending = 1; } - if ((cmd->flags & TRIG_WAKE_EOS)) { /* don't we want wake up every scan? */ - printk("pl816: You wankt WAKE_EOS but I dont want handle it"); + /* don't we want wake up every scan? */ + if ((cmd->flags & TRIG_WAKE_EOS)) { + printk(KERN_INFO + "pl816: You wankt WAKE_EOS but I dont want handle it"); /* devpriv->ai_eos=1; */ /* if (devpriv->ai_n_chan==1) */ /* devpriv->dma=0; // DMA is useless for this situation */ @@ -697,9 +710,17 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (devpriv->dma) { bytes = devpriv->hwdmasize[0]; if (!devpriv->ai_neverending) { - bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(short); /* how many */ - devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fill */ - devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */ + /* how many */ + bytes = s->async->cmd.chanlist_len * + s->async->cmd.chanlist_len * + sizeof(short); + + /* how many DMA pages we must fill */ + devpriv->dma_runs_to_end = bytes / + devpriv->hwdmasize[0]; + + /* on last dma transfer must be moved */ + devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end >= 0) bytes = devpriv->hwdmasize[0]; @@ -722,14 +743,22 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) switch (cmd->convert_src) { case TRIG_TIMER: devpriv->int816_mode = INT_TYPE_AI1_DMA; - outb(0x32, dev->iobase + PCL816_CONTROL); /* Pacer+IRQ+DMA */ - outb(dmairq, dev->iobase + PCL816_STATUS); /* write irq and DMA to card */ + + /* Pacer+IRQ+DMA */ + outb(0x32, dev->iobase + PCL816_CONTROL); + + /* write irq and DMA to card */ + outb(dmairq, dev->iobase + PCL816_STATUS); break; default: devpriv->int816_mode = INT_TYPE_AI3_DMA; - outb(0x34, dev->iobase + PCL816_CONTROL); /* Ext trig+IRQ+DMA */ - outb(dmairq, dev->iobase + PCL816_STATUS); /* write irq to card */ + + /* Ext trig+IRQ+DMA */ + outb(0x34, dev->iobase + PCL816_CONTROL); + + /* write irq to card */ + outb(dmairq, dev->iobase + PCL816_STATUS); break; } @@ -758,7 +787,8 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } - top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */ + /* where is now DMA in buffer */ + top1 = devpriv->hwdmasize[0] - top1; top1 >>= 1; /* sample position */ top2 = top1 - devpriv->ai_poll_ptr; if (top2 < 1) { /* no new samples */ @@ -798,16 +828,23 @@ static int pcl816_ai_cancel(struct comedi_device *dev, disable_dma(devpriv->dma); case INT_TYPE_AI1_INT: case INT_TYPE_AI3_INT: - outb(inb(dev->iobase + PCL816_CONTROL) & 0x73, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + outb(inb(dev->iobase + PCL816_CONTROL) & 0x73, + dev->iobase + PCL816_CONTROL); /* Stop A/D */ udelay(1); outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */ - outb(0xb0, dev->iobase + PCL816_CTRCTL); /* Stop pacer */ + + /* Stop pacer */ + outb(0xb0, dev->iobase + PCL816_CTRCTL); outb(0x70, dev->iobase + PCL816_CTRCTL); outb(0, dev->iobase + PCL816_AD_LO); inb(dev->iobase + PCL816_AD_LO); inb(dev->iobase + PCL816_AD_HI); - outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ - outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + + /* clear INT request */ + outb(0, dev->iobase + PCL816_CLRINT); + + /* Stop A/D */ + outb(0, dev->iobase + PCL816_CONTROL); devpriv->irq_blocked = 0; devpriv->irq_was_now_closed = devpriv->int816_mode; devpriv->int816_mode = 0; @@ -877,8 +914,11 @@ start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, outb(0xff, dev->iobase + PCL816_CTR0); outb(0x00, dev->iobase + PCL816_CTR0); udelay(1); - outb(0xb4, dev->iobase + PCL816_CTRCTL); /* set counter 2 as mode 3 */ - outb(0x74, dev->iobase + PCL816_CTRCTL); /* set counter 1 as mode 3 */ + + /* set counter 2 as mode 3 */ + outb(0xb4, dev->iobase + PCL816_CTRCTL); + /* set counter 1 as mode 3 */ + outb(0x74, dev->iobase + PCL816_CTRCTL); udelay(1); if (mode == 1) { @@ -914,41 +954,51 @@ check_channel_list(struct comedi_device *dev, } if (chanlen > 1) { - chansegment[0] = chanlist[0]; /* first channel is everytime ok */ + /* first channel is everytime ok */ + chansegment[0] = chanlist[0]; for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { /* build part of chanlist */ - DEBUG(printk("%d. %d %d\n", i, CR_CHAN(chanlist[i]), + DEBUG(printk(KERN_INFO "%d. %d %d\n", i, + CR_CHAN(chanlist[i]), CR_RANGE(chanlist[i]));) + + /* we detect loop, this must by finish */ if (chanlist[0] == chanlist[i]) - break; /* we detect loop, this must by finish */ + break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ - printk - ("comedi%d: pcl816: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", - dev->minor, i, CR_CHAN(chanlist[i]), - nowmustbechan, CR_CHAN(chanlist[0])); + printk(KERN_WARNING + "comedi%d: pcl816: channel list must " + "be continous! chanlist[%i]=%d but " + "must be %d or %d!\n", dev->minor, + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); return 0; } - chansegment[i] = chanlist[i]; /* well, this is next correct channel in list */ + /* well, this is next correct channel in list */ + chansegment[i] = chanlist[i]; } - for (i = 0, segpos = 0; i < chanlen; i++) { /* check whole chanlist */ + /* check whole chanlist */ + for (i = 0, segpos = 0; i < chanlen; i++) { DEBUG(printk("%d %d=%d %d\n", CR_CHAN(chansegment[i % seglen]), CR_RANGE(chansegment[i % seglen]), CR_CHAN(chanlist[i]), CR_RANGE(chanlist[i]));) if (chanlist[i] != chansegment[i % seglen]) { - printk - ("comedi%d: pcl816: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", - dev->minor, i, CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); + printk(KERN_WARNING + "comedi%d: pcl816: bad channel or range" + " number! chanlist[%i]=%d,%d,%d and not" + " %d,%d,%d!\n", dev->minor, i, + CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); return 0; /* chan/gain list is strange */ } } @@ -976,12 +1026,15 @@ setup_channel_list(struct comedi_device *dev, for (i = 0; i < seglen; i++) { /* store range list to card */ devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]); outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX); - outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE); /* select gain */ + /* select gain */ + outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE); } udelay(1); - - outb(devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4), dev->iobase + PCL816_MUX); /* select channel interval to scan */ + /* select channel interval to scan */ + outb(devpriv->ai_act_chanlist[0] | + (devpriv->ai_act_chanlist[seglen - 1] << 4), + dev->iobase + PCL816_MUX); } #ifdef unused @@ -1009,11 +1062,11 @@ static int set_rtc_irq_bit(unsigned char bit) save_flags(flags); cli(); val = CMOS_READ(RTC_CONTROL); - if (bit) { + if (bit) val |= RTC_PIE; - } else { + else val &= ~RTC_PIE; - } + CMOS_WRITE(val, RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); restore_flags(flags); @@ -1083,7 +1136,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->iobase = iobase; if (pcl816_check(iobase)) { - printk(", I cann't detect board. FAIL!\n"); + printk(KERN_ERR ", I cann't detect board. FAIL!\n"); return -EIO; } @@ -1101,30 +1154,29 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (irq) { /* we want to use IRQ */ if (((1 << irq) & this_board->IRQbits) == 0) { printk - (", IRQ %u is out of allowed range, DISABLING IT", - irq); + (", IRQ %u is out of allowed range, " + "DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { if (request_irq (irq, interrupt_pcl816, 0, "pcl816", dev)) { printk - (", unable to allocate IRQ %u, DISABLING IT", - irq); + (", unable to allocate IRQ %u, " + "DISABLING IT", irq); irq = 0; /* Can't use IRQ */ } else { - printk(", irq=%u", irq); + printk(KERN_INFO ", irq=%u", irq); } } } } dev->irq = irq; - if (irq) { + if (irq) /* 1=we have allocated irq */ devpriv->irq_free = 1; - } /* 1=we have allocated irq */ - else { + else devpriv->irq_free = 0; - } + devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ devpriv->int816_mode = 0; /* mode of irq */ @@ -1181,18 +1233,22 @@ no_rtc: } ret = request_dma(dma, "pcl816"); if (ret) { - printk(", unable to allocate DMA %u, FAIL!\n", dma); + printk(KERN_ERR + ", unable to allocate DMA %u, FAIL!\n", dma); return -EBUSY; /* DMA isn't free */ } devpriv->dma = dma; - printk(", dma=%u", dma); + printk(KERN_INFO ", dma=%u", dma); pages = 2; /* we need 16KB */ devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[0]) { printk(", unable to allocate DMA buffer, FAIL!\n"); - /* maybe experiment with try_to_free_pages() will help .... */ + /* + * maybe experiment with try_to_free_pages() + * will help .... + */ return -EBUSY; /* no buffer :-( */ } devpriv->dmapages[0] = pages; @@ -1203,8 +1259,9 @@ no_rtc: if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */ devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { - printk - (", unable to allocate DMA buffer, FAIL!\n"); + printk(KERN_ERR + ", unable to allocate DMA buffer, " + "FAIL!\n"); return -EBUSY; } devpriv->dmapages[1] = pages; @@ -1288,7 +1345,7 @@ case COMEDI_SUBD_DO: */ static int pcl816_detach(struct comedi_device *dev) { - DEBUG(printk("comedi%d: pcl816: remove\n", dev->minor);) + DEBUG(printk(KERN_INFO "comedi%d: pcl816: remove\n", dev->minor);) free_resources(dev); #ifdef unused if (devpriv->dma_rtc) -- cgit v1.2.3 From 8b83e005d11bce0f9a59d9be337a285e6cc487a6 Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Wed, 16 Jun 2010 00:36:54 -0500 Subject: Staging: comedi: drivers: fix coding style issues in pcmda12.c This is a patch to the pcmda12.c file that fixes up five printk() warning issues Signed-off-by: Gustavo Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmda12.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 6d6b86ad817d..0e9ffa28d745 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -157,7 +157,8 @@ static int pcmda12_attach(struct comedi_device *dev, unsigned long iobase; iobase = it->options[0]; - printk("comedi%d: %s: io: %lx %s ", dev->minor, driver.driver_name, + printk(KERN_INFO + "comedi%d: %s: io: %lx %s ", dev->minor, driver.driver_name, iobase, it->options[1] ? "simultaneous xfer mode enabled" : ""); if (!request_region(iobase, IOSIZE, driver.driver_name)) { @@ -177,7 +178,7 @@ static int pcmda12_attach(struct comedi_device *dev, * convenient macro defined in comedidev.h. */ if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) { - printk("cannot allocate private data structure\n"); + printk(KERN_ERR "cannot allocate private data structure\n"); return -ENOMEM; } @@ -191,7 +192,7 @@ static int pcmda12_attach(struct comedi_device *dev, * 96-channel version of the board. */ if (alloc_subdevices(dev, 1) < 0) { - printk("cannot allocate subdevice data structures\n"); + printk(KERN_ERR "cannot allocate subdevice data structures\n"); return -ENOMEM; } @@ -207,7 +208,7 @@ static int pcmda12_attach(struct comedi_device *dev, zero_chans(dev); /* clear out all the registers, basically */ - printk("attached\n"); + printk(KERN_INFO "attached\n"); return 1; } @@ -222,7 +223,8 @@ static int pcmda12_attach(struct comedi_device *dev, */ static int pcmda12_detach(struct comedi_device *dev) { - printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name); + printk(KERN_INFO + "comedi%d: %s: remove\n", dev->minor, driver.driver_name); if (dev->iobase) release_region(dev->iobase, IOSIZE); return 0; -- cgit v1.2.3 From 3420f6b4c1ac731e80d0911e0092705992cef14f Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Wed, 16 Jun 2010 01:01:07 -0500 Subject: Staging: comedi: drivers: fix coding style issues in quatech_daqp_cs.c This is a patch to the quatech_daqp_cs.c file that fixes up the following issues: ERROR: code indent should use tabs where possible x 1 WARNING: line over 80 characters x 1 WARNING: braces {} are not necessary for single statement blocks x 10 WARNING: printk() should include KERN_ facility level x 6 Signed-off-by: Gustavo Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 53 ++++++++++++------------ 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 78eb254bd619..8d16380744b2 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -14,7 +14,7 @@ Documentation for the DAQP PCMCIA cards can be found on Quatech's site: - ftp://ftp.quatech.com/Manuals/daqp-208.pdf + ftp://ftp.quatech.com/Manuals/daqp-208.pdf This manual is for both the DAQP-208 and the DAQP-308. @@ -195,7 +195,7 @@ static struct comedi_driver driver_daqp = { static void daqp_dump(struct comedi_device *dev) { - printk("DAQP: status %02x; aux status %02x\n", + printk(KERN_INFO "DAQP: status %02x; aux status %02x\n", inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX)); } @@ -207,9 +207,9 @@ static void hex_dump(char *str, void *ptr, int len) printk(str); for (i = 0; i < len; i++) { - if (i % 16 == 0) { + if (i % 16 == 0) printk("\n0x%08x:", (unsigned int)cptr); - } + printk(" %02x", *(cptr++)); } printk("\n"); @@ -223,9 +223,9 @@ static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct local_info_t *local = (struct local_info_t *)s->private; - if (local->stop) { + if (local->stop) return -EIO; - } + outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND); @@ -355,9 +355,9 @@ static int daqp_ai_insn_read(struct comedi_device *dev, int v; int counter = 10000; - if (local->stop) { + if (local->stop) return -EIO; - } + /* Stop any running conversion */ daqp_ai_cancel(dev, s); @@ -372,9 +372,9 @@ static int daqp_ai_insn_read(struct comedi_device *dev, v = DAQP_SCANLIST_CHANNEL(CR_CHAN(insn->chanspec)) | DAQP_SCANLIST_GAIN(CR_RANGE(insn->chanspec)); - if (CR_AREF(insn->chanspec) == AREF_DIFF) { + if (CR_AREF(insn->chanspec) == AREF_DIFF) v |= DAQP_SCANLIST_DIFFERENTIAL; - } + v |= DAQP_SCANLIST_START; @@ -488,7 +488,10 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* + * step 2: make sure trigger sources + * are unique and mutually compatible + */ /* note that mutual compatibility is not an issue here */ if (cmd->scan_begin_src != TRIG_TIMER && @@ -588,9 +591,9 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int i; int v; - if (local->stop) { + if (local->stop) return -EIO; - } + /* Stop any running conversion */ daqp_ai_cancel(dev, s); @@ -640,13 +643,11 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) v = DAQP_SCANLIST_CHANNEL(CR_CHAN(chanspec)) | DAQP_SCANLIST_GAIN(CR_RANGE(chanspec)); - if (CR_AREF(chanspec) == AREF_DIFF) { + if (CR_AREF(chanspec) == AREF_DIFF) v |= DAQP_SCANLIST_DIFFERENTIAL; - } - if (i == 0 || scanlist_start_on_every_entry) { + if (i == 0 || scanlist_start_on_every_entry) v |= DAQP_SCANLIST_START; - } outb(v & 0xff, dev->iobase + DAQP_SCANLIST); outb(v >> 8, dev->iobase + DAQP_SCANLIST); @@ -760,7 +761,8 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) while (--counter && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ; if (!counter) { - printk("daqp: couldn't clear interrupts in status register\n"); + printk(KERN_ERR + "daqp: couldn't clear interrupts in status register\n"); return -1; } @@ -785,9 +787,8 @@ static int daqp_ao_insn_write(struct comedi_device *dev, int d; unsigned int chan; - if (local->stop) { + if (local->stop) return -EIO; - } chan = CR_CHAN(insn->chanspec); d = data[0]; @@ -811,9 +812,8 @@ static int daqp_di_insn_read(struct comedi_device *dev, { struct local_info_t *local = (struct local_info_t *)s->private; - if (local->stop) { + if (local->stop) return -EIO; - } data[0] = inb(dev->iobase + DAQP_DIGITAL_IO); @@ -828,9 +828,8 @@ static int daqp_do_insn_write(struct comedi_device *dev, { struct local_info_t *local = (struct local_info_t *)s->private; - if (local->stop) { + if (local->stop) return -EIO; - } outw(data[0] & 0xf, dev->iobase + DAQP_DIGITAL_IO); @@ -878,7 +877,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret < 0) return ret; - printk("comedi%d: attaching daqp%d (io 0x%04lx)\n", + printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n", dev->minor, it->options[0], dev->iobase); s = dev->subdevices + 0; @@ -931,7 +930,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) static int daqp_detach(struct comedi_device *dev) { - printk("comedi%d: detaching daqp\n", dev->minor); + printk(KERN_INFO "comedi%d: detaching daqp\n", dev->minor); return 0; } @@ -1152,7 +1151,7 @@ static void daqp_cs_config(struct pcmcia_device *link) /* Finally, report what we've done */ dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %u", link->irq); + printk(KERN_INFO ", irq %u", link->irq); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); -- cgit v1.2.3 From 389cd417e3b0f707ecd933b8fd26e910898ac2fc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 14 Jun 2010 12:25:05 +0100 Subject: Staging: comedi: drivers: das08: Add whitespace to driver comment block Previous whitespace changes to das08.c removed some whitespace from a "driver comment block" that the Comedi team would like to keep. "Header continuation lines" in this comment block should be indented with whitespace. (This is after the " * " at the start of each line.) Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 7e7b1a7d3fe5..ad18572a1224 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -29,11 +29,11 @@ * Description: DAS-08 compatible boards * Author: Warren Jasper, ds, Frank Hess * Devices: [Keithley Metrabyte] DAS08 (isa-das08), - * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), - * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), - * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), - * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08), - * PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16) + * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), + * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), + * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), + * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08), + * PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16) * Status: works * * This is a rewrite of the das08 and das08jr drivers. -- cgit v1.2.3 From 9a390f38b6a84d5a11c89a116363db3fe587598b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 14 Jun 2010 12:49:26 +0100 Subject: Staging: comedi: drivers: skel: Add whitespace to example comment block The Comedi team have a script 'dump_doc' to extract text from the driver comment block (starting with line 'Driver:') in (most of) the comedi driver source files. This was recently updated to allow and strip off a " * " prefix at the start of each line (well actually, it uses the perl substitution 's/^ ?\* ?//'). The skel.c file contains an instructional comment block about how to format this driver comment block, but the updated 'dump_doc' script mistakenly treats this as a valid driver comment block. This patch adds some extra whitespace to stop the instructional comment block being treated as a valid driver comment block by Comedi's 'dump_doc' script. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/skel.c | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 732a323ab710..0b9ecb19511e 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -39,28 +39,28 @@ Configuration Options: * The previous block comment is used to automatically generate * documentation in Comedi and Comedilib. The fields: * - * Driver: the name of the driver - * Description: a short phrase describing the driver. Don't list boards. - * Devices: a full list of the boards that attempt to be supported by - * the driver. Format is "(manufacturer) board name [comedi name]", - * where comedi_name is the name that is used to configure the board. - * See the comment near board_name: in the struct comedi_driver structure - * below. If (manufacturer) or [comedi name] is missing, the previous - * value is used. - * Author: you - * Updated: date when the _documentation_ was last updated. Use 'date -R' - * to get a value for this. - * Status: a one-word description of the status. Valid values are: - * works - driver works correctly on most boards supported, and - * passes comedi_test. - * unknown - unknown. Usually put there by ds. - * experimental - may not work in any particular release. Author - * probably wants assistance testing it. - * bitrotten - driver has not been update in a long time, probably - * doesn't work, and probably is missing support for significant - * Comedi interface features. - * untested - author probably wrote it "blind", and is believed to - * work, but no confirmation. + * Driver: the name of the driver + * Description: a short phrase describing the driver. Don't list boards. + * Devices: a full list of the boards that attempt to be supported by + * the driver. Format is "(manufacturer) board name [comedi name]", + * where comedi_name is the name that is used to configure the board. + * See the comment near board_name: in the struct comedi_driver structure + * below. If (manufacturer) or [comedi name] is missing, the previous + * value is used. + * Author: you + * Updated: date when the _documentation_ was last updated. Use 'date -R' + * to get a value for this. + * Status: a one-word description of the status. Valid values are: + * works - driver works correctly on most boards supported, and + * passes comedi_test. + * unknown - unknown. Usually put there by ds. + * experimental - may not work in any particular release. Author + * probably wants assistance testing it. + * bitrotten - driver has not been update in a long time, probably + * doesn't work, and probably is missing support for significant + * Comedi interface features. + * untested - author probably wrote it "blind", and is believed to + * work, but no confirmation. * * These headers should be followed by a blank line, and any comments * you wish to say about the driver. The comment area is the place -- cgit v1.2.3 From 80370692f60b4d5dfa243cb0fbd0a87a42a939a8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 14 Jun 2010 12:49:27 +0100 Subject: Staging: Comedi: drivers: Remove comment copied from skel.c The dmm32at.c and comedi_bond.c comedi driver files contain an instructional comment block copied over from skel.c about how to format a driver comment block. This comment was modified in skel.c by a previous patch in this series to stop Comedi's 'dump_doc' script treating it as an actual driver comment block. There isn't any need to repeat this comment block in the other source files, so rather than modify it, this patch just removes it from those files. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/comedi_bond.c | 37 ---------------------------- drivers/staging/comedi/drivers/dmm32at.c | 37 ---------------------------- 2 files changed, 74 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 701622280ff4..cfcbd9b8f393 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -50,43 +50,6 @@ Configuration Options: within each minor will be concatenated together in the order given here. */ -/* - * The previous block comment is used to automatically generate - * documentation in Comedi and Comedilib. The fields: - * - * Driver: the name of the driver - * Description: a short phrase describing the driver. Don't list boards. - * Devices: a full list of the boards that attempt to be supported by - * the driver. Format is "(manufacturer) board name [comedi name]", - * where comedi_name is the name that is used to configure the board. - * See the comment near board_name: in the struct comedi_driver structure - * below. If (manufacturer) or [comedi name] is missing, the previous - * value is used. - * Author: you - * Updated: date when the _documentation_ was last updated. Use 'date -R' - * to get a value for this. - * Status: a one-word description of the status. Valid values are: - * works - driver works correctly on most boards supported, and - * passes comedi_test. - * unknown - unknown. Usually put there by ds. - * experimental - may not work in any particular release. Author - * probably wants assistance testing it. - * bitrotten - driver has not been update in a long time, probably - * doesn't work, and probably is missing support for significant - * Comedi interface features. - * untested - author probably wrote it "blind", and is believed to - * work, but no confirmation. - * - * These headers should be followed by a blank line, and any comments - * you wish to say about the driver. The comment area is the place - * to put any known bugs, limitations, unsupported features, supported - * command triggers, whether or not commands are supported on particular - * subdevices, etc. - * - * Somewhere in the comment should be information about configuration - * options that are used with comedi_config. - */ - #include #include #include "../comedi.h" diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index dcde8d8dd406..957322320b73 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -37,43 +37,6 @@ Configuration Options: comedi_config /dev/comedi0 dmm32at baseaddr,irq */ -/* - * The previous block comment is used to automatically generate - * documentation in Comedi and Comedilib. The fields: - * - * Driver: the name of the driver - * Description: a short phrase describing the driver. Don't list boards. - * Devices: a full list of the boards that attempt to be supported by - * the driver. Format is "(manufacturer) board name [comedi name]", - * where comedi_name is the name that is used to configure the board. - * See the comment near board_name: in the struct comedi_driver structure - * below. If (manufacturer) or [comedi name] is missing, the previous - * value is used. - * Author: you - * Updated: date when the _documentation_ was last updated. Use 'date -R' - * to get a value for this. - * Status: a one-word description of the status. Valid values are: - * works - driver works correctly on most boards supported, and - * passes comedi_test. - * unknown - unknown. Usually put there by ds. - * experimental - may not work in any particular release. Author - * probably wants assistance testing it. - * bitrotten - driver has not been update in a long time, probably - * doesn't work, and probably is missing support for significant - * Comedi interface features. - * untested - author probably wrote it "blind", and is believed to - * work, but no confirmation. - * - * These headers should be followed by a blank line, and any comments - * you wish to say about the driver. The comment area is the place - * to put any known bugs, limitations, unsupported features, supported - * command triggers, whether or not commands are supported on particular - * subdevices, etc. - * - * Somewhere in the comment should be information about configuration - * options that are used with comedi_config. - */ - #include #include "../comedidev.h" #include -- cgit v1.2.3 From ba22a15ae8018606234b3c2c99e3ae1b922b3f60 Mon Sep 17 00:00:00 2001 From: Lars Lindley Date: Wed, 19 May 2010 15:07:30 +0100 Subject: Staging: et131x: Small format/style tidyups I fixed indentation in one place and two long lines, a space and a brace found by checkpatch.pl and fixed some long lines and whitespace around an =. Signed-off-by: Lars Lindley Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et1310_phy.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c index a6d9f29ff49c..21c5eeec62dd 100644 --- a/drivers/staging/et131x/et1310_phy.c +++ b/drivers/staging/et131x/et1310_phy.c @@ -760,7 +760,8 @@ void et131x_Mii_check(struct et131x_adapter *etdev, if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { /* NOTE - Is there a way to query this without * TruePHY? - * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) { + * && TRU_QueryCoreType(etdev->hTruePhy, 0) == + * EMI_TRUEPHY_A13O) { */ u16 Register18; @@ -778,7 +779,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev, * in the LinkDetectionDPC). */ if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) || - (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) { + (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) { spin_lock_irqsave(&etdev->Lock, flags); etdev->MediaState = NETIF_STATUS_MEDIA_DISCONNECT; @@ -836,7 +837,8 @@ void et131x_Mii_check(struct et131x_adapter *etdev, /* * NOTE - Is there a way to query this without * TruePHY? - * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) { + * && TRU_QueryCoreType(etdev->hTruePhy, 0)== + * EMI_TRUEPHY_A13O) { */ u16 Register18; -- cgit v1.2.3 From 3cc544df9373c7947be35f30ddee9725710994b0 Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Fri, 18 Jun 2010 00:01:34 -0500 Subject: Staging: comedi: drivers: fix coding style issues in pcl812.c This is a patch to the pcl812.c file that fixes up the following issues: ERROR: code indent should use tabs where possible x 27 WARNING: line over 80 characters x 37 WARNING: please, no space before tabs x 13 WARNING: braces {} are not necessary for single statement blocks x 2 WARNING: printk() should include KERN_ facility level x 22 WARNING: braces {} are not necessary for any arm of this statement x 5 Signed-off-by: Gustavo Silva Acked-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 476 +++++++++++++++++--------------- 1 file changed, 259 insertions(+), 217 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 943fb713bd7d..c6dce4a1425e 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -15,97 +15,98 @@ * card: A-823PGH, A-823PGL, A-826PG * driver: a823pgh, a823pgl, a826pg */ + /* -Driver: pcl812 -Description: Advantech PCL-812/PG, PCL-813/B, - ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, - ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG, - ICP DAS ISO-813 -Author: Michal Dobes -Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg), - PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg), - ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216), - [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl), - A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl), - A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg) -Updated: Mon, 06 Aug 2007 12:03:15 +0100 -Status: works (I hope. My board fire up under my hands - and I cann't test all features.) - -This driver supports insn and cmd interfaces. Some boards support only insn -becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). -Data transfer over DMA is supported only when you measure only one -channel, this is too hardware limitation of these boards. - -Options for PCL-812: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) - [2] - DMA (0=disable, 1, 3) - [3] - 0=trigger source is internal 8253 with 2MHz clock - 1=trigger source is external - [4] - 0=A/D input range is +/-10V - 1=A/D input range is +/-5V - 2=A/D input range is +/-2.5V - 3=A/D input range is +/-1.25V - 4=A/D input range is +/-0.625V - 5=A/D input range is +/-0.3125V - [5] - 0=D/A outputs 0-5V (internal reference -5V) - 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - -Options for PCL-812PG, ACL-8112PG: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) - [2] - DMA (0=disable, 1, 3) - [3] - 0=trigger source is internal 8253 with 2MHz clock - 1=trigger source is external - [4] - 0=A/D have max +/-5V input - 1=A/D have max +/-10V input - [5] - 0=D/A outputs 0-5V (internal reference -5V) - 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - -Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) - [2] - DMA (0=disable, 1, 3) - [3] - 0=trigger source is internal 8253 with 2MHz clock - 1=trigger source is external - [4] - 0=A/D channels are S.E. - 1=A/D channels are DIFF - [5] - 0=D/A outputs 0-5V (internal reference -5V) - 1=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - -Options for A-821PGL/PGH: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - 0=A/D channels are S.E. - 1=A/D channels are DIFF - [3] - 0=D/A output 0-5V (internal reference -5V) - 1=D/A output 0-10V (internal reference -10V) - -Options for A-821PGL-NDA: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - 0=A/D channels are S.E. - 1=A/D channels are DIFF - -Options for PCL-813: - [0] - IO Base - -Options for PCL-813B: - [0] - IO Base - [1] - 0= bipolar inputs - 1= unipolar inputs - -Options for ACL-8113, ISO-813: - [0] - IO Base - [1] - 0= 10V bipolar inputs - 1= 10V unipolar inputs - 2= 20V bipolar inputs - 3= 20V unipolar inputs -*/ + * Driver: pcl812 + * Description: Advantech PCL-812/PG, PCL-813/B, + * ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, + * ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG, + * ICP DAS ISO-813 + * Author: Michal Dobes + * Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg), + * PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg), + * ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216), + * [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl), + * A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl), + * A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg) + * Updated: Mon, 06 Aug 2007 12:03:15 +0100 + * Status: works (I hope. My board fire up under my hands + * and I cann't test all features.) + * + * This driver supports insn and cmd interfaces. Some boards support only insn + * becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). + * Data transfer over DMA is supported only when you measure only one + * channel, this is too hardware limitation of these boards. + * + * Options for PCL-812: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0=trigger source is internal 8253 with 2MHz clock + * 1=trigger source is external + * [4] - 0=A/D input range is +/-10V + * 1=A/D input range is +/-5V + * 2=A/D input range is +/-2.5V + * 3=A/D input range is +/-1.25V + * 4=A/D input range is +/-0.625V + * 5=A/D input range is +/-0.3125V + * [5] - 0=D/A outputs 0-5V (internal reference -5V) + * 1=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * + * Options for PCL-812PG, ACL-8112PG: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0=trigger source is internal 8253 with 2MHz clock + * 1=trigger source is external + * [4] - 0=A/D have max +/-5V input + * 1=A/D have max +/-10V input + * [5] - 0=D/A outputs 0-5V (internal reference -5V) + * 1=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * + * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0=trigger source is internal 8253 with 2MHz clock + * 1=trigger source is external + * [4] - 0=A/D channels are S.E. + * 1=A/D channels are DIFF + * [5] - 0=D/A outputs 0-5V (internal reference -5V) + * 1=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * + * Options for A-821PGL/PGH: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - 0=A/D channels are S.E. + * 1=A/D channels are DIFF + * [3] - 0=D/A output 0-5V (internal reference -5V) + * 1=D/A output 0-10V (internal reference -10V) + * + * Options for A-821PGL-NDA: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - 0=A/D channels are S.E. + * 1=A/D channels are DIFF + * + * Options for PCL-813: + * [0] - IO Base + * + * Options for PCL-813B: + * [0] - IO Base + * [1] - 0= bipolar inputs + * 1= unipolar inputs + * + * Options for ACL-8113, ISO-813: + * [0] - IO Base + * [1] - 0= 10V bipolar inputs + * 1= 10V unipolar inputs + * 2= 20V bipolar inputs + * 3= 20V unipolar inputs + */ #include #include @@ -117,49 +118,50 @@ Options for ACL-8113, ISO-813: #include "8253.h" -#undef PCL812_EXTDEBUG /* if this is defined then a lot of messages is printed */ +/* if this is defined then a lot of messages is printed */ +#undef PCL812_EXTDEBUG /* hardware types of the cards */ -#define boardPCL812PG 0 /* and ACL-8112PG */ -#define boardPCL813B 1 -#define boardPCL812 2 -#define boardPCL813 3 -#define boardISO813 5 -#define boardACL8113 6 -#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ -#define boardACL8216 8 /* and ICP DAS A-826PG */ -#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ - -#define PCLx1x_IORANGE 16 - -#define PCL812_CTR0 0 -#define PCL812_CTR1 1 -#define PCL812_CTR2 2 -#define PCL812_CTRCTL 3 -#define PCL812_AD_LO 4 -#define PCL812_DA1_LO 4 -#define PCL812_AD_HI 5 -#define PCL812_DA1_HI 5 -#define PCL812_DA2_LO 6 -#define PCL812_DI_LO 6 -#define PCL812_DA2_HI 7 -#define PCL812_DI_HI 7 -#define PCL812_CLRINT 8 -#define PCL812_GAIN 9 -#define PCL812_MUX 10 -#define PCL812_MODE 11 -#define PCL812_CNTENABLE 10 -#define PCL812_SOFTTRIG 12 -#define PCL812_DO_LO 13 -#define PCL812_DO_HI 14 - -#define PCL812_DRDY 0x10 /* =0 data ready */ - -#define ACL8216_STATUS 8 /* 5. bit signalize data ready */ - -#define ACL8216_DRDY 0x20 /* =0 data ready */ - -#define MAX_CHANLIST_LEN 256 /* length of scan list */ +#define boardPCL812PG 0 /* and ACL-8112PG */ +#define boardPCL813B 1 +#define boardPCL812 2 +#define boardPCL813 3 +#define boardISO813 5 +#define boardACL8113 6 +#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ +#define boardACL8216 8 /* and ICP DAS A-826PG */ +#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ + +#define PCLx1x_IORANGE 16 + +#define PCL812_CTR0 0 +#define PCL812_CTR1 1 +#define PCL812_CTR2 2 +#define PCL812_CTRCTL 3 +#define PCL812_AD_LO 4 +#define PCL812_DA1_LO 4 +#define PCL812_AD_HI 5 +#define PCL812_DA1_HI 5 +#define PCL812_DA2_LO 6 +#define PCL812_DI_LO 6 +#define PCL812_DA2_HI 7 +#define PCL812_DI_HI 7 +#define PCL812_CLRINT 8 +#define PCL812_GAIN 9 +#define PCL812_MUX 10 +#define PCL812_MODE 11 +#define PCL812_CNTENABLE 10 +#define PCL812_SOFTTRIG 12 +#define PCL812_DO_LO 13 +#define PCL812_DO_HI 14 + +#define PCL812_DRDY 0x10 /* =0 data ready */ + +#define ACL8216_STATUS 8 /* 5. bit signalize data ready */ + +#define ACL8216_DRDY 0x20 /* =0 data ready */ + +#define MAX_CHANLIST_LEN 256 /* length of scan list */ static const struct comedi_lrange range_pcl812pg_ai = { 5, { BIP_RANGE(5), @@ -477,10 +479,13 @@ static int pcl812_ai_insn_read(struct comedi_device *dev, int n; int timeout, hi; - outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE); /* select software trigger */ - setup_range_channel(dev, s, insn->chanspec, 1); /* select channel and renge */ + /* select software trigger */ + outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE); + /* select channel and renge */ + setup_range_channel(dev, s, insn->chanspec, 1); for (n = 0; n < insn->n; n++) { - outb(255, dev->iobase + PCL812_SOFTTRIG); /* start conversion */ + /* start conversion */ + outb(255, dev->iobase + PCL812_SOFTTRIG); udelay(5); timeout = 50; /* wait max 50us, it must finish under 33us */ while (timeout--) { @@ -512,10 +517,13 @@ static int acl8216_ai_insn_read(struct comedi_device *dev, int n; int timeout; - outb(1, dev->iobase + PCL812_MODE); /* select software trigger */ - setup_range_channel(dev, s, insn->chanspec, 1); /* select channel and renge */ + /* select software trigger */ + outb(1, dev->iobase + PCL812_MODE); + /* select channel and renge */ + setup_range_channel(dev, s, insn->chanspec, 1); for (n = 0; n < insn->n; n++) { - outb(255, dev->iobase + PCL812_SOFTTRIG); /* start conversion */ + /* start conversion */ + outb(255, dev->iobase + PCL812_SOFTTRIG); udelay(5); timeout = 50; /* wait max 50us, it must finish under 33us */ while (timeout--) { @@ -569,9 +577,8 @@ static int pcl812_ao_insn_read(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); int i; - for (i = 0; i < insn->n; i++) { + for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; - } return i; } @@ -619,14 +626,15 @@ static int pcl812_do_insn_bits(struct comedi_device *dev, */ static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd) { - printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + printk(KERN_INFO "pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, cmd->start_src, cmd->scan_begin_src, cmd->convert_src); - printk("pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + printk(KERN_INFO "pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e, cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); - printk("pcl812 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, - cmd->scan_end_src); - printk("pcl812 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", e, - cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); + printk(KERN_INFO "pcl812 e=%d stopsrc=%x scanend=%x\n", e, + cmd->stop_src, cmd->scan_end_src); + printk(KERN_INFO "pcl812 e=%d stoparg=%d scanendarg=%d " + "chanlistlen=%d\n", e, cmd->stop_arg, cmd->scan_end_arg, + cmd->chanlist_len); } #endif @@ -656,11 +664,11 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, err++; tmp = cmd->convert_src; - if (devpriv->use_ext_trg) { + if (devpriv->use_ext_trg) cmd->convert_src &= TRIG_EXT; - } else { + else cmd->convert_src &= TRIG_TIMER; - } + if (!cmd->convert_src || tmp != cmd->convert_src) err++; @@ -684,7 +692,10 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, return 1; } - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* + * step 2: make sure trigger sources are + * unique and mutually compatible + */ if (cmd->start_src != TRIG_NOW) { cmd->start_src = TRIG_NOW; @@ -818,7 +829,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n"); #endif if (cmd->start_src != TRIG_NOW) @@ -853,13 +864,15 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_n_chan = cmd->chanlist_len; memcpy(devpriv->ai_chanlist, cmd->chanlist, sizeof(unsigned int) * cmd->scan_end_arg); - setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1); /* select first channel and range */ + /* select first channel and range */ + setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1); if (devpriv->dma) { /* check if we can use DMA transfer */ devpriv->ai_dma = 1; for (i = 1; i < devpriv->ai_n_chan; i++) if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) { - devpriv->ai_dma = 0; /* we cann't use DMA :-( */ + /* we cann't use DMA :-( */ + devpriv->ai_dma = 0; break; } } else @@ -880,14 +893,18 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_poll_ptr = 0; s->async->cur_chan = 0; - if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { /* don't we want wake up every scan? */ + /* don't we want wake up every scan? */ + if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { devpriv->ai_eos = 1; + + /* DMA is useless for this situation */ if (devpriv->ai_n_chan == 1) - devpriv->ai_dma = 0; /* DMA is useless for this situation */ + devpriv->ai_dma = 0; } if (devpriv->ai_dma) { - if (devpriv->ai_eos) { /* we use EOS, so adapt DMA buffer to one scan */ + /* we use EOS, so adapt DMA buffer to one scan */ + if (devpriv->ai_eos) { devpriv->dmabytestomove[0] = devpriv->ai_n_chan * sizeof(short); devpriv->dmabytestomove[1] = @@ -905,9 +922,17 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (devpriv->ai_neverending) { devpriv->dma_runs_to_end = 1; } else { - bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many samples we must transfer? */ - devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0]; /* how many DMA pages we must fill */ - devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0]; /* on last dma transfer must be moved */ + /* how many samples we must transfer? */ + bytes = devpriv->ai_n_chan * + devpriv->ai_scans * sizeof(short); + + /* how many DMA pages we must fill */ + devpriv->dma_runs_to_end = + bytes / devpriv->dmabytestomove[0]; + + /* on last dma transfer must be moved */ + devpriv->last_dma_run = + bytes % devpriv->dmabytestomove[0]; if (devpriv->dma_runs_to_end == 0) devpriv->dmabytestomove[0] = devpriv->last_dma_run; @@ -945,14 +970,13 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; } - if (devpriv->ai_dma) { - outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE); /* let's go! */ - } else { - outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE); /* let's go! */ - } + if (devpriv->ai_dma) /* let's go! */ + outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE); + else /* let's go! */ + outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE); #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: END: pcl812_ai_cmd(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cmd(...)\n"); #endif return 0; @@ -994,7 +1018,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) if (err) { printk - ("comedi%d: pcl812: (%s at 0x%lx) A/D cmd IRQ without DRDY!\n", + ("comedi%d: pcl812: (%s at 0x%lx) " + "A/D cmd IRQ without DRDY!\n", dev->minor, dev->board_name, dev->iobase); pcl812_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; @@ -1020,7 +1045,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) if (next_chan == 0) { /* one scan done */ devpriv->ai_act_scan++; if (!(devpriv->ai_neverending)) - if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + /* all data sampled */ + if (devpriv->ai_act_scan >= devpriv->ai_scans) { pcl812_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA; } @@ -1041,14 +1067,16 @@ static void transfer_from_dma_buf(struct comedi_device *dev, s->async->events = 0; for (i = len; i; i--) { - comedi_buf_put(s->async, ptr[bufptr++]); /* get one sample */ + /* get one sample */ + comedi_buf_put(s->async, ptr[bufptr++]); s->async->cur_chan++; if (s->async->cur_chan >= devpriv->ai_n_chan) { s->async->cur_chan = 0; devpriv->ai_act_scan++; if (!devpriv->ai_neverending) - if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + /* all data sampled */ + if (devpriv->ai_act_scan >= devpriv->ai_scans) { pcl812_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA; break; @@ -1071,7 +1099,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) short *ptr; #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n"); #endif ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf]; len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - @@ -1106,7 +1134,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) transfer_from_dma_buf(dev, s, ptr, bufptr, len); #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n"); #endif return IRQ_HANDLED; } @@ -1122,11 +1150,10 @@ static irqreturn_t interrupt_pcl812(int irq, void *d) comedi_error(dev, "spurious interrupt"); return IRQ_HANDLED; } - if (devpriv->ai_dma) { + if (devpriv->ai_dma) return interrupt_pcl812_ai_dma(irq, d); - } else { + else return interrupt_pcl812_ai_int(irq, d); - }; } /* @@ -1143,7 +1170,8 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) spin_lock_irqsave(&dev->spinlock, flags); for (i = 0; i < 10; i++) { - top1 = get_dma_residue(devpriv->ai_dma); /* where is now DMA */ + /* where is now DMA */ + top1 = get_dma_residue(devpriv->ai_dma); top2 = get_dma_residue(devpriv->ai_dma); if (top1 == top2) break; @@ -1153,8 +1181,8 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) spin_unlock_irqrestore(&dev->spinlock, flags); return 0; } - - top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; /* where is now DMA in buffer */ + /* where is now DMA in buffer */ + top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; top1 >>= 1; /* sample position */ top2 = top1 - devpriv->ai_poll_ptr; if (top2 < 1) { /* no new samples */ @@ -1182,7 +1210,9 @@ static void setup_range_channel(struct comedi_device *dev, unsigned int rangechan, char wait) { unsigned char chan_reg = CR_CHAN(rangechan); /* normal board */ - unsigned char gain_reg = CR_RANGE(rangechan) + devpriv->range_correction; /* gain index */ + /* gain index */ + unsigned char gain_reg = CR_RANGE(rangechan) + + devpriv->range_correction; if ((chan_reg == devpriv->old_chan_reg) && (gain_reg == devpriv->old_gain_reg)) @@ -1195,20 +1225,25 @@ static void setup_range_channel(struct comedi_device *dev, if (devpriv->use_diff) { chan_reg = chan_reg | 0x30; /* DIFF inputs */ } else { - if (chan_reg & 0x80) { - chan_reg = chan_reg | 0x20; /* SE inputs 8-15 */ - } else { - chan_reg = chan_reg | 0x10; /* SE inputs 0-7 */ - } + if (chan_reg & 0x80) + /* SE inputs 8-15 */ + chan_reg = chan_reg | 0x20; + else + /* SE inputs 0-7 */ + chan_reg = chan_reg | 0x10; } } outb(chan_reg, dev->iobase + PCL812_MUX); /* select channel */ outb(gain_reg, dev->iobase + PCL812_GAIN); /* select gain */ - if (wait) { - udelay(devpriv->max_812_ai_mode0_rangewait); /* XXX this depends on selected range and can be very long for some high gain ranges! */ - } + + if (wait) + /* + * XXX this depends on selected range and can be very long for + * some high gain ranges! + */ + udelay(devpriv->max_812_ai_mode0_rangewait); } /* @@ -1218,8 +1253,8 @@ static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, unsigned int divisor2) { #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, divisor1, - divisor2); + printk(KERN_DEBUG "pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, + divisor1, divisor2); #endif outb(0xb4, dev->iobase + PCL812_CTRCTL); outb(0x74, dev->iobase + PCL812_CTRCTL); @@ -1232,7 +1267,7 @@ static void start_pacer(struct comedi_device *dev, int mode, outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1); } #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: END: start_pacer(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: END: start_pacer(...)\n"); #endif } @@ -1263,16 +1298,17 @@ static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n"); #endif if (devpriv->ai_dma) disable_dma(devpriv->dma); outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ - outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); /* Stop A/D */ + /* Stop A/D */ + outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); start_pacer(dev, -1, 0, 0); /* stop 8254 */ outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: END: pcl812_ai_cancel(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cancel(...)\n"); #endif return 0; } @@ -1283,7 +1319,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev, static void pcl812_reset(struct comedi_device *dev) { #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: BGN: pcl812_reset(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_reset(...)\n"); #endif outb(0, dev->iobase + PCL812_MUX); outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN); @@ -1315,7 +1351,7 @@ static void pcl812_reset(struct comedi_device *dev) } udelay(5); #ifdef PCL812_EXTDEBUG - printk("pcl812 EDBG: END: pcl812_reset(...)\n"); + printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_reset(...)\n"); #endif } @@ -1333,8 +1369,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) int n_subdevices; iobase = it->options[0]; - printk("comedi%d: pcl812: board=%s, ioport=0x%03lx", dev->minor, - this_board->name, iobase); + printk(KERN_INFO "comedi%d: pcl812: board=%s, ioport=0x%03lx", + dev->minor, this_board->name, iobase); if (!request_region(iobase, this_board->io_range, "pcl812")) { printk("I/O port conflict\n"); @@ -1356,18 +1392,18 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (irq) { /* we want to use IRQ */ if (((1 << irq) & this_board->IRQbits) == 0) { printk - (", IRQ %u is out of allowed range, DISABLING IT", - irq); + (", IRQ %u is out of allowed range, " + "DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { if (request_irq (irq, interrupt_pcl812, 0, "pcl812", dev)) { printk - (", unable to allocate IRQ %u, DISABLING IT", - irq); + (", unable to allocate IRQ %u, " + "DISABLING IT", irq); irq = 0; /* Can't use IRQ */ } else { - printk(", irq=%u", irq); + printk(KERN_INFO ", irq=%u", irq); } } } @@ -1387,16 +1423,20 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) } ret = request_dma(dma, "pcl812"); if (ret) { - printk(", unable to allocate DMA %u, FAIL!\n", dma); + printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n", + dma); return -EBUSY; /* DMA isn't free */ } devpriv->dma = dma; - printk(", dma=%u", dma); + printk(KERN_INFO ", dma=%u", dma); pages = 1; /* we want 8KB */ devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[0]) { printk(", unable to allocate DMA buffer, FAIL!\n"); - /* maybe experiment with try_to_free_pages() will help .... */ + /* + * maybe experiment with try_to_free_pages() + * will help .... + */ free_resources(dev); return -EBUSY; /* no buffer :-( */ } @@ -1405,7 +1445,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages); devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { - printk(", unable to allocate DMA buffer, FAIL!\n"); + printk(KERN_ERR ", unable to allocate DMA buffer, FAIL!\n"); free_resources(dev); return -EBUSY; } @@ -1468,11 +1508,11 @@ no_dma: s->maxdata = this_board->ai_maxdata; s->len_chanlist = MAX_CHANLIST_LEN; s->range_table = this_board->rangelist_ai; - if (this_board->board_type == boardACL8216) { + if (this_board->board_type == boardACL8216) s->insn_read = acl8216_ai_insn_read; - } else { + else s->insn_read = pcl812_ai_insn_read; - } + devpriv->use_MPC = this_board->haveMPC508; s->cancel = pcl812_ai_cancel; if (dev->irq) { @@ -1511,8 +1551,8 @@ no_dma: s->range_table = &range_bipolar10; break; printk - (", incorrect range number %d, changing to 0 (+/-10V)", - it->options[4]); + (", incorrect range number %d, changing " + "to 0 (+/-10V)", it->options[4]); break; } break; @@ -1541,8 +1581,8 @@ no_dma: s->range_table = &range_iso813_1_ai; break; printk - (", incorrect range number %d, changing to 0 ", - it->options[1]); + (", incorrect range number %d, " + "changing to 0 ", it->options[1]); break; } break; @@ -1566,8 +1606,8 @@ no_dma: s->range_table = &range_acl8113_1_ai; break; printk - (", incorrect range number %d, changing to 0 ", - it->options[1]); + (", incorrect range number %d, " + "changing to 0 ", it->options[1]); break; } break; @@ -1638,7 +1678,8 @@ no_dma: case boardACL8112: devpriv->max_812_ai_mode0_rangewait = 1; if (it->options[3] > 0) - devpriv->use_ext_trg = 1; /* we use external trigger */ + /* we use external trigger */ + devpriv->use_ext_trg = 1; case boardA821: devpriv->max_812_ai_mode0_rangewait = 1; devpriv->mode_reg_int = (irq << 4) & 0xf0; @@ -1647,11 +1688,12 @@ no_dma: case boardPCL813: case boardISO813: case boardACL8113: - devpriv->max_812_ai_mode0_rangewait = 5; /* maybe there must by greatest timeout */ + /* maybe there must by greatest timeout */ + devpriv->max_812_ai_mode0_rangewait = 5; break; } - printk("\n"); + printk(KERN_INFO "\n"); devpriv->valid = 1; pcl812_reset(dev); @@ -1666,7 +1708,7 @@ static int pcl812_detach(struct comedi_device *dev) { #ifdef PCL812_EXTDEBUG - printk("comedi%d: pcl812: remove\n", dev->minor); + printk(KERN_DEBUG "comedi%d: pcl812: remove\n", dev->minor); #endif free_resources(dev); return 0; -- cgit v1.2.3 From 15f0beb16937acef2bbfd1d7541612c2e7b0d37c Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 20 May 2010 10:39:38 +0200 Subject: Staging: hv: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/vmbus_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c21731a12ca7..4f6f64031f8f 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -1025,7 +1025,7 @@ static void __exit vmbus_exit(void) * installed and/or configured. We don't do anything else with the table, but * it needs to be present. */ -const static struct pci_device_id microsoft_hv_pci_table[] = { +static const struct pci_device_id microsoft_hv_pci_table[] = { { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ { 0 } }; -- cgit v1.2.3 From cb016cc48a011cbe23c4c742a577108853b66e3f Mon Sep 17 00:00:00 2001 From: Adam Latham Date: Wed, 19 May 2010 06:55:26 +0100 Subject: Staging: winbond: Fix C99 Comment issues in mac_structures.h This patch fixes the use of //C99 comments in the mac_structures.h found by the checkpatch.pl tool Signed-off-by: Adam Latham Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/mac_structures.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/winbond/mac_structures.h b/drivers/staging/winbond/mac_structures.h index 7441015cb187..a390adff247b 100644 --- a/drivers/staging/winbond/mac_structures.h +++ b/drivers/staging/winbond/mac_structures.h @@ -98,28 +98,28 @@ #define ELEMENT_ID_CF_PARAMETER_SET 4 #define ELEMENT_ID_TIM 5 #define ELEMENT_ID_IBSS_PARAMETER_SET 6 -// 7~15 reserverd +/* 7~15 reserverd */ #define ELEMENT_ID_CHALLENGE_TEXT 16 -// 17~31 reserved for challenge text extension -// 32~255 reserved -//-- 11G -- +/* 17~31 reserved for challenge text extension */ +/* 32~255 reserved */ +/*-- 11G -- */ #define ELEMENT_ID_ERP_INFORMATION 42 #define ELEMENT_ID_EXTENDED_SUPPORTED_RATES 50 -//-- WPA -- +/* -- WPA -- */ #define ELEMENT_ID_RSN_WPA 221 #ifdef _WPA2_ #define ELEMENT_ID_RSN_WPA2 48 -#endif //endif WPA2 +#endif /* endif WPA2 */ #define WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT ((u16) 6) #define WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT ((u16) 2) -//=================================================================== -// Reason Code (Table 18): indicate the reason of DisAssoc, DeAuthen -// length of ReasonCode is 2 Octs. -//=================================================================== +/* =================================================================== +* Reason Code (Table 18): indicate the reason of DisAssoc, DeAuthen +* length of ReasonCode is 2 Octs. +* =================================================================== */ #define REASON_REASERED 0 #define REASON_UNSPECIDIED 1 #define REASON_PREAUTH_INVALID 2 @@ -433,7 +433,7 @@ struct suite_selector }; }; -//-- WPA -- +/* -- WPA -- */ struct RSN_Information_Element { u8 Element_ID; -- cgit v1.2.3 From 07bbf350483e75823ff9c21d213d63a8bbf751ca Mon Sep 17 00:00:00 2001 From: Adam Latham Date: Fri, 21 May 2010 06:22:09 +0100 Subject: Staging: winbond: Fix for brace style, length and whitespace in mac_structures.h This patch fixes line length, brace style and whitespace issues in the mac_structures.h file found by the checkpatch.pl tool Signed-off-by: Adam Latham Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/mac_structures.h | 122 +++++++++++++++---------------- 1 file changed, 59 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/winbond/mac_structures.h b/drivers/staging/winbond/mac_structures.h index a390adff247b..415256f69c32 100644 --- a/drivers/staging/winbond/mac_structures.h +++ b/drivers/staging/winbond/mac_structures.h @@ -41,8 +41,10 @@ #define DOT_11_MAC_HEADER_SIZE 24 #define DOT_11_SNAP_SIZE 6 #define DOT_11_DURATION_OFFSET 2 -#define DOT_11_SEQUENCE_OFFSET 22 /* Sequence control offset */ -#define DOT_11_TYPE_OFFSET 30 /* The start offset of 802.11 Frame// */ +/* Sequence control offset */ +#define DOT_11_SEQUENCE_OFFSET 22 +/* The start offset of 802.11 Frame// */ +#define DOT_11_TYPE_OFFSET 30 #define DOT_11_DATA_OFFSET 24 #define DOT_11_DA_OFFSET 4 #define DOT_3_TYPE_ARP 0x80F3 @@ -385,9 +387,11 @@ struct Extended_Supported_Rates_Element { #ifdef _WPA2_ #define VERSION_WPA2 1 #endif /* end def _WPA2_ */ -#define OUI_WPA 0x00F25000 /* WPA2.0 OUI=00:50:F2, the MSB is reserved for suite type */ +/* WPA2.0 OUI=00:50:F2, the MSB is reserved for suite type */ +#define OUI_WPA 0x00F25000 #ifdef _WPA2_ -#define OUI_WPA2 0x00AC0F00 /* for wpa2 change to 0x00ACOF04 by Ws 26/04/04 */ +/* for wpa2 change to 0x00ACOF04 by Ws 26/04/04 */ +#define OUI_WPA2 0x00AC0F00 #endif /* end def _WPA2_ */ #define OUI_WPA_ADDITIONAL 0x01 @@ -400,8 +404,8 @@ struct Extended_Supported_Rates_Element { #define WPA_OUI_BIG ((u32) 0x01F25000)/* added by ws 09/23/04 */ #define WPA_OUI_LITTLE ((u32) 0x01F25001)/* added by ws 09/23/04 */ - -#define WPA_WPS_OUI cpu_to_le32(0x04F25000) /* 20061108 For WPS. It's little endian. Big endian is 0x0050F204 */ +/* 20061108 For WPS. It's little endian. Big endian is 0x0050F204 */ +#define WPA_WPS_OUI cpu_to_le32(0x04F25000) /* -----WPA2----- */ #ifdef _WPA2_ @@ -420,75 +424,65 @@ struct Extended_Supported_Rates_Element { #define OUI_CIPHER_CCMP 0x04 #define OUI_CIPHER_WEP_104 0x05 -struct suite_selector -{ - union - { +struct suite_selector{ + union{ u8 Value[4]; - struct _SUIT_ - { + struct _SUIT_ { u8 OUI[3]; u8 Type; - }SuitSelector; + } SuitSelector; }; }; /* -- WPA -- */ -struct RSN_Information_Element -{ +struct RSN_Information_Element{ u8 Element_ID; u8 Length; - struct suite_selector OuiWPAAdditional; /* WPA version 2.0 additional field, and should be 00:50:F2:01 */ + /* WPA version 2.0 additional field, and should be 00:50:F2:01 */ + struct suite_selector OuiWPAAdditional; u16 Version; struct suite_selector GroupKeySuite; u16 PairwiseKeySuiteCount; struct suite_selector PairwiseKeySuite[1]; -}__attribute__ ((packed)); -struct RSN_Auth_Sub_Information_Element -{ +} __attribute__ ((packed)); +struct RSN_Auth_Sub_Information_Element { u16 AuthKeyMngtSuiteCount; struct suite_selector AuthKeyMngtSuite[1]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -- WPA2 -- */ -struct RSN_Capability_Element -{ - union - { +struct RSN_Capability_Element { + union { u16 __attribute__ ((packed)) wValue; #ifdef _BIG_ENDIAN_ /* 20060927 add by anson's endian */ - struct _RSN_Capability - { - u16 __attribute__ ((packed)) Reserved2 : 8; /* 20051201 */ - u16 __attribute__ ((packed)) Reserved1 : 2; - u16 __attribute__ ((packed)) GTK_Replay_Counter : 2; - u16 __attribute__ ((packed)) PTK_Replay_Counter : 2; - u16 __attribute__ ((packed)) No_Pairwise : 1; - u16 __attribute__ ((packed)) Pre_Auth : 1; - }__attribute__ ((packed)) RSN_Capability; + struct _RSN_Capability { + u16 __attribute__ ((packed)) Reserved2:8; /* 20051201 */ + u16 __attribute__ ((packed)) Reserved1:2; + u16 __attribute__ ((packed)) GTK_Replay_Counter:2; + u16 __attribute__ ((packed)) PTK_Replay_Counter:2; + u16 __attribute__ ((packed)) No_Pairwise:1; + u16 __attribute__ ((packed)) Pre_Auth:1; + } __attribute__ ((packed)) RSN_Capability; #else - struct _RSN_Capability - { - u16 __attribute__ ((packed)) Pre_Auth : 1; - u16 __attribute__ ((packed)) No_Pairwise : 1; - u16 __attribute__ ((packed)) PTK_Replay_Counter : 2; - u16 __attribute__ ((packed)) GTK_Replay_Counter : 2; - u16 __attribute__ ((packed)) Reserved1 : 2; - u16 __attribute__ ((packed)) Reserved2 : 8; /* 20051201 */ - }__attribute__ ((packed)) RSN_Capability; + struct _RSN_Capability { + u16 __attribute__ ((packed)) Pre_Auth:1; + u16 __attribute__ ((packed)) No_Pairwise:1; + u16 __attribute__ ((packed)) PTK_Replay_Counter:2; + u16 __attribute__ ((packed)) GTK_Replay_Counter:2; + u16 __attribute__ ((packed)) Reserved1:2; + u16 __attribute__ ((packed)) Reserved2:8; /* 20051201 */ + } __attribute__ ((packed)) RSN_Capability; #endif - }__attribute__ ((packed)) ; -}__attribute__ ((packed)) ; + } __attribute__ ((packed)) ; +} __attribute__ ((packed)) ; #ifdef _WPA2_ -struct pmkid -{ +struct pmkid { u8 pValue[16]; }; -struct WPA2_RSN_Information_Element -{ +struct WPA2_RSN_Information_Element { u8 Element_ID; u8 Length; u16 Version; @@ -496,29 +490,28 @@ struct WPA2_RSN_Information_Element u16 PairwiseKeySuiteCount; struct suite_selector PairwiseKeySuite[1]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); -struct WPA2_RSN_Auth_Sub_Information_Element -{ +struct WPA2_RSN_Auth_Sub_Information_Element { u16 AuthKeyMngtSuiteCount; struct suite_selector AuthKeyMngtSuite[1]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); -struct PMKID_Information_Element -{ +struct PMKID_Information_Element { u16 PMKID_Count; struct pmkid pmkid[16]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); #endif /* enddef _WPA2_ */ /*============================================================ // MAC Frame structure (different type) and subfield structure //============================================================*/ -struct MAC_frame_control -{ - u8 mac_frame_info; /* a combination of the [Protocol Version, Control Type, Control Subtype]*/ - #ifdef _BIG_ENDIAN_ /* 20060927 add by anson's endian */ +struct MAC_frame_control { +/* a combination of the [Protocol Version, Control Type, Control Subtype]*/ + u8 mac_frame_info; +/* 20060927 add by anson's endian */ + #ifdef _BIG_ENDIAN_ u8 order:1; u8 WEP:1; u8 more_data:1; @@ -540,7 +533,8 @@ struct MAC_frame_control } __attribute__ ((packed)); struct Management_Frame { - struct MAC_frame_control frame_control; /* 2B, ToDS,FromDS,MoreFrag,MoreData,Order=0 */ +/* 2B, ToDS,FromDS,MoreFrag,MoreData,Order=0 */ + struct MAC_frame_control frame_control; u16 duration; u8 DA[MAC_ADDR_LENGTH]; /* Addr1 */ u8 SA[MAC_ADDR_LENGTH]; /* Addr2 */ @@ -552,7 +546,8 @@ struct Management_Frame { /* SW-MAC don't Tx/Rx Control-Frame, HW-MAC do it. */ struct Control_Frame { - struct MAC_frame_control frame_control; /* ToDS,FromDS,MoreFrag,Retry,MoreData,WEP,Order=0 */ +/* ToDS,FromDS,MoreFrag,Retry,MoreData,WEP,Order=0 */ + struct MAC_frame_control frame_control; u16 duration; u8 RA[MAC_ADDR_LENGTH]; u8 TA[MAC_ADDR_LENGTH]; @@ -627,8 +622,9 @@ struct Authentication_Frame_Body { u16 algorithmNumber; u16 sequenceNumber; u16 statusCode; - /* NB: don't include ChallengeText in this structure - // struct Challenge_Text_Element sChallengeTextElement; // wkchen added */ + /* NB: don't include ChallengeText in this structure + // struct Challenge_Text_Element sChallengeTextElement; + // wkchen added */ } __attribute__ ((packed)); -- cgit v1.2.3 From 3a4d1b9096cce99f3dd8870cc87980dcabf6787e Mon Sep 17 00:00:00 2001 From: Timofey Trofimov Date: Tue, 25 May 2010 18:19:54 +0400 Subject: Staging: winbond: fix some checkpatch.pl issues in phy_calibration.c This is a patch to the phy_calibration.c that fixes up almost all warnings and errors (except 80 characters limit and lack of tabs errors) found by the checkpatch.pl tool Signed-off-by: Timofey Trofimov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/phy_calibration.c | 835 ++++++++++++------------------ 1 file changed, 345 insertions(+), 490 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c index 78935865df19..5eefea31948c 100644 --- a/drivers/staging/winbond/phy_calibration.c +++ b/drivers/staging/winbond/phy_calibration.c @@ -19,23 +19,25 @@ /****************** LOCAL CONSTANT AND MACRO SECTION ************************/ #define LOOP_TIMES 20 -#define US 1000//MICROSECOND +#define US 1000/* MICROSECOND*/ #define AG_CONST 0.6072529350 #define FIXED(X) ((s32)((X) * 32768.0)) #define DEG2RAD(X) 0.017453 * (X) -static const s32 Angles[] = -{ - FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)), - FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)), - FIXED(DEG2RAD(0.895174)),FIXED(DEG2RAD(0.447614)),FIXED(DEG2RAD(0.223811)), - FIXED(DEG2RAD(0.111906)),FIXED(DEG2RAD(0.055953)),FIXED(DEG2RAD(0.027977)) +static const s32 Angles[] = { + FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)), + FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)), + FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)), FIXED(DEG2RAD(0.223811)), + FIXED(DEG2RAD(0.111906)), FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977)) }; -/****************** LOCAL FUNCTION DECLARATION SECTION **********************/ -//void _phy_rf_write_delay(struct hw_data *phw_data); -//void phy_init_rf(struct hw_data *phw_data); +/****************** LOCAL FUNCTION DECLARATION SECTION ********************** + +/* + * void _phy_rf_write_delay(struct hw_data *phw_data); + * void phy_init_rf(struct hw_data *phw_data); + */ /****************** FUNCTION DEFINITION SECTION *****************************/ @@ -46,9 +48,7 @@ s32 _s13_to_s32(u32 data) val = (data & 0x0FFF); if ((data & BIT(12)) != 0) - { val |= 0xFFFFF000; - } return ((s32) val); } @@ -58,13 +58,9 @@ u32 _s32_to_s13(s32 data) u32 val; if (data > 4095) - { data = 4095; - } else if (data < -4096) - { data = -4096; - } val = data & 0x1FFF; @@ -79,9 +75,7 @@ s32 _s4_to_s32(u32 data) val = (data & 0x0007); if ((data & BIT(3)) != 0) - { val |= 0xFFFFFFF8; - } return val; } @@ -91,13 +85,9 @@ u32 _s32_to_s4(s32 data) u32 val; if (data > 7) - { data = 7; - } else if (data < -8) - { data = -8; - } val = data & 0x000F; @@ -112,9 +102,7 @@ s32 _s5_to_s32(u32 data) val = (data & 0x000F); if ((data & BIT(4)) != 0) - { val |= 0xFFFFFFF0; - } return val; } @@ -124,13 +112,9 @@ u32 _s32_to_s5(s32 data) u32 val; if (data > 15) - { data = 15; - } else if (data < -16) - { data = -16; - } val = data & 0x001F; @@ -145,9 +129,7 @@ s32 _s6_to_s32(u32 data) val = (data & 0x001F); if ((data & BIT(5)) != 0) - { val |= 0xFFFFFFE0; - } return val; } @@ -157,11 +139,8 @@ u32 _s32_to_s6(s32 data) u32 val; if (data > 31) - { data = 31; - } else if (data < -32) - { data = -32; } @@ -178,9 +157,7 @@ s32 _s9_to_s32(u32 data) val = data & 0x00FF; if ((data & BIT(8)) != 0) - { val |= 0xFFFFFF00; - } return val; } @@ -190,13 +167,9 @@ u32 _s32_to_s9(s32 data) u32 val; if (data > 255) - { data = 255; - } else if (data < -256) - { data = -256; - } val = data & 0x01FF; @@ -207,21 +180,19 @@ u32 _s32_to_s9(s32 data) s32 _floor(s32 n) { if (n > 0) - { - n += 5; - } + n += 5; else - { n -= 5; - } return (n/10); } /****************************************************************************/ -// The following code is sqare-root function. -// sqsum is the input and the output is sq_rt; -// The maximum of sqsum = 2^27 -1; +/* + * The following code is sqare-root function. + * sqsum is the input and the output is sq_rt; + * The maximum of sqsum = 2^27 -1; + */ u32 _sqrt(u32 sqsum) { u32 sq_rt; @@ -232,18 +203,17 @@ u32 _sqrt(u32 sqsum) int step; g4 = sqsum / 100000000; - g3 = (sqsum - g4*100000000) /1000000; - g2 = (sqsum - g4*100000000 - g3*1000000) /10000; - g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) /100; + g3 = (sqsum - g4*100000000) / 1000000; + g2 = (sqsum - g4*100000000 - g3*1000000) / 10000; + g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100; g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100); next = g4; step = 0; seed = 0; - while (((seed+1)*(step+1)) <= next) - { - step++; - seed++; + while (((seed+1)*(step+1)) <= next) { + step++; + seed++; } sq_rt = seed * 10000; @@ -251,20 +221,18 @@ u32 _sqrt(u32 sqsum) step = 0; seed = 2 * seed * 10; - while (((seed+1)*(step+1)) <= next) - { + while (((seed+1)*(step+1)) <= next) { step++; - seed++; + seed++; } sq_rt = sq_rt + step * 1000; next = (next - seed * step) * 100 + g2; seed = (seed + step) * 10; step = 0; - while (((seed+1)*(step+1)) <= next) - { + while (((seed+1)*(step+1)) <= next) { step++; - seed++; + seed++; } sq_rt = sq_rt + step * 100; @@ -272,21 +240,19 @@ u32 _sqrt(u32 sqsum) seed = (seed + step) * 10; step = 0; - while (((seed+1)*(step+1)) <= next) - { + while (((seed+1)*(step+1)) <= next) { step++; - seed++; + seed++; } sq_rt = sq_rt + step * 10; - next = (next - seed* step) * 100 + g0; + next = (next - seed * step) * 100 + g0; seed = (seed + step) * 10; step = 0; - while (((seed+1)*(step+1)) <= next) - { + while (((seed+1)*(step+1)) <= next) { step++; - seed++; + seed++; } sq_rt = sq_rt + step; @@ -300,38 +266,31 @@ void _sin_cos(s32 angle, s32 *sin, s32 *cos) s32 X, Y, TargetAngle, CurrAngle; unsigned Step; - X=FIXED(AG_CONST); // AG_CONST * cos(0) - Y=0; // AG_CONST * sin(0) - TargetAngle=abs(angle); - CurrAngle=0; + X = FIXED(AG_CONST); /* AG_CONST * cos(0) */ + Y = 0; /* AG_CONST * sin(0) */ + TargetAngle = abs(angle); + CurrAngle = 0; - for (Step=0; Step < 12; Step++) - { + for (Step = 0; Step < 12; Step++) { s32 NewX; - if(TargetAngle > CurrAngle) - { - NewX=X - (Y >> Step); - Y=(X >> Step) + Y; - X=NewX; + if (TargetAngle > CurrAngle) { + NewX = X - (Y >> Step); + Y = (X >> Step) + Y; + X = NewX; CurrAngle += Angles[Step]; - } - else - { - NewX=X + (Y >> Step); - Y=-(X >> Step) + Y; - X=NewX; + } else { + NewX = X + (Y >> Step); + Y = -(X >> Step) + Y; + X = NewX; CurrAngle -= Angles[Step]; } } - if (angle > 0) - { + if (angle > 0) { *cos = X; *sin = Y; - } - else - { + } else { *cos = X; *sin = -Y; } @@ -343,7 +302,7 @@ static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 * number += 0x1000; return Wb35Reg_ReadSync(pHwData, number, pValue); } -#define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (u32 *)_C ) +#define hw_get_dxx_reg(_A, _B, _C) hal_get_dxx_reg(_A, _B, (u32 *)_C) static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number, u32 value) { @@ -354,7 +313,7 @@ static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number, u32 va ret = Wb35Reg_WriteSync(pHwData, number, value); return ret; } -#define hw_set_dxx_reg( _A, _B, _C ) hal_set_dxx_reg( _A, _B, (u32)_C ) +#define hw_set_dxx_reg(_A, _B, _C) hal_set_dxx_reg(_A, _B, (u32)_C) void _reset_rx_cal(struct hw_data *phw_data) @@ -363,25 +322,20 @@ void _reset_rx_cal(struct hw_data *phw_data) hw_get_dxx_reg(phw_data, 0x54, &val); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */ val &= 0xFFFF0000; - } - else // 2nd-cut - { + else /* 2nd-cut */ val &= 0x000003FF; - } hw_set_dxx_reg(phw_data, 0x54, val); } -// ************for winbond calibration********* -// +/**************for winbond calibration*********/ + + -// -// -// ********************************************* +/**********************************************/ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency) { u32 reg_agc_ctrl3; @@ -392,35 +346,31 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n")); phy_init_rf(phw_data); - // set calibration channel - if( (RF_WB_242 == phw_data->phy_type) || - (RF_WB_242_1 == phw_data->phy_type) ) // 20060619.5 Add - { - if ((frequency >= 2412) && (frequency <= 2484)) - { - // w89rf242 change frequency to 2390Mhz + /* set calibration channel */ + if ((RF_WB_242 == phw_data->phy_type) || + (RF_WB_242_1 == phw_data->phy_type)) /* 20060619.5 Add */{ + if ((frequency >= 2412) && (frequency <= 2484)) { + /* w89rf242 change frequency to 2390Mhz */ PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n")); phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); } - } - else - { + } else { } - // reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel + /* reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel */ hw_get_dxx_reg(phw_data, 0x5C, &val); val &= ~(0x03FF); hw_set_dxx_reg(phw_data, 0x5C, val); - // reset the TX and RX IQ calibration data + /* reset the TX and RX IQ calibration data */ hw_set_dxx_reg(phw_data, 0x3C, 0); hw_set_dxx_reg(phw_data, 0x54, 0); - hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed + hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ - // a. Disable AGC + /* a. Disable AGC */ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); reg_agc_ctrl3 &= ~BIT(2); reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); @@ -430,7 +380,7 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen val |= MASK_AGC_FIX_GAIN; hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); - // b. Turn off BB RX + /* b. Turn off BB RX */ hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, ®_a_acq_ctrl); reg_a_acq_ctrl |= MASK_AMER_OFF_REG; hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl); @@ -439,9 +389,9 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen reg_b_acq_ctrl |= MASK_BMER_OFF_REG; hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl); - // c. Make sure MAC is in receiving mode - // d. Turn ON ADC calibration - // - ADC calibrator is triggered by this signal rising from 0 to 1 + /* c. Make sure MAC is in receiving mode + * d. Turn ON ADC calibration + * - ADC calibrator is triggered by this signal rising from 0 to 1 */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); val &= ~MASK_ADC_DC_CAL_STR; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); @@ -449,7 +399,7 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen val |= MASK_ADC_DC_CAL_STR; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); - // e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]" + /* e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]" */ #ifdef _DEBUG hw_get_dxx_reg(phw_data, REG_OFFSET_READ, &val); PHY_DEBUG(("[CAL] REG_OFFSET_READ = 0x%08X\n", val)); @@ -464,23 +414,23 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen val &= ~MASK_ADC_DC_CAL_STR; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); - // f. Turn on BB RX - //hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, ®_a_acq_ctrl); + /* f. Turn on BB RX */ + /* hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, ®_a_acq_ctrl); */ reg_a_acq_ctrl &= ~MASK_AMER_OFF_REG; hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl); - //hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, ®_b_acq_ctrl); + /* hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, ®_b_acq_ctrl); */ reg_b_acq_ctrl &= ~MASK_BMER_OFF_REG; hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl); - // g. Enable AGC - //hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); + /* g. Enable AGC */ + /* hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); */ reg_agc_ctrl3 |= BIT(2); reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX); hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); } -//////////////////////////////////////////////////////// +/****************************************************************/ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) { u32 reg_agc_ctrl3; @@ -497,22 +447,22 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] -> [2]_txidac_dc_offset_cancellation()\n")); - // a. Set to "TX calibration mode" + /* a. Set to "TX calibration mode" */ - //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits + /* 0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); - //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit + /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); - //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized + /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); - //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); - //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode + /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); - hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed + hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ - // a. Disable AGC + /* a. Disable AGC */ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); reg_agc_ctrl3 &= ~BIT(2); reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); @@ -522,19 +472,19 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) val |= MASK_AGC_FIX_GAIN; hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); - // b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0 + /* b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0 */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); - // mode=2, tone=0 - //reg_mode_ctrl |= (MASK_CALIB_START|2); + /* mode=2, tone=0 */ + /* reg_mode_ctrl |= (MASK_CALIB_START|2); */ - // mode=2, tone=1 - //reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2)); + /* mode=2, tone=1 */ + /* reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2)); */ - // mode=2, tone=2 + /* mode=2, tone=2 */ reg_mode_ctrl |= (MASK_CALIB_START|2|(2<<2)); hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); @@ -542,12 +492,10 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) hw_get_dxx_reg(phw_data, 0x5C, ®_dc_cancel); PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel)); - for (loop = 0; loop < LOOP_TIMES; loop++) - { + for (loop = 0; loop < LOOP_TIMES; loop++) { PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop)); - // c. - // reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel + /* c. reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel */ reg_dc_cancel &= ~(0x03FF); PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); @@ -562,7 +510,7 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", mag_0, iqcal_image_i, iqcal_image_q)); - // d. + /* d. */ reg_dc_cancel |= (1 << CANCEL_DC_I_SHIFT); PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); @@ -577,18 +525,12 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", mag_1, iqcal_image_i, iqcal_image_q)); - // e. Calculate the correct DC offset cancellation value for I + /* e. Calculate the correct DC offset cancellation value for I */ if (mag_0 != mag_1) - { fix_cancel_dc_i = (mag_0*10000) / (mag_0*10000 - mag_1*10000); - } - else - { + else { if (mag_0 == mag_1) - { PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n")); - } - fix_cancel_dc_i = 0; } @@ -596,12 +538,10 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i))); if ((abs(mag_1-mag_0)*6) > mag_0) - { break; - } } - if ( loop >= 19 ) + if (loop >= 19) fix_cancel_dc_i = 0; reg_dc_cancel &= ~(0x03FF); @@ -609,13 +549,13 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); - // g. + /* g. */ reg_mode_ctrl &= ~MASK_CALIB_START; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); } -/////////////////////////////////////////////////////// +/*****************************************************/ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) { u32 reg_agc_ctrl3; @@ -631,20 +571,20 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) int loop; PHY_DEBUG(("[CAL] -> [3]_txqdac_dc_offset_cacellation()\n")); - //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits + /*0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); - //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit + /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); - //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized + /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); - //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); - //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode + /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); - hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed + hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ - // a. Disable AGC + /* a. Disable AGC */ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); reg_agc_ctrl3 &= ~BIT(2); reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); @@ -654,11 +594,11 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) val |= MASK_AGC_FIX_GAIN; hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); - // a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0 + /* a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0 */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); - //reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); + /* reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); */ reg_mode_ctrl &= ~(MASK_IQCAL_MODE); reg_mode_ctrl |= (MASK_CALIB_START|3); hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); @@ -667,12 +607,10 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) hw_get_dxx_reg(phw_data, 0x5C, ®_dc_cancel); PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel)); - for (loop = 0; loop < LOOP_TIMES; loop++) - { + for (loop = 0; loop < LOOP_TIMES; loop++) { PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop)); - // b. - // reset cancel_dc_q[4:0] in register DC_Cancel + /* b. reset cancel_dc_q[4:0] in register DC_Cancel */ reg_dc_cancel &= ~(0x001F); PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); @@ -687,7 +625,7 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", mag_0, iqcal_image_i, iqcal_image_q)); - // c. + /* c. */ reg_dc_cancel |= (1 << CANCEL_DC_Q_SHIFT); PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); @@ -702,18 +640,12 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", mag_1, iqcal_image_i, iqcal_image_q)); - // d. Calculate the correct DC offset cancellation value for I + /* d. Calculate the correct DC offset cancellation value for I */ if (mag_0 != mag_1) - { fix_cancel_dc_q = (mag_0*10000) / (mag_0*10000 - mag_1*10000); - } - else - { + else { if (mag_0 == mag_1) - { PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n")); - } - fix_cancel_dc_q = 0; } @@ -721,12 +653,10 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) fix_cancel_dc_q, _s32_to_s5(fix_cancel_dc_q))); if ((abs(mag_1-mag_0)*6) > mag_0) - { break; - } } - if ( loop >= 19 ) + if (loop >= 19) fix_cancel_dc_q = 0; reg_dc_cancel &= ~(0x001F); @@ -735,13 +665,13 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); - // f. + /* f. */ reg_mode_ctrl &= ~MASK_CALIB_START; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); } -//20060612.1.a 20060718.1 Modify +/* 20060612.1.a 20060718.1 Modify */ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, s32 a_2_threshold, s32 b_2_threshold) @@ -765,7 +695,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, s32 temp1, temp2; u32 val; u16 loop; - s32 iqcal_tone_i_avg,iqcal_tone_q_avg; + s32 iqcal_tone_i_avg, iqcal_tone_q_avg; u8 verify_count; int capture_time; @@ -780,18 +710,18 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, loop = LOOP_TIMES; - while (loop > 0) - { + while (loop > 0) { PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1))); - iqcal_tone_i_avg=0; - iqcal_tone_q_avg=0; - if( !hw_set_dxx_reg(phw_data, 0x3C, 0x00) ) // 20060718.1 modify + iqcal_tone_i_avg = 0; + iqcal_tone_q_avg = 0; + if (!hw_set_dxx_reg(phw_data, 0x3C, 0x00)) /* 20060718.1 modify */ return 0; - for(capture_time=0;capture_time<10;capture_time++) - { - // a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to - // enable "IQ alibration Mode II" + for (capture_time = 0; capture_time < 10; capture_time++) { + /* + * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to + * enable "IQ alibration Mode II" + */ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); reg_mode_ctrl &= ~MASK_IQCAL_MODE; reg_mode_ctrl |= (MASK_CALIB_START|0x02); @@ -799,7 +729,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // b. + /* b. */ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); @@ -813,21 +743,23 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, iq_mag_0_tx = (s32) _sqrt(sqsum); PHY_DEBUG(("[CAL] ** iq_mag_0_tx=%d\n", iq_mag_0_tx)); - // c. Set "calib_start" to 0x0 + /* c. Set "calib_start" to 0x0 */ reg_mode_ctrl &= ~MASK_CALIB_START; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to - // enable "IQ alibration Mode II" - //hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); + /* + * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to + * enable "IQ alibration Mode II" + */ + /* hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); reg_mode_ctrl &= ~MASK_IQCAL_MODE; reg_mode_ctrl |= (MASK_CALIB_START|0x03); hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // e. + /* e. */ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); @@ -835,14 +767,11 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13); PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n", iqcal_tone_i, iqcal_tone_q)); - if( capture_time == 0) - { + if (capture_time == 0) continue; - } - else - { - iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time; - iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time; + else { + iqcal_tone_i_avg = (iqcal_tone_i_avg*(capture_time-1) + iqcal_tone_i)/capture_time; + iqcal_tone_q_avg = (iqcal_tone_q_avg*(capture_time-1) + iqcal_tone_q)/capture_time; } } @@ -857,11 +786,10 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, PHY_DEBUG(("[CAL] ** rot_i_b = %d, rot_q_b = %d\n", rot_i_b, rot_q_b)); - // f. + /* f. */ divisor = ((iq_mag_0_tx * iq_mag_0_tx * 2)/1024 - rot_i_b) * 2; - if (divisor == 0) - { + if (divisor == 0) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n")); PHY_DEBUG(("[CAL] ** divisor=0 to calculate EPS and THETA !!\n")); PHY_DEBUG(("[CAL] ******************************************\n")); @@ -876,18 +804,16 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, phw_data->iq_rsdl_gain_tx_d2 = a_2; phw_data->iq_rsdl_phase_tx_d2 = b_2; - //if ((abs(a_2) < 150) && (abs(b_2) < 100)) - //if ((abs(a_2) < 200) && (abs(b_2) < 200)) - if ((abs(a_2) < a_2_threshold) && (abs(b_2) < b_2_threshold)) - { + /* if ((abs(a_2) < 150) && (abs(b_2) < 100)) */ + /* if ((abs(a_2) < 200) && (abs(b_2) < 200)) */ + if ((abs(a_2) < a_2_threshold) && (abs(b_2) < b_2_threshold)) { verify_count++; PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n")); PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count)); PHY_DEBUG(("[CAL] ******************************************\n")); - if (verify_count > 2) - { + if (verify_count > 2) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION (EPS,THETA) OK !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); @@ -895,37 +821,29 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, } continue; - } - else - { + } else verify_count = 0; - } _sin_cos(b_2, &sin_b, &cos_b); _sin_cos(b_2*2, &sin_2b, &cos_2b); PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b)); PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b)); - if (cos_2b == 0) - { + if (cos_2b == 0) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n")); PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n")); PHY_DEBUG(("[CAL] ******************************************\n")); break; } - // 1280 * 32768 = 41943040 + /* 1280 * 32768 = 41943040 */ temp1 = (41943040/cos_2b)*cos_b; - //temp2 = (41943040/cos_2b)*sin_b*(-1); - if (phw_data->revision == 0x2002) // 1st-cut - { + /* temp2 = (41943040/cos_2b)*sin_b*(-1); */ + if (phw_data->revision == 0x2002) /* 1st-cut */ temp2 = (41943040/cos_2b)*sin_b*(-1); - } - else // 2nd-cut - { + else /* 2nd-cut */ temp2 = (41943040*4/cos_2b)*sin_b*(-1); - } tx_cal_flt_b[0] = _floor(temp1/(32768+a_2)); tx_cal_flt_b[1] = _floor(temp2/(32768+a_2)); @@ -937,37 +855,34 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, PHY_DEBUG(("[CAL] tx_cal_flt_b[3] = %d\n", tx_cal_flt_b[3])); tx_cal[2] = tx_cal_flt_b[2]; - tx_cal[2] = tx_cal[2] +3; + tx_cal[2] = tx_cal[2] + 3; tx_cal[1] = tx_cal[2]; tx_cal[3] = tx_cal_flt_b[3] - 128; - tx_cal[0] = -tx_cal[3]+1; + tx_cal[0] = -tx_cal[3] + 1; PHY_DEBUG(("[CAL] tx_cal[0] = %d\n", tx_cal[0])); PHY_DEBUG(("[CAL] tx_cal[1] = %d\n", tx_cal[1])); PHY_DEBUG(("[CAL] tx_cal[2] = %d\n", tx_cal[2])); PHY_DEBUG(("[CAL] tx_cal[3] = %d\n", tx_cal[3])); - //if ((tx_cal[0] == 0) && (tx_cal[1] == 0) && - // (tx_cal[2] == 0) && (tx_cal[3] == 0)) - //{ - // PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n")); - // PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION COMPLETE !!\n")); - // PHY_DEBUG(("[CAL] ******************************************\n")); - // return 0; - //} - - // g. - if (phw_data->revision == 0x2002) // 1st-cut - { + /* if ((tx_cal[0] == 0) && (tx_cal[1] == 0) && + (tx_cal[2] == 0) && (tx_cal[3] == 0)) + { */ + /* PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n")); + * PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION COMPLETE !!\n")); + * PHY_DEBUG(("[CAL] ******************************************\n")); + * return 0; + } */ + + /* g. */ + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28); tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24); tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20); tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ hw_get_dxx_reg(phw_data, 0x3C, &val); PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val)); tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); @@ -982,22 +897,17 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2])); PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3])); - if (phw_data->revision == 0x2002) // 1st-cut - { - if (((tx_cal_reg[0]==7) || (tx_cal_reg[0]==(-8))) && - ((tx_cal_reg[3]==7) || (tx_cal_reg[3]==(-8)))) - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ + if (((tx_cal_reg[0] == 7) || (tx_cal_reg[0] == (-8))) && + ((tx_cal_reg[3] == 7) || (tx_cal_reg[3] == (-8)))) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); break; } - } - else // 2nd-cut - { - if (((tx_cal_reg[0]==31) || (tx_cal_reg[0]==(-32))) && - ((tx_cal_reg[3]==31) || (tx_cal_reg[3]==(-32)))) - { + } else /* 2nd-cut */{ + if (((tx_cal_reg[0] == 31) || (tx_cal_reg[0] == (-32))) && + ((tx_cal_reg[3] == 31) || (tx_cal_reg[3] == (-32)))) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); @@ -1014,8 +924,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, PHY_DEBUG(("[CAL] apply tx_cal[2] = %d\n", tx_cal[2])); PHY_DEBUG(("[CAL] apply tx_cal[3] = %d\n", tx_cal[3])); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ val &= 0x0000FFFF; val |= ((_s32_to_s4(tx_cal[0]) << 28)| (_s32_to_s4(tx_cal[1]) << 24)| @@ -1024,9 +933,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, hw_set_dxx_reg(phw_data, 0x54, val); PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val)); return 0; - } - else // 2nd-cut - { + } else /* 2nd-cut */{ val &= 0x000003FF; val |= ((_s32_to_s5(tx_cal[0]) << 27)| (_s32_to_s6(tx_cal[1]) << 21)| @@ -1037,7 +944,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, return 0; } - // i. Set "calib_start" to 0x0 + /* i. Set "calib_start" to 0x0 */ reg_mode_ctrl &= ~MASK_CALIB_START; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); @@ -1061,26 +968,26 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) PHY_DEBUG(("[CAL] -> [4]_tx_iq_calibration()\n")); - //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits + /* 0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); - //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit - phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); // 20060612.1.a 0x1905D6); - //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized - phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); //0x24C60A (high temperature) - //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized - phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); // 20060612.1.a 0x06890C); - //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode + /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ + phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); /* 20060612.1.a 0x1905D6); */ + /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ + phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); /* 0x24C60A (high temperature) */ + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ + phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); /* 20060612.1.a 0x06890C); */ + /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); - //; [BB-chip]: Calibration (6f).Send test pattern - //; [BB-chip]: Calibration (6g). Search RXGCL optimal value - //; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table - //phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); + /* ; [BB-chip]: Calibration (6f).Send test pattern */ + /* ; [BB-chip]: Calibration (6g). Search RXGCL optimal value */ + /* ; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table */ + /* phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); */ - msleep(30); // 20060612.1.a 30ms delay. Add the follow 2 lines - //To adjust TXVGA to fit iq_mag_0 range from 1250 ~ 1750 - adjust_TXVGA_for_iq_mag( phw_data ); + msleep(30); /* 20060612.1.a 30ms delay. Add the follow 2 lines */ + /* To adjust TXVGA to fit iq_mag_0 range from 1250 ~ 1750 */ + adjust_TXVGA_for_iq_mag(phw_data); - // a. Disable AGC + /* a. Disable AGC */ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); reg_agc_ctrl3 &= ~BIT(2); reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); @@ -1092,16 +999,12 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) result = _tx_iq_calibration_loop_winbond(phw_data, 150, 100); - if (result > 0) - { - if (phw_data->revision == 0x2002) // 1st-cut - { + if (result > 0) { + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); val &= 0x0000FFFF; hw_set_dxx_reg(phw_data, 0x54, val); - } - else // 2nd-cut - { + } else /* 2nd-cut*/{ hw_get_dxx_reg(phw_data, 0x3C, &val); val &= 0x000003FF; hw_set_dxx_reg(phw_data, 0x3C, val); @@ -1109,32 +1012,24 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) result = _tx_iq_calibration_loop_winbond(phw_data, 300, 200); - if (result > 0) - { - if (phw_data->revision == 0x2002) // 1st-cut - { + if (result > 0) { + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); val &= 0x0000FFFF; hw_set_dxx_reg(phw_data, 0x54, val); - } - else // 2nd-cut - { + } else /* 2nd-cut*/{ hw_get_dxx_reg(phw_data, 0x3C, &val); val &= 0x000003FF; hw_set_dxx_reg(phw_data, 0x3C, val); } result = _tx_iq_calibration_loop_winbond(phw_data, 500, 400); - if (result > 0) - { - if (phw_data->revision == 0x2002) // 1st-cut - { + if (result > 0) { + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); val &= 0x0000FFFF; hw_set_dxx_reg(phw_data, 0x54, val); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ hw_get_dxx_reg(phw_data, 0x3C, &val); val &= 0x000003FF; hw_set_dxx_reg(phw_data, 0x3C, val); @@ -1143,20 +1038,16 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) result = _tx_iq_calibration_loop_winbond(phw_data, 700, 500); - if (result > 0) - { + if (result > 0) { PHY_DEBUG(("[CAL] ** <_tx_iq_calibration> **************\n")); PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION FAILURE !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); val &= 0x0000FFFF; hw_set_dxx_reg(phw_data, 0x54, val); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ hw_get_dxx_reg(phw_data, 0x3C, &val); val &= 0x000003FF; hw_set_dxx_reg(phw_data, 0x3C, val); @@ -1166,30 +1057,27 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) } } - // i. Set "calib_start" to 0x0 + /* i. Set "calib_start" to 0x0 */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); reg_mode_ctrl &= ~MASK_CALIB_START; hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // g. Enable AGC - //hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); + /* g. Enable AGC */ + /* hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); */ reg_agc_ctrl3 |= BIT(2); reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX); hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); #ifdef _DEBUG - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ hw_get_dxx_reg(phw_data, 0x54, &val); PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28); tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24); tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20); tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16); - } - else // 2nd-cut - { + } else /* 2nd-cut */ { hw_get_dxx_reg(phw_data, 0x3C, &val); PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val)); tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); @@ -1206,11 +1094,13 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) #endif - // for test - BEN - // RF Control Override + /* + * for test - BEN + * RF Control Override + */ } -///////////////////////////////////////////////////////////////////////////////////////// +/*****************************************************/ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 frequency) { u32 reg_mode_ctrl; @@ -1236,51 +1126,49 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre u32 pwr_image; u8 verify_count; - s32 iqcal_tone_i_avg,iqcal_tone_q_avg; - s32 iqcal_image_i_avg,iqcal_image_q_avg; - u16 capture_time; + s32 iqcal_tone_i_avg, iqcal_tone_q_avg; + s32 iqcal_image_i_avg, iqcal_image_q_avg; + u16 capture_time; PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration_loop()\n")); PHY_DEBUG(("[CAL] ** factor = %d\n", factor)); -// RF Control Override +/* RF Control Override */ hw_get_cxx_reg(phw_data, 0x80, &val); val |= BIT(19); hw_set_cxx_reg(phw_data, 0x80, val); -// RF_Ctrl +/* RF_Ctrl */ hw_get_cxx_reg(phw_data, 0xE4, &val); val |= BIT(0); hw_set_cxx_reg(phw_data, 0xE4, val); PHY_DEBUG(("[CAL] ** RF_CTRL(0xE4) = 0x%08X", val)); - hw_set_dxx_reg(phw_data, 0x58, 0x44444444); // IQ_Alpha + hw_set_dxx_reg(phw_data, 0x58, 0x44444444); /* IQ_Alpha */ - // b. + /* b. */ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); verify_count = 0; - //for (loop = 0; loop < 1; loop++) - //for (loop = 0; loop < LOOP_TIMES; loop++) + /* for (loop = 0; loop < 1; loop++) */ + /* for (loop = 0; loop < LOOP_TIMES; loop++) */ loop = LOOP_TIMES; - while (loop > 0) - { + while (loop > 0) { PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1))); - iqcal_tone_i_avg=0; - iqcal_tone_q_avg=0; - iqcal_image_i_avg=0; - iqcal_image_q_avg=0; - capture_time=0; - - for(capture_time=0; capture_time<10; capture_time++) - { - // i. Set "calib_start" to 0x0 + iqcal_tone_i_avg = 0; + iqcal_tone_q_avg = 0; + iqcal_image_i_avg = 0; + iqcal_image_q_avg = 0; + capture_time = 0; + + for (capture_time = 0; capture_time < 10; capture_time++) { + /* i. Set "calib_start" to 0x0 */ reg_mode_ctrl &= ~MASK_CALIB_START; - if( !hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl) )//20060718.1 modify + if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */ return 0; PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); @@ -1289,7 +1177,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // c. + /* c. */ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); @@ -1305,16 +1193,13 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n", iqcal_image_i, iqcal_image_q)); - if( capture_time == 0) - { + if (capture_time == 0) continue; - } - else - { - iqcal_image_i_avg=( iqcal_image_i_avg*(capture_time-1) +iqcal_image_i)/capture_time; - iqcal_image_q_avg=( iqcal_image_q_avg*(capture_time-1) +iqcal_image_q)/capture_time; - iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time; - iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time; + else { + iqcal_image_i_avg = (iqcal_image_i_avg*(capture_time-1) + iqcal_image_i)/capture_time; + iqcal_image_q_avg = (iqcal_image_q_avg*(capture_time-1) + iqcal_image_q)/capture_time; + iqcal_tone_i_avg = (iqcal_tone_i_avg*(capture_time-1) + iqcal_tone_i)/capture_time; + iqcal_tone_q_avg = (iqcal_tone_q_avg*(capture_time-1) + iqcal_tone_q)/capture_time; } } @@ -1324,7 +1209,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre iqcal_tone_i = iqcal_tone_i_avg; iqcal_tone_q = iqcal_tone_q_avg; - // d. + /* d. */ rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i + iqcal_tone_q * iqcal_tone_q) / 1024; rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) + @@ -1339,9 +1224,8 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre PHY_DEBUG(("[CAL] ** rot_image_i_b = %d\n", rot_image_i_b)); PHY_DEBUG(("[CAL] ** rot_image_q_b = %d\n", rot_image_q_b)); - // f. - if (rot_tone_i_b == 0) - { + /* f. */ + if (rot_tone_i_b == 0) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n")); PHY_DEBUG(("[CAL] ** rot_tone_i_b=0 to calculate EPS and THETA !!\n")); PHY_DEBUG(("[CAL] ******************************************\n")); @@ -1363,26 +1247,21 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b)); PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b)); - if (cos_2b == 0) - { + if (cos_2b == 0) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n")); PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n")); PHY_DEBUG(("[CAL] ******************************************\n")); break; } - // 1280 * 32768 = 41943040 + /* 1280 * 32768 = 41943040 */ temp1 = (41943040/cos_2b)*cos_b; - //temp2 = (41943040/cos_2b)*sin_b*(-1); - if (phw_data->revision == 0x2002) // 1st-cut - { + /* temp2 = (41943040/cos_2b)*sin_b*(-1); */ + if (phw_data->revision == 0x2002)/* 1st-cut */ temp2 = (41943040/cos_2b)*sin_b*(-1); - } - else // 2nd-cut - { + else/* 2nd-cut */ temp2 = (41943040*4/cos_2b)*sin_b*(-1); - } rx_cal_flt_b[0] = _floor(temp1/(32768+a_2)); rx_cal_flt_b[1] = _floor(temp2/(32768-a_2)); @@ -1403,23 +1282,21 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre PHY_DEBUG(("[CAL] rx_cal[2] = %d\n", rx_cal[2])); PHY_DEBUG(("[CAL] rx_cal[3] = %d\n", rx_cal[3])); - // e. + /* e. */ pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q); pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor; PHY_DEBUG(("[CAL] ** pwr_tone = %d\n", pwr_tone)); PHY_DEBUG(("[CAL] ** pwr_image = %d\n", pwr_image)); - if (pwr_tone > pwr_image) - { + if (pwr_tone > pwr_image) { verify_count++; PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *************\n")); PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count)); PHY_DEBUG(("[CAL] ******************************************\n")); - if (verify_count > 2) - { + if (verify_count > 2) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION OK !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); @@ -1428,19 +1305,16 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre continue; } - // g. + /* g. */ hw_get_dxx_reg(phw_data, 0x54, &val); PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12); rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8); rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4); rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F)); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); @@ -1452,22 +1326,17 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2])); PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3])); - if (phw_data->revision == 0x2002) // 1st-cut - { - if (((rx_cal_reg[0]==7) || (rx_cal_reg[0]==(-8))) && - ((rx_cal_reg[3]==7) || (rx_cal_reg[3]==(-8)))) - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ + if (((rx_cal_reg[0] == 7) || (rx_cal_reg[0] == (-8))) && + ((rx_cal_reg[3] == 7) || (rx_cal_reg[3] == (-8)))) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); break; } - } - else // 2nd-cut - { - if (((rx_cal_reg[0]==31) || (rx_cal_reg[0]==(-32))) && - ((rx_cal_reg[3]==31) || (rx_cal_reg[3]==(-32)))) - { + } else /* 2nd-cut */{ + if (((rx_cal_reg[0] == 31) || (rx_cal_reg[0] == (-32))) && + ((rx_cal_reg[3] == 31) || (rx_cal_reg[3] == (-32)))) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); @@ -1485,17 +1354,14 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre PHY_DEBUG(("[CAL] apply rx_cal[3] = %d\n", rx_cal[3])); hw_get_dxx_reg(phw_data, 0x54, &val); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ val &= 0x0000FFFF; val |= ((_s32_to_s4(rx_cal[0]) << 12)| (_s32_to_s4(rx_cal[1]) << 8)| (_s32_to_s4(rx_cal[2]) << 4)| (_s32_to_s4(rx_cal[3]))); hw_set_dxx_reg(phw_data, 0x54, val); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ val &= 0x000003FF; val |= ((_s32_to_s5(rx_cal[0]) << 27)| (_s32_to_s6(rx_cal[1]) << 21)| @@ -1503,7 +1369,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre (_s32_to_s5(rx_cal[3]) << 10)); hw_set_dxx_reg(phw_data, 0x54, val); - if( loop == 3 ) + if (loop == 3) return 0; } PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val)); @@ -1514,12 +1380,12 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre return 1; } -////////////////////////////////////////////////////////// +/*************************************************/ -////////////////////////////////////////////////////////////////////////// +/***************************************************************/ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) { -// figo 20050523 marked thsi flag for can't compile for relesase +/* figo 20050523 marked this flag for can't compile for relesase */ #ifdef _DEBUG s32 rx_cal_reg[4]; u32 val; @@ -1528,37 +1394,34 @@ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) u8 result; PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration()\n")); -// a. Set RFIC to "RX calibration mode" - //; ----- Calibration (7). RX path IQ imbalance calibration loop - // 0x01 0xFFBFC2 ; 3FEFF ; Calibration (7a). enable RX IQ calibration loop circuits +/* a. Set RFIC to "RX calibration mode" */ + /* ; ----- Calibration (7). RX path IQ imbalance calibration loop */ + /* 0x01 0xFFBFC2 ; 3FEFF ; Calibration (7a). enable RX IQ calibration loop circuits */ phy_set_rf_data(phw_data, 1, (1<<24)|0xEFBFC2); - // 0x0B 0x1A01D6 ; 06817 ; Calibration (7b). enable RX I/Q cal loop SW1 circuit + /* 0x0B 0x1A01D6 ; 06817 ; Calibration (7b). enable RX I/Q cal loop SW1 circuits */ phy_set_rf_data(phw_data, 11, (11<<24)|0x1A05D6); - //0x05 0x24848A ; 09212 ; Calibration (7c). setting TX-VGA gain (TXGCH) to 2 --> to be optimized - phy_set_rf_data(phw_data, 5, (5<<24)| phw_data->txvga_setting_for_cal); - //0x06 0x06840C ; 01A10 ; Calibration (7d). RXGCH=00; RXGCL=010 000 (RXVGA) --> to be optimized + /* 0x05 0x24848A ; 09212 ; Calibration (7c). setting TX-VGA gain (TXGCH) to 2 --> to be optimized */ + phy_set_rf_data(phw_data, 5, (5<<24) | phw_data->txvga_setting_for_cal); + /* 0x06 0x06840C ; 01A10 ; Calibration (7d). RXGCH=00; RXGCL=010 000 (RXVGA) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x06834C); - //0x00 0xFFF1C0 ; 3F7C7 ; Calibration (7e). turn on IQ imbalance/Test mode + /* 0x00 0xFFF1C0 ; 3F7C7 ; Calibration (7e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFFF1C0); - // ; [BB-chip]: Calibration (7f). Send test pattern - // ; [BB-chip]: Calibration (7g). Search RXGCL optimal value - // ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table + /* ; [BB-chip]: Calibration (7f). Send test pattern */ + /* ; [BB-chip]: Calibration (7g). Search RXGCL optimal value */ + /* ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table */ result = _rx_iq_calibration_loop_winbond(phw_data, 12589, frequency); - if (result > 0) - { + if (result > 0) { _reset_rx_cal(phw_data); result = _rx_iq_calibration_loop_winbond(phw_data, 7943, frequency); - if (result > 0) - { + if (result > 0) { _reset_rx_cal(phw_data); result = _rx_iq_calibration_loop_winbond(phw_data, 5011, frequency); - if (result > 0) - { + if (result > 0) { PHY_DEBUG(("[CAL] ** <_rx_iq_calibration> **************\n")); PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION FAILURE !!\n")); PHY_DEBUG(("[CAL] **************************************\n")); @@ -1571,15 +1434,12 @@ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) hw_get_dxx_reg(phw_data, 0x54, &val); PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); - if (phw_data->revision == 0x2002) // 1st-cut - { + if (phw_data->revision == 0x2002) /* 1st-cut */{ rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12); rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8); rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4); rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F)); - } - else // 2nd-cut - { + } else /* 2nd-cut */{ rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); @@ -1594,7 +1454,7 @@ void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) } -//////////////////////////////////////////////////////////////////////// +/*******************************************************/ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) { u32 reg_mode_ctrl; @@ -1602,7 +1462,7 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) PHY_DEBUG(("[CAL] -> phy_calibration_winbond()\n")); - // 20040701 1.1.25.1000 kevin + /* 20040701 1.1.25.1000 kevin */ hw_get_cxx_reg(phw_data, 0x80, &mac_ctrl); hw_get_cxx_reg(phw_data, 0xE4, &rf_ctrl); hw_get_dxx_reg(phw_data, 0x58, &iq_alpha); @@ -1610,72 +1470,71 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) _rxadc_dc_offset_cancellation_winbond(phw_data, frequency); - //_txidac_dc_offset_cancellation_winbond(phw_data); - //_txqdac_dc_offset_cacellation_winbond(phw_data); + /* _txidac_dc_offset_cancellation_winbond(phw_data); */ + /* _txqdac_dc_offset_cacellation_winbond(phw_data); */ _tx_iq_calibration_winbond(phw_data); _rx_iq_calibration_winbond(phw_data, frequency); - //------------------------------------------------------------------------ + /*********************************************************************/ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); - reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE|MASK_CALIB_START); // set when finish + reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE|MASK_CALIB_START); /* set when finish */ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - // i. Set RFIC to "Normal mode" + /* i. Set RFIC to "Normal mode" */ hw_set_cxx_reg(phw_data, 0x80, mac_ctrl); hw_set_cxx_reg(phw_data, 0xE4, rf_ctrl); hw_set_dxx_reg(phw_data, 0x58, iq_alpha); - //------------------------------------------------------------------------ + /*********************************************************************/ phy_init_rf(phw_data); } -//=========================== -void phy_set_rf_data( struct hw_data * pHwData, u32 index, u32 value ) +/******************/ +void phy_set_rf_data(struct hw_data *pHwData, u32 index, u32 value) { - u32 ltmp=0; - - switch( pHwData->phy_type ) - { - case RF_MAXIM_2825: - case RF_MAXIM_V1: // 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) - ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 ); - break; - - case RF_MAXIM_2827: - ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 ); - break; - - case RF_MAXIM_2828: - ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 ); - break; - - case RF_MAXIM_2829: - ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 ); - break; - - case RF_AIROHA_2230: - case RF_AIROHA_2230S: // 20060420 Add this - ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( value, 20 ); - break; - - case RF_AIROHA_7230: - ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff); - break; - - case RF_WB_242: - case RF_WB_242_1: // 20060619.5 Add - ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( value, 24 ); - break; - } + u32 ltmpi = 0; + + switch (pHwData->phy_type) { + case RF_MAXIM_2825: + case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */ + ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); + break; + + case RF_MAXIM_2827: + ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); + break; + + case RF_MAXIM_2828: + ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); + break; + + case RF_MAXIM_2829: + ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); + break; + + case RF_AIROHA_2230: + case RF_AIROHA_2230S: /* 20060420 Add this */ + ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20); + break; + + case RF_AIROHA_7230: + ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff); + break; + + case RF_WB_242: + case RF_WB_242_1:/* 20060619.5 Add */ + ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24); + break; + } - Wb35Reg_WriteSync( pHwData, 0x0864, ltmp ); + Wb35Reg_WriteSync(pHwData, 0x0864, ltmp); } -// 20060717 modify as Bruce's mail +/* 20060717 modify as Bruce's mail */ unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) { int init_txvga = 0; @@ -1685,26 +1544,27 @@ unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) s32 iqcal_tone_q0; u32 sqsum; s32 iq_mag_0_tx; - u8 reg_state; - int current_txvga; + u8 reg_state; + int current_txvga; reg_state = 0; - for( init_txvga=0; init_txvga<10; init_txvga++) - { - current_txvga = ( 0x24C40A|(init_txvga<<6) ); - phy_set_rf_data(phw_data, 5, ((5<<24)|current_txvga) ); + for (init_txvga = 0; init_txvga < 10; init_txvga++) { + current_txvga = (0x24C40A|(init_txvga<<6)); + phy_set_rf_data(phw_data, 5, ((5<<24)|current_txvga)); phw_data->txvga_setting_for_cal = current_txvga; - msleep(30); // 20060612.1.a + msleep(30);/* 20060612.1.a */ - if( !hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl) ) // 20060718.1 modify + if (!hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl))/* 20060718.1 modify */ return false; PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); - // a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to - // enable "IQ alibration Mode II" + /* + * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to + * enable "IQ alibration Mode II" + */ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); reg_mode_ctrl &= ~MASK_IQCAL_MODE; reg_mode_ctrl |= (MASK_CALIB_START|0x02); @@ -1712,15 +1572,15 @@ unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); - udelay(1); // 20060612.1.a + udelay(1);/* 20060612.1.a */ - udelay(300); // 20060612.1.a + udelay(300);/* 20060612.1.a */ - // b. + /* b. */ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); - udelay(300); // 20060612.1.a + udelay(300);/* 20060612.1.a */ iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF); iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13); @@ -1731,23 +1591,18 @@ unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) iq_mag_0_tx = (s32) _sqrt(sqsum); PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx)); - if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 ) + if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750) break; - else if(iq_mag_0_tx > 1750) - { - init_txvga=-2; + else if (iq_mag_0_tx > 1750) { + init_txvga = -2; continue; - } - else + } else continue; } - if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 ) + if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750) return true; else return false; } - - - -- cgit v1.2.3 From c92069f3d74c9b62dcffb359a4ae00388290d338 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 19 May 2010 09:53:17 -0700 Subject: Staging: vt6655: use ETH_ZLEN macro instead of custom one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom minimum packet lenght definition MIN_PACKET_LEN by ETH_ZLEN from . Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/mib.c | 4 ++-- drivers/staging/vt6655/tether.h | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index 4ca7877075b2..2f390ab5ed9d 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -341,10 +341,10 @@ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, if (WLAN_GET_FC_MOREFRAG(pHeader->wFrameCtl)) pStatistic->dwRsrRxFragment++; - if (cbFrameLength < MIN_PACKET_LEN + 4) { + if (cbFrameLength < ETH_ZLEN + 4) { pStatistic->dwRsrRunt++; } - else if (cbFrameLength == MIN_PACKET_LEN + 4) { + else if (cbFrameLength == ETH_ZLEN + 4) { pStatistic->dwRsrRxFrmLen64++; } else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) { diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 3c9acd7903a8..99fdc032d47a 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -39,12 +39,6 @@ #define U_ETHER_ADDR_STR_LEN (ETH_ALEN * 2 + 1) // Ethernet address string length -#define MIN_DATA_LEN 46 // min data length - -#define MIN_PACKET_LEN (MIN_DATA_LEN + ETH_HLEN) - // 60 - // min total packet length (tx) - #define MAX_LOOKAHEAD_SIZE ETH_FRAME_LEN #define U_MULTI_ADDR_LEN 8 // multicast address length -- cgit v1.2.3 From 670ea81eadf68fa68023731e3f747fd6b0c61dd4 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 19 May 2010 11:30:51 -0700 Subject: Staging: vt6655: use is_multicast_ether_addr instead of custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom macro IS_MULTICAST_ADDRESS by is_multicast_ether_addr from . Remove linux/if_ether.h include as it is included in linux/etherdevice.h already. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/vt6655/dpc.c | 4 ++-- drivers/staging/vt6655/mib.c | 4 ++-- drivers/staging/vt6655/rxtx.c | 10 +++++----- drivers/staging/vt6655/tether.h | 5 +---- 5 files changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index e49bb258b5c3..24b6d4507db6 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -2307,7 +2307,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { spin_unlock_irq(&pDevice->lock); return 0; } - if (IS_MULTICAST_ADDRESS((PBYTE)(skb->data))) { + if (is_multicast_ether_addr((PBYTE)(skb->data))) { uNodeIndex = 0; bNodeExist = TRUE; if (pMgmt->sNodeDBTable[0].bPSEnable) { diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 6b758a8c1af3..addbd4d1989d 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -463,7 +463,7 @@ device_receive_frame ( return FALSE; } - if (!IS_MULTICAST_ADDRESS(pbyFrame) && !IS_BROADCAST_ADDRESS(pbyFrame)) { + if (!is_multicast_ether_addr(pbyFrame) && !IS_BROADCAST_ADDRESS(pbyFrame)) { if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) (skb->data + 4))) { pDevice->s802_11Counter.FrameDuplicateCount++; return FALSE; @@ -1460,7 +1460,7 @@ static BOOL s_bAPModeRxData ( if (FrameSize > CB_MAX_BUF_SIZE) return FALSE; // check DA - if(IS_MULTICAST_ADDRESS((PBYTE)(skb->data+cbHeaderOffset))) { + if(is_multicast_ether_addr((PBYTE)(skb->data+cbHeaderOffset))) { if (pMgmt->sNodeDBTable[0].bPSEnable) { skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz); diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index 2f390ab5ed9d..1300f06aae9a 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -475,7 +475,7 @@ STAvUpdateTDStatCounter ( pStatistic->ullTxBroadcastFrames[uIdx]++; pStatistic->ullTxBroadcastBytes[uIdx] += (ULONGLONG)cbFrameLength; } - else if (IS_MULTICAST_ADDRESS(pbyDestAddr)) { + else if (is_multicast_ether_addr(pbyDestAddr)) { pStatistic->ullTxMulticastFrames[uIdx]++; pStatistic->ullTxMulticastBytes[uIdx] += (ULONGLONG)cbFrameLength; } @@ -497,7 +497,7 @@ STAvUpdateTDStatCounter ( if (IS_BROADCAST_ADDRESS(pbyDestAddr)) pStatistic->dwTsrBroadcast[uIdx]++; - else if (IS_MULTICAST_ADDRESS(pbyDestAddr)) + else if (is_multicast_ether_addr(pbyDestAddr)) pStatistic->dwTsrMulticast[uIdx]++; else pStatistic->dwTsrDirected[uIdx]++; diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index a0445c3427ea..253ca249e3df 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1394,7 +1394,7 @@ s_cbFillTxBufHead ( if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { - if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; } @@ -2123,7 +2123,7 @@ vGenerateFIFOHeader ( if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { - if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); @@ -2424,7 +2424,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); - if (IS_MULTICAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0])) || + if (is_multicast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0])) || IS_BROADCAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; } @@ -2760,7 +2760,7 @@ cbGetFragCount ( if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { - if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; } @@ -2938,7 +2938,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDU pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); - if (IS_MULTICAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0])) || + if (is_multicast_ether_addr(&(p80211Header->sA3.abyAddr1[0])) || IS_BROADCAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; if (pDevice->bEnableHostWEP) { diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 99fdc032d47a..5365e7fadeab 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -29,7 +29,7 @@ #ifndef __TETHER_H__ #define __TETHER_H__ -#include +#include #include "ttype.h" /*--------------------- Export Definitions -------------------------*/ @@ -188,9 +188,6 @@ S802_11Header, *PS802_11Header; /*--------------------- Export Macros ------------------------------*/ // Frame type macro -#define IS_MULTICAST_ADDRESS(pbyEtherAddr) \ - ((*(PBYTE)(pbyEtherAddr) & 0x01) == 1) - #define IS_BROADCAST_ADDRESS(pbyEtherAddr) ( \ (*(PDWORD)(pbyEtherAddr) == 0xFFFFFFFFL) && \ (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0xFFFF) \ -- cgit v1.2.3 From ca9e12acda7ab451ab481d29911af7ee27c512cf Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 19 May 2010 11:30:52 -0700 Subject: Staging: vt6655: use is_broadcast_ether_addr instead of custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom macro IS_BROADCAST_ADDRESS by is_broadcast_ether_addr from . Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 2 +- drivers/staging/vt6655/dpc.c | 2 +- drivers/staging/vt6655/iwctl.c | 2 +- drivers/staging/vt6655/key.c | 2 +- drivers/staging/vt6655/mib.c | 4 ++-- drivers/staging/vt6655/rxtx.c | 10 +++++----- drivers/staging/vt6655/tether.h | 5 ----- drivers/staging/vt6655/wpactl.c | 4 ++-- 8 files changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 6312a55dab1a..0c27150ed47c 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -144,7 +144,7 @@ BYTE ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00}; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList BSSID[%02X %02X %02X-%02X %02X %02X]\n", *pbyDesireBSSID,*(pbyDesireBSSID+1),*(pbyDesireBSSID+2), *(pbyDesireBSSID+3),*(pbyDesireBSSID+4),*(pbyDesireBSSID+5)); - if ((!IS_BROADCAST_ADDRESS(pbyDesireBSSID)) && + if ((!is_broadcast_ether_addr(pbyDesireBSSID)) && (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)){ pbyBSSID = pbyDesireBSSID; } diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index addbd4d1989d..c82fc3101fa3 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -463,7 +463,7 @@ device_receive_frame ( return FALSE; } - if (!is_multicast_ether_addr(pbyFrame) && !IS_BROADCAST_ADDRESS(pbyFrame)) { + if (!is_multicast_ether_addr(pbyFrame) && !is_broadcast_ether_addr(pbyFrame)) { if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) (skb->data + 4))) { pDevice->s802_11Counter.FrameDuplicateCount++; return FALSE; diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index cf69034fc0f0..16632357d500 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -706,7 +706,7 @@ if (pMgmt->eScanState == WMAC_IS_SCANNING) { return rc; } //mike :add - if ((IS_BROADCAST_ADDRESS(pMgmt->abyDesireBSSID)) || + if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) || (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)){ PRINT_K("SIOCSIWAP:invalid desired BSSID return!\n"); return rc; diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index bfc5c509d902..474091c69047 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -371,7 +371,7 @@ BOOL KeybRemoveKey ( { int i; - if (IS_BROADCAST_ADDRESS(pbyBSSID)) { + if (is_broadcast_ether_addr(pbyBSSID)) { // dealte all key if ((dwKeyIndex & PAIRWISE_KEY) != 0) { for (i=0;iCustomStat.ullTsrAllOK = (pStatistic->ullTsrOK[TYPE_AC0DMA] + pStatistic->ullTsrOK[TYPE_TXDMA0]); // update counters in case that successful transmit - if (IS_BROADCAST_ADDRESS(pbyDestAddr)) { + if (is_broadcast_ether_addr(pbyDestAddr)) { pStatistic->ullTxBroadcastFrames[uIdx]++; pStatistic->ullTxBroadcastBytes[uIdx] += (ULONGLONG)cbFrameLength; } @@ -495,7 +495,7 @@ STAvUpdateTDStatCounter ( pStatistic->dwTsrACKData[uIdx]++; } - if (IS_BROADCAST_ADDRESS(pbyDestAddr)) + if (is_broadcast_ether_addr(pbyDestAddr)) pStatistic->dwTsrBroadcast[uIdx]++; else if (is_multicast_ether_addr(pbyDestAddr)) pStatistic->dwTsrMulticast[uIdx]++; diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 253ca249e3df..590fc7f7fcb5 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1395,7 +1395,7 @@ s_cbFillTxBufHead ( (pDevice->eOPMode == OP_MODE_AP)) { if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || - IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + is_broadcast_ether_addr(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; } else { @@ -2124,7 +2124,7 @@ vGenerateFIFOHeader ( if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || - IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + is_broadcast_ether_addr(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); } @@ -2425,7 +2425,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { if (is_multicast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0])) || - IS_BROADCAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0]))) { + is_broadcast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; } else { @@ -2761,7 +2761,7 @@ cbGetFragCount ( if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])) || - IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + is_broadcast_ether_addr(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; } else { @@ -2939,7 +2939,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDU if (is_multicast_ether_addr(&(p80211Header->sA3.abyAddr1[0])) || - IS_BROADCAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0]))) { + is_broadcast_ether_addr(&(p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; if (pDevice->bEnableHostWEP) { uNodeIndex = 0; diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 5365e7fadeab..e25ad4b47285 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -188,11 +188,6 @@ S802_11Header, *PS802_11Header; /*--------------------- Export Macros ------------------------------*/ // Frame type macro -#define IS_BROADCAST_ADDRESS(pbyEtherAddr) ( \ - (*(PDWORD)(pbyEtherAddr) == 0xFFFFFFFFL) && \ - (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0xFFFF) \ -) - #define IS_NULL_ADDRESS(pbyEtherAddr) ( \ (*(PDWORD)(pbyEtherAddr) == 0L) && \ (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0) \ diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 22c2fab3f328..3d1371239ce7 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -351,8 +351,8 @@ spin_lock_irq(&pDevice->lock); } // spin_lock_irq(&pDevice->lock); - if (IS_BROADCAST_ADDRESS(¶m->addr[0]) || (param->addr == NULL)) { - // If IS_BROADCAST_ADDRESS, set the key as every key entry's group key. + if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { + // If is_broadcast_ether_addr, set the key as every key entry's group key. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); if ((KeybSetAllGroupKey(&(pDevice->sKey), -- cgit v1.2.3 From 8b0591e5017ea2a78f5181fd136e1b281323e5a3 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 19 May 2010 11:30:53 -0700 Subject: Staging: vt6655: use is_zero_ether_addr instead of custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom macro IS_NULL_ADDRESS by is_zero_ether_addr from . Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 2 +- drivers/staging/vt6655/tether.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 7bc2d7654b07..de5f2ba2cf46 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1319,7 +1319,7 @@ BOOL CARDbSetBSSID(void *pDeviceHandler, PBYTE pbyBSSID, CARD_OP_MODE eOPMode) pDevice->byRxMode &= ~RCR_BSSID; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); } else { - if (IS_NULL_ADDRESS(pDevice->abyBSSID) == FALSE) { + if (is_zero_ether_addr(pDevice->abyBSSID) == FALSE) { MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID); pDevice->bBSSIDFilter = TRUE; pDevice->byRxMode |= RCR_BSSID; diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index e25ad4b47285..71ef0f1c898b 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -188,11 +188,6 @@ S802_11Header, *PS802_11Header; /*--------------------- Export Macros ------------------------------*/ // Frame type macro -#define IS_NULL_ADDRESS(pbyEtherAddr) ( \ - (*(PDWORD)(pbyEtherAddr) == 0L) && \ - (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0) \ -) - #define IS_ETH_ADDRESS_EQUAL(pbyAddr1, pbyAddr2) ( \ (*(PDWORD)(pbyAddr1) == *(PDWORD)(pbyAddr2)) && \ (*(PWORD)((PBYTE)(pbyAddr1) + 4) == \ -- cgit v1.2.3 From 2ef98c606516be4efb176c3c5e339b769ca1833a Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 19 May 2010 11:30:54 -0700 Subject: Staging: vt6655: use compare_ether_addr instead of custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom macro IS_ETH_ADDRESS_EQUAL by compare_ether_addr from . Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 8 ++++---- drivers/staging/vt6655/dpc.c | 6 +++--- drivers/staging/vt6655/iwctl.c | 4 ++-- drivers/staging/vt6655/key.c | 10 +++++----- drivers/staging/vt6655/tether.h | 7 ------- drivers/staging/vt6655/vntwifi.c | 2 +- drivers/staging/vt6655/wctl.c | 4 ++-- drivers/staging/vt6655/wmgr.c | 4 ++-- drivers/staging/vt6655/wpactl.c | 2 +- 9 files changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 0c27150ed47c..d07241af7c08 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -162,7 +162,7 @@ BYTE ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00}; if(pDevice->bLinkPass==FALSE) pCurrBSS->bSelected = FALSE; if ((pCurrBSS->bActive) && (pCurrBSS->bSelected == FALSE)) { - if (IS_ETH_ADDRESS_EQUAL(pCurrBSS->abyBSSID, pbyBSSID)) { + if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) { if (pSSID != NULL) { // compare ssid if ( !memcmp(pSSID->abySSID, @@ -293,7 +293,7 @@ BSSvClearBSSList( for (ii = 0; ii < MAX_BSS_NUM; ii++) { if (bKeepCurrBSSID) { if (pMgmt->sBSSList[ii].bActive && - IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) { + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) { // bKeepCurrBSSID = FALSE; continue; } @@ -338,7 +338,7 @@ BSSpAddrIsInBSSList( for (ii = 0; ii < MAX_BSS_NUM; ii++) { pBSSList = &(pMgmt->sBSSList[ii]); if (pBSSList->bActive) { - if (IS_ETH_ADDRESS_EQUAL(pBSSList->abyBSSID, abyBSSID)) { + if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) { // if (pSSID == NULL) // return pBSSList; if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){ @@ -775,7 +775,7 @@ BSSDBbIsSTAInNodeDB( // Index = 0 reserved for AP Node for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { - if (IS_ETH_ADDRESS_EQUAL(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) { + if (!compare_ether_addr(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) { *puNodeIndex = ii; return TRUE; } diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index c82fc3101fa3..535e033427a9 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -198,10 +198,10 @@ s_vProcessRxMACHeader ( }; pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize); - if (IS_ETH_ADDRESS_EQUAL(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { + if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { cbHeaderSize += 6; } - else if (IS_ETH_ADDRESS_EQUAL(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { + else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); if ((*pwType!= TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) { @@ -475,7 +475,7 @@ device_receive_frame ( s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader); // filter packet send from myself - if (IS_ETH_ADDRESS_EQUAL((PBYTE)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) + if (!compare_ether_addr((PBYTE)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) return FALSE; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index 16632357d500..00564535c9a3 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -717,7 +717,7 @@ if (pMgmt->eScanState == WMAC_IS_SCANNING) { UINT ii , uSameBssidNum=0; for (ii = 0; ii < MAX_BSS_NUM; ii++) { if (pMgmt->sBSSList[ii].bActive && - IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID,pMgmt->abyDesireBSSID)) { + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) { uSameBssidNum++; } } @@ -906,7 +906,7 @@ if (pMgmt->eScanState == WMAC_IS_SCANNING) { // by means of judging if there are two same BSSID exist in list ? for (ii = 0; ii < MAX_BSS_NUM; ii++) { if (pMgmt->sBSSList[ii].bActive && - IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { uSameBssidNum++; } } diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 474091c69047..f8527a704635 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -145,7 +145,7 @@ BOOL KeybGetKey ( *pKey = NULL; for (i=0;iKeyTable[i].bInUse == TRUE) && - IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if (dwKeyIndex == 0xFFFFFFFF) { if (pTable->KeyTable[i].PairwiseKey.bKeyValid == TRUE) { *pKey = &(pTable->KeyTable[i].PairwiseKey); @@ -216,7 +216,7 @@ BOOL KeybSetKey ( j = i; } if ((pTable->KeyTable[i].bInUse == TRUE) && - IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { // found table already exist if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key @@ -398,7 +398,7 @@ BOOL KeybRemoveKey ( for (i=0;iKeyTable[i].bInUse == TRUE) && - IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if ((dwKeyIndex & PAIRWISE_KEY) != 0) { pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; s_vCheckKeyTableValid(pTable, dwIoBase); @@ -445,7 +445,7 @@ BOOL KeybRemoveAllKey ( for (i=0;iKeyTable[i].bInUse == TRUE) && - IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; for(u=0;uKeyTable[i].GroupKey[u].bKeyValid = FALSE; @@ -529,7 +529,7 @@ BOOL KeybGetTransmitKey ( *pKey = NULL; for (i=0;iKeyTable[i].bInUse == TRUE) && - IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if (dwKeyType == PAIRWISE_KEY) { diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 71ef0f1c898b..d0183a25e651 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -186,13 +186,6 @@ typedef struct tagS802_11Header { S802_11Header, *PS802_11Header; /*--------------------- Export Macros ------------------------------*/ -// Frame type macro - -#define IS_ETH_ADDRESS_EQUAL(pbyAddr1, pbyAddr2) ( \ - (*(PDWORD)(pbyAddr1) == *(PDWORD)(pbyAddr2)) && \ - (*(PWORD)((PBYTE)(pbyAddr1) + 4) == \ - *(PWORD)((PBYTE)(pbyAddr2) + 4)) \ -) /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index b527a019188b..680c4962cd33 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -800,7 +800,7 @@ VNTWIFIbRadarPresent( (byChannel == (BYTE) pMgmt->uCurrChannel) && (pMgmt->bSwitchChannel != TRUE) && (pMgmt->b11hEnable == TRUE)) { - if (IS_ETH_ADDRESS_EQUAL(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) { + if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) { pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(BYTE) pMgmt->uCurrChannel); pMgmt->bSwitchChannel = TRUE; } diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c index 64a66b2f1fc5..e9c3a6e57a0d 100644 --- a/drivers/staging/vt6655/wctl.c +++ b/drivers/staging/vt6655/wctl.c @@ -78,7 +78,7 @@ BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) { pCacheEntry = &(pCache->asCacheEntry[uIndex]); if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) && - (IS_ETH_ADDRESS_EQUAL (&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) + (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) ) { /* Duplicate match */ return TRUE; @@ -114,7 +114,7 @@ UINT ii; for(ii=0;iicbDFCB;ii++) { if ((pDevice->sRxDFCB[ii].bInUse == TRUE) && - (IS_ETH_ADDRESS_EQUAL (&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) + (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) ) { // return(ii); diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 8af356fd139e..56e15a19675e 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -1769,7 +1769,7 @@ s_vMgrRxDeauthentication( vMgrDecodeDeauthen(&sFrame); DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason)))); // TODO: update BSS list for specific BSSID if pre-authentication case - if (IS_ETH_ADDRESS_EQUAL(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) { + if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) { if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) { pMgmt->sNodeDBTable[0].bActive = FALSE; pMgmt->eCurrMode = WMAC_MODE_STANDBY; @@ -3098,7 +3098,7 @@ s_vMgrSynchBSS ( // for (ii = 0; ii < MAX_BSS_NUM; ii++) { // if (pMgmt->sBSSList[ii].bActive && - // IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { + // !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { // uSameBssidNum++; // } // } diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 3d1371239ce7..4adc2f05be14 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -408,7 +408,7 @@ spin_lock_irq(&pDevice->lock); } else { // Key Table Full - if (IS_ETH_ADDRESS_EQUAL(¶m->addr[0], pDevice->abyBSSID)) { + if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); //spin_unlock_irq(&pDevice->lock); return -EINVAL; -- cgit v1.2.3 From 6b1e6b8f957386e60e3fac15a64518c8f7ce5a69 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Thu, 20 May 2010 11:08:55 -0700 Subject: Staging: vt6655: remove unused argument in ChannelValid function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 5 ++--- drivers/staging/vt6655/card.h | 2 +- drivers/staging/vt6655/wcmd.c | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index de5f2ba2cf46..f239920d7f23 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -440,8 +440,7 @@ s_vCaculateOFDMRParameter( /*--------------------- Export function -------------------------*/ /************************************************************************ * Country Channel Valid - * Input: CountryCode, ChannelNum - * ChanneIndex is defined as VT3253 MAC channel: + * Input: ChannelIndex is defined as VT3253 MAC channel: * 1 = 2.4G channel 1 * 2 = 2.4G channel 2 * ... @@ -458,7 +457,7 @@ s_vCaculateOFDMRParameter( ************************************************************************/ //2008-8-4 by chester BOOL -ChannelValid(UINT CountryCode, UINT ChannelIndex) +ChannelValid(UINT ChannelIndex) { BOOL bValid; diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 76313462cf76..d2207bfbe11f 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -86,7 +86,7 @@ typedef enum _CARD_OP_MODE { /*--------------------- Export Functions --------------------------*/ -BOOL ChannelValid(UINT CountryCode, UINT ChannelIndex); +BOOL ChannelValid(UINT ChannelIndex); void CARDvSetRSPINF(void *pDeviceHandler, CARD_PHY_TYPE ePHYType); void vUpdateIFS(void *pDeviceHandler); void CARDvUpdateBasicTopRate(void *pDeviceHandler); diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index 28665d870f59..c2bf287961a9 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -408,7 +408,7 @@ vCommandTimer ( } else { //2008-8-4 by chester - if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { + if (!ChannelValid(pMgmt->uScanChannel)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel); s_bCommandComplete(pDevice); return; @@ -441,7 +441,7 @@ vCommandTimer ( // printk("chester-ch=%d\n",pMgmt->uScanChannel); pMgmt->uScanChannel++; //2008-8-4 by chester - if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && + if (!ChannelValid(pMgmt->uScanChannel) && pMgmt->uScanChannel <= pDevice->byMaxChannel ){ pMgmt->uScanChannel=pDevice->byMaxChannel+1; pMgmt->eCommandState = WLAN_CMD_SCAN_END; -- cgit v1.2.3 From 8fee12e4d1fbf03a44594b4c3951cb0f86958d7a Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 21 May 2010 12:55:33 -0700 Subject: Staging: vt6655: remove double definition of Calcu_LinkQual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calcu_LinkQual is already defined a couple lines earlier. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/ttype.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 2921083a9f22..f436da04a3b0 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -65,10 +65,6 @@ typedef int BOOL; #define Calcu_LinkQual #endif -#ifndef Calcu_LinkQual -#define Calcu_LinkQual -#endif - /****** Simple typedefs ***************************************************/ /* These lines assume that your compiler's longs are 32 bits and -- cgit v1.2.3 From 8fa5dd133ed38cb412c42f7daca2f6de3fdbbce8 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 28 May 2010 09:17:44 -0700 Subject: Staging: vt6655: remove unused OUT definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/ttype.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index f436da04a3b0..0ee260c84794 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -33,10 +33,6 @@ /******* Common definitions and typedefs ***********************************/ -#ifndef OUT -#define OUT -#endif - #ifndef TxInSleep #define TxInSleep #endif -- cgit v1.2.3 From ec28c7fab4c5e5e5c168f0b48bc10bfc7f9896d5 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 28 May 2010 12:34:18 -0700 Subject: Staging: vt6655: remove I8 custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove custom macro for signed 8-bit integers. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 4 ++-- drivers/staging/vt6655/card.h | 4 ++-- drivers/staging/vt6655/device.h | 10 +++++----- drivers/staging/vt6655/ttype.h | 2 -- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index f239920d7f23..b972130f7e96 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -2095,7 +2095,7 @@ void CARDvSetPowerConstraint ( void *pDeviceHandler, BYTE byChannel, - I8 byPower + char byPower ) { PSDevice pDevice = (PSDevice) pDeviceHandler; @@ -2253,7 +2253,7 @@ CARDbySetSupportChannels ( * Return Value: none. * -*/ -I8 +char CARDbyGetTransmitPower ( void *pDeviceHandler ) diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index d2207bfbe11f..00dce0310b5d 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -189,7 +189,7 @@ void CARDvSetPowerConstraint ( void *pDeviceHandler, BYTE byChannel, - I8 byPower + char byPower ); void @@ -205,7 +205,7 @@ CARDbySetSupportChannels ( PBYTE pbyIEs ); -I8 +char CARDbyGetTransmitPower ( void *pDeviceHandler ); diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 40ee4e14237e..de1289196e74 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -693,13 +693,13 @@ typedef struct __device_info { BYTE byCCKPwr; BYTE byOFDMPwrG; BYTE byCurPwr; - I8 byCurPwrdBm; + char byCurPwrdBm; BYTE abyCCKPwrTbl[CB_MAX_CHANNEL_24G+1]; BYTE abyOFDMPwrTbl[CB_MAX_CHANNEL+1]; - I8 abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1]; - I8 abyOFDMDefaultPwr[CB_MAX_CHANNEL+1]; - I8 abyRegPwr[CB_MAX_CHANNEL+1]; - I8 abyLocalPwr[CB_MAX_CHANNEL+1]; + char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1]; + char abyOFDMDefaultPwr[CB_MAX_CHANNEL+1]; + char abyRegPwr[CB_MAX_CHANNEL+1]; + char abyLocalPwr[CB_MAX_CHANNEL+1]; // BaseBand Loopback Use diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 0ee260c84794..574edfe62281 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,8 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef signed char I8; /* 8-bit signed integer */ - typedef unsigned char U8; /* 8-bit unsigned integer */ typedef unsigned short U16; /* 16-bit unsigned integer */ typedef unsigned long U32; /* 32-bit unsigned integer */ -- cgit v1.2.3 From 737c3d708c845ab39bfeb1b656e51e84d5771035 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 28 May 2010 12:34:19 -0700 Subject: Staging: vt6655: remove U8 custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove custom macro for unsigned 8-bit integers. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/desc.h | 12 +++---- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/vt6655/iocmd.h | 66 ++++++++++++++++++------------------ drivers/staging/vt6655/mac.c | 2 +- drivers/staging/vt6655/ttype.h | 1 - 5 files changed, 41 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index cedb1e7df4fa..b4327c015e28 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -259,9 +259,9 @@ typedef struct tagRDES0 { union { volatile U16 f15Reserved; struct { - volatile U8 f8Reserved1; - volatile U8 f1Owner:1; - volatile U8 f7Reserved:7; + volatile u8 f8Reserved1; + volatile u8 f1Owner:1; + volatile u8 f7Reserved:7; } __attribute__ ((__packed__)); } __attribute__ ((__packed__)); } __attribute__ ((__packed__)) @@ -319,9 +319,9 @@ typedef struct tagTDES0 { union { volatile U16 f15Txtime; struct { - volatile U8 f8Reserved1; - volatile U8 f1Owner:1; - volatile U8 f7Reserved:7; + volatile u8 f8Reserved1; + volatile u8 f1Owner:1; + volatile u8 f7Reserved:7; } __attribute__ ((__packed__)); } __attribute__ ((__packed__)); } __attribute__ ((__packed__)) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 24b6d4507db6..12d1e8b8a0ee 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1151,7 +1151,7 @@ static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, static BOOL device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) { U16 pci_cmd; - U8 b; + u8 b; UINT cis_addr; #ifdef PLICE_DEBUG BYTE pci_config[256]; diff --git a/drivers/staging/vt6655/iocmd.h b/drivers/staging/vt6655/iocmd.h index 60c0a3623613..aedcefe4aac5 100644 --- a/drivers/staging/vt6655/iocmd.h +++ b/drivers/staging/vt6655/iocmd.h @@ -109,7 +109,7 @@ typedef enum tagWZONETYPE { // #pragma pack(1) typedef struct tagSCmdRequest { - U8 name[16]; + u8 name[16]; void *data; U16 wResult; U16 wCmdCode; @@ -121,7 +121,7 @@ typedef struct tagSCmdRequest { typedef struct tagSCmdScan { - U8 ssid[SSID_MAXLEN + 2]; + u8 ssid[SSID_MAXLEN + 2]; } SCmdScan, *PSCmdScan; @@ -134,7 +134,7 @@ typedef struct tagSCmdBSSJoin { U16 wBSSType; U16 wBBPType; - U8 ssid[SSID_MAXLEN + 2]; + u8 ssid[SSID_MAXLEN + 2]; U32 uChannel; BOOL bPSEnable; BOOL bShareKeyAuth; @@ -155,9 +155,9 @@ typedef struct tagSCmdZoneTypeSet { #ifdef WPA_SM_Transtatus typedef struct tagSWPAResult { char ifname[100]; - U8 proto; - U8 key_mgmt; - U8 eap_type; + u8 proto; + u8 key_mgmt; + u8 eap_type; BOOL authenticated; } SWPAResult, *PSWPAResult; #endif @@ -166,11 +166,11 @@ typedef struct tagSCmdStartAP { U16 wBSSType; U16 wBBPType; - U8 ssid[SSID_MAXLEN + 2]; + u8 ssid[SSID_MAXLEN + 2]; U32 uChannel; U32 uBeaconInt; BOOL bShareKeyAuth; - U8 byBasicRate; + u8 byBasicRate; } SCmdStartAP, *PSCmdStartAP; @@ -178,8 +178,8 @@ typedef struct tagSCmdStartAP { typedef struct tagSCmdSetWEP { BOOL bEnableWep; - U8 byKeyIndex; - U8 abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN]; + u8 byKeyIndex; + u8 abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN]; BOOL bWepKeyAvailable[WEP_NKEYS]; U32 auWepKeyLength[WEP_NKEYS]; @@ -190,13 +190,13 @@ typedef struct tagSCmdSetWEP { typedef struct tagSBSSIDItem { U32 uChannel; - U8 abyBSSID[BSSID_LEN]; - U8 abySSID[SSID_MAXLEN + 1]; + u8 abyBSSID[BSSID_LEN]; + u8 abySSID[SSID_MAXLEN + 1]; //2006-1116-01, by NomadZhao //U16 wBeaconInterval; //U16 wCapInfo; - //U8 byNetType; - U8 byNetType; + //u8 byNetType; + u8 byNetType; U16 wBeaconInterval; U16 wCapInfo; // for address of byNetType at align 4 @@ -217,9 +217,9 @@ typedef struct tagSCmdLinkStatus { BOOL bLink; U16 wBSSType; - U8 byState; - U8 abyBSSID[BSSID_LEN]; - U8 abySSID[SSID_MAXLEN + 2]; + u8 byState; + u8 abyBSSID[BSSID_LEN]; + u8 abySSID[SSID_MAXLEN + 2]; U32 uChannel; U32 uLinkRate; @@ -329,8 +329,8 @@ typedef struct tagSStatMIBCount { U32 dwCntRxFrmLength; U32 dwCntTxBufLength; - U8 abyCntRxPattern[16]; - U8 abyCntTxPattern[16]; + u8 abyCntRxPattern[16]; + u8 abyCntTxPattern[16]; // Software check.... U32 dwCntRxDataErr; // rx buffer data software compare CRC err count @@ -354,15 +354,15 @@ typedef struct tagSStatMIBCount { typedef struct tagSNodeItem { // STA info U16 wAID; - U8 abyMACAddr[6]; + u8 abyMACAddr[6]; U16 wTxDataRate; U16 wInActiveCount; U16 wEnQueueCnt; U16 wFlags; BOOL bPWBitOn; - U8 byKeyIndex; + u8 byKeyIndex; U16 wWepKeyLength; - U8 abyWepKey[WEP_KEYMAXLEN]; + u8 abyWepKey[WEP_KEYMAXLEN]; // Auto rate fallback vars BOOL bIsInFallback; U32 uTxFailures; @@ -419,24 +419,24 @@ enum { struct viawget_hostapd_param { U32 cmd; - U8 sta_addr[6]; + u8 sta_addr[6]; union { struct { U16 aid; U16 capability; - U8 tx_supp_rates; + u8 tx_supp_rates; } add_sta; struct { U32 inactive_sec; } get_info_sta; struct { - U8 alg; + u8 alg; U32 flags; U32 err; - U8 idx; - U8 seq[8]; + u8 idx; + u8 seq[8]; U16 key_len; - U8 key[0]; + u8 key[0]; } crypt; struct { U32 flags_and; @@ -445,19 +445,19 @@ struct viawget_hostapd_param { struct { U16 rid; U16 len; - U8 data[0]; + u8 data[0]; } rid; struct { - U8 len; - U8 data[0]; + u8 len; + u8 data[0]; } generic_elem; struct { U16 cmd; U16 reason_code; } mlme; struct { - U8 ssid_len; - U8 ssid[32]; + u8 ssid_len; + u8 ssid[32]; } scan_req; } u; }; diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index f1ef7da75c2b..eae881c5a9f9 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -1046,7 +1046,7 @@ void MACvInitialize (DWORD_PTR dwIoBase) //MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD); // wait until EEPROM loading complete //while (TRUE) { - // U8 u8Data; + // u8 u8Data; // VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &u8Data); // if ( !(u8Data & I2MCSR_AUTOLD)) // break; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 574edfe62281..105cabce97ab 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned char U8; /* 8-bit unsigned integer */ typedef unsigned short U16; /* 16-bit unsigned integer */ typedef unsigned long U32; /* 32-bit unsigned integer */ -- cgit v1.2.3 From c17ce8c21d809c62b427bf8e2d2672ebe0904fd2 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 28 May 2010 12:34:20 -0700 Subject: Staging: vt6655: remove U16 custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove custom macro for unsigned 16-bit integers. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/desc.h | 4 +-- drivers/staging/vt6655/device_main.c | 4 +-- drivers/staging/vt6655/iocmd.h | 50 ++++++++++++++++++------------------ drivers/staging/vt6655/ttype.h | 1 - 4 files changed, 29 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index b4327c015e28..d99b19a25b15 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -257,7 +257,7 @@ SRDES0; typedef struct tagRDES0 { volatile WORD wResCount; union { - volatile U16 f15Reserved; + volatile u16 f15Reserved; struct { volatile u8 f8Reserved1; volatile u8 f1Owner:1; @@ -317,7 +317,7 @@ typedef struct tagTDES0 { volatile BYTE byTSR0; volatile BYTE byTSR1; union { - volatile U16 f15Txtime; + volatile u16 f15Txtime; struct { volatile u8 f8Reserved1; volatile u8 f1Owner:1; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 12d1e8b8a0ee..06585c1d3c83 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1150,14 +1150,14 @@ static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, static BOOL device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) { - U16 pci_cmd; + u16 pci_cmd; u8 b; UINT cis_addr; #ifdef PLICE_DEBUG BYTE pci_config[256]; BYTE value =0x00; int ii,j; - U16 max_lat=0x0000; + u16 max_lat=0x0000; memset(pci_config,0x00,256); #endif diff --git a/drivers/staging/vt6655/iocmd.h b/drivers/staging/vt6655/iocmd.h index aedcefe4aac5..d61f596a394a 100644 --- a/drivers/staging/vt6655/iocmd.h +++ b/drivers/staging/vt6655/iocmd.h @@ -111,8 +111,8 @@ typedef enum tagWZONETYPE { typedef struct tagSCmdRequest { u8 name[16]; void *data; - U16 wResult; - U16 wCmdCode; + u16 wResult; + u16 wCmdCode; } SCmdRequest, *PSCmdRequest; // @@ -132,8 +132,8 @@ typedef struct tagSCmdScan { typedef struct tagSCmdBSSJoin { - U16 wBSSType; - U16 wBBPType; + u16 wBSSType; + u16 wBBPType; u8 ssid[SSID_MAXLEN + 2]; U32 uChannel; BOOL bPSEnable; @@ -164,8 +164,8 @@ typedef struct tagSWPAResult { typedef struct tagSCmdStartAP { - U16 wBSSType; - U16 wBBPType; + u16 wBSSType; + u16 wBBPType; u8 ssid[SSID_MAXLEN + 2]; U32 uChannel; U32 uBeaconInt; @@ -193,12 +193,12 @@ typedef struct tagSBSSIDItem { u8 abyBSSID[BSSID_LEN]; u8 abySSID[SSID_MAXLEN + 1]; //2006-1116-01, by NomadZhao - //U16 wBeaconInterval; - //U16 wCapInfo; + //u16 wBeaconInterval; + //u16 wCapInfo; //u8 byNetType; u8 byNetType; - U16 wBeaconInterval; - U16 wCapInfo; // for address of byNetType at align 4 + u16 wBeaconInterval; + u16 wCapInfo; // for address of byNetType at align 4 BOOL bWEPOn; U32 uRSSI; @@ -216,7 +216,7 @@ typedef struct tagSBSSIDList { typedef struct tagSCmdLinkStatus { BOOL bLink; - U16 wBSSType; + u16 wBSSType; u8 byState; u8 abyBSSID[BSSID_LEN]; u8 abySSID[SSID_MAXLEN + 2]; @@ -353,21 +353,21 @@ typedef struct tagSStatMIBCount { typedef struct tagSNodeItem { // STA info - U16 wAID; + u16 wAID; u8 abyMACAddr[6]; - U16 wTxDataRate; - U16 wInActiveCount; - U16 wEnQueueCnt; - U16 wFlags; + u16 wTxDataRate; + u16 wInActiveCount; + u16 wEnQueueCnt; + u16 wFlags; BOOL bPWBitOn; u8 byKeyIndex; - U16 wWepKeyLength; + u16 wWepKeyLength; u8 abyWepKey[WEP_KEYMAXLEN]; // Auto rate fallback vars BOOL bIsInFallback; U32 uTxFailures; U32 uTxAttempts; - U16 wFailureRatio; + u16 wFailureRatio; } SNodeItem; @@ -422,8 +422,8 @@ struct viawget_hostapd_param { u8 sta_addr[6]; union { struct { - U16 aid; - U16 capability; + u16 aid; + u16 capability; u8 tx_supp_rates; } add_sta; struct { @@ -435,7 +435,7 @@ struct viawget_hostapd_param { U32 err; u8 idx; u8 seq[8]; - U16 key_len; + u16 key_len; u8 key[0]; } crypt; struct { @@ -443,8 +443,8 @@ struct viawget_hostapd_param { U32 flags_or; } set_flags_sta; struct { - U16 rid; - U16 len; + u16 rid; + u16 len; u8 data[0]; } rid; struct { @@ -452,8 +452,8 @@ struct viawget_hostapd_param { u8 data[0]; } generic_elem; struct { - U16 cmd; - U16 reason_code; + u16 cmd; + u16 reason_code; } mlme; struct { u8 ssid_len; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 105cabce97ab..fd1efeb62e68 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned short U16; /* 16-bit unsigned integer */ typedef unsigned long U32; /* 32-bit unsigned integer */ -- cgit v1.2.3 From 902d2411298a6e0b8a473a0163aa4bf6d5c8a073 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Fri, 28 May 2010 12:34:21 -0700 Subject: Staging: vt6655: remove U32 custom macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove custom macro for unsigned 32-bit integers, replace by u32. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/desc.h | 12 +- drivers/staging/vt6655/device.h | 18 +-- drivers/staging/vt6655/device_main.c | 4 +- drivers/staging/vt6655/iocmd.h | 212 +++++++++++++++++------------------ drivers/staging/vt6655/iwctl.c | 2 +- drivers/staging/vt6655/ttype.h | 3 - 6 files changed, 124 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index d99b19a25b15..a16d2e0049dc 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -291,11 +291,11 @@ SRDES1; typedef struct tagSRxDesc { volatile SRDES0 m_rd0RD0; volatile SRDES1 m_rd1RD1; - volatile U32 buff_addr; - volatile U32 next_desc; + volatile u32 buff_addr; + volatile u32 next_desc; struct tagSRxDesc *next;//4 bytes volatile PDEVICE_RD_INFO pRDInfo;//4 bytes - volatile U32 Reserved[2];//8 bytes + volatile u32 Reserved[2];//8 bytes } __attribute__ ((__packed__)) SRxDesc, *PSRxDesc; typedef const SRxDesc *PCSRxDesc; @@ -378,11 +378,11 @@ static inline PDEVICE_TD_INFO alloc_td_info(void) { typedef struct tagSTxDesc { volatile STDES0 m_td0TD0; volatile STDES1 m_td1TD1; - volatile U32 buff_addr; - volatile U32 next_desc; + volatile u32 buff_addr; + volatile u32 next_desc; struct tagSTxDesc* next; //4 bytes volatile PDEVICE_TD_INFO pTDInfo;//4 bytes - volatile U32 Reserved[2];//8 bytes + volatile u32 Reserved[2];//8 bytes } __attribute__ ((__packed__)) STxDesc, *PSTxDesc; typedef const STxDesc *PCSTxDesc; diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index de1289196e74..0766a917237a 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -291,7 +291,7 @@ typedef struct __chip_info_tbl{ char* name; int io_size; int nTxQueue; - U32 flags; + u32 flags; } CHIP_INFO, *PCHIP_INFO; @@ -386,7 +386,7 @@ typedef struct __device_opt { int short_retry; int long_retry; int bbp_type; - U32 flags; + u32 flags; } OPTIONS, *POPTIONS; @@ -423,11 +423,11 @@ typedef struct __device_info { CHIP_TYPE chip_id; - U32 PortOffset; + u32 PortOffset; DWORD dwIsr; - U32 memaddr; - U32 ioaddr; - U32 io_size; + u32 memaddr; + u32 ioaddr; + u32 io_size; BYTE byRevId; WORD SubSystemID; @@ -454,9 +454,9 @@ typedef struct __device_info { OPTIONS sOpts; - U32 flags; + u32 flags; - U32 rx_buf_sz; + u32 rx_buf_sz; int multicast_limit; BYTE byRxMode; @@ -472,7 +472,7 @@ typedef struct __device_info { //PLICE_DEBUG <- - U32 rx_bytes; + u32 rx_bytes; // Version control BYTE byLocalID; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 06585c1d3c83..38f93d6041f0 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -384,7 +384,7 @@ device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* } static void -device_set_bool_opt(unsigned int *opt, int val,BOOL def,U32 flag, char* name,char* devname) { +device_set_bool_opt(unsigned int *opt, int val,BOOL def,u32 flag, char* name,char* devname) { (*opt)&=(~flag); if (val==-1) *opt|=(def ? flag : 0); @@ -976,7 +976,7 @@ device_found1(struct pci_dev *pcid, const struct pci_device_id *ent) printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n",pDevice->memaddr,pDevice->ioaddr,pDevice->io_size); { int i; - U32 bar,len; + u32 bar,len; u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, diff --git a/drivers/staging/vt6655/iocmd.h b/drivers/staging/vt6655/iocmd.h index d61f596a394a..3deaafae7df1 100644 --- a/drivers/staging/vt6655/iocmd.h +++ b/drivers/staging/vt6655/iocmd.h @@ -135,7 +135,7 @@ typedef struct tagSCmdBSSJoin { u16 wBSSType; u16 wBBPType; u8 ssid[SSID_MAXLEN + 2]; - U32 uChannel; + u32 uChannel; BOOL bPSEnable; BOOL bShareKeyAuth; @@ -167,8 +167,8 @@ typedef struct tagSCmdStartAP { u16 wBSSType; u16 wBBPType; u8 ssid[SSID_MAXLEN + 2]; - U32 uChannel; - U32 uBeaconInt; + u32 uChannel; + u32 uBeaconInt; BOOL bShareKeyAuth; u8 byBasicRate; @@ -181,7 +181,7 @@ typedef struct tagSCmdSetWEP { u8 byKeyIndex; u8 abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN]; BOOL bWepKeyAvailable[WEP_NKEYS]; - U32 auWepKeyLength[WEP_NKEYS]; + u32 auWepKeyLength[WEP_NKEYS]; } SCmdSetWEP, *PSCmdSetWEP; @@ -189,7 +189,7 @@ typedef struct tagSCmdSetWEP { typedef struct tagSBSSIDItem { - U32 uChannel; + u32 uChannel; u8 abyBSSID[BSSID_LEN]; u8 abySSID[SSID_MAXLEN + 1]; //2006-1116-01, by NomadZhao @@ -201,14 +201,14 @@ typedef struct tagSBSSIDItem { u16 wCapInfo; // for address of byNetType at align 4 BOOL bWEPOn; - U32 uRSSI; + u32 uRSSI; } SBSSIDItem; typedef struct tagSBSSIDList { - U32 uItem; + u32 uItem; SBSSIDItem sBSSIDList[0]; } SBSSIDList, *PSBSSIDList; @@ -220,8 +220,8 @@ typedef struct tagSCmdLinkStatus { u8 byState; u8 abyBSSID[BSSID_LEN]; u8 abySSID[SSID_MAXLEN + 2]; - U32 uChannel; - U32 uLinkRate; + u32 uChannel; + u32 uLinkRate; } SCmdLinkStatus, *PSCmdLinkStatus; @@ -229,18 +229,18 @@ typedef struct tagSCmdLinkStatus { // 802.11 counter // typedef struct tagSDot11MIBCount { - U32 TransmittedFragmentCount; - U32 MulticastTransmittedFrameCount; - U32 FailedCount; - U32 RetryCount; - U32 MultipleRetryCount; - U32 RTSSuccessCount; - U32 RTSFailureCount; - U32 ACKFailureCount; - U32 FrameDuplicateCount; - U32 ReceivedFragmentCount; - U32 MulticastReceivedFrameCount; - U32 FCSErrorCount; + u32 TransmittedFragmentCount; + u32 MulticastTransmittedFrameCount; + u32 FailedCount; + u32 RetryCount; + u32 MultipleRetryCount; + u32 RTSSuccessCount; + u32 RTSFailureCount; + u32 ACKFailureCount; + u32 FrameDuplicateCount; + u32 ReceivedFragmentCount; + u32 MulticastReceivedFrameCount; + u32 FCSErrorCount; } SDot11MIBCount, *PSDot11MIBCount; @@ -252,102 +252,102 @@ typedef struct tagSStatMIBCount { // // ISR status count // - U32 dwIsrTx0OK; - U32 dwIsrTx1OK; - U32 dwIsrBeaconTxOK; - U32 dwIsrRxOK; - U32 dwIsrTBTTInt; - U32 dwIsrSTIMERInt; - U32 dwIsrUnrecoverableError; - U32 dwIsrSoftInterrupt; - U32 dwIsrRxNoBuf; + u32 dwIsrTx0OK; + u32 dwIsrTx1OK; + u32 dwIsrBeaconTxOK; + u32 dwIsrRxOK; + u32 dwIsrTBTTInt; + u32 dwIsrSTIMERInt; + u32 dwIsrUnrecoverableError; + u32 dwIsrSoftInterrupt; + u32 dwIsrRxNoBuf; ///////////////////////////////////// - U32 dwIsrUnknown; // unknown interrupt count + u32 dwIsrUnknown; // unknown interrupt count // RSR status count // - U32 dwRsrFrmAlgnErr; - U32 dwRsrErr; - U32 dwRsrCRCErr; - U32 dwRsrCRCOk; - U32 dwRsrBSSIDOk; - U32 dwRsrADDROk; - U32 dwRsrICVOk; - U32 dwNewRsrShortPreamble; - U32 dwRsrLong; - U32 dwRsrRunt; - - U32 dwRsrRxControl; - U32 dwRsrRxData; - U32 dwRsrRxManage; - - U32 dwRsrRxPacket; - U32 dwRsrRxOctet; - U32 dwRsrBroadcast; - U32 dwRsrMulticast; - U32 dwRsrDirected; + u32 dwRsrFrmAlgnErr; + u32 dwRsrErr; + u32 dwRsrCRCErr; + u32 dwRsrCRCOk; + u32 dwRsrBSSIDOk; + u32 dwRsrADDROk; + u32 dwRsrICVOk; + u32 dwNewRsrShortPreamble; + u32 dwRsrLong; + u32 dwRsrRunt; + + u32 dwRsrRxControl; + u32 dwRsrRxData; + u32 dwRsrRxManage; + + u32 dwRsrRxPacket; + u32 dwRsrRxOctet; + u32 dwRsrBroadcast; + u32 dwRsrMulticast; + u32 dwRsrDirected; // 64-bit OID - U32 ullRsrOK; + u32 ullRsrOK; // for some optional OIDs (64 bits) and DMI support - U32 ullRxBroadcastBytes; - U32 ullRxMulticastBytes; - U32 ullRxDirectedBytes; - U32 ullRxBroadcastFrames; - U32 ullRxMulticastFrames; - U32 ullRxDirectedFrames; - - U32 dwRsrRxFragment; - U32 dwRsrRxFrmLen64; - U32 dwRsrRxFrmLen65_127; - U32 dwRsrRxFrmLen128_255; - U32 dwRsrRxFrmLen256_511; - U32 dwRsrRxFrmLen512_1023; - U32 dwRsrRxFrmLen1024_1518; + u32 ullRxBroadcastBytes; + u32 ullRxMulticastBytes; + u32 ullRxDirectedBytes; + u32 ullRxBroadcastFrames; + u32 ullRxMulticastFrames; + u32 ullRxDirectedFrames; + + u32 dwRsrRxFragment; + u32 dwRsrRxFrmLen64; + u32 dwRsrRxFrmLen65_127; + u32 dwRsrRxFrmLen128_255; + u32 dwRsrRxFrmLen256_511; + u32 dwRsrRxFrmLen512_1023; + u32 dwRsrRxFrmLen1024_1518; // TSR0,1 status count // - U32 dwTsrTotalRetry[2]; // total collision retry count - U32 dwTsrOnceRetry[2]; // this packet only occur one collision - U32 dwTsrMoreThanOnceRetry[2]; // this packet occur more than one collision - U32 dwTsrRetry[2]; // this packet has ever occur collision, + u32 dwTsrTotalRetry[2]; // total collision retry count + u32 dwTsrOnceRetry[2]; // this packet only occur one collision + u32 dwTsrMoreThanOnceRetry[2]; // this packet occur more than one collision + u32 dwTsrRetry[2]; // this packet has ever occur collision, // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0) - U32 dwTsrACKData[2]; - U32 dwTsrErr[2]; - U32 dwAllTsrOK[2]; - U32 dwTsrRetryTimeout[2]; - U32 dwTsrTransmitTimeout[2]; - - U32 dwTsrTxPacket[2]; - U32 dwTsrTxOctet[2]; - U32 dwTsrBroadcast[2]; - U32 dwTsrMulticast[2]; - U32 dwTsrDirected[2]; + u32 dwTsrACKData[2]; + u32 dwTsrErr[2]; + u32 dwAllTsrOK[2]; + u32 dwTsrRetryTimeout[2]; + u32 dwTsrTransmitTimeout[2]; + + u32 dwTsrTxPacket[2]; + u32 dwTsrTxOctet[2]; + u32 dwTsrBroadcast[2]; + u32 dwTsrMulticast[2]; + u32 dwTsrDirected[2]; // RD/TD count - U32 dwCntRxFrmLength; - U32 dwCntTxBufLength; + u32 dwCntRxFrmLength; + u32 dwCntTxBufLength; - u8 abyCntRxPattern[16]; - u8 abyCntTxPattern[16]; + u8 abyCntRxPattern[16]; + u8 abyCntTxPattern[16]; // Software check.... - U32 dwCntRxDataErr; // rx buffer data software compare CRC err count - U32 dwCntDecryptErr; // rx buffer data software compare CRC err count - U32 dwCntRxICVErr; // rx buffer data software compare CRC err count - U32 idxRxErrorDesc; // index for rx data error RD + u32 dwCntRxDataErr; // rx buffer data software compare CRC err count + u32 dwCntDecryptErr; // rx buffer data software compare CRC err count + u32 dwCntRxICVErr; // rx buffer data software compare CRC err count + u32 idxRxErrorDesc; // index for rx data error RD // 64-bit OID - U32 ullTsrOK[2]; + u32 ullTsrOK[2]; // for some optional OIDs (64 bits) and DMI support - U32 ullTxBroadcastFrames[2]; - U32 ullTxMulticastFrames[2]; - U32 ullTxDirectedFrames[2]; - U32 ullTxBroadcastBytes[2]; - U32 ullTxMulticastBytes[2]; - U32 ullTxDirectedBytes[2]; + u32 ullTxBroadcastFrames[2]; + u32 ullTxMulticastFrames[2]; + u32 ullTxDirectedFrames[2]; + u32 ullTxBroadcastBytes[2]; + u32 ullTxMulticastBytes[2]; + u32 ullTxDirectedBytes[2]; } SStatMIBCount, *PSStatMIBCount; @@ -365,8 +365,8 @@ typedef struct tagSNodeItem { u8 abyWepKey[WEP_KEYMAXLEN]; // Auto rate fallback vars BOOL bIsInFallback; - U32 uTxFailures; - U32 uTxAttempts; + u32 uTxFailures; + u32 uTxAttempts; u16 wFailureRatio; } SNodeItem; @@ -374,7 +374,7 @@ typedef struct tagSNodeItem { typedef struct tagSNodeList { - U32 uItem; + u32 uItem; SNodeItem sNodeList[0]; } SNodeList, *PSNodeList; @@ -383,7 +383,7 @@ typedef struct tagSNodeList { typedef struct tagSCmdValue { - U32 dwValue; + u32 dwValue; } SCmdValue, *PSCmdValue; @@ -418,7 +418,7 @@ enum { struct viawget_hostapd_param { - U32 cmd; + u32 cmd; u8 sta_addr[6]; union { struct { @@ -427,20 +427,20 @@ struct viawget_hostapd_param { u8 tx_supp_rates; } add_sta; struct { - U32 inactive_sec; + u32 inactive_sec; } get_info_sta; struct { u8 alg; - U32 flags; - U32 err; + u32 flags; + u32 err; u8 idx; u8 seq[8]; u16 key_len; u8 key[0]; } crypt; struct { - U32 flags_and; - U32 flags_or; + u32 flags_and; + u32 flags_or; } set_flags_sta; struct { u16 rid; diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index 00564535c9a3..f778e7d670cc 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -116,7 +116,7 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.discard.nwid = 0; pDevice->wstats.discard.code = 0; pDevice->wstats.discard.fragment = 0; - pDevice->wstats.discard.retries = (U32)pDevice->scStatistic.dwTsrErr; + pDevice->wstats.discard.retries = (u32)pDevice->scStatistic.dwTsrErr; pDevice->wstats.discard.misc = 0; pDevice->wstats.miss.beacon = 0; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index fd1efeb62e68..4974703bab9d 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,9 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned long U32; /* 32-bit unsigned integer */ - - typedef char CHAR; typedef signed short SHORT; typedef signed int INT; -- cgit v1.2.3 From 5a4197bdda7914558fdc24f63d4ed6c64c5e54b3 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Tue, 1 Jun 2010 12:38:54 -0700 Subject: Staging: vt6655: removed custom CHAR typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/country.h | 2 +- drivers/staging/vt6655/device.h | 4 ++-- drivers/staging/vt6655/ttype.h | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/country.h b/drivers/staging/vt6655/country.h index 2005d2768680..3206feec8b34 100644 --- a/drivers/staging/vt6655/country.h +++ b/drivers/staging/vt6655/country.h @@ -162,7 +162,7 @@ typedef enum _COUNTRY_CODE { typedef struct tagSCountryTable { BYTE byChannelCountryCode; /* The country code */ - CHAR chCountryCode[2]; + char chCountryCode[2]; BYTE bChannelIdxList[CB_MAX_CHANNEL]; /* Available channels Index */ BYTE byPower[CB_MAX_CHANNEL]; } SCountryTable, *PSCountryTable; diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 0766a917237a..4ea94a7d5ff5 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -686,8 +686,8 @@ typedef struct __device_info { SHORT sPSetPointOFDMA; LONG lPFormulaOffset; SHORT sPThreshold; - CHAR cAdjustStep; - CHAR cMinTxAGC; + char cAdjustStep; + char cMinTxAGC; // For RF Power table BYTE byCCKPwr; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 4974703bab9d..1be30d8108a7 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef char CHAR; typedef signed short SHORT; typedef signed int INT; typedef signed long LONG; -- cgit v1.2.3 From 0c93a98a0e9073e0ffa7aea1e515a5e146e798a7 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Tue, 1 Jun 2010 12:38:55 -0700 Subject: Staging: vt6655: removed custom SHORT typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device.h | 8 ++++---- drivers/staging/vt6655/ttype.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 4ea94a7d5ff5..5f4efb5904db 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -681,11 +681,11 @@ typedef struct __device_info { // For Auto Power Tunning BYTE byAutoPwrTunning; - SHORT sPSetPointCCK; - SHORT sPSetPointOFDMG; - SHORT sPSetPointOFDMA; + short sPSetPointCCK; + short sPSetPointOFDMG; + short sPSetPointOFDMA; LONG lPFormulaOffset; - SHORT sPThreshold; + short sPThreshold; char cAdjustStep; char cMinTxAGC; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 1be30d8108a7..52f1a0c2adc7 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef signed short SHORT; typedef signed int INT; typedef signed long LONG; -- cgit v1.2.3 From 7ca3019525e6e3ba727e36dfdc07d8e8d487a5e2 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Tue, 1 Jun 2010 12:38:56 -0700 Subject: Staging: vt6655: remove custom INT typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 2 +- drivers/staging/vt6655/device_main.c | 38 ++++++++++++++++++------------------ drivers/staging/vt6655/dpc.c | 16 +++++++-------- drivers/staging/vt6655/mib.c | 26 ++++++++++++------------ drivers/staging/vt6655/ttype.h | 1 - drivers/staging/vt6655/wmgr.c | 2 +- 6 files changed, 42 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index b972130f7e96..f6ecbadc7f36 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -2362,7 +2362,7 @@ CARDbyAutoChannelSelect( // PSDevice pDevice = (PSDevice) pDeviceHandler; UINT ii = 0; BYTE byOptionChannel = 0; - INT aiWeight[CB_MAX_CHANNEL_24G+1] = {-1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + int aiWeight[CB_MAX_CHANNEL_24G+1] = {-1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; if (ePHYType == PHY_TYPE_11A) { for(ii=CB_MAX_CHANNEL_24G+1;ii<=CB_MAX_CHANNEL;ii++) { diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 38f93d6041f0..3c1ae3962173 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -464,18 +464,18 @@ pDevice->bUpdateBBVGA = TRUE; pDevice->byPreambleType = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uChannel= %d\n",(INT)pDevice->uChannel); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byOpMode= %d\n",(INT)pDevice->byOpMode); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ePSMode= %d\n",(INT)pDevice->ePSMode); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" wRTSThreshold= %d\n",(INT)pDevice->wRTSThreshold); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortRetryLimit= %d\n",(INT)pDevice->byShortRetryLimit); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byLongRetryLimit= %d\n",(INT)pDevice->byLongRetryLimit); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byPreambleType= %d\n",(INT)pDevice->byPreambleType); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortPreamble= %d\n",(INT)pDevice->byShortPreamble); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uConnectionRate= %d\n",(INT)pDevice->uConnectionRate); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byBBType= %d\n",(INT)pDevice->byBBType); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->b11hEnable= %d\n",(INT)pDevice->b11hEnable); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->bDiversityRegCtlON= %d\n",(INT)pDevice->bDiversityRegCtlON); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uChannel= %d\n",(int)pDevice->uChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byOpMode= %d\n",(int)pDevice->byOpMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ePSMode= %d\n",(int)pDevice->ePSMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" wRTSThreshold= %d\n",(int)pDevice->wRTSThreshold); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortRetryLimit= %d\n",(int)pDevice->byShortRetryLimit); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byLongRetryLimit= %d\n",(int)pDevice->byLongRetryLimit); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byPreambleType= %d\n",(int)pDevice->byPreambleType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortPreamble= %d\n",(int)pDevice->byShortPreamble); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uConnectionRate= %d\n",(int)pDevice->uConnectionRate); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byBBType= %d\n",(int)pDevice->byBBType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->b11hEnable= %d\n",(int)pDevice->b11hEnable); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->bDiversityRegCtlON= %d\n",(int)pDevice->bDiversityRegCtlON); } static void s_vCompleteCurrentMeasure (PSDevice pDevice, BYTE byResult) @@ -530,7 +530,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) BYTE byValue1; BYTE byCCKPwrdBm = 0; BYTE byOFDMPwrdBm = 0; - INT zonetype=0; + int zonetype=0; PSMgmtObject pMgmt = &(pDevice->sMgmtObj); MACbShutdown(pDevice->PortOffset); BBvSoftwareReset(pDevice->PortOffset); @@ -1710,7 +1710,7 @@ static int device_tx_srv(PSDevice pDevice, UINT uIdx) { if ( !(byTsr1 & TSR1_TERR)) { if (byTsr0 != 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n", - (INT)uIdx, byTsr1, byTsr0); + (int)uIdx, byTsr1, byTsr0); } if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) { pDevice->s802_11Counter.TransmittedFragmentCount ++; @@ -1720,7 +1720,7 @@ static int device_tx_srv(PSDevice pDevice, UINT uIdx) { } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n", - (INT)uIdx, byTsr1, byTsr0); + (int)uIdx, byTsr1, byTsr0); pStats->tx_errors++; pStats->tx_dropped++; } @@ -1742,11 +1742,11 @@ static int device_tx_srv(PSDevice pDevice, UINT uIdx) { if (byTsr1 & TSR1_TERR) { if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", - (INT)uIdx, byTsr1, byTsr0); + (int)uIdx, byTsr1, byTsr0); } // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", -// (INT)uIdx, byTsr1, byTsr0); +// (int)uIdx, byTsr1, byTsr0); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) { @@ -1763,7 +1763,7 @@ static int device_tx_srv(PSDevice pDevice, UINT uIdx) { pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n" - ,(INT)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt); + ,(int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt); pStats->tx_errors--; pStats->tx_dropped--; } @@ -1844,7 +1844,7 @@ void InitRxManagementQueue(PSDevice pDevice) //PLICE_DEBUG -> -INT MlmeThread( +int MlmeThread( void * Context) { PSDevice pDevice = (PSDevice) Context; diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 535e033427a9..e00999fb8107 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -101,7 +101,7 @@ s_vProcessRxMACHeader ( static BOOL s_bAPModeRxCtl( PSDevice pDevice, PBYTE pbyFrame, - INT iSANodeIndex + int iSANodeIndex ); @@ -111,8 +111,8 @@ static BOOL s_bAPModeRxData ( struct sk_buff* skb, UINT FrameSize, UINT cbHeaderOffset, - INT iSANodeIndex, - INT iDANodeIndex + int iSANodeIndex, + int iDANodeIndex ); @@ -360,8 +360,8 @@ device_receive_frame ( UINT cbHeaderOffset; UINT FrameSize; WORD wEtherType = 0; - INT iSANodeIndex = -1; - INT iDANodeIndex = -1; + int iSANodeIndex = -1; + int iDANodeIndex = -1; UINT ii; UINT cbIVOffset; BOOL bExtIV = FALSE; @@ -1041,7 +1041,7 @@ device_receive_frame ( static BOOL s_bAPModeRxCtl ( PSDevice pDevice, PBYTE pbyFrame, - INT iSANodeIndex + int iSANodeIndex ) { PS802_11Header p802_11Header; @@ -1444,8 +1444,8 @@ static BOOL s_bAPModeRxData ( struct sk_buff* skb, UINT FrameSize, UINT cbHeaderOffset, - INT iSANodeIndex, - INT iDANodeIndex + int iSANodeIndex, + int iDANodeIndex ) { PSMgmtObject pMgmt = pDevice->pMgmt; diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index 7f7dc7e7e247..b4e916f2c650 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -212,87 +212,87 @@ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr11MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"11M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr11M, (INT)pStatistic->CustomStat.ullRsr11MCRCOk, byRSR); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"11M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr11M, (int)pStatistic->CustomStat.ullRsr11MCRCOk, byRSR); } else if(byRxRate==11) { pStatistic->CustomStat.ullRsr5M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr5MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 5M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr5M, (INT)pStatistic->CustomStat.ullRsr5MCRCOk, byRSR); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 5M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr5M, (int)pStatistic->CustomStat.ullRsr5MCRCOk, byRSR); } else if(byRxRate==4) { pStatistic->CustomStat.ullRsr2M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr2MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 2M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr2M, (INT)pStatistic->CustomStat.ullRsr2MCRCOk, byRSR); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 2M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr2M, (int)pStatistic->CustomStat.ullRsr2MCRCOk, byRSR); } else if(byRxRate==2){ pStatistic->CustomStat.ullRsr1M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr1MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 1M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr1M, (INT)pStatistic->CustomStat.ullRsr1MCRCOk, byRSR); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 1M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr1M, (int)pStatistic->CustomStat.ullRsr1MCRCOk, byRSR); } else if(byRxRate==12){ pStatistic->CustomStat.ullRsr6M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr6MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 6M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr6M, (INT)pStatistic->CustomStat.ullRsr6MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 6M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr6M, (int)pStatistic->CustomStat.ullRsr6MCRCOk); } else if(byRxRate==18){ pStatistic->CustomStat.ullRsr9M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr9MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 9M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr9M, (INT)pStatistic->CustomStat.ullRsr9MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 9M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr9M, (int)pStatistic->CustomStat.ullRsr9MCRCOk); } else if(byRxRate==24){ pStatistic->CustomStat.ullRsr12M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr12MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"12M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr12M, (INT)pStatistic->CustomStat.ullRsr12MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"12M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr12M, (int)pStatistic->CustomStat.ullRsr12MCRCOk); } else if(byRxRate==36){ pStatistic->CustomStat.ullRsr18M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr18MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"18M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr18M, (INT)pStatistic->CustomStat.ullRsr18MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"18M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr18M, (int)pStatistic->CustomStat.ullRsr18MCRCOk); } else if(byRxRate==48){ pStatistic->CustomStat.ullRsr24M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr24MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"24M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr24M, (INT)pStatistic->CustomStat.ullRsr24MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"24M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr24M, (int)pStatistic->CustomStat.ullRsr24MCRCOk); } else if(byRxRate==72){ pStatistic->CustomStat.ullRsr36M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr36MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"36M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr36M, (INT)pStatistic->CustomStat.ullRsr36MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"36M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr36M, (int)pStatistic->CustomStat.ullRsr36MCRCOk); } else if(byRxRate==96){ pStatistic->CustomStat.ullRsr48M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr48MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"48M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr48M, (INT)pStatistic->CustomStat.ullRsr48MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"48M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr48M, (int)pStatistic->CustomStat.ullRsr48MCRCOk); } else if(byRxRate==108){ pStatistic->CustomStat.ullRsr54M++; if(byRSR & RSR_CRCOK) { pStatistic->CustomStat.ullRsr54MCRCOk++; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"54M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr54M, (INT)pStatistic->CustomStat.ullRsr54MCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"54M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr54M, (int)pStatistic->CustomStat.ullRsr54MCRCOk); } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown: Total[%d], CRCOK[%d]\n", (INT)pStatistic->dwRsrRxPacket+1, (INT)pStatistic->dwRsrCRCOk); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown: Total[%d], CRCOK[%d]\n", (int)pStatistic->dwRsrRxPacket+1, (int)pStatistic->dwRsrCRCOk); } if (byRSR & RSR_BSSIDOK) diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 52f1a0c2adc7..9ccef04cab59 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef signed int INT; typedef signed long LONG; typedef unsigned char UCHAR; diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 56e15a19675e..d9980f17055b 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -3077,7 +3077,7 @@ s_vMgrSynchBSS ( pMgmt->uCurrChannel = pCurr->uChannel; pMgmt->eCurrentPHYMode = ePhyType; pMgmt->byERPContext = pCurr->sERP.byERP; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:Set to channel = [%d]\n", (INT)pCurr->uChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:Set to channel = [%d]\n", (int)pCurr->uChannel); *pStatus = CMD_STATUS_SUCCESS; -- cgit v1.2.3 From b83cc2ed466f1b9938521d73fefe8b34baf265ea Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Tue, 1 Jun 2010 12:38:57 -0700 Subject: Staging: vt6655: remove custom LONG typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 6 +++--- drivers/staging/vt6655/bssdb.h | 6 +++--- drivers/staging/vt6655/device.h | 4 ++-- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/vt6655/dpc.c | 4 ++-- drivers/staging/vt6655/ioctl.c | 2 +- drivers/staging/vt6655/mib.h | 12 ++++++------ drivers/staging/vt6655/rf.c | 4 ++-- drivers/staging/vt6655/ttype.h | 2 -- 9 files changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index d07241af7c08..16aaedca8c25 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -609,7 +609,7 @@ BSSbUpdateToBSSList ( PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; PSRxMgmtPacket pRxPacket = (PSRxMgmtPacket)pRxPacketContext; - LONG ldBm; + long ldBm; BOOL bParsingQuiet = FALSE; PWLAN_IE_QUIET pQuiet = NULL; @@ -1629,8 +1629,8 @@ void s_vCheckSensitivity( pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); if (pBSSList != NULL) { // Updata BB Reg if RSSI is too strong. - LONG LocalldBmAverage = 0; - LONG uNumofdBm = 0; + long LocalldBmAverage = 0; + long uNumofdBm = 0; for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { if (pBSSList->ldBmAverage[ii] != 0) { uNumofdBm ++; diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index e09ef8762979..6a98834d7516 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -118,9 +118,9 @@ typedef struct tagKnownBSS { // WORD wATIMWindow; BYTE byRSSIStatCnt; - LONG ldBmMAX; - LONG ldBmAverage[RSSI_STAT_COUNT]; - LONG ldBmAverRange; + long ldBmMAX; + long ldBmAverage[RSSI_STAT_COUNT]; + long ldBmAverRange; //For any BSSID selection improvment BOOL bSelected; diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 5f4efb5904db..5dc081f560d8 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -666,7 +666,7 @@ typedef struct __device_info { BYTE byBBVGANew; BYTE byBBVGACurrent; BYTE abyBBVGA[BB_VGA_LEVEL]; - LONG ldBmThreshold[BB_VGA_LEVEL]; + long ldBmThreshold[BB_VGA_LEVEL]; BYTE byBBPreEDRSSI; BYTE byBBPreEDIndex; @@ -684,7 +684,7 @@ typedef struct __device_info { short sPSetPointCCK; short sPSetPointOFDMG; short sPSetPointOFDMA; - LONG lPFormulaOffset; + long lPFormulaOffset; short sPThreshold; char cAdjustStep; char cMinTxAGC; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 3c1ae3962173..a84c9199e854 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -2830,7 +2830,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { //pDevice->bBeaconSent = FALSE; } else { if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == TRUE) && (pDevice->uCurrRSSI != 0)) { - LONG ldBm; + long ldBm; RFvRSSITodBm(pDevice, (BYTE) pDevice->uCurrRSSI, &ldBm); for (ii=0;iiwResult = 0; diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 2308319a4051..190fc475e5d5 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -72,15 +72,15 @@ typedef struct tagSDot11Counters { // MIB2 counter // typedef struct tagSMib2Counter { - LONG ifIndex; + long ifIndex; char ifDescr[256]; // max size 255 plus zero ending // e.g. "interface 1" - LONG ifType; - LONG ifMtu; + long ifType; + long ifMtu; DWORD ifSpeed; BYTE ifPhysAddress[ETH_ALEN]; - LONG ifAdminStatus; - LONG ifOperStatus; + long ifAdminStatus; + long ifOperStatus; DWORD ifLastChange; DWORD ifInOctets; DWORD ifInUcastPkts; @@ -111,7 +111,7 @@ typedef struct tagSMib2Counter { // RMON counter // typedef struct tagSRmonCounter { - LONG etherStatsIndex; + long etherStatsIndex; DWORD etherStatsDataSource; DWORD etherStatsDropEvents; DWORD etherStatsOctets; diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 7cb86fe2eeb9..4f2c01bceb76 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -1209,8 +1209,8 @@ RFvRSSITodBm ( ) { BYTE byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03); - LONG b = (byCurrRSSI & 0x3F); - LONG a = 0; + long b = (byCurrRSSI & 0x3F); + long a = 0; BYTE abyAIROHARF[4] = {0, 18, 0, 40}; switch (pDevice->byRFType) { diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 9ccef04cab59..302829af6ebe 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,8 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef signed long LONG; - typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; -- cgit v1.2.3 From 5c9824e124f67c2590e1dbd33045603c36168609 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 2 Jun 2010 09:51:59 -0700 Subject: Staging: vt6655: remove custom UCHAR typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device.h | 2 +- drivers/staging/vt6655/device_main.c | 14 ++++++++------ drivers/staging/vt6655/ttype.h | 1 - drivers/staging/vt6655/wmgr.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 5dc081f560d8..915dd901fc93 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -218,7 +218,7 @@ typedef enum __device_init_type { #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 // PMKID Structures -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; +typedef unsigned char NDIS_802_11_PMKID_VALUE[16]; typedef enum _NDIS_802_11_WEP_STATUS diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index a84c9199e854..32d38931a5e2 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -340,7 +340,8 @@ static void device_free_rd0_ring(PSDevice pDevice); static void device_free_rd1_ring(PSDevice pDevice); static void device_free_rings(PSDevice pDevice); static void device_free_frag_buf(PSDevice pDevice); -static int Config_FileGetParameter(UCHAR *string, UCHAR *dest,UCHAR *source); +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, unsigned char *source); /*--------------------- Export Variables --------------------------*/ @@ -2978,9 +2979,10 @@ static inline u32 ether_crc(int length, unsigned char *data) } //2008-8-4 by chester -static int Config_FileGetParameter(UCHAR *string, UCHAR *dest,UCHAR *source) +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, unsigned char *source) { - UCHAR buf1[100]; + unsigned char buf1[100]; int source_len = strlen(source); memset(buf1,0,100); @@ -2993,9 +2995,9 @@ static int Config_FileGetParameter(UCHAR *string, UCHAR *dest,UCHAR *source) } int Config_FileOperation(PSDevice pDevice,BOOL fwrite,unsigned char *Parameter) { - UCHAR *config_path=CONFIG_PATH; - UCHAR *buffer=NULL; - UCHAR tmpbuffer[20]; + unsigned char *config_path = CONFIG_PATH; + unsigned char *buffer = NULL; + unsigned char tmpbuffer[20]; struct file *filp=NULL; mm_segment_t old_fs = get_fs(); //int oldfsuid=0,oldfsgid=0; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 302829af6ebe..74ec69f822fe 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index 9ae7e0d55bc4..d53aed7ad526 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -88,7 +88,7 @@ typedef void (*TimerFunction)(ULONG); //+++ NDIS related -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; +typedef unsigned char NDIS_802_11_MAC_ADDRESS[6]; typedef struct _NDIS_802_11_AI_REQFI { USHORT Capabilities; -- cgit v1.2.3 From 800acdbdf83efe6a2b4dbe61e3ab676b5c99d153 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 2 Jun 2010 09:52:00 -0700 Subject: Staging: vt6655: remove custom USHORT typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/ttype.h | 1 - drivers/staging/vt6655/wmgr.h | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 74ec69f822fe..eaf77d5348e4 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; typedef unsigned long long ULONGLONG; //64 bit diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index d53aed7ad526..9367f478dbf6 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -91,26 +91,26 @@ typedef void (*TimerFunction)(ULONG); typedef unsigned char NDIS_802_11_MAC_ADDRESS[6]; typedef struct _NDIS_802_11_AI_REQFI { - USHORT Capabilities; - USHORT ListenInterval; + unsigned short Capabilities; + unsigned short ListenInterval; NDIS_802_11_MAC_ADDRESS CurrentAPAddress; } NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; typedef struct _NDIS_802_11_AI_RESFI { - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; + unsigned short Capabilities; + unsigned short StatusCode; + unsigned short AssociationId; } NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION { ULONG Length; - USHORT AvailableRequestFixedIEs; + unsigned short AvailableRequestFixedIEs; NDIS_802_11_AI_REQFI RequestFixedIEs; ULONG RequestIELength; ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; + unsigned short AvailableResponseFixedIEs; NDIS_802_11_AI_RESFI ResponseFixedIEs; ULONG ResponseIELength; ULONG OffsetResponseIEs; -- cgit v1.2.3 From b6e95cd52a81079abc1def7867e27bf541953089 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 2 Jun 2010 09:52:01 -0700 Subject: Staging: vt6655: remove custom UINT typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/80211mgr.h | 48 +++---- drivers/staging/vt6655/IEEE11h.c | 5 +- drivers/staging/vt6655/baseband.c | 26 ++-- drivers/staging/vt6655/baseband.h | 6 +- drivers/staging/vt6655/bssdb.c | 66 +++++----- drivers/staging/vt6655/bssdb.h | 46 +++---- drivers/staging/vt6655/card.c | 71 +++++----- drivers/staging/vt6655/card.h | 14 +- drivers/staging/vt6655/datarate.c | 12 +- drivers/staging/vt6655/datarate.h | 2 +- drivers/staging/vt6655/device.h | 60 ++++----- drivers/staging/vt6655/device_main.c | 40 +++--- drivers/staging/vt6655/dpc.c | 40 +++--- drivers/staging/vt6655/hostap.c | 12 +- drivers/staging/vt6655/ioctl.c | 6 +- drivers/staging/vt6655/iwctl.c | 8 +- drivers/staging/vt6655/key.c | 12 +- drivers/staging/vt6655/mac.c | 41 +++--- drivers/staging/vt6655/mac.h | 25 ++-- drivers/staging/vt6655/mib.c | 12 +- drivers/staging/vt6655/mib.h | 11 +- drivers/staging/vt6655/michael.c | 8 +- drivers/staging/vt6655/michael.h | 2 +- drivers/staging/vt6655/power.c | 4 +- drivers/staging/vt6655/rc4.c | 22 ++-- drivers/staging/vt6655/rc4.h | 10 +- drivers/staging/vt6655/rf.c | 8 +- drivers/staging/vt6655/rf.h | 6 +- drivers/staging/vt6655/rxtx.c | 248 +++++++++++++++++------------------ drivers/staging/vt6655/rxtx.h | 20 +-- drivers/staging/vt6655/tcrc.c | 6 +- drivers/staging/vt6655/tcrc.h | 6 +- drivers/staging/vt6655/tether.c | 2 +- drivers/staging/vt6655/tether.h | 2 +- drivers/staging/vt6655/ttype.h | 1 - drivers/staging/vt6655/vntwifi.c | 20 +-- drivers/staging/vt6655/vntwifi.h | 4 +- drivers/staging/vt6655/wcmd.c | 12 +- drivers/staging/vt6655/wcmd.h | 2 +- drivers/staging/vt6655/wctl.c | 16 +-- drivers/staging/vt6655/wctl.h | 7 +- drivers/staging/vt6655/wmgr.c | 66 +++++----- drivers/staging/vt6655/wmgr.h | 30 ++--- drivers/staging/vt6655/wpa2.c | 4 +- drivers/staging/vt6655/wpa2.h | 2 +- drivers/staging/vt6655/wroute.c | 10 +- drivers/staging/vt6655/wroute.h | 2 +- 47 files changed, 545 insertions(+), 538 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h index 658fe144f898..b6ee8220f1f6 100644 --- a/drivers/staging/vt6655/80211mgr.h +++ b/drivers/staging/vt6655/80211mgr.h @@ -495,8 +495,8 @@ typedef struct _WLAN_IE_IBSS_DFS { // prototype structure, all mgmt frame types will start with these members typedef struct tagWLAN_FR_MGMT { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; @@ -505,8 +505,8 @@ typedef struct tagWLAN_FR_MGMT { // Beacon frame typedef struct tagWLAN_FR_BEACON { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; // fixed fields @@ -537,8 +537,8 @@ typedef struct tagWLAN_FR_BEACON { // IBSS ATIM frame typedef struct tagWLAN_FR_IBSSATIM { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; @@ -551,8 +551,8 @@ typedef struct tagWLAN_FR_IBSSATIM { // Disassociation typedef struct tagWLAN_FR_DISASSOC { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -564,8 +564,8 @@ typedef struct tagWLAN_FR_DISASSOC { // Association Request typedef struct tagWLAN_FR_ASSOCREQ { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -585,8 +585,8 @@ typedef struct tagWLAN_FR_ASSOCREQ { // Association Response typedef struct tagWLAN_FR_ASSOCRESP { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -602,8 +602,8 @@ typedef struct tagWLAN_FR_ASSOCRESP { // Reassociation Request typedef struct tagWLAN_FR_REASSOCREQ { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; @@ -624,8 +624,8 @@ typedef struct tagWLAN_FR_REASSOCREQ { // Reassociation Response typedef struct tagWLAN_FR_REASSOCRESP { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -641,8 +641,8 @@ typedef struct tagWLAN_FR_REASSOCRESP { // Probe Request typedef struct tagWLAN_FR_PROBEREQ { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -656,8 +656,8 @@ typedef struct tagWLAN_FR_PROBEREQ { // Probe Response typedef struct tagWLAN_FR_PROBERESP { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -685,8 +685,8 @@ typedef struct tagWLAN_FR_PROBERESP { // Authentication typedef struct tagWLAN_FR_AUTHEN { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -701,8 +701,8 @@ typedef struct tagWLAN_FR_AUTHEN { // Deauthenication typedef struct tagWLAN_FR_DEAUTHEN { - UINT uType; - UINT len; + unsigned int uType; + unsigned int len; PBYTE pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c index 22f12f5ef90c..55e66e9e0dde 100644 --- a/drivers/staging/vt6655/IEEE11h.c +++ b/drivers/staging/vt6655/IEEE11h.c @@ -97,7 +97,8 @@ typedef struct _WLAN_FRAME_TPCREP { /*--------------------- Static Variables --------------------------*/ /*--------------------- Static Functions --------------------------*/ -static BOOL s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq, UINT uLength) +static BOOL s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq, + unsigned int uLength) { size_t uNumOfEIDs = 0; BOOL bResult = TRUE; @@ -209,7 +210,7 @@ IEEE11hbMgrRxAction ( { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; PWLAN_FRAME_ACTION pAction = NULL; - UINT uLength = 0; + unsigned int uLength = 0; PWLAN_IE_CH_SW pChannelSwitch = NULL; diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 5414c6c6c050..2fe91b87666a 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1776,19 +1776,19 @@ s_vChangeAntenna ( * Return Value: FrameTime * */ -UINT +unsigned int BBuGetFrameTime ( BYTE byPreambleType, BYTE byPktType, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wRate ) { - UINT uFrameTime; - UINT uPreamble; - UINT uTmp; - UINT uRateIdx = (UINT)wRate; - UINT uRate = 0; + unsigned int uFrameTime; + unsigned int uPreamble; + unsigned int uTmp; + unsigned int uRateIdx = (unsigned int) wRate; + unsigned int uRate = 0; if (uRateIdx > RATE_54M) { @@ -1796,7 +1796,7 @@ BBuGetFrameTime ( return 0; } - uRate = (UINT)awcFrameTime[uRateIdx]; + uRate = (unsigned int) awcFrameTime[uRateIdx]; if (uRateIdx <= 3) { //CCK mode @@ -1846,7 +1846,7 @@ BBuGetFrameTime ( void BBvCaculateParameter ( PSDevice pDevice, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wRate, BYTE byPacketType, PWORD pwPhyLen, @@ -1854,9 +1854,9 @@ BBvCaculateParameter ( PBYTE pbyPhySgn ) { - UINT cbBitCount; - UINT cbUsCount = 0; - UINT cbTmp; + unsigned int cbBitCount; + unsigned int cbUsCount = 0; + unsigned int cbTmp; BOOL bExtBit; BYTE byPreambleType = pDevice->byPreambleType; BOOL bCCK = pDevice->bCCK; @@ -2762,7 +2762,7 @@ ULONG ulPacketNum; void BBvClearAntDivSQ3Value (PSDevice pDevice) { - UINT ii; + unsigned int ii; pDevice->uDiversityCnt = 0; for (ii = 0; ii < MAX_RATE; ii++) { diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index b236ff4139a0..3372546662d9 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -118,18 +118,18 @@ /*--------------------- Export Functions --------------------------*/ -UINT +unsigned int BBuGetFrameTime( BYTE byPreambleType, BYTE byPktType, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wRate ); void BBvCaculateParameter ( PSDevice pDevice, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wRate, BYTE byPacketType, PWORD pwPhyLen, diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 16aaedca8c25..e919b2954a52 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -138,8 +138,8 @@ BSSpSearchBSSList( PKnownBSS pCurrBSS = NULL; PKnownBSS pSelect = NULL; BYTE ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00}; - UINT ii = 0; -// UINT jj = 0; //DavidWang + unsigned int ii = 0; + if (pbyDesireBSSID != NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList BSSID[%02X %02X %02X-%02X %02X %02X]\n", *pbyDesireBSSID,*(pbyDesireBSSID+1),*(pbyDesireBSSID+2), @@ -288,7 +288,7 @@ BSSvClearBSSList( { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT ii; + unsigned int ii; for (ii = 0; ii < MAX_BSS_NUM; ii++) { if (bKeepCurrBSSID) { @@ -333,7 +333,7 @@ BSSpAddrIsInBSSList( PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; PKnownBSS pBSSList = NULL; - UINT ii; + unsigned int ii; for (ii = 0; ii < MAX_BSS_NUM; ii++) { pBSSList = &(pMgmt->sBSSList[ii]); @@ -382,7 +382,7 @@ BSSbInsertToBSSList ( PWLAN_IE_RSN_EXT pRSNWPA, PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, - UINT uIELength, + unsigned int uIELength, PBYTE pbyIEs, void *pRxPacketContext ) @@ -392,7 +392,7 @@ BSSbInsertToBSSList ( PSMgmtObject pMgmt = pDevice->pMgmt; PSRxMgmtPacket pRxPacket = (PSRxMgmtPacket)pRxPacketContext; PKnownBSS pBSSList = NULL; - UINT ii; + unsigned int ii; BOOL bParsingQuiet = FALSE; PWLAN_IE_QUIET pQuiet = NULL; @@ -468,9 +468,9 @@ BSSbInsertToBSSList ( WPA_ClearRSN(pBSSList); if (pRSNWPA != NULL) { - UINT uLen = pRSNWPA->len + 2; + unsigned int uLen = pRSNWPA->len + 2; - if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { pBSSList->wWPALen = uLen; memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); WPA_ParseRSN(pBSSList, pRSNWPA); @@ -480,8 +480,8 @@ BSSbInsertToBSSList ( WPA2_ClearRSN(pBSSList); if (pRSN != NULL) { - UINT uLen = pRSN->len + 2; - if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + unsigned int uLen = pRSN->len + 2; + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { pBSSList->wRSNLen = uLen; memcpy(pBSSList->byRSNIE, pRSN, uLen); WPA2vParseRSN(pBSSList, pRSN); @@ -600,7 +600,7 @@ BSSbUpdateToBSSList ( PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, PKnownBSS pBSSList, - UINT uIELength, + unsigned int uIELength, PBYTE pbyIEs, void *pRxPacketContext ) @@ -670,8 +670,8 @@ BSSbUpdateToBSSList ( WPA_ClearRSN(pBSSList); //mike update if (pRSNWPA != NULL) { - UINT uLen = pRSNWPA->len + 2; - if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + unsigned int uLen = pRSNWPA->len + 2; + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { pBSSList->wWPALen = uLen; memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); WPA_ParseRSN(pBSSList, pRSNWPA); @@ -681,8 +681,8 @@ BSSbUpdateToBSSList ( WPA2_ClearRSN(pBSSList); //mike update if (pRSN != NULL) { - UINT uLen = pRSN->len + 2; - if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + unsigned int uLen = pRSN->len + 2; + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { pBSSList->wRSNLen = uLen; memcpy(pBSSList->byRSNIE, pRSN, uLen); WPA2vParseRSN(pBSSList, pRSN); @@ -770,7 +770,7 @@ BSSDBbIsSTAInNodeDB( ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; - UINT ii; + unsigned int ii; // Index = 0 reserved for AP Node for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { @@ -806,9 +806,9 @@ BSSvCreateOneNode( PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT ii; - UINT BigestCount = 0; - UINT SelectIndex; + unsigned int ii; + unsigned int BigestCount = 0; + unsigned int SelectIndex; struct sk_buff *skb; // Index = 0 reserved for AP Node (In STA mode) // Index = 0 reserved for Broadcast/MultiCast (In AP mode) @@ -865,7 +865,7 @@ BSSvCreateOneNode( void BSSvRemoveOneNode( void *hDeviceContext, - UINT uNodeIndex + unsigned int uNodeIndex ) { @@ -905,7 +905,7 @@ BSSvUpdateAPNode( { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uRateLen = WLAN_RATES_MAXLEN; + unsigned int uRateLen = WLAN_RATES_MAXLEN; memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); @@ -1009,7 +1009,7 @@ BSSvAddMulticastNode( //2008-4-14 by chester for led issue #ifdef FOR_LED_ON_NOTEBOOK BOOL cc=FALSE; -UINT status; +unsigned int status; #endif void BSSvSecondCallBack( @@ -1018,11 +1018,11 @@ BSSvSecondCallBack( { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT ii; + unsigned int ii; PWLAN_IE_SSID pItemSSID, pCurrSSID; - UINT uSleepySTACnt = 0; - UINT uNonShortSlotSTACnt = 0; - UINT uLongPreambleSTACnt = 0; + unsigned int uSleepySTACnt = 0; + unsigned int uNonShortSlotSTACnt = 0; + unsigned int uLongPreambleSTACnt = 0; viawget_wpa_header* wpahdr; //DavidWang spin_lock_irq(&pDevice->lock); @@ -1394,20 +1394,20 @@ BSSvUpdateNodeTxCounter( BYTE byTsr0, BYTE byTsr1, PBYTE pbyBuffer, - UINT uFIFOHeaderSize + unsigned int uFIFOHeaderSize ) { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; BYTE byTxRetry = (byTsr0 & TSR0_NCR); PSTxBufHead pTxBufHead; PS802_11Header pMACHeader; WORD wRate; WORD wFallBackRate = RATE_1M; BYTE byFallBack; - UINT ii; -// UINT txRetryTemp; + unsigned int ii; +// unsigned int txRetryTemp; //PLICE_DEBUG-> //txRetryTemp = byTxRetry; //if (txRetryTemp== 8) @@ -1584,14 +1584,14 @@ BSSvUpdateNodeTxCounter( void BSSvClearNodeDBTable( void *hDeviceContext, - UINT uStartIndex + unsigned int uStartIndex ) { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; struct sk_buff *skb; - UINT ii; + unsigned int ii; for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { @@ -1666,7 +1666,7 @@ BSSvClearAnyBSSJoinRecord ( { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT ii; + unsigned int ii; for (ii = 0; ii < MAX_BSS_NUM; ii++) { pMgmt->sBSSList[ii].bSelected = FALSE; diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index 6a98834d7516..c7283d208dfb 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -106,10 +106,10 @@ typedef struct tagKnownBSS { // BSS info BOOL bActive; BYTE abyBSSID[WLAN_BSSID_LEN]; - UINT uChannel; + unsigned int uChannel; BYTE abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; - UINT uRSSI; + unsigned int uRSSI; BYTE bySQ; WORD wBeaconInterval; WORD wCapInfo; @@ -150,9 +150,9 @@ typedef struct tagKnownBSS { WORD wRSNLen; // Clear count - UINT uClearCount; + unsigned int uClearCount; // BYTE abyIEs[WLAN_BEACON_FR_MAXLEN]; - UINT uIELength; + unsigned int uIELength; QWORD qwBSSTimestamp; QWORD qwLocalTSF; // local TSF timer @@ -189,7 +189,7 @@ typedef struct tagKnownNodeDB { BOOL bShortPreamble; BOOL bERPExist; BOOL bShortSlotTime; - UINT uInActiveCount; + unsigned int uInActiveCount; WORD wMaxBasicRate; //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp. WORD wMaxSuppRate; //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon. WORD wSuppRate; @@ -217,23 +217,23 @@ typedef struct tagKnownNodeDB { BYTE byCipherSuite; DWORD dwTSC47_16; WORD wTSC15_0; - UINT uWepKeyLength; + unsigned int uWepKeyLength; BYTE abyWepKey[WLAN_WEPMAX_KEYLEN]; // // Auto rate fallback vars BOOL bIsInFallback; - UINT uAverageRSSI; - UINT uRateRecoveryTimeout; - UINT uRatePollTimeout; - UINT uTxFailures; - UINT uTxAttempts; - - UINT uTxRetry; - UINT uFailureRatio; - UINT uRetryRatio; - UINT uTxOk[MAX_RATE+1]; - UINT uTxFail[MAX_RATE+1]; - UINT uTimeCount; + unsigned int uAverageRSSI; + unsigned int uRateRecoveryTimeout; + unsigned int uRatePollTimeout; + unsigned int uTxFailures; + unsigned int uTxAttempts; + + unsigned int uTxRetry; + unsigned int uFailureRatio; + unsigned int uRetryRatio; + unsigned int uTxOk[MAX_RATE+1]; + unsigned int uTxFail[MAX_RATE+1]; + unsigned int uTimeCount; } KnownNodeDB, *PKnownNodeDB; @@ -279,7 +279,7 @@ BSSbInsertToBSSList( PWLAN_IE_RSN_EXT pRSNWPA, PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, - UINT uIELength, + unsigned int uIELength, PBYTE pbyIEs, void *pRxPacketContext ); @@ -302,7 +302,7 @@ BSSbUpdateToBSSList( PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, PKnownBSS pBSSList, - UINT uIELength, + unsigned int uIELength, PBYTE pbyIEs, void *pRxPacketContext ); @@ -342,13 +342,13 @@ BSSvUpdateNodeTxCounter( BYTE byTsr0, BYTE byTsr1, PBYTE pbyBuffer, - UINT uFIFOHeaderSize + unsigned int uFIFOHeaderSize ); void BSSvRemoveOneNode( void *hDeviceContext, - UINT uNodeIndex + unsigned int uNodeIndex ); void @@ -360,7 +360,7 @@ BSSvAddMulticastNode( void BSSvClearNodeDBTable( void *hDeviceContext, - UINT uStartIndex + unsigned int uStartIndex ); void diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index f6ecbadc7f36..439bb0c4ca68 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -82,7 +82,7 @@ static int msglevel =MSG_LEVEL_INFO; typedef struct tagSChannelTblElement { BYTE byChannelNumber; - UINT uFrequency; + unsigned int uFrequency; BOOL bValid; BYTE byMAP; }SChannelTblElement, *PSChannelTblElement; @@ -457,7 +457,7 @@ s_vCaculateOFDMRParameter( ************************************************************************/ //2008-8-4 by chester BOOL -ChannelValid(UINT ChannelIndex) +ChannelValid(unsigned int ChannelIndex) { BOOL bValid; @@ -729,7 +729,7 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, /*--------------------- Export Functions --------------------------*/ BYTE CARDbyGetChannelMapping (void *pDeviceHandler, BYTE byChannelNumber, CARD_PHY_TYPE ePhyType) { - UINT ii; + unsigned int ii; if ((ePhyType == PHY_TYPE_11B) || (ePhyType == PHY_TYPE_11G)) { return (byChannelNumber); @@ -764,7 +764,7 @@ BYTE CARDbyGetChannelNumber (void *pDeviceHandler, BYTE byChannelIndex) * Return Value: TRUE if succeeded; FALSE if failed. * */ -BOOL CARDbSetChannel (void *pDeviceHandler, UINT uConnectionChannel) +BOOL CARDbSetChannel (void *pDeviceHandler, unsigned int uConnectionChannel) { PSDevice pDevice = (PSDevice) pDeviceHandler; BOOL bResult = TRUE; @@ -852,7 +852,7 @@ BOOL CARDbSetChannel (void *pDeviceHandler, UINT uConnectionChannel) * */ /* -BOOL CARDbSendPacket (void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, UINT uLength) +BOOL CARDbSendPacket (void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, unsigned int uLength) { PSDevice pDevice = (PSDevice) pDeviceHandler; if (ePktType == PKT_TYPE_802_11_MNG) { @@ -1145,10 +1145,10 @@ BOOL CARDbUpdateTSF (void *pDeviceHandler, BYTE byRxRate, QWORD qwBSSTimestamp, BOOL CARDbSetBeaconPeriod (void *pDeviceHandler, WORD wBeaconInterval) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT uBeaconInterval = 0; - UINT uLowNextTBTT = 0; - UINT uHighRemain = 0; - UINT uLowRemain = 0; + unsigned int uBeaconInterval = 0; + unsigned int uLowNextTBTT = 0; + unsigned int uHighRemain = 0; + unsigned int uLowRemain = 0; QWORD qwNextTBTT; HIDWORD(qwNextTBTT) = 0; @@ -1396,7 +1396,7 @@ CARDbPowerDown( ) { PSDevice pDevice = (PSDevice)pDeviceHandler; - UINT uIdx; + unsigned int uIdx; // check if already in Doze mode if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) @@ -1557,7 +1557,7 @@ CARDbAdd_PMKID_Candidate ( { PSDevice pDevice = (PSDevice) pDeviceHandler; PPMKID_CANDIDATE pCandidateList; - UINT ii = 0; + unsigned int ii = 0; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); @@ -1614,7 +1614,7 @@ void CARDvInitChannelTable (void *pDeviceHandler) { PSDevice pDevice = (PSDevice) pDeviceHandler; BOOL bMultiBand = FALSE; - UINT ii; + unsigned int ii; for(ii=1;ii<=CARD_MAX_CHANNEL_TBL;ii++) { sChannelTbl[ii].bValid = FALSE; @@ -1709,7 +1709,7 @@ BOOL CARDbStartMeasure ( void *pDeviceHandler, void *pvMeasureEIDs, - UINT uNumOfMeasureEIDs + unsigned int uNumOfMeasureEIDs ) { PSDevice pDevice = (PSDevice) pDeviceHandler; @@ -1886,7 +1886,7 @@ CARDbSetQuiet ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii = 0; + unsigned int ii = 0; if (bResetQuiet == TRUE) { MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); @@ -1937,9 +1937,9 @@ CARDbStartQuiet ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii = 0; + unsigned int ii = 0; DWORD dwStartTime = 0xFFFFFFFF; - UINT uCurrentQuietIndex = 0; + unsigned int uCurrentQuietIndex = 0; DWORD dwNextTime = 0; DWORD dwGap = 0; DWORD dwDuration = 0; @@ -2040,10 +2040,10 @@ CARDvSetCountryInfo ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii = 0; - UINT uu = 0; - UINT step = 0; - UINT uNumOfCountryInfo = 0; + unsigned int ii = 0; + unsigned int uu = 0; + unsigned int step = 0; + unsigned int uNumOfCountryInfo = 0; BYTE byCh = 0; PWLAN_IE_COUNTRY pIE_Country = (PWLAN_IE_COUNTRY) pIE; @@ -2169,7 +2169,7 @@ CARDbySetSupportChannels ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii; + unsigned int ii; BYTE byCount; PWLAN_IE_SUPP_CH pIE = (PWLAN_IE_SUPP_CH) pbyIEs; PBYTE pbyChTupple; @@ -2266,7 +2266,7 @@ CARDbyGetTransmitPower ( BOOL CARDbChannelGetList ( - UINT uCountryCodeIdx, + unsigned int uCountryCodeIdx, PBYTE pbyChannelTable ) { @@ -2285,7 +2285,7 @@ CARDvSetCountryIE( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii; + unsigned int ii; PWLAN_IE_COUNTRY pIECountry = (PWLAN_IE_COUNTRY) pIE; pIECountry->byElementID = WLAN_EID_COUNTRY; @@ -2307,7 +2307,7 @@ CARDvSetCountryIE( BOOL CARDbGetChannelMapInfo( void *pDeviceHandler, - UINT uChannelIndex, + unsigned int uChannelIndex, PBYTE pbyChannelNumber, PBYTE pbyMap ) @@ -2326,7 +2326,7 @@ CARDbGetChannelMapInfo( void CARDvSetChannelMapInfo( void *pDeviceHandler, - UINT uChannelIndex, + unsigned int uChannelIndex, BYTE byMap ) { @@ -2345,7 +2345,7 @@ CARDvClearChannelMapInfo( ) { // PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii = 0; + unsigned int ii = 0; for (ii = 1; ii <= CB_MAX_CHANNEL; ii++) { sChannelTbl[ii].byMAP = 0; @@ -2360,7 +2360,7 @@ CARDbyAutoChannelSelect( ) { // PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ii = 0; + unsigned int ii = 0; BYTE byOptionChannel = 0; int aiWeight[CB_MAX_CHANNEL_24G+1] = {-1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; @@ -2425,7 +2425,7 @@ CARDvSafeResetTx ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT uu; + unsigned int uu; PSTxDesc pCurrTD; // initialize TD index @@ -2481,7 +2481,7 @@ CARDvSafeResetRx ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT uu; + unsigned int uu; PSRxDesc pDesc; @@ -2539,7 +2539,7 @@ CARDvSafeResetRx ( WORD CARDwGetCCKControlRate(void *pDeviceHandler, WORD wRateIdx) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ui = (UINT)wRateIdx; + unsigned int ui = (unsigned int) wRateIdx; while (ui > RATE_1M) { if (pDevice->wBasicRate & ((WORD)1 << ui)) { @@ -2566,7 +2566,7 @@ WORD CARDwGetCCKControlRate(void *pDeviceHandler, WORD wRateIdx) WORD CARDwGetOFDMControlRate (void *pDeviceHandler, WORD wRateIdx) { PSDevice pDevice = (PSDevice) pDeviceHandler; - UINT ui = (UINT)wRateIdx; + unsigned int ui = (unsigned int) wRateIdx; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BASIC RATE: %X\n", pDevice->wBasicRate); @@ -3002,9 +3002,9 @@ BOOL CARDbGetCurrentTSF (DWORD_PTR dwIoBase, PQWORD pqwCurrTSF) QWORD CARDqGetNextTBTT (QWORD qwTSF, WORD wBeaconInterval) { - UINT uLowNextTBTT; - UINT uHighRemain, uLowRemain; - UINT uBeaconInterval; + unsigned int uLowNextTBTT; + unsigned int uHighRemain, uLowRemain; + unsigned int uBeaconInterval; uBeaconInterval = wBeaconInterval * 1024; // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval @@ -3084,7 +3084,8 @@ void CARDvUpdateNextTBTT (DWORD_PTR dwIoBase, QWORD qwTSF, WORD wBeaconInterval) VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwTSF)); VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwTSF)); MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:Update Next TBTT[%8xh:%8xh] \n",(UINT)HIDWORD(qwTSF), (UINT)LODWORD(qwTSF)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:Update Next TBTT[%8xh:%8xh] \n", + (unsigned int) HIDWORD(qwTSF), (unsigned int) LODWORD(qwTSF)); return; } diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 00dce0310b5d..f2f79407f4ab 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -86,7 +86,7 @@ typedef enum _CARD_OP_MODE { /*--------------------- Export Functions --------------------------*/ -BOOL ChannelValid(UINT ChannelIndex); +BOOL ChannelValid(unsigned int ChannelIndex); void CARDvSetRSPINF(void *pDeviceHandler, CARD_PHY_TYPE ePHYType); void vUpdateIFS(void *pDeviceHandler); void CARDvUpdateBasicTopRate(void *pDeviceHandler); @@ -107,8 +107,8 @@ void CARDvSafeResetRx(void *pDeviceHandler); //xxx BOOL CARDbRadioPowerOff(void *pDeviceHandler); BOOL CARDbRadioPowerOn(void *pDeviceHandler); -BOOL CARDbSetChannel(void *pDeviceHandler, UINT uConnectionChannel); -//BOOL CARDbSendPacket(void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, UINT uLength); +BOOL CARDbSetChannel(void *pDeviceHandler, unsigned int uConnectionChannel); +//BOOL CARDbSendPacket(void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, unsigned int uLength); BOOL CARDbIsShortPreamble(void *pDeviceHandler); BOOL CARDbIsShorSlotTime(void *pDeviceHandler); BOOL CARDbSetPhyParameter(void *pDeviceHandler, CARD_PHY_TYPE ePHYType, WORD wCapInfo, BYTE byERPField, void *pvSupportRateIEs, void *pvExtSupportRateIEs); @@ -152,7 +152,7 @@ BOOL CARDbStartMeasure ( void *pDeviceHandler, void *pvMeasureEIDs, - UINT uNumOfMeasureEIDs + unsigned int uNumOfMeasureEIDs ); BOOL @@ -212,7 +212,7 @@ CARDbyGetTransmitPower ( BOOL CARDbChannelGetList ( - UINT uCountryCodeIdx, + unsigned int uCountryCodeIdx, PBYTE pbyChannelTable ); @@ -225,7 +225,7 @@ CARDvSetCountryIE( BOOL CARDbGetChannelMapInfo( void *pDeviceHandler, - UINT uChannelIndex, + unsigned int uChannelIndex, PBYTE pbyChannelNumber, PBYTE pbyMap ); @@ -233,7 +233,7 @@ CARDbGetChannelMapInfo( void CARDvSetChannelMapInfo( void *pDeviceHandler, - UINT uChannelIndex, + unsigned int uChannelIndex, BYTE byMap ); diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c index 38b09a7fb53b..ecec01ea0807 100644 --- a/drivers/staging/vt6655/datarate.c +++ b/drivers/staging/vt6655/datarate.c @@ -208,11 +208,11 @@ RATEvParseMaxRate ( ) { PSDevice pDevice = (PSDevice) pDeviceHandler; -UINT ii; +unsigned int ii; BYTE byHighSuppRate = 0; BYTE byRate = 0; WORD wOldBasicRate = pDevice->wBasicRate; -UINT uRateLen; +unsigned int uRateLen; if (pItemRates == NULL) @@ -248,7 +248,7 @@ UINT uRateLen; if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && (pDevice->eCurrentPHYType != PHY_TYPE_11B)) { - UINT uExtRateLen = pItemExtRates->len; + unsigned int uExtRateLen = pItemExtRates->len; if (uExtRateLen > WLAN_RATES_MAXLEN) uExtRateLen = WLAN_RATES_MAXLEN; @@ -315,7 +315,7 @@ RATEvTxRateFallBack ( { PSDevice pDevice = (PSDevice) pDeviceHandler; WORD wIdxDownRate = 0; -UINT ii; +unsigned int ii; //DWORD dwRateTable[MAX_RATE] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; BOOL bAutoRate[MAX_RATE] = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}; DWORD dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; @@ -413,10 +413,10 @@ BYTE RATEuSetIE ( PWLAN_IE_SUPP_RATES pSrcRates, PWLAN_IE_SUPP_RATES pDstRates, - UINT uRateLen + unsigned int uRateLen ) { - UINT ii, uu, uRateCnt = 0; + unsigned int ii, uu, uRateCnt = 0; if ((pSrcRates == NULL) || (pDstRates == NULL)) return 0; diff --git a/drivers/staging/vt6655/datarate.h b/drivers/staging/vt6655/datarate.h index b8ca792e9c6e..760d464890c7 100644 --- a/drivers/staging/vt6655/datarate.h +++ b/drivers/staging/vt6655/datarate.h @@ -77,7 +77,7 @@ BYTE RATEuSetIE( PWLAN_IE_SUPP_RATES pSrcRates, PWLAN_IE_SUPP_RATES pDstRates, - UINT uRateLen + unsigned int uRateLen ); WORD diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 915dd901fc93..1685fb98d2fd 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -311,7 +311,7 @@ typedef struct tagSCache{ /* The receive cache is updated circularly. The next entry to be written is * indexed by the "InPtr". */ - UINT uInPtr; // Place to use next + unsigned int uInPtr; // Place to use next SCacheEntry asCacheEntry[DUPLICATE_RX_CACHE_LENGTH]; } SCache, *PSCache; @@ -322,10 +322,10 @@ typedef struct tagSDeFragControlBlock WORD wSequence; WORD wFragNum; BYTE abyAddr2[ETH_ALEN]; - UINT uLifetime; + unsigned int uLifetime; struct sk_buff* skb; PBYTE pbyRxBuffer; - UINT cbFrameLength; + unsigned int cbFrameLength; BOOL bInUse; } SDeFragControlBlock, *PSDeFragControlBlock; @@ -448,9 +448,9 @@ typedef struct __device_info { SCache sDupRxCache; SDeFragControlBlock sRxDFCB[CB_MAX_RX_FRAG]; - UINT cbDFCB; - UINT cbFreeDFCB; - UINT uCurrentDFCBIdx; + unsigned int cbDFCB; + unsigned int cbFreeDFCB; + unsigned int uCurrentDFCBIdx; OPTIONS sOpts; @@ -497,7 +497,7 @@ typedef struct __device_info { SMgmtObject sMgmtObj; // 802.11 MAC specific - UINT uCurrRSSI; + unsigned int uCurrRSSI; BYTE byCurrSQ; DWORD dwTxAntennaSel; @@ -508,12 +508,12 @@ typedef struct __device_info { BOOL bTxRxAntInv; PBYTE pbyTmpBuff; - UINT uSIFS; //Current SIFS - UINT uDIFS; //Current DIFS - UINT uEIFS; //Current EIFS - UINT uSlot; //Current SlotTime - UINT uCwMin; //Current CwMin - UINT uCwMax; //CwMax is fixed on 1023. + unsigned int uSIFS; //Current SIFS + unsigned int uDIFS; //Current DIFS + unsigned int uEIFS; //Current EIFS + unsigned int uSlot; //Current SlotTime + unsigned int uCwMin; //Current CwMin + unsigned int uCwMax; //CwMax is fixed on 1023. // PHY parameter BYTE bySIFS; BYTE byDIFS; @@ -532,7 +532,7 @@ typedef struct __device_info { BYTE byMinChannel; BYTE byMaxChannel; - UINT uConnectionRate; + unsigned int uConnectionRate; BYTE byPreambleType; BYTE byShortPreamble; @@ -588,10 +588,10 @@ typedef struct __device_info { BOOL bBeaconBufReady; BOOL bBeaconSent; BOOL bIsBeaconBufReadySet; - UINT cbBeaconBufReadySetCnt; + unsigned int cbBeaconBufReadySetCnt; BOOL bFixRate; BYTE byCurrentCh; - UINT uScanTime; + unsigned int uScanTime; CMD_STATE eCommandState; @@ -601,14 +601,14 @@ typedef struct __device_info { BOOL bStopBeacon; BOOL bStopDataPkt; BOOL bStopTx0Pkt; - UINT uAutoReConnectTime; + unsigned int uAutoReConnectTime; // 802.11 counter CMD_ITEM eCmdQueue[CMD_Q_SIZE]; - UINT uCmdDequeueIdx; - UINT uCmdEnqueueIdx; - UINT cbFreeCmdQueue; + unsigned int uCmdDequeueIdx; + unsigned int uCmdEnqueueIdx; + unsigned int cbFreeCmdQueue; BOOL bCmdRunning; BOOL bCmdClear; @@ -629,19 +629,19 @@ typedef struct __device_info { DWORD dwIVCounter; QWORD qwPacketNumber; //For CCMP and TKIP as TSC(6 bytes) - UINT uCurrentWEPMode; + unsigned int uCurrentWEPMode; RC4Ext SBox; BYTE abyPRNG[WLAN_WEPMAX_KEYLEN+3]; BYTE byKeyIndex; - UINT uKeyLength; + unsigned int uKeyLength; BYTE abyKey[WLAN_WEP232_KEYLEN]; BOOL bAES; BYTE byCntMeasure; // for AP mode - UINT uAssocCount; + unsigned int uAssocCount; BOOL bMoreData; // QoS @@ -657,12 +657,12 @@ typedef struct __device_info { BOOL bRxMICFail; - UINT uRATEIdx; + unsigned int uRATEIdx; // For Update BaseBand VGA Gain Offset BOOL bUpdateBBVGA; - UINT uBBVGADiffCount; + unsigned int uBBVGADiffCount; BYTE byBBVGANew; BYTE byBBVGACurrent; BYTE abyBBVGA[BB_VGA_LEVEL]; @@ -766,7 +766,7 @@ typedef struct __device_info { BOOL b11hEnable; BYTE abyCountryCode[3]; // for 802.11h DFS - UINT uNumOfMeasureEIDs; + unsigned int uNumOfMeasureEIDs; PWLAN_IE_MEASURE_REQ pCurrMeasureEID; BOOL bMeasureInProgress; BYTE byOrgChannel; @@ -783,7 +783,7 @@ typedef struct __device_info { BOOL bQuietEnable; BOOL bEnableFirstQuiet; BYTE byQuietStartCount; - UINT uQuietEnqueue; + unsigned int uQuietEnqueue; DWORD dwCurrentQuietEndTime; SQuietControl sQuiet[MAX_QUIET_COUNT]; // for 802.11h TPC @@ -803,7 +803,7 @@ typedef struct __device_info { BOOL bwextstep2; BOOL bwextstep3; */ - UINT bwextcount; + unsigned int bwextcount; BOOL bWPASuppWextEnabled; #endif @@ -816,7 +816,7 @@ typedef struct __device_info { struct net_device *apdev; int (*tx_80211)(struct sk_buff *skb, struct net_device *dev); #endif - UINT uChannel; + unsigned int uChannel; BOOL bMACSuspend; struct iw_statistics wstats; // wireless stats @@ -920,7 +920,7 @@ static inline PDEVICE_TD_INFO alloc_td_info(void) { /*--------------------- Export Functions --------------------------*/ -BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, UINT uNodeIndex); +BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex); BOOL device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF); int Config_FileOperation(PSDevice pDevice,BOOL fwrite,unsigned char *Parameter); #endif diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 32d38931a5e2..c8ae43aba80e 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -329,8 +329,8 @@ static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev); static BOOL device_release_WPADEV(PSDevice pDevice); static int ethtool_ioctl(struct net_device *dev, void *useraddr); -static int device_rx_srv(PSDevice pDevice, UINT uIdx); -static int device_tx_srv(PSDevice pDevice, UINT uIdx); +static int device_rx_srv(PSDevice pDevice, unsigned int uIdx); +static int device_tx_srv(PSDevice pDevice, unsigned int uIdx); static BOOL device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pDesc); static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType); static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc); @@ -481,7 +481,7 @@ pDevice->bUpdateBBVGA = TRUE; static void s_vCompleteCurrentMeasure (PSDevice pDevice, BYTE byResult) { - UINT ii; + unsigned int ii; DWORD dwDuration = 0; BYTE byRPI0 = 0; @@ -526,7 +526,7 @@ static void s_vCompleteCurrentMeasure (PSDevice pDevice, BYTE byResult) static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) { - UINT ii; + unsigned int ii; BYTE byValue; BYTE byValue1; BYTE byCCKPwrdBm = 0; @@ -1153,7 +1153,7 @@ static BOOL device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) { u16 pci_cmd; u8 b; - UINT cis_addr; + unsigned int cis_addr; #ifdef PLICE_DEBUG BYTE pci_config[256]; BYTE value =0x00; @@ -1594,7 +1594,7 @@ static void device_free_td1_ring(PSDevice pDevice) { /*-----------------------------------------------------------------*/ -static int device_rx_srv(PSDevice pDevice, UINT uIdx) { +static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) { PSRxDesc pRD; int works = 0; @@ -1662,17 +1662,17 @@ BOOL device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) { -static int device_tx_srv(PSDevice pDevice, UINT uIdx) { +static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { PSTxDesc pTD; BOOL bFull=FALSE; int works = 0; BYTE byTsr0; BYTE byTsr1; - UINT uFrameSize, uFIFOHeaderSize; + unsigned int uFrameSize, uFIFOHeaderSize; PSTxBufHead pTxBufHead; struct net_device_stats* pStats = &pDevice->stats; struct sk_buff* skb; - UINT uNodeIndex; + unsigned int uNodeIndex; PSMgmtObject pMgmt = pDevice->pMgmt; @@ -2084,7 +2084,7 @@ device_release_WPADEV(pDevice); static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { PSDevice pDevice=netdev_priv(dev); PBYTE pbMPDU; - UINT cbMPDULen = 0; + unsigned int cbMPDULen = 0; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n"); @@ -2116,16 +2116,16 @@ static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { -BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, UINT uNodeIndex) { +BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) { PSMgmtObject pMgmt = pDevice->pMgmt; PSTxDesc pHeadTD, pLastTD; - UINT cbFrameBodySize; - UINT uMACfragNum; + unsigned int cbFrameBodySize; + unsigned int uMACfragNum; BYTE byPktType; BOOL bNeedEncryption = FALSE; PSKeyItem pTransmitKey = NULL; - UINT cbHeaderSize; - UINT ii; + unsigned int cbHeaderSize; + unsigned int ii; SKeyItem STempKey; // BYTE byKeyIndex = 0; @@ -2270,17 +2270,17 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { PSMgmtObject pMgmt = pDevice->pMgmt; PSTxDesc pHeadTD, pLastTD; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; WORD wAID; - UINT uMACfragNum = 1; - UINT cbFrameBodySize; + unsigned int uMACfragNum = 1; + unsigned int cbFrameBodySize; BYTE byPktType; - UINT cbHeaderSize; + unsigned int cbHeaderSize; BOOL bNeedEncryption = FALSE; PSKeyItem pTransmitKey = NULL; SKeyItem STempKey; - UINT ii; + unsigned int ii; BOOL bTKIP_UseGTK = FALSE; BOOL bNeedDeAuth = FALSE; PBYTE pbyBSSID; diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index ce6ccab25e26..8fa87dd5c43b 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -92,7 +92,7 @@ void s_vProcessRxMACHeader ( PSDevice pDevice, PBYTE pbyRxBufferAddr, - UINT cbPacketSize, + unsigned int cbPacketSize, BOOL bIsWEP, BOOL bExtIV, PUINT pcbHeadSize @@ -109,8 +109,8 @@ static BOOL s_bAPModeRxCtl( static BOOL s_bAPModeRxData ( PSDevice pDevice, struct sk_buff* skb, - UINT FrameSize, - UINT cbHeaderOffset, + unsigned int FrameSize, + unsigned int cbHeaderOffset, int iSANodeIndex, int iDANodeIndex ); @@ -119,7 +119,7 @@ static BOOL s_bAPModeRxData ( static BOOL s_bHandleRxEncryption( PSDevice pDevice, PBYTE pbyFrame, - UINT FrameSize, + unsigned int FrameSize, PBYTE pbyRsr, PBYTE pbyNewRsr, PSKeyItem *pKeyOut, @@ -132,7 +132,7 @@ static BOOL s_bHostWepRxEncryption( PSDevice pDevice, PBYTE pbyFrame, - UINT FrameSize, + unsigned int FrameSize, PBYTE pbyRsr, BOOL bOnFly, PSKeyItem pKey, @@ -167,14 +167,14 @@ void s_vProcessRxMACHeader ( PSDevice pDevice, PBYTE pbyRxBufferAddr, - UINT cbPacketSize, + unsigned int cbPacketSize, BOOL bIsWEP, BOOL bExtIV, PUINT pcbHeadSize ) { PBYTE pbyRxBuffer; - UINT cbHeaderSize = 0; + unsigned int cbHeaderSize = 0; PWORD pwType; PS802_11Header pMACHeader; int ii; @@ -269,7 +269,7 @@ s_vGetDASA ( PSEthernetHeader psEthHeader ) { - UINT cbHeaderSize = 0; + unsigned int cbHeaderSize = 0; PS802_11Header pMACHeader; int ii; @@ -357,18 +357,18 @@ device_receive_frame ( PBYTE pbyFrame; BOOL bDeFragRx = FALSE; BOOL bIsWEP = FALSE; - UINT cbHeaderOffset; - UINT FrameSize; + unsigned int cbHeaderOffset; + unsigned int FrameSize; WORD wEtherType = 0; int iSANodeIndex = -1; int iDANodeIndex = -1; - UINT ii; - UINT cbIVOffset; + unsigned int ii; + unsigned int cbIVOffset; BOOL bExtIV = FALSE; PBYTE pbyRxSts; PBYTE pbyRxRate; PBYTE pbySQ; - UINT cbHeaderSize; + unsigned int cbHeaderSize; PSKeyItem pKey = NULL; WORD wRxTSC15_0 = 0; DWORD dwRxTSC47_16 = 0; @@ -1165,7 +1165,7 @@ static BOOL s_bAPModeRxCtl ( static BOOL s_bHandleRxEncryption ( PSDevice pDevice, PBYTE pbyFrame, - UINT FrameSize, + unsigned int FrameSize, PBYTE pbyRsr, PBYTE pbyNewRsr, PSKeyItem *pKeyOut, @@ -1174,7 +1174,7 @@ static BOOL s_bHandleRxEncryption ( PDWORD pdwRxTSC47_16 ) { - UINT PayloadLen = FrameSize; + unsigned int PayloadLen = FrameSize; PBYTE pbyIV; BYTE byKeyIdx; PSKeyItem pKey = NULL; @@ -1311,7 +1311,7 @@ static BOOL s_bHandleRxEncryption ( static BOOL s_bHostWepRxEncryption ( PSDevice pDevice, PBYTE pbyFrame, - UINT FrameSize, + unsigned int FrameSize, PBYTE pbyRsr, BOOL bOnFly, PSKeyItem pKey, @@ -1321,7 +1321,7 @@ static BOOL s_bHostWepRxEncryption ( PDWORD pdwRxTSC47_16 ) { - UINT PayloadLen = FrameSize; + unsigned int PayloadLen = FrameSize; PBYTE pbyIV; BYTE byKeyIdx; BYTE byDecMode = KEY_CTL_WEP; @@ -1442,8 +1442,8 @@ static BOOL s_bHostWepRxEncryption ( static BOOL s_bAPModeRxData ( PSDevice pDevice, struct sk_buff* skb, - UINT FrameSize, - UINT cbHeaderOffset, + unsigned int FrameSize, + unsigned int cbHeaderOffset, int iSANodeIndex, int iDANodeIndex ) @@ -1515,7 +1515,7 @@ static BOOL s_bAPModeRxData ( iDANodeIndex = 0; if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { - ROUTEbRelay(pDevice, (PBYTE)(skb->data + cbHeaderOffset), FrameSize, (UINT)iDANodeIndex); + ROUTEbRelay(pDevice, (PBYTE)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex); } if (bRelayOnly) diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index 195cc36654ae..01429d1a95b5 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -215,7 +215,7 @@ int vt6655_hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked) static int hostap_remove_sta(PSDevice pDevice, struct viawget_hostapd_param *param) { - UINT uNodeIndex; + unsigned int uNodeIndex; if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) { @@ -244,7 +244,7 @@ static int hostap_add_sta(PSDevice pDevice, struct viawget_hostapd_param *param) { PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uNodeIndex; + unsigned int uNodeIndex; if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { @@ -304,7 +304,7 @@ static int hostap_get_info_sta(PSDevice pDevice, struct viawget_hostapd_param *param) { PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uNodeIndex; + unsigned int uNodeIndex; if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { param->u.get_info_sta.inactive_sec = @@ -338,7 +338,7 @@ static int hostap_reset_txexc_sta(PSDevice pDevice, struct viawget_hostapd_param *param) { PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uNodeIndex; + unsigned int uNodeIndex; if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0; @@ -368,13 +368,13 @@ static int hostap_set_flags_sta(PSDevice pDevice, struct viawget_hostapd_param *param) { PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uNodeIndex; + unsigned int uNodeIndex; if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or; pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n", - (UINT)pMgmt->sNodeDBTable[uNodeIndex].dwFlags); + (unsigned int)pMgmt->sNodeDBTable[uNodeIndex].dwFlags); } else { return -ENOENT; diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index d8c8ee572334..b7049938c30a 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -70,10 +70,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { SNodeList sNodeList; PSBSSIDList pList; PSNodeList pNodeList; - UINT cbListCount; + unsigned int cbListCount; PKnownBSS pBSS; PKnownNodeDB pNode; - UINT ii, jj; + unsigned int ii, jj; SCmdLinkStatus sLinkStatus; BYTE abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -341,7 +341,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo; // pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); - pList->sBSSIDList[ii].uRSSI = (UINT)ldBm; + pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm; memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN); pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1); diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index f778e7d670cc..74c0b9afd658 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -714,7 +714,7 @@ if (pMgmt->eScanState == WMAC_IS_SCANNING) { //mike add: if desired AP is hidden ssid(there are two same BSSID in list), // then ignore,because you don't known which one to be connect with?? { - UINT ii , uSameBssidNum=0; + unsigned int ii , uSameBssidNum=0; for (ii = 0; ii < MAX_BSS_NUM; ii++) { if (pMgmt->sBSSList[ii].bActive && !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) { @@ -886,7 +886,7 @@ if (pMgmt->eScanState == WMAC_IS_SCANNING) { { PKnownBSS pCurr = NULL; BYTE abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; - UINT ii , uSameBssidNum=0; + unsigned int ii , uSameBssidNum=0; memcpy(abyTmpDesireSSID,pMgmt->abyDesireSSID,sizeof(abyTmpDesireSSID)); pCurr = BSSpSearchBSSList(pDevice, @@ -1515,7 +1515,7 @@ int iwctl_giwencode(struct net_device *dev, PSMgmtObject pMgmt = &(pDevice->sMgmtObj); int rc = 0; char abyKey[WLAN_WEP232_KEYLEN]; - UINT index = (UINT)(wrq->flags & IW_ENCODE_INDEX); + unsigned int index = (unsigned int)(wrq->flags & IW_ENCODE_INDEX); PSKeyItem pKey = NULL; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); @@ -1584,7 +1584,7 @@ int iwctl_giwencode(struct net_device *dev, PSMgmtObject pMgmt = &(pDevice->sMgmtObj); char abyKey[WLAN_WEP232_KEYLEN]; - UINT index = (UINT)(wrq->flags & IW_ENCODE_INDEX); + unsigned int index = (unsigned int)(wrq->flags & IW_ENCODE_INDEX); PSKeyItem pKey = NULL; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index f8527a704635..da5def3214b3 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -202,9 +202,9 @@ BOOL KeybSetKey ( ) { int i,j; - UINT ii; + unsigned int ii; PSKeyItem pKey; - UINT uKeyIdx; + unsigned int uKeyIdx; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); @@ -642,9 +642,9 @@ BOOL KeybSetDefaultKey ( BYTE byLocalID ) { - UINT ii; + unsigned int ii; PSKeyItem pKey; - UINT uKeyIdx; + unsigned int uKeyIdx; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetDefaultKey: %1x, %d \n", (int)dwKeyIndex, (int)uKeyLength); @@ -750,9 +750,9 @@ BOOL KeybSetAllGroupKey ( ) { int i; - UINT ii; + unsigned int ii; PSKeyItem pKey; - UINT uKeyIdx; + unsigned int uKeyIdx; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index eae881c5a9f9..f4acb2f3213f 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -209,7 +209,7 @@ BOOL MACbIsIntDisable (DWORD_PTR dwIoBase) * Return Value: Mask Value read * */ -BYTE MACbyReadMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx) +BYTE MACbyReadMultiAddr (DWORD_PTR dwIoBase, unsigned int uByteIdx) { BYTE byData; @@ -234,7 +234,7 @@ BYTE MACbyReadMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx) * Return Value: none * */ -void MACvWriteMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx, BYTE byData) +void MACvWriteMultiAddr (DWORD_PTR dwIoBase, unsigned int uByteIdx, BYTE byData) { MACvSelectPage1(dwIoBase); VNSvOutPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, byData); @@ -257,7 +257,7 @@ void MACvWriteMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx, BYTE byData) */ void MACvSetMultiAddrByHash (DWORD_PTR dwIoBase, BYTE byHashIdx) { - UINT uByteIdx; + unsigned int uByteIdx; BYTE byBitMask; BYTE byOrgValue; @@ -288,7 +288,7 @@ void MACvSetMultiAddrByHash (DWORD_PTR dwIoBase, BYTE byHashIdx) */ void MACvResetMultiAddrByHash (DWORD_PTR dwIoBase, BYTE byHashIdx) { - UINT uByteIdx; + unsigned int uByteIdx; BYTE byBitMask; BYTE byOrgValue; @@ -1244,10 +1244,10 @@ void MACvSetCurrTXDescAddr (int iTxType, DWORD_PTR dwIoBase, DWORD dwCurrDescAdd * Return Value: none * */ -void MACvTimer0MicroSDelay (DWORD_PTR dwIoBase, UINT uDelay) +void MACvTimer0MicroSDelay (DWORD_PTR dwIoBase, unsigned int uDelay) { BYTE byValue; -UINT uu,ii; +unsigned int uu,ii; VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelay); @@ -1280,7 +1280,7 @@ UINT uu,ii; * Return Value: none * */ -void MACvOneShotTimer0MicroSec (DWORD_PTR dwIoBase, UINT uDelayTime) +void MACvOneShotTimer0MicroSec (DWORD_PTR dwIoBase, unsigned int uDelayTime) { VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelayTime); @@ -1301,7 +1301,7 @@ void MACvOneShotTimer0MicroSec (DWORD_PTR dwIoBase, UINT uDelayTime) * Return Value: none * */ -void MACvOneShotTimer1MicroSec (DWORD_PTR dwIoBase, UINT uDelayTime) +void MACvOneShotTimer1MicroSec (DWORD_PTR dwIoBase, unsigned int uDelayTime) { VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0); VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime); @@ -1319,10 +1319,10 @@ void MACvSetMISCFifo (DWORD_PTR dwIoBase, WORD wOffset, DWORD dwData) } -BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, UINT idx) +BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, unsigned int idx) { BYTE byData; -UINT ww = 0; +unsigned int ww = 0; if (idx == TYPE_TXDMA0) { VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN); @@ -1350,7 +1350,7 @@ UINT ww = 0; void MACvClearBusSusInd (DWORD_PTR dwIoBase) { DWORD dwOrgValue; - UINT ww; + unsigned int ww; // check if BcnSusInd enabled VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); if( !(dwOrgValue & EnCFG_BcnSusInd)) @@ -1373,7 +1373,7 @@ void MACvEnableBusSusEn (DWORD_PTR dwIoBase) { BYTE byOrgValue; DWORD dwOrgValue; - UINT ww; + unsigned int ww; // check if BcnSusInd enabled VNSvInPortB(dwIoBase + MAC_REG_CFG , &byOrgValue); @@ -1394,7 +1394,7 @@ void MACvEnableBusSusEn (DWORD_PTR dwIoBase) BOOL MACbFlushSYNCFifo (DWORD_PTR dwIoBase) { BYTE byOrgValue; - UINT ww; + unsigned int ww; // Read MACCR VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue); @@ -1418,7 +1418,7 @@ BOOL MACbFlushSYNCFifo (DWORD_PTR dwIoBase) BOOL MACbPSWakeup (DWORD_PTR dwIoBase) { BYTE byOrgValue; - UINT ww; + unsigned int ww; // Read PSCTL if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) { return TRUE; @@ -1455,7 +1455,8 @@ BOOL MACbPSWakeup (DWORD_PTR dwIoBase) * */ -void MACvSetKeyEntry (DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, UINT uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID) +void MACvSetKeyEntry (DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, + unsigned int uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; @@ -1521,7 +1522,7 @@ int ii; * Return Value: none * */ -void MACvDisableKeyEntry (DWORD_PTR dwIoBase, UINT uEntryIdx) +void MACvDisableKeyEntry (DWORD_PTR dwIoBase, unsigned int uEntryIdx) { WORD wOffset; @@ -1549,7 +1550,8 @@ WORD wOffset; * */ -void MACvSetDefaultKeyEntry (DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID) +void MACvSetDefaultKeyEntry (DWORD_PTR dwIoBase, unsigned int uKeyLen, + unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; @@ -1664,7 +1666,8 @@ DWORD dwData; * Return Value: none * */ -void MACvSetDefaultTKIPKeyEntry (DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID) +void MACvSetDefaultTKIPKeyEntry (DWORD_PTR dwIoBase, unsigned int uKeyLen, + unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; @@ -1720,7 +1723,7 @@ int ii; * */ -void MACvSetDefaultKeyCtl (DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, BYTE byLocalID) +void MACvSetDefaultKeyCtl (DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, BYTE byLocalID) { WORD wOffset; DWORD dwData; diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 5eb7f57f7182..88a440398734 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -1082,8 +1082,8 @@ BOOL MACbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits); BOOL MACbIsIntDisable(DWORD_PTR dwIoBase); -BYTE MACbyReadMultiAddr(DWORD_PTR dwIoBase, UINT uByteIdx); -void MACvWriteMultiAddr(DWORD_PTR dwIoBase, UINT uByteIdx, BYTE byData); +BYTE MACbyReadMultiAddr(DWORD_PTR dwIoBase, unsigned int uByteIdx); +void MACvWriteMultiAddr(DWORD_PTR dwIoBase, unsigned int uByteIdx, BYTE byData); void MACvSetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); void MACvResetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); @@ -1125,13 +1125,13 @@ void MACvSetCurrTx0DescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); void MACvSetCurrAC0DescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); void MACvSetCurrSyncDescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); void MACvSetCurrATIMDescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); -void MACvTimer0MicroSDelay(DWORD_PTR dwIoBase, UINT uDelay); -void MACvOneShotTimer0MicroSec(DWORD_PTR dwIoBase, UINT uDelayTime); -void MACvOneShotTimer1MicroSec(DWORD_PTR dwIoBase, UINT uDelayTime); +void MACvTimer0MicroSDelay(DWORD_PTR dwIoBase, unsigned int uDelay); +void MACvOneShotTimer0MicroSec(DWORD_PTR dwIoBase, unsigned int uDelayTime); +void MACvOneShotTimer1MicroSec(DWORD_PTR dwIoBase, unsigned int uDelayTime); void MACvSetMISCFifo(DWORD_PTR dwIoBase, WORD wOffset, DWORD dwData); -BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, UINT idx); +BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, unsigned int idx); void MACvClearBusSusInd(DWORD_PTR dwIoBase); void MACvEnableBusSusEn(DWORD_PTR dwIoBase); @@ -1139,13 +1139,16 @@ void MACvEnableBusSusEn(DWORD_PTR dwIoBase); BOOL MACbFlushSYNCFifo(DWORD_PTR dwIoBase); BOOL MACbPSWakeup(DWORD_PTR dwIoBase); -void MACvSetKeyEntry(DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, UINT uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID); -void MACvDisableKeyEntry(DWORD_PTR dwIoBase, UINT uEntryIdx); -void MACvSetDefaultKeyEntry(DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID); +void MACvSetKeyEntry(DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, + unsigned int uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID); +void MACvDisableKeyEntry(DWORD_PTR dwIoBase, unsigned int uEntryIdx); +void MACvSetDefaultKeyEntry(DWORD_PTR dwIoBase, unsigned int uKeyLen, + unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID); //void MACvEnableDefaultKey(DWORD_PTR dwIoBase, BYTE byLocalID); void MACvDisableDefaultKey(DWORD_PTR dwIoBase); -void MACvSetDefaultTKIPKeyEntry(DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID); -void MACvSetDefaultKeyCtl(DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, BYTE byLocalID); +void MACvSetDefaultTKIPKeyEntry(DWORD_PTR dwIoBase, unsigned int uKeyLen, + unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID); +void MACvSetDefaultKeyCtl(DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, BYTE byLocalID); #endif // __MAC_H__ diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index b4e916f2c650..e6cab78de0f4 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -178,7 +178,7 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, DWORD dwIsr) */ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, - PBYTE pbyBuffer, UINT cbFrameLength) + PBYTE pbyBuffer, unsigned int cbFrameLength) { //need change PS802_11Header pHeader = (PS802_11Header)pbyBuffer; @@ -393,7 +393,7 @@ STAvUpdateRDStatCounterEx ( BYTE byNewRSR, BYTE byRxRate, PBYTE pbyBuffer, - UINT cbFrameLength + unsigned int cbFrameLength ) { STAvUpdateRDStatCounter( @@ -435,8 +435,8 @@ STAvUpdateTDStatCounter ( BYTE byTSR0, BYTE byTSR1, PBYTE pbyBuffer, - UINT cbFrameLength, - UINT uIdx + unsigned int cbFrameLength, + unsigned int uIdx ) { PWLAN_80211HDR_A4 pHeader; @@ -526,9 +526,9 @@ STAvUpdateTDStatCounterEx ( DWORD cbFrameLength ) { - UINT uPktLength; + unsigned int uPktLength; - uPktLength = (UINT)cbFrameLength; + uPktLength = (unsigned int)cbFrameLength; // tx length pStatistic->dwCntTxBufLength = uPktLength; diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 190fc475e5d5..ffd5fb1d39d5 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -301,7 +301,7 @@ typedef struct tagSStatCounter { DWORD dwCntRxDataErr; // rx buffer data software compare CRC err count DWORD dwCntDecryptErr; // rx buffer data software compare CRC err count DWORD dwCntRxICVErr; // rx buffer data software compare CRC err count - UINT idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD + unsigned int idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD // 64-bit OID ULONGLONG ullTsrOK[TYPE_MAXTD]; @@ -348,15 +348,14 @@ void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, DWORD dwIsr); void STAvUpdateRDStatCounter(PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, - PBYTE pbyBuffer, UINT cbFrameLength); + PBYTE pbyBuffer, unsigned int cbFrameLength); void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRsr, BYTE byRxRate, - PBYTE pbyBuffer, UINT cbFrameLength); + PBYTE pbyBuffer, unsigned int cbFrameLength); -void STAvUpdateTDStatCounter(PSStatCounter pStatistic, - BYTE byTSR0, BYTE byTSR1, - PBYTE pbyBuffer, UINT cbFrameLength, UINT uIdx ); +void STAvUpdateTDStatCounter(PSStatCounter pStatistic, BYTE byTSR0, BYTE byTSR1, + PBYTE pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx); void STAvUpdateTDStatCounterEx( PSStatCounter pStatistic, diff --git a/drivers/staging/vt6655/michael.c b/drivers/staging/vt6655/michael.c index 0bf57efdede0..3a92257bd3e8 100644 --- a/drivers/staging/vt6655/michael.c +++ b/drivers/staging/vt6655/michael.c @@ -61,7 +61,7 @@ static DWORD L, R; // Current state static DWORD K0, K1; // Key static DWORD M; // Message accumulator (single word) -static UINT nBytesInM; // # bytes in M +static unsigned int nBytesInM; // # bytes in M /*--------------------- Export Functions --------------------------*/ @@ -70,7 +70,7 @@ static DWORD s_dwGetUINT32 (BYTE * p) // Convert from BYTE[] to DWORD in a portable way { DWORD res = 0; - UINT i; + unsigned int i; for(i=0; i<4; i++ ) { res |= (*p++) << (8*i); @@ -81,7 +81,7 @@ static DWORD s_dwGetUINT32 (BYTE * p) static void s_vPutUINT32 (BYTE* p, DWORD val) // Convert from DWORD to BYTE[] in a portable way { - UINT i; + unsigned int i; for(i=0; i<4; i++ ) { *p++ = (BYTE) (val & 0xff); @@ -149,7 +149,7 @@ void MIC_vUnInit (void) s_vClear(); } -void MIC_vAppend (PBYTE src, UINT nBytes) +void MIC_vAppend (PBYTE src, unsigned int nBytes) { // This is simple while (nBytes > 0) diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h index 97de77b4da2c..c1584a0ce7a1 100644 --- a/drivers/staging/vt6655/michael.h +++ b/drivers/staging/vt6655/michael.h @@ -40,7 +40,7 @@ void MIC_vInit(DWORD dwK0, DWORD dwK1); void MIC_vUnInit(void); // Append bytes to the message to be MICed -void MIC_vAppend(PBYTE src, UINT nBytes); +void MIC_vAppend(PBYTE src, unsigned int nBytes); // Get the MIC result. Destination should accept 8 bytes of result. // This also resets the message to empty. diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 64c22c3e4bb3..d4e076513f63 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -191,7 +191,7 @@ PSbConsiderPowerDown( { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uIdx; + unsigned int uIdx; // check if already in Doze mode if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) @@ -304,7 +304,7 @@ PSbSendNullPacket( PSDevice pDevice = (PSDevice)hDeviceContext; PSTxMgmtPacket pTxPacket = NULL; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT uIdx; + unsigned int uIdx; if (pDevice->bLinkPass == FALSE) { diff --git a/drivers/staging/vt6655/rc4.c b/drivers/staging/vt6655/rc4.c index 4a53f159cb30..0d641ffefc99 100644 --- a/drivers/staging/vt6655/rc4.c +++ b/drivers/staging/vt6655/rc4.c @@ -32,13 +32,13 @@ #include "rc4.h" -void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, UINT cbKey_len) +void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len) { - UINT ust1, ust2; - UINT keyindex; - UINT stateindex; + unsigned int ust1, ust2; + unsigned int keyindex; + unsigned int stateindex; PBYTE pbyst; - UINT idx; + unsigned int idx; pbyst = pRC4->abystate; pRC4->ux = 0; @@ -58,11 +58,11 @@ void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, UINT cbKey_len) } } -UINT rc4_byte(PRC4Ext pRC4) +unsigned int rc4_byte(PRC4Ext pRC4) { - UINT ux; - UINT uy; - UINT ustx, usty; + unsigned int ux; + unsigned int uy; + unsigned int ustx, usty; PBYTE pbyst; pbyst = pRC4->abystate; @@ -79,9 +79,9 @@ UINT rc4_byte(PRC4Ext pRC4) } void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, - PBYTE pbySrc, UINT cbData_len) + PBYTE pbySrc, unsigned int cbData_len) { - UINT ii; + unsigned int ii; for (ii = 0; ii < cbData_len; ii++) pbyDest[ii] = (BYTE)(pbySrc[ii] ^ rc4_byte(pRC4)); } diff --git a/drivers/staging/vt6655/rc4.h b/drivers/staging/vt6655/rc4.h index e65cae69efaf..a40030461c12 100644 --- a/drivers/staging/vt6655/rc4.h +++ b/drivers/staging/vt6655/rc4.h @@ -35,13 +35,13 @@ /*--------------------- Export Definitions -------------------------*/ /*--------------------- Export Types ------------------------------*/ typedef struct { - UINT ux; - UINT uy; + unsigned int ux; + unsigned int uy; BYTE abystate[256]; } RC4Ext, *PRC4Ext; -void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, UINT cbKey_len); -UINT rc4_byte(PRC4Ext pRC4); -void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, PBYTE pbySrc, UINT cbData_len); +void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len); +unsigned int rc4_byte(PRC4Ext pRC4); +void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, PBYTE pbySrc, unsigned int cbData_len); #endif //__RC4_H__ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 4f2c01bceb76..c86504dc38b8 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -911,7 +911,7 @@ BOOL bResult = TRUE; * Return Value: None. * */ -BOOL RFvWriteWakeProgSyn (DWORD_PTR dwIoBase, BYTE byRFType, UINT uChannel) +BOOL RFvWriteWakeProgSyn (DWORD_PTR dwIoBase, BYTE byRFType, unsigned int uChannel) { int ii; BYTE byInitCount = 0; @@ -998,8 +998,8 @@ BOOL RFvWriteWakeProgSyn (DWORD_PTR dwIoBase, BYTE byRFType, UINT uChannel) */ BOOL RFbSetPower ( PSDevice pDevice, - UINT uRATE, - UINT uCH + unsigned int uRATE, + unsigned int uCH ) { BOOL bResult = TRUE; @@ -1138,7 +1138,7 @@ BYTE byPwrdBm = 0; BOOL RFbRawSetPower ( PSDevice pDevice, BYTE byPwr, - UINT uRATE + unsigned int uRATE ) { BOOL bResult = TRUE; diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index 25dfc7942f67..7571b3d1ca48 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -81,12 +81,12 @@ BOOL RFbSelectChannel(DWORD_PTR dwIoBase, BYTE byRFType, BYTE byChannel); BOOL RFbInit ( PSDevice pDevice ); -BOOL RFvWriteWakeProgSyn(DWORD_PTR dwIoBase, BYTE byRFType, UINT uChannel); -BOOL RFbSetPower(PSDevice pDevice, UINT uRATE, UINT uCH); +BOOL RFvWriteWakeProgSyn(DWORD_PTR dwIoBase, BYTE byRFType, unsigned int uChannel); +BOOL RFbSetPower(PSDevice pDevice, unsigned int uRATE, unsigned int uCH); BOOL RFbRawSetPower( PSDevice pDevice, BYTE byPwr, - UINT uRATE + unsigned int uRATE ); void diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 590fc7f7fcb5..271a4ab94886 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -134,7 +134,7 @@ s_vFillRTSHead( PSDevice pDevice, BYTE byPktType, void * pvRTS, - UINT cbFrameLength, + unsigned int cbFrameLength, BOOL bNeedAck, BOOL bDisCRC, PSEthernetHeader psEthHeader, @@ -151,9 +151,9 @@ s_vGenerateTxParameter( void * pvRrvTime, void * pvRTS, void * pvCTS, - UINT cbFrameSize, + unsigned int cbFrameSize, BOOL bNeedACK, - UINT uDMAIdx, + unsigned int uDMAIdx, PSEthernetHeader psEthHeader, WORD wCurrentRate ); @@ -163,43 +163,43 @@ s_vGenerateTxParameter( static void s_vFillFragParameter( PSDevice pDevice, PBYTE pbyBuffer, - UINT uTxType, + unsigned int uTxType, void * pvtdCurr, WORD wFragType, - UINT cbReqCount + unsigned int cbReqCount ); static -UINT +unsigned int s_cbFillTxBufHead ( PSDevice pDevice, BYTE byPktType, PBYTE pbyTxBufferAddr, - UINT cbFrameBodySize, - UINT uDMAIdx, + unsigned int cbFrameBodySize, + unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, PBYTE pPacket, BOOL bNeedEncrypt, PSKeyItem pTransmitKey, - UINT uNodeIndex, + unsigned int uNodeIndex, PUINT puMACfragNum ); static -UINT +unsigned int s_uFillDataHead ( PSDevice pDevice, BYTE byPktType, void * pTxDataHead, - UINT cbFrameLength, - UINT uDMAIdx, + unsigned int cbFrameLength, + unsigned int uDMAIdx, BOOL bNeedAck, - UINT uFragIdx, - UINT cbLastFragmentSize, - UINT uMACfragNum, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, BYTE byFBOption, WORD wCurrentRate ); @@ -336,7 +336,7 @@ s_vSWencryption ( WORD wPayloadSize ) { - UINT cbICVlen = 4; + unsigned int cbICVlen = 4; DWORD dwICV = 0xFFFFFFFFL; PDWORD pdwICV; @@ -377,16 +377,16 @@ s_vSWencryption ( PK_TYPE_11GA 3 */ static -UINT +unsigned int s_uGetTxRsvTime ( PSDevice pDevice, BYTE byPktType, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wRate, BOOL bNeedAck ) { - UINT uDataTime, uAckTime; + unsigned int uDataTime, uAckTime; uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate); #ifdef PLICE_DEBUG @@ -408,16 +408,16 @@ s_uGetTxRsvTime ( //byFreqType: 0=>5GHZ 1=>2.4GHZ static -UINT +unsigned int s_uGetRTSCTSRsvTime ( PSDevice pDevice, BYTE byRTSRsvType, BYTE byPktType, - UINT cbFrameLength, + unsigned int cbFrameLength, WORD wCurrentRate ) { - UINT uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; + unsigned int uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; @@ -450,22 +450,22 @@ s_uGetRTSCTSRsvTime ( //byFreqType 0: 5GHz, 1:2.4Ghz static -UINT +unsigned int s_uGetDataDuration ( PSDevice pDevice, BYTE byDurType, - UINT cbFrameLength, + unsigned int cbFrameLength, BYTE byPktType, WORD wRate, BOOL bNeedAck, - UINT uFragIdx, - UINT cbLastFragmentSize, - UINT uMACfragNum, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, BYTE byFBOption ) { BOOL bLastFrag = 0; - UINT uAckTime =0, uNextPktTime = 0; + unsigned int uAckTime =0, uNextPktTime = 0; @@ -621,18 +621,18 @@ s_uGetDataDuration ( //byFreqType: 0=>5GHZ 1=>2.4GHZ static -UINT +unsigned int s_uGetRTSCTSDuration ( PSDevice pDevice, BYTE byDurType, - UINT cbFrameLength, + unsigned int cbFrameLength, BYTE byPktType, WORD wRate, BOOL bNeedAck, BYTE byFBOption ) { - UINT uCTSTime = 0, uDurTime = 0; + unsigned int uCTSTime = 0, uDurTime = 0; switch (byDurType) { @@ -719,17 +719,17 @@ s_uGetRTSCTSDuration ( static -UINT +unsigned int s_uFillDataHead ( PSDevice pDevice, BYTE byPktType, void * pTxDataHead, - UINT cbFrameLength, - UINT uDMAIdx, + unsigned int cbFrameLength, + unsigned int uDMAIdx, BOOL bNeedAck, - UINT uFragIdx, - UINT cbLastFragmentSize, - UINT uMACfragNum, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, BYTE byFBOption, WORD wCurrentRate ) @@ -856,7 +856,7 @@ s_vFillRTSHead ( PSDevice pDevice, BYTE byPktType, void * pvRTS, - UINT cbFrameLength, + unsigned int cbFrameLength, BOOL bNeedAck, BOOL bDisCRC, PSEthernetHeader psEthHeader, @@ -864,7 +864,7 @@ s_vFillRTSHead ( BYTE byFBOption ) { - UINT uRTSFrameLen = 20; + unsigned int uRTSFrameLen = 20; WORD wLen = 0x0000; if (pvRTS == NULL) @@ -1048,17 +1048,17 @@ static void s_vFillCTSHead ( PSDevice pDevice, - UINT uDMAIdx, + unsigned int uDMAIdx, BYTE byPktType, void * pvCTS, - UINT cbFrameLength, + unsigned int cbFrameLength, BOOL bNeedAck, BOOL bDisCRC, WORD wCurrentRate, BYTE byFBOption ) { - UINT uCTSFrameLen = 14; + unsigned int uCTSFrameLen = 14; WORD wLen = 0x0000; if (pvCTS == NULL) { @@ -1148,7 +1148,7 @@ s_vFillCTSHead ( * Return Value: none * -*/ -// UINT cbFrameSize,//Hdr+Payload+FCS +// unsigned int cbFrameSize,//Hdr+Payload+FCS static void s_vGenerateTxParameter ( @@ -1158,14 +1158,14 @@ s_vGenerateTxParameter ( void * pvRrvTime, void * pvRTS, void * pvCTS, - UINT cbFrameSize, + unsigned int cbFrameSize, BOOL bNeedACK, - UINT uDMAIdx, + unsigned int uDMAIdx, PSEthernetHeader psEthHeader, WORD wCurrentRate ) { - UINT cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24 + unsigned int cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24 WORD wFifoCtl; BOOL bDisCRC = FALSE; BYTE byFBOption = AUTO_FB_NONE; @@ -1265,17 +1265,17 @@ s_vGenerateTxParameter ( /* PBYTE pbyBuffer,//point to pTxBufHead WORD wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last - UINT cbFragmentSize,//Hdr+payoad+FCS + unsigned int cbFragmentSize,//Hdr+payoad+FCS */ static void s_vFillFragParameter( PSDevice pDevice, PBYTE pbyBuffer, - UINT uTxType, + unsigned int uTxType, void * pvtdCurr, WORD wFragType, - UINT cbReqCount + unsigned int cbReqCount ) { PSTxBufHead pTxBufHead = (PSTxBufHead) pbyBuffer; @@ -1316,57 +1316,57 @@ s_vFillFragParameter( } static -UINT +unsigned int s_cbFillTxBufHead ( PSDevice pDevice, BYTE byPktType, PBYTE pbyTxBufferAddr, - UINT cbFrameBodySize, - UINT uDMAIdx, + unsigned int cbFrameBodySize, + unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, PBYTE pPacket, BOOL bNeedEncrypt, PSKeyItem pTransmitKey, - UINT uNodeIndex, + unsigned int uNodeIndex, PUINT puMACfragNum ) { - UINT cbMACHdLen; - UINT cbFrameSize; - UINT cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS - UINT cbFragPayloadSize; - UINT cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS - UINT cbLastFragPayloadSize; - UINT uFragIdx; + unsigned int cbMACHdLen; + unsigned int cbFrameSize; + unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + unsigned int cbFragPayloadSize; + unsigned int cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + unsigned int cbLastFragPayloadSize; + unsigned int uFragIdx; PBYTE pbyPayloadHead; PBYTE pbyIVHead; PBYTE pbyMacHdr; WORD wFragType; //00:Non-Frag, 01:Start, 10:Mid, 11:Last - UINT uDuration; + unsigned int uDuration; PBYTE pbyBuffer; -// UINT uKeyEntryIdx = NUM_KEY_ENTRY+1; +// unsigned int uKeyEntryIdx = NUM_KEY_ENTRY+1; // BYTE byKeySel = 0xFF; - UINT cbIVlen = 0; - UINT cbICVlen = 0; - UINT cbMIClen = 0; - UINT cbFCSlen = 4; - UINT cb802_1_H_len = 0; - UINT uLength = 0; - UINT uTmpLen = 0; + unsigned int cbIVlen = 0; + unsigned int cbICVlen = 0; + unsigned int cbMIClen = 0; + unsigned int cbFCSlen = 4; + unsigned int cb802_1_H_len = 0; + unsigned int uLength = 0; + unsigned int uTmpLen = 0; // BYTE abyTmp[8]; // DWORD dwCRC; - UINT cbMICHDR = 0; + unsigned int cbMICHDR = 0; DWORD dwMICKey0, dwMICKey1; DWORD dwMIC_Priority; PDWORD pdwMIC_L; PDWORD pdwMIC_R; DWORD dwSafeMIC_L, dwSafeMIC_R; //Fix "Last Frag Size" < "MIC length". BOOL bMIC2Frag = FALSE; - UINT uMICFragLen = 0; - UINT uMACfragNum = 1; - UINT uPadding = 0; - UINT cbReqCount = 0; + unsigned int uMICFragLen = 0; + unsigned int uMACfragNum = 1; + unsigned int uPadding = 0; + unsigned int cbReqCount = 0; BOOL bNeedACK; BOOL bRTS; @@ -1374,15 +1374,15 @@ s_cbFillTxBufHead ( PBYTE pbyType; PSTxDesc ptdCurr; PSTxBufHead psTxBufHd = (PSTxBufHead) pbyTxBufferAddr; -// UINT tmpDescIdx; - UINT cbHeaderLength = 0; +// unsigned int tmpDescIdx; + unsigned int cbHeaderLength = 0; void * pvRrvTime; PSMICHDRHead pMICHDR; void * pvRTS; void * pvCTS; void * pvTxDataHd; WORD wTxBufSize; // FFinfo size - UINT uTotalCopyLength = 0; + unsigned int uTotalCopyLength = 0; BYTE byFBOption = AUTO_FB_NONE; BOOL bIsWEP256 = FALSE; PSMgmtObject pMgmt = pDevice->pMgmt; @@ -2099,18 +2099,18 @@ vGenerateFIFOHeader ( BYTE byPktType, PBYTE pbyTxBufferAddr, BOOL bNeedEncrypt, - UINT cbPayloadSize, - UINT uDMAIdx, + unsigned int cbPayloadSize, + unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, PBYTE pPacket, PSKeyItem pTransmitKey, - UINT uNodeIndex, + unsigned int uNodeIndex, PUINT puMACfragNum, PUINT pcbHeaderSize ) { - UINT wTxBufSize; // FFinfo size + unsigned int wTxBufSize; // FFinfo size BOOL bNeedACK; BOOL bIsAdhoc; WORD cbMacHdLen; @@ -2272,8 +2272,8 @@ vGenerateMACHeader ( PSEthernetHeader psEthHeader, BOOL bNeedEncrypt, WORD wFragType, - UINT uDMAIdx, - UINT uFragIdx + unsigned int uDMAIdx, + unsigned int uFragIdx ) { PS802_11Header pMACHeader = (PS802_11Header)pbyBufferAddr; @@ -2345,22 +2345,22 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { void * pvRTS; PSCTS pCTS; void * pvTxDataHd; - UINT uDuration; - UINT cbReqCount; + unsigned int uDuration; + unsigned int cbReqCount; PS802_11Header pMACHeader; - UINT cbHeaderSize; - UINT cbFrameBodySize; + unsigned int cbHeaderSize; + unsigned int cbFrameBodySize; BOOL bNeedACK; BOOL bIsPSPOLL = FALSE; PSTxBufHead pTxBufHead; - UINT cbFrameSize; - UINT cbIVlen = 0; - UINT cbICVlen = 0; - UINT cbMIClen = 0; - UINT cbFCSlen = 4; - UINT uPadding = 0; + unsigned int cbFrameSize; + unsigned int cbIVlen = 0; + unsigned int cbICVlen = 0; + unsigned int cbMIClen = 0; + unsigned int cbFCSlen = 4; + unsigned int uPadding = 0; WORD wTxBufSize; - UINT cbMacHdLen; + unsigned int cbMacHdLen; SEthernetHeader sEthHeader; void * pvRrvTime; void * pMICHDR; @@ -2663,8 +2663,8 @@ CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { BYTE byPktType; PBYTE pbyBuffer = (PBYTE)pDevice->tx_beacon_bufs; - UINT cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; - UINT cbHeaderSize = 0; + unsigned int cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; + unsigned int cbHeaderSize = 0; WORD wTxBufSize = sizeof(STxShortBufHead); PSTxShortBufHead pTxBufHead = (PSTxShortBufHead) pbyBuffer; PSTxDataHead_ab pTxDataHead = (PSTxDataHead_ab) (pbyBuffer + wTxBufSize); @@ -2736,24 +2736,24 @@ CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { -UINT +unsigned int cbGetFragCount ( PSDevice pDevice, PSKeyItem pTransmitKey, - UINT cbFrameBodySize, + unsigned int cbFrameBodySize, PSEthernetHeader psEthHeader ) { - UINT cbMACHdLen; - UINT cbFrameSize; - UINT cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS - UINT cbFragPayloadSize; - UINT cbLastFragPayloadSize; - UINT cbIVlen = 0; - UINT cbICVlen = 0; - UINT cbMIClen = 0; - UINT cbFCSlen = 4; - UINT uMACfragNum = 1; + unsigned int cbMACHdLen; + unsigned int cbFrameSize; + unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + unsigned int cbFragPayloadSize; + unsigned int cbLastFragPayloadSize; + unsigned int cbIVlen = 0; + unsigned int cbICVlen = 0; + unsigned int cbMIClen = 0; + unsigned int cbFCSlen = 4; + unsigned int uMACfragNum = 1; BOOL bNeedACK; @@ -2826,7 +2826,7 @@ cbGetFragCount ( void -vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDULen) { +vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned int cbMPDULen) { PSTxDesc pFrstTD; BYTE byPktType; @@ -2834,35 +2834,35 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDU void * pvRTS; void * pvCTS; void * pvTxDataHd; - UINT uDuration; - UINT cbReqCount; + unsigned int uDuration; + unsigned int cbReqCount; PS802_11Header pMACHeader; - UINT cbHeaderSize; - UINT cbFrameBodySize; + unsigned int cbHeaderSize; + unsigned int cbFrameBodySize; BOOL bNeedACK; BOOL bIsPSPOLL = FALSE; PSTxBufHead pTxBufHead; - UINT cbFrameSize; - UINT cbIVlen = 0; - UINT cbICVlen = 0; - UINT cbMIClen = 0; - UINT cbFCSlen = 4; - UINT uPadding = 0; - UINT cbMICHDR = 0; - UINT uLength = 0; + unsigned int cbFrameSize; + unsigned int cbIVlen = 0; + unsigned int cbICVlen = 0; + unsigned int cbMIClen = 0; + unsigned int cbFCSlen = 4; + unsigned int uPadding = 0; + unsigned int cbMICHDR = 0; + unsigned int uLength = 0; DWORD dwMICKey0, dwMICKey1; DWORD dwMIC_Priority; PDWORD pdwMIC_L; PDWORD pdwMIC_R; WORD wTxBufSize; - UINT cbMacHdLen; + unsigned int cbMacHdLen; SEthernetHeader sEthHeader; void * pvRrvTime; void * pMICHDR; PSMgmtObject pMgmt = pDevice->pMgmt; WORD wCurrentRate = RATE_1M; PUWLAN_80211HDR p80211Header; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; BOOL bNodeExist = FALSE; SKeyItem STempKey; PSKeyItem pTransmitKey = NULL; @@ -2870,7 +2870,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDU PBYTE pbyPayloadHead; PBYTE pbyMacHdr; - UINT cbExtSuppRate = 0; + unsigned int cbExtSuppRate = 0; // PWLAN_IE pItem; diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index b008fc23adb9..e2754071317e 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -44,7 +44,7 @@ void vGenerateMACHeader( PSDevice pDevice, DWORD dwTxBufferAddr, PBYTE pbySkbData, - UINT cbPacketSize, + unsigned int cbPacketSize, BOOL bDMA0Used, PUINT pcbHeadSize, PUINT pcbAppendPayload @@ -53,7 +53,7 @@ void vGenerateMACHeader( void vProcessRxMACHeader ( PSDevice pDevice, DWORD dwRxBufferAddr, - UINT cbPacketSize, + unsigned int cbPacketSize, BOOL bIsWEP, PUINT pcbHeadSize ); @@ -68,16 +68,16 @@ vGenerateMACHeader ( PSEthernetHeader psEthHeader, BOOL bNeedEncrypt, WORD wFragType, - UINT uDMAIdx, - UINT uFragIdx + unsigned int uDMAIdx, + unsigned int uFragIdx ); -UINT +unsigned int cbGetFragCount( PSDevice pDevice, PSKeyItem pTransmitKey, - UINT cbFrameBodySize, + unsigned int cbFrameBodySize, PSEthernetHeader psEthHeader ); @@ -88,19 +88,19 @@ vGenerateFIFOHeader ( BYTE byPktTyp, PBYTE pbyTxBufferAddr, BOOL bNeedEncrypt, - UINT cbPayloadSize, - UINT uDMAIdx, + unsigned int cbPayloadSize, + unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, PBYTE pPacket, PSKeyItem pTransmitKey, - UINT uNodeIndex, + unsigned int uNodeIndex, PUINT puMACfragNum, PUINT pcbHeaderSize ); -void vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDULen); +void vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned int cbMPDULen); CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); diff --git a/drivers/staging/vt6655/tcrc.c b/drivers/staging/vt6655/tcrc.c index 5f0c74763f87..d13e8e1ccd96 100644 --- a/drivers/staging/vt6655/tcrc.c +++ b/drivers/staging/vt6655/tcrc.c @@ -132,7 +132,7 @@ static const DWORD s_adwCrc32Table[256] = { * Return Value: CRC-32 * -*/ -DWORD CRCdwCrc32 (PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed) +DWORD CRCdwCrc32 (PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed) { DWORD dwCrc; @@ -164,7 +164,7 @@ DWORD CRCdwCrc32 (PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed) * Return Value: CRC-32 * -*/ -DWORD CRCdwGetCrc32 (PBYTE pbyData, UINT cbByte) +DWORD CRCdwGetCrc32 (PBYTE pbyData, unsigned int cbByte) { return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL); } @@ -190,7 +190,7 @@ DWORD CRCdwGetCrc32 (PBYTE pbyData, UINT cbByte) * Return Value: CRC-32 * -*/ -DWORD CRCdwGetCrc32Ex(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC) +DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC) { return CRCdwCrc32(pbyData, cbByte, dwPreCRC); } diff --git a/drivers/staging/vt6655/tcrc.h b/drivers/staging/vt6655/tcrc.h index 5faa48b0a748..17581b2d6a0c 100644 --- a/drivers/staging/vt6655/tcrc.h +++ b/drivers/staging/vt6655/tcrc.h @@ -43,9 +43,9 @@ /*--------------------- Export Functions --------------------------*/ -DWORD CRCdwCrc32(PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed); -DWORD CRCdwGetCrc32(PBYTE pbyData, UINT cbByte); -DWORD CRCdwGetCrc32Ex(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC); +DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed); +DWORD CRCdwGetCrc32(PBYTE pbyData, unsigned int cbByte); +DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC); #endif // __TCRC_H__ diff --git a/drivers/staging/vt6655/tether.c b/drivers/staging/vt6655/tether.c index d8ba67395cb1..150647db1529 100644 --- a/drivers/staging/vt6655/tether.c +++ b/drivers/staging/vt6655/tether.c @@ -96,7 +96,7 @@ BYTE ETHbyGetHashIndexByCrc32 (PBYTE pbyMultiAddr) * Return Value: TRUE if ok; FALSE if error. * */ -BOOL ETHbIsBufferCrc32Ok (PBYTE pbyBuffer, UINT cbFrameLength) +BOOL ETHbIsBufferCrc32Ok (PBYTE pbyBuffer, unsigned int cbFrameLength) { DWORD dwCRC; diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index d0183a25e651..4a9d20287d7c 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -195,7 +195,7 @@ S802_11Header, *PS802_11Header; BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr); //BYTE ETHbyGetHashIndexByCrc(PBYTE pbyMultiAddr); -BOOL ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, UINT cbFrameLength); +BOOL ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, unsigned int cbFrameLength); #endif // __TETHER_H__ diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index eaf77d5348e4..23533a7d2990 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned int UINT; typedef unsigned long ULONG; typedef unsigned long long ULONGLONG; //64 bit diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index 680c4962cd33..21a9111e91ed 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -103,7 +103,7 @@ VNTWIFIvSetIBSSParameter ( void *pMgmtHandle, WORD wBeaconPeriod, WORD wATIMWindow, - UINT uChannel + unsigned int uChannel ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; @@ -150,7 +150,7 @@ VNTWIFIpGetCurrentSSID ( * Return Value: current Channel. * -*/ -UINT +unsigned int VNTWIFIpGetCurrentChannel ( void *pMgmtHandle ) @@ -210,7 +210,7 @@ VNTWIFIbyGetMaxSupportRate ( { BYTE byMaxSupportRate = RATE_1M; BYTE bySupportRate = RATE_1M; - UINT ii = 0; + unsigned int ii = 0; if (pSupportRateIEs) { for (ii = 0; ii < pSupportRateIEs->len; ii++) { @@ -257,7 +257,7 @@ VNTWIFIbyGetACKTxRate ( { BYTE byMaxAckRate; BYTE byBasicRate; - UINT ii; + unsigned int ii; if (byRxDataRate <= RATE_11M) { byMaxAckRate = RATE_1M; @@ -431,10 +431,10 @@ VNTWIFIvQueryBSSList ( void **pvFirstBSS ) { - UINT ii = 0; + unsigned int ii = 0; PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; PKnownBSS pBSS = NULL; - UINT uCount = 0; + unsigned int uCount = 0; *pvFirstBSS = NULL; @@ -504,8 +504,8 @@ VNTWIFIvUpdateNodeTxCounter( ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; - UINT uNodeIndex = 0; - UINT ii; + unsigned int uNodeIndex = 0; + unsigned int ii; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { @@ -540,7 +540,7 @@ VNTWIFIvGetTxRate( ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; WORD wTxDataRate = RATE_1M; BYTE byACKRate = RATE_1M; BYTE byCCKBasicRate = RATE_1M; @@ -626,7 +626,7 @@ VNTWIFIbInit( { PSMgmtObject pMgmt = NULL; - UINT ii; + unsigned int ii; pMgmt = (PSMgmtObject)kmalloc(sizeof(SMgmtObject), (int)GFP_ATOMIC); diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h index c91dfd79adca..683a6acef94c 100644 --- a/drivers/staging/vt6655/vntwifi.h +++ b/drivers/staging/vt6655/vntwifi.h @@ -145,7 +145,7 @@ VNTWIFIvSetIBSSParameter ( void *pMgmtHandle, WORD wBeaconPeriod, WORD wATIMWindow, - UINT uChannel + unsigned int uChannel ); void @@ -159,7 +159,7 @@ VNTWIFIpGetCurrentSSID( void *pMgmtHandle ); -UINT +unsigned int VNTWIFIpGetCurrentChannel( void *pMgmtHandle ); diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index c2bf287961a9..517cad9fbed2 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -216,7 +216,7 @@ s_vProbeChannel( PBYTE pbyRate; PSTxMgmtPacket pTxPacket; PSMgmtObject pMgmt = pDevice->pMgmt; - UINT ii; + unsigned int ii; if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { @@ -320,7 +320,7 @@ s_MgrMakeProbeRequest( void vCommandTimerWait( void *hDeviceContext, - UINT MSecond + unsigned int MSecond ) { PSDevice pDevice = (PSDevice)hDeviceContext; @@ -329,7 +329,7 @@ vCommandTimerWait( pDevice->sTimerCommand.data = (ULONG)pDevice; pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; // RUN_AT :1 msec ~= (HZ/1024) - pDevice->sTimerCommand.expires = (UINT)RUN_AT((MSecond * HZ) >> 10); + pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); add_timer(&pDevice->sTimerCommand); return; } @@ -347,7 +347,7 @@ vCommandTimer ( PWLAN_IE_SSID pItemSSID; PWLAN_IE_SSID pItemSSIDCurr; CMD_STATUS Status; - UINT ii; + unsigned int ii; BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; struct sk_buff *skb; @@ -1065,8 +1065,8 @@ BOOL bClearBSSID_SCAN ( ) { PSDevice pDevice = (PSDevice)hDeviceContext; - UINT uCmdDequeueIdx = pDevice->uCmdDequeueIdx; - UINT ii; + unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx; + unsigned int ii; if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii ++) { diff --git a/drivers/staging/vt6655/wcmd.h b/drivers/staging/vt6655/wcmd.h index c3c418089513..0063b9945504 100644 --- a/drivers/staging/vt6655/wcmd.h +++ b/drivers/staging/vt6655/wcmd.h @@ -133,7 +133,7 @@ bScheduleCommand( void vCommandTimerWait( void *hDeviceContext, - UINT MSecond + unsigned int MSecond ); #ifdef TxInSleep void diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c index e9c3a6e57a0d..3e0d0eba73f9 100644 --- a/drivers/staging/vt6655/wctl.c +++ b/drivers/staging/vt6655/wctl.c @@ -68,8 +68,8 @@ BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) { - UINT uIndex; - UINT ii; + unsigned int uIndex; + unsigned int ii; PSCacheEntry pCacheEntry; if (IS_FC_RETRY(pMACHeader)) { @@ -108,9 +108,9 @@ BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) * Return Value: index number in Defragment Database * */ -UINT WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader) +unsigned int WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader) { -UINT ii; +unsigned int ii; for(ii=0;iicbDFCB;ii++) { if ((pDevice->sRxDFCB[ii].bInUse == TRUE) && @@ -138,9 +138,9 @@ UINT ii; * Return Value: index number in Defragment Database * */ -UINT WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader) +unsigned int WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader) { -UINT ii; +unsigned int ii; if (pDevice->cbFreeDFCB == 0) return(pDevice->cbDFCB); @@ -175,9 +175,9 @@ UINT ii; * Return Value: TRUE if it is valid fragment packet and we have resource to defragment; otherwise FALSE * */ -BOOL WCTLbHandleFragment (PSDevice pDevice, PS802_11Header pMACHeader, UINT cbFrameLength, BOOL bWEP, BOOL bExtIV) +BOOL WCTLbHandleFragment (PSDevice pDevice, PS802_11Header pMACHeader, unsigned int cbFrameLength, BOOL bWEP, BOOL bExtIV) { -UINT uHeaderSize; +unsigned int uHeaderSize; if (bWEP == TRUE) { diff --git a/drivers/staging/vt6655/wctl.h b/drivers/staging/vt6655/wctl.h index a1ac4791bfd3..f5255b1de338 100644 --- a/drivers/staging/vt6655/wctl.h +++ b/drivers/staging/vt6655/wctl.h @@ -98,9 +98,10 @@ /*--------------------- Export Functions --------------------------*/ BOOL WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader); -BOOL WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, UINT cbFrameLength, BOOL bWEP, BOOL bExtIV); -UINT WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader); -UINT WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader); +BOOL WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, + unsigned int cbFrameLength, BOOL bWEP, BOOL bExtIV); +unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader); +unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader); #endif // __WCTL_H__ diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index d9980f17055b..093ccd3163e3 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -118,7 +118,7 @@ s_vMgrRxAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, PSRxMgmtPacket pRxPacket, - UINT uNodeIndex + unsigned int uNodeIndex ); static @@ -242,7 +242,7 @@ s_MgrMakeBeacon( PSMgmtObject pMgmt, WORD wCurrCapInfo, WORD wCurrBeaconPeriod, - UINT uCurrChannel, + unsigned int uCurrChannel, WORD wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, PBYTE pCurrBSSID, @@ -287,7 +287,7 @@ s_MgrMakeProbeResponse( PSMgmtObject pMgmt, WORD wCurrCapInfo, WORD wCurrBeaconPeriod, - UINT uCurrChannel, + unsigned int uCurrChannel, WORD wCurrATIMWinodw, PBYTE pDstAddr, PWLAN_IE_SSID pCurrSSID, @@ -310,7 +310,7 @@ static void s_vMgrSynchBSS ( PSDevice pDevice, - UINT uBSSMode, + unsigned int uBSSMode, PKnownBSS pCurr, PCMD_STATUS pStatus ); @@ -683,7 +683,7 @@ s_vMgrRxAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, PSRxMgmtPacket pRxPacket, - UINT uNodeIndex + unsigned int uNodeIndex ) { WLAN_FR_ASSOCREQ sFrame; @@ -691,7 +691,7 @@ s_vMgrRxAssocRequest( PSTxMgmtPacket pTxPacket; WORD wAssocStatus = 0; WORD wAssocAID = 0; - UINT uRateLen = WLAN_RATES_MAXLEN; + unsigned int uRateLen = WLAN_RATES_MAXLEN; BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; @@ -845,7 +845,7 @@ s_vMgrRxReAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, PSRxMgmtPacket pRxPacket, - UINT uNodeIndex + unsigned int uNodeIndex ) { WLAN_FR_REASSOCREQ sFrame; @@ -853,7 +853,7 @@ s_vMgrRxReAssocRequest( PSTxMgmtPacket pTxPacket; WORD wAssocStatus = 0; WORD wAssocAID = 0; - UINT uRateLen = WLAN_RATES_MAXLEN; + unsigned int uRateLen = WLAN_RATES_MAXLEN; BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; @@ -1331,7 +1331,7 @@ s_vMgrRxAuthenSequence_1( ) { PSTxMgmtPacket pTxPacket = NULL; - UINT uNodeIndex; + unsigned int uNodeIndex; WLAN_FR_AUTHEN sFrame; PSKeyItem pTransmitKey; @@ -1539,8 +1539,8 @@ s_vMgrRxAuthenSequence_3( ) { PSTxMgmtPacket pTxPacket = NULL; - UINT uStatusCode = 0 ; - UINT uNodeIndex = 0; + unsigned int uStatusCode = 0 ; + unsigned int uNodeIndex = 0; WLAN_FR_AUTHEN sFrame; if (!WLAN_GET_FC_ISWEP(pFrame->pHdr->sA3.wFrameCtl)) { @@ -1666,7 +1666,7 @@ s_vMgrRxDisassociation( ) { WLAN_FR_DISASSOC sFrame; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; // CMD_STATUS CmdStatus; viawget_wpa_header *wpahdr; @@ -1745,7 +1745,7 @@ s_vMgrRxDeauthentication( ) { WLAN_FR_DEAUTHEN sFrame; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; viawget_wpa_header *wpahdr; @@ -1882,17 +1882,17 @@ s_vMgrRxBeacon( BOOL bUpdateTSF = FALSE; BOOL bIsAPBeacon = FALSE; BOOL bIsChannelEqual = FALSE; - UINT uLocateByteIndex; + unsigned int uLocateByteIndex; BYTE byTIMBitOn = 0; WORD wAIDNumber = 0; - UINT uNodeIndex; + unsigned int uNodeIndex; QWORD qwTimestamp, qwLocalTSF; QWORD qwCurrTSF; WORD wStartIndex = 0; WORD wAIDIndex = 0; BYTE byCurrChannel = pRxPacket->byRxChannel; ERPObject sERP; - UINT uRateLen = WLAN_RATES_MAXLEN; + unsigned int uRateLen = WLAN_RATES_MAXLEN; BOOL bChannelHit = FALSE; BOOL bUpdatePhyParameter = FALSE; BYTE byIEChannel = 0; @@ -2397,7 +2397,7 @@ vMgrCreateOwnIBSS( BYTE byTopCCKBasicRate; BYTE byTopOFDMBasicRate; QWORD qwCurrTSF; - UINT ii; + unsigned int ii; BYTE abyRATE[] = {0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, 0x0C, 0x12, 0x18, 0x60}; BYTE abyCCK_RATE[] = {0x82, 0x84, 0x8B, 0x96}; BYTE abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; @@ -2661,11 +2661,11 @@ vMgrJoinBSSBegin( PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; PKnownBSS pCurr = NULL; - UINT ii, uu; + unsigned int ii, uu; PWLAN_IE_SUPP_RATES pItemRates = NULL; PWLAN_IE_SUPP_RATES pItemExtRates = NULL; PWLAN_IE_SSID pItemSSID; - UINT uRateLen = WLAN_RATES_MAXLEN; + unsigned int uRateLen = WLAN_RATES_MAXLEN; WORD wMaxBasicRate = RATE_1M; WORD wMaxSuppRate = RATE_1M; WORD wSuppRate; @@ -2764,7 +2764,7 @@ vMgrJoinBSSBegin( uRateLen); // Stuffing Rate IE if ((pItemExtRates->len > 0) && (pItemRates->len < 8)) { - for (ii = 0; ii < (UINT)(8 - pItemRates->len); ) { + for (ii = 0; ii < (unsigned int)(8 - pItemRates->len); ) { pItemRates->abyRates[pItemRates->len + ii] = pItemExtRates->abyRates[ii]; ii ++; if (pItemExtRates->len <= ii) @@ -2923,7 +2923,7 @@ static void s_vMgrSynchBSS ( PSDevice pDevice, - UINT uBSSMode, + unsigned int uBSSMode, PKnownBSS pCurr, PCMD_STATUS pStatus ) @@ -3094,7 +3094,7 @@ s_vMgrSynchBSS ( ) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - // UINT ii , uSameBssidNum=0; + // unsigned int ii , uSameBssidNum=0; // for (ii = 0; ii < MAX_BSS_NUM; ii++) { // if (pMgmt->sBSSList[ii].bActive && @@ -3153,7 +3153,7 @@ s_vMgrFormatTIM( { BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; BYTE byMap; - UINT ii, jj; + unsigned int ii, jj; BOOL bStartFound = FALSE; BOOL bMulticast = FALSE; WORD wStartIndex = 0; @@ -3226,7 +3226,7 @@ s_MgrMakeBeacon( PSMgmtObject pMgmt, WORD wCurrCapInfo, WORD wCurrBeaconPeriod, - UINT uCurrChannel, + unsigned int uCurrChannel, WORD wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, PBYTE pCurrBSSID, @@ -3238,9 +3238,9 @@ s_MgrMakeBeacon( WLAN_FR_BEACON sFrame; BYTE abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; PBYTE pbyBuffer; - UINT uLength = 0; + unsigned int uLength = 0; PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; - UINT ii; + unsigned int ii; // prepare beacon frame pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; @@ -3455,7 +3455,7 @@ s_MgrMakeProbeResponse( PSMgmtObject pMgmt, WORD wCurrCapInfo, WORD wCurrBeaconPeriod, - UINT uCurrChannel, + unsigned int uCurrChannel, WORD wCurrATIMWinodw, PBYTE pDstAddr, PWLAN_IE_SSID pCurrSSID, @@ -3468,9 +3468,9 @@ s_MgrMakeProbeResponse( PSTxMgmtPacket pTxPacket = NULL; WLAN_FR_PROBERESP sFrame; PBYTE pbyBuffer; - UINT uLength = 0; + unsigned int uLength = 0; PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; - UINT ii; + unsigned int ii; pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; @@ -3799,7 +3799,7 @@ s_MgrMakeAssocRequest( } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && (pMgmt->pCurrBSS != NULL)) { - UINT ii; + unsigned int ii; PWORD pwPMKID; // WPA IE @@ -4055,7 +4055,7 @@ s_MgrMakeReAssocRequest( } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && (pMgmt->pCurrBSS != NULL)) { - UINT ii; + unsigned int ii; PWORD pwPMKID; /* WPA IE */ @@ -4543,7 +4543,7 @@ vMgrRxManagePacket( { PSDevice pDevice = (PSDevice)hDeviceContext; BOOL bInScan = FALSE; - UINT uNodeIndex = 0; + unsigned int uNodeIndex = 0; NODE_STATE eNodeState = 0; CMD_STATUS Status; @@ -4816,7 +4816,7 @@ bAdd_PMKID_Candidate ( { PSDevice pDevice = (PSDevice)hDeviceContext; PPMKID_CANDIDATE pCandidateList; - UINT ii = 0; + unsigned int ii = 0; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index 9367f478dbf6..6b807d0834f0 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -224,8 +224,8 @@ typedef enum tagWMAC_POWER_MODE { typedef struct tagSTxMgmtPacket { PUWLAN_80211HDR p80211Header; - UINT cbMPDULen; - UINT cbPayloadLen; + unsigned int cbMPDULen; + unsigned int cbPayloadLen; } STxMgmtPacket, *PSTxMgmtPacket; @@ -235,9 +235,9 @@ typedef struct tagSRxMgmtPacket { PUWLAN_80211HDR p80211Header; QWORD qwLocalTSF; - UINT cbMPDULen; - UINT cbPayloadLen; - UINT uRSSI; + unsigned int cbMPDULen; + unsigned int cbPayloadLen; + unsigned int uRSSI; BYTE bySQ; BYTE byRxRate; BYTE byRxChannel; @@ -271,7 +271,7 @@ typedef struct tagSMgmtObject // BYTE abyNewExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; // Current state vars - UINT uCurrChannel; + unsigned int uCurrChannel; BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE abyCurrSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; @@ -284,7 +284,7 @@ typedef struct tagSMgmtObject BYTE byERPContext; CMD_STATE eCommandState; - UINT uScanChannel; + unsigned int uScanChannel; // Desire joinning BSS vars BYTE abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; @@ -294,22 +294,22 @@ typedef struct tagSMgmtObject //BYTE abyAdHocSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; WORD wIBSSBeaconPeriod; WORD wIBSSATIMWindow; - UINT uIBSSChannel; + unsigned int uIBSSChannel; BYTE abyIBSSSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; BYTE byAPBBType; BYTE abyWPAIE[MAX_WPA_IE_LEN]; WORD wWPAIELen; - UINT uAssocCount; + unsigned int uAssocCount; BOOL bMoreData; // Scan state vars WMAC_SCAN_STATE eScanState; WMAC_SCAN_TYPE eScanType; - UINT uScanStartCh; - UINT uScanEndCh; + unsigned int uScanStartCh; + unsigned int uScanEndCh; WORD wScanSteps; - UINT uScanBSSType; + unsigned int uScanBSSType; // Desire scannig vars BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; BYTE abyScanBSSID[WLAN_BSSID_LEN]; @@ -338,8 +338,8 @@ typedef struct tagSMgmtObject BYTE abyPSTxMap[MAX_NODE_NUM + 1]; // management command related - UINT uCmdBusy; - UINT uCmdHostAPBusy; + unsigned int uCmdBusy; + unsigned int uCmdHostAPBusy; // management packet pool PBYTE pbyMgmtPacketPool; @@ -381,7 +381,7 @@ typedef struct tagSMgmtObject BOOL bSwitchChannel; BYTE byNewChannel; PWLAN_IE_MEASURE_REP pCurrMeasureEIDRep; - UINT uLengthOfRepEIDs; + unsigned int uLengthOfRepEIDs; BYTE abyCurrentMSRReq[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; BYTE abyCurrentMSRRep[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; BYTE abyIECountry[WLAN_A3FR_MAXLEN]; diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c index 7a42a0aad7d2..caa32b752c9f 100644 --- a/drivers/staging/vt6655/wpa2.c +++ b/drivers/staging/vt6655/wpa2.c @@ -261,7 +261,7 @@ WPA2vParseRSN ( * Return Value: length of IEs. * -*/ -UINT +unsigned int WPA2uSetIEs( void *pMgmtHandle, PWLAN_IE_RSN pRSNIEs @@ -269,7 +269,7 @@ WPA2uSetIEs( { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; PBYTE pbyBuffer = NULL; - UINT ii = 0; + unsigned int ii = 0; PWORD pwPMKID = NULL; if (pRSNIEs == NULL) { diff --git a/drivers/staging/vt6655/wpa2.h b/drivers/staging/vt6655/wpa2.h index 7200db37f430..8ad1eeaec70f 100644 --- a/drivers/staging/vt6655/wpa2.h +++ b/drivers/staging/vt6655/wpa2.h @@ -69,7 +69,7 @@ WPA2vParseRSN ( PWLAN_IE_RSN pRSN ); -UINT +unsigned int WPA2uSetIEs( void *pMgmtHandle, PWLAN_IE_RSN pRSNIEs diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c index bf92fb9908fe..648ae1aa2b18 100644 --- a/drivers/staging/vt6655/wroute.c +++ b/drivers/staging/vt6655/wroute.c @@ -65,18 +65,18 @@ static int msglevel =MSG_LEVEL_INFO; * Return Value: TRUE if packet duplicate; otherwise FALSE * */ -BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, UINT uDataLen, UINT uNodeIndex) +BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex) { PSMgmtObject pMgmt = pDevice->pMgmt; PSTxDesc pHeadTD, pLastTD; - UINT cbFrameBodySize; - UINT uMACfragNum; + unsigned int cbFrameBodySize; + unsigned int uMACfragNum; BYTE byPktType; BOOL bNeedEncryption = FALSE; SKeyItem STempKey; PSKeyItem pTransmitKey = NULL; - UINT cbHeaderSize; - UINT ii; + unsigned int cbHeaderSize; + unsigned int ii; PBYTE pbyBSSID; diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h index 295cdc5b8e9d..199d31153d8e 100644 --- a/drivers/staging/vt6655/wroute.h +++ b/drivers/staging/vt6655/wroute.h @@ -39,7 +39,7 @@ /*--------------------- Export Functions --------------------------*/ -BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, UINT uDataLen, UINT uNodeIndex); +BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex); #endif // __WROUTE_H__ -- cgit v1.2.3 From e3fd16d0819e3b316a4fe316e5f32032df61e9db Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 2 Jun 2010 09:52:02 -0700 Subject: Staging: vt6655: remove custom ULONG typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 10 +++++----- drivers/staging/vt6655/bssdb.c | 6 +++--- drivers/staging/vt6655/bssdb.h | 2 +- drivers/staging/vt6655/card.h | 2 +- drivers/staging/vt6655/device.h | 28 ++++++++++++++-------------- drivers/staging/vt6655/device_main.c | 13 +++++++------ drivers/staging/vt6655/ioctl.c | 2 +- drivers/staging/vt6655/ioctl.h | 2 +- drivers/staging/vt6655/key.c | 6 +++--- drivers/staging/vt6655/key.h | 8 ++++---- drivers/staging/vt6655/mib.h | 20 ++++++++++---------- drivers/staging/vt6655/ttype.h | 1 - drivers/staging/vt6655/upc.h | 2 +- drivers/staging/vt6655/vntwifi.c | 2 +- drivers/staging/vt6655/vntwifi.h | 2 +- drivers/staging/vt6655/wcmd.c | 6 +++--- drivers/staging/vt6655/wmgr.c | 6 +++--- drivers/staging/vt6655/wmgr.h | 14 +++++++------- drivers/staging/vt6655/wpa2.h | 2 +- 19 files changed, 67 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 2fe91b87666a..c772c2901641 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1719,7 +1719,7 @@ const WORD awcFrameTime[MAX_RATE] = /*--------------------- Static Functions --------------------------*/ static -ULONG +unsigned long s_ulGetRatio(PSDevice pDevice); static @@ -2651,12 +2651,12 @@ BBvExitDeepSleep (DWORD_PTR dwIoBase, BYTE byLocalID) static -ULONG +unsigned long s_ulGetRatio (PSDevice pDevice) { -ULONG ulRatio = 0; -ULONG ulMaxPacket; -ULONG ulPacketNum; +unsigned long ulRatio = 0; +unsigned long ulMaxPacket; +unsigned long ulPacketNum; //This is a thousand-ratio ulMaxPacket = pDevice->uNumSQ3[RATE_54M]; diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index e919b2954a52..d16d799636a3 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -1680,9 +1680,9 @@ void s_uCalculateLinkQual( ) { PSDevice pDevice = (PSDevice)hDeviceContext; - ULONG TxOkRatio, TxCnt; - ULONG RxOkRatio,RxCnt; - ULONG RssiRatio; + unsigned long TxOkRatio, TxCnt; + unsigned long RxOkRatio,RxCnt; + unsigned long RssiRatio; long ldBm; TxCnt = pDevice->scStatistic.TxNoRetryOkCount + diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index c7283d208dfb..6da5685440f8 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -205,7 +205,7 @@ typedef struct tagKnownNodeDB { BOOL bPSEnable; BOOL bRxPSPoll; BYTE byAuthSequence; - ULONG ulLastRxJiffer; + unsigned long ulLastRxJiffer; BYTE bySuppRate; DWORD dwFlags; WORD wEnQueueCnt; diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index f2f79407f4ab..40271a1f1873 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -99,7 +99,7 @@ void CARDvUpdateNextTBTT(DWORD_PTR dwIoBase, QWORD qwTSF, WORD wBeaconInterval); BOOL CARDbGetCurrentTSF(DWORD_PTR dwIoBase, PQWORD pqwCurrTSF); QWORD CARDqGetNextTBTT(QWORD qwTSF, WORD wBeaconInterval); QWORD CARDqGetTSFOffset(BYTE byRxRate, QWORD qwTSF1, QWORD qwTSF2); -BOOL CARDbSetTxPower(void *pDeviceHandler, ULONG ulTxPower); +BOOL CARDbSetTxPower(void *pDeviceHandler, unsigned long ulTxPower); BYTE CARDbyGetPktType(void *pDeviceHandler); void CARDvSafeResetTx(void *pDeviceHandler); void CARDvSafeResetRx(void *pDeviceHandler); diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 1685fb98d2fd..736af6e49a8e 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -250,7 +250,7 @@ typedef enum _NDIS_802_11_STATUS_TYPE //Added new types for PMKID Candidate lists. typedef struct _PMKID_CANDIDATE { NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; + unsigned long Flags; } PMKID_CANDIDATE, *PPMKID_CANDIDATE; @@ -261,15 +261,15 @@ typedef struct _BSSID_INFO } BSSID_INFO, *PBSSID_INFO; typedef struct tagSPMKID { - ULONG Length; - ULONG BSSIDInfoCount; + unsigned long Length; + unsigned long BSSIDInfoCount; BSSID_INFO BSSIDInfo[MAX_BSSIDINFO_4_PMKID]; } SPMKID, *PSPMKID; typedef struct tagSPMKIDCandidateEvent { NDIS_802_11_STATUS_TYPE StatusType; - ULONG Version; // Version of the structure - ULONG NumCandidates; // No. of pmkid candidates + unsigned long Version; // Version of the structure + unsigned long NumCandidates; // No. of pmkid candidates PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST]; } SPMKIDCandidateEvent, *PSPMKIDCandidateEvent; @@ -618,7 +618,7 @@ typedef struct __device_info { //WOW BYTE abyIPAddr[4]; - ULONG ulTxPower; + unsigned long ulTxPower; NDIS_802_11_WEP_STATUS eEncryptionStatus; BOOL bTransmitKey; //2007-0925-01by MikeLiu @@ -712,7 +712,7 @@ typedef struct __device_info { struct timer_list sTimerCommand; #ifdef TxInSleep struct timer_list sTimerTxData; - ULONG nTxDataTimeCout; + unsigned long nTxDataTimeCout; BOOL fTxDataInSleep; BOOL IsTxDataTrigger; #endif @@ -728,18 +728,18 @@ typedef struct __device_info { BOOL bDiversityRegCtlON; BOOL bDiversityEnable; - ULONG ulDiversityNValue; - ULONG ulDiversityMValue; + unsigned long ulDiversityNValue; + unsigned long ulDiversityMValue; BYTE byTMax; BYTE byTMax2; BYTE byTMax3; - ULONG ulSQ3TH; + unsigned long ulSQ3TH; // ANT diversity - ULONG uDiversityCnt; + unsigned long uDiversityCnt; BYTE byAntennaState; - ULONG ulRatio_State0; - ULONG ulRatio_State1; + unsigned long ulRatio_State0; + unsigned long ulRatio_State1; //SQ3 functions for antenna diversity struct timer_list TimerSQ3Tmax1; @@ -747,7 +747,7 @@ typedef struct __device_info { struct timer_list TimerSQ3Tmax3; - ULONG uNumSQ3[MAX_RATE]; + unsigned long uNumSQ3[MAX_RATE]; WORD wAntDiversityMaxRate; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index c8ae43aba80e..e3c2ba758b2e 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -588,7 +588,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52); pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53); pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54); - pDevice->ulSQ3TH = 0;//(ULONG) SROMbyReadEmbedded(pDevice->PortOffset, 0x55); + pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55); pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56); if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { @@ -851,17 +851,17 @@ else CARDbRadioPowerOn(pDevice); static void device_init_diversity_timer(PSDevice pDevice) { init_timer(&pDevice->TimerSQ3Tmax1); - pDevice->TimerSQ3Tmax1.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice; pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack; pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); init_timer(&pDevice->TimerSQ3Tmax2); - pDevice->TimerSQ3Tmax2.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice; pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack; pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); init_timer(&pDevice->TimerSQ3Tmax3); - pDevice->TimerSQ3Tmax3.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice; pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack; pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); @@ -1112,10 +1112,11 @@ static void device_print_info(PSDevice pDevice) DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id)); DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr); #ifdef IO_MAP - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx ",(ULONG) pDevice->ioaddr); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx ",(unsigned long) pDevice->ioaddr); DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq); #else - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx Mem=0x%lx ",(ULONG) pDevice->ioaddr,(ULONG) pDevice->PortOffset); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx Mem=0x%lx ", + (unsigned long) pDevice->ioaddr,(unsigned long) pDevice->PortOffset); DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq); #endif diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index b7049938c30a..6118a3cb02e4 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -719,7 +719,7 @@ vConfigWEPKey ( PSDevice pDevice, DWORD dwKeyIndex, PBYTE pbyKey, - ULONG uKeyLength + unsigned long uKeyLength ) { int ii; diff --git a/drivers/staging/vt6655/ioctl.h b/drivers/staging/vt6655/ioctl.h index 0d10c2a923c6..4a30e271294f 100644 --- a/drivers/staging/vt6655/ioctl.h +++ b/drivers/staging/vt6655/ioctl.h @@ -47,7 +47,7 @@ void vConfigWEPKey ( PSDevice pDevice, DWORD dwKeyIndex, PBYTE pbyKey, - ULONG uKeyLength + unsigned long uKeyLength ); */ diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index da5def3214b3..141d249541c2 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -193,7 +193,7 @@ BOOL KeybSetKey ( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, @@ -634,7 +634,7 @@ BOOL KeybCheckPairewiseKey ( BOOL KeybSetDefaultKey ( PSKeyManagement pTable, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, @@ -741,7 +741,7 @@ BOOL KeybSetDefaultKey ( BOOL KeybSetAllGroupKey ( PSKeyManagement pTable, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index 39403d93aeb1..8ba8b2752ce6 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -58,7 +58,7 @@ typedef struct tagSKeyItem { BOOL bKeyValid; - ULONG uKeyLength; + unsigned long uKeyLength; BYTE abyKey[MAX_KEY_LEN]; QWORD KeyRSC; DWORD dwTSC47_16; @@ -114,7 +114,7 @@ BOOL KeybSetKey( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, @@ -125,7 +125,7 @@ BOOL KeybSetKey( BOOL KeybSetDefaultKey( PSKeyManagement pTable, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, @@ -172,7 +172,7 @@ void KeyvRemoveAllWEPKey( BOOL KeybSetAllGroupKey ( PSKeyManagement pTable, DWORD dwKeyIndex, - ULONG uKeyLength, + unsigned long uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode, diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index ffd5fb1d39d5..9f3f52114b56 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -39,7 +39,7 @@ // typedef struct tagSDot11Counters { - ULONG Length; // Length of structure + unsigned long Length; // Length of structure ULONGLONG TransmittedFragmentCount; ULONGLONG MulticastTransmittedFrameCount; ULONGLONG FailedCount; @@ -138,7 +138,7 @@ typedef struct tagSRmonCounter { // Custom counter // typedef struct tagSCustomCounters { - ULONG Length; + unsigned long Length; ULONGLONG ullTsrAllOK; @@ -177,7 +177,7 @@ typedef struct tagSCustomCounters { // Custom counter // typedef struct tagSISRCounters { - ULONG Length; + unsigned long Length; DWORD dwIsrTx0OK; DWORD dwIsrAC0TxOK; @@ -324,15 +324,15 @@ typedef struct tagSStatCounter { #ifdef Calcu_LinkQual //Tx count: - ULONG TxNoRetryOkCount; //success tx no retry ! - ULONG TxRetryOkCount; //success tx but retry ! - ULONG TxFailCount; //fail tx ? + unsigned long TxNoRetryOkCount; //success tx no retry ! + unsigned long TxRetryOkCount; //success tx but retry ! + unsigned long TxFailCount; //fail tx ? //Rx count: - ULONG RxOkCnt; //success rx ! - ULONG RxFcsErrCnt; //fail rx ? + unsigned long RxOkCnt; //success rx ! + unsigned long RxFcsErrCnt; //fail rx ? //statistic - ULONG SignalStren; - ULONG LinkQuality; + unsigned long SignalStren; + unsigned long LinkQuality; #endif } SStatCounter, *PSStatCounter; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 23533a7d2990..950fb097e460 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,7 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned long ULONG; typedef unsigned long long ULONGLONG; //64 bit diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index acd1b661490d..78a950cbf00d 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -141,7 +141,7 @@ #define PCAvDelayByIO(uDelayUnit) { \ BYTE byData; \ - ULONG ii; \ + unsigned long ii; \ \ if (uDelayUnit <= 50) { \ udelay(uDelayUnit); \ diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index 21a9111e91ed..22069057ac0a 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -665,7 +665,7 @@ VNTWIFIbInit( BOOL VNTWIFIbSetPMKIDCache ( void *pMgmtObject, - ULONG ulCount, + unsigned long ulCount, void *pPMKIDInfo ) { diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h index 683a6acef94c..fc1a4f152491 100644 --- a/drivers/staging/vt6655/vntwifi.h +++ b/drivers/staging/vt6655/vntwifi.h @@ -265,7 +265,7 @@ VNTWIFIbyGetKeyCypher( BOOL VNTWIFIbSetPMKIDCache ( void *pMgmtObject, - ULONG ulCount, + unsigned long ulCount, void *pPMKIDInfo ); diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index 517cad9fbed2..9aae07709e34 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -326,7 +326,7 @@ vCommandTimerWait( PSDevice pDevice = (PSDevice)hDeviceContext; init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.data = (unsigned long) pDevice; pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; // RUN_AT :1 msec ~= (HZ/1024) pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); @@ -723,7 +723,7 @@ printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySS // printk("Re-initial TxDataTimer****\n"); del_timer(&pDevice->sTimerTxData); init_timer(&pDevice->sTimerTxData); - pDevice->sTimerTxData.data = (ULONG)pDevice; + pDevice->sTimerTxData.data = (unsigned long) pDevice; pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback pDevice->fTxDataInSleep = FALSE; @@ -1092,7 +1092,7 @@ vResetCommandTimer( del_timer(&pDevice->sTimerCommand); //init timer init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.data = (unsigned long) pDevice; pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; pDevice->sTimerCommand.expires = RUN_AT(HZ); pDevice->cbFreeCmdQueue = CMD_Q_SIZE; diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 093ccd3163e3..41f520afea11 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -393,18 +393,18 @@ vMgrTimerInit( init_timer(&pMgmt->sTimerSecondCallback); - pMgmt->sTimerSecondCallback.data = (ULONG)pDevice; + pMgmt->sTimerSecondCallback.data = (unsigned long) pDevice; pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack; pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ); init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.data = (unsigned long) pDevice; pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; pDevice->sTimerCommand.expires = RUN_AT(HZ); #ifdef TxInSleep init_timer(&pDevice->sTimerTxData); - pDevice->sTimerTxData.data = (ULONG)pDevice; + pDevice->sTimerTxData.data = (unsigned long) pDevice; pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback pDevice->fTxDataInSleep = FALSE; diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index 6b807d0834f0..a08403e3c610 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -83,7 +83,7 @@ /*--------------------- Export Types ------------------------------*/ #define timer_expire(timer,next_tick) mod_timer(&timer, RUN_AT(next_tick)) -typedef void (*TimerFunction)(ULONG); +typedef void (*TimerFunction)(unsigned long); //+++ NDIS related @@ -105,15 +105,15 @@ typedef struct _NDIS_802_11_AI_RESFI typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION { - ULONG Length; + unsigned long Length; unsigned short AvailableRequestFixedIEs; NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; + unsigned long RequestIELength; + unsigned long OffsetRequestIEs; unsigned short AvailableResponseFixedIEs; NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; + unsigned long ResponseIELength; + unsigned long OffsetResponseIEs; } NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; @@ -122,7 +122,7 @@ typedef struct tagSAssocInfo { NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; BYTE abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN]; // store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION - ULONG RequestIELength; + unsigned long RequestIELength; BYTE abyReqIEs[WLAN_BEACON_FR_MAXLEN]; } SAssocInfo, *PSAssocInfo; //--- diff --git a/drivers/staging/vt6655/wpa2.h b/drivers/staging/vt6655/wpa2.h index 8ad1eeaec70f..b6b3768350a2 100644 --- a/drivers/staging/vt6655/wpa2.h +++ b/drivers/staging/vt6655/wpa2.h @@ -45,7 +45,7 @@ typedef struct tagsPMKIDInfo { } PMKIDInfo, *PPMKIDInfo; typedef struct tagSPMKIDCache { - ULONG BSSIDInfoCount; + unsigned long BSSIDInfoCount; PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; } SPMKIDCache, *PSPMKIDCache; -- cgit v1.2.3 From b2e876b6089160e5ecaed859eb1b87cd4913793e Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Wed, 2 Jun 2010 09:52:03 -0700 Subject: Staging: vt6655: remove custom ULONGLONG typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.h | 2 +- drivers/staging/vt6655/dpc.c | 4 +- drivers/staging/vt6655/mib.c | 30 ++++----- drivers/staging/vt6655/mib.h | 136 ++++++++++++++++++++-------------------- drivers/staging/vt6655/ttype.h | 4 -- drivers/staging/vt6655/wpactl.h | 2 +- 6 files changed, 87 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index 6da5685440f8..d1d947879197 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -211,7 +211,7 @@ typedef struct tagKnownNodeDB { WORD wEnQueueCnt; BOOL bOnFly; - ULONGLONG KeyRSC; + unsigned long long KeyRSC; BYTE byKeyIndex; DWORD dwKeyIndex; BYTE byCipherSuite; diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 8fa87dd5c43b..286461ca4e56 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -919,9 +919,9 @@ device_receive_frame ( if (bIsWEP) { WORD wLocalTSC15_0 = 0; DWORD dwLocalTSC47_16 = 0; - ULONGLONG RSC = 0; + unsigned long long RSC = 0; // endian issues - RSC = *((ULONGLONG *) &(pKey->KeyRSC)); + RSC = *((unsigned long long *) &(pKey->KeyRSC)); wLocalTSC15_0 = (WORD) RSC; dwLocalTSC47_16 = (DWORD) (RSC>>16); diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index e6cab78de0f4..d34ebd31efcb 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -194,15 +194,15 @@ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, // update counters in case that successful transmit if (byRSR & RSR_ADDRBROAD) { pStatistic->ullRxBroadcastFrames++; - pStatistic->ullRxBroadcastBytes += (ULONGLONG)cbFrameLength; + pStatistic->ullRxBroadcastBytes += (unsigned long long) cbFrameLength; } else if (byRSR & RSR_ADDRMULTI) { pStatistic->ullRxMulticastFrames++; - pStatistic->ullRxMulticastBytes += (ULONGLONG)cbFrameLength; + pStatistic->ullRxMulticastBytes += (unsigned long long) cbFrameLength; } else { pStatistic->ullRxDirectedFrames++; - pStatistic->ullRxDirectedBytes += (ULONGLONG)cbFrameLength; + pStatistic->ullRxDirectedBytes += (unsigned long long) cbFrameLength; } } } @@ -473,15 +473,15 @@ STAvUpdateTDStatCounter ( // update counters in case that successful transmit if (is_broadcast_ether_addr(pbyDestAddr)) { pStatistic->ullTxBroadcastFrames[uIdx]++; - pStatistic->ullTxBroadcastBytes[uIdx] += (ULONGLONG)cbFrameLength; + pStatistic->ullTxBroadcastBytes[uIdx] += (unsigned long long) cbFrameLength; } else if (is_multicast_ether_addr(pbyDestAddr)) { pStatistic->ullTxMulticastFrames[uIdx]++; - pStatistic->ullTxMulticastBytes[uIdx] += (ULONGLONG)cbFrameLength; + pStatistic->ullTxMulticastBytes[uIdx] += (unsigned long long) cbFrameLength; } else { pStatistic->ullTxDirectedFrames[uIdx]++; - pStatistic->ullTxDirectedBytes[uIdx] += (ULONGLONG)cbFrameLength; + pStatistic->ullTxDirectedBytes[uIdx] += (unsigned long long) cbFrameLength; } } else { @@ -559,21 +559,21 @@ STAvUpdate802_11Counter( ) { //p802_11Counter->TransmittedFragmentCount - p802_11Counter->MulticastTransmittedFrameCount = (ULONGLONG) (pStatistic->dwTsrBroadcast[TYPE_AC0DMA] + + p802_11Counter->MulticastTransmittedFrameCount = (unsigned long long) (pStatistic->dwTsrBroadcast[TYPE_AC0DMA] + pStatistic->dwTsrBroadcast[TYPE_TXDMA0] + pStatistic->dwTsrMulticast[TYPE_AC0DMA] + pStatistic->dwTsrMulticast[TYPE_TXDMA0]); - p802_11Counter->FailedCount = (ULONGLONG) (pStatistic->dwTsrErr[TYPE_AC0DMA] + pStatistic->dwTsrErr[TYPE_TXDMA0]); - p802_11Counter->RetryCount = (ULONGLONG) (pStatistic->dwTsrRetry[TYPE_AC0DMA] + pStatistic->dwTsrRetry[TYPE_TXDMA0]); - p802_11Counter->MultipleRetryCount = (ULONGLONG) (pStatistic->dwTsrMoreThanOnceRetry[TYPE_AC0DMA] + + p802_11Counter->FailedCount = (unsigned long long) (pStatistic->dwTsrErr[TYPE_AC0DMA] + pStatistic->dwTsrErr[TYPE_TXDMA0]); + p802_11Counter->RetryCount = (unsigned long long) (pStatistic->dwTsrRetry[TYPE_AC0DMA] + pStatistic->dwTsrRetry[TYPE_TXDMA0]); + p802_11Counter->MultipleRetryCount = (unsigned long long) (pStatistic->dwTsrMoreThanOnceRetry[TYPE_AC0DMA] + pStatistic->dwTsrMoreThanOnceRetry[TYPE_TXDMA0]); //p802_11Counter->FrameDuplicateCount - p802_11Counter->RTSSuccessCount += (ULONGLONG) (dwCounter & 0x000000ff); - p802_11Counter->RTSFailureCount += (ULONGLONG) ((dwCounter & 0x0000ff00) >> 8); - p802_11Counter->ACKFailureCount += (ULONGLONG) ((dwCounter & 0x00ff0000) >> 16); - p802_11Counter->FCSErrorCount += (ULONGLONG) ((dwCounter & 0xff000000) >> 24); + p802_11Counter->RTSSuccessCount += (unsigned long long) (dwCounter & 0x000000ff); + p802_11Counter->RTSFailureCount += (unsigned long long) ((dwCounter & 0x0000ff00) >> 8); + p802_11Counter->ACKFailureCount += (unsigned long long) ((dwCounter & 0x00ff0000) >> 16); + p802_11Counter->FCSErrorCount += (unsigned long long) ((dwCounter & 0xff000000) >> 24); //p802_11Counter->ReceivedFragmentCount - p802_11Counter->MulticastReceivedFrameCount = (ULONGLONG) (pStatistic->dwRsrBroadcast + + p802_11Counter->MulticastReceivedFrameCount = (unsigned long long) (pStatistic->dwRsrBroadcast + pStatistic->dwRsrMulticast); } diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 9f3f52114b56..1540b27faf70 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -40,31 +40,31 @@ typedef struct tagSDot11Counters { unsigned long Length; // Length of structure - ULONGLONG TransmittedFragmentCount; - ULONGLONG MulticastTransmittedFrameCount; - ULONGLONG FailedCount; - ULONGLONG RetryCount; - ULONGLONG MultipleRetryCount; - ULONGLONG RTSSuccessCount; - ULONGLONG RTSFailureCount; - ULONGLONG ACKFailureCount; - ULONGLONG FrameDuplicateCount; - ULONGLONG ReceivedFragmentCount; - ULONGLONG MulticastReceivedFrameCount; - ULONGLONG FCSErrorCount; - ULONGLONG TKIPLocalMICFailures; - ULONGLONG TKIPRemoteMICFailures; - ULONGLONG TKIPICVErrors; - ULONGLONG TKIPCounterMeasuresInvoked; - ULONGLONG TKIPReplays; - ULONGLONG CCMPFormatErrors; - ULONGLONG CCMPReplays; - ULONGLONG CCMPDecryptErrors; - ULONGLONG FourWayHandshakeFailures; -// ULONGLONG WEPUndecryptableCount; -// ULONGLONG WEPICVErrorCount; -// ULONGLONG DecryptSuccessCount; -// ULONGLONG DecryptFailureCount; + unsigned long long TransmittedFragmentCount; + unsigned long long MulticastTransmittedFrameCount; + unsigned long long FailedCount; + unsigned long long RetryCount; + unsigned long long MultipleRetryCount; + unsigned long long RTSSuccessCount; + unsigned long long RTSFailureCount; + unsigned long long ACKFailureCount; + unsigned long long FrameDuplicateCount; + unsigned long long ReceivedFragmentCount; + unsigned long long MulticastReceivedFrameCount; + unsigned long long FCSErrorCount; + unsigned long long TKIPLocalMICFailures; + unsigned long long TKIPRemoteMICFailures; + unsigned long long TKIPICVErrors; + unsigned long long TKIPCounterMeasuresInvoked; + unsigned long long TKIPReplays; + unsigned long long CCMPFormatErrors; + unsigned long long CCMPReplays; + unsigned long long CCMPDecryptErrors; + unsigned long long FourWayHandshakeFailures; +// unsigned long long WEPUndecryptableCount; +// unsigned long long WEPICVErrorCount; +// unsigned long long DecryptSuccessCount; +// unsigned long long DecryptFailureCount; } SDot11Counters, *PSDot11Counters; @@ -140,35 +140,35 @@ typedef struct tagSRmonCounter { typedef struct tagSCustomCounters { unsigned long Length; - ULONGLONG ullTsrAllOK; - - ULONGLONG ullRsr11M; - ULONGLONG ullRsr5M; - ULONGLONG ullRsr2M; - ULONGLONG ullRsr1M; - - ULONGLONG ullRsr11MCRCOk; - ULONGLONG ullRsr5MCRCOk; - ULONGLONG ullRsr2MCRCOk; - ULONGLONG ullRsr1MCRCOk; - - ULONGLONG ullRsr54M; - ULONGLONG ullRsr48M; - ULONGLONG ullRsr36M; - ULONGLONG ullRsr24M; - ULONGLONG ullRsr18M; - ULONGLONG ullRsr12M; - ULONGLONG ullRsr9M; - ULONGLONG ullRsr6M; - - ULONGLONG ullRsr54MCRCOk; - ULONGLONG ullRsr48MCRCOk; - ULONGLONG ullRsr36MCRCOk; - ULONGLONG ullRsr24MCRCOk; - ULONGLONG ullRsr18MCRCOk; - ULONGLONG ullRsr12MCRCOk; - ULONGLONG ullRsr9MCRCOk; - ULONGLONG ullRsr6MCRCOk; + unsigned long long ullTsrAllOK; + + unsigned long long ullRsr11M; + unsigned long long ullRsr5M; + unsigned long long ullRsr2M; + unsigned long long ullRsr1M; + + unsigned long long ullRsr11MCRCOk; + unsigned long long ullRsr5MCRCOk; + unsigned long long ullRsr2MCRCOk; + unsigned long long ullRsr1MCRCOk; + + unsigned long long ullRsr54M; + unsigned long long ullRsr48M; + unsigned long long ullRsr36M; + unsigned long long ullRsr24M; + unsigned long long ullRsr18M; + unsigned long long ullRsr12M; + unsigned long long ullRsr9M; + unsigned long long ullRsr6M; + + unsigned long long ullRsr54MCRCOk; + unsigned long long ullRsr48MCRCOk; + unsigned long long ullRsr36MCRCOk; + unsigned long long ullRsr24MCRCOk; + unsigned long long ullRsr18MCRCOk; + unsigned long long ullRsr12MCRCOk; + unsigned long long ullRsr9MCRCOk; + unsigned long long ullRsr6MCRCOk; } SCustomCounters, *PSCustomCounters; @@ -251,15 +251,15 @@ typedef struct tagSStatCounter { DWORD dwRsrMulticast; DWORD dwRsrDirected; // 64-bit OID - ULONGLONG ullRsrOK; + unsigned long long ullRsrOK; // for some optional OIDs (64 bits) and DMI support - ULONGLONG ullRxBroadcastBytes; - ULONGLONG ullRxMulticastBytes; - ULONGLONG ullRxDirectedBytes; - ULONGLONG ullRxBroadcastFrames; - ULONGLONG ullRxMulticastFrames; - ULONGLONG ullRxDirectedFrames; + unsigned long long ullRxBroadcastBytes; + unsigned long long ullRxMulticastBytes; + unsigned long long ullRxDirectedBytes; + unsigned long long ullRxBroadcastFrames; + unsigned long long ullRxMulticastFrames; + unsigned long long ullRxDirectedFrames; DWORD dwRsrRxFragment; DWORD dwRsrRxFrmLen64; @@ -304,15 +304,15 @@ typedef struct tagSStatCounter { unsigned int idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD // 64-bit OID - ULONGLONG ullTsrOK[TYPE_MAXTD]; + unsigned long long ullTsrOK[TYPE_MAXTD]; // for some optional OIDs (64 bits) and DMI support - ULONGLONG ullTxBroadcastFrames[TYPE_MAXTD]; - ULONGLONG ullTxMulticastFrames[TYPE_MAXTD]; - ULONGLONG ullTxDirectedFrames[TYPE_MAXTD]; - ULONGLONG ullTxBroadcastBytes[TYPE_MAXTD]; - ULONGLONG ullTxMulticastBytes[TYPE_MAXTD]; - ULONGLONG ullTxDirectedBytes[TYPE_MAXTD]; + unsigned long long ullTxBroadcastFrames[TYPE_MAXTD]; + unsigned long long ullTxMulticastFrames[TYPE_MAXTD]; + unsigned long long ullTxDirectedFrames[TYPE_MAXTD]; + unsigned long long ullTxBroadcastBytes[TYPE_MAXTD]; + unsigned long long ullTxMulticastBytes[TYPE_MAXTD]; + unsigned long long ullTxDirectedBytes[TYPE_MAXTD]; // DWORD dwTxRetryCount[8]; // diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 950fb097e460..f97a3eeed9a1 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -68,10 +68,6 @@ typedef int BOOL; * but it doesn't matter if they're signed or unsigned. */ -typedef unsigned long long ULONGLONG; //64 bit - - - typedef unsigned char BYTE; // 8-bit typedef unsigned short WORD; // 16-bit typedef unsigned long DWORD; // 32-bit diff --git a/drivers/staging/vt6655/wpactl.h b/drivers/staging/vt6655/wpactl.h index b0d92d51a2a6..52bc7e3dbb48 100644 --- a/drivers/staging/vt6655/wpactl.h +++ b/drivers/staging/vt6655/wpactl.h @@ -54,7 +54,7 @@ typedef enum { KEY_MGMT_802_1X, KEY_MGMT_CCKM,KEY_MGMT_PSK, KEY_MGMT_NONE, -typedef ULONGLONG NDIS_802_11_KEY_RSC; +typedef unsigned long long NDIS_802_11_KEY_RSC; /*--------------------- Export Classes ----------------------------*/ -- cgit v1.2.3 From 2989e96f17f2dcbd73aee37856899c2885df0686 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Sat, 5 Jun 2010 15:13:47 -0700 Subject: Staging: vt6655: remove PBYTE typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use unsigned char * instead. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/80211hdr.h | 4 +- drivers/staging/vt6655/80211mgr.c | 34 ++--- drivers/staging/vt6655/80211mgr.h | 24 ++-- drivers/staging/vt6655/IEEE11h.c | 6 +- drivers/staging/vt6655/aes_ccmp.c | 6 +- drivers/staging/vt6655/aes_ccmp.h | 2 +- drivers/staging/vt6655/baseband.c | 8 +- drivers/staging/vt6655/baseband.h | 8 +- drivers/staging/vt6655/bssdb.c | 26 ++-- drivers/staging/vt6655/bssdb.h | 16 +-- drivers/staging/vt6655/card.c | 28 ++-- drivers/staging/vt6655/card.h | 18 +-- drivers/staging/vt6655/datarate.c | 4 +- drivers/staging/vt6655/datarate.h | 4 +- drivers/staging/vt6655/desc.h | 2 +- drivers/staging/vt6655/device.h | 10 +- drivers/staging/vt6655/device_main.c | 22 +-- drivers/staging/vt6655/dpc.c | 106 +++++++-------- drivers/staging/vt6655/hostap.c | 4 +- drivers/staging/vt6655/ioctl.c | 4 +- drivers/staging/vt6655/ioctl.h | 2 +- drivers/staging/vt6655/iwctl.c | 2 +- drivers/staging/vt6655/key.c | 16 +-- drivers/staging/vt6655/key.h | 16 +-- drivers/staging/vt6655/mac.c | 20 +-- drivers/staging/vt6655/mac.h | 24 ++-- drivers/staging/vt6655/mib.c | 12 +- drivers/staging/vt6655/mib.h | 8 +- drivers/staging/vt6655/michael.c | 2 +- drivers/staging/vt6655/michael.h | 2 +- drivers/staging/vt6655/power.c | 4 +- drivers/staging/vt6655/rc4.c | 10 +- drivers/staging/vt6655/rc4.h | 4 +- drivers/staging/vt6655/rxtx.c | 250 +++++++++++++++++------------------ drivers/staging/vt6655/rxtx.h | 10 +- drivers/staging/vt6655/srom.c | 12 +- drivers/staging/vt6655/srom.h | 8 +- drivers/staging/vt6655/tcrc.c | 6 +- drivers/staging/vt6655/tcrc.h | 6 +- drivers/staging/vt6655/tether.c | 4 +- drivers/staging/vt6655/tether.h | 6 +- drivers/staging/vt6655/tkip.c | 6 +- drivers/staging/vt6655/tkip.h | 6 +- drivers/staging/vt6655/ttype.h | 2 - drivers/staging/vt6655/upc.h | 4 +- drivers/staging/vt6655/vntwifi.c | 16 +-- drivers/staging/vt6655/vntwifi.h | 14 +- drivers/staging/vt6655/wcmd.c | 12 +- drivers/staging/vt6655/wcmd.h | 2 +- drivers/staging/vt6655/wctl.c | 4 +- drivers/staging/vt6655/wmgr.c | 140 ++++++++++---------- drivers/staging/vt6655/wmgr.h | 10 +- drivers/staging/vt6655/wpa.c | 4 +- drivers/staging/vt6655/wpa2.c | 6 +- drivers/staging/vt6655/wpactl.c | 12 +- drivers/staging/vt6655/wroute.c | 6 +- drivers/staging/vt6655/wroute.h | 2 +- 57 files changed, 503 insertions(+), 503 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/80211hdr.h b/drivers/staging/vt6655/80211hdr.h index b7b170e19aa2..5d8e4c64df9a 100644 --- a/drivers/staging/vt6655/80211hdr.h +++ b/drivers/staging/vt6655/80211hdr.h @@ -282,8 +282,8 @@ #define WLAN_MGMT_GET_TIM_OFFSET(b) (((b) & ~BIT0) >> 1) /* 3-Addr & 4-Addr */ -#define WLAN_HDR_A3_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR3_LEN) -#define WLAN_HDR_A4_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR4_LEN) +#define WLAN_HDR_A3_DATA_PTR(p) (((unsigned char *)(p)) + WLAN_HDR_ADDR3_LEN) +#define WLAN_HDR_A4_DATA_PTR(p) (((unsigned char *)(p)) + WLAN_HDR_ADDR4_LEN) /* IEEE ADDR */ #define IEEE_ADDR_UNIVERSAL 0x02 diff --git a/drivers/staging/vt6655/80211mgr.c b/drivers/staging/vt6655/80211mgr.c index 38697c862489..9fbced855059 100644 --- a/drivers/staging/vt6655/80211mgr.c +++ b/drivers/staging/vt6655/80211mgr.c @@ -139,9 +139,9 @@ vMgrDecodeBeacon( + WLAN_BEACON_OFF_CAPINFO); // Information elements - pItem = (PWLAN_IE)((PBYTE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))) + pItem = (PWLAN_IE)((unsigned char *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))) + WLAN_BEACON_OFF_SSID); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ){ + while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ){ switch (pItem->byElementID) { case WLAN_EID_SSID: @@ -223,7 +223,7 @@ vMgrDecodeBeacon( break; } - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); } return; @@ -386,7 +386,7 @@ vMgrDecodeAssocRequest( pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_SSID); - while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { + while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) { switch (pItem->byElementID){ case WLAN_EID_SSID: if (pFrame->pSSID == NULL) @@ -418,7 +418,7 @@ vMgrDecodeAssocRequest( pItem->byElementID); break; } - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); } return; } @@ -488,9 +488,10 @@ vMgrDecodeAssocResponse( + WLAN_ASSOCRESP_OFF_SUPP_RATES); pItem = (PWLAN_IE)(pFrame->pSuppRates); - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); - if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && + (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem); } @@ -564,7 +565,7 @@ vMgrDecodeReassocRequest( pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_SSID); - while(((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { + while(((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) { switch (pItem->byElementID){ case WLAN_EID_SSID: @@ -597,7 +598,7 @@ vMgrDecodeReassocRequest( pItem->byElementID); break; } - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); } return; } @@ -649,7 +650,7 @@ vMgrDecodeProbeRequest( // Information elements pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ) { switch (pItem->byElementID) { case WLAN_EID_SSID: @@ -672,7 +673,7 @@ vMgrDecodeProbeRequest( break; } - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); } return; } @@ -746,7 +747,7 @@ vMgrDecodeProbeResponse( pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_SSID); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ) { switch (pItem->byElementID) { case WLAN_EID_SSID: if (pFrame->pSSID == NULL) @@ -821,7 +822,7 @@ vMgrDecodeProbeResponse( break; } - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); } return; } @@ -890,7 +891,7 @@ vMgrDecodeAuthen( pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_CHALLENGE); - if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) { + if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) { pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem; } @@ -1017,9 +1018,10 @@ vMgrDecodeReassocResponse( + WLAN_REASSOCRESP_OFF_SUPP_RATES); pItem = (PWLAN_IE)(pFrame->pSuppRates); - pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len); - if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && + (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; } return; diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h index b6ee8220f1f6..bb58ed0ba3a3 100644 --- a/drivers/staging/vt6655/80211mgr.h +++ b/drivers/staging/vt6655/80211mgr.h @@ -497,7 +497,7 @@ typedef struct tagWLAN_FR_MGMT { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; } WLAN_FR_MGMT, *PWLAN_FR_MGMT; @@ -507,7 +507,7 @@ typedef struct tagWLAN_FR_BEACON { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; // fixed fields PQWORD pqwTimestamp; @@ -539,7 +539,7 @@ typedef struct tagWLAN_FR_IBSSATIM { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; // fixed fields @@ -553,7 +553,7 @@ typedef struct tagWLAN_FR_DISASSOC { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwReason; @@ -566,7 +566,7 @@ typedef struct tagWLAN_FR_ASSOCREQ { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwCapInfo; @@ -587,7 +587,7 @@ typedef struct tagWLAN_FR_ASSOCRESP { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwCapInfo; @@ -604,7 +604,7 @@ typedef struct tagWLAN_FR_REASSOCREQ { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ @@ -626,7 +626,7 @@ typedef struct tagWLAN_FR_REASSOCRESP { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwCapInfo; @@ -643,7 +643,7 @@ typedef struct tagWLAN_FR_PROBEREQ { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ /*-- info elements ----------*/ @@ -658,7 +658,7 @@ typedef struct tagWLAN_FR_PROBERESP { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PQWORD pqwTimestamp; @@ -687,7 +687,7 @@ typedef struct tagWLAN_FR_AUTHEN { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwAuthAlgorithm; @@ -703,7 +703,7 @@ typedef struct tagWLAN_FR_DEAUTHEN { unsigned int uType; unsigned int len; - PBYTE pBuf; + unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PWORD pwReason; diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c index 55e66e9e0dde..7576289c4902 100644 --- a/drivers/staging/vt6655/IEEE11h.c +++ b/drivers/staging/vt6655/IEEE11h.c @@ -125,9 +125,9 @@ static BOOL s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, BYTE byR pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); - pFrame = (PWLAN_FRAME_TPCREP)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); pFrame->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) @@ -276,7 +276,7 @@ BOOL IEEE11hbMSRRepTx ( pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); pMSRRep->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c index fef1b91c2925..f148356cdfc5 100644 --- a/drivers/staging/vt6655/aes_ccmp.c +++ b/drivers/staging/vt6655/aes_ccmp.c @@ -243,7 +243,7 @@ BYTE abyRoundKey[16]; * Return Value: MIC compare result * */ -BOOL AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize) +BOOL AESbGenCCMP(unsigned char *pbyRxKey, unsigned char *pbyFrame, WORD wFrameSize) { BYTE abyNonce[13]; BYTE MIC_IV[16]; @@ -256,8 +256,8 @@ BYTE abyPlainText[16]; BYTE abyLastCipher[16]; PS802_11Header pMACHeader = (PS802_11Header) pbyFrame; -PBYTE pbyIV; -PBYTE pbyPayload; +unsigned char *pbyIV; +unsigned char *pbyPayload; WORD wHLen = 22; WORD wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC BOOL bA4 = FALSE; diff --git a/drivers/staging/vt6655/aes_ccmp.h b/drivers/staging/vt6655/aes_ccmp.h index f2ba1d5aa1e5..2909e5b79a57 100644 --- a/drivers/staging/vt6655/aes_ccmp.h +++ b/drivers/staging/vt6655/aes_ccmp.h @@ -41,6 +41,6 @@ /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Functions --------------------------*/ -BOOL AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize); +BOOL AESbGenCCMP(unsigned char *pbyRxKey, unsigned char *pbyFrame, WORD wFrameSize); #endif //__AES_H__ diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index c772c2901641..f96a33787d1e 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1850,8 +1850,8 @@ BBvCaculateParameter ( WORD wRate, BYTE byPacketType, PWORD pwPhyLen, - PBYTE pbyPhySrv, - PBYTE pbyPhySgn + unsigned char *pbyPhySrv, + unsigned char *pbyPhySgn ) { unsigned int cbBitCount; @@ -2015,7 +2015,7 @@ BBvCaculateParameter ( * Return Value: TRUE if succeeded; FALSE if failed. * */ -BOOL BBbReadEmbeded (DWORD_PTR dwIoBase, BYTE byBBAddr, PBYTE pbyData) +BOOL BBbReadEmbeded (DWORD_PTR dwIoBase, BYTE byBBAddr, unsigned char *pbyData) { WORD ww; BYTE byValue; @@ -2321,7 +2321,7 @@ BOOL BBbVT3253Init (PSDevice pDevice) * Return Value: none * */ -void BBvReadAllRegs (DWORD_PTR dwIoBase, PBYTE pbyBBRegs) +void BBvReadAllRegs (DWORD_PTR dwIoBase, unsigned char *pbyBBRegs) { int ii; BYTE byBase = 1; diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 3372546662d9..616dab6f3ac1 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -133,14 +133,14 @@ BBvCaculateParameter ( WORD wRate, BYTE byPacketType, PWORD pwPhyLen, - PBYTE pbyPhySrv, - PBYTE pbyPhySgn + unsigned char *pbyPhySrv, + unsigned char *pbyPhySgn ); -BOOL BBbReadEmbeded(DWORD_PTR dwIoBase, BYTE byBBAddr, PBYTE pbyData); +BOOL BBbReadEmbeded(DWORD_PTR dwIoBase, BYTE byBBAddr, unsigned char *pbyData); BOOL BBbWriteEmbeded(DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byData); -void BBvReadAllRegs(DWORD_PTR dwIoBase, PBYTE pbyBBRegs); +void BBvReadAllRegs(DWORD_PTR dwIoBase, unsigned char *pbyBBRegs); void BBvLoopbackOn(PSDevice pDevice); void BBvLoopbackOff(PSDevice pDevice); void BBvSetShortSlotTime(PSDevice pDevice); diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index d16d799636a3..76e81362fc17 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -126,14 +126,14 @@ void s_vCheckPreEDThreshold( PKnownBSS BSSpSearchBSSList( void *hDeviceContext, - PBYTE pbyDesireBSSID, - PBYTE pbyDesireSSID, + unsigned char *pbyDesireBSSID, + unsigned char *pbyDesireSSID, CARD_PHY_TYPE ePhyType ) { PSDevice pDevice = (PSDevice)hDeviceContext; PSMgmtObject pMgmt = pDevice->pMgmt; - PBYTE pbyBSSID = NULL; + unsigned char *pbyBSSID = NULL; PWLAN_IE_SSID pSSID = NULL; PKnownBSS pCurrBSS = NULL; PKnownBSS pSelect = NULL; @@ -326,7 +326,7 @@ BSSvClearBSSList( PKnownBSS BSSpAddrIsInBSSList( void *hDeviceContext, - PBYTE abyBSSID, + unsigned char *abyBSSID, PWLAN_IE_SSID pSSID ) { @@ -369,7 +369,7 @@ BSSpAddrIsInBSSList( BOOL BSSbInsertToBSSList ( void *hDeviceContext, - PBYTE abyBSSIDAddr, + unsigned char *abyBSSIDAddr, QWORD qwTimestamp, WORD wBeaconInterval, WORD wCapInfo, @@ -383,7 +383,7 @@ BSSbInsertToBSSList ( PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, unsigned int uIELength, - PBYTE pbyIEs, + unsigned char *pbyIEs, void *pRxPacketContext ) { @@ -470,7 +470,7 @@ BSSbInsertToBSSList ( if (pRSNWPA != NULL) { unsigned int uLen = pRSNWPA->len + 2; - if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((unsigned char *)pRSNWPA - pbyIEs))) { pBSSList->wWPALen = uLen; memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); WPA_ParseRSN(pBSSList, pRSNWPA); @@ -481,7 +481,7 @@ BSSbInsertToBSSList ( if (pRSN != NULL) { unsigned int uLen = pRSN->len + 2; - if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((unsigned char *)pRSN - pbyIEs))) { pBSSList->wRSNLen = uLen; memcpy(pBSSList->byRSNIE, pRSN, uLen); WPA2vParseRSN(pBSSList, pRSN); @@ -601,7 +601,7 @@ BSSbUpdateToBSSList ( PWLAN_IE_QUIET pIE_Quiet, PKnownBSS pBSSList, unsigned int uIELength, - PBYTE pbyIEs, + unsigned char *pbyIEs, void *pRxPacketContext ) { @@ -671,7 +671,7 @@ BSSbUpdateToBSSList ( if (pRSNWPA != NULL) { unsigned int uLen = pRSNWPA->len + 2; - if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((unsigned char *)pRSNWPA - pbyIEs))) { pBSSList->wWPALen = uLen; memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); WPA_ParseRSN(pBSSList, pRSNWPA); @@ -682,7 +682,7 @@ BSSbUpdateToBSSList ( if (pRSN != NULL) { unsigned int uLen = pRSN->len + 2; - if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + if (uLen <= (uIELength - (unsigned int)(ULONG_PTR)((unsigned char *)pRSN - pbyIEs))) { pBSSList->wRSNLen = uLen; memcpy(pBSSList->byRSNIE, pRSN, uLen); WPA2vParseRSN(pBSSList, pRSN); @@ -765,7 +765,7 @@ BSSbUpdateToBSSList ( BOOL BSSDBbIsSTAInNodeDB( void *pMgmtObject, - PBYTE abyDstAddr, + unsigned char *abyDstAddr, PUINT puNodeIndex ) { @@ -1393,7 +1393,7 @@ BSSvUpdateNodeTxCounter( void *hDeviceContext, BYTE byTsr0, BYTE byTsr1, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int uFIFOHeaderSize ) { diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index d1d947879197..ac6473a05ba3 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -245,15 +245,15 @@ typedef struct tagKnownNodeDB { PKnownBSS BSSpSearchBSSList( void *hDeviceContext, - PBYTE pbyDesireBSSID, - PBYTE pbyDesireSSID, + unsigned char *pbyDesireBSSID, + unsigned char *pbyDesireSSID, CARD_PHY_TYPE ePhyType ); PKnownBSS BSSpAddrIsInBSSList( void *hDeviceContext, - PBYTE abyBSSID, + unsigned char *abyBSSID, PWLAN_IE_SSID pSSID ); @@ -266,7 +266,7 @@ BSSvClearBSSList( BOOL BSSbInsertToBSSList( void *hDeviceContext, - PBYTE abyBSSIDAddr, + unsigned char *abyBSSIDAddr, QWORD qwTimestamp, WORD wBeaconInterval, WORD wCapInfo, @@ -280,7 +280,7 @@ BSSbInsertToBSSList( PWLAN_IE_COUNTRY pIE_Country, PWLAN_IE_QUIET pIE_Quiet, unsigned int uIELength, - PBYTE pbyIEs, + unsigned char *pbyIEs, void *pRxPacketContext ); @@ -303,7 +303,7 @@ BSSbUpdateToBSSList( PWLAN_IE_QUIET pIE_Quiet, PKnownBSS pBSSList, unsigned int uIELength, - PBYTE pbyIEs, + unsigned char *pbyIEs, void *pRxPacketContext ); @@ -311,7 +311,7 @@ BSSbUpdateToBSSList( BOOL BSSDBbIsSTAInNodeDB( void *hDeviceContext, - PBYTE abyDstAddr, + unsigned char *abyDstAddr, PUINT puNodeIndex ); @@ -341,7 +341,7 @@ BSSvUpdateNodeTxCounter( void *hDeviceContext, BYTE byTsr0, BYTE byTsr1, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int uFIFOHeaderSize ); diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 439bb0c4ca68..5ce98a07c554 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -427,8 +427,8 @@ void s_vCaculateOFDMRParameter( BYTE byRate, CARD_PHY_TYPE ePHYType, - PBYTE pbyTxRate, - PBYTE pbyRsvTime + unsigned char *pbyTxRate, + unsigned char *pbyRsvTime ); @@ -499,8 +499,8 @@ void s_vCaculateOFDMRParameter ( BYTE byRate, CARD_PHY_TYPE ePHYType, - PBYTE pbyTxRate, - PBYTE pbyRsvTime + unsigned char *pbyTxRate, + unsigned char *pbyRsvTime ) { switch (byRate) { @@ -1296,7 +1296,7 @@ BOOL CARDbStartTxPacket (void *pDeviceHandler, CARD_PKT_TYPE ePktType) * Return Value: TRUE if success; FALSE if failed. * */ -BOOL CARDbSetBSSID(void *pDeviceHandler, PBYTE pbyBSSID, CARD_OP_MODE eOPMode) +BOOL CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE eOPMode) { PSDevice pDevice = (PSDevice) pDeviceHandler; @@ -1522,7 +1522,7 @@ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); //LED issue -BOOL CARDbRemoveKey (void *pDeviceHandler, PBYTE pbyBSSID) +BOOL CARDbRemoveKey (void *pDeviceHandler, unsigned char *pbyBSSID) { PSDevice pDevice = (PSDevice) pDeviceHandler; @@ -1550,7 +1550,7 @@ BOOL CARDbRemoveKey (void *pDeviceHandler, PBYTE pbyBSSID) BOOL CARDbAdd_PMKID_Candidate ( void *pDeviceHandler, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, BOOL bRSNCapExist, WORD wRSNCap ) @@ -2129,8 +2129,8 @@ CARDvSetPowerConstraint ( void CARDvGetPowerCapability ( void *pDeviceHandler, - PBYTE pbyMinPower, - PBYTE pbyMaxPower + unsigned char *pbyMinPower, + unsigned char *pbyMaxPower ) { PSDevice pDevice = (PSDevice) pDeviceHandler; @@ -2165,14 +2165,14 @@ CARDvGetPowerCapability ( BYTE CARDbySetSupportChannels ( void *pDeviceHandler, - PBYTE pbyIEs + unsigned char *pbyIEs ) { PSDevice pDevice = (PSDevice) pDeviceHandler; unsigned int ii; BYTE byCount; PWLAN_IE_SUPP_CH pIE = (PWLAN_IE_SUPP_CH) pbyIEs; - PBYTE pbyChTupple; + unsigned char *pbyChTupple; BYTE byLen = 0; @@ -2267,7 +2267,7 @@ CARDbyGetTransmitPower ( BOOL CARDbChannelGetList ( unsigned int uCountryCodeIdx, - PBYTE pbyChannelTable + unsigned char *pbyChannelTable ) { if (uCountryCodeIdx >= CCODE_MAX) { @@ -2308,8 +2308,8 @@ BOOL CARDbGetChannelMapInfo( void *pDeviceHandler, unsigned int uChannelIndex, - PBYTE pbyChannelNumber, - PBYTE pbyMap + unsigned char *pbyChannelNumber, + unsigned char *pbyMap ) { // PSDevice pDevice = (PSDevice) pDeviceHandler; diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 40271a1f1873..034394d46dc8 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -116,7 +116,7 @@ BOOL CARDbUpdateTSF(void *pDeviceHandler, BYTE byRxRate, QWORD qwBSSTimestamp, Q BOOL CARDbStopTxPacket(void *pDeviceHandler, CARD_PKT_TYPE ePktType); BOOL CARDbStartTxPacket(void *pDeviceHandler, CARD_PKT_TYPE ePktType); BOOL CARDbSetBeaconPeriod(void *pDeviceHandler, WORD wBeaconInterval); -BOOL CARDbSetBSSID(void *pDeviceHandler, PBYTE pbyBSSID, CARD_OP_MODE eOPMode); +BOOL CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE eOPMode); BOOL CARDbPowerDown( @@ -129,12 +129,12 @@ BOOL CARDbSetTxDataRate( ); -BOOL CARDbRemoveKey (void *pDeviceHandler, PBYTE pbyBSSID); +BOOL CARDbRemoveKey (void *pDeviceHandler, unsigned char *pbyBSSID); BOOL CARDbAdd_PMKID_Candidate ( void *pDeviceHandler, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, BOOL bRSNCapExist, WORD wRSNCap ); @@ -195,14 +195,14 @@ CARDvSetPowerConstraint ( void CARDvGetPowerCapability ( void *pDeviceHandler, - PBYTE pbyMinPower, - PBYTE pbyMaxPower + unsigned char *pbyMinPower, + unsigned char *pbyMaxPower ); BYTE CARDbySetSupportChannels ( void *pDeviceHandler, - PBYTE pbyIEs + unsigned char *pbyIEs ); char @@ -213,7 +213,7 @@ CARDbyGetTransmitPower ( BOOL CARDbChannelGetList ( unsigned int uCountryCodeIdx, - PBYTE pbyChannelTable + unsigned char *pbyChannelTable ); void @@ -226,8 +226,8 @@ BOOL CARDbGetChannelMapInfo( void *pDeviceHandler, unsigned int uChannelIndex, - PBYTE pbyChannelNumber, - PBYTE pbyMap + unsigned char *pbyChannelNumber, + unsigned char *pbyMap ); void diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c index ecec01ea0807..e1ab30079c03 100644 --- a/drivers/staging/vt6655/datarate.c +++ b/drivers/staging/vt6655/datarate.c @@ -203,8 +203,8 @@ RATEvParseMaxRate ( PWORD pwMaxBasicRate, PWORD pwMaxSuppRate, PWORD pwSuppRate, - PBYTE pbyTopCCKRate, - PBYTE pbyTopOFDMRate + unsigned char *pbyTopCCKRate, + unsigned char *pbyTopOFDMRate ) { PSDevice pDevice = (PSDevice) pDeviceHandler; diff --git a/drivers/staging/vt6655/datarate.h b/drivers/staging/vt6655/datarate.h index 760d464890c7..2cb3b5097a5c 100644 --- a/drivers/staging/vt6655/datarate.h +++ b/drivers/staging/vt6655/datarate.h @@ -63,8 +63,8 @@ RATEvParseMaxRate( PWORD pwMaxBasicRate, PWORD pwMaxSuppRate, PWORD pwSuppRate, - PBYTE pbyTopCCKRate, - PBYTE pbyTopOFDMRate + unsigned char *pbyTopCCKRate, + unsigned char *pbyTopOFDMRate ); void diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index a16d2e0049dc..9894d9e2e28f 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -350,7 +350,7 @@ STDES1; typedef struct tagDEVICE_TD_INFO{ struct sk_buff* skb; - PBYTE buf; + unsigned char *buf; dma_addr_t skb_dma; dma_addr_t buf_dma; dma_addr_t curr_desc; diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 736af6e49a8e..56e05f0fa963 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -324,7 +324,7 @@ typedef struct tagSDeFragControlBlock BYTE abyAddr2[ETH_ALEN]; unsigned int uLifetime; struct sk_buff* skb; - PBYTE pbyRxBuffer; + unsigned char *pbyRxBuffer; unsigned int cbFrameLength; BOOL bInUse; } SDeFragControlBlock, *PSDeFragControlBlock; @@ -417,9 +417,9 @@ typedef struct __device_info { dma_addr_t tx_bufs_dma1; dma_addr_t tx_beacon_dma; - PBYTE tx0_bufs; - PBYTE tx1_bufs; - PBYTE tx_beacon_bufs; + unsigned char *tx0_bufs; + unsigned char *tx1_bufs; + unsigned char *tx_beacon_bufs; CHIP_TYPE chip_id; @@ -507,7 +507,7 @@ typedef struct __device_info { BYTE byTxAntennaMode; BOOL bTxRxAntInv; - PBYTE pbyTmpBuff; + unsigned char *pbyTmpBuff; unsigned int uSIFS; //Current SIFS unsigned int uDIFS; //Current DIFS unsigned int uEIFS; //Current EIFS diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index e3c2ba758b2e..ecc362d3fdd9 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1699,13 +1699,13 @@ static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { STAvUpdateTDStatCounter(&pDevice->scStatistic, byTsr0, byTsr1, - (PBYTE)(pTD->pTDInfo->buf + uFIFOHeaderSize), + (unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize), uFrameSize, uIdx); BSSvUpdateNodeTxCounter(pDevice, byTsr0, byTsr1, - (PBYTE)(pTD->pTDInfo->buf), + (unsigned char *)(pTD->pTDInfo->buf), uFIFOHeaderSize ); @@ -1756,7 +1756,7 @@ static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; skb = pTD->pTDInfo->skb; - if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data), &uNodeIndex)) { + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) { if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; @@ -2084,7 +2084,7 @@ device_release_WPADEV(pDevice); static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { PSDevice pDevice=netdev_priv(dev); - PBYTE pbMPDU; + unsigned char *pbMPDU; unsigned int cbMPDULen = 0; @@ -2154,7 +2154,7 @@ BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeI pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); - memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), ETH_HLEN); + memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN); cbFrameBodySize = skb->len - ETH_HLEN; // 802.1H @@ -2228,7 +2228,7 @@ BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeI } vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption, cbFrameBodySize, TYPE_TXDMA0, pHeadTD, - &pDevice->sTxEthHeader, (PBYTE)skb->data, pTransmitKey, uNodeIndex, + &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex, &uMACfragNum, &cbHeaderSize ); @@ -2284,7 +2284,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int ii; BOOL bTKIP_UseGTK = FALSE; BOOL bNeedDeAuth = FALSE; - PBYTE pbyBSSID; + unsigned char *pbyBSSID; BOOL bNodeExist = FALSE; @@ -2309,7 +2309,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { spin_unlock_irq(&pDevice->lock); return 0; } - if (is_multicast_ether_addr((PBYTE)(skb->data))) { + if (is_multicast_ether_addr((unsigned char *)(skb->data))) { uNodeIndex = 0; bNodeExist = TRUE; if (pMgmt->sNodeDBTable[0].bPSEnable) { @@ -2321,7 +2321,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { return 0; } }else { - if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data), &uNodeIndex)) { + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) { if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; @@ -2358,7 +2358,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); - memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), ETH_HLEN); + memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN); cbFrameBodySize = skb->len - ETH_HLEN; // 802.1H if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) { @@ -2586,7 +2586,7 @@ pDevice->byTopCCKBasicRate,pDevice->byTopOFDMBasicRate); #endif vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption, cbFrameBodySize, TYPE_AC0DMA, pHeadTD, - &pDevice->sTxEthHeader, (PBYTE)skb->data, pTransmitKey, uNodeIndex, + &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex, &uMACfragNum, &cbHeaderSize ); diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 286461ca4e56..723f8466bd61 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -82,7 +82,7 @@ static BYTE s_byGetRateIdx(BYTE byRate); static void s_vGetDASA( - PBYTE pbyRxBufferAddr, + unsigned char *pbyRxBufferAddr, PUINT pcbHeaderSize, PSEthernetHeader psEthHeader ); @@ -91,7 +91,7 @@ static void s_vProcessRxMACHeader ( PSDevice pDevice, - PBYTE pbyRxBufferAddr, + unsigned char *pbyRxBufferAddr, unsigned int cbPacketSize, BOOL bIsWEP, BOOL bExtIV, @@ -100,7 +100,7 @@ s_vProcessRxMACHeader ( static BOOL s_bAPModeRxCtl( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, int iSANodeIndex ); @@ -118,10 +118,10 @@ static BOOL s_bAPModeRxData ( static BOOL s_bHandleRxEncryption( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, unsigned int FrameSize, - PBYTE pbyRsr, - PBYTE pbyNewRsr, + unsigned char *pbyRsr, + unsigned char *pbyNewRsr, PSKeyItem *pKeyOut, int * pbExtIV, PWORD pwRxTSC15_0, @@ -131,12 +131,12 @@ static BOOL s_bHandleRxEncryption( static BOOL s_bHostWepRxEncryption( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, unsigned int FrameSize, - PBYTE pbyRsr, + unsigned char *pbyRsr, BOOL bOnFly, PSKeyItem pKey, - PBYTE pbyNewRsr, + unsigned char *pbyNewRsr, int * pbExtIV, PWORD pwRxTSC15_0, PDWORD pdwRxTSC47_16 @@ -166,14 +166,14 @@ static void s_vProcessRxMACHeader ( PSDevice pDevice, - PBYTE pbyRxBufferAddr, + unsigned char *pbyRxBufferAddr, unsigned int cbPacketSize, BOOL bIsWEP, BOOL bExtIV, PUINT pcbHeadSize ) { - PBYTE pbyRxBuffer; + unsigned char *pbyRxBuffer; unsigned int cbHeaderSize = 0; PWORD pwType; PS802_11Header pMACHeader; @@ -182,7 +182,7 @@ s_vProcessRxMACHeader ( pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize); - s_vGetDASA((PBYTE)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); + s_vGetDASA((unsigned char *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); if (bIsWEP) { if (bExtIV) { @@ -197,7 +197,7 @@ s_vProcessRxMACHeader ( cbHeaderSize += WLAN_HDR_ADDR3_LEN; }; - pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize); + pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize); if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { cbHeaderSize += 6; } @@ -237,7 +237,7 @@ s_vProcessRxMACHeader ( } cbHeaderSize -= (ETH_ALEN * 2); - pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize); + pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize); for(ii=0;iisRxEthHeader.abyDstAddr[ii]; for(ii=0;iipMgmt; PSRxMgmtPacket pRxPacket = &(pDevice->pMgmt->sRxPacket); PS802_11Header p802_11Header; - PBYTE pbyRsr; - PBYTE pbyNewRsr; - PBYTE pbyRSSI; + unsigned char *pbyRsr; + unsigned char *pbyNewRsr; + unsigned char *pbyRSSI; PQWORD pqwTSFTime; PWORD pwFrameSize; - PBYTE pbyFrame; + unsigned char *pbyFrame; BOOL bDeFragRx = FALSE; BOOL bIsWEP = FALSE; unsigned int cbHeaderOffset; @@ -365,9 +365,9 @@ device_receive_frame ( unsigned int ii; unsigned int cbIVOffset; BOOL bExtIV = FALSE; - PBYTE pbyRxSts; - PBYTE pbyRxRate; - PBYTE pbySQ; + unsigned char *pbyRxSts; + unsigned char *pbyRxRate; + unsigned char *pbySQ; unsigned int cbHeaderSize; PSKeyItem pKey = NULL; WORD wRxTSC15_0 = 0; @@ -402,14 +402,14 @@ device_receive_frame ( return FALSE; } - pbyRxSts = (PBYTE) (skb->data); - pbyRxRate = (PBYTE) (skb->data + 1); - pbyRsr = (PBYTE) (skb->data + FrameSize - 1); - pbyRSSI = (PBYTE) (skb->data + FrameSize - 2); - pbyNewRsr = (PBYTE) (skb->data + FrameSize - 3); - pbySQ = (PBYTE) (skb->data + FrameSize - 4); + pbyRxSts = (unsigned char *) (skb->data); + pbyRxRate = (unsigned char *) (skb->data + 1); + pbyRsr = (unsigned char *) (skb->data + FrameSize - 1); + pbyRSSI = (unsigned char *) (skb->data + FrameSize - 2); + pbyNewRsr = (unsigned char *) (skb->data + FrameSize - 3); + pbySQ = (unsigned char *) (skb->data + FrameSize - 4); pqwTSFTime = (PQWORD) (skb->data + FrameSize - 12); - pbyFrame = (PBYTE)(skb->data + 4); + pbyFrame = (unsigned char *)(skb->data + 4); // get packet size FrameSize = cpu_to_le16(*pwFrameSize); @@ -431,7 +431,7 @@ device_receive_frame ( #endif - pMACHeader=(PS802_11Header)((PBYTE) (skb->data)+8); + pMACHeader=(PS802_11Header)((unsigned char *) (skb->data)+8); //PLICE_DEBUG<- if (pDevice->bMeasureInProgress == TRUE) { if ((*pbyRsr & RSR_CRCOK) != 0) { @@ -475,14 +475,14 @@ device_receive_frame ( s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader); // filter packet send from myself - if (!compare_ether_addr((PBYTE)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) + if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) return FALSE; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { p802_11Header = (PS802_11Header) (pbyFrame); // get SA NodeIndex - if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(p802_11Header->abyAddr2), &iSANodeIndex)) { + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(p802_11Header->abyAddr2), &iSANodeIndex)) { pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; } @@ -594,8 +594,8 @@ device_receive_frame ( // Handle Control & Manage Frame if (IS_TYPE_MGMT((skb->data+4))) { - PBYTE pbyData1; - PBYTE pbyData2; + unsigned char *pbyData1; + unsigned char *pbyData2; pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4); pRxPacket->cbMPDULen = FrameSize; @@ -827,11 +827,11 @@ device_receive_frame ( } MIC_vInit(dwMICKey0, dwMICKey1); - MIC_vAppend((PBYTE)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12); + MIC_vAppend((unsigned char *)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12); dwMIC_Priority = 0; - MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + MIC_vAppend((unsigned char *)&dwMIC_Priority, 4); // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. - MIC_vAppend((PBYTE)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8), + MIC_vAppend((unsigned char *)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8), FrameSize - WLAN_HDR_ADDR3_LEN - 8); MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); MIC_vUnInit(); @@ -963,7 +963,7 @@ device_receive_frame ( } - s_vProcessRxMACHeader(pDevice, (PBYTE)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); + s_vProcessRxMACHeader(pDevice, (unsigned char *)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); FrameSize -= cbHeaderOffset; cbHeaderOffset += 4; // 4 is Rcv buffer header @@ -1040,7 +1040,7 @@ device_receive_frame ( static BOOL s_bAPModeRxCtl ( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, int iSANodeIndex ) { @@ -1063,7 +1063,7 @@ static BOOL s_bAPModeRxCtl ( // reason = (6) class 2 received from nonauth sta vMgrDeAuthenBeginSta(pDevice, pMgmt, - (PBYTE)(p802_11Header->abyAddr2), + (unsigned char *)(p802_11Header->abyAddr2), (WLAN_MGMT_REASON_CLASS2_NONAUTH), &Status ); @@ -1075,7 +1075,7 @@ static BOOL s_bAPModeRxCtl ( // reason = (7) class 3 received from nonassoc sta vMgrDisassocBeginSta(pDevice, pMgmt, - (PBYTE)(p802_11Header->abyAddr2), + (unsigned char *)(p802_11Header->abyAddr2), (WLAN_MGMT_REASON_CLASS3_NONASSOC), &Status ); @@ -1122,7 +1122,7 @@ static BOOL s_bAPModeRxCtl ( else { vMgrDeAuthenBeginSta(pDevice, pMgmt, - (PBYTE)(p802_11Header->abyAddr2), + (unsigned char *)(p802_11Header->abyAddr2), (WLAN_MGMT_REASON_CLASS2_NONAUTH), &Status ); @@ -1164,10 +1164,10 @@ static BOOL s_bAPModeRxCtl ( static BOOL s_bHandleRxEncryption ( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, unsigned int FrameSize, - PBYTE pbyRsr, - PBYTE pbyNewRsr, + unsigned char *pbyRsr, + unsigned char *pbyNewRsr, PSKeyItem *pKeyOut, int * pbExtIV, PWORD pwRxTSC15_0, @@ -1175,7 +1175,7 @@ static BOOL s_bHandleRxEncryption ( ) { unsigned int PayloadLen = FrameSize; - PBYTE pbyIV; + unsigned char *pbyIV; BYTE byKeyIdx; PSKeyItem pKey = NULL; BYTE byDecMode = KEY_CTL_WEP; @@ -1310,19 +1310,19 @@ static BOOL s_bHandleRxEncryption ( static BOOL s_bHostWepRxEncryption ( PSDevice pDevice, - PBYTE pbyFrame, + unsigned char *pbyFrame, unsigned int FrameSize, - PBYTE pbyRsr, + unsigned char *pbyRsr, BOOL bOnFly, PSKeyItem pKey, - PBYTE pbyNewRsr, + unsigned char *pbyNewRsr, int * pbExtIV, PWORD pwRxTSC15_0, PDWORD pdwRxTSC47_16 ) { unsigned int PayloadLen = FrameSize; - PBYTE pbyIV; + unsigned char *pbyIV; BYTE byKeyIdx; BYTE byDecMode = KEY_CTL_WEP; PS802_11Header pMACHeader; @@ -1460,7 +1460,7 @@ static BOOL s_bAPModeRxData ( if (FrameSize > CB_MAX_BUF_SIZE) return FALSE; // check DA - if(is_multicast_ether_addr((PBYTE)(skb->data+cbHeaderOffset))) { + if(is_multicast_ether_addr((unsigned char *)(skb->data+cbHeaderOffset))) { if (pMgmt->sNodeDBTable[0].bPSEnable) { skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz); @@ -1486,7 +1486,7 @@ static BOOL s_bAPModeRxData ( } else { // check if relay - if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data+cbHeaderOffset), &iDANodeIndex)) { + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data+cbHeaderOffset), &iDANodeIndex)) { if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) { if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) { // queue this skb until next PS tx, and then release. @@ -1515,7 +1515,7 @@ static BOOL s_bAPModeRxData ( iDANodeIndex = 0; if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { - ROUTEbRelay(pDevice, (PBYTE)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex); + ROUTEbRelay(pDevice, (unsigned char *)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex); } if (bRelayOnly) diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index 01429d1a95b5..8faeb6e8a2f3 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -580,7 +580,7 @@ static int hostap_set_encryption(PSDevice pDevice, dwKeyIndex & ~(USE_KEYRSC), param->u.crypt.key_len, (PQWORD) &(KeyRSC), - (PBYTE)abyKey, + (unsigned char *)abyKey, KEY_CTL_WEP, pDevice->PortOffset, pDevice->byLocalID) == TRUE) { @@ -649,7 +649,7 @@ static int hostap_set_encryption(PSDevice pDevice, dwKeyIndex, param->u.crypt.key_len, (PQWORD) &(KeyRSC), - (PBYTE)abyKey, + (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == TRUE) { diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index 6118a3cb02e4..cc4f4c1b4cc0 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -257,7 +257,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { dwKeyIndex, sWEPCmd.auWepKeyLength[ii], NULL, - (PBYTE)&sWEPCmd.abyWepKey[ii][0], + (unsigned char *)&sWEPCmd.abyWepKey[ii][0], KEY_CTL_WEP, pDevice->PortOffset, pDevice->byLocalID); @@ -718,7 +718,7 @@ void vConfigWEPKey ( PSDevice pDevice, DWORD dwKeyIndex, - PBYTE pbyKey, + unsigned char *pbyKey, unsigned long uKeyLength ) { diff --git a/drivers/staging/vt6655/ioctl.h b/drivers/staging/vt6655/ioctl.h index 4a30e271294f..0de2324d15da 100644 --- a/drivers/staging/vt6655/ioctl.h +++ b/drivers/staging/vt6655/ioctl.h @@ -46,7 +46,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq); void vConfigWEPKey ( PSDevice pDevice, DWORD dwKeyIndex, - PBYTE pbyKey, + unsigned char *pbyKey, unsigned long uKeyLength ); */ diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index 74c0b9afd658..a2b2bc5d4341 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -2096,7 +2096,7 @@ int iwctl_siwmlme(struct net_device *dev, switch(mlme->cmd){ case IW_MLME_DEAUTH: //this command seems to be not complete,please test it --einsnliu - //bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (PBYTE)&reason); + //bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (unsigned char *)&reason); break; case IW_MLME_DISASSOC: if(pDevice->bLinkPass == TRUE){ diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 141d249541c2..add139f18662 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -133,7 +133,7 @@ void KeyvInitTable (PSKeyManagement pTable, DWORD_PTR dwIoBase) */ BOOL KeybGetKey ( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, PSKeyItem *pKey ) @@ -191,11 +191,11 @@ BOOL KeybGetKey ( */ BOOL KeybSetKey ( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID @@ -364,7 +364,7 @@ BOOL KeybSetKey ( */ BOOL KeybRemoveKey ( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, DWORD_PTR dwIoBase ) @@ -437,7 +437,7 @@ BOOL KeybRemoveKey ( */ BOOL KeybRemoveAllKey ( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD_PTR dwIoBase ) { @@ -519,7 +519,7 @@ void KeyvRemoveAllWEPKey ( */ BOOL KeybGetTransmitKey ( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyType, PSKeyItem *pKey ) @@ -636,7 +636,7 @@ BOOL KeybSetDefaultKey ( DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID @@ -743,7 +743,7 @@ BOOL KeybSetAllGroupKey ( DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index 8ba8b2752ce6..e8a74b469efc 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -105,18 +105,18 @@ void KeyvInitTable(PSKeyManagement pTable, DWORD_PTR dwIoBase); BOOL KeybGetKey( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, PSKeyItem *pKey ); BOOL KeybSetKey( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID @@ -127,7 +127,7 @@ BOOL KeybSetDefaultKey( DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID @@ -135,14 +135,14 @@ BOOL KeybSetDefaultKey( BOOL KeybRemoveKey( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyIndex, DWORD_PTR dwIoBase ); BOOL KeybGetTransmitKey( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD dwKeyType, PSKeyItem *pKey ); @@ -154,7 +154,7 @@ BOOL KeybCheckPairewiseKey( BOOL KeybRemoveAllKey( PSKeyManagement pTable, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, DWORD_PTR dwIoBase ); @@ -174,7 +174,7 @@ BOOL KeybSetAllGroupKey ( DWORD dwKeyIndex, unsigned long uKeyLength, PQWORD pKeyRSC, - PBYTE pbyKey, + unsigned char *pbyKey, BYTE byKeyDecMode, DWORD_PTR dwIoBase, BYTE byLocalID diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index f4acb2f3213f..9d54b421f770 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -103,7 +103,7 @@ static int msglevel =MSG_LEVEL_INFO; * Return Value: none * */ -void MACvReadAllRegs (DWORD_PTR dwIoBase, PBYTE pbyMacRegs) +void MACvReadAllRegs (DWORD_PTR dwIoBase, unsigned char *pbyMacRegs) { int ii; @@ -342,7 +342,7 @@ void MACvSetRxThreshold (DWORD_PTR dwIoBase, BYTE byThreshold) * Return Value: none * */ -void MACvGetRxThreshold (DWORD_PTR dwIoBase, PBYTE pbyThreshold) +void MACvGetRxThreshold (DWORD_PTR dwIoBase, unsigned char *pbyThreshold) { // get FCR0 VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold); @@ -388,7 +388,7 @@ void MACvSetTxThreshold (DWORD_PTR dwIoBase, BYTE byThreshold) * Return Value: none * */ -void MACvGetTxThreshold (DWORD_PTR dwIoBase, PBYTE pbyThreshold) +void MACvGetTxThreshold (DWORD_PTR dwIoBase, unsigned char *pbyThreshold) { // get FCR0 VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold); @@ -434,7 +434,7 @@ void MACvSetDmaLength (DWORD_PTR dwIoBase, BYTE byDmaLength) * Return Value: none * */ -void MACvGetDmaLength (DWORD_PTR dwIoBase, PBYTE pbyDmaLength) +void MACvGetDmaLength (DWORD_PTR dwIoBase, unsigned char *pbyDmaLength) { // get FCR0 VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyDmaLength); @@ -474,7 +474,7 @@ void MACvSetShortRetryLimit (DWORD_PTR dwIoBase, BYTE byRetryLimit) * Return Value: none * */ -void MACvGetShortRetryLimit (DWORD_PTR dwIoBase, PBYTE pbyRetryLimit) +void MACvGetShortRetryLimit (DWORD_PTR dwIoBase, unsigned char *pbyRetryLimit) { // get SRT VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit); @@ -513,7 +513,7 @@ void MACvSetLongRetryLimit (DWORD_PTR dwIoBase, BYTE byRetryLimit) * Return Value: none * */ -void MACvGetLongRetryLimit (DWORD_PTR dwIoBase, PBYTE pbyRetryLimit) +void MACvGetLongRetryLimit (DWORD_PTR dwIoBase, unsigned char *pbyRetryLimit) { // get LRT VNSvInPortB(dwIoBase + MAC_REG_LRT, pbyRetryLimit); @@ -643,7 +643,7 @@ void MACvSetPacketFilter (DWORD_PTR dwIoBase, WORD wFilterType) * Return Value: none * */ -void MACvSaveContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +void MACvSaveContext (DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf) { int ii; @@ -676,7 +676,7 @@ void MACvSaveContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) * Return Value: none * */ -void MACvRestoreContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +void MACvRestoreContext (DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf) { int ii; @@ -728,7 +728,7 @@ void MACvRestoreContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) * Return Value: TRUE if all values are the same; otherwise FALSE * */ -BOOL MACbCompareContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +BOOL MACbCompareContext (DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf) { DWORD dwData; @@ -1456,7 +1456,7 @@ BOOL MACbPSWakeup (DWORD_PTR dwIoBase) */ void MACvSetKeyEntry (DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID) + unsigned int uKeyIdx, unsigned char *pbyAddr, PDWORD pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 88a440398734..24e9b7ae6e15 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -765,7 +765,7 @@ { \ VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ VNSvInPortB(dwIoBase + MAC_REG_BSSID0, \ - (PBYTE)pbyEtherAddr); \ + (unsigned char *)pbyEtherAddr); \ VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 1, \ pbyEtherAddr + 1); \ VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 2, \ @@ -801,7 +801,7 @@ { \ VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ VNSvInPortB(dwIoBase + MAC_REG_PAR0, \ - (PBYTE)pbyEtherAddr); \ + (unsigned char *)pbyEtherAddr); \ VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 1, \ pbyEtherAddr + 1); \ VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 2, \ @@ -1075,7 +1075,7 @@ /*--------------------- Export Functions --------------------------*/ extern WORD TxRate_iwconfig;//2008-5-8 by chester -void MACvReadAllRegs(DWORD_PTR dwIoBase, PBYTE pbyMacRegs); +void MACvReadAllRegs(DWORD_PTR dwIoBase, unsigned char *pbyMacRegs); BOOL MACbIsRegBitsOn(DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits); BOOL MACbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits); @@ -1088,28 +1088,28 @@ void MACvSetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); void MACvResetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); void MACvSetRxThreshold(DWORD_PTR dwIoBase, BYTE byThreshold); -void MACvGetRxThreshold(DWORD_PTR dwIoBase, PBYTE pbyThreshold); +void MACvGetRxThreshold(DWORD_PTR dwIoBase, unsigned char *pbyThreshold); void MACvSetTxThreshold(DWORD_PTR dwIoBase, BYTE byThreshold); -void MACvGetTxThreshold(DWORD_PTR dwIoBase, PBYTE pbyThreshold); +void MACvGetTxThreshold(DWORD_PTR dwIoBase, unsigned char *pbyThreshold); void MACvSetDmaLength(DWORD_PTR dwIoBase, BYTE byDmaLength); -void MACvGetDmaLength(DWORD_PTR dwIoBase, PBYTE pbyDmaLength); +void MACvGetDmaLength(DWORD_PTR dwIoBase, unsigned char *pbyDmaLength); void MACvSetShortRetryLimit(DWORD_PTR dwIoBase, BYTE byRetryLimit); -void MACvGetShortRetryLimit(DWORD_PTR dwIoBase, PBYTE pbyRetryLimit); +void MACvGetShortRetryLimit(DWORD_PTR dwIoBase, unsigned char *pbyRetryLimit); void MACvSetLongRetryLimit(DWORD_PTR dwIoBase, BYTE byRetryLimit); -void MACvGetLongRetryLimit(DWORD_PTR dwIoBase, PBYTE pbyRetryLimit); +void MACvGetLongRetryLimit(DWORD_PTR dwIoBase, unsigned char *pbyRetryLimit); void MACvSetLoopbackMode(DWORD_PTR dwIoBase, BYTE byLoopbackMode); BOOL MACbIsInLoopbackMode(DWORD_PTR dwIoBase); void MACvSetPacketFilter(DWORD_PTR dwIoBase, WORD wFilterType); -void MACvSaveContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); -void MACvRestoreContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); -BOOL MACbCompareContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); +void MACvSaveContext(DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf); +void MACvRestoreContext(DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf); +BOOL MACbCompareContext(DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf); BOOL MACbSoftwareReset(DWORD_PTR dwIoBase); BOOL MACbSafeSoftwareReset(DWORD_PTR dwIoBase); @@ -1140,7 +1140,7 @@ BOOL MACbFlushSYNCFifo(DWORD_PTR dwIoBase); BOOL MACbPSWakeup(DWORD_PTR dwIoBase); void MACvSetKeyEntry(DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID); + unsigned int uKeyIdx, unsigned char *pbyAddr, PDWORD pdwKey, BYTE byLocalID); void MACvDisableKeyEntry(DWORD_PTR dwIoBase, unsigned int uEntryIdx); void MACvSetDefaultKeyEntry(DWORD_PTR dwIoBase, unsigned int uKeyLen, unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID); diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c index d34ebd31efcb..867d8d261927 100644 --- a/drivers/staging/vt6655/mib.c +++ b/drivers/staging/vt6655/mib.c @@ -178,7 +178,7 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, DWORD dwIsr) */ void STAvUpdateRDStatCounter (PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, - PBYTE pbyBuffer, unsigned int cbFrameLength) + unsigned char *pbyBuffer, unsigned int cbFrameLength) { //need change PS802_11Header pHeader = (PS802_11Header)pbyBuffer; @@ -392,7 +392,7 @@ STAvUpdateRDStatCounterEx ( BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int cbFrameLength ) { @@ -408,7 +408,7 @@ STAvUpdateRDStatCounterEx ( // rx length pStatistic->dwCntRxFrmLength = cbFrameLength; // rx pattern, we just see 10 bytes for sample - memcpy(pStatistic->abyCntRxPattern, (PBYTE)pbyBuffer, 10); + memcpy(pStatistic->abyCntRxPattern, (unsigned char *)pbyBuffer, 10); } @@ -434,13 +434,13 @@ STAvUpdateTDStatCounter ( PSStatCounter pStatistic, BYTE byTSR0, BYTE byTSR1, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx ) { PWLAN_80211HDR_A4 pHeader; - PBYTE pbyDestAddr; + unsigned char *pbyDestAddr; BYTE byTSR0_NCR = byTSR0 & TSR0_NCR; @@ -522,7 +522,7 @@ STAvUpdateTDStatCounter ( void STAvUpdateTDStatCounterEx ( PSStatCounter pStatistic, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, DWORD cbFrameLength ) { diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h index 1540b27faf70..35bb7c48eff7 100644 --- a/drivers/staging/vt6655/mib.h +++ b/drivers/staging/vt6655/mib.h @@ -348,18 +348,18 @@ void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, DWORD dwIsr); void STAvUpdateRDStatCounter(PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, - PBYTE pbyBuffer, unsigned int cbFrameLength); + unsigned char *pbyBuffer, unsigned int cbFrameLength); void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRsr, BYTE byRxRate, - PBYTE pbyBuffer, unsigned int cbFrameLength); + unsigned char *pbyBuffer, unsigned int cbFrameLength); void STAvUpdateTDStatCounter(PSStatCounter pStatistic, BYTE byTSR0, BYTE byTSR1, - PBYTE pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx); + unsigned char *pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx); void STAvUpdateTDStatCounterEx( PSStatCounter pStatistic, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, DWORD cbFrameLength ); diff --git a/drivers/staging/vt6655/michael.c b/drivers/staging/vt6655/michael.c index 3a92257bd3e8..2a346307f4db 100644 --- a/drivers/staging/vt6655/michael.c +++ b/drivers/staging/vt6655/michael.c @@ -149,7 +149,7 @@ void MIC_vUnInit (void) s_vClear(); } -void MIC_vAppend (PBYTE src, unsigned int nBytes) +void MIC_vAppend (unsigned char *src, unsigned int nBytes) { // This is simple while (nBytes > 0) diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h index c1584a0ce7a1..ecb2912939c6 100644 --- a/drivers/staging/vt6655/michael.h +++ b/drivers/staging/vt6655/michael.h @@ -40,7 +40,7 @@ void MIC_vInit(DWORD dwK0, DWORD dwK1); void MIC_vUnInit(void); // Append bytes to the message to be MICed -void MIC_vAppend(PBYTE src, unsigned int nBytes); +void MIC_vAppend(unsigned char *src, unsigned int nBytes); // Get the MIC result. Destination should accept 8 bytes of result. // This also resets the message to empty. diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index d4e076513f63..a2491d3d0a8a 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -262,7 +262,7 @@ PSvSendPSPOLL( memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN); pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool; - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16( ( WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) | @@ -329,7 +329,7 @@ PSbSendNullPacket( memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN); pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool; - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); if (pDevice->bEnablePSMode) { diff --git a/drivers/staging/vt6655/rc4.c b/drivers/staging/vt6655/rc4.c index 0d641ffefc99..783fdff6d63a 100644 --- a/drivers/staging/vt6655/rc4.c +++ b/drivers/staging/vt6655/rc4.c @@ -32,12 +32,12 @@ #include "rc4.h" -void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len) +void rc4_init(PRC4Ext pRC4, unsigned char *pbyKey, unsigned int cbKey_len) { unsigned int ust1, ust2; unsigned int keyindex; unsigned int stateindex; - PBYTE pbyst; + unsigned char *pbyst; unsigned int idx; pbyst = pRC4->abystate; @@ -63,7 +63,7 @@ unsigned int rc4_byte(PRC4Ext pRC4) unsigned int ux; unsigned int uy; unsigned int ustx, usty; - PBYTE pbyst; + unsigned char *pbyst; pbyst = pRC4->abystate; ux = (pRC4->ux + 1) & 0xff; @@ -78,8 +78,8 @@ unsigned int rc4_byte(PRC4Ext pRC4) return pbyst[(ustx + usty) & 0xff]; } -void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, - PBYTE pbySrc, unsigned int cbData_len) +void rc4_encrypt(PRC4Ext pRC4, unsigned char *pbyDest, + unsigned char *pbySrc, unsigned int cbData_len) { unsigned int ii; for (ii = 0; ii < cbData_len; ii++) diff --git a/drivers/staging/vt6655/rc4.h b/drivers/staging/vt6655/rc4.h index a40030461c12..c94eea27ac85 100644 --- a/drivers/staging/vt6655/rc4.h +++ b/drivers/staging/vt6655/rc4.h @@ -40,8 +40,8 @@ typedef struct { BYTE abystate[256]; } RC4Ext, *PRC4Ext; -void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len); +void rc4_init(PRC4Ext pRC4, unsigned char *pbyKey, unsigned int cbKey_len); unsigned int rc4_byte(PRC4Ext pRC4); -void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, PBYTE pbySrc, unsigned int cbData_len); +void rc4_encrypt(PRC4Ext pRC4, unsigned char *pbyDest, unsigned char *pbySrc, unsigned int cbData_len); #endif //__RC4_H__ diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 271a4ab94886..32725dadf855 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -118,12 +118,12 @@ static void s_vFillTxKey( PSDevice pDevice, - PBYTE pbyBuf, - PBYTE pbyIVHead, + unsigned char *pbyBuf, + unsigned char *pbyIVHead, PSKeyItem pTransmitKey, - PBYTE pbyHdrBuf, + unsigned char *pbyHdrBuf, WORD wPayloadLen, - PBYTE pMICHDR + unsigned char *pMICHDR ); @@ -162,7 +162,7 @@ s_vGenerateTxParameter( static void s_vFillFragParameter( PSDevice pDevice, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int uTxType, void * pvtdCurr, WORD wFragType, @@ -175,12 +175,12 @@ unsigned int s_cbFillTxBufHead ( PSDevice pDevice, BYTE byPktType, - PBYTE pbyTxBufferAddr, + unsigned char *pbyTxBufferAddr, unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, - PBYTE pPacket, + unsigned char *pPacket, BOOL bNeedEncrypt, PSKeyItem pTransmitKey, unsigned int uNodeIndex, @@ -213,16 +213,16 @@ static void s_vFillTxKey ( PSDevice pDevice, - PBYTE pbyBuf, - PBYTE pbyIVHead, + unsigned char *pbyBuf, + unsigned char *pbyIVHead, PSKeyItem pTransmitKey, - PBYTE pbyHdrBuf, + unsigned char *pbyHdrBuf, WORD wPayloadLen, - PBYTE pMICHDR + unsigned char *pMICHDR ) { PDWORD pdwIV = (PDWORD) pbyIVHead; - PDWORD pdwExtIV = (PDWORD) ((PBYTE)pbyIVHead+4); + PDWORD pdwExtIV = (PDWORD) ((unsigned char *)pbyIVHead+4); WORD wValue; PS802_11Header pMACHeader = (PS802_11Header)pbyHdrBuf; DWORD dwRevIVCounter; @@ -240,13 +240,13 @@ s_vFillTxKey ( if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){ - memcpy(pDevice->abyPRNG, (PBYTE)&(dwRevIVCounter), 3); + memcpy(pDevice->abyPRNG, (unsigned char *)&(dwRevIVCounter), 3); memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); } else { - memcpy(pbyBuf, (PBYTE)&(dwRevIVCounter), 3); + memcpy(pbyBuf, (unsigned char *)&(dwRevIVCounter), 3); memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) { - memcpy(pbyBuf+8, (PBYTE)&(dwRevIVCounter), 3); + memcpy(pbyBuf+8, (unsigned char *)&(dwRevIVCounter), 3); memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength); } memcpy(pDevice->abyPRNG, pbyBuf, 16); @@ -291,26 +291,26 @@ s_vFillTxKey ( //Fill MICHDR0 *pMICHDR = 0x59; - *((PBYTE)(pMICHDR+1)) = 0; // TxPriority + *((unsigned char *)(pMICHDR+1)) = 0; // TxPriority memcpy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6); - *((PBYTE)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16)); - *((PBYTE)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16)); - *((PBYTE)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16)); - *((PBYTE)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16)); - *((PBYTE)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0); - *((PBYTE)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0); - *((PBYTE)(pMICHDR+14)) = HIBYTE(wPayloadLen); - *((PBYTE)(pMICHDR+15)) = LOBYTE(wPayloadLen); + *((unsigned char *)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((unsigned char *)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((unsigned char *)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((unsigned char *)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((unsigned char *)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0); + *((unsigned char *)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0); + *((unsigned char *)(pMICHDR+14)) = HIBYTE(wPayloadLen); + *((unsigned char *)(pMICHDR+15)) = LOBYTE(wPayloadLen); //Fill MICHDR1 - *((PBYTE)(pMICHDR+16)) = 0; // HLEN[15:8] + *((unsigned char *)(pMICHDR+16)) = 0; // HLEN[15:8] if (pDevice->bLongHeader) { - *((PBYTE)(pMICHDR+17)) = 28; // HLEN[7:0] + *((unsigned char *)(pMICHDR+17)) = 28; // HLEN[7:0] } else { - *((PBYTE)(pMICHDR+17)) = 22; // HLEN[7:0] + *((unsigned char *)(pMICHDR+17)) = 22; // HLEN[7:0] } wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F); - memcpy(pMICHDR+18, (PBYTE)&wValue, 2); // MSKFRACTL + memcpy(pMICHDR+18, (unsigned char *)&wValue, 2); // MSKFRACTL memcpy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6); memcpy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6); @@ -319,7 +319,7 @@ s_vFillTxKey ( wValue = pMACHeader->wSeqCtl; wValue &= 0x000F; wValue = cpu_to_le16(wValue); - memcpy(pMICHDR+38, (PBYTE)&wValue, 2); // MSKSEQCTL + memcpy(pMICHDR+38, (unsigned char *)&wValue, 2); // MSKSEQCTL if (pDevice->bLongHeader) { memcpy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6); } @@ -332,7 +332,7 @@ void s_vSWencryption ( PSDevice pDevice, PSKeyItem pTransmitKey, - PBYTE pbyPayloadHead, + unsigned char *pbyPayloadHead, WORD wPayloadSize ) { @@ -745,11 +745,11 @@ s_uFillDataHead ( PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get Duration and TimeStamp @@ -771,11 +771,11 @@ s_uFillDataHead ( PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get Duration and TimeStamp @@ -800,7 +800,7 @@ s_uFillDataHead ( PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -817,7 +817,7 @@ s_uFillDataHead ( PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -835,7 +835,7 @@ s_uFillDataHead ( PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -883,11 +883,11 @@ s_vFillRTSHead ( PSRTS_g pBuf = (PSRTS_g)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); //Get Duration @@ -916,11 +916,11 @@ s_vFillRTSHead ( PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -958,7 +958,7 @@ s_vFillRTSHead ( PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -987,7 +987,7 @@ s_vFillRTSHead ( PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -1017,7 +1017,7 @@ s_vFillRTSHead ( PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -1077,7 +1077,7 @@ s_vFillCTSHead ( PSCTS_FB pBuf = (PSCTS_FB)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); @@ -1104,7 +1104,7 @@ s_vFillCTSHead ( PSCTS pBuf = (PSCTS)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get CTSDuration_ba @@ -1263,7 +1263,7 @@ s_vGenerateTxParameter ( //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n"); } /* - PBYTE pbyBuffer,//point to pTxBufHead + unsigned char *pbyBuffer,//point to pTxBufHead WORD wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last unsigned int cbFragmentSize,//Hdr+payoad+FCS */ @@ -1271,7 +1271,7 @@ static void s_vFillFragParameter( PSDevice pDevice, - PBYTE pbyBuffer, + unsigned char *pbyBuffer, unsigned int uTxType, void * pvtdCurr, WORD wFragType, @@ -1320,12 +1320,12 @@ unsigned int s_cbFillTxBufHead ( PSDevice pDevice, BYTE byPktType, - PBYTE pbyTxBufferAddr, + unsigned char *pbyTxBufferAddr, unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, - PBYTE pPacket, + unsigned char *pPacket, BOOL bNeedEncrypt, PSKeyItem pTransmitKey, unsigned int uNodeIndex, @@ -1339,12 +1339,12 @@ s_cbFillTxBufHead ( unsigned int cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS unsigned int cbLastFragPayloadSize; unsigned int uFragIdx; - PBYTE pbyPayloadHead; - PBYTE pbyIVHead; - PBYTE pbyMacHdr; + unsigned char *pbyPayloadHead; + unsigned char *pbyIVHead; + unsigned char *pbyMacHdr; WORD wFragType; //00:Non-Frag, 01:Start, 10:Mid, 11:Last unsigned int uDuration; - PBYTE pbyBuffer; + unsigned char *pbyBuffer; // unsigned int uKeyEntryIdx = NUM_KEY_ENTRY+1; // BYTE byKeySel = 0xFF; unsigned int cbIVlen = 0; @@ -1371,7 +1371,7 @@ s_cbFillTxBufHead ( BOOL bNeedACK; BOOL bRTS; BOOL bIsAdhoc; - PBYTE pbyType; + unsigned char *pbyType; PSTxDesc ptdCurr; PSTxBufHead psTxBufHd = (PSTxBufHead) pbyTxBufferAddr; // unsigned int tmpDescIdx; @@ -1562,17 +1562,17 @@ s_cbFillTxBufHead ( } // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); - MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); + MIC_vAppend((unsigned char *)&(psEthHeader->abyDstAddr[0]), 12); dwMIC_Priority = 0; - MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + MIC_vAppend((unsigned char *)&dwMIC_Priority, 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); } /////////////////////////////////////////////////////////////////// - pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderLength); - pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen); - pbyIVHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding); + pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderLength); + pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen); + pbyIVHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding); if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == TRUE) && (bIsWEP256 == FALSE)) { // Fragmentation @@ -1611,8 +1611,8 @@ s_cbFillTxBufHead ( if (bNeedEncrypt == TRUE) { //Fill TXKEY - s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, - pbyMacHdr, (WORD)cbFragPayloadSize, (PBYTE)pMICHDR); + s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFragPayloadSize, (unsigned char *)pMICHDR); //Fill IV(ExtIV,RSNHDR) if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; @@ -1625,12 +1625,12 @@ s_cbFillTxBufHead ( if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if ((psEthHeader->wType == TYPE_PKT_IPX) || (psEthHeader->wType == cpu_to_le16(0xF380))) { - memcpy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); + memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); } else { - memcpy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); + memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); } - pbyType = (PBYTE) (pbyPayloadHead + 6); + pbyType = (unsigned char *) (pbyPayloadHead + 6); memcpy(pbyType, &(psEthHeader->wType), sizeof(WORD)); cb802_1_H_len = 8; } @@ -1641,15 +1641,15 @@ s_cbFillTxBufHead ( //--------------------------- //Fill MICHDR //if (pDevice->bAES) { - // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); + // s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); //} //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (void *)psTxBufHd, byKeySel, // pbyPayloadHead, (WORD)cbFragPayloadSize, uDMAIdx); - //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; - pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; + //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; + pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf; uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len; //copy TxBufferHeader + MacHeader to desc @@ -1716,8 +1716,8 @@ s_cbFillTxBufHead ( if (bNeedEncrypt == TRUE) { //Fill TXKEY - s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, - pbyMacHdr, (WORD)cbLastFragPayloadSize, (PBYTE)pMICHDR); + s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbLastFragPayloadSize, (unsigned char *)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; @@ -1734,8 +1734,8 @@ s_cbFillTxBufHead ( - pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; - //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; + pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf; + //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen; @@ -1766,23 +1766,23 @@ s_cbFillTxBufHead ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); } else { if (uMICFragLen >= 4) { - memcpy((pbyBuffer + uLength), ((PBYTE)&dwSafeMIC_R + (uMICFragLen - 4)), + memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)), (cbMIClen - uMICFragLen)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen >= 4: %X, %d\n", - *(PBYTE)((PBYTE)&dwSafeMIC_R + (uMICFragLen - 4)), + *(unsigned char *)((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)), (cbMIClen - uMICFragLen)); } else { - memcpy((pbyBuffer + uLength), ((PBYTE)&dwSafeMIC_L + uMICFragLen), + memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_L + uMICFragLen), (4 - uMICFragLen)); memcpy((pbyBuffer + uLength + (4 - uMICFragLen)), &dwSafeMIC_R, 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen < 4: %X, %d\n", - *(PBYTE)((PBYTE)&dwSafeMIC_R + uMICFragLen - 4), + *(unsigned char *)((unsigned char *)&dwSafeMIC_R + uMICFragLen - 4), (cbMIClen - uMICFragLen)); } /* for (ii = 0; ii < cbLastFragPayloadSize + 8 + 24; ii++) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii - 8 - 24))); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii - 8 - 24))); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n"); */ @@ -1847,8 +1847,8 @@ s_cbFillTxBufHead ( if (bNeedEncrypt == TRUE) { //Fill TXKEY - s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, - pbyMacHdr, (WORD)cbFragPayloadSize, (PBYTE)pMICHDR); + s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFragPayloadSize, (unsigned char *)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; @@ -1862,14 +1862,14 @@ s_cbFillTxBufHead ( //--------------------------- //Fill MICHDR //if (pDevice->bAES) { - // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); + // s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); //} //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (void *)psTxBufHd, byKeySel, // pbyPayloadHead, (WORD)cbFragPayloadSize, uDMAIdx); - pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; - //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; + pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf; + //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen; @@ -1906,7 +1906,7 @@ s_cbFillTxBufHead ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MIC in Middle frag [%d]\n", uMICFragLen); /* for (ii = 0; ii < uMICFragLen; ii++) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength + uTmpLen) + ii))); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength + uTmpLen) + ii))); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); */ @@ -1915,7 +1915,7 @@ s_cbFillTxBufHead ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Middle frag len: %d\n", uTmpLen); /* for (ii = 0; ii < uTmpLen; ii++) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii))); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii))); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n"); */ @@ -1976,8 +1976,8 @@ s_cbFillTxBufHead ( if (bNeedEncrypt == TRUE) { //Fill TXKEY - s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, - pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); + s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFrameBodySize, (unsigned char *)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; @@ -1989,12 +1989,12 @@ s_cbFillTxBufHead ( if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if ((psEthHeader->wType == TYPE_PKT_IPX) || (psEthHeader->wType == cpu_to_le16(0xF380))) { - memcpy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); + memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); } else { - memcpy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); + memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); } - pbyType = (PBYTE) (pbyPayloadHead + 6); + pbyType = (unsigned char *) (pbyPayloadHead + 6); memcpy(pbyType, &(psEthHeader->wType), sizeof(WORD)); cb802_1_H_len = 8; } @@ -2006,11 +2006,11 @@ s_cbFillTxBufHead ( //Fill MICHDR //if (pDevice->bAES) { // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MICHDR...\n"); - // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFrameBodySize); + // s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (WORD)cbFrameBodySize); //} - pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; - //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; + pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf; + //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len; @@ -2028,7 +2028,7 @@ s_cbFillTxBufHead ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Length:%d, %d\n", cbFrameBodySize - cb802_1_H_len, uLength); /* for (ii = 0; ii < (cbFrameBodySize - cb802_1_H_len); ii++) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii))); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii))); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); */ @@ -2053,7 +2053,7 @@ s_cbFillTxBufHead ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); /* for (ii = 0; ii < 8; ii++) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(((PBYTE)(pdwMIC_L) + ii))); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(((unsigned char *)(pdwMIC_L) + ii))); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); */ @@ -2097,13 +2097,13 @@ void vGenerateFIFOHeader ( PSDevice pDevice, BYTE byPktType, - PBYTE pbyTxBufferAddr, + unsigned char *pbyTxBufferAddr, BOOL bNeedEncrypt, unsigned int cbPayloadSize, unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, - PBYTE pPacket, + unsigned char *pPacket, PSKeyItem pTransmitKey, unsigned int uNodeIndex, PUINT puMACfragNum, @@ -2267,7 +2267,7 @@ vGenerateFIFOHeader ( void vGenerateMACHeader ( PSDevice pDevice, - PBYTE pbyBufferAddr, + unsigned char *pbyBufferAddr, WORD wDuration, PSEthernetHeader psEthHeader, BOOL bNeedEncrypt, @@ -2341,7 +2341,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { PSTxDesc pFrstTD; BYTE byPktType; - PBYTE pbyTxBufferAddr; + unsigned char *pbyTxBufferAddr; void * pvRTS; PSCTS pCTS; void * pvTxDataHd; @@ -2373,7 +2373,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { } pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0]; - pbyTxBufferAddr = (PBYTE)pFrstTD->pTDInfo->buf; + pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf; cbFrameBodySize = pPacket->cbPayloadLen; pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; wTxBufSize = sizeof(STxBufHead); @@ -2539,17 +2539,17 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize; if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { - PBYTE pbyIVHead; - PBYTE pbyPayloadHead; - PBYTE pbyBSSID; + unsigned char *pbyIVHead; + unsigned char *pbyPayloadHead; + unsigned char *pbyBSSID; PSKeyItem pTransmitKey = NULL; - pbyIVHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding); - pbyPayloadHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen); + pbyIVHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding); + pbyPayloadHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen); //Fill TXKEY //Kyle: Need fix: TKIP and AES did't encryt Mnt Packet. - //s_vFillTxKey(pDevice, (PBYTE)pTxBufHead->adwTxKey, NULL); + //s_vFillTxKey(pDevice, (unsigned char *)pTxBufHead->adwTxKey, NULL); //Fill IV(ExtIV,RSNHDR) //s_vFillPrePayload(pDevice, pbyIVHead, NULL); @@ -2558,7 +2558,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { //--------------------------- //Fill MICHDR //if (pDevice->bAES) { - // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, (PBYTE)pMACHeader, (WORD)cbFrameBodySize); + // s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, (unsigned char *)pMACHeader, (WORD)cbFrameBodySize); //} do { if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && @@ -2586,11 +2586,11 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { } } while(FALSE); //Fill TXKEY - s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, - (PBYTE)pMACHeader, (WORD)cbFrameBodySize, NULL); + s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + (unsigned char *)pMACHeader, (WORD)cbFrameBodySize, NULL); memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen); - memcpy(pbyPayloadHead, ((PBYTE)(pPacket->p80211Header) + cbMacHdLen), + memcpy(pbyPayloadHead, ((unsigned char *)(pPacket->p80211Header) + cbMacHdLen), cbFrameBodySize); } else { @@ -2662,7 +2662,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { BYTE byPktType; - PBYTE pbyBuffer = (PBYTE)pDevice->tx_beacon_bufs; + unsigned char *pbyBuffer = (unsigned char *)pDevice->tx_beacon_bufs; unsigned int cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; unsigned int cbHeaderSize = 0; WORD wTxBufSize = sizeof(STxShortBufHead); @@ -2703,7 +2703,7 @@ CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { } BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType, - (PWORD)&(wLen), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) + (PWORD)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField) ); pTxDataHead->wTransmitLength = cpu_to_le16(wLen); //Get TimeStampOff @@ -2826,11 +2826,11 @@ cbGetFragCount ( void -vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned int cbMPDULen) { +vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, unsigned int cbMPDULen) { PSTxDesc pFrstTD; BYTE byPktType; - PBYTE pbyTxBufferAddr; + unsigned char *pbyTxBufferAddr; void * pvRTS; void * pvCTS; void * pvTxDataHd; @@ -2866,9 +2866,9 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in BOOL bNodeExist = FALSE; SKeyItem STempKey; PSKeyItem pTransmitKey = NULL; - PBYTE pbyIVHead; - PBYTE pbyPayloadHead; - PBYTE pbyMacHdr; + unsigned char *pbyIVHead; + unsigned char *pbyPayloadHead; + unsigned char *pbyMacHdr; unsigned int cbExtSuppRate = 0; // PWLAN_IE pItem; @@ -2886,7 +2886,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0]; - pbyTxBufferAddr = (PBYTE)pFrstTD->pTDInfo->buf; + pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf; pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; wTxBufSize = sizeof(STxBufHead); memset(pTxBufHead, 0, wTxBufSize); @@ -2948,7 +2948,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in } else { if (pDevice->bEnableHostWEP) { - if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (PBYTE)(p80211Header->sA3.abyAddr1), &uNodeIndex)) + if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (unsigned char *)(p80211Header->sA3.abyAddr1), &uNodeIndex)) bNodeExist = TRUE; }; bNeedACK = TRUE; @@ -3082,9 +3082,9 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate; - pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderSize); - pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen); - pbyIVHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding); + pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize); + pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen); + pbyIVHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding); // Copy the Packet into a tx Buffer memcpy(pbyMacHdr, pbMPDU, cbMacHdLen); @@ -3132,9 +3132,9 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); - MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); + MIC_vAppend((unsigned char *)&(sEthHeader.abyDstAddr[0]), 12); dwMIC_Priority = 0; - MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + MIC_vAppend((unsigned char *)&dwMIC_Priority, 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; @@ -3160,8 +3160,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned in } - s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, - pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); + s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFrameBodySize, (unsigned char *)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index e2754071317e..1e5e31f77ca0 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -43,7 +43,7 @@ void vGenerateMACHeader( PSDevice pDevice, DWORD dwTxBufferAddr, - PBYTE pbySkbData, + unsigned char *pbySkbData, unsigned int cbPacketSize, BOOL bDMA0Used, PUINT pcbHeadSize, @@ -63,7 +63,7 @@ void vProcessRxMACHeader ( void vGenerateMACHeader ( PSDevice pDevice, - PBYTE pbyBufferAddr, + unsigned char *pbyBufferAddr, WORD wDuration, PSEthernetHeader psEthHeader, BOOL bNeedEncrypt, @@ -86,13 +86,13 @@ void vGenerateFIFOHeader ( PSDevice pDevice, BYTE byPktTyp, - PBYTE pbyTxBufferAddr, + unsigned char *pbyTxBufferAddr, BOOL bNeedEncrypt, unsigned int cbPayloadSize, unsigned int uDMAIdx, PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, - PBYTE pPacket, + unsigned char *pPacket, PSKeyItem pTransmitKey, unsigned int uNodeIndex, PUINT puMACfragNum, @@ -100,7 +100,7 @@ vGenerateFIFOHeader ( ); -void vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, unsigned int cbMPDULen); +void vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, unsigned int cbMPDULen); CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index 418575fdc2c0..cd4895ea45f6 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -266,7 +266,7 @@ BOOL SROMbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits) * Return Value: none * */ -void SROMvReadAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) +void SROMvReadAllContents(DWORD_PTR dwIoBase, unsigned char *pbyEepromRegs) { int ii; @@ -291,7 +291,7 @@ void SROMvReadAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) * Return Value: none * */ -void SROMvWriteAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) +void SROMvWriteAllContents(DWORD_PTR dwIoBase, unsigned char *pbyEepromRegs) { int ii; @@ -315,7 +315,7 @@ void SROMvWriteAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) * Return Value: none * */ -void SROMvReadEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) +void SROMvReadEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress) { BYTE ii; @@ -340,7 +340,7 @@ void SROMvReadEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) * Return Value: none * */ -void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) +void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress) { BYTE ii; @@ -366,9 +366,9 @@ void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) */ void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId) { - PBYTE pbyData; + unsigned char *pbyData; - pbyData = (PBYTE)pdwSubSysVenId; + pbyData = (unsigned char *)pdwSubSysVenId; /* sub vendor */ *pbyData = SROMbyReadEmbedded(dwIoBase, 6); *(pbyData+1) = SROMbyReadEmbedded(dwIoBase, 7); diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index dbb3f5efe979..d51791491751 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -144,11 +144,11 @@ void SROMvRegBitsOff(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byBits); BOOL SROMbIsRegBitsOn(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits); BOOL SROMbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits); -void SROMvReadAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs); -void SROMvWriteAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs); +void SROMvReadAllContents(DWORD_PTR dwIoBase, unsigned char *pbyEepromRegs); +void SROMvWriteAllContents(DWORD_PTR dwIoBase, unsigned char *pbyEepromRegs); -void SROMvReadEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress); -void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress); +void SROMvReadEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress); +void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress); void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId); diff --git a/drivers/staging/vt6655/tcrc.c b/drivers/staging/vt6655/tcrc.c index d13e8e1ccd96..d48777a8e4b6 100644 --- a/drivers/staging/vt6655/tcrc.c +++ b/drivers/staging/vt6655/tcrc.c @@ -132,7 +132,7 @@ static const DWORD s_adwCrc32Table[256] = { * Return Value: CRC-32 * -*/ -DWORD CRCdwCrc32 (PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed) +DWORD CRCdwCrc32 (unsigned char *pbyData, unsigned int cbByte, DWORD dwCrcSeed) { DWORD dwCrc; @@ -164,7 +164,7 @@ DWORD CRCdwCrc32 (PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed) * Return Value: CRC-32 * -*/ -DWORD CRCdwGetCrc32 (PBYTE pbyData, unsigned int cbByte) +DWORD CRCdwGetCrc32 (unsigned char *pbyData, unsigned int cbByte) { return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL); } @@ -190,7 +190,7 @@ DWORD CRCdwGetCrc32 (PBYTE pbyData, unsigned int cbByte) * Return Value: CRC-32 * -*/ -DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC) +DWORD CRCdwGetCrc32Ex(unsigned char *pbyData, unsigned int cbByte, DWORD dwPreCRC) { return CRCdwCrc32(pbyData, cbByte, dwPreCRC); } diff --git a/drivers/staging/vt6655/tcrc.h b/drivers/staging/vt6655/tcrc.h index 17581b2d6a0c..7d5cd89ed432 100644 --- a/drivers/staging/vt6655/tcrc.h +++ b/drivers/staging/vt6655/tcrc.h @@ -43,9 +43,9 @@ /*--------------------- Export Functions --------------------------*/ -DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed); -DWORD CRCdwGetCrc32(PBYTE pbyData, unsigned int cbByte); -DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC); +DWORD CRCdwCrc32(unsigned char *pbyData, unsigned int cbByte, DWORD dwCrcSeed); +DWORD CRCdwGetCrc32(unsigned char *pbyData, unsigned int cbByte); +DWORD CRCdwGetCrc32Ex(unsigned char *pbyData, unsigned int cbByte, DWORD dwPreCRC); #endif // __TCRC_H__ diff --git a/drivers/staging/vt6655/tether.c b/drivers/staging/vt6655/tether.c index 150647db1529..baf373931b6c 100644 --- a/drivers/staging/vt6655/tether.c +++ b/drivers/staging/vt6655/tether.c @@ -61,7 +61,7 @@ * Return Value: Hash value * */ -BYTE ETHbyGetHashIndexByCrc32 (PBYTE pbyMultiAddr) +BYTE ETHbyGetHashIndexByCrc32 (unsigned char *pbyMultiAddr) { int ii; BYTE byTmpHash; @@ -96,7 +96,7 @@ BYTE ETHbyGetHashIndexByCrc32 (PBYTE pbyMultiAddr) * Return Value: TRUE if ok; FALSE if error. * */ -BOOL ETHbIsBufferCrc32Ok (PBYTE pbyBuffer, unsigned int cbFrameLength) +BOOL ETHbIsBufferCrc32Ok (unsigned char *pbyBuffer, unsigned int cbFrameLength) { DWORD dwCRC; diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h index 4a9d20287d7c..5d90cd8da8af 100644 --- a/drivers/staging/vt6655/tether.h +++ b/drivers/staging/vt6655/tether.h @@ -193,9 +193,9 @@ S802_11Header, *PS802_11Header; /*--------------------- Export Functions --------------------------*/ -BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr); -//BYTE ETHbyGetHashIndexByCrc(PBYTE pbyMultiAddr); -BOOL ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, unsigned int cbFrameLength); +BYTE ETHbyGetHashIndexByCrc32(unsigned char *pbyMultiAddr); +//BYTE ETHbyGetHashIndexByCrc(unsigned char *pbyMultiAddr); +BOOL ETHbIsBufferCrc32Ok(unsigned char *pbyBuffer, unsigned int cbFrameLength); #endif // __TETHER_H__ diff --git a/drivers/staging/vt6655/tkip.c b/drivers/staging/vt6655/tkip.c index f83af5913aa6..569c911193c2 100644 --- a/drivers/staging/vt6655/tkip.c +++ b/drivers/staging/vt6655/tkip.c @@ -184,11 +184,11 @@ unsigned int rotr1(unsigned int a) * */ void TKIPvMixKey( - PBYTE pbyTKey, - PBYTE pbyTA, + unsigned char *pbyTKey, + unsigned char *pbyTA, WORD wTSC15_0, DWORD dwTSC47_16, - PBYTE pbyRC4Key + unsigned char *pbyRC4Key ) { unsigned int p1k[5]; diff --git a/drivers/staging/vt6655/tkip.h b/drivers/staging/vt6655/tkip.h index 3dfa7f5ee7ec..cdadf66746f7 100644 --- a/drivers/staging/vt6655/tkip.h +++ b/drivers/staging/vt6655/tkip.h @@ -47,11 +47,11 @@ /*--------------------- Export Functions --------------------------*/ void TKIPvMixKey( - PBYTE pbyTKey, - PBYTE pbyTA, + unsigned char *pbyTKey, + unsigned char *pbyTA, WORD wTSC15_0, DWORD dwTSC47_16, - PBYTE pbyRC4Key + unsigned char *pbyRC4Key ); #endif // __TKIP_H__ diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index f97a3eeed9a1..6fe184fb77d6 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -92,8 +92,6 @@ typedef unsigned long DWORD_PTR; // 32-bit // boolean pointer typedef unsigned int * PUINT; -typedef BYTE * PBYTE; - typedef WORD * PWORD; typedef DWORD * PDWORD; diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index 78a950cbf00d..c12d028d5ec1 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -76,7 +76,7 @@ #define VNSvInPortB(dwIOAddress, pbyData) { \ - volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress)); \ + volatile BYTE* pbyAddr = ((unsigned char *)(dwIOAddress)); \ *(pbyData) = readb(pbyAddr); \ } @@ -93,7 +93,7 @@ #define VNSvOutPortB(dwIOAddress, byData) { \ - volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress)); \ + volatile BYTE* pbyAddr = ((unsigned char *)(dwIOAddress)); \ writeb((BYTE)byData, pbyAddr); \ } diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index 22069057ac0a..88c0ad420a41 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -497,10 +497,10 @@ VNTWIFIvGetNextBSS ( void VNTWIFIvUpdateNodeTxCounter( void *pMgmtHandle, - PBYTE pbyDestAddress, + unsigned char *pbyDestAddress, BOOL bTxOk, WORD wRate, - PBYTE pbyTxFailCount + unsigned char *pbyTxFailCount ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; @@ -532,11 +532,11 @@ VNTWIFIvUpdateNodeTxCounter( void VNTWIFIvGetTxRate( void *pMgmtHandle, - PBYTE pbyDestAddress, + unsigned char *pbyDestAddress, PWORD pwTxDataRate, - PBYTE pbyACKRate, - PBYTE pbyCCKBasicRate, - PBYTE pbyOFDMBasicRate + unsigned char *pbyACKRate, + unsigned char *pbyCCKBasicRate, + unsigned char *pbyOFDMBasicRate ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; @@ -721,11 +721,11 @@ VNTWIFIbMeasureReport( BYTE byReportMode, BYTE byBasicMap, BYTE byCCAFraction, - PBYTE pbyRPIs + unsigned char *pbyRPIs ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; - PBYTE pbyCurrentEID = (PBYTE) (pMgmt->pCurrMeasureEIDRep); + unsigned char *pbyCurrentEID = (unsigned char *) (pMgmt->pCurrMeasureEIDRep); //spin_lock_irq(&pDevice->lock); if ((pvMeasureEID != NULL) && diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h index fc1a4f152491..6d14161e6de4 100644 --- a/drivers/staging/vt6655/vntwifi.h +++ b/drivers/staging/vt6655/vntwifi.h @@ -229,21 +229,21 @@ VNTWIFIvGetNextBSS ( void VNTWIFIvUpdateNodeTxCounter( void *pMgmtHandle, - PBYTE pbyDestAddress, + unsigned char *pbyDestAddress, BOOL bTxOk, WORD wRate, - PBYTE pbyTxFailCount + unsigned char *pbyTxFailCount ); void VNTWIFIvGetTxRate( void *pMgmtHandle, - PBYTE pbyDestAddress, + unsigned char *pbyDestAddress, PWORD pwTxDataRate, - PBYTE pbyACKRate, - PBYTE pbyCCKBasicRate, - PBYTE pbyOFDMBasicRate + unsigned char *pbyACKRate, + unsigned char *pbyCCKBasicRate, + unsigned char *pbyOFDMBasicRate ); /* BOOL @@ -294,7 +294,7 @@ VNTWIFIbMeasureReport( BYTE byReportMode, BYTE byBasicMap, BYTE byCCAFraction, - PBYTE pbyRPIs + unsigned char *pbyRPIs ); BOOL diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index 9aae07709e34..4e7b457cb9a9 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -77,7 +77,7 @@ PSTxMgmtPacket s_MgrMakeProbeRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pScanBSSID, + unsigned char *pScanBSSID, PWLAN_IE_SSID pSSID, PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates @@ -213,7 +213,7 @@ s_vProbeChannel( //6M, 9M, 12M, 48M BYTE abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; BYTE abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; - PBYTE pbyRate; + unsigned char *pbyRate; PSTxMgmtPacket pTxPacket; PSMgmtObject pMgmt = pDevice->pMgmt; unsigned int ii; @@ -269,7 +269,7 @@ PSTxMgmtPacket s_MgrMakeProbeRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pScanBSSID, + unsigned char *pScanBSSID, PWLAN_IE_SSID pSSID, PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates @@ -282,8 +282,8 @@ s_MgrMakeProbeRequest( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_PROBEREQ_FR_MAXLEN; vMgrEncodeProbeRequest(&sFrame); sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( @@ -982,7 +982,7 @@ s_bCommandComplete ( BOOL bScheduleCommand ( void *hDeviceContext, CMD_CODE eCommand, - PBYTE pbyItem0 + unsigned char *pbyItem0 ) { PSDevice pDevice = (PSDevice)hDeviceContext; diff --git a/drivers/staging/vt6655/wcmd.h b/drivers/staging/vt6655/wcmd.h index 0063b9945504..3eb5d75c6b55 100644 --- a/drivers/staging/vt6655/wcmd.h +++ b/drivers/staging/vt6655/wcmd.h @@ -127,7 +127,7 @@ BOOL bScheduleCommand( void *hDeviceContext, CMD_CODE eCommand, - PBYTE pbyItem0 + unsigned char *pbyItem0 ); void diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c index 3e0d0eba73f9..8a37b769e8ae 100644 --- a/drivers/staging/vt6655/wctl.c +++ b/drivers/staging/vt6655/wctl.c @@ -205,7 +205,7 @@ unsigned int uHeaderSize; } } // reserve 4 byte to match MAC RX Buffer - pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (unsigned char *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4); memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength); pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength; pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength; @@ -220,7 +220,7 @@ unsigned int uHeaderSize; (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) && ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) { - memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize)); + memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((unsigned char *) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize)); pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize); pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize); pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 41f520afea11..3994ed21d4fa 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -104,7 +104,7 @@ PSTxMgmtPacket s_MgrMakeAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pDAddr, + unsigned char *pDAddr, WORD wCurrCapInfo, WORD wListenInterval, PWLAN_IE_SSID pCurrSSID, @@ -126,7 +126,7 @@ PSTxMgmtPacket s_MgrMakeReAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pDAddr, + unsigned char *pDAddr, WORD wCurrCapInfo, WORD wListenInterval, PWLAN_IE_SSID pCurrSSID, @@ -245,7 +245,7 @@ s_MgrMakeBeacon( unsigned int uCurrChannel, WORD wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, - PBYTE pCurrBSSID, + unsigned char *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ); @@ -260,7 +260,7 @@ s_MgrMakeAssocResponse( WORD wCurrCapInfo, WORD wAssocStatus, WORD wAssocAID, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ); @@ -274,7 +274,7 @@ s_MgrMakeReAssocResponse( WORD wCurrCapInfo, WORD wAssocStatus, WORD wAssocAID, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ); @@ -289,9 +289,9 @@ s_MgrMakeProbeResponse( WORD wCurrBeaconPeriod, unsigned int uCurrChannel, WORD wCurrATIMWinodw, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SSID pCurrSSID, - PBYTE pCurrBSSID, + unsigned char *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates, BYTE byPHYType @@ -320,8 +320,8 @@ static BOOL s_bCipherMatch ( PKnownBSS pBSSNode, NDIS_802_11_ENCRYPTION_STATUS EncStatus, - PBYTE pbyCCSPK, - PBYTE pbyCCSGK + unsigned char *pbyCCSPK, + unsigned char *pbyCCSGK ); static void Encyption_Rebuild( @@ -619,7 +619,7 @@ void vMgrDisassocBeginSta( void *hDeviceContext, PSMgmtObject pMgmt, - PBYTE abyDestAddress, + unsigned char *abyDestAddress, WORD wReason, PCMD_STATUS pStatus ) @@ -630,10 +630,10 @@ vMgrDisassocBeginSta( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DISASSOC_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_DISASSOC_FR_MAXLEN; // format fixed field frame structure @@ -708,7 +708,7 @@ s_vMgrRxAssocRequest( memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeAssocRequest(&sFrame); @@ -866,7 +866,7 @@ s_vMgrRxReAssocRequest( //decode the frame memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ)); sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeReassocRequest(&sFrame); if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) { @@ -1000,7 +1000,7 @@ s_vMgrRxAssocResponse( { WLAN_FR_ASSOCRESP sFrame; PWLAN_IE_SSID pItemSSID; - PBYTE pbyIEs; + unsigned char *pbyIEs; viawget_wpa_header *wpahdr; @@ -1009,7 +1009,7 @@ s_vMgrRxAssocResponse( pMgmt->eCurrState == WMAC_STATE_ASSOC) { sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; // decode the frame vMgrDecodeAssocResponse(&sFrame); if ((sFrame.pwCapInfo == 0) || @@ -1163,8 +1163,8 @@ vMgrAuthenBeginSta( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_AUTHEN_FR_MAXLEN; vMgrEncodeAuthen(&sFrame); /* insert values */ @@ -1212,7 +1212,7 @@ void vMgrDeAuthenBeginSta( void *hDeviceContext, PSMgmtObject pMgmt, - PBYTE abyDestAddress, + unsigned char *abyDestAddress, WORD wReason, PCMD_STATUS pStatus ) @@ -1224,8 +1224,8 @@ vMgrDeAuthenBeginSta( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DEAUTHEN_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN; vMgrEncodeDeauthen(&sFrame); /* insert values */ @@ -1282,7 +1282,7 @@ s_vMgrRxAuthentication( // decode the frame sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeAuthen(&sFrame); switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){ case 1: @@ -1353,8 +1353,8 @@ s_vMgrRxAuthenSequence_1( // send auth reply pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_AUTHEN_FR_MAXLEN; // format buffer structure vMgrEncodeAuthen(&sFrame); @@ -1466,8 +1466,8 @@ s_vMgrRxAuthenSequence_2( if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) { pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_AUTHEN_FR_MAXLEN; // format buffer structure vMgrEncodeAuthen(&sFrame); @@ -1573,8 +1573,8 @@ reply: // send auth reply pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_AUTHEN_FR_MAXLEN; // format buffer structure vMgrEncodeAuthen(&sFrame); @@ -1674,7 +1674,7 @@ s_vMgrRxDisassociation( // if is acting an AP.. // a STA is leaving this BSS.. sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { BSSvRemoveOneNode(pDevice, uNodeIndex); } @@ -1684,7 +1684,7 @@ s_vMgrRxDisassociation( } else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ){ sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeDisassociation(&sFrame); DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason))); //TODO: do something let upper layer know or @@ -1754,7 +1754,7 @@ s_vMgrRxDeauthentication( // if is acting an AP.. // a STA is leaving this BSS.. sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { BSSvRemoveOneNode(pDevice, uNodeIndex); } @@ -1765,7 +1765,7 @@ s_vMgrRxDeauthentication( else { if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ) { sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeDeauthen(&sFrame); DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason)))); // TODO: update BSS list for specific BSSID if pre-authentication case @@ -1900,7 +1900,7 @@ s_vMgrRxBeacon( memset(&sFrame, 0, sizeof(WLAN_FR_BEACON)); sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; // decode the beacon frame vMgrDecodeBeacon(&sFrame); @@ -3229,7 +3229,7 @@ s_MgrMakeBeacon( unsigned int uCurrChannel, WORD wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, - PBYTE pCurrBSSID, + unsigned char *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ) @@ -3237,7 +3237,7 @@ s_MgrMakeBeacon( PSTxMgmtPacket pTxPacket = NULL; WLAN_FR_BEACON sFrame; BYTE abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - PBYTE pbyBuffer; + unsigned char *pbyBuffer; unsigned int uLength = 0; PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; unsigned int ii; @@ -3245,9 +3245,9 @@ s_MgrMakeBeacon( // prepare beacon frame pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_BEACON_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure. - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_BEACON_FR_MAXLEN; vMgrEncodeBeacon(&sFrame); // Setup the header @@ -3342,7 +3342,7 @@ s_MgrMakeBeacon( if ((pMgmt->b11hEnable == TRUE) && (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { // Country IE - pbyBuffer = (PBYTE)(sFrame.pBuf + sFrame.len); + pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len); CARDvSetCountryIE(pMgmt->pAdapter, pbyBuffer); CARDvSetCountryInfo(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer); uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN; @@ -3457,9 +3457,9 @@ s_MgrMakeProbeResponse( WORD wCurrBeaconPeriod, unsigned int uCurrChannel, WORD wCurrATIMWinodw, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SSID pCurrSSID, - PBYTE pCurrBSSID, + unsigned char *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates, BYTE byPHYType @@ -3467,7 +3467,7 @@ s_MgrMakeProbeResponse( { PSTxMgmtPacket pTxPacket = NULL; WLAN_FR_PROBERESP sFrame; - PBYTE pbyBuffer; + unsigned char *pbyBuffer; unsigned int uLength = 0; PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; unsigned int ii; @@ -3475,9 +3475,9 @@ s_MgrMakeProbeResponse( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBERESP_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure. - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_PROBERESP_FR_MAXLEN; vMgrEncodeProbeResponse(&sFrame); // Setup the header @@ -3546,7 +3546,7 @@ s_MgrMakeProbeResponse( if ((pMgmt->b11hEnable == TRUE) && (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { // Country IE - pbyBuffer = (PBYTE)(sFrame.pBuf + sFrame.len); + pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len); CARDvSetCountryIE(pMgmt->pAdapter, pbyBuffer); CARDvSetCountryInfo(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer); uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN; @@ -3642,7 +3642,7 @@ PSTxMgmtPacket s_MgrMakeAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pDAddr, + unsigned char *pDAddr, WORD wCurrCapInfo, WORD wListenInterval, PWLAN_IE_SSID pCurrSSID, @@ -3652,15 +3652,15 @@ s_MgrMakeAssocRequest( { PSTxMgmtPacket pTxPacket = NULL; WLAN_FR_ASSOCREQ sFrame; - PBYTE pbyIEs; - PBYTE pbyRSN; + unsigned char *pbyIEs; + unsigned char *pbyRSN; pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure. - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN; // format fixed field frame structure vMgrEncodeAssocRequest(&sFrame); @@ -3722,7 +3722,7 @@ s_MgrMakeAssocRequest( } if (sFrame.pCurrSuppCh == NULL) { sFrame.pCurrSuppCh = (PWLAN_IE_SUPP_CH)(sFrame.pBuf + sFrame.len); - sFrame.len += CARDbySetSupportChannels(pMgmt->pAdapter,(PBYTE)sFrame.pCurrSuppCh); + sFrame.len += CARDbySetSupportChannels(pMgmt->pAdapter,(unsigned char *)sFrame.pCurrSuppCh); } } @@ -3765,7 +3765,7 @@ s_MgrMakeAssocRequest( sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; } // Auth Key Management Suite - pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); *pbyRSN++=0x01; *pbyRSN++=0x00; *pbyRSN++=0x00; @@ -3917,7 +3917,7 @@ PSTxMgmtPacket s_MgrMakeReAssocRequest( PSDevice pDevice, PSMgmtObject pMgmt, - PBYTE pDAddr, + unsigned char *pDAddr, WORD wCurrCapInfo, WORD wListenInterval, PWLAN_IE_SSID pCurrSSID, @@ -3927,15 +3927,15 @@ s_MgrMakeReAssocRequest( { PSTxMgmtPacket pTxPacket = NULL; WLAN_FR_REASSOCREQ sFrame; - PBYTE pbyIEs; - PBYTE pbyRSN; + unsigned char *pbyIEs; + unsigned char *pbyRSN; pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset( pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_REASSOCREQ_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); /* Setup the sFrame structure. */ - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN; // format fixed field frame structure @@ -4024,7 +4024,7 @@ s_MgrMakeReAssocRequest( sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; } // Auth Key Management Suite - pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); *pbyRSN++=0x01; *pbyRSN++=0x00; *pbyRSN++=0x00; @@ -4172,7 +4172,7 @@ s_MgrMakeAssocResponse( WORD wCurrCapInfo, WORD wAssocStatus, WORD wAssocAID, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ) @@ -4183,9 +4183,9 @@ s_MgrMakeAssocResponse( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; vMgrEncodeAssocResponse(&sFrame); // Setup the header @@ -4246,7 +4246,7 @@ s_MgrMakeReAssocResponse( WORD wCurrCapInfo, WORD wAssocStatus, WORD wAssocAID, - PBYTE pDstAddr, + unsigned char *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates ) @@ -4257,9 +4257,9 @@ s_MgrMakeReAssocResponse( pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); // Setup the sFrame structure - sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header; sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; vMgrEncodeReassocResponse(&sFrame); // Setup the header @@ -4331,7 +4331,7 @@ s_vMgrRxProbeResponse( memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP)); // decode the frame sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeProbeResponse(&sFrame); if ((sFrame.pqwTimestamp == 0) || @@ -4458,7 +4458,7 @@ s_vMgrRxProbeRequest( memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ)); // decode the frame sFrame.len = pRxPacket->cbMPDULen; - sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeProbeRequest(&sFrame); /* DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n", @@ -4495,7 +4495,7 @@ s_vMgrRxProbeRequest( 0, sFrame.pHdr->sA3.abyAddr2, (PWLAN_IE_SSID)pMgmt->abyCurrSSID, - (PBYTE)pMgmt->abyCurrBSSID, + (unsigned char *)pMgmt->abyCurrBSSID, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, byPHYType @@ -4708,7 +4708,7 @@ bMgrPrepareBeaconToSend( pMgmt->uCurrChannel, pMgmt->wCurrATIMWindow, //0, (PWLAN_IE_SSID)pMgmt->abyCurrSSID, - (PBYTE)pMgmt->abyCurrBSSID, + (unsigned char *)pMgmt->abyCurrBSSID, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates ); @@ -4810,7 +4810,7 @@ s_vMgrLogStatus( BOOL bAdd_PMKID_Candidate ( void *hDeviceContext, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, PSRSNCapObject psRSNCapObj ) { @@ -4885,8 +4885,8 @@ static BOOL s_bCipherMatch ( PKnownBSS pBSSNode, NDIS_802_11_ENCRYPTION_STATUS EncStatus, - PBYTE pbyCCSPK, - PBYTE pbyCCSGK + unsigned char *pbyCCSPK, + unsigned char *pbyCCSGK ) { BYTE byMulticastCipher = KEY_CTL_INVALID; diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index a08403e3c610..748706fcaef7 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -332,7 +332,7 @@ typedef struct tagSMgmtObject WORD wListenInterval; WORD wCountToWakeUp; BOOL bInTIMWake; - PBYTE pbyPSPacketPool; + unsigned char *pbyPSPacketPool; BYTE byPSPacketPool[sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN]; BOOL bRxBeaconInTBTTWake; BYTE abyPSTxMap[MAX_NODE_NUM + 1]; @@ -342,7 +342,7 @@ typedef struct tagSMgmtObject unsigned int uCmdHostAPBusy; // management packet pool - PBYTE pbyMgmtPacketPool; + unsigned char *pbyMgmtPacketPool; BYTE byMgmtPacketPool[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; @@ -432,7 +432,7 @@ void vMgrDisassocBeginSta( void *hDeviceContext, PSMgmtObject pMgmt, - PBYTE abyDestAddress, + unsigned char *abyDestAddress, WORD wReason, PCMD_STATUS pStatus ); @@ -475,7 +475,7 @@ void vMgrDeAuthenBeginSta( void *hDeviceContext, PSMgmtObject pMgmt, - PBYTE abyDestAddress, + unsigned char *abyDestAddress, WORD wReason, PCMD_STATUS pStatus ); @@ -490,7 +490,7 @@ bMgrPrepareBeaconToSend( BOOL bAdd_PMKID_Candidate ( void *hDeviceContext, - PBYTE pbyBSSID, + unsigned char *pbyBSSID, PSRSNCapObject psRSNCapObj ); diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c index da5c814e200e..d3b54c514026 100644 --- a/drivers/staging/vt6655/wpa.c +++ b/drivers/staging/vt6655/wpa.c @@ -112,7 +112,7 @@ WPA_ParseRSN ( { PWLAN_IE_RSN_AUTH pIE_RSN_Auth = NULL; int i, j, m, n = 0; - PBYTE pbyCaps; + unsigned char *pbyCaps; WPA_ClearRSN(pBSSList); @@ -207,7 +207,7 @@ WPA_ParseRSN ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+4+(m+n)*4: %d\n", 14+4+(m+n)*4); if(pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2) - pbyCaps = (PBYTE)pIE_RSN_Auth->AuthKSList[n].abyOUI; + pbyCaps = (unsigned char *)pIE_RSN_Auth->AuthKSList[n].abyOUI; pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG; pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS); pBSSList->sRSNCapObj.bRSNCapExist = TRUE; diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c index caa32b752c9f..e77fb08c9cf7 100644 --- a/drivers/staging/vt6655/wpa2.c +++ b/drivers/staging/vt6655/wpa2.c @@ -115,7 +115,7 @@ WPA2vParseRSN ( { int i, j; WORD m = 0, n = 0; - PBYTE pbyOUI; + unsigned char *pbyOUI; BOOL bUseGK = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len); @@ -268,7 +268,7 @@ WPA2uSetIEs( ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; - PBYTE pbyBuffer = NULL; + unsigned char *pbyBuffer = NULL; unsigned int ii = 0; PWORD pwPMKID = NULL; @@ -279,7 +279,7 @@ WPA2uSetIEs( (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && (pMgmt->pCurrBSS != NULL)) { /* WPA2 IE */ - pbyBuffer = (PBYTE) pRSNIEs; + pbyBuffer = (unsigned char *) pRSNIEs; pRSNIEs->byElementID = WLAN_EID_RSN; pRSNIEs->len = 6; //Version(2)+GK(4) pRSNIEs->wVersion = 1; diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 4adc2f05be14..714364388c55 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -359,7 +359,7 @@ spin_lock_irq(&pDevice->lock); dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), - (PBYTE)abyKey, + (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == TRUE) && @@ -367,7 +367,7 @@ spin_lock_irq(&pDevice->lock); dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), - (PBYTE)abyKey, + (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == TRUE) ) { @@ -400,7 +400,7 @@ spin_lock_irq(&pDevice->lock); dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), - (PBYTE)abyKey, + (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == TRUE) { @@ -613,13 +613,13 @@ static int wpa_get_scan(PSDevice pDevice, PSMgmtObject pMgmt = pDevice->pMgmt; PWLAN_IE_SSID pItemSSID; PKnownBSS pBSS; - PBYTE pBuf; + unsigned char *pBuf; int ret = 0; u16 count = 0; u16 ii, jj; #if 1 - PBYTE ptempBSS; + unsigned char *ptempBSS; @@ -713,7 +713,7 @@ static int wpa_get_scan(PSDevice pDevice, scan_buf->rsn_ie_len = pBSS->wRSNLen; memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); } - scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); + scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result)); jj ++; } } diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c index 648ae1aa2b18..6d02cea7b41d 100644 --- a/drivers/staging/vt6655/wroute.c +++ b/drivers/staging/vt6655/wroute.c @@ -65,7 +65,7 @@ static int msglevel =MSG_LEVEL_INFO; * Return Value: TRUE if packet duplicate; otherwise FALSE * */ -BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex) +BOOL ROUTEbRelay (PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex) { PSMgmtObject pMgmt = pDevice->pMgmt; PSTxDesc pHeadTD, pLastTD; @@ -77,7 +77,7 @@ BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, uns PSKeyItem pTransmitKey = NULL; unsigned int cbHeaderSize; unsigned int ii; - PBYTE pbyBSSID; + unsigned char *pbyBSSID; @@ -91,7 +91,7 @@ BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, uns pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); - memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)pbySkbData, ETH_HLEN); + memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)pbySkbData, ETH_HLEN); cbFrameBodySize = uDataLen - ETH_HLEN; diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h index 199d31153d8e..79f3014ab000 100644 --- a/drivers/staging/vt6655/wroute.h +++ b/drivers/staging/vt6655/wroute.h @@ -39,7 +39,7 @@ /*--------------------- Export Functions --------------------------*/ -BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex); +BOOL ROUTEbRelay (PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex); #endif // __WROUTE_H__ -- cgit v1.2.3 From 15df6c2b922de3088203ad90347a30d31ccca67e Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Sat, 5 Jun 2010 15:13:48 -0700 Subject: Staging: vt6655: remove PWORD typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use unsigned short * instead. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/80211mgr.c | 76 ++++++++++++++++++------------------ drivers/staging/vt6655/80211mgr.h | 38 +++++++++--------- drivers/staging/vt6655/aes_ccmp.c | 4 +- drivers/staging/vt6655/baseband.c | 2 +- drivers/staging/vt6655/baseband.h | 2 +- drivers/staging/vt6655/bssdb.c | 18 ++++----- drivers/staging/vt6655/bssdb.h | 2 +- drivers/staging/vt6655/card.c | 2 +- drivers/staging/vt6655/datarate.c | 6 +-- drivers/staging/vt6655/datarate.h | 6 +-- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/vt6655/dpc.c | 32 +++++++-------- drivers/staging/vt6655/rxtx.c | 34 ++++++++-------- drivers/staging/vt6655/ttype.h | 2 - drivers/staging/vt6655/upc.h | 4 +- drivers/staging/vt6655/vntwifi.c | 2 +- drivers/staging/vt6655/vntwifi.h | 2 +- drivers/staging/vt6655/wcmd.c | 2 +- drivers/staging/vt6655/wmgr.c | 12 +++--- drivers/staging/vt6655/wpa.c | 2 +- drivers/staging/vt6655/wpa2.c | 14 +++---- 21 files changed, 131 insertions(+), 133 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/80211mgr.c b/drivers/staging/vt6655/80211mgr.c index 9fbced855059..9156a0bacdd2 100644 --- a/drivers/staging/vt6655/80211mgr.c +++ b/drivers/staging/vt6655/80211mgr.c @@ -99,9 +99,9 @@ vMgrEncodeBeacon( // Fixed Fields pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_TS); - pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_BCN_INT); - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_CAPINFO); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID; @@ -133,9 +133,9 @@ vMgrDecodeBeacon( // Fixed Fields pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_TS); - pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_BCN_INT); - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_CAPINFO); // Information elements @@ -296,7 +296,7 @@ vMgrEncodeDisassociation( // Fixed Fields - pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DISASSOC_OFF_REASON); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason)); @@ -323,7 +323,7 @@ vMgrDecodeDisassociation( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DISASSOC_OFF_REASON); return; @@ -348,9 +348,9 @@ vMgrEncodeAssocRequest( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_CAP_INFO); - pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_LISTEN_INT); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval)); return; @@ -377,9 +377,9 @@ vMgrDecodeAssocRequest( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_CAP_INFO); - pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_LISTEN_INT); // Information elements @@ -442,11 +442,11 @@ vMgrEncodeAssocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_CAP_INFO); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_STATUS); - pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_AID); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid)); @@ -476,11 +476,11 @@ vMgrDecodeAssocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_CAP_INFO); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_STATUS); - pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_AID); // Information elements @@ -521,9 +521,9 @@ vMgrEncodeReassocRequest( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CAP_INFO); - pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_LISTEN_INT); pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CURR_AP); @@ -554,9 +554,9 @@ vMgrDecodeReassocRequest( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CAP_INFO); - pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_LISTEN_INT); pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CURR_AP); @@ -701,9 +701,9 @@ vMgrEncodeProbeResponse( // Fixed Fields pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_TS); - pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_BCN_INT); - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_CAP_INFO); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO + @@ -738,9 +738,9 @@ vMgrDecodeProbeResponse( // Fixed Fields pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_TS); - pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_BCN_INT); - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_CAP_INFO); // Information elements @@ -847,11 +847,11 @@ vMgrEncodeAuthen( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_ALG); - pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_SEQ); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_STATUS); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus)); @@ -880,11 +880,11 @@ vMgrDecodeAuthen( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_ALG); - pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_SEQ); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_STATUS); // Information elements @@ -918,7 +918,7 @@ vMgrEncodeDeauthen( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DEAUTHEN_OFF_REASON); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason)); @@ -945,7 +945,7 @@ vMgrDecodeDeauthen( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DEAUTHEN_OFF_REASON); return; @@ -971,11 +971,11 @@ vMgrEncodeReassocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_CAP_INFO); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_STATUS); - pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_AID); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid)); @@ -1006,11 +1006,11 @@ vMgrDecodeReassocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; // Fixed Fields - pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_CAP_INFO); - pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_STATUS); - pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_AID); //Information elements diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h index bb58ed0ba3a3..a11e6633a3c6 100644 --- a/drivers/staging/vt6655/80211mgr.h +++ b/drivers/staging/vt6655/80211mgr.h @@ -511,8 +511,8 @@ typedef struct tagWLAN_FR_BEACON { PUWLAN_80211HDR pHdr; // fixed fields PQWORD pqwTimestamp; - PWORD pwBeaconInterval; - PWORD pwCapInfo; + unsigned short *pwBeaconInterval; + unsigned short *pwCapInfo; /*-- info elements ----------*/ PWLAN_IE_SSID pSSID; PWLAN_IE_SUPP_RATES pSuppRates; @@ -556,7 +556,7 @@ typedef struct tagWLAN_FR_DISASSOC { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwReason; + unsigned short *pwReason; /*-- info elements ----------*/ } WLAN_FR_DISASSOC, *PWLAN_FR_DISASSOC; @@ -569,8 +569,8 @@ typedef struct tagWLAN_FR_ASSOCREQ { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwCapInfo; - PWORD pwListenInterval; + unsigned short *pwCapInfo; + unsigned short *pwListenInterval; /*-- info elements ----------*/ PWLAN_IE_SSID pSSID; PWLAN_IE_SUPP_RATES pSuppRates; @@ -590,9 +590,9 @@ typedef struct tagWLAN_FR_ASSOCRESP { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwCapInfo; - PWORD pwStatus; - PWORD pwAid; + unsigned short *pwCapInfo; + unsigned short *pwStatus; + unsigned short *pwAid; /*-- info elements ----------*/ PWLAN_IE_SUPP_RATES pSuppRates; PWLAN_IE_SUPP_RATES pExtSuppRates; @@ -608,8 +608,8 @@ typedef struct tagWLAN_FR_REASSOCREQ { PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwCapInfo; - PWORD pwListenInterval; + unsigned short *pwCapInfo; + unsigned short *pwListenInterval; PIEEE_ADDR pAddrCurrAP; /*-- info elements ----------*/ @@ -629,9 +629,9 @@ typedef struct tagWLAN_FR_REASSOCRESP { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwCapInfo; - PWORD pwStatus; - PWORD pwAid; + unsigned short *pwCapInfo; + unsigned short *pwStatus; + unsigned short *pwAid; /*-- info elements ----------*/ PWLAN_IE_SUPP_RATES pSuppRates; PWLAN_IE_SUPP_RATES pExtSuppRates; @@ -662,8 +662,8 @@ typedef struct tagWLAN_FR_PROBERESP { PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ PQWORD pqwTimestamp; - PWORD pwBeaconInterval; - PWORD pwCapInfo; + unsigned short *pwBeaconInterval; + unsigned short *pwCapInfo; /*-- info elements ----------*/ PWLAN_IE_SSID pSSID; PWLAN_IE_SUPP_RATES pSuppRates; @@ -690,9 +690,9 @@ typedef struct tagWLAN_FR_AUTHEN { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwAuthAlgorithm; - PWORD pwAuthSequence; - PWORD pwStatus; + unsigned short *pwAuthAlgorithm; + unsigned short *pwAuthSequence; + unsigned short *pwStatus; /*-- info elements ----------*/ PWLAN_IE_CHALLENGE pChallenge; @@ -706,7 +706,7 @@ typedef struct tagWLAN_FR_DEAUTHEN { unsigned char *pBuf; PUWLAN_80211HDR pHdr; /*-- fixed fields -----------*/ - PWORD pwReason; + unsigned short *pwReason; /*-- info elements ----------*/ diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c index f148356cdfc5..a77a104a69cb 100644 --- a/drivers/staging/vt6655/aes_ccmp.c +++ b/drivers/staging/vt6655/aes_ccmp.c @@ -267,8 +267,8 @@ int ii,jj,kk; pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; - if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && - WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) && + WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) { bA4 = TRUE; pbyIV += 6; // 6 is 802.11 address4 wHLen += 6; diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index f96a33787d1e..87c66e20d929 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1849,7 +1849,7 @@ BBvCaculateParameter ( unsigned int cbFrameLength, WORD wRate, BYTE byPacketType, - PWORD pwPhyLen, + unsigned short *pwPhyLen, unsigned char *pbyPhySrv, unsigned char *pbyPhySgn ) diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 616dab6f3ac1..eb0368ad850f 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -132,7 +132,7 @@ BBvCaculateParameter ( unsigned int cbFrameLength, WORD wRate, BYTE byPacketType, - PWORD pwPhyLen, + unsigned short *pwPhyLen, unsigned char *pbyPhySrv, unsigned char *pbyPhySgn ); diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 76e81362fc17..ddfc97cabd64 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -542,8 +542,8 @@ BSSbInsertToBSSList ( TRUE, pQuiet->byQuietCount, pQuiet->byQuietPeriod, - *((PWORD)pQuiet->abyQuietDuration), - *((PWORD)pQuiet->abyQuietOffset) + *((unsigned short *)pQuiet->abyQuietDuration), + *((unsigned short *)pQuiet->abyQuietOffset) ); } else { pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; @@ -551,8 +551,8 @@ BSSbInsertToBSSList ( FALSE, pQuiet->byQuietCount, pQuiet->byQuietPeriod, - *((PWORD)pQuiet->abyQuietDuration), - *((PWORD)pQuiet->abyQuietOffset) + *((unsigned short *)pQuiet->abyQuietDuration), + *((unsigned short *)pQuiet->abyQuietOffset) ); } } @@ -719,8 +719,8 @@ BSSbUpdateToBSSList ( TRUE, pQuiet->byQuietCount, pQuiet->byQuietPeriod, - *((PWORD)pQuiet->abyQuietDuration), - *((PWORD)pQuiet->abyQuietOffset) + *((unsigned short *)pQuiet->abyQuietDuration), + *((unsigned short *)pQuiet->abyQuietOffset) ); } else { pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; @@ -728,8 +728,8 @@ BSSbUpdateToBSSList ( FALSE, pQuiet->byQuietCount, pQuiet->byQuietPeriod, - *((PWORD)pQuiet->abyQuietDuration), - *((PWORD)pQuiet->abyQuietOffset) + *((unsigned short *)pQuiet->abyQuietDuration), + *((unsigned short *)pQuiet->abyQuietOffset) ); } } @@ -898,7 +898,7 @@ BSSvRemoveOneNode( void BSSvUpdateAPNode( void *hDeviceContext, - PWORD pwCapInfo, + unsigned short *pwCapInfo, PWLAN_IE_SUPP_RATES pSuppRates, PWLAN_IE_SUPP_RATES pExtSuppRates ) diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h index ac6473a05ba3..9f197c3bb57f 100644 --- a/drivers/staging/vt6655/bssdb.h +++ b/drivers/staging/vt6655/bssdb.h @@ -324,7 +324,7 @@ BSSvCreateOneNode( void BSSvUpdateAPNode( void *hDeviceContext, - PWORD pwCapInfo, + unsigned short *pwCapInfo, PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pExtSuppRates ); diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 5ce98a07c554..6cc0c3db53ac 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1748,7 +1748,7 @@ CARDbStartMeasure ( if (pDevice->byLocalID > REV_ID_VT3253_B1) { HIDWORD(qwStartTSF) = HIDWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime))); LODWORD(qwStartTSF) = LODWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime))); - wDuration = *((PWORD) (pDevice->pCurrMeasureEID->sReq.abyDuration)); + wDuration = *((unsigned short *) (pDevice->pCurrMeasureEID->sReq.abyDuration)); wDuration += 1; // 1 TU for channel switching if ((LODWORD(qwStartTSF) == 0) && (HIDWORD(qwStartTSF) == 0)) { diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c index e1ab30079c03..4be933c0ad04 100644 --- a/drivers/staging/vt6655/datarate.c +++ b/drivers/staging/vt6655/datarate.c @@ -200,9 +200,9 @@ RATEvParseMaxRate ( PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates, BOOL bUpdateBasicRate, - PWORD pwMaxBasicRate, - PWORD pwMaxSuppRate, - PWORD pwSuppRate, + unsigned short *pwMaxBasicRate, + unsigned short *pwMaxSuppRate, + unsigned short *pwSuppRate, unsigned char *pbyTopCCKRate, unsigned char *pbyTopOFDMRate ) diff --git a/drivers/staging/vt6655/datarate.h b/drivers/staging/vt6655/datarate.h index 2cb3b5097a5c..dc4baed51d49 100644 --- a/drivers/staging/vt6655/datarate.h +++ b/drivers/staging/vt6655/datarate.h @@ -60,9 +60,9 @@ RATEvParseMaxRate( PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates, BOOL bUpdateBasicRate, - PWORD pwMaxBasicRate, - PWORD pwMaxSuppRate, - PWORD pwSuppRate, + unsigned short *pwMaxBasicRate, + unsigned short *pwMaxSuppRate, + unsigned short *pwSuppRate, unsigned char *pbyTopCCKRate, unsigned char *pbyTopOFDMRate ); diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index ecc362d3fdd9..f1af517b74b3 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -487,7 +487,7 @@ static void s_vCompleteCurrentMeasure (PSDevice pDevice, BYTE byResult) for(ii=1;ii<8;ii++) { pDevice->dwRPIs[ii] *= 255; - dwDuration |= *((PWORD) (pDevice->pCurrMeasureEID->sReq.abyDuration)); + dwDuration |= *((unsigned short *) (pDevice->pCurrMeasureEID->sReq.abyDuration)); dwDuration <<= 10; pDevice->dwRPIs[ii] /= dwDuration; pDevice->abyRPIs[ii] = (BYTE) pDevice->dwRPIs[ii]; diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 723f8466bd61..98bc2552fa00 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -124,7 +124,7 @@ static BOOL s_bHandleRxEncryption( unsigned char *pbyNewRsr, PSKeyItem *pKeyOut, int * pbExtIV, - PWORD pwRxTSC15_0, + unsigned short *pwRxTSC15_0, PDWORD pdwRxTSC47_16 ); @@ -138,7 +138,7 @@ static BOOL s_bHostWepRxEncryption( PSKeyItem pKey, unsigned char *pbyNewRsr, int * pbExtIV, - PWORD pwRxTSC15_0, + unsigned short *pwRxTSC15_0, PDWORD pdwRxTSC47_16 ); @@ -175,7 +175,7 @@ s_vProcessRxMACHeader ( { unsigned char *pbyRxBuffer; unsigned int cbHeaderSize = 0; - PWORD pwType; + unsigned short *pwType; PS802_11Header pMACHeader; int ii; @@ -203,12 +203,12 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; - pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); if ((*pwType!= TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) { } else { cbHeaderSize -= 8; - pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); if (bIsWEP) { if (bExtIV) { *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV @@ -223,7 +223,7 @@ s_vProcessRxMACHeader ( } else { cbHeaderSize -= 2; - pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); if (bIsWEP) { if (bExtIV) { *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV @@ -353,7 +353,7 @@ device_receive_frame ( unsigned char *pbyNewRsr; unsigned char *pbyRSSI; PQWORD pqwTSFTime; - PWORD pwFrameSize; + unsigned short *pwFrameSize; unsigned char *pbyFrame; BOOL bDeFragRx = FALSE; BOOL bIsWEP = FALSE; @@ -391,7 +391,7 @@ device_receive_frame ( pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); #endif //PLICE_DEBUG<- - pwFrameSize = (PWORD)(skb->data + 2); + pwFrameSize = (unsigned short *)(skb->data + 2); FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount); // Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR @@ -1170,7 +1170,7 @@ static BOOL s_bHandleRxEncryption ( unsigned char *pbyNewRsr, PSKeyItem *pKeyOut, int * pbExtIV, - PWORD pwRxTSC15_0, + unsigned short *pwRxTSC15_0, PDWORD pdwRxTSC47_16 ) { @@ -1186,8 +1186,8 @@ static BOOL s_bHandleRxEncryption ( *pdwRxTSC47_16 = 0; pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; - if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && - WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) && + WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) { pbyIV += 6; // 6 is 802.11 address4 PayloadLen -= 6; } @@ -1280,7 +1280,7 @@ static BOOL s_bHandleRxEncryption ( if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); } else { - *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV); + *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); @@ -1317,7 +1317,7 @@ static BOOL s_bHostWepRxEncryption ( PSKeyItem pKey, unsigned char *pbyNewRsr, int * pbExtIV, - PWORD pwRxTSC15_0, + unsigned short *pwRxTSC15_0, PDWORD pdwRxTSC47_16 ) { @@ -1333,8 +1333,8 @@ static BOOL s_bHostWepRxEncryption ( *pdwRxTSC47_16 = 0; pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; - if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && - WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) && + WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) { pbyIV += 6; // 6 is 802.11 address4 PayloadLen -= 6; } @@ -1391,7 +1391,7 @@ static BOOL s_bHostWepRxEncryption ( if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); } else { - *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV); + *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 32725dadf855..f3051b10c136 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -745,11 +745,11 @@ s_uFillDataHead ( PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get Duration and TimeStamp @@ -771,11 +771,11 @@ s_uFillDataHead ( PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get Duration and TimeStamp @@ -800,7 +800,7 @@ s_uFillDataHead ( PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -817,7 +817,7 @@ s_uFillDataHead ( PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -835,7 +835,7 @@ s_uFillDataHead ( PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration and TimeStampOff @@ -883,11 +883,11 @@ s_vFillRTSHead ( PSRTS_g pBuf = (PSRTS_g)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); //Get Duration @@ -916,11 +916,11 @@ s_vFillRTSHead ( PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); @@ -958,7 +958,7 @@ s_vFillRTSHead ( PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -987,7 +987,7 @@ s_vFillRTSHead ( PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -1017,7 +1017,7 @@ s_vFillRTSHead ( PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration @@ -1077,7 +1077,7 @@ s_vFillCTSHead ( PSCTS_FB pBuf = (PSCTS_FB)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); @@ -1104,7 +1104,7 @@ s_vFillCTSHead ( PSCTS pBuf = (PSCTS)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, - (PWORD)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) + (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get CTSDuration_ba @@ -2703,7 +2703,7 @@ CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { } BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType, - (PWORD)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField) + (unsigned short *)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField) ); pTxDataHead->wTransmitLength = cpu_to_le16(wLen); //Get TimeStampOff diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 6fe184fb77d6..660bc5b20894 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -92,8 +92,6 @@ typedef unsigned long DWORD_PTR; // 32-bit // boolean pointer typedef unsigned int * PUINT; -typedef WORD * PWORD; - typedef DWORD * PDWORD; typedef QWORD * PQWORD; diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index c12d028d5ec1..ecf683feca39 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -82,7 +82,7 @@ #define VNSvInPortW(dwIOAddress, pwData) { \ - volatile WORD* pwAddr = ((PWORD)(dwIOAddress)); \ + volatile WORD* pwAddr = ((unsigned short *)(dwIOAddress)); \ *(pwData) = readw(pwAddr); \ } @@ -99,7 +99,7 @@ #define VNSvOutPortW(dwIOAddress, wData) { \ - volatile WORD* pwAddr = ((PWORD)(dwIOAddress)); \ + volatile WORD* pwAddr = ((unsigned short *)(dwIOAddress)); \ writew((WORD)wData, pwAddr); \ } diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index 88c0ad420a41..ce60f7c7f8b4 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -533,7 +533,7 @@ void VNTWIFIvGetTxRate( void *pMgmtHandle, unsigned char *pbyDestAddress, - PWORD pwTxDataRate, + unsigned short *pwTxDataRate, unsigned char *pbyACKRate, unsigned char *pbyCCKBasicRate, unsigned char *pbyOFDMBasicRate diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h index 6d14161e6de4..724cd4c9b6bc 100644 --- a/drivers/staging/vt6655/vntwifi.h +++ b/drivers/staging/vt6655/vntwifi.h @@ -240,7 +240,7 @@ void VNTWIFIvGetTxRate( void *pMgmtHandle, unsigned char *pbyDestAddress, - PWORD pwTxDataRate, + unsigned short *pwTxDataRate, unsigned char *pbyACKRate, unsigned char *pbyCCKBasicRate, unsigned char *pbyOFDMBasicRate diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index 4e7b457cb9a9..1eb4f6b596f9 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -1014,7 +1014,7 @@ BOOL bScheduleCommand ( break; /* case WLAN_CMD_DEAUTH: - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((PWORD)pbyItem0); + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((unsigned short *)pbyItem0); break; */ diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 3994ed21d4fa..231a3e70436e 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -3329,11 +3329,11 @@ s_MgrMakeBeacon( // Pairwise Key Cipher Suite sFrame.pRSNWPA->wPKCount = 0; // Auth Key Management Suite - *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; sFrame.pRSNWPA->len +=2; // RSN Capabilites - *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; sFrame.pRSNWPA->len +=2; sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; } @@ -3800,7 +3800,7 @@ s_MgrMakeAssocRequest( (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && (pMgmt->pCurrBSS != NULL)) { unsigned int ii; - PWORD pwPMKID; + unsigned short *pwPMKID; // WPA IE sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); @@ -3865,7 +3865,7 @@ s_MgrMakeAssocRequest( if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == TRUE) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID pbyRSN = &sFrame.pRSN->abyRSN[18]; - pwPMKID = (PWORD)pbyRSN; // Point to PMKID count + pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count *pwPMKID = 0; // Initialize PMKID count pbyRSN += 2; // Point to PMKID list for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { @@ -4056,7 +4056,7 @@ s_MgrMakeReAssocRequest( (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && (pMgmt->pCurrBSS != NULL)) { unsigned int ii; - PWORD pwPMKID; + unsigned short *pwPMKID; /* WPA IE */ sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); @@ -4121,7 +4121,7 @@ s_MgrMakeReAssocRequest( if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == TRUE) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID pbyRSN = &sFrame.pRSN->abyRSN[18]; - pwPMKID = (PWORD)pbyRSN; // Point to PMKID count + pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count *pwPMKID = 0; // Initialize PMKID count pbyRSN += 2; // Point to PMKID list for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c index d3b54c514026..4f81364dffea 100644 --- a/drivers/staging/vt6655/wpa.c +++ b/drivers/staging/vt6655/wpa.c @@ -211,7 +211,7 @@ WPA_ParseRSN ( pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG; pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS); pBSSList->sRSNCapObj.bRSNCapExist = TRUE; - pBSSList->sRSNCapObj.wRSNCap = *(PWORD)pbyCaps; + pBSSList->sRSNCapObj.wRSNCap = *(unsigned short *)pbyCaps; //DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps)); //DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK)); //DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx)); diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c index e77fb08c9cf7..c4387de67c4d 100644 --- a/drivers/staging/vt6655/wpa2.c +++ b/drivers/staging/vt6655/wpa2.c @@ -164,7 +164,7 @@ WPA2vParseRSN ( } if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2) - pBSSNode->wCSSPKCount = *((PWORD) &(pRSN->abyRSN[4])); + pBSSNode->wCSSPKCount = *((unsigned short *) &(pRSN->abyRSN[4])); j = 0; pbyOUI = &(pRSN->abyRSN[6]); @@ -213,10 +213,10 @@ WPA2vParseRSN ( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount); } - m = *((PWORD) &(pRSN->abyRSN[4])); + m = *((unsigned short *) &(pRSN->abyRSN[4])); if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2) - pBSSNode->wAKMSSAuthCount = *((PWORD) &(pRSN->abyRSN[6+4*m]));; + pBSSNode->wAKMSSAuthCount = *((unsigned short *) &(pRSN->abyRSN[6+4*m]));; j = 0; pbyOUI = &(pRSN->abyRSN[8+4*m]); for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(BYTE)); i++) { @@ -235,10 +235,10 @@ WPA2vParseRSN ( pBSSNode->wAKMSSAuthCount = (WORD)j; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount); - n = *((PWORD) &(pRSN->abyRSN[6+4*m]));; + n = *((unsigned short *) &(pRSN->abyRSN[6+4*m]));; if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2) pBSSNode->sRSNCapObj.bRSNCapExist = TRUE; - pBSSNode->sRSNCapObj.wRSNCap = *((PWORD) &(pRSN->abyRSN[8+4*m+4*n])); + pBSSNode->sRSNCapObj.wRSNCap = *((unsigned short *) &(pRSN->abyRSN[8+4*m+4*n])); } } //ignore PMKID lists bcs only (Re)Assocrequest has this field @@ -270,7 +270,7 @@ WPA2uSetIEs( PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; unsigned char *pbyBuffer = NULL; unsigned int ii = 0; - PWORD pwPMKID = NULL; + unsigned short *pwPMKID = NULL; if (pRSNIEs == NULL) { return(0); @@ -342,7 +342,7 @@ WPA2uSetIEs( (pMgmt->bRoaming == TRUE) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID - pwPMKID = (PWORD)(&pRSNIEs->abyRSN[18]); // Point to PMKID count + pwPMKID = (unsigned short *)(&pRSNIEs->abyRSN[18]); // Point to PMKID count *pwPMKID = 0; // Initialize PMKID count pbyBuffer = &pRSNIEs->abyRSN[20]; // Point to PMKID list for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) { -- cgit v1.2.3 From 9d828c458f77043ddd9626ee0cfa688dda99c0eb Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Sat, 5 Jun 2010 15:13:49 -0700 Subject: Staging: vt6655: remove PDWORD typedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use unsigned long * instead. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/aes_ccmp.c | 12 +++++----- drivers/staging/vt6655/dpc.c | 36 ++++++++++++++-------------- drivers/staging/vt6655/ioctl.c | 2 +- drivers/staging/vt6655/key.c | 8 +++---- drivers/staging/vt6655/mac.c | 24 +++++++++---------- drivers/staging/vt6655/mac.h | 18 +++++++------- drivers/staging/vt6655/michael.c | 2 +- drivers/staging/vt6655/michael.h | 2 +- drivers/staging/vt6655/rxtx.c | 50 +++++++++++++++++++-------------------- drivers/staging/vt6655/srom.c | 2 +- drivers/staging/vt6655/srom.h | 2 +- drivers/staging/vt6655/tether.c | 2 +- drivers/staging/vt6655/ttype.h | 2 -- drivers/staging/vt6655/upc.h | 4 ++-- 14 files changed, 82 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c index a77a104a69cb..ae5c0e4f13ab 100644 --- a/drivers/staging/vt6655/aes_ccmp.c +++ b/drivers/staging/vt6655/aes_ccmp.c @@ -112,9 +112,9 @@ BYTE dot3_table[256] = { void xor_128(BYTE *a, BYTE *b, BYTE *out) { -PDWORD dwPtrA = (PDWORD) a; -PDWORD dwPtrB = (PDWORD) b; -PDWORD dwPtrOut =(PDWORD) out; +unsigned long *dwPtrA = (unsigned long *) a; +unsigned long *dwPtrB = (unsigned long *) b; +unsigned long *dwPtrOut =(unsigned long *) out; (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); @@ -125,9 +125,9 @@ PDWORD dwPtrOut =(PDWORD) out; void xor_32(BYTE *a, BYTE *b, BYTE *out) { -PDWORD dwPtrA = (PDWORD) a; -PDWORD dwPtrB = (PDWORD) b; -PDWORD dwPtrOut =(PDWORD) out; +unsigned long *dwPtrA = (unsigned long *) a; +unsigned long *dwPtrB = (unsigned long *) b; +unsigned long *dwPtrOut =(unsigned long *) out; (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); } diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 98bc2552fa00..3f3f83a83191 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -125,7 +125,7 @@ static BOOL s_bHandleRxEncryption( PSKeyItem *pKeyOut, int * pbExtIV, unsigned short *pwRxTSC15_0, - PDWORD pdwRxTSC47_16 + unsigned long *pdwRxTSC47_16 ); static BOOL s_bHostWepRxEncryption( @@ -139,7 +139,7 @@ static BOOL s_bHostWepRxEncryption( unsigned char *pbyNewRsr, int * pbExtIV, unsigned short *pwRxTSC15_0, - PDWORD pdwRxTSC47_16 + unsigned long *pdwRxTSC47_16 ); @@ -800,8 +800,8 @@ device_receive_frame ( // Soft MIC if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { if (bIsWEP) { - PDWORD pdwMIC_L; - PDWORD pdwMIC_R; + unsigned long *pdwMIC_L; + unsigned long *pdwMIC_R; DWORD dwMIC_Priority; DWORD dwMICKey0 = 0, dwMICKey1 = 0; DWORD dwLocalMIC_L = 0; @@ -810,19 +810,19 @@ device_receive_frame ( if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { - dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24])); - dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28])); + dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28])); } else { if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { - dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16])); - dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20])); + dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20])); } else if ((pKey->dwKeyIndex & BIT28) == 0) { - dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16])); - dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20])); + dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20])); } else { - dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24])); - dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28])); + dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28])); } } @@ -836,8 +836,8 @@ device_receive_frame ( MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); MIC_vUnInit(); - pdwMIC_L = (PDWORD)(skb->data + 4 + FrameSize); - pdwMIC_R = (PDWORD)(skb->data + 4 + FrameSize + 4); + pdwMIC_L = (unsigned long *)(skb->data + 4 + FrameSize); + pdwMIC_R = (unsigned long *)(skb->data + 4 + FrameSize + 4); //DBG_PRN_GRP12(("RxL: %lx, RxR: %lx\n", *pdwMIC_L, *pdwMIC_R)); //DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R)); //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1); @@ -1171,7 +1171,7 @@ static BOOL s_bHandleRxEncryption ( PSKeyItem *pKeyOut, int * pbExtIV, unsigned short *pwRxTSC15_0, - PDWORD pdwRxTSC47_16 + unsigned long *pdwRxTSC47_16 ) { unsigned int PayloadLen = FrameSize; @@ -1275,7 +1275,7 @@ static BOOL s_bHandleRxEncryption ( // TKIP/AES PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc - *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); + *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); @@ -1318,7 +1318,7 @@ static BOOL s_bHostWepRxEncryption ( unsigned char *pbyNewRsr, int * pbExtIV, unsigned short *pwRxTSC15_0, - PDWORD pdwRxTSC47_16 + unsigned long *pdwRxTSC47_16 ) { unsigned int PayloadLen = FrameSize; @@ -1385,7 +1385,7 @@ static BOOL s_bHostWepRxEncryption ( // TKIP/AES PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc - *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); + *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index cc4f4c1b4cc0..210ad80a329f 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -732,7 +732,7 @@ vConfigWEPKey ( pDevice->auWepKeyLength[dwKeyIndex] = uKeyLength; MACvSetDefaultKeyEntry(pDevice->PortOffset, uKeyLength, dwKeyIndex, - (PDWORD) &(pDevice->abyWepKey[dwKeyIndex][0]), pDevice->byLocalID); + (unsigned long *) &(pDevice->abyWepKey[dwKeyIndex][0]), pDevice->byLocalID); if (pDevice->eEncryptionStatus < Ndis802_11EncryptionNotSupported) { for(ii=0; iiabyKey[15] |= 0x80; } - MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey, byLocalID); + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID); if ((dwKeyIndex & USE_KEYRSC) == 0) { // RSC set by NIC @@ -317,7 +317,7 @@ BOOL KeybSetKey ( if (uKeyLength == WLAN_WEP104_KEYLEN) pKey->abyKey[15] |= 0x80; } - MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey, byLocalID); + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID); if ((dwKeyIndex & USE_KEYRSC) == 0) { // RSC set by NIC @@ -693,7 +693,7 @@ BOOL KeybSetDefaultKey ( if (uKeyLength == WLAN_WEP104_KEYLEN) pKey->abyKey[15] |= 0x80; } - MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (PDWORD)pKey->abyKey, byLocalID); + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID); if ((dwKeyIndex & USE_KEYRSC) == 0) { // RSC set by NIC @@ -792,7 +792,7 @@ BOOL KeybSetAllGroupKey ( if (uKeyLength == WLAN_WEP104_KEYLEN) pKey->abyKey[15] |= 0x80; } - MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (PDWORD)pKey->abyKey, byLocalID); + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID); if ((dwKeyIndex & USE_KEYRSC) == 0) { // RSC set by NIC diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 9d54b421f770..9ec1248bbf98 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -703,14 +703,14 @@ void MACvRestoreContext (DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf) } // restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR - VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(PDWORD)(pbyCxtBuf + MAC_REG_TXDMAPTR0)); - VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(PDWORD)(pbyCxtBuf + MAC_REG_AC0DMAPTR)); - VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(PDWORD)(pbyCxtBuf + MAC_REG_BCNDMAPTR)); + VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0)); + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR)); + VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_BCNDMAPTR)); - VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR0)); + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0)); - VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR1)); + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1)); } @@ -737,22 +737,22 @@ BOOL MACbCompareContext (DWORD_PTR dwIoBase, unsigned char *pbyCxtBuf) // compare CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, &dwData); - if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_TXDMAPTR0)) { + if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0)) { return FALSE; } VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, &dwData); - if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_AC0DMAPTR)) { + if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR)) { return FALSE; } VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, &dwData); - if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR0)) { + if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0)) { return FALSE; } VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, &dwData); - if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR1)) { + if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1)) { return FALSE; } @@ -1456,7 +1456,7 @@ BOOL MACbPSWakeup (DWORD_PTR dwIoBase) */ void MACvSetKeyEntry (DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, unsigned char *pbyAddr, PDWORD pdwKey, BYTE byLocalID) + unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; @@ -1551,7 +1551,7 @@ WORD wOffset; */ void MACvSetDefaultKeyEntry (DWORD_PTR dwIoBase, unsigned int uKeyLen, - unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID) + unsigned int uKeyIdx, unsigned long *pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; @@ -1667,7 +1667,7 @@ DWORD dwData; * */ void MACvSetDefaultTKIPKeyEntry (DWORD_PTR dwIoBase, unsigned int uKeyLen, - unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID) + unsigned int uKeyIdx, unsigned long *pdwKey, BYTE byLocalID) { WORD wOffset; DWORD dwData; diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 24e9b7ae6e15..0ded9a6d46d0 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -714,37 +714,37 @@ #define MACvGetCurrRx0DescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } #define MACvGetCurrRx1DescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } #define MACvGetCurrTx0DescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } #define MACvGetCurrAC0DescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } #define MACvGetCurrSyncDescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_SYNCDMAPTR, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } #define MACvGetCurrATIMDescAddr(dwIoBase, pdwCurrDescAddr) \ { \ VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR, \ - (PDWORD)pdwCurrDescAddr); \ + (unsigned long *)pdwCurrDescAddr); \ } \ // set the chip with current BCN tx descriptor address @@ -1140,14 +1140,14 @@ BOOL MACbFlushSYNCFifo(DWORD_PTR dwIoBase); BOOL MACbPSWakeup(DWORD_PTR dwIoBase); void MACvSetKeyEntry(DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, unsigned char *pbyAddr, PDWORD pdwKey, BYTE byLocalID); + unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, BYTE byLocalID); void MACvDisableKeyEntry(DWORD_PTR dwIoBase, unsigned int uEntryIdx); void MACvSetDefaultKeyEntry(DWORD_PTR dwIoBase, unsigned int uKeyLen, - unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID); + unsigned int uKeyIdx, unsigned long *pdwKey, BYTE byLocalID); //void MACvEnableDefaultKey(DWORD_PTR dwIoBase, BYTE byLocalID); void MACvDisableDefaultKey(DWORD_PTR dwIoBase); void MACvSetDefaultTKIPKeyEntry(DWORD_PTR dwIoBase, unsigned int uKeyLen, - unsigned int uKeyIdx, PDWORD pdwKey, BYTE byLocalID); + unsigned int uKeyIdx, unsigned long *pdwKey, BYTE byLocalID); void MACvSetDefaultKeyCtl(DWORD_PTR dwIoBase, WORD wKeyCtl, unsigned int uEntryIdx, BYTE byLocalID); #endif // __MAC_H__ diff --git a/drivers/staging/vt6655/michael.c b/drivers/staging/vt6655/michael.c index 2a346307f4db..74c66b56498e 100644 --- a/drivers/staging/vt6655/michael.c +++ b/drivers/staging/vt6655/michael.c @@ -159,7 +159,7 @@ void MIC_vAppend (unsigned char *src, unsigned int nBytes) } } -void MIC_vGetMIC (PDWORD pdwL, PDWORD pdwR) +void MIC_vGetMIC (unsigned long *pdwL, unsigned long *pdwR) { // Append the minimum padding s_vAppendByte(0x5a); diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h index ecb2912939c6..be399494aaa4 100644 --- a/drivers/staging/vt6655/michael.h +++ b/drivers/staging/vt6655/michael.h @@ -44,7 +44,7 @@ void MIC_vAppend(unsigned char *src, unsigned int nBytes); // Get the MIC result. Destination should accept 8 bytes of result. // This also resets the message to empty. -void MIC_vGetMIC(PDWORD pdwL, PDWORD pdwR); +void MIC_vGetMIC(unsigned long *pdwL, unsigned long *pdwR); /*--------------------- Export Macros ------------------------------*/ diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index f3051b10c136..478c140be11c 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -221,8 +221,8 @@ s_vFillTxKey ( unsigned char *pMICHDR ) { - PDWORD pdwIV = (PDWORD) pbyIVHead; - PDWORD pdwExtIV = (PDWORD) ((unsigned char *)pbyIVHead+4); + unsigned long *pdwIV = (unsigned long *) pbyIVHead; + unsigned long *pdwExtIV = (unsigned long *) ((unsigned char *)pbyIVHead+4); WORD wValue; PS802_11Header pMACHeader = (PS802_11Header)pbyHdrBuf; DWORD dwRevIVCounter; @@ -338,7 +338,7 @@ s_vSWencryption ( { unsigned int cbICVlen = 4; DWORD dwICV = 0xFFFFFFFFL; - PDWORD pdwICV; + unsigned long *pdwICV; if (pTransmitKey == NULL) return; @@ -347,7 +347,7 @@ s_vSWencryption ( //======================================================================= // Append ICV after payload dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) - pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); + pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize); // finally, we must invert dwCRC to get the correct answer *pdwICV = cpu_to_le32(~dwICV); // RC4 encryption @@ -358,7 +358,7 @@ s_vSWencryption ( //======================================================================= //Append ICV after payload dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) - pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); + pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize); // finally, we must invert dwCRC to get the correct answer *pdwICV = cpu_to_le32(~dwICV); // RC4 encryption @@ -1359,8 +1359,8 @@ s_cbFillTxBufHead ( unsigned int cbMICHDR = 0; DWORD dwMICKey0, dwMICKey1; DWORD dwMIC_Priority; - PDWORD pdwMIC_L; - PDWORD pdwMIC_R; + unsigned long *pdwMIC_L; + unsigned long *pdwMIC_R; DWORD dwSafeMIC_L, dwSafeMIC_R; //Fix "Last Frag Size" < "MIC length". BOOL bMIC2Frag = FALSE; unsigned int uMICFragLen = 0; @@ -1549,16 +1549,16 @@ s_cbFillTxBufHead ( ////////////////////////////////////////////////////////////////// if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { - dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); - dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]); } else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) { - dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); - dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]); } else { - dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[24]); - dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[28]); + dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[24]); + dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[28]); } // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); @@ -1760,8 +1760,8 @@ s_cbFillTxBufHead ( if (bMIC2Frag == FALSE) { if (uTmpLen != 0) MIC_vAppend((pbyBuffer + uLength), uTmpLen); - pdwMIC_L = (PDWORD)(pbyBuffer + uLength + uTmpLen); - pdwMIC_R = (PDWORD)(pbyBuffer + uLength + uTmpLen + 4); + pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen); + pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); } else { @@ -1895,8 +1895,8 @@ s_cbFillTxBufHead ( uMICFragLen = cbFragPayloadSize - uTmpLen; ASSERT(uMICFragLen < cbMIClen); - pdwMIC_L = (PDWORD)(pbyBuffer + uLength + uTmpLen); - pdwMIC_R = (PDWORD)(pbyBuffer + uLength + uTmpLen + 4); + pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen); + pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); dwSafeMIC_L = *pdwMIC_L; dwSafeMIC_R = *pdwMIC_R; @@ -2035,8 +2035,8 @@ s_cbFillTxBufHead ( MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFrameBodySize); - pdwMIC_L = (PDWORD)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize); - pdwMIC_R = (PDWORD)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize + 4); + pdwMIC_L = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize); + pdwMIC_R = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); MIC_vUnInit(); @@ -2852,8 +2852,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un unsigned int uLength = 0; DWORD dwMICKey0, dwMICKey1; DWORD dwMIC_Priority; - PDWORD pdwMIC_L; - PDWORD pdwMIC_R; + unsigned long *pdwMIC_L; + unsigned long *pdwMIC_R; WORD wTxBufSize; unsigned int cbMacHdLen; SEthernetHeader sEthHeader; @@ -3127,8 +3127,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { - dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); - dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]); // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); @@ -3141,8 +3141,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize); - pdwMIC_L = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize); - pdwMIC_R = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4); + pdwMIC_L = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize); + pdwMIC_R = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); MIC_vUnInit(); diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index cd4895ea45f6..26f7a9ca60aa 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -364,7 +364,7 @@ void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress) * Return Value: none * */ -void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId) +void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, unsigned long *pdwSubSysVenId) { unsigned char *pbyData; diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index d51791491751..53e3f596a33f 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -150,7 +150,7 @@ void SROMvWriteAllContents(DWORD_PTR dwIoBase, unsigned char *pbyEepromRegs); void SROMvReadEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress); void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, unsigned char *pbyEtherAddress); -void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId); +void SROMvReadSubSysVenId(DWORD_PTR dwIoBase, unsigned long *pdwSubSysVenId); BOOL SROMbAutoLoad (DWORD_PTR dwIoBase); diff --git a/drivers/staging/vt6655/tether.c b/drivers/staging/vt6655/tether.c index baf373931b6c..f654a718279a 100644 --- a/drivers/staging/vt6655/tether.c +++ b/drivers/staging/vt6655/tether.c @@ -101,7 +101,7 @@ BOOL ETHbIsBufferCrc32Ok (unsigned char *pbyBuffer, unsigned int cbFrameLength) DWORD dwCRC; dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4); - if (cpu_to_le32(*((PDWORD)(pbyBuffer + cbFrameLength - 4))) != dwCRC) { + if (cpu_to_le32(*((unsigned long *)(pbyBuffer + cbFrameLength - 4))) != dwCRC) { return FALSE; } return TRUE; diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h index 660bc5b20894..aaad1dbd957d 100644 --- a/drivers/staging/vt6655/ttype.h +++ b/drivers/staging/vt6655/ttype.h @@ -92,8 +92,6 @@ typedef unsigned long DWORD_PTR; // 32-bit // boolean pointer typedef unsigned int * PUINT; -typedef DWORD * PDWORD; - typedef QWORD * PQWORD; #endif // __TTYPE_H__ diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index ecf683feca39..7abd231c4d57 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -87,7 +87,7 @@ } #define VNSvInPortD(dwIOAddress, pdwData) { \ - volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress)); \ + volatile DWORD* pdwAddr = ((unsigned long *)(dwIOAddress)); \ *(pdwData) = readl(pdwAddr); \ } @@ -104,7 +104,7 @@ } #define VNSvOutPortD(dwIOAddress, dwData) { \ - volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress)); \ + volatile DWORD* pdwAddr = ((unsigned long *)(dwIOAddress)); \ writel((DWORD)dwData, pdwAddr); \ } -- cgit v1.2.3 From cf160bc9269fecba0a10e9957e8591fcc293dddf Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Thu, 3 Jun 2010 09:15:54 -0700 Subject: Staging: vt6655: include linux/ headers instead of asm/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 56e05f0fa963..9e236f745ce5 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -48,10 +48,10 @@ #include #include #include -#include +#include #include //#include -#include +#include #include #include #include -- cgit v1.2.3 From afb97d9a265f6001411df43d3ea523338c73c83f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Jun 2010 10:30:21 -0700 Subject: Staging: vt6655: fix up U32 conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 902d2411298a6e0b8a473a0163aa4bf6d5c8a073 converted U32 to u32 which you would think would be just fine. Unfortunatly, it seems that VIA only builds their code on a 32bit processor (which makes sense if you think about it), but this doesn't work on x86-64. So fix up the few places where this really wanted to be an unsigned long width. Cc: Charles Clément Cc: Forest Bond , Cc: Andres More Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device.h | 2 +- drivers/staging/vt6655/iwctl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 9e236f745ce5..bad32562a7fb 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -423,7 +423,7 @@ typedef struct __device_info { CHIP_TYPE chip_id; - u32 PortOffset; + unsigned long PortOffset; DWORD dwIsr; u32 memaddr; u32 ioaddr; diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index a2b2bc5d4341..f3545071151c 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -116,7 +116,7 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.discard.nwid = 0; pDevice->wstats.discard.code = 0; pDevice->wstats.discard.fragment = 0; - pDevice->wstats.discard.retries = (u32)pDevice->scStatistic.dwTsrErr; + pDevice->wstats.discard.retries = (unsigned long)pDevice->scStatistic.dwTsrErr; pDevice->wstats.discard.misc = 0; pDevice->wstats.miss.beacon = 0; -- cgit v1.2.3 From 33d33e42b647095b01b1223c7b88718584129d2e Mon Sep 17 00:00:00 2001 From: Andres More Date: Wed, 19 May 2010 23:50:00 -0300 Subject: Staging: vt6656: code cleanup, fixed 'for' statements Resolved checkpatch findings, but some long lines warnings. ERROR: space required before the open parenthesis '(' ERROR: spaces required around that Signed-off-by: Andres More Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.c | 70 ++++++++++++++++++++++----------------- drivers/staging/vt6656/card.c | 7 ++-- drivers/staging/vt6656/channel.c | 45 ++++++++++++------------- drivers/staging/vt6656/datarate.c | 10 +++--- drivers/staging/vt6656/dpc.c | 9 ++--- drivers/staging/vt6656/ioctl.c | 6 ++-- drivers/staging/vt6656/iwctl.c | 24 +++++++------- drivers/staging/vt6656/key.c | 22 +++++------- drivers/staging/vt6656/mac.c | 4 +-- drivers/staging/vt6656/main_usb.c | 30 ++++++++--------- drivers/staging/vt6656/michael.c | 4 +-- drivers/staging/vt6656/wctl.c | 21 ++++++------ drivers/staging/vt6656/wmgr.c | 58 ++++++++++++++++---------------- drivers/staging/vt6656/wpa.c | 6 ++-- drivers/staging/vt6656/wpactl.c | 5 ++- 15 files changed, 161 insertions(+), 160 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index 36ed61b595ca..8d4b6633b96b 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -699,12 +699,14 @@ BOOL BSSbUpdateToBSSList(void *hDeviceContext, pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; ldBmSum = 0; - for(ii=0, jj=0;iildBmAverage[ii] != 0) { - pBSSList->ldBmMAX = max(pBSSList->ldBmAverage[ii], ldBm); - ldBmSum += pBSSList->ldBmAverage[ii]; - jj++; - } + for (ii = 0, jj = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pBSSList->ldBmAverage[ii] != 0) { + pBSSList->ldBmMAX = + max(pBSSList->ldBmAverage[ii], ldBm); + ldBmSum += + pBSSList->ldBmAverage[ii]; + jj++; + } } pBSSList->ldBmAverRange = ldBmSum /jj; } @@ -1422,21 +1424,25 @@ void BSSvUpdateNodeTxCounter(void *hDeviceContext, (wRate < RATE_18M) ) { pMgmt->sNodeDBTable[0].uTxFail[wRate]+=byTxRetry; } else if (byFallBack == AUTO_FB_0) { - for(ii=0;iisNodeDBTable[0].uTxFail[wFallBackRate]++; - } + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry0[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry0[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } } else if (byFallBack == AUTO_FB_1) { - for(ii=0;iisNodeDBTable[0].uTxFail[wFallBackRate]++; - } + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry1[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry1[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } } } }; @@ -1476,21 +1482,23 @@ void BSSvUpdateNodeTxCounter(void *hDeviceContext, (wRate < RATE_18M) ) { pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wRate]+=byTxRetry; } else if (byFallBack == AUTO_FB_0) { - for(ii=0;iisNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry0[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry0[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; } } else if (byFallBack == AUTO_FB_1) { - for(ii=0;iisNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; - } + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + } } } }; diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index fe4ec913ffea..35bf4fda330d 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -457,12 +457,11 @@ void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType) abyData[14] = abySignal[3]; abyData[15] = abyServ[3]; - for(i=0;i<9;i++) { - abyData[16+i*2] = abyTxRate[i]; - abyData[16+i*2+1] = abyRsvTime[i]; + for (i = 0; i < 9; i++) { + abyData[16+i*2] = abyTxRate[i]; + abyData[16+i*2+1] = abyRsvTime[i]; } - CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index f49b6e133394..6ad03e492edb 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -441,11 +441,10 @@ void CHvInitChannelTable(void *pDeviceHandler) { PSDevice pDevice = (PSDevice) pDeviceHandler; BOOL bMultiBand = FALSE; - unsigned int ii; + unsigned int ii; - for(ii=1;ii<=CB_MAX_CHANNEL;ii++) { - sChannelTbl[ii].bValid = FALSE; - } + for (ii = 1; ii <= CB_MAX_CHANNEL; ii++) + sChannelTbl[ii].bValid = FALSE; switch (pDevice->byRFType) { case RF_AL2230: @@ -464,43 +463,43 @@ void CHvInitChannelTable(void *pDeviceHandler) if ((pDevice->dwDiagRefCount != 0) || (pDevice->b11hEable == TRUE)) { if (bMultiBand == TRUE) { - for(ii=0;iiabyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; //pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; - } - for(ii=0;iiabyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; //pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; - } + } } else { - for(ii=0;iiabyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; //pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; - } + } } } else if (pDevice->byZoneType <= CCODE_MAX) { if (bMultiBand == TRUE) { - for(ii=0;iibyZoneType].bChannelIdxList[ii] != 0) { - sChannelTbl[ii+1].bValid = TRUE; + for (ii = 0; ii < CB_MAX_CHANNEL; ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = TRUE; //pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; //pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; - } - } + } + } } else { - for(ii=0;iibyZoneType].bChannelIdxList[ii] != 0) { - sChannelTbl[ii+1].bValid = TRUE; + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = TRUE; //pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; //pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; - } - } + } + } } } DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO"Zone=[%d][%c][%c]!!\n",pDevice->byZoneType,ChannelRuleTab[pDevice->byZoneType].chCountryCode[0],ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]); - for(ii=0;iiabyRegPwr[ii+1] == 0) { pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; diff --git a/drivers/staging/vt6656/datarate.c b/drivers/staging/vt6656/datarate.c index 2e183ddbfd0e..51dc540da2fb 100644 --- a/drivers/staging/vt6656/datarate.c +++ b/drivers/staging/vt6656/datarate.c @@ -72,7 +72,7 @@ void s_vResetCounter(PKnownNodeDB psNodeDBTable) BYTE ii; // clear statistic counter for auto_rate - for(ii=0;ii<=MAX_RATE;ii++) { + for (ii = 0; ii <= MAX_RATE; ii++) { psNodeDBTable->uTxOk[ii] = 0; psNodeDBTable->uTxFail[ii] = 0; } @@ -337,7 +337,7 @@ DWORD dwTxDiff = 0; psNodeDBTable->uTimeCount = 0; } - for(ii=0;iiwSuppRate & (0x0001<wTxDataRate;ii++) { + for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) { if ( (psNodeDBTable->uTxOk[ii] != 0) || (psNodeDBTable->uTxFail[ii] != 0) ) { dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii]; @@ -362,7 +362,7 @@ DWORD dwTxDiff = 0; dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; wIdxDownRate = psNodeDBTable->wTxDataRate; - for(ii = psNodeDBTable->wTxDataRate; ii > 0;) { + for (ii = psNodeDBTable->wTxDataRate; ii > 0;) { ii--; if ( (dwThroughputTbl[ii] > dwThroughput) && (bAutoRate[ii]==TRUE) ) { @@ -400,7 +400,7 @@ long ldBm; return; } - for(ii=0;iiwSuppRate & (0x0001<pCurrBSS->byRSSIStatCnt++; pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; - for(ii=0;iipCurrBSS->ldBmAverage[ii] != 0) { - pMgmt->pCurrBSS->ldBmMAX = max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); - } + for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { + pMgmt->pCurrBSS->ldBmMAX = + max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); + } } } */ diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c index 19a84b66b097..7c32125fbd51 100644 --- a/drivers/staging/vt6656/ioctl.c +++ b/drivers/staging/vt6656/ioctl.c @@ -232,10 +232,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) { pDevice->bEncryptionEnable = FALSE; pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; spin_lock_irq(&pDevice->lock); - for(uu=0;uulock); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable. \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable.\n"); break; } diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index fa40522d4a9a..8f28dbb8de53 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -653,7 +653,7 @@ int iwctl_giwrange(struct net_device *dev, // Should be based on cap_rid.country to give only // what the current card support k = 0; - for(i = 0; i < 14; i++) { + for (i = 0; i < 14; i++) { range->freq[k].i = i + 1; // List index range->freq[k].m = frequency_list[i] * 100000; range->freq[k++].e = 1; // Values in table in MHz -> * 10^5 * 10 @@ -669,7 +669,7 @@ int iwctl_giwrange(struct net_device *dev, range->max_qual.noise = 0; range->sensitivity = 255; - for(i = 0 ; i < 13 ; i++) { + for (i = 0 ; i < 13 ; i++) { range->bitrate[i] = abySupportedRates[i] * 500000; if(range->bitrate[i] == 0) break; @@ -1057,7 +1057,7 @@ int iwctl_siwrate(struct net_device *dev, u8 normvalue = (u8) (wrq->value/500000); // Check if rate is valid - for(i = 0 ; i < 13 ; i++) { + for (i = 0 ; i < 13 ; i++) { if(normvalue == abySupportedRates[i]) { brate = i; break; @@ -1067,7 +1067,7 @@ int iwctl_siwrate(struct net_device *dev, // -1 designed the max rate (mostly auto mode) if(wrq->value == -1) { // Get the highest available rate - for(i = 0 ; i < 13 ; i++) { + for (i = 0 ; i < 13 ; i++) { if(abySupportedRates[i] == 0) break; } @@ -1405,8 +1405,8 @@ int iwctl_siwencode(struct net_device *dev, pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; if (pDevice->flags & DEVICE_FLAGS_OPENED) { spin_lock_irq(&pDevice->lock); - for(uu=0;uulock); } } @@ -1935,14 +1935,14 @@ printk("param->u.wpa_key.set_tx =%d\n",param->u.wpa_key.set_tx); printk("param->u.wpa_key.key_index =%d\n",param->u.wpa_key.key_index); printk("param->u.wpa_key.key_len =%d\n",param->u.wpa_key.key_len); printk("param->u.wpa_key.key ="); -for(ii=0;iiu.wpa_key.key_len;ii++) - printk("%02x:",param->u.wpa_key.key[ii]); - printk("\n"); +for (ii = 0; ii < param->u.wpa_key.key_len; ii++) + printk(KERN_DEBUG "%02x:", param->u.wpa_key.key[ii]); +printk("\n"); printk("param->u.wpa_key.seq_len =%d\n",param->u.wpa_key.seq_len); printk("param->u.wpa_key.seq ="); -for(ii=0;iiu.wpa_key.seq_len;ii++) - printk("%02x:",param->u.wpa_key.seq[ii]); - printk("\n"); +for (ii = 0; ii < param->u.wpa_key.seq_len; ii++) + printk(KERN_DEBUG "%02x:", param->u.wpa_key.seq[ii]); +printk("\n"); printk("...........\n"); #endif diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index b0890c181e7d..6a77ce35e708 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -485,9 +485,9 @@ BOOL KeybRemoveAllKey( if ((pTable->KeyTable[i].bInUse == TRUE) && IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; - for(u=0;uKeyTable[i].GroupKey[u].bKeyValid = FALSE; - } + for (u = 0; u < MAX_GROUP_KEY; u++) + pTable->KeyTable[i].GroupKey[u].bKeyValid = FALSE; + pTable->KeyTable[i].dwGTKeyIndex = 0; s_vCheckKeyTableValid(pDevice, pTable); return (TRUE); @@ -531,19 +531,13 @@ void KeyvRemoveWEPKey( return; } -void KeyvRemoveAllWEPKey( - void *pDeviceHandler, - PSKeyManagement pTable - ) +void KeyvRemoveAllWEPKey(void *pDeviceHandler, PSKeyManagement pTable) { - PSDevice pDevice = (PSDevice) pDeviceHandler; - - int i; - - for(i=0;i>8); pbyData[6] = (BYTE)(dwData2>>16); pbyData[7] = (BYTE)(dwData2>>24); - for(ii=8;ii<24;ii++) - pbyData[ii] = *pbyKey++; + for (ii = 8; ii < 24; ii++) + pbyData[ii] = *pbyKey++; CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_SETKEY, diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 098b0455e325..804047d4a448 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -407,8 +407,8 @@ static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) sInitCmd.byInitClass = (BYTE)InitType; sInitCmd.bExistSWNetAddr = (BYTE) pDevice->bExistSWNetAddr; - for(ii=0;ii<6;ii++) - sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii]; + for (ii = 0; ii < 6; ii++) + sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii]; sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit; sInitCmd.byLongRetryLimit = pDevice->byLongRetryLimit; @@ -487,10 +487,10 @@ static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&& (pDevice->byOriginalZonetype == ZoneType_USA)) { - for(ii=11;ii<14;ii++) { - pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; - pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; - } + for (ii = 11; ii < 14; ii++) { + pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; + pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; + } } //{{ RobertYu: 20041124 @@ -1234,10 +1234,10 @@ device_release_WPADEV(pDevice); pMgmt->bShareKeyAlgorithm = FALSE; pDevice->bEncryptionEnable = FALSE; pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; - spin_lock_irq(&pDevice->lock); - for(uu=0;uulock); + for (uu = 0; uu < MAX_KEY_TABLE; uu++) MACvDisableKeyEntry(pDevice,uu); - spin_unlock_irq(&pDevice->lock); + spin_unlock_irq(&pDevice->lock); if ((pDevice->flags & DEVICE_FLAGS_UNPLUG) == FALSE) { MACbShutdown(pDevice); @@ -1447,12 +1447,12 @@ static int Config_FileGetParameter(unsigned char *string, return FALSE; //check if current config line is marked by "#" ?? -for(ii=1;;ii++) { - if(memcmp(start_p-ii,"\n",1)==0) - break; - if(memcmp(start_p-ii,"#",1)==0) - return FALSE; -} + for (ii = 1; ; ii++) { + if (memcmp(start_p - ii, "\n", 1) == 0) + break; + if (memcmp(start_p - ii, "#", 1) == 0) + return FALSE; + } //find target string end point end_p = kstrstr(start_p,"\n"); diff --git a/drivers/staging/vt6656/michael.c b/drivers/staging/vt6656/michael.c index 671a8cf33e23..4d419814f27f 100644 --- a/drivers/staging/vt6656/michael.c +++ b/drivers/staging/vt6656/michael.c @@ -74,7 +74,7 @@ static DWORD s_dwGetUINT32 (BYTE * p) { DWORD res = 0; unsigned int i; - for(i=0; i<4; i++ ) + for (i = 0; i < 4; i++) res |= (*p++) << (8*i); return res; } @@ -83,7 +83,7 @@ static void s_vPutUINT32(BYTE *p, DWORD val) // Convert from DWORD to BYTE[] in a portable way { unsigned int i; - for(i=0; i<4; i++ ) { + for (i = 0; i < 4; i++) { *p++ = (BYTE) (val & 0xff); val >>= 8; } diff --git a/drivers/staging/vt6656/wctl.c b/drivers/staging/vt6656/wctl.c index 857ce0bc00a4..0a41bbe24e6c 100644 --- a/drivers/staging/vt6656/wctl.c +++ b/drivers/staging/vt6656/wctl.c @@ -111,22 +111,21 @@ BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader) * Return Value: index number in Defragment Database * */ + unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader) { unsigned int ii; - for(ii=0;iicbDFCB;ii++) { - if ((pDevice->sRxDFCB[ii].bInUse == TRUE) && - (IS_ETH_ADDRESS_EQUAL (&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]))) - ) { - // - return(ii); - } - } - return(pDevice->cbDFCB); + for (ii = 0; ii < pDevice->cbDFCB; ii++) { + if ((pDevice->sRxDFCB[ii].bInUse == TRUE) && + (IS_ETH_ADDRESS_EQUAL(&(pDevice->sRxDFCB[ii].abyAddr2[0]), + &(pMACHeader->abyAddr2[0])))) { + return ii; + } + } + return pDevice->cbDFCB; } - /* * Description: * Insert received fragment packet in Defragment Database @@ -147,7 +146,7 @@ unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader) if (pDevice->cbFreeDFCB == 0) return(pDevice->cbDFCB); - for(ii=0;iicbDFCB;ii++) { + for (ii = 0; ii < pDevice->cbDFCB; ii++) { if (pDevice->sRxDFCB[ii].bInUse == FALSE) { pDevice->cbFreeDFCB--; pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime; diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c index 93c15f0580fe..2bca1589ddb1 100644 --- a/drivers/staging/vt6656/wmgr.c +++ b/drivers/staging/vt6656/wmgr.c @@ -353,9 +353,9 @@ void vMgrObjectInit(void *hDeviceContext) pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0]; pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0]; pMgmt->uCurrChannel = pDevice->uChannel; - for(ii=0;iiabyDesireBSSID[ii] = 0xFF; - } + for (ii = 0; ii < WLAN_BSSID_LEN; ii++) + pMgmt->abyDesireBSSID[ii] = 0xFF; + pMgmt->sAssocInfo.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); //memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN +1); pMgmt->byCSSPK = KEY_CTL_NONE; @@ -4795,21 +4795,21 @@ s_bCipherMatch ( byMulticastCipher = KEY_CTL_INVALID; } - // check Pairwise Key Cipher - for(i=0;iwCSSPKCount;i++) { - if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) || - (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) { - // this should not happen as defined 802.11i - byCipherMask |= 0x01; - } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) { - byCipherMask |= 0x02; - } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) { - byCipherMask |= 0x04; - } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) { - // use group key only ignore all others - byCipherMask = 0; - i = pBSSNode->wCSSPKCount; - } + /* check Pairwise Key Cipher */ + for (i = 0; i < pBSSNode->wCSSPKCount; i++) { + if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) || + (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) { + /* this should not happen as defined 802.11i */ + byCipherMask |= 0x01; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) { + /* use group key only ignore all others */ + byCipherMask = 0; + i = pBSSNode->wCSSPKCount; + } } } else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && @@ -4828,17 +4828,17 @@ s_bCipherMatch ( byMulticastCipher = KEY_CTL_INVALID; } - // check Pairwise Key Cipher - for(i=0;iwPKCount;i++) { - if (pBSSNode->abyPKType[i] == WPA_TKIP) { - byCipherMask |= 0x02; - } else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) { - byCipherMask |= 0x04; - } else if (pBSSNode->abyPKType[i] == WPA_NONE) { - // use group key only ignore all others - byCipherMask = 0; - i = pBSSNode->wPKCount; - } + /* check Pairwise Key Cipher */ + for (i = 0; i < pBSSNode->wPKCount; i++) { + if (pBSSNode->abyPKType[i] == WPA_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyPKType[i] == WPA_NONE) { + /* use group key only ignore all others */ + byCipherMask = 0; + i = pBSSNode->wPKCount; + } } } diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c index 1fa6c9b88ed3..f492778ee8b6 100644 --- a/drivers/staging/vt6656/wpa.c +++ b/drivers/staging/vt6656/wpa.c @@ -148,7 +148,8 @@ WPA_ParseRSN ( { j = 0; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); - for(i = 0; (i < pRSN->wPKCount) && (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) { + for (i = 0; (i < pRSN->wPKCount) && + (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) { if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) pBSSList->abyPKType[j++] = WPA_NONE; @@ -180,7 +181,8 @@ WPA_ParseRSN ( j = 0; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n", pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType)); - for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) { + for (i = 0; (i < pIE_RSN_Auth->wAuthCount) && + (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) { if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4)) pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X; diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c index 961f583368a1..c886722a54bc 100644 --- a/drivers/staging/vt6656/wpactl.c +++ b/drivers/staging/vt6656/wpactl.c @@ -186,7 +186,6 @@ int wpa_set_wpadev(PSDevice pDevice, int val) return wpa_release_wpadev(pDevice); } - /* * Description: * Set WPA algorithm & keys @@ -647,9 +646,9 @@ static int wpa_get_scan(PSDevice pDevice, for (ii = 0; ii < MAX_BSS_NUM; ii++) { - for(jj=0;jjsBSSList[jj].bActive!=TRUE) || + if ((pMgmt->sBSSList[jj].bActive != TRUE) || ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=FALSE))) { -- cgit v1.2.3 From d9d1ccb51f60cc211e0aa8d132bc3487053b2b1d Mon Sep 17 00:00:00 2001 From: Andres More Date: Wed, 26 May 2010 20:00:36 -0300 Subject: Staging: vt6656: code cleanup, resolved checkpatch findings in headers Resolved whitespace-related checkpatch findings in .h files Signed-off-by: Andres More Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/80211mgr.h | 31 +++++---------- drivers/staging/vt6656/baseband.h | 19 ++++----- drivers/staging/vt6656/bssdb.h | 8 ++-- drivers/staging/vt6656/channel.h | 12 +++--- drivers/staging/vt6656/control.h | 14 +++---- drivers/staging/vt6656/desc.h | 79 +++++++++++++++++-------------------- drivers/staging/vt6656/device.h | 42 ++++++-------------- drivers/staging/vt6656/device_cfg.h | 16 +++----- drivers/staging/vt6656/int.h | 2 +- drivers/staging/vt6656/iocmd.h | 14 +++---- drivers/staging/vt6656/iowpa.h | 47 ++++++++-------------- drivers/staging/vt6656/iwctl.h | 4 +- drivers/staging/vt6656/mac.h | 8 ++-- drivers/staging/vt6656/mib.h | 14 +++---- drivers/staging/vt6656/michael.h | 6 +-- drivers/staging/vt6656/rf.h | 19 ++------- drivers/staging/vt6656/rndis.h | 2 +- drivers/staging/vt6656/tether.h | 6 +-- drivers/staging/vt6656/ttype.h | 2 +- drivers/staging/vt6656/wmgr.h | 2 +- drivers/staging/vt6656/wpa2.h | 18 ++------- 21 files changed, 136 insertions(+), 229 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/80211mgr.h b/drivers/staging/vt6656/80211mgr.h index c140a957d9df..7f939e3bf175 100644 --- a/drivers/staging/vt6656/80211mgr.h +++ b/drivers/staging/vt6656/80211mgr.h @@ -222,46 +222,39 @@ #define MEASURE_MODE_INCAPABLE 0x02 #define MEASURE_MODE_REFUSED 0x04 - - /*--------------------- Export Classes ----------------------------*/ /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Types ------------------------------*/ - // Information Element Types #pragma pack(1) typedef struct tagWLAN_IE { BYTE byElementID; BYTE len; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE, *PWLAN_IE; - // Service Set Identity (SSID) #pragma pack(1) typedef struct tagWLAN_IE_SSID { BYTE byElementID; BYTE len; BYTE abySSID[1]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_SSID, *PWLAN_IE_SSID; - // Supported Rates #pragma pack(1) typedef struct tagWLAN_IE_SUPP_RATES { BYTE byElementID; BYTE len; BYTE abyRates[1]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_SUPP_RATES, *PWLAN_IE_SUPP_RATES; - - // FH Parameter Set #pragma pack(1) typedef struct _WLAN_IE_FH_PARMS { @@ -279,10 +272,9 @@ typedef struct tagWLAN_IE_DS_PARMS { BYTE byElementID; BYTE len; BYTE byCurrChannel; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_DS_PARMS, *PWLAN_IE_DS_PARMS; - // CF Parameter Set #pragma pack(1) typedef struct tagWLAN_IE_CF_PARMS { @@ -292,10 +284,9 @@ typedef struct tagWLAN_IE_CF_PARMS { BYTE byCFPPeriod; WORD wCFPMaxDuration; WORD wCFPDurRemaining; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_CF_PARMS, *PWLAN_IE_CF_PARMS; - // TIM #pragma pack(1) typedef struct tagWLAN_IE_TIM { @@ -305,30 +296,27 @@ typedef struct tagWLAN_IE_TIM { BYTE byDTIMPeriod; BYTE byBitMapCtl; BYTE byVirtBitMap[1]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_TIM, *PWLAN_IE_TIM; - // IBSS Parameter Set #pragma pack(1) typedef struct tagWLAN_IE_IBSS_PARMS { BYTE byElementID; BYTE len; WORD wATIMWindow; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_IBSS_PARMS, *PWLAN_IE_IBSS_PARMS; - // Challenge Text #pragma pack(1) typedef struct tagWLAN_IE_CHALLENGE { BYTE byElementID; BYTE len; BYTE abyChallenge[1]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_CHALLENGE, *PWLAN_IE_CHALLENGE; - #pragma pack(1) typedef struct tagWLAN_IE_RSN_EXT { BYTE byElementID; @@ -391,10 +379,9 @@ typedef struct tagWLAN_IE_ERP { BYTE byElementID; BYTE len; BYTE byContext; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) WLAN_IE_ERP, *PWLAN_IE_ERP; - #pragma pack(1) typedef struct _MEASEURE_REQ { BYTE byChannel; diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index bc4633d5fead..8db8cd07d5f5 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -104,16 +104,13 @@ BBuGetFrameTime( WORD wRate ); -void -BBvCaculateParameter ( - PSDevice pDevice, - unsigned int cbFrameLength, - WORD wRate, - BYTE byPacketType, - PWORD pwPhyLen, - PBYTE pbyPhySrv, - PBYTE pbyPhySgn - ); +void BBvCaculateParameter(PSDevice pDevice, + unsigned int cbFrameLength, + WORD wRate, + BYTE byPacketType, + PWORD pwPhyLen, + PBYTE pbyPhySrv, + PBYTE pbyPhySgn); // timer for antenna diversity @@ -128,7 +125,7 @@ void BBvSoftwareReset(PSDevice pDevice); void BBvSetShortSlotTime(PSDevice pDevice); void BBvSetVGAGainOffset(PSDevice pDevice, BYTE byData); void BBvSetAntennaMode(PSDevice pDevice, BYTE byAntennaMode); -BOOL BBbVT3184Init (PSDevice pDevice); +BOOL BBbVT3184Init(PSDevice pDevice); void BBvSetDeepSleep(PSDevice pDevice); void BBvExitDeepSleep(PSDevice pDevice); void BBvUpdatePreEDThreshold( diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index 9686d8600d63..c3aaefec93e3 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -40,7 +40,7 @@ #define MAX_NODE_NUM 64 #define MAX_BSS_NUM 42 -#define LOST_BEACON_COUNT 10 // 10 sec, XP defined +#define LOST_BEACON_COUNT 10 /* 10 sec, XP defined */ #define MAX_PS_TX_BUF 32 // sta max power saving tx buf #define ADHOC_LOST_BEACON_COUNT 30 // 30 sec, beacon lost for adhoc only #define MAX_INACTIVE_COUNT 300 // 300 sec, inactive STA node refresh @@ -83,13 +83,13 @@ typedef struct tagSERPObject { BOOL bERPExist; BYTE byERP; -}ERPObject, *PERPObject; +} ERPObject, *PERPObject; typedef struct tagSRSNCapObject { BOOL bRSNCapExist; WORD wRSNCap; -}SRSNCapObject, *PSRSNCapObject; +} SRSNCapObject, *PSRSNCapObject; // BSS info(AP) #pragma pack(1) @@ -153,7 +153,7 @@ typedef struct tagKnownBSS { SRSNCapObject sRSNCapObj; BYTE abyIEs[1024]; // don't move this field !! -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) KnownBSS , *PKnownBSS; diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h index 91c2ffc6f1f0..e7b3c1231825 100644 --- a/drivers/staging/vt6656/channel.h +++ b/drivers/staging/vt6656/channel.h @@ -35,23 +35,21 @@ /*--------------------- Export Definitions -------------------------*/ /*--------------------- Export Classes ----------------------------*/ + typedef struct tagSChannelTblElement { BYTE byChannelNumber; unsigned int uFrequency; BOOL bValid; -}SChannelTblElement, *PSChannelTblElement; +} SChannelTblElement, *PSChannelTblElement; /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Functions --------------------------*/ + BOOL ChannelValid(unsigned int CountryCode, unsigned int ChannelNum); void CHvInitChannelTable(void *pDeviceHandler); BYTE CHbyGetChannelMapping(BYTE byChannelNumber); -BOOL -CHvChannelGetList ( - unsigned int uCountryCodeIdx, - PBYTE pbyChannelTable - ); +BOOL CHvChannelGetList(unsigned int uCountryCodeIdx, PBYTE pbyChannelTable); -#endif /* _REGULATE_H_ */ +#endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6656/control.h b/drivers/staging/vt6656/control.h index 146b450e13d0..bbe610fd8b5a 100644 --- a/drivers/staging/vt6656/control.h +++ b/drivers/staging/vt6656/control.h @@ -36,16 +36,14 @@ /*--------------------- Export Definitions -------------------------*/ +#define CONTROLnsRequestOut(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlOut(Device, Request, Value, Index, Length, Buffer) -#define CONTROLnsRequestOut( Device,Request,Value,Index,Length,Buffer) \ - PIPEnsControlOut( Device,Request,Value,Index,Length,Buffer) - -#define CONTROLnsRequestOutAsyn( Device,Request,Value,Index,Length,Buffer) \ - PIPEnsControlOutAsyn( Device,Request,Value,Index,Length,Buffer) - -#define CONTROLnsRequestIn( Device,Request,Value,Index,Length,Buffer) \ - PIPEnsControlIn( Device,Request,Value,Index,Length,Buffer) +#define CONTROLnsRequestOutAsyn(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlOutAsyn(Device, Request, Value, Index, Length, Buffer) +#define CONTROLnsRequestIn(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlIn(Device, Request, Value, Index, Length, Buffer) /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index 07f794ec6db2..767112b3c4a9 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -51,7 +51,6 @@ #define MAX_INTERRUPT_SIZE 32 - #define RX_BLOCKS 64 // form 0x60 to 0xA0 #define TX_BLOCKS 32 // from 0xA0 to 0xC0 @@ -63,8 +62,6 @@ #define CB_RD_NUM 64 // default # of RD #define CB_TD_NUM 64 // default # of TD - - // // Bits in the RSR register // @@ -87,7 +84,6 @@ #define NEWRSR_BCNHITAID 0x02 // 0000 0010 #define NEWRSR_BCNHITAID0 0x01 // 0000 0001 - // // Bits in the TSR register // @@ -96,17 +92,13 @@ #define TSR_ACKDATA 0x02 // 0000 0010 #define TSR_VALID 0x01 // 0000 0001 - #define CB_PROTOCOL_RESERVED_SECTION 16 - - // if retrys excess 15 times , tx will abort, and // if tx fifo underflow, tx will fail // we should try to resend it #define CB_MAX_TX_ABORT_RETRY 3 - #define FIFOCTL_AUTO_FB_1 0x1000 // 0001 0000 0000 0000 #define FIFOCTL_AUTO_FB_0 0x0800 // 0000 1000 0000 0000 #define FIFOCTL_GRPACK 0x0400 // 0000 0100 0000 0000 @@ -137,7 +129,6 @@ #define FRAGCTL_STAFRAG 0x0001 // 0000 0000 0000 0001 #define FRAGCTL_NONFRAG 0x0000 // 0000 0000 0000 0000 - //#define TYPE_AC0DMA 0 //#define TYPE_TXDMA0 1 #define TYPE_TXDMA0 0 @@ -152,8 +143,6 @@ #define TYPE_RXDMA1 1 #define TYPE_MAXRD 2 - - // TD_INFO flags control bit #define TD_FLAGS_NETIF_SKB 0x01 // check if need release skb #define TD_FLAGS_PRIV_SKB 0x02 // check if called from private skb(hostap) @@ -162,7 +151,6 @@ /*--------------------- Export Types ------------------------------*/ - // // RsvTime buffer header // @@ -173,8 +161,9 @@ typedef struct tagSRrvTime_gRTS { WORD wReserved; WORD wTxRrvTime_b; WORD wTxRrvTime_a; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRrvTime_gRTS, *PSRrvTime_gRTS; + typedef const SRrvTime_gRTS *PCSRrvTime_gRTS; typedef struct tagSRrvTime_gCTS { @@ -182,22 +171,25 @@ typedef struct tagSRrvTime_gCTS { WORD wReserved; WORD wTxRrvTime_b; WORD wTxRrvTime_a; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRrvTime_gCTS, *PSRrvTime_gCTS; + typedef const SRrvTime_gCTS *PCSRrvTime_gCTS; typedef struct tagSRrvTime_ab { WORD wRTSTxRrvTime; WORD wTxRrvTime; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRrvTime_ab, *PSRrvTime_ab; + typedef const SRrvTime_ab *PCSRrvTime_ab; typedef struct tagSRrvTime_atim { WORD wCTSTxRrvTime_ba; WORD wTxRrvTime_a; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRrvTime_atim, *PSRrvTime_atim; + typedef const SRrvTime_atim *PCSRrvTime_atim; // @@ -208,8 +200,9 @@ typedef struct tagSRTSData { WORD wDurationID; BYTE abyRA[ETH_ALEN]; BYTE abyTA[ETH_ALEN]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRTSData, *PSRTSData; + typedef const SRTSData *PCSRTSData; typedef struct tagSRTS_g { @@ -224,11 +217,10 @@ typedef struct tagSRTS_g { WORD wDuration_bb; WORD wReserved; SRTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRTS_g, *PSRTS_g; typedef const SRTS_g *PCSRTS_g; - typedef struct tagSRTS_g_FB { BYTE bySignalField_b; BYTE byServiceField_b; @@ -245,10 +237,10 @@ typedef struct tagSRTS_g_FB { WORD wRTSDuration_ba_f1; WORD wRTSDuration_aa_f1; SRTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRTS_g_FB, *PSRTS_g_FB; -typedef const SRTS_g_FB *PCSRTS_g_FB; +typedef const SRTS_g_FB *PCSRTS_g_FB; typedef struct tagSRTS_ab { BYTE bySignalField; @@ -257,10 +249,10 @@ typedef struct tagSRTS_ab { WORD wDuration; WORD wReserved; SRTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRTS_ab, *PSRTS_ab; -typedef const SRTS_ab *PCSRTS_ab; +typedef const SRTS_ab *PCSRTS_ab; typedef struct tagSRTS_a_FB { BYTE bySignalField; @@ -271,8 +263,9 @@ typedef struct tagSRTS_a_FB { WORD wRTSDuration_f0; WORD wRTSDuration_f1; SRTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SRTS_a_FB, *PSRTS_a_FB; + typedef const SRTS_a_FB *PCSRTS_a_FB; @@ -284,7 +277,7 @@ typedef struct tagSCTSData { WORD wDurationID; BYTE abyRA[ETH_ALEN]; WORD wReserved; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SCTSData, *PSCTSData; typedef struct tagSCTS { @@ -294,8 +287,9 @@ typedef struct tagSCTS { WORD wDuration_ba; WORD wReserved; SCTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SCTS, *PSCTS; + typedef const SCTS *PCSCTS; typedef struct tagSCTS_FB { @@ -307,10 +301,10 @@ typedef struct tagSCTS_FB { WORD wCTSDuration_ba_f0; WORD wCTSDuration_ba_f1; SCTSData Data; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SCTS_FB, *PSCTS_FB; -typedef const SCTS_FB *PCSCTS_FB; +typedef const SCTS_FB *PCSCTS_FB; // // Tx FIFO header @@ -321,14 +315,14 @@ typedef struct tagSTxBufHead { WORD wTimeStamp; WORD wFragCtl; WORD wReserved; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxBufHead, *PSTxBufHead; typedef const STxBufHead *PCSTxBufHead; typedef struct tagSTxShortBufHead { WORD wFIFOCtl; WORD wTimeStamp; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxShortBufHead, *PSTxShortBufHead; typedef const STxShortBufHead *PCSTxShortBufHead; @@ -346,8 +340,9 @@ typedef struct tagSTxDataHead_g { WORD wDuration_a; WORD wTimeStampOff_b; WORD wTimeStampOff_a; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxDataHead_g, *PSTxDataHead_g; + typedef const STxDataHead_g *PCSTxDataHead_g; typedef struct tagSTxDataHead_g_FB { @@ -363,22 +358,20 @@ typedef struct tagSTxDataHead_g_FB { WORD wDuration_a_f1; WORD wTimeStampOff_b; WORD wTimeStampOff_a; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxDataHead_g_FB, *PSTxDataHead_g_FB; typedef const STxDataHead_g_FB *PCSTxDataHead_g_FB; - typedef struct tagSTxDataHead_ab { BYTE bySignalField; BYTE byServiceField; WORD wTransmitLength; WORD wDuration; WORD wTimeStampOff; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxDataHead_ab, *PSTxDataHead_ab; typedef const STxDataHead_ab *PCSTxDataHead_ab; - typedef struct tagSTxDataHead_a_FB { BYTE bySignalField; BYTE byServiceField; @@ -387,7 +380,7 @@ typedef struct tagSTxDataHead_a_FB { WORD wTimeStampOff; WORD wDuration_f0; WORD wDuration_f1; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) STxDataHead_a_FB, *PSTxDataHead_a_FB; typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB; @@ -398,23 +391,23 @@ typedef struct tagSMICHDRHead { DWORD adwHDR0[4]; DWORD adwHDR1[4]; DWORD adwHDR2[4]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SMICHDRHead, *PSMICHDRHead; + typedef const SMICHDRHead *PCSMICHDRHead; typedef struct tagSBEACONCtl { DWORD BufReady : 1; - DWORD TSF : 15; - DWORD BufLen : 11; + DWORD TSF : 15; + DWORD BufLen : 11; DWORD Reserved : 5; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SBEACONCtl; - typedef struct tagSSecretKey { DWORD dwLowDword; BYTE byHighByte; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SSecretKey; typedef struct tagSKeyEntry { @@ -426,7 +419,7 @@ typedef struct tagSKeyEntry { DWORD dwKey2[4]; DWORD dwKey3[4]; DWORD dwKey4[4]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SKeyEntry; /*--------------------- Export Macros ------------------------------*/ diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index ef9fd97d3ca7..0bd8a9d21c16 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -109,7 +109,6 @@ #define MAX_MULTICAST_ADDRESS_NUM 32 #define MULTICAST_ADDRESS_LIST_SIZE (MAX_MULTICAST_ADDRESS_NUM * ETH_ALEN) - //#define OP_MODE_INFRASTRUCTURE 0 //#define OP_MODE_ADHOC 1 //#define OP_MODE_AP 2 @@ -130,8 +129,6 @@ #define KEYSEL_TKIP 2 #define KEYSEL_CCMP 3 - - #define AUTO_FB_NONE 0 #define AUTO_FB_0 1 #define AUTO_FB_1 2 @@ -162,8 +159,6 @@ #define BB_VGA_LEVEL 4 #define BB_VGA_CHANGE_THRESHOLD 3 - - #ifndef RUN_AT #define RUN_AT(x) (jiffies+(x)) #endif @@ -175,24 +170,23 @@ /*--------------------- Export Types ------------------------------*/ -#define DBG_PRT(l, p, args...) {if (l<=msglevel) printk( p ,##args);} -#define PRINT_K(p, args...) {if (PRIVATE_Message) printk( p ,##args);} +#define DBG_PRT(l, p, args...) { if (l <= msglevel) printk(p, ##args); } +#define PRINT_K(p, args...) { if (PRIVATE_Message) printk(p, ##args); } typedef enum __device_msg_level { - MSG_LEVEL_ERR=0, //Errors that will cause abnormal operation. - MSG_LEVEL_NOTICE=1, //Some errors need users to be notified. - MSG_LEVEL_INFO=2, //Normal message. - MSG_LEVEL_VERBOSE=3, //Will report all trival errors. - MSG_LEVEL_DEBUG=4 //Only for debug purpose. + MSG_LEVEL_ERR = 0, /* Errors causing abnormal operation */ + MSG_LEVEL_NOTICE = 1, /* Errors needing user notification */ + MSG_LEVEL_INFO = 2, /* Normal message. */ + MSG_LEVEL_VERBOSE = 3, /* Will report all trival errors. */ + MSG_LEVEL_DEBUG = 4 /* Only for debug purpose. */ } DEVICE_MSG_LEVEL, *PDEVICE_MSG_LEVEL; typedef enum __device_init_type { - DEVICE_INIT_COLD=0, // cold init - DEVICE_INIT_RESET, // reset init or Dx to D0 power remain init - DEVICE_INIT_DXPL // Dx to D0 power lost init + DEVICE_INIT_COLD = 0, /* cold init */ + DEVICE_INIT_RESET, /* reset init or Dx to D0 power remain */ + DEVICE_INIT_DXPL /* Dx to D0 power lost init */ } DEVICE_INIT_TYPE, *PDEVICE_INIT_TYPE; - //USB // @@ -203,9 +197,6 @@ typedef enum _CONTEXT_TYPE { CONTEXT_MGMT_PACKET } CONTEXT_TYPE; - - - // RCB (Receive Control Block) typedef struct _RCB { @@ -219,7 +210,6 @@ typedef struct _RCB } RCB, *PRCB; - // used to track bulk out irps typedef struct _USB_SEND_CONTEXT { void *pDevice; @@ -233,7 +223,6 @@ typedef struct _USB_SEND_CONTEXT { unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS]; } USB_SEND_CONTEXT, *PUSB_SEND_CONTEXT; - /* structure got from configuration file as user-desired default settings */ typedef struct _DEFAULT_CONFIG { signed int ZoneType; @@ -254,12 +243,10 @@ typedef struct { BOOL bInUse; } INT_BUFFER, *PINT_BUFFER; - - //0:11A 1:11B 2:11G typedef enum _VIA_BB_TYPE { - BB_TYPE_11A=0, + BB_TYPE_11A = 0, BB_TYPE_11B, BB_TYPE_11G } VIA_BB_TYPE, *PVIA_BB_TYPE; @@ -267,22 +254,19 @@ typedef enum _VIA_BB_TYPE //0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate) typedef enum _VIA_PKT_TYPE { - PK_TYPE_11A=0, + PK_TYPE_11A = 0, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA } VIA_PKT_TYPE, *PVIA_PKT_TYPE; - - - //++ NDIS related #define NDIS_STATUS int #define NTSTATUS int typedef enum __DEVICE_NDIS_STATUS { - STATUS_SUCCESS=0, + STATUS_SUCCESS = 0, STATUS_FAILURE, STATUS_RESOURCES, STATUS_PENDING, diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h index c816901882ad..a0b82169dad3 100644 --- a/drivers/staging/vt6656/device_cfg.h +++ b/drivers/staging/vt6656/device_cfg.h @@ -77,25 +77,20 @@ struct _version { //Max: 2378=2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR #define PKT_BUF_SZ 2390 - #define MAX_UINTS 8 #define OPTION_DEFAULT { [0 ... MAX_UINTS-1] = -1} - - -typedef enum _chip_type{ - VT3184=1 +typedef enum _chip_type { + VT3184 = 1 } CHIP_TYPE, *PCHIP_TYPE; - - #ifdef VIAWET_DEBUG #define ASSERT(x) { \ if (!(x)) { \ - printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\ + printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x, \ __FUNCTION__, __LINE__);\ - *(int*) 0=0;\ - }\ + *(int *) 0 = 0; \ + } \ } #define DBG_PORT80(value) outb(value, 0x80) #else @@ -103,5 +98,4 @@ typedef enum _chip_type{ #define DBG_PORT80(value) #endif - #endif diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index cdf355130de7..d32ba351bc45 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -57,7 +57,7 @@ typedef struct tagSINTData { BYTE byACKFail; BYTE byFCSErr; BYTE abySW[2]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SINTData, *PSINTData; diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index fbba1d53e49d..ec55eb0a74cf 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h @@ -70,10 +70,10 @@ typedef enum tagWMAC_CMD { } WMAC_CMD, *PWMAC_CMD; typedef enum tagWZONETYPE { - ZoneType_USA=0, - ZoneType_Japan=1, - ZoneType_Europe=2 -}WZONETYPE; + ZoneType_USA = 0, + ZoneType_Japan = 1, + ZoneType_Europe = 2 +} WZONETYPE; #define ADHOC 0 #define INFRA 1 @@ -83,9 +83,9 @@ typedef enum tagWZONETYPE { #define ADHOC_STARTED 1 #define ADHOC_JOINTED 2 -#define PHY80211a 0 -#define PHY80211b 1 -#define PHY80211g 2 +#define PHY80211a 0 +#define PHY80211b 1 +#define PHY80211g 2 #define SSID_ID 0 #define SSID_MAXLEN 32 diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index da03edcbacb0..959c8868f6e2 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h @@ -31,10 +31,8 @@ /*--------------------- Export Definitions -------------------------*/ - #define WPA_IE_LEN 64 - //WPA related /* typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; @@ -54,7 +52,7 @@ enum { VIAWGET_SET_DROP_UNENCRYPT = 7, VIAWGET_SET_DEAUTHENTICATE = 8, VIAWGET_SET_ASSOCIATE = 9, - VIAWGET_SET_DISASSOCIATE= 10 + VIAWGET_SET_DISASSOCIATE = 10 }; @@ -76,8 +74,6 @@ typedef struct viawget_wpa_header { u16 resp_ie_len; } viawget_wpa_header; - - struct viawget_wpa_param { u32 cmd; u8 addr[6]; @@ -86,43 +82,37 @@ struct viawget_wpa_param { u8 len; u8 data[0]; } generic_elem; - struct { - u8 bssid[6]; + u8 bssid[6]; u8 ssid[32]; u8 ssid_len; - u8 *wpa_ie; - u16 wpa_ie_len; - int pairwise_suite; - int group_suite; - int key_mgmt_suite; - int auth_alg; - int mode; - u8 roam_dbm; //DavidWang + u8 *wpa_ie; + u16 wpa_ie_len; + int pairwise_suite; + int group_suite; + int key_mgmt_suite; + int auth_alg; + int mode; + u8 roam_dbm; } wpa_associate; - struct { - int alg_name; - u16 key_index; - u16 set_tx; - u8 *seq; - u16 seq_len; - u8 *key; - u16 key_len; + int alg_name; + u16 key_index; + u16 set_tx; + u8 *seq; + u16 seq_len; + u8 *key; + u16 key_len; } wpa_key; - struct { u8 ssid_len; u8 ssid[32]; } scan_req; - struct { u16 scan_count; u8 *buf; } scan_results; - } u; - }; #pragma pack(1) @@ -142,15 +132,12 @@ struct viawget_scan_result { int maxrate; }; - /*--------------------- Export Classes ----------------------------*/ /*--------------------- Export Variables --------------------------*/ - /*--------------------- Export Types ------------------------------*/ - /*--------------------- Export Functions --------------------------*/ #endif /* __IOWPA_H__ */ diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index df9a4cf3baac..d601e9220219 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -33,15 +33,13 @@ /*--------------------- Export Definitions -------------------------*/ - /*--------------------- Export Classes ----------------------------*/ /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Functions --------------------------*/ -struct iw_statistics *iwctl_get_wireless_stats (struct net_device *dev); - +struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev); int iwctl_siwap(struct net_device *dev, struct iw_request_info *info, diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h index 775c70928ec7..491ff5ecd04b 100644 --- a/drivers/staging/vt6656/mac.h +++ b/drivers/staging/vt6656/mac.h @@ -420,11 +420,11 @@ /*--------------------- Export Functions --------------------------*/ -void MACvSetMultiAddrByHash (PSDevice pDevice, BYTE byHashIdx); +void MACvSetMultiAddrByHash(PSDevice pDevice, BYTE byHashIdx); void MACvWriteMultiAddr(PSDevice pDevice, unsigned int uByteIdx, BYTE byData); -BOOL MACbShutdown(PSDevice pDevice);; -void MACvSetBBType(PSDevice pDevice,BYTE byType); -void MACvSetMISCFifo (PSDevice pDevice, WORD wOffset, DWORD dwData); +BOOL MACbShutdown(PSDevice pDevice); +void MACvSetBBType(PSDevice pDevice, BYTE byType); +void MACvSetMISCFifo(PSDevice pDevice, WORD wOffset, DWORD dwData); void MACvDisableKeyEntry(PSDevice pDevice, unsigned int uEntryIdx); void MACvSetKeyEntry(PSDevice pDevice, WORD wKeyCtl, unsigned int uEntryIdx, unsigned int uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey); diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h index 0455ec9d327d..050dd9c05d5c 100644 --- a/drivers/staging/vt6656/mib.h +++ b/drivers/staging/vt6656/mib.h @@ -381,7 +381,9 @@ typedef struct tagSStatCounter { void STAvClearAllCounter(PSStatCounter pStatistic); -void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr1); +void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, + BYTE byIsr0, + BYTE byIsr1); void STAvUpdateRDStatCounter(PSStatCounter pStatistic, BYTE byRSR, BYTE byNewRSR, BYTE byRxSts, @@ -393,14 +395,8 @@ void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic, BYTE byRxRate, PBYTE pbyBuffer, unsigned int cbFrameLength); -void -STAvUpdateTDStatCounter ( - PSStatCounter pStatistic, - BYTE byPktNum, - BYTE byRate, - BYTE byTSR - ); - +void STAvUpdateTDStatCounter(PSStatCounter pStatistic, BYTE byPktNum, + BYTE byRate, BYTE byTSR); void STAvUpdate802_11Counter( diff --git a/drivers/staging/vt6656/michael.h b/drivers/staging/vt6656/michael.h index 3ab60928ef35..81351f506232 100644 --- a/drivers/staging/vt6656/michael.h +++ b/drivers/staging/vt6656/michael.h @@ -49,8 +49,8 @@ void MIC_vGetMIC(PDWORD pdwL, PDWORD pdwR); /*--------------------- Export Macros ------------------------------*/ // Rotation functions on 32 bit values -#define ROL32( A, n ) \ - ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) -#define ROR32( A, n ) ROL32( (A), 32-(n) ) +#define ROL32(A, n) \ + (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) +#define ROR32(A, n) ROL32((A), 32-(n)) #endif /* __MICHAEL_H__ */ diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h index d4f8b94132b9..f5ba8fd7f816 100644 --- a/drivers/staging/vt6656/rf.h +++ b/drivers/staging/vt6656/rf.h @@ -64,11 +64,7 @@ extern const BYTE RFaby11aChannelIndex[200]; /*--------------------- Export Functions --------------------------*/ BOOL IFRFbWriteEmbeded(PSDevice pDevice, DWORD dwData); -BOOL RFbSetPower ( - PSDevice pDevice, - unsigned int uRATE, - unsigned int uCH - ); +BOOL RFbSetPower(PSDevice pDevice, unsigned int uRATE, unsigned int uCH); BOOL RFbRawSetPower( PSDevice pDevice, @@ -76,17 +72,8 @@ BOOL RFbRawSetPower( unsigned int uRATE ); -void -RFvRSSITodBm ( - PSDevice pDevice, - BYTE byCurrRSSI, - long * pldBm - ); - -void -RFbRFTableDownload ( - PSDevice pDevice - ); +void RFvRSSITodBm(PSDevice pDevice, BYTE byCurrRSSI, long *pldBm); +void RFbRFTableDownload(PSDevice pDevice); BOOL s_bVT3226D0_11bLoCurrentAdjust( PSDevice pDevice, diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h index ac842dd13a68..fccf7e98eb68 100644 --- a/drivers/staging/vt6656/rndis.h +++ b/drivers/staging/vt6656/rndis.h @@ -152,7 +152,7 @@ typedef struct _CMD_CHANGE_BBTYPE /*--------------------- Export Macros -------------------------*/ -#define EXCH_WORD(w) ( (WORD)((WORD)(w)<<8) | (WORD)((WORD)(w)>>8) ) +#define EXCH_WORD(w) ((WORD)((WORD)(w)<<8) | (WORD)((WORD)(w)>>8)) /*--------------------- Export Variables --------------------------*/ diff --git a/drivers/staging/vt6656/tether.h b/drivers/staging/vt6656/tether.h index d63586d5cdb2..819aaf7c00e3 100644 --- a/drivers/staging/vt6656/tether.h +++ b/drivers/staging/vt6656/tether.h @@ -168,7 +168,7 @@ typedef struct tagSEthernetHeader { BYTE abyDstAddr[ETH_ALEN]; BYTE abySrcAddr[ETH_ALEN]; WORD wType; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) SEthernetHeader, *PSEthernetHeader; @@ -179,7 +179,7 @@ typedef struct tagS802_3Header { BYTE abyDstAddr[ETH_ALEN]; BYTE abySrcAddr[ETH_ALEN]; WORD wLen; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) S802_3Header, *PS802_3Header; // @@ -193,7 +193,7 @@ typedef struct tagS802_11Header { BYTE abyAddr3[ETH_ALEN]; WORD wSeqCtl; BYTE abyAddr4[ETH_ALEN]; -}__attribute__ ((__packed__)) +} __attribute__ ((__packed__)) S802_11Header, *PS802_11Header; /*--------------------- Export Macros ------------------------------*/ diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h index c27f9858e2e9..3ffcd7f790de 100644 --- a/drivers/staging/vt6656/ttype.h +++ b/drivers/staging/vt6656/ttype.h @@ -58,7 +58,7 @@ typedef int BOOL; #endif //2007-0809-01by MikeLiu -#ifndef update_BssList +#ifndef update_BssList #define update_BssList #endif diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h index 1e5b916aea1d..a7ea49107225 100644 --- a/drivers/staging/vt6656/wmgr.h +++ b/drivers/staging/vt6656/wmgr.h @@ -82,7 +82,7 @@ /*--------------------- Export Types ------------------------------*/ //mike define: make timer to expire after desired times -#define timer_expire(timer,next_tick) mod_timer(&timer, RUN_AT(next_tick)) +#define timer_expire(timer, next_tick) mod_timer(&timer, RUN_AT(next_tick)) typedef void (*TimerFunction)(unsigned long); diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h index 429a910a5c50..46c295905b48 100644 --- a/drivers/staging/vt6656/wpa2.h +++ b/drivers/staging/vt6656/wpa2.h @@ -58,21 +58,9 @@ typedef struct tagSPMKIDCache { /*--------------------- Export Functions --------------------------*/ -void -WPA2_ClearRSN ( - PKnownBSS pBSSNode - ); +void WPA2_ClearRSN(PKnownBSS pBSSNode); +void WPA2vParseRSN(PKnownBSS pBSSNode, PWLAN_IE_RSN pRSN); -void -WPA2vParseRSN ( - PKnownBSS pBSSNode, - PWLAN_IE_RSN pRSN - ); - -unsigned int -WPA2uSetIEs( - void *pMgmtHandle, - PWLAN_IE_RSN pRSNIEs - ); +unsigned int WPA2uSetIEs(void *pMgmtHandle, PWLAN_IE_RSN pRSNIEs); #endif /* __WPA2_H__ */ -- cgit v1.2.3 From d500648ef675d9abfc02ffb96b09141bc9f76dba Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 21 May 2010 19:08:14 -0300 Subject: Staging: vt6656: fix up built-in compilation together with rt2870 Fix this build error: drivers/staging/vt6656/built-in.o: In function `rotr1': (.text+0x1a878): multiple definition of `rotr1' drivers/staging/rt2870/built-in.o:(.text+0x106c2): first defined here drivers/staging/vt6656/built-in.o: In function `tkip_sbox': (.text+0x1a848): multiple definition of `tkip_sbox' drivers/staging/rt2870/built-in.o:(.text+0x10697): first defined here drivers/staging/vt6656/built-in.o: In function `xor_32': (.text+0x1ec24): multiple definition of `xor_32' drivers/staging/rt2870/built-in.o:(.text+0x111c4): first defined here drivers/staging/vt6656/built-in.o: In function `xor_128': (.text+0x1ec00): multiple definition of `xor_128' drivers/staging/rt2870/built-in.o:(.text+0x111dd): first defined here Signed-off-by: Otavio Salvador Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/aes_ccmp.c | 4 ++-- drivers/staging/vt6656/tkip.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/aes_ccmp.c b/drivers/staging/vt6656/aes_ccmp.c index b3d367b9bdc6..f7a3b8f8da70 100644 --- a/drivers/staging/vt6656/aes_ccmp.c +++ b/drivers/staging/vt6656/aes_ccmp.c @@ -106,7 +106,7 @@ BYTE dot3_table[256] = { /*--------------------- Export Functions --------------------------*/ -void xor_128(BYTE *a, BYTE *b, BYTE *out) +static void xor_128(BYTE *a, BYTE *b, BYTE *out) { PDWORD dwPtrA = (PDWORD) a; PDWORD dwPtrB = (PDWORD) b; @@ -119,7 +119,7 @@ void xor_128(BYTE *a, BYTE *b, BYTE *out) } -void xor_32(BYTE *a, BYTE *b, BYTE *out) +static void xor_32(BYTE *a, BYTE *b, BYTE *out) { PDWORD dwPtrA = (PDWORD) a; PDWORD dwPtrB = (PDWORD) b; diff --git a/drivers/staging/vt6656/tkip.c b/drivers/staging/vt6656/tkip.c index f83af5913aa6..a6bd533f9577 100644 --- a/drivers/staging/vt6656/tkip.c +++ b/drivers/staging/vt6656/tkip.c @@ -129,8 +129,6 @@ const BYTE TKIP_Sbox_Upper[256] = { //STKIPKeyManagement sTKIPKeyTable[MAX_TKIP_KEY]; /*--------------------- Static Functions --------------------------*/ -unsigned int tkip_sbox(unsigned int index); -unsigned int rotr1(unsigned int a); /*--------------------- Export Variables --------------------------*/ @@ -139,7 +137,7 @@ unsigned int rotr1(unsigned int a); /* Returns a 16 bit value from a 64K entry table. The Table */ /* is synthesized from two 256 entry byte wide tables. */ /************************************************************/ -unsigned int tkip_sbox(unsigned int index) +static unsigned int tkip_sbox(unsigned int index) { unsigned int index_low; unsigned int index_high; @@ -155,7 +153,7 @@ unsigned int tkip_sbox(unsigned int index) }; -unsigned int rotr1(unsigned int a) +static unsigned int rotr1(unsigned int a) { unsigned int b; -- cgit v1.2.3 From 2555cd9f9331a3a2ba79bd7263c7f334895d9cfa Mon Sep 17 00:00:00 2001 From: Timofey Trofimov Date: Sat, 22 May 2010 20:42:54 +0400 Subject: Staging: vt6656: fix coding style issues in 80211mgr.c This is a patch to the 80211mgr.c file that fixes up warnings found by the checkpatch.pl tool Signed-off-by: Timofey Trofimov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/80211mgr.c | 514 +++++++++++++++++++------------------- 1 file changed, 251 insertions(+), 263 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c index f24dc55e68f1..723601951bb7 100644 --- a/drivers/staging/vt6656/80211mgr.c +++ b/drivers/staging/vt6656/80211mgr.c @@ -67,8 +67,8 @@ /*--------------------- Static Variables --------------------------*/ -static int msglevel =MSG_LEVEL_INFO; -//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel = MSG_LEVEL_INFO; +/*static int msglevel =MSG_LEVEL_DEBUG;*/ /*--------------------- Static Functions --------------------------*/ @@ -96,7 +96,7 @@ vMgrEncodeBeacon( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_TS); pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -130,7 +130,7 @@ vMgrDecodeBeacon( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_TS); pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -138,88 +138,87 @@ vMgrDecodeBeacon( pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_BEACON_OFF_CAPINFO); - // Information elements + /* Information elements */ pItem = (PWLAN_IE)((PBYTE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))) + WLAN_BEACON_OFF_SSID); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ){ + while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { switch (pItem->byElementID) { - case WLAN_EID_SSID: - if (pFrame->pSSID == NULL) - pFrame->pSSID = (PWLAN_IE_SSID)pItem; - break; - case WLAN_EID_SUPP_RATES: - if (pFrame->pSuppRates == NULL) - pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - case WLAN_EID_FH_PARMS: - //pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem; - break; - case WLAN_EID_DS_PARMS: - if (pFrame->pDSParms == NULL) - pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; - break; - case WLAN_EID_CF_PARMS: - if (pFrame->pCFParms == NULL) - pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; - break; - case WLAN_EID_IBSS_PARMS: - if (pFrame->pIBSSParms == NULL) - pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; - break; - case WLAN_EID_TIM: - if (pFrame->pTIM == NULL) - pFrame->pTIM = (PWLAN_IE_TIM)pItem; - break; - - case WLAN_EID_RSN: - if (pFrame->pRSN == NULL) { - pFrame->pRSN = (PWLAN_IE_RSN)pItem; - } - break; - case WLAN_EID_RSN_WPA: - if (pFrame->pRSNWPA == NULL) { - if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) - pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; - } - break; - - case WLAN_EID_ERP: - if (pFrame->pERP == NULL) - pFrame->pERP = (PWLAN_IE_ERP)pItem; - break; - case WLAN_EID_EXTSUPP_RATES: - if (pFrame->pExtSuppRates == NULL) - pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - - case WLAN_EID_COUNTRY: //7 - if (pFrame->pIE_Country == NULL) - pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; - break; - - case WLAN_EID_PWR_CONSTRAINT: //32 - if (pFrame->pIE_PowerConstraint == NULL) - pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; - break; - - case WLAN_EID_CH_SWITCH: //37 - if (pFrame->pIE_CHSW == NULL) - pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; - break; - - case WLAN_EID_QUIET: //40 - if (pFrame->pIE_Quiet == NULL) - pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; - break; - - case WLAN_EID_IBSS_DFS: - if (pFrame->pIE_IBSSDFS == NULL) - pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; - break; - - default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID); + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + case WLAN_EID_FH_PARMS: + /* pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem; */ + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + case WLAN_EID_TIM: + if (pFrame->pTIM == NULL) + pFrame->pTIM = (PWLAN_IE_TIM)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: /* 7 */ + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: /* 32 */ + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: /* 37 */ + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: /* 40 */ + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID); break; } @@ -295,7 +294,7 @@ vMgrEncodeDisassociation( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DISASSOC_OFF_REASON); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason)); @@ -322,7 +321,7 @@ vMgrDecodeDisassociation( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DISASSOC_OFF_REASON); @@ -347,7 +346,7 @@ vMgrEncodeAssocRequest( ) { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_CAP_INFO); pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -376,47 +375,46 @@ vMgrDecodeAssocRequest( PWLAN_IE pItem; pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_CAP_INFO); pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_LISTEN_INT); - // Information elements + /* Information elements */ pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCREQ_OFF_SSID); while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { - switch (pItem->byElementID){ - case WLAN_EID_SSID: - if (pFrame->pSSID == NULL) - pFrame->pSSID = (PWLAN_IE_SSID)pItem; - break; - case WLAN_EID_SUPP_RATES: - if (pFrame->pSuppRates == NULL) - pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - - case WLAN_EID_RSN: - if (pFrame->pRSN == NULL) { - pFrame->pRSN = (PWLAN_IE_RSN)pItem; - } - break; - case WLAN_EID_RSN_WPA: - if (pFrame->pRSNWPA == NULL) { - if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) - pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; - } - break; - case WLAN_EID_EXTSUPP_RATES: - if (pFrame->pExtSuppRates == NULL) - pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - - default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n", - pItem->byElementID); - break; + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n", + pItem->byElementID); + break; } pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); } @@ -441,7 +439,7 @@ vMgrEncodeAssocResponse( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_CAP_INFO); pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -475,7 +473,7 @@ vMgrDecodeAssocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_CAP_INFO); pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -483,7 +481,7 @@ vMgrDecodeAssocResponse( pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_AID); - // Information elements + /* Information elements */ pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_ASSOCRESP_OFF_SUPP_RATES); @@ -493,8 +491,7 @@ vMgrDecodeAssocResponse( if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem); - } - else { + } else { pFrame->pExtSuppRates = NULL; } return; @@ -519,7 +516,7 @@ vMgrEncodeReassocRequest( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CAP_INFO); pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -552,7 +549,7 @@ vMgrDecodeReassocRequest( PWLAN_IE pItem; pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CAP_INFO); pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -560,42 +557,41 @@ vMgrDecodeReassocRequest( pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_CURR_AP); - // Information elements + /* Information elements */ pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCREQ_OFF_SSID); - while(((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { - - switch (pItem->byElementID){ - case WLAN_EID_SSID: - if (pFrame->pSSID == NULL) - pFrame->pSSID = (PWLAN_IE_SSID)pItem; - break; - case WLAN_EID_SUPP_RATES: - if (pFrame->pSuppRates == NULL) - pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - - case WLAN_EID_RSN: - if (pFrame->pRSN == NULL) { - pFrame->pRSN = (PWLAN_IE_RSN)pItem; - } - break; - case WLAN_EID_RSN_WPA: - if (pFrame->pRSNWPA == NULL) { - if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) - pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; - } - break; + while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { - case WLAN_EID_EXTSUPP_RATES: - if (pFrame->pExtSuppRates == NULL) - pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n", - pItem->byElementID); - break; + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n", + pItem->byElementID); + break; } pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); } @@ -646,30 +642,30 @@ vMgrDecodeProbeRequest( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Information elements + /* Information elements */ pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { switch (pItem->byElementID) { - case WLAN_EID_SSID: - if (pFrame->pSSID == NULL) - pFrame->pSSID = (PWLAN_IE_SSID)pItem; - break; + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; - case WLAN_EID_SUPP_RATES: - if (pFrame->pSuppRates == NULL) - pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; - case WLAN_EID_EXTSUPP_RATES: - if (pFrame->pExtSuppRates == NULL) - pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; - default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID); - break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID); + break; } pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); @@ -697,7 +693,7 @@ vMgrEncodeProbeResponse( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_TS); pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -734,7 +730,7 @@ vMgrDecodeProbeResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_TS); pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -742,83 +738,82 @@ vMgrDecodeProbeResponse( pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_CAP_INFO); - // Information elements + /* Information elements */ pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_PROBERESP_OFF_SSID); - while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { switch (pItem->byElementID) { - case WLAN_EID_SSID: - if (pFrame->pSSID == NULL) + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) pFrame->pSSID = (PWLAN_IE_SSID)pItem; - break; - case WLAN_EID_SUPP_RATES: - if (pFrame->pSuppRates == NULL) + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - case WLAN_EID_FH_PARMS: - break; - case WLAN_EID_DS_PARMS: - if (pFrame->pDSParms == NULL) - pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; - break; - case WLAN_EID_CF_PARMS: - if (pFrame->pCFParms == NULL) - pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; - break; - case WLAN_EID_IBSS_PARMS: - if (pFrame->pIBSSParms == NULL) - pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; - break; - - case WLAN_EID_RSN: - if (pFrame->pRSN == NULL) { - pFrame->pRSN = (PWLAN_IE_RSN)pItem; - } - break; - case WLAN_EID_RSN_WPA: - if (pFrame->pRSNWPA == NULL) { - if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) - pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; - } - break; - case WLAN_EID_ERP: - if (pFrame->pERP == NULL) - pFrame->pERP = (PWLAN_IE_ERP)pItem; - break; - case WLAN_EID_EXTSUPP_RATES: - if (pFrame->pExtSuppRates == NULL) - pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - break; - - case WLAN_EID_COUNTRY: //7 - if (pFrame->pIE_Country == NULL) - pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; - break; - - case WLAN_EID_PWR_CONSTRAINT: //32 - if (pFrame->pIE_PowerConstraint == NULL) - pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; - break; - - case WLAN_EID_CH_SWITCH: //37 - if (pFrame->pIE_CHSW == NULL) - pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; - break; - - case WLAN_EID_QUIET: //40 - if (pFrame->pIE_Quiet == NULL) - pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; - break; - - case WLAN_EID_IBSS_DFS: - if (pFrame->pIE_IBSSDFS == NULL) - pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; - break; - - default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID); - break; + break; + case WLAN_EID_FH_PARMS: + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: /* 7 */ + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: /* 32 */ + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: /* 37 */ + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: /* 40 */ + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID); + break; } pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); @@ -845,7 +840,7 @@ vMgrEncodeAuthen( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_ALG); pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -853,7 +848,6 @@ vMgrEncodeAuthen( pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_STATUS); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus)); - return; } @@ -878,7 +872,7 @@ vMgrDecodeAuthen( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_AUTH_ALG); pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -886,14 +880,12 @@ vMgrDecodeAuthen( pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_STATUS); - // Information elements + /* Information elements */ pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_AUTHEN_OFF_CHALLENGE); - if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) { + if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem; - } - return; } @@ -916,11 +908,10 @@ vMgrEncodeDeauthen( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DEAUTHEN_OFF_REASON); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason)); - return; } @@ -943,10 +934,9 @@ vMgrDecodeDeauthen( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_DEAUTHEN_OFF_REASON); - return; } @@ -969,7 +959,7 @@ vMgrEncodeReassocResponse( { pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_CAP_INFO); pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -978,7 +968,6 @@ vMgrEncodeReassocResponse( + WLAN_REASSOCRESP_OFF_AID); pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid)); - return; } @@ -1004,7 +993,7 @@ vMgrDecodeReassocResponse( pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; - // Fixed Fields + /* Fixed Fields */ pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_CAP_INFO); pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) @@ -1012,15 +1001,14 @@ vMgrDecodeReassocResponse( pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_AID); - //Information elements + /* Information elements */ pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + WLAN_REASSOCRESP_OFF_SUPP_RATES); pItem = (PWLAN_IE)(pFrame->pSuppRates); pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); - if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; - } return; } -- cgit v1.2.3 From 0d74395177b38db079caf57b5d27c3cc0ee59ef3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 11 Jun 2010 12:17:04 +0200 Subject: Staging: vt665*: fix typos concerning "management" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/80211mgr.h | 2 +- drivers/staging/vt6656/80211mgr.c | 2 +- drivers/staging/vt6656/80211mgr.h | 2 +- drivers/staging/vt6656/power.c | 2 +- drivers/staging/vt6656/power.h | 2 +- drivers/staging/vt6656/wmgr.h | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h index a11e6633a3c6..bebb5d6b5936 100644 --- a/drivers/staging/vt6655/80211mgr.h +++ b/drivers/staging/vt6655/80211mgr.h @@ -19,7 +19,7 @@ * * File: 80211mgr.h * - * Purpose: 802.11 managment frames pre-defines. + * Purpose: 802.11 management frames pre-defines. * * * Author: Lyndon Chen diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c index 723601951bb7..fceec4999c36 100644 --- a/drivers/staging/vt6656/80211mgr.c +++ b/drivers/staging/vt6656/80211mgr.c @@ -18,7 +18,7 @@ * * File: 80211mgr.c * - * Purpose: Handles the 802.11 managment support functions + * Purpose: Handles the 802.11 management support functions * * Author: Lyndon Chen * diff --git a/drivers/staging/vt6656/80211mgr.h b/drivers/staging/vt6656/80211mgr.h index 7f939e3bf175..3d57f793986d 100644 --- a/drivers/staging/vt6656/80211mgr.h +++ b/drivers/staging/vt6656/80211mgr.h @@ -19,7 +19,7 @@ * * File: 80211mgr.h * - * Purpose: 802.11 managment frames pre-defines. + * Purpose: 802.11 management frames pre-defines. * * * Author: Lyndon Chen diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index 766c5be6fd22..5ff15bf59c5b 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -19,7 +19,7 @@ * * File: power.c * - * Purpose: Handles 802.11 power managment functions + * Purpose: Handles 802.11 power management functions * * Author: Lyndon Chen * diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h index 50792bb8c978..41bffe528b44 100644 --- a/drivers/staging/vt6656/power.h +++ b/drivers/staging/vt6656/power.h @@ -18,7 +18,7 @@ * * File: power.h * - * Purpose: Handles 802.11 power managment functions + * Purpose: Handles 802.11 power management functions * * Author: Lyndon Chen * diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h index a7ea49107225..9aa9de399cbf 100644 --- a/drivers/staging/vt6656/wmgr.h +++ b/drivers/staging/vt6656/wmgr.h @@ -343,11 +343,11 @@ typedef struct tagSMgmtObject BOOL bRxBeaconInTBTTWake; BYTE abyPSTxMap[MAX_NODE_NUM + 1]; - // managment command related + // management command related unsigned int uCmdBusy; unsigned int uCmdHostAPBusy; - // managment packet pool + // management packet pool PBYTE pbyMgmtPacketPool; BYTE byMgmtPacketPool[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; -- cgit v1.2.3 From 013a468c4504738856d67118492ce7b7fff53a48 Mon Sep 17 00:00:00 2001 From: Charles Clément Date: Tue, 15 Jun 2010 10:39:24 -0700 Subject: Staging: vt6655: struct pci_driver cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename driver struct and callbacks to vt6655_* instead of device_* and add __devinit/__devexit directives. Signed-off-by: Charles Clément Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index f1af517b74b3..bd27a959add0 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -26,9 +26,9 @@ * * Functions: * - * device_found1 - module initial (insmod) driver entry - * device_remove1 - module remove entry - * device_init_info - device structure resource allocation function + * vt6655_probe - module initial (insmod) driver entry + * vt6655_remove - module remove entry + * vt6655_init_info - device structure resource allocation function * device_free_info - device structure resource free function * device_get_pci_info - get allocated pci io/mem resource * device_print_info - print out resource @@ -284,7 +284,7 @@ static CHIP_INFO chip_info_table[]= { {0,NULL} }; -DEFINE_PCI_DEVICE_TABLE(device_id_table) = { +DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = { { PCI_VDEVICE(VIA, 0x3253), (kernel_ulong_t)chip_info_table}, { 0, } }; @@ -292,8 +292,8 @@ DEFINE_PCI_DEVICE_TABLE(device_id_table) = { /*--------------------- Static Functions --------------------------*/ -static int device_found1(struct pci_dev *pcid, const struct pci_device_id *ent); -static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO); +static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); +static BOOL vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO); static void device_free_info(PSDevice pDevice); static BOOL device_get_pci_info(PSDevice, struct pci_dev* pcid); static void device_print_info(PSDevice pDevice); @@ -358,7 +358,7 @@ static char* get_chip_name(int chip_id) { return chip_info_table[i].name; } -static void device_remove1(struct pci_dev *pcid) +static void __devexit vt6655_remove(struct pci_dev *pcid) { PSDevice pDevice=pci_get_drvdata(pcid); @@ -915,8 +915,8 @@ static const struct net_device_ops device_netdev_ops = { -static int -device_found1(struct pci_dev *pcid, const struct pci_device_id *ent) +static int __devinit +vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) { static BOOL bFirst = TRUE; struct net_device* dev = NULL; @@ -948,7 +948,7 @@ device_found1(struct pci_dev *pcid, const struct pci_device_id *ent) bFirst=FALSE; } - if (!device_init_info(pcid, &pDevice, pChip_info)) { + if (!vt6655_init_info(pcid, &pDevice, pChip_info)) { return -ENOMEM; } pDevice->dev = dev; @@ -1122,7 +1122,7 @@ static void device_print_info(PSDevice pDevice) } -static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, +static BOOL __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO pChip_info) { PSDevice p; @@ -3601,20 +3601,20 @@ static int ethtool_ioctl(struct net_device *dev, void *useraddr) /*------------------------------------------------------------------*/ -MODULE_DEVICE_TABLE(pci, device_id_table); +MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); static struct pci_driver device_driver = { name: DEVICE_NAME, - id_table: device_id_table, - probe: device_found1, - remove: device_remove1, + id_table: vt6655_pci_id_table, + probe: vt6655_probe, + remove: vt6655_remove, #ifdef CONFIG_PM suspend: viawget_suspend, resume: viawget_resume, #endif }; -static int __init device_init_module(void) +static int __init vt6655_init_module(void) { int ret; @@ -3630,7 +3630,7 @@ static int __init device_init_module(void) return ret; } -static void __exit device_cleanup_module(void) +static void __exit vt6655_cleanup_module(void) { @@ -3641,8 +3641,8 @@ static void __exit device_cleanup_module(void) } -module_init(device_init_module); -module_exit(device_cleanup_module); +module_init(vt6655_init_module); +module_exit(vt6655_cleanup_module); #ifdef CONFIG_PM -- cgit v1.2.3 From 702422bd2d3f44e454a97ca7054edde84cc18126 Mon Sep 17 00:00:00 2001 From: "R.M. Thomas" Date: Fri, 18 Jun 2010 12:29:49 -0700 Subject: Staging: easycap: add easycap driver This adds the easycap USB video adapter driver to the staging directory. Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/easycap/Kconfig | 16 + drivers/staging/easycap/Makefile | 13 + drivers/staging/easycap/README | 130 + drivers/staging/easycap/easycap.h | 632 ++++ drivers/staging/easycap/easycap_debug.h | 27 + drivers/staging/easycap/easycap_ioctl.c | 2651 +++++++++++++++++ drivers/staging/easycap/easycap_ioctl.h | 29 + drivers/staging/easycap/easycap_low.c | 1057 +++++++ drivers/staging/easycap/easycap_main.c | 4342 ++++++++++++++++++++++++++++ drivers/staging/easycap/easycap_settings.c | 489 ++++ drivers/staging/easycap/easycap_sound.c | 973 +++++++ drivers/staging/easycap/easycap_sound.h | 30 + drivers/staging/easycap/easycap_standard.h | 27 + drivers/staging/easycap/easycap_testcard.c | 392 +++ 16 files changed, 10811 insertions(+) create mode 100644 drivers/staging/easycap/Kconfig create mode 100644 drivers/staging/easycap/Makefile create mode 100644 drivers/staging/easycap/README create mode 100644 drivers/staging/easycap/easycap.h create mode 100644 drivers/staging/easycap/easycap_debug.h create mode 100644 drivers/staging/easycap/easycap_ioctl.c create mode 100644 drivers/staging/easycap/easycap_ioctl.h create mode 100644 drivers/staging/easycap/easycap_low.c create mode 100644 drivers/staging/easycap/easycap_main.c create mode 100644 drivers/staging/easycap/easycap_settings.c create mode 100644 drivers/staging/easycap/easycap_sound.c create mode 100644 drivers/staging/easycap/easycap_sound.h create mode 100644 drivers/staging/easycap/easycap_standard.h create mode 100644 drivers/staging/easycap/easycap_testcard.c (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 2faff9697467..d5b827ccecf8 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -149,5 +149,7 @@ source "drivers/staging/mrst-touchscreen/Kconfig" source "drivers/staging/msm/Kconfig" +source "drivers/staging/easycap/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6d21710d3311..2c14f89387be 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_ADIS16255) += adis16255/ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ obj-$(CONFIG_MSM_STAGING) += msm/ +obj-$(CONFIG_EASYCAP) += easycap/ diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig new file mode 100644 index 000000000000..9bff7cf74f01 --- /dev/null +++ b/drivers/staging/easycap/Kconfig @@ -0,0 +1,16 @@ +config EASYCAP + tristate "EasyCAP USB ID 05e1:0408 support" + + ---help--- + This is an integrated audio/video driver for EasyCAP cards with + USB ID 05e1:0408. It supports two hardware variants: + + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, + having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) + + * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled + 1, 2, 3, 4 and an unlabelled input cable for a microphone. + + To compile this driver as a module, choose M here: the + module will be called easycap + diff --git a/drivers/staging/easycap/Makefile b/drivers/staging/easycap/Makefile new file mode 100644 index 000000000000..d93bd6b70a4b --- /dev/null +++ b/drivers/staging/easycap/Makefile @@ -0,0 +1,13 @@ + +obj-$(CONFIG_EASYCAP) += easycap.o + +easycap-objs := easycap_main.o easycap_low.o easycap_sound.o +easycap-objs += easycap_ioctl.o easycap_settings.o +easycap-objs += easycap_testcard.o + +EXTRA_CFLAGS += -Wall +# Impose all or none of the following: +EXTRA_CFLAGS += -DEASYCAP_IS_VIDEODEV_CLIENT +EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_DEVICE_H +EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_FOPS + diff --git a/drivers/staging/easycap/README b/drivers/staging/easycap/README new file mode 100644 index 000000000000..3775481f05e8 --- /dev/null +++ b/drivers/staging/easycap/README @@ -0,0 +1,130 @@ + + *********************************************************** + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60 * + * and * + * EasyCAP002 4-Channel USB 2.0 DVR * + *********************************************************** + Mike Thomas + + + +SUPPORTED HARDWARE +------------------ + +This driver is intended for use with hardware having USB ID 05e1:0408. +Two kinds of EasyCAP have this USB ID, namely: + + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, + having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) + + * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled + 1, 2, 3, 4 and an unlabelled input cable for a microphone. + + +BUILD OPTIONS AND DEPENDENCIES +------------------------------ + +If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation +the built module is entirely independent of the videodev module, and when +the EasyCAP is physically plugged into a USB port the special files +/dev/easycap0 and /dev/easysnd1 are created as video and sound sources +respectively. + +If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation +the built easycap module is configured to register with the videodev module, +in which case the special files created when the EasyCAP is plugged in are +/dev/video0 and /dev/easysnd0. Use of the easycap module as a client of +the videodev module has received very little testing as of June 2010. + + +KNOWN BUILD PROBLEMS +-------------------- + +(1) Recent gcc versions may generate the message: + + warning: the frame size of .... bytes is larger than 1024 bytes + +This warning can be suppressed by specifying in the Makefile: + + EXTRA_CFLAGS += -Wframe-larger-than=8192 + +but it would be preferable to remove the cause of the warning. + + +KNOWN RUNTIME ISSUES +-------------------- + +(1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any +output at start-up. Closing mplayer (or whatever the user program is) and +restarting it restores normal performance without any other remedial action +being necessary. The reason for this is not known. + +(2) Intentionally, this driver will not stream material which is unambiguously +identified by the hardware as copy-protected. The video output will freeze +within about a minute when this situation arises. + +(3) The controls for luminance, contrast, saturation, hue and volume may not +always work properly. + +(4) Reduced-resolution S-Video seems to suffer from moire artefacts. No +attempt has yet been made to rememdy this. + + +SUPPORTED TV STANDARDS AND RESOLUTIONS +-------------------------------------- + +The following TV standards are natively supported by the hardware and are +usable as (for example) the "norm=" parameter in the mplayer command: + + PAL_BGHIN, NTSC_N_443, + PAL_Nc, NTSC_N, + SECAM, NTSC_M, NTSC_M_JP, + PAL_60, NTSC_443, + PAL_M. + +The available picture sizes are: + + at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; + at 30 frames per second: 720x480, 640x480, 360x240, 320x240; + + +WHAT'S TESTED AND WHAT'S NOT +---------------------------- + +This driver is known to work with mplayer, mencoder, tvtime and sufficiently +recent versions of vlc. An interface to ffmpeg is implemented, but serious +audio-video synchronization problems remain. + +The driver is designed to support all the TV standards accepted by the +hardware, but as yet it has actually been tested on only a few of these. + +I have been unable to test and calibrate the S-video input myself because I +do not possess any equipment with S-video output. + +This driver does not understand the V4L1 IOCTL commands, so programs such +as camorama are not compatible. There are reports that the driver does +work with sufficiently recent (V4L2) versions of zoneminder, but I have not +attempted to confirm this myself. + + +UDEV RULES +---------- + +In order that the special files /dev/easycap0 and /dev/easysnd1 are created +with conveniently relaxed permissions when the EasyCAP is plugged in, a file +is preferably to be provided in directory /etc/udev/rules.d with content: + +ACTION!="add|change", GOTO="easycap_rules_end" +ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ + MODE="0666", OWNER="root", GROUP="root" +LABEL="easycap_rules_end" + + +ACKNOWLEGEMENTS AND REFERENCES +------------------------------ +This driver makes use of information contained in the Syntek Semicon DC-1125 +Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/ +by Nicolas Vivien. Particularly useful has been a patch to the latter driver +provided by Ivor Hewitt in January 2009. The NTSC implementation is taken +from the work of Ben Trask. + diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h new file mode 100644 index 000000000000..83ae2fb6db7c --- /dev/null +++ b/drivers/staging/easycap/easycap.h @@ -0,0 +1,632 @@ +/***************************************************************************** +* * +* easycap.h * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * THE FOLLOWING PARAMETERS ARE UNDEFINED: + * + * EASYCAP_DEBUG + * EASYCAP_IS_VIDEODEV_CLIENT + * EASYCAP_NEEDS_USBVIDEO_H + * EASYCAP_NEEDS_V4L2_DEVICE_H + * EASYCAP_NEEDS_V4L2_FOPS + * + * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER + * OPTIONS. + */ +/*---------------------------------------------------------------------------*/ + +#if (!defined(EASYCAP_H)) +#define EASYCAP_H + +#if defined(EASYCAP_DEBUG) +#if (9 < EASYCAP_DEBUG) +#error Debug levels 0 to 9 are okay.\ + To achieve higher levels, remove this trap manually from easycap.h +#endif +#endif /*EASYCAP_DEBUG*/ +/*---------------------------------------------------------------------------*/ +/* + * THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED: + */ +/*---------------------------------------------------------------------------*/ +#undef PREFER_NTSC +#undef EASYCAP_TESTCARD +#undef EASYCAP_TESTTONE +#undef LOCKFRAME +#undef NOREADBACK +#undef AUDIOTIME +/*---------------------------------------------------------------------------*/ +/* + * + * DEFINE BRIDGER TO ACTIVATE THE ROUTINE FOR BRIDGING VIDEOTAPE DROPOUTS. + * + * *** UNDER DEVELOPMENT/TESTING - NOT READY YET!*** + * + */ +/*---------------------------------------------------------------------------*/ +#undef BRIDGER +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +#if (!defined(__OLD_VIDIOC_)) +#define __OLD_VIDIOC_ +#endif /* !defined(__OLD_VIDIOC_) */ + +#include + +#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) +#include +#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +#if (!defined(__OLD_VIDIOC_)) +#define __OLD_VIDIOC_ +#endif /* !defined(__OLD_VIDIOC_) */ +#include + +#include + +#if defined(EASYCAP_NEEDS_USBVIDEO_H) +#include +#endif /*EASYCAP_NEEDS_USBVIDEO_H*/ + +#if (!defined(PAGE_SIZE)) +#error "PAGE_SIZE not defined" +#endif + +#define STRINGIZE_AGAIN(x) #x +#define STRINGIZE(x) STRINGIZE_AGAIN(x) + +/*---------------------------------------------------------------------------*/ +/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd + * + * EITHER EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60 + * with input cabling: AUDIO(L), AUDIO(R), CVBS, S-VIDEO. + * + * OR EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002 + * with input cabling: MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4. + */ +/*---------------------------------------------------------------------------*/ +#define USB_EASYCAP_VENDOR_ID 0x05e1 +#define USB_EASYCAP_PRODUCT_ID 0x0408 + +#define EASYCAP_DRIVER_VERSION "0.8" +#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60" + +#define USB_SKEL_MINOR_BASE 192 +#define VIDEO_DEVICE_MANY 8 + +/*---------------------------------------------------------------------------*/ +/* + * DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE + */ +/*---------------------------------------------------------------------------*/ +#define SAA_0A_DEFAULT 0x7F +#define SAA_0B_DEFAULT 0x3F +#define SAA_0C_DEFAULT 0x2F +#define SAA_0D_DEFAULT 0x00 +/*---------------------------------------------------------------------------*/ +/* + * VIDEO STREAMING PARAMETERS: + * USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT + * OF 3072 BYTES PER MICROFRAME for wMaxPacketSize. + */ +/*---------------------------------------------------------------------------*/ +#define VIDEO_ISOC_BUFFER_MANY 16 +#define VIDEO_ISOC_ORDER 3 +#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER) +#define USB_2_0_MAXPACKETSIZE 3072 +#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE) +#error video_isoc_buffer[.] will not be big enough +#endif +/*---------------------------------------------------------------------------*/ +/* + * VIDEO BUFFERS + */ +/*---------------------------------------------------------------------------*/ +#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE) +#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE) +#define FIELD_BUFFER_MANY 4 +#define FRAME_BUFFER_MANY 6 +/*---------------------------------------------------------------------------*/ +/* + * AUDIO STREAMING PARAMETERS + */ +/*---------------------------------------------------------------------------*/ +#define AUDIO_ISOC_BUFFER_MANY 16 +#define AUDIO_ISOC_ORDER 3 +#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER) +/*---------------------------------------------------------------------------*/ +/* + * AUDIO BUFFERS + */ +/*---------------------------------------------------------------------------*/ +#define AUDIO_FRAGMENT_MANY 32 +/*---------------------------------------------------------------------------*/ +/* + * STRUCTURE DEFINITIONS + */ +/*---------------------------------------------------------------------------*/ +struct data_buffer { +struct list_head list_head; +void *pgo; +void *pto; +__u16 kount; +}; +/*---------------------------------------------------------------------------*/ +struct data_urb { +struct list_head list_head; +struct urb *purb; +int isbuf; +int length; +}; +/*---------------------------------------------------------------------------*/ +/* + * easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256 + * easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9 + * easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9 + */ +/*---------------------------------------------------------------------------*/ +struct easycap { + +int ilk; +bool microphone; + +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +struct video_device *pvideo_device; +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +struct usb_device *pusb_device; +struct usb_interface *pusb_interface; + +struct kref kref; + +struct mutex mutex_mmap_video[FRAME_BUFFER_MANY]; +struct mutex mutex_timeval0; +struct mutex mutex_timeval1; + +int queued[FRAME_BUFFER_MANY]; +int done[FRAME_BUFFER_MANY]; + +wait_queue_head_t wq_video; +wait_queue_head_t wq_audio; + +int input; +int polled; +int standard_offset; +int format_offset; + +int fps; +int usec; +int tolerate; +int merit[180]; + +struct timeval timeval0; +struct timeval timeval1; +struct timeval timeval2; +struct timeval timeval7; +long long int dnbydt; + +int video_interface; +int video_altsetting_on; +int video_altsetting_off; +int video_endpointnumber; +int video_isoc_maxframesize; +int video_isoc_buffer_size; +int video_isoc_framesperdesc; + +int video_isoc_streaming; +int video_isoc_sequence; +int video_idle; +int video_eof; +int video_junk; + +int fudge; + +struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY]; +struct data_buffer \ + field_buffer[FIELD_BUFFER_MANY][(FIELD_BUFFER_SIZE/PAGE_SIZE)]; +struct data_buffer \ + frame_buffer[FRAME_BUFFER_MANY][(FRAME_BUFFER_SIZE/PAGE_SIZE)]; + +struct list_head urb_video_head; +struct list_head *purb_video_head; + +int vma_many; + +/*---------------------------------------------------------------------------*/ +/* + * BUFFER INDICATORS + */ +/*---------------------------------------------------------------------------*/ +int field_fill; /* Field buffer being filled by easycap_complete(). */ + /* Bumped only by easycap_complete(). */ +int field_page; /* Page of field buffer page being filled by */ + /* easycap_complete(). */ +int field_read; /* Field buffer to be read by field2frame(). */ + /* Bumped only by easycap_complete(). */ +int frame_fill; /* Frame buffer being filled by field2frame(). */ + /* Bumped only by easycap_dqbuf() when */ + /* field2frame() has created a complete frame. */ +int frame_read; /* Frame buffer offered to user by DQBUF. */ + /* Set only by easycap_dqbuf() to trail frame_fill.*/ +int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */ +/*---------------------------------------------------------------------------*/ +/* + * IMAGE PROPERTIES + */ +/*---------------------------------------------------------------------------*/ +__u32 pixelformat; +__u32 field; +int width; +int height; +int bytesperpixel; +bool byteswaporder; +bool decimatepixel; +bool offerfields; +int frame_buffer_used; +int frame_buffer_many; +int videofieldamount; + +int brightness; +int contrast; +int saturation; +int hue; + +int allocation_video_urb; +int allocation_video_page; +int allocation_video_struct; +int registered_video; +/*---------------------------------------------------------------------------*/ +/* + * SOUND PROPERTIES + */ +/*---------------------------------------------------------------------------*/ +int audio_interface; +int audio_altsetting_on; +int audio_altsetting_off; +int audio_endpointnumber; +int audio_isoc_maxframesize; +int audio_isoc_buffer_size; +int audio_isoc_framesperdesc; + +int audio_isoc_streaming; +int audio_idle; +int audio_eof; +int volume; +int mute; + +struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY]; + +struct list_head urb_audio_head; +struct list_head *purb_audio_head; +/*---------------------------------------------------------------------------*/ +/* + * BUFFER INDICATORS + */ +/*---------------------------------------------------------------------------*/ +int audio_fill; /* Audio buffer being filled by easysnd_complete(). */ + /* Bumped only by easysnd_complete(). */ +int audio_read; /* Audio buffer page being read by easysnd_read(). */ + /* Set by easysnd_read() to trail audio_fill by */ + /* one fragment. */ +/*---------------------------------------------------------------------------*/ +/* + * SOUND PROPERTIES + */ +/*---------------------------------------------------------------------------*/ + +int audio_buffer_many; + +int allocation_audio_urb; +int allocation_audio_page; +int allocation_audio_struct; +int registered_audio; + +long long int audio_sample; +long long int audio_niveau; +long long int audio_square; + +struct data_buffer audio_buffer[]; +}; +/*---------------------------------------------------------------------------*/ +struct easycap_standard { +__u16 mask; +struct v4l2_standard v4l2_standard; +}; +struct easycap_format { +__u16 mask; +char name[128]; +struct v4l2_format v4l2_format; +}; +/*---------------------------------------------------------------------------*/ +/* + * VIDEO FUNCTION PROTOTYPES + */ +/*---------------------------------------------------------------------------*/ +void easycap_complete(struct urb *); +int easycap_open(struct inode *, struct file *); +int easycap_release(struct inode *, struct file *); +int easycap_ioctl(struct inode *, struct file *, \ + unsigned int, unsigned long); + +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +int easycap_open_noinode(struct file *); +int easycap_release_noinode(struct file *); +long easycap_ioctl_noinode(struct file *, \ + unsigned int, unsigned long); +int videodev_release(struct video_device *); +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +unsigned int easycap_poll(struct file *, poll_table *); +int easycap_mmap(struct file *, struct vm_area_struct *); +int easycap_usb_probe(struct usb_interface *, \ + const struct usb_device_id *); +void easycap_usb_disconnect(struct usb_interface *); +void easycap_delete(struct kref *); + +void easycap_vma_open(struct vm_area_struct *); +void easycap_vma_close(struct vm_area_struct *); +int easycap_vma_fault(struct vm_area_struct *, struct vm_fault *); +int easycap_dqbuf(struct easycap *, int); +int submit_video_urbs(struct easycap *); +int kill_video_urbs(struct easycap *); +int field2frame(struct easycap *); +int redaub(struct easycap *, void *, void *, \ + int, int, __u8, __u8, bool); +void debrief(struct easycap *); +void sayreadonly(struct easycap *); +void easycap_testcard(struct easycap *, int); +int explain_ioctl(__u32); +int explain_cid(__u32); +int fillin_formats(void); +int adjust_standard(struct easycap *, v4l2_std_id); +int adjust_format(struct easycap *, __u32, __u32, __u32, \ + int, bool); +int adjust_brightness(struct easycap *, int); +int adjust_contrast(struct easycap *, int); +int adjust_saturation(struct easycap *, int); +int adjust_hue(struct easycap *, int); +int adjust_volume(struct easycap *, int); +/*---------------------------------------------------------------------------*/ +/* + * AUDIO FUNCTION PROTOTYPES + */ +/*---------------------------------------------------------------------------*/ +void easysnd_complete(struct urb *); +ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); +int easysnd_open(struct inode *, struct file *); +int easysnd_release(struct inode *, struct file *); +int easysnd_ioctl(struct inode *, struct file *, \ + unsigned int, unsigned long); +unsigned int easysnd_poll(struct file *, poll_table *); +void easysnd_delete(struct kref *); +int submit_audio_urbs(struct easycap *); +int kill_audio_urbs(struct easycap *); +void easysnd_testtone(struct easycap *, int); +int audio_setup(struct easycap *); +/*---------------------------------------------------------------------------*/ +/* + * LOW-LEVEL FUNCTION PROTOTYPES + */ +/*---------------------------------------------------------------------------*/ +int audio_gainget(struct usb_device *); +int audio_gainset(struct usb_device *, __s8); + +int set_interface(struct usb_device *, __u16); +int wakeup_device(struct usb_device *); +int confirm_resolution(struct usb_device *); +int confirm_stream(struct usb_device *); + +int setup_stk(struct usb_device *); +int setup_saa(struct usb_device *); +int setup_vt(struct usb_device *); +int check_stk(struct usb_device *); +int check_saa(struct usb_device *); +int ready_saa(struct usb_device *); +int merit_saa(struct usb_device *); +int check_vt(struct usb_device *); +int select_input(struct usb_device *, int, int); +int set_resolution(struct usb_device *, \ + __u16, __u16, __u16, __u16); + +int read_saa(struct usb_device *, __u16); +int read_stk(struct usb_device *, __u32); +int write_saa(struct usb_device *, __u16, __u16); +int wait_i2c(struct usb_device *); +int write_000(struct usb_device *, __u16, __u16); +int start_100(struct usb_device *); +int stop_100(struct usb_device *); +int write_300(struct usb_device *); +int read_vt(struct usb_device *, __u16); +int write_vt(struct usb_device *, __u16, __u16); + +int set2to78(struct usb_device *); +int set2to93(struct usb_device *); + +int regset(struct usb_device *, __u16, __u16); +int regget(struct usb_device *, __u16, void *); +/*---------------------------------------------------------------------------*/ +struct signed_div_result { +long long int quotient; +unsigned long long int remainder; +} signed_div(long long int, long long int); +/*---------------------------------------------------------------------------*/ +/* + * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND, + * ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND. + * THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT + * ONLY MUST THE PARAMETER + * STANDARD_MANY + * BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE + * NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS + * MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN + * ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE. + */ +/*---------------------------------------------------------------------------*/ +#define PAL_BGHIN 0 +#define PAL_Nc 2 +#define SECAM 4 +#define NTSC_N 6 +#define NTSC_N_443 8 +#define NTSC_M 1 +#define NTSC_443 3 +#define NTSC_M_JP 5 +#define PAL_60 7 +#define PAL_M 9 +#define STANDARD_MANY 10 +/*---------------------------------------------------------------------------*/ +/* + * ENUMS + */ +/*---------------------------------------------------------------------------*/ +enum { +AT_720x576, +AT_704x576, +AT_640x480, +AT_720x480, +AT_360x288, +AT_320x240, +AT_360x240, +RESOLUTION_MANY +}; +enum { +FMT_UYVY, +FMT_YUY2, +FMT_RGB24, +FMT_RGB32, +FMT_BGR24, +FMT_BGR32, +PIXELFORMAT_MANY +}; +enum { +FIELD_NONE, +FIELD_INTERLACED, +FIELD_ALTERNATE, +INTERLACE_MANY +}; +#define SETTINGS_MANY (STANDARD_MANY * \ + RESOLUTION_MANY * \ + 2 * \ + PIXELFORMAT_MANY * \ + INTERLACE_MANY) +/*---------------------------------------------------------------------------*/ +/* + * MACROS + */ +/*---------------------------------------------------------------------------*/ +#define GET(X, Y, Z) do { \ + int rc; \ + *(Z) = (__u16)0; \ + rc = regget(X, Y, Z); \ + if (0 > rc) { \ + JOT(8, ":-(%i\n", __LINE__); return(rc); \ + } \ +} while (0) + +#define SET(X, Y, Z) do { \ + int rc; \ + rc = regset(X, Y, Z); \ + if (0 > rc) { \ + JOT(8, ":-(%i\n", __LINE__); return(rc); \ + } \ +} while (0) +/*---------------------------------------------------------------------------*/ + +#define SAY(format, args...) do { \ + printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \ +} while (0) + + +#if defined(EASYCAP_DEBUG) +#define JOT(n, format, args...) do { \ + if (n <= easycap_debug) { \ + printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \ + } \ +} while (0) +#else +#define JOT(n, format, args...) do {} while (0) +#endif /*EASYCAP_DEBUG*/ + +#define POUT JOT(8, ":-(in file %s line %4i\n", __FILE__, __LINE__) + +#define MICROSECONDS(X, Y) \ + ((1000000*((long long int)(X.tv_sec - Y.tv_sec))) + \ + (long long int)(X.tv_usec - Y.tv_usec)) + +/*---------------------------------------------------------------------------*/ +/* + * (unsigned char *)P pointer to next byte pair + * (long int *)X pointer to accumulating count + * (long int *)Y pointer to accumulating sum + * (long long int *)Z pointer to accumulating sum of squares + */ +/*---------------------------------------------------------------------------*/ +#define SUMMER(P, X, Y, Z) do { \ + unsigned char *p; \ + unsigned int u0, u1, u2; \ + long int s; \ + p = (unsigned char *)(P); \ + u0 = (unsigned int) (*p); \ + u1 = (unsigned int) (*(p + 1)); \ + u2 = (unsigned int) ((u1 << 8) | u0); \ + if (0x8000 & u2) \ + s = -(long int)(0x7FFF & (~u2)); \ + else \ + s = (long int)(0x7FFF & u2); \ + *((X)) += (long int) 1; \ + *((Y)) += (long int) s; \ + *((Z)) += ((long long int)(s) * (long long int)(s)); \ +} while (0) +/*---------------------------------------------------------------------------*/ + +#endif /*EASYCAP_H*/ diff --git a/drivers/staging/easycap/easycap_debug.h b/drivers/staging/easycap/easycap_debug.h new file mode 100644 index 000000000000..1d10d7ea7d68 --- /dev/null +++ b/drivers/staging/easycap/easycap_debug.h @@ -0,0 +1,27 @@ +/***************************************************************************** +* * +* easycap_debug.h * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +extern int easycap_debug; diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c new file mode 100644 index 000000000000..f71cd9eaeb6b --- /dev/null +++ b/drivers/staging/easycap/easycap_ioctl.c @@ -0,0 +1,2651 @@ +/****************************************************************************** +* * +* easycap_ioctl.c * +* * +******************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ + +#include "easycap.h" +#include "easycap_debug.h" +#include "easycap_standard.h" +#include "easycap_ioctl.h" + +/*--------------------------------------------------------------------------*/ +/* + * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE + * FOLLOWING: + * peasycap->standard_offset + * peasycap->fps + * peasycap->usec + * peasycap->tolerate + */ +/*---------------------------------------------------------------------------*/ +int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id) +{ +struct easycap_standard *peasycap_standard; +__u16 reg, set; +int ir, rc, need; +unsigned int itwas, isnow; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +peasycap_standard = &easycap_standard[0]; +while (0xFFFF != peasycap_standard->mask) { + if (std_id & peasycap_standard->v4l2_standard.id) + break; + peasycap_standard++; +} +if (0xFFFF == peasycap_standard->mask) { + SAY("ERROR: 0x%08X=std_id: standard not found\n", \ + (unsigned int)std_id); + return -EINVAL; +} +SAY("user requests standard: %s\n", \ + &(peasycap_standard->v4l2_standard.name[0])); +if (peasycap->standard_offset == \ + (int)(peasycap_standard - &easycap_standard[0])) { + SAY("requested standard already in effect\n"); + return 0; +} +peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]); +peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \ + peasycap_standard->v4l2_standard.frameperiod.numerator; +if (!peasycap->fps) { + SAY("MISTAKE: frames-per-second is zero\n"); + return -EFAULT; +} +JOT(8, "%i frames-per-second\n", peasycap->fps); +peasycap->usec = 1000000 / (2 * peasycap->fps); +peasycap->tolerate = 1000 * (25 / peasycap->fps); + +kill_video_urbs(peasycap); + +/*--------------------------------------------------------------------------*/ +/* + * SAA7113H DATASHEET PAGE 44, TABLE 42 + */ +/*--------------------------------------------------------------------------*/ +need = 0; itwas = 0; reg = 0x00; set = 0x00; +switch (peasycap_standard->mask & 0x000F) { +case NTSC_M_JP: { + reg = 0x0A; set = 0x95; + ir = read_saa(peasycap->pusb_device, reg); + if (0 > ir) + SAY("ERROR: cannot read SAA register 0x%02X\n", reg); + else + itwas = (unsigned int)ir; + + + set2to78(peasycap->pusb_device); + + + rc = write_saa(peasycap->pusb_device, reg, set); + if (0 != rc) + SAY("ERROR: failed to set SAA register " \ + "0x%02X to 0x%02X for JP standard\n", reg, set); + else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed " \ + "to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " \ + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + + set2to78(peasycap->pusb_device); + + } + + reg = 0x0B; set = 0x48; + ir = read_saa(peasycap->pusb_device, reg); + if (0 > ir) + SAY("ERROR: cannot read SAA register 0x%02X\n", reg); + else + itwas = (unsigned int)ir; + + set2to78(peasycap->pusb_device); + + rc = write_saa(peasycap->pusb_device, reg, set); + if (0 != rc) + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X " \ + "for JP standard\n", reg, set); + else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed " \ + "to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " \ + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + + set2to78(peasycap->pusb_device); + + } +/*--------------------------------------------------------------------------*/ +/* + * NOTE: NO break HERE: RUN ON TO NEXT CASE + */ +/*--------------------------------------------------------------------------*/ +} +case NTSC_M: +case PAL_BGHIN: { + reg = 0x0E; set = 0x01; need = 1; break; +} +case NTSC_N_443: +case PAL_60: { + reg = 0x0E; set = 0x11; need = 1; break; +} +case NTSC_443: +case PAL_Nc: { + reg = 0x0E; set = 0x21; need = 1; break; +} +case NTSC_N: +case PAL_M: { + reg = 0x0E; set = 0x31; need = 1; break; +} +case SECAM: { + reg = 0x0E; set = 0x51; need = 1; break; +} +default: + break; +} +/*--------------------------------------------------------------------------*/ +if (need) { + ir = read_saa(peasycap->pusb_device, reg); + if (0 > ir) + SAY("ERROR: failed to read SAA register 0x%02X\n", reg); + else + itwas = (unsigned int)ir; + + set2to78(peasycap->pusb_device); + + rc = write_saa(peasycap->pusb_device, reg, set); + if (0 != write_saa(peasycap->pusb_device, reg, set)) { + SAY("ERROR: failed to set SAA register " \ + "0x%02X to 0x%02X for table 42\n", reg, set); + } else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed " \ + "to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " \ + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + } +} +/*--------------------------------------------------------------------------*/ +/* + * SAA7113H DATASHEET PAGE 41 + */ +/*--------------------------------------------------------------------------*/ +reg = 0x08; +ir = read_saa(peasycap->pusb_device, reg); +if (0 > ir) + SAY("ERROR: failed to read SAA register 0x%02X " \ + "so cannot reset\n", reg); +else { + itwas = (unsigned int)ir; + if (peasycap_standard->mask & 0x0001) + set = itwas | 0x40 ; + else + set = itwas & ~0x40 ; + +set2to78(peasycap->pusb_device); + +rc = write_saa(peasycap->pusb_device, reg, set); +if (0 != rc) + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set); +else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " \ + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + } +} +/*--------------------------------------------------------------------------*/ +/* + * SAA7113H DATASHEET PAGE 51, TABLE 57 + */ +/*---------------------------------------------------------------------------*/ +reg = 0x40; +ir = read_saa(peasycap->pusb_device, reg); +if (0 > ir) + SAY("ERROR: failed to read SAA register 0x%02X " \ + "so cannot reset\n", reg); +else { + itwas = (unsigned int)ir; + if (peasycap_standard->mask & 0x0001) + set = itwas | 0x80 ; + else + set = itwas & ~0x80 ; + +set2to78(peasycap->pusb_device); + +rc = write_saa(peasycap->pusb_device, reg, set); +if (0 != rc) + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set); +else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " \ + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + } +} +/*--------------------------------------------------------------------------*/ +/* + * SAA7113H DATASHEET PAGE 53, TABLE 66 + */ +/*--------------------------------------------------------------------------*/ +reg = 0x5A; +ir = read_saa(peasycap->pusb_device, reg); +if (0 > ir) + SAY("ERROR: failed to read SAA register 0x%02X but continuing\n", reg); + itwas = (unsigned int)ir; + if (peasycap_standard->mask & 0x0001) + set = 0x0A ; + else + set = 0x07 ; + + set2to78(peasycap->pusb_device); + + if (0 != write_saa(peasycap->pusb_device, reg, set)) + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \ + reg, set); + else { + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); + if (0 > ir) + JOT(8, "SAA register 0x%02X changed " + "to 0x%02X\n", reg, isnow); + else + JOT(8, "SAA register 0x%02X changed " + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); + } + if (0 != check_saa(peasycap->pusb_device)) + SAY("ERROR: check_saa() failed\n"); +return 0; +} +/*****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL DEPENDS ON THE + * CURRENT VALUE OF peasycap->standard_offset. + * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN + * THIS ROUTINE UPDATES THE FOLLOWING: + * peasycap->format_offset + * peasycap->pixelformat + * peasycap->field + * peasycap->height + * peasycap->width + * peasycap->bytesperpixel + * peasycap->byteswaporder + * peasycap->decimatepixel + * peasycap->frame_buffer_used + * peasycap->videofieldamount + * peasycap->offerfields + * + * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[] + * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER. + * ERRORS RETURN A NEGATIVE NUMBER. + */ +/*--------------------------------------------------------------------------*/ +int adjust_format(struct easycap *peasycap, \ + __u32 width, __u32 height, __u32 pixelformat, int field, bool try) +{ +struct easycap_format *peasycap_format, *peasycap_best_format; +__u16 mask; +struct usb_device *p; +int miss, multiplier, best; +char bf[5], *pc; +__u32 uc; + +if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; +} +p = peasycap->pusb_device; +if ((struct usb_device *)NULL == p) { + SAY("ERROR: peaycap->pusb_device is NULL\n"); + return -EFAULT; +} +pc = &bf[0]; +uc = pixelformat; memcpy((void *)pc, (void *)(&uc), 4); bf[4] = 0; +mask = easycap_standard[peasycap->standard_offset].mask; +SAY("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \ + width, height, pc, pixelformat, field, mask); +if (V4L2_FIELD_ANY == field) { + field = V4L2_FIELD_INTERLACED; + SAY("prefer: V4L2_FIELD_INTERLACED=field, was V4L2_FIELD_ANY\n"); +} +peasycap_best_format = (struct easycap_format *)NULL; +peasycap_format = &easycap_format[0]; +while (0 != peasycap_format->v4l2_format.fmt.pix.width) { + JOT(16, ".> %i %i 0x%08X %ix%i\n", \ + peasycap_format->mask & 0x01, + peasycap_format->v4l2_format.fmt.pix.field, + peasycap_format->v4l2_format.fmt.pix.pixelformat, + peasycap_format->v4l2_format.fmt.pix.width, + peasycap_format->v4l2_format.fmt.pix.height); + + if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \ + (peasycap_format->v4l2_format.fmt.pix.field == field) && \ + (peasycap_format->v4l2_format.fmt.pix.pixelformat == \ + pixelformat) && \ + (peasycap_format->v4l2_format.fmt.pix.width == width) && \ + (peasycap_format->v4l2_format.fmt.pix.height == height)) { + peasycap_best_format = peasycap_format; + break; + } + peasycap_format++; +} +if (0 == peasycap_format->v4l2_format.fmt.pix.width) { + SAY("cannot do: %ix%i with standard mask 0x%02X\n", \ + width, height, mask); + peasycap_format = &easycap_format[0]; best = -1; + while (0 != peasycap_format->v4l2_format.fmt.pix.width) { + if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \ + (peasycap_format->v4l2_format.fmt.pix\ + .field == field) && \ + (peasycap_format->v4l2_format.fmt.pix\ + .pixelformat == pixelformat)) { + miss = abs(peasycap_format->\ + v4l2_format.fmt.pix.width - width); + if ((best > miss) || (best < 0)) { + best = miss; + peasycap_best_format = peasycap_format; + if (!miss) + break; + } + } + peasycap_format++; + } + if (-1 == best) { + SAY("cannot do %ix... with standard mask 0x%02X\n", \ + width, mask); + SAY("cannot do ...x%i with standard mask 0x%02X\n", \ + height, mask); + SAY(" %ix%i unmatched\n", width, height); + return peasycap->format_offset; + } +} +if ((struct easycap_format *)NULL == peasycap_best_format) { + SAY("MISTAKE: peasycap_best_format is NULL"); + return -EINVAL; +} +peasycap_format = peasycap_best_format; + +/*...........................................................................*/ +if (true == try) + return (int)(peasycap_best_format - &easycap_format[0]); +/*...........................................................................*/ + +if (false != try) { + SAY("MISTAKE: true==try where is should be false\n"); + return -EINVAL; +} +SAY("actioning: %ix%i %s\n", \ + peasycap_format->v4l2_format.fmt.pix.width, \ + peasycap_format->v4l2_format.fmt.pix.height, + &peasycap_format->name[0]); +peasycap->height = peasycap_format->v4l2_format.fmt.pix.height; +peasycap->width = peasycap_format->v4l2_format.fmt.pix.width; +peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat; +peasycap->field = peasycap_format->v4l2_format.fmt.pix.field; +peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]); +peasycap->bytesperpixel = (0x00F0 & peasycap_format->mask) >> 4 ; +if (0x0100 & peasycap_format->mask) + peasycap->byteswaporder = true; +else + peasycap->byteswaporder = false; +if (0x0800 & peasycap_format->mask) + peasycap->decimatepixel = true; +else + peasycap->decimatepixel = false; +if (0x1000 & peasycap_format->mask) + peasycap->offerfields = true; +else + peasycap->offerfields = false; +if (true == peasycap->decimatepixel) + multiplier = 2; +else + multiplier = 1; +peasycap->videofieldamount = multiplier * peasycap->width * \ + multiplier * peasycap->height; +peasycap->frame_buffer_used = peasycap->bytesperpixel * \ + peasycap->width * peasycap->height; + +if (true == peasycap->offerfields) { + SAY("WARNING: %i=peasycap->field is untested: " \ + "please report problems\n", peasycap->field); + + +/* + * FIXME ---- THIS IS UNTESTED, MAY BE (AND PROBABLY IS) INCORRECT: + * + * peasycap->frame_buffer_used = peasycap->frame_buffer_used / 2; + * + * SO DO NOT RISK IT YET. + * + */ + + + +} + +kill_video_urbs(peasycap); + +/*---------------------------------------------------------------------------*/ +/* + * PAL + */ +/*---------------------------------------------------------------------------*/ +if (0 == (0x01 & peasycap_format->mask)) { + if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \ + (576 == \ + peasycap_format->v4l2_format.fmt.pix.height)) || \ + ((360 == \ + peasycap_format->v4l2_format.fmt.pix.width) && \ + (288 == \ + peasycap_format->v4l2_format.fmt.pix.height))) { + if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) { + SAY("ERROR: set_resolution() failed\n"); + return -EINVAL; + } + } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \ + (576 == peasycap_format->v4l2_format.fmt.pix.height)) { + if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) { + SAY("ERROR: set_resolution() failed\n"); + return -EINVAL; + } + } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \ + (480 == \ + peasycap_format->v4l2_format.fmt.pix.height)) || \ + ((320 == \ + peasycap_format->v4l2_format.fmt.pix.width) && \ + (240 == \ + peasycap_format->v4l2_format.fmt.pix.height))) { + if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) { + SAY("ERROR: set_resolution() failed\n"); + return -EINVAL; + } + } else { + SAY("MISTAKE: bad format, cannot set resolution\n"); + return -EINVAL; + } +/*---------------------------------------------------------------------------*/ +/* + * NTSC + */ +/*---------------------------------------------------------------------------*/ +} else { + if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \ + (480 == \ + peasycap_format->v4l2_format.fmt.pix.height)) || \ + ((360 == \ + peasycap_format->v4l2_format.fmt.pix.width) && \ + (240 == \ + peasycap_format->v4l2_format.fmt.pix.height))) { + if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) { + SAY("ERROR: set_resolution() failed\n"); + return -EINVAL; + } + } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \ + (480 == \ + peasycap_format->v4l2_format.fmt.pix.height)) || \ + ((320 == \ + peasycap_format->v4l2_format.fmt.pix.width) && \ + (240 == \ + peasycap_format->v4l2_format.fmt.pix.height))) { + if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) { + SAY("ERROR: set_resolution() failed\n"); + return -EINVAL; + } + } else { + SAY("MISTAKE: bad format, cannot set resolution\n"); + return -EINVAL; + } +} +/*---------------------------------------------------------------------------*/ + +check_stk(peasycap->pusb_device); + +return (int)(peasycap_best_format - &easycap_format[0]); +} +/*****************************************************************************/ +int adjust_brightness(struct easycap *peasycap, int value) +{ +unsigned int mood; +int i1; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) { + if ((easycap_control[i1].minimum > value) || \ + (easycap_control[i1].maximum < value)) + value = easycap_control[i1].default_value; + peasycap->brightness = value; + mood = 0x00FF & (unsigned int)peasycap->brightness; + + set2to78(peasycap->pusb_device); + + if (!write_saa(peasycap->pusb_device, 0x0A, mood)) { + SAY("adjusting brightness to 0x%02X\n", mood); + return 0; + } else { + SAY("WARNING: failed to adjust brightness " \ + "to 0x%02X\n", mood); + return -ENOENT; + } + + set2to78(peasycap->pusb_device); + + break; + } + i1++; +} +SAY("WARNING: failed to adjust brightness: control not found\n"); +return -ENOENT; +} +/*****************************************************************************/ +int adjust_contrast(struct easycap *peasycap, int value) +{ +unsigned int mood; +int i1; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_CONTRAST == easycap_control[i1].id) { + if ((easycap_control[i1].minimum > value) || \ + (easycap_control[i1].maximum < value)) + value = easycap_control[i1].default_value; + peasycap->contrast = value; + mood = 0x00FF & (unsigned int) (peasycap->contrast - 128); + + set2to78(peasycap->pusb_device); + + if (!write_saa(peasycap->pusb_device, 0x0B, mood)) { + SAY("adjusting contrast to 0x%02X\n", mood); + return 0; + } else { + SAY("WARNING: failed to adjust contrast to " \ + "0x%02X\n", mood); + return -ENOENT; + } + + set2to78(peasycap->pusb_device); + + break; + } + i1++; +} +SAY("WARNING: failed to adjust contrast: control not found\n"); +return -ENOENT; +} +/*****************************************************************************/ +int adjust_saturation(struct easycap *peasycap, int value) +{ +unsigned int mood; +int i1; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_SATURATION == easycap_control[i1].id) { + if ((easycap_control[i1].minimum > value) || \ + (easycap_control[i1].maximum < value)) + value = easycap_control[i1].default_value; + peasycap->saturation = value; + mood = 0x00FF & (unsigned int) (peasycap->saturation - 128); + + set2to78(peasycap->pusb_device); + + if (!write_saa(peasycap->pusb_device, 0x0C, mood)) { + SAY("adjusting saturation to 0x%02X\n", mood); + return 0; + } else { + SAY("WARNING: failed to adjust saturation to " \ + "0x%02X\n", mood); + return -ENOENT; + } + break; + + set2to78(peasycap->pusb_device); + + } + i1++; +} +SAY("WARNING: failed to adjust saturation: control not found\n"); +return -ENOENT; +} +/*****************************************************************************/ +int adjust_hue(struct easycap *peasycap, int value) +{ +unsigned int mood; +int i1, i2; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_HUE == easycap_control[i1].id) { + if ((easycap_control[i1].minimum > value) || \ + (easycap_control[i1].maximum < value)) + value = easycap_control[i1].default_value; + peasycap->hue = value; + i2 = peasycap->hue - 128; + mood = 0x00FF & ((int) i2); + + set2to78(peasycap->pusb_device); + + if (!write_saa(peasycap->pusb_device, 0x0D, mood)) { + SAY("adjusting hue to 0x%02X\n", mood); + return 0; + } else { + SAY("WARNING: failed to adjust hue to 0x%02X\n", mood); + return -ENOENT; + } + + set2to78(peasycap->pusb_device); + + break; + } + i1++; +} +SAY("WARNING: failed to adjust hue: control not found\n"); +return -ENOENT; +} +/*****************************************************************************/ +int adjust_volume(struct easycap *peasycap, int value) +{ +__s8 mood; +int i1; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) { + if ((easycap_control[i1].minimum > value) || \ + (easycap_control[i1].maximum < value)) + value = easycap_control[i1].default_value; + peasycap->volume = value; + mood = (16 > peasycap->volume) ? 16 : \ + ((31 < peasycap->volume) ? 31 : \ + (__s8) peasycap->volume); + if (!audio_gainset(peasycap->pusb_device, mood)) { + SAY("adjusting volume to 0x%01X\n", mood); + return 0; + } else { + SAY("WARNING: failed to adjust volume to " \ + "0x%1X\n", mood); + return -ENOENT; + } + break; + } +i1++; +} +SAY("WARNING: failed to adjust volume: control not found\n"); +return -ENOENT; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE: + * usb_set_interface(peasycap->pusb_device, \ + * peasycap->audio_interface, \ + * peasycap->audio_altsetting_off); + * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS + * -ESHUTDOWN. THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT + * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE. + */ +/*---------------------------------------------------------------------------*/ +int adjust_mute(struct easycap *peasycap, int value) +{ +int i1; + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +i1 = 0; +while (0xFFFFFFFF != easycap_control[i1].id) { + if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) { + peasycap->mute = value; + switch (peasycap->mute) { + case 1: { + peasycap->audio_idle = 1; + peasycap->timeval0.tv_sec = 0; + SAY("adjusting mute: %i=peasycap->audio_idle\n", \ + peasycap->audio_idle); + return 0; + } + default: { + peasycap->audio_idle = 0; + SAY("adjusting mute: %i=peasycap->audio_idle\n", \ + peasycap->audio_idle); + return 0; + } + } + break; + } + i1++; +} +SAY("WARNING: failed to adjust mute: control not found\n"); +return -ENOENT; +} +/****************************************************************************/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +long +easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg)\ + { + return easycap_ioctl((struct inode *)NULL, file, cmd, arg); +} +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*--------------------------------------------------------------------------*/ +int easycap_ioctl(struct inode *inode, struct file *file, \ + unsigned int cmd, unsigned long arg) +{ +static struct easycap *peasycap; +static struct usb_device *p; +static __u32 isequence; + +peasycap = (struct easycap *)file->private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -1; +} +p = peasycap->pusb_device; +if ((struct usb_device *)NULL == p) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +/* + * MOST OF THE VARIABLES DECLARED static IN THE case{} BLOCKS BELOW ARE SO + * DECLARED SIMPLY TO AVOID A COMPILER WARNING OF THE KIND: + * easycap_ioctl.c: warning: + * the frame size of ... bytes is larger than 1024 bytes + */ +/*---------------------------------------------------------------------------*/ +switch (cmd) { +case VIDIOC_QUERYCAP: { + static struct v4l2_capability v4l2_capability; + static char version[16], *p1, *p2; + static int i, rc, k[3]; + static long lng; + + JOT(8, "VIDIOC_QUERYCAP\n"); + + if (16 <= strlen(EASYCAP_DRIVER_VERSION)) { + SAY("ERROR: bad driver version string\n"); return -EINVAL; + } + strcpy(&version[0], EASYCAP_DRIVER_VERSION); + for (i = 0; i < 3; i++) + k[i] = 0; + p2 = &version[0]; i = 0; + while (*p2) { + p1 = p2; + while (*p2 && ('.' != *p2)) + p2++; + if (*p2) + *p2++ = 0; + if (3 > i) { + rc = (int) strict_strtol(p1, 10, &lng); + if (0 != rc) { + SAY("ERROR: %i=strict_strtol(%s,.,,)\n", \ + rc, p1); + return -EINVAL; + } + k[i] = (int)lng; + } + i++; + } + + memset(&v4l2_capability, 0, sizeof(struct v4l2_capability)); + strlcpy(&v4l2_capability.driver[0], "easycap", \ + sizeof(v4l2_capability.driver)); + + v4l2_capability.capabilities = \ + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE; + + v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]); + JOT(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]); + + strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \ + sizeof(v4l2_capability.card)); + + if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\ + sizeof(v4l2_capability.bus_info)) < 0) { + strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \ + sizeof(v4l2_capability.bus_info)); + JOT(8, "%s=v4l2_capability.bus_info\n", \ + &v4l2_capability.bus_info[0]); + } + if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \ + sizeof(struct v4l2_capability))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_ENUMINPUT: { + static struct v4l2_input v4l2_input; + static __u32 index; + + JOT(8, "VIDIOC_ENUMINPUT\n"); + + if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \ + sizeof(struct v4l2_input))) { + POUT; + return -EFAULT; + } + + index = v4l2_input.index; + memset(&v4l2_input, 0, sizeof(struct v4l2_input)); + + switch (index) { + case 0: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "CVBS0"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + case 1: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "CVBS1"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + case 2: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "CVBS2"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + case 3: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "CVBS3"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + case 4: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "CVBS4"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + case 5: { + v4l2_input.index = index; + strcpy(&v4l2_input.name[0], "S-VIDEO"); + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; + v4l2_input.audioset = 0x01; + v4l2_input.tuner = 0; + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ + V4L2_STD_NTSC ; + v4l2_input.status = 0; + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); + break; + } + default: { + JOT(8, "%i=index: exhausts inputs\n", index); + return -EINVAL; + } + } + + if (0 != copy_to_user((void __user *)arg, &v4l2_input, \ + sizeof(struct v4l2_input))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_INPUT: { + static __u32 index; + + JOT(8, "VIDIOC_G_INPUT\n"); + index = (__u32)peasycap->input; + JOT(8, "user is told: %i\n", index); + if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_INPUT: + { + static __u32 index; + + JOT(8, "VIDIOC_S_INPUT\n"); + + if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) { + POUT; + return -EFAULT; + } + + JOT(8, "user requests input %i\n", index); + + if ((int)index == peasycap->input) { + SAY("requested input already in effect\n"); + break; + } + + if ((0 > index) || (5 < index)) { + JOT(8, "ERROR: bad requested input: %i\n", index); + return -EINVAL; + } + peasycap->input = (int)index; + + select_input(peasycap->pusb_device, peasycap->input, 9); + + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_ENUMAUDIO: { + JOT(8, "VIDIOC_ENUMAUDIO\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_ENUMAUDOUT: { + static struct v4l2_audioout v4l2_audioout; + + JOT(8, "VIDIOC_ENUMAUDOUT\n"); + + if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \ + sizeof(struct v4l2_audioout))) { + POUT; + return -EFAULT; + } + + if (0 != v4l2_audioout.index) + return -EINVAL; + memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout)); + v4l2_audioout.index = 0; + strcpy(&v4l2_audioout.name[0], "Soundtrack"); + + if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \ + sizeof(struct v4l2_audioout))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_QUERYCTRL: { + static int i1; + static struct v4l2_queryctrl v4l2_queryctrl; + + JOT(8, "VIDIOC_QUERYCTRL\n"); + + if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \ + sizeof(struct v4l2_queryctrl))) { + POUT; + return -EFAULT; + } + + i1 = 0; + while (0xFFFFFFFF != easycap_control[i1].id) { + if (easycap_control[i1].id == v4l2_queryctrl.id) { + JOT(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]" \ + ".name\n", &easycap_control[i1].name[0], i1); + memcpy(&v4l2_queryctrl, &easycap_control[i1], \ + sizeof(struct v4l2_queryctrl)); + break; + } + i1++; + } + if (0xFFFFFFFF == easycap_control[i1].id) { + JOT(8, "%i=index: exhausts controls\n", i1); + return -EINVAL; + } + if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \ + sizeof(struct v4l2_queryctrl))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_QUERYMENU: { + JOT(8, "VIDIOC_QUERYMENU unsupported\n"); + return -EINVAL; + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_CTRL: { + static struct v4l2_control v4l2_control; + + JOT(8, "VIDIOC_G_CTRL\n"); + + if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ + sizeof(struct v4l2_control))) { + POUT; + return -EFAULT; + } + + switch (v4l2_control.id) { + case V4L2_CID_BRIGHTNESS: { + v4l2_control.value = peasycap->brightness; + JOT(8, "user enquires brightness: %i\n", v4l2_control.value); + break; + } + case V4L2_CID_CONTRAST: { + v4l2_control.value = peasycap->contrast; + JOT(8, "user enquires contrast: %i\n", v4l2_control.value); + break; + } + case V4L2_CID_SATURATION: { + v4l2_control.value = peasycap->saturation; + JOT(8, "user enquires saturation: %i\n", v4l2_control.value); + break; + } + case V4L2_CID_HUE: { + v4l2_control.value = peasycap->hue; + JOT(8, "user enquires hue: %i\n", v4l2_control.value); + break; + } + case V4L2_CID_AUDIO_VOLUME: { + v4l2_control.value = peasycap->volume; + JOT(8, "user enquires volume: %i\n", v4l2_control.value); + break; + } + case V4L2_CID_AUDIO_MUTE: { + if (1 == peasycap->mute) + v4l2_control.value = true; + else + v4l2_control.value = false; + JOT(8, "user enquires mute: %i\n", v4l2_control.value); + break; + } + default: { + SAY("ERROR: unknown V4L2 control: 0x%08X=id\n", \ + v4l2_control.id); + explain_cid(v4l2_control.id); + return -EINVAL; + } + } + if (0 != copy_to_user((void __user *)arg, &v4l2_control, \ + sizeof(struct v4l2_control))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if defined(VIDIOC_S_CTRL_OLD) +case VIDIOC_S_CTRL_OLD: { + JOT(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n"); +} +#endif /*VIDIOC_S_CTRL_OLD*/ +case VIDIOC_S_CTRL: + { + static struct v4l2_control v4l2_control; + + JOT(8, "VIDIOC_S_CTRL\n"); + + if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ + sizeof(struct v4l2_control))) { + POUT; + return -EFAULT; + } + + switch (v4l2_control.id) { + case V4L2_CID_BRIGHTNESS: { + JOT(8, "user requests brightness %i\n", v4l2_control.value); + if (0 != adjust_brightness(peasycap, v4l2_control.value)) + ; + break; + } + case V4L2_CID_CONTRAST: { + JOT(8, "user requests contrast %i\n", v4l2_control.value); + if (0 != adjust_contrast(peasycap, v4l2_control.value)) + ; + break; + } + case V4L2_CID_SATURATION: { + JOT(8, "user requests saturation %i\n", v4l2_control.value); + if (0 != adjust_saturation(peasycap, v4l2_control.value)) + ; + break; + } + case V4L2_CID_HUE: { + JOT(8, "user requests hue %i\n", v4l2_control.value); + if (0 != adjust_hue(peasycap, v4l2_control.value)) + ; + break; + } + case V4L2_CID_AUDIO_VOLUME: { + JOT(8, "user requests volume %i\n", v4l2_control.value); + if (0 != adjust_volume(peasycap, v4l2_control.value)) + ; + break; + } + case V4L2_CID_AUDIO_MUTE: { + int mute; + + JOT(8, "user requests mute %i\n", v4l2_control.value); + if (true == v4l2_control.value) + mute = 1; + else + mute = 0; + + if (0 != adjust_mute(peasycap, mute)) + SAY("WARNING: failed to adjust mute to %i\n", mute); + break; + } + default: { + SAY("ERROR: unknown V4L2 control: 0x%08X=id\n", \ + v4l2_control.id); + explain_cid(v4l2_control.id); + return -EINVAL; + } + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_EXT_CTRLS: { + JOT(8, "VIDIOC_S_EXT_CTRLS unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_ENUM_FMT: { + static __u32 index; + static struct v4l2_fmtdesc v4l2_fmtdesc; + + JOT(8, "VIDIOC_ENUM_FMT\n"); + + if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \ + sizeof(struct v4l2_fmtdesc))) { + POUT; + return -EFAULT; + } + + index = v4l2_fmtdesc.index; + memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc)); + + v4l2_fmtdesc.index = index; + v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + switch (index) { + case 0: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "uyvy"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + case 1: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "yuy2"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + case 2: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "rgb24"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + case 3: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "rgb32"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + case 4: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "bgr24"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + case 5: { + v4l2_fmtdesc.flags = 0; + strcpy(&v4l2_fmtdesc.description[0], "bgr32"); + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32; + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); + break; + } + default: { + JOT(8, "%i=index: exhausts formats\n", index); + return -EINVAL; + } + } + if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \ + sizeof(struct v4l2_fmtdesc))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_ENUM_FRAMESIZES: { + JOT(8, "VIDIOC_ENUM_FRAMESIZES unsupported\n"); + return -EINVAL; +} +case VIDIOC_ENUM_FRAMEINTERVALS: { + JOT(8, "VIDIOC_ENUM_FRAME_INTERVALS unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_FMT: { + static struct v4l2_format v4l2_format; + static struct v4l2_pix_format v4l2_pix_format; + + JOT(8, "VIDIOC_G_FMT\n"); + + if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ + sizeof(struct v4l2_format))) { + POUT; + return -EFAULT; + } + + if (v4l2_format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + POUT; + return -EINVAL; + } + + memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memcpy(&(v4l2_format.fmt.pix), \ + &(easycap_format[peasycap->format_offset]\ + .v4l2_format.fmt.pix), sizeof(v4l2_pix_format)); + JOT(8, "user is told: %s\n", \ + &easycap_format[peasycap->format_offset].name[0]); + + if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ + sizeof(struct v4l2_format))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_TRY_FMT: +case VIDIOC_S_FMT: { + static struct v4l2_format v4l2_format; + static struct v4l2_pix_format v4l2_pix_format; + static bool try; + static int best_format; + + if (VIDIOC_TRY_FMT == cmd) { + JOT(8, "VIDIOC_TRY_FMT\n"); + try = true; + } else { + JOT(8, "VIDIOC_S_FMT\n"); + try = false; + } + + if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ + sizeof(struct v4l2_format))) { + POUT; + return -EFAULT; + } + + best_format = adjust_format(peasycap, \ + v4l2_format.fmt.pix.width, \ + v4l2_format.fmt.pix.height, \ + v4l2_format.fmt.pix.pixelformat, \ + v4l2_format.fmt.pix.field, \ + try); + if (0 > best_format) { + JOT(8, "WARNING: adjust_format() returned %i\n", best_format); + return -ENOENT; + } +/*...........................................................................*/ + memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\ + .v4l2_format.fmt.pix), sizeof(v4l2_pix_format)); + JOT(8, "user is told: %s\n", &easycap_format[best_format].name[0]); + + if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ + sizeof(struct v4l2_format))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_CROPCAP: { + static struct v4l2_cropcap v4l2_cropcap; + + JOT(8, "VIDIOC_CROPCAP\n"); + + if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \ + sizeof(struct v4l2_cropcap))) { + POUT; + return -EFAULT; + } + + if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + JOT(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); + + memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap)); + v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_cropcap.bounds.left = 0; + v4l2_cropcap.bounds.top = 0; + v4l2_cropcap.bounds.width = peasycap->width; + v4l2_cropcap.bounds.height = peasycap->height; + v4l2_cropcap.defrect.left = 0; + v4l2_cropcap.defrect.top = 0; + v4l2_cropcap.defrect.width = peasycap->width; + v4l2_cropcap.defrect.height = peasycap->height; + v4l2_cropcap.pixelaspect.numerator = 1; + v4l2_cropcap.pixelaspect.denominator = 1; + + JOT(8, "user is told: %ix%i\n", peasycap->width, peasycap->height); + + if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \ + sizeof(struct v4l2_cropcap))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_CROP: +case VIDIOC_S_CROP: { + JOT(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_QUERYSTD: { + JOT(8, "VIDIOC_QUERYSTD: " \ + "EasyCAP is incapable of detecting standard\n"); + return -EINVAL; + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/*---------------------------------------------------------------------------*/ +/* + * THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND + * FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer. + * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer. + */ +/*---------------------------------------------------------------------------*/ +case VIDIOC_ENUMSTD: { + static int last0 = -1, last1 = -1, last2 = -1, last3 = -1; + static struct v4l2_standard v4l2_standard; + static __u32 index; + static struct easycap_standard *peasycap_standard; + + JOT(8, "VIDIOC_ENUMSTD\n"); + + if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \ + sizeof(struct v4l2_standard))) { + POUT; + return -EFAULT; + } + index = v4l2_standard.index; + + last3 = last2; last2 = last1; last1 = last0; last0 = index; + if ((index == last3) && (index == last2) && \ + (index == last1) && (index == last0)) { + index++; + last3 = last2; last2 = last1; last1 = last0; last0 = index; + } + + memset(&v4l2_standard, 0, sizeof(struct v4l2_standard)); + + peasycap_standard = &easycap_standard[0]; + while (0xFFFF != peasycap_standard->mask) { + if ((int)(peasycap_standard - &easycap_standard[0]) == index) + break; + peasycap_standard++; + } + if (0xFFFF == peasycap_standard->mask) { + JOT(8, "%i=index: exhausts standards\n", index); + return -EINVAL; + } + JOT(8, "%i=index: %s\n", index, \ + &(peasycap_standard->v4l2_standard.name[0])); + peasycap_standard->v4l2_standard.index = index; + v4l2_standard.index = index; + + if (0 != copy_to_user((void __user *)arg, \ + &(peasycap_standard->v4l2_standard), \ + sizeof(struct v4l2_standard))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_STD: { + static v4l2_std_id std_id; + static struct easycap_standard *peasycap_standard; + + JOT(8, "VIDIOC_G_STD\n"); + + if (0 != copy_from_user(&std_id, (void __user *)arg, \ + sizeof(v4l2_std_id))) { + POUT; + return -EFAULT; + } + + peasycap_standard = &easycap_standard[peasycap->standard_offset]; + std_id = peasycap_standard->v4l2_standard.id; + + JOT(8, "user is told: %s\n", \ + &peasycap_standard->v4l2_standard.name[0]); + + if (0 != copy_to_user((void __user *)arg, &std_id, \ + sizeof(v4l2_std_id))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_STD: { + static v4l2_std_id std_id; + static int rc; + + JOT(8, "VIDIOC_S_STD\n"); + + if (0 != copy_from_user(&std_id, (void __user *)arg, \ + sizeof(v4l2_std_id))) { + POUT; + return -EFAULT; + } + + rc = adjust_standard(peasycap, std_id); + if (0 > rc) { + JOT(8, "WARNING: adjust_standard() returned %i\n", rc); + return -ENOENT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_REQBUFS: { + static int nbuffers; + static struct v4l2_requestbuffers v4l2_requestbuffers; + + JOT(8, "VIDIOC_REQBUFS\n"); + + if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \ + sizeof(struct v4l2_requestbuffers))) { + POUT; + return -EFAULT; + } + + if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) { + POUT; + return -EINVAL; + } + nbuffers = v4l2_requestbuffers.count; + JOT(8, " User requests %i buffers ...\n", nbuffers); + if (nbuffers < 2) + nbuffers = 2; + if (nbuffers > FRAME_BUFFER_MANY) + nbuffers = FRAME_BUFFER_MANY; + if (v4l2_requestbuffers.count == nbuffers) { + JOT(8, " ... agree to %i buffers\n", \ + nbuffers); + } else { + JOT(8, " ... insist on %i buffers\n", \ + nbuffers); + v4l2_requestbuffers.count = nbuffers; + } + peasycap->frame_buffer_many = nbuffers; + + if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \ + sizeof(struct v4l2_requestbuffers))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_QUERYBUF: { + static __u32 index; + static struct v4l2_buffer v4l2_buffer; + + JOT(8, "VIDIOC_QUERYBUF\n"); + + if (peasycap->video_eof) { + JOT(8, "returning -1 because %i=video_eof\n", \ + peasycap->video_eof); + return -1; + } + + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + index = v4l2_buffer.index; + if (index < 0 || index >= peasycap->frame_buffer_many) + return -EINVAL; + memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer)); + v4l2_buffer.index = index; + v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_buffer.bytesused = peasycap->frame_buffer_used; + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \ + peasycap->done[index] | \ + peasycap->queued[index]; + v4l2_buffer.field = peasycap->field; + v4l2_buffer.memory = V4L2_MEMORY_MMAP; + v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE; + v4l2_buffer.length = FRAME_BUFFER_SIZE; + + JOT(16, " %10i=index\n", v4l2_buffer.index); + JOT(16, " 0x%08X=type\n", v4l2_buffer.type); + JOT(16, " %10i=bytesused\n", v4l2_buffer.bytesused); + JOT(16, " 0x%08X=flags\n", v4l2_buffer.flags); + JOT(16, " %10i=field\n", v4l2_buffer.field); + JOT(16, " %10li=timestamp.tv_usec\n", \ + (long)v4l2_buffer.timestamp.tv_usec); + JOT(16, " %10i=sequence\n", v4l2_buffer.sequence); + JOT(16, " 0x%08X=memory\n", v4l2_buffer.memory); + JOT(16, " %10i=m.offset\n", v4l2_buffer.m.offset); + JOT(16, " %10i=length\n", v4l2_buffer.length); + + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_QBUF: { + static struct v4l2_buffer v4l2_buffer; + + JOT(8, "VIDIOC_QBUF\n"); + + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (v4l2_buffer.index < 0 || \ + (v4l2_buffer.index >= peasycap->frame_buffer_many)) + return -EINVAL; + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED; + + peasycap->done[v4l2_buffer.index] = 0; + peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED; + + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + + JOT(8, "..... user queueing frame buffer %i\n", \ + (int)v4l2_buffer.index); + + peasycap->frame_lock = 0; + + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_DQBUF: + { +#if defined(AUDIOTIME) + static struct signed_div_result sdr; + static long long int above, below, dnbydt, fudge, sll; + static unsigned long long int ull; + static struct timeval timeval0; + struct timeval timeval1; +#endif /*AUDIOTIME*/ + static struct timeval timeval, timeval2; + static int i, j; + static struct v4l2_buffer v4l2_buffer; + + JOT(8, "VIDIOC_DQBUF\n"); + + if ((peasycap->video_idle) || (peasycap->video_eof)) { + JOT(8, "returning -EIO because " \ + "%i=video_idle %i=video_eof\n", \ + peasycap->video_idle, peasycap->video_eof); + return -EIO; + } + + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (!peasycap->video_isoc_streaming) { + JOT(16, "returning -EIO because video urbs not streaming\n"); + return -EIO; + } +/*---------------------------------------------------------------------------*/ +/* + * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING + * THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE. IN THIS + * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read + */ +/*---------------------------------------------------------------------------*/ + + if (!peasycap->polled) { + if (-EIO == easycap_dqbuf(peasycap, 0)) + return -EIO; + } else { + if (peasycap->video_eof) + return -EIO; + } + if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) { + SAY("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \ + peasycap->done[peasycap->frame_read]); + } + peasycap->polled = 0; + + if (!(isequence % 10)) { + for (i = 0; i < 179; i++) + peasycap->merit[i] = peasycap->merit[i+1]; + peasycap->merit[179] = merit_saa(peasycap->pusb_device); + j = 0; + for (i = 0; i < 180; i++) + j += peasycap->merit[i]; + if (90 < j) { + SAY("easycap driver shutting down " \ + "on condition blue\n"); + peasycap->video_eof = 1; peasycap->audio_eof = 1; + } + } + + v4l2_buffer.index = peasycap->frame_read; + v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_buffer.bytesused = peasycap->frame_buffer_used; + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; + v4l2_buffer.field = peasycap->field; + if (V4L2_FIELD_ALTERNATE == v4l2_buffer.field) + v4l2_buffer.field = \ + 0x000F & (peasycap->\ + frame_buffer[peasycap->frame_read][0].kount); + do_gettimeofday(&timeval); + timeval2 = timeval; + +#if defined(AUDIOTIME) + if (!peasycap->timeval0.tv_sec) { + timeval0 = timeval; + timeval1 = timeval; + timeval2 = timeval; + dnbydt = 192000; + + if (mutex_lock_interruptible(&(peasycap->mutex_timeval0))) + return -ERESTARTSYS; + peasycap->timeval0 = timeval0; + mutex_unlock(&(peasycap->mutex_timeval0)); + } else { + if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) + return -ERESTARTSYS; + dnbydt = peasycap->dnbydt; + timeval1 = peasycap->timeval1; + mutex_unlock(&(peasycap->mutex_timeval1)); + above = dnbydt * MICROSECONDS(timeval, timeval1); + below = 192000; + sdr = signed_div(above, below); + + above = sdr.quotient + timeval1.tv_usec - 350000; + + below = 1000000; + sdr = signed_div(above, below); + timeval2.tv_usec = sdr.remainder; + timeval2.tv_sec = timeval1.tv_sec + sdr.quotient; + } + if (!(isequence % 500)) { + fudge = ((long long int)(1000000)) * \ + ((long long int)(timeval.tv_sec - \ + timeval2.tv_sec)) + \ + (long long int)(timeval.tv_usec - \ + timeval2.tv_usec); + sdr = signed_div(fudge, 1000); + sll = sdr.quotient; + ull = sdr.remainder; + + SAY("%5lli.%-3lli=ms timestamp fudge\n", sll, ull); + } +#endif /*AUDIOTIME*/ + + v4l2_buffer.timestamp = timeval2; + v4l2_buffer.sequence = isequence++; + v4l2_buffer.memory = V4L2_MEMORY_MMAP; + v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE; + v4l2_buffer.length = FRAME_BUFFER_SIZE; + + JOT(16, " %10i=index\n", v4l2_buffer.index); + JOT(16, " 0x%08X=type\n", v4l2_buffer.type); + JOT(16, " %10i=bytesused\n", v4l2_buffer.bytesused); + JOT(16, " 0x%08X=flags\n", v4l2_buffer.flags); + JOT(16, " %10i=field\n", v4l2_buffer.field); + JOT(16, " %10li=timestamp.tv_usec\n", \ + (long)v4l2_buffer.timestamp.tv_usec); + JOT(16, " %10i=sequence\n", v4l2_buffer.sequence); + JOT(16, " 0x%08X=memory\n", v4l2_buffer.memory); + JOT(16, " %10i=m.offset\n", v4l2_buffer.m.offset); + JOT(16, " %10i=length\n", v4l2_buffer.length); + + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ + sizeof(struct v4l2_buffer))) { + POUT; + return -EFAULT; + } + + JOT(8, "..... user is offered frame buffer %i\n", \ + peasycap->frame_read); + peasycap->frame_lock = 1; + if (peasycap->frame_read == peasycap->frame_fill) { + if (peasycap->frame_lock) { + JOT(8, "ERROR: filling frame buffer " \ + "while offered to user\n"); + } + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/*---------------------------------------------------------------------------*/ +/* + * AUDIO URBS HAVE ALREADY BEEN SUBMITTED WHEN THIS COMMAND IS RECEIVED; + * VIDEO URBS HAVE NOT. + */ +/*---------------------------------------------------------------------------*/ +case VIDIOC_STREAMON: { + static int i; + + JOT(8, "VIDIOC_STREAMON\n"); + + isequence = 0; + for (i = 0; i < 180; i++) + peasycap->merit[i] = 0; + if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; + } + submit_video_urbs(peasycap); + peasycap->video_idle = 0; + peasycap->audio_idle = 0; + peasycap->video_eof = 0; + peasycap->audio_eof = 0; + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_STREAMOFF: { + JOT(8, "VIDIOC_STREAMOFF\n"); + + if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; + } + + peasycap->video_idle = 1; + peasycap->audio_idle = 1; peasycap->timeval0.tv_sec = 0; +/*---------------------------------------------------------------------------*/ +/* + * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND + * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. + */ +/*---------------------------------------------------------------------------*/ + JOT(8, "calling wake_up on wq_video and wq_audio\n"); + wake_up_interruptible(&(peasycap->wq_video)); + wake_up_interruptible(&(peasycap->wq_audio)); +/*---------------------------------------------------------------------------*/ + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_PARM: { + static struct v4l2_streamparm v4l2_streamparm; + + JOT(8, "VIDIOC_G_PARM\n"); + + if (0 != copy_from_user(&v4l2_streamparm, (void __user *)arg, \ + sizeof(struct v4l2_streamparm))) { + POUT; + return -EFAULT; + } + + if (v4l2_streamparm.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + POUT; + return -EINVAL; + } + v4l2_streamparm.parm.capture.capability = 0; + v4l2_streamparm.parm.capture.capturemode = 0; + v4l2_streamparm.parm.capture.timeperframe.numerator = 1; + v4l2_streamparm.parm.capture.timeperframe.denominator = 30; + v4l2_streamparm.parm.capture.readbuffers = peasycap->frame_buffer_many; + v4l2_streamparm.parm.capture.extendedmode = 0; + if (0 != copy_to_user((void __user *)arg, &v4l2_streamparm, \ + sizeof(struct v4l2_streamparm))) { + POUT; + return -EFAULT; + } + break; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_PARM: { + JOT(8, "VIDIOC_S_PARM unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_AUDIO: { + JOT(8, "VIDIOC_G_AUDIO unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_AUDIO: { + JOT(8, "VIDIOC_S_AUDIO unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_S_TUNER: { + JOT(8, "VIDIOC_S_TUNER unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_FBUF: +case VIDIOC_S_FBUF: +case VIDIOC_OVERLAY: { + JOT(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +case VIDIOC_G_TUNER: { + JOT(8, "VIDIOC_G_TUNER unsupported\n"); + return -EINVAL; +} +case VIDIOC_G_FREQUENCY: +case VIDIOC_S_FREQUENCY: { + JOT(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n"); + return -EINVAL; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +default: { + JOT(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd); + explain_ioctl(cmd); + POUT; + return -ENOIOCTLCMD; +} +} +return 0; +} +/****************************************************************************/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +long +easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) +{ + return easysnd_ioctl((struct inode *)NULL, file, cmd, arg); +} +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*--------------------------------------------------------------------------*/ +int easysnd_ioctl(struct inode *inode, struct file *file, \ + unsigned int cmd, unsigned long arg) +{ +struct easycap *peasycap; +struct usb_device *p; + +peasycap = (struct easycap *)file->private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL.\n"); + return -1; +} +p = peasycap->pusb_device; +/*---------------------------------------------------------------------------*/ +switch (cmd) { +case SNDCTL_DSP_GETCAPS: { + int caps; + JOT(8, "SNDCTL_DSP_GETCAPS\n"); + + if (true == peasycap->microphone) + caps = 0x02400000; + else + caps = 0x04400000; + + if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_GETFMTS: { + int incoming; + JOT(8, "SNDCTL_DSP_GETFMTS\n"); + + if (true == peasycap->microphone) + incoming = AFMT_S16_LE; + else + incoming = AFMT_S16_LE; + + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_SETFMT: { + int incoming, outgoing; + JOT(8, "SNDCTL_DSP_SETFMT\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + + if (true == peasycap->microphone) + outgoing = AFMT_S16_LE; + else + outgoing = AFMT_S16_LE; + + if (incoming != outgoing) { + JOT(8, "........... %i=outgoing\n", outgoing); + JOT(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE); + JOT(8, " cf. %i=AFMT_U8\n", AFMT_U8); + if (0 != copy_to_user((void __user *)arg, &outgoing, \ + sizeof(int))) + return -EFAULT; + return -EINVAL ; + } + break; +} +case SNDCTL_DSP_STEREO: { + int incoming; + JOT(8, "SNDCTL_DSP_STEREO\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + + if (true == peasycap->microphone) + incoming = 0; + else + incoming = 1; + + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_SPEED: { + int incoming; + JOT(8, "SNDCTL_DSP_SPEED\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + + if (true == peasycap->microphone) + incoming = 8000; + else + incoming = 48000; + + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_GETTRIGGER: { + int incoming; + JOT(8, "SNDCTL_DSP_GETTRIGGER\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + + incoming = PCM_ENABLE_INPUT; + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_SETTRIGGER: { + int incoming; + JOT(8, "SNDCTL_DSP_SETTRIGGER\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + JOT(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \ + "0x%x=PCM_ENABLE_OUTPUT\n", \ + PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT); + ; + ; + ; + ; + break; +} +case SNDCTL_DSP_GETBLKSIZE: { + int incoming; + JOT(8, "SNDCTL_DSP_GETBLKSIZE\n"); + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) + return -EFAULT; + JOT(8, "........... %i=incoming\n", incoming); + incoming = audio_bytes_per_fragment; + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) + return -EFAULT; + break; +} +case SNDCTL_DSP_GETISPACE: { + struct audio_buf_info audio_buf_info; + + JOT(8, "SNDCTL_DSP_GETISPACE\n"); + + audio_buf_info.bytes = audio_bytes_per_fragment; + audio_buf_info.fragments = 1; + audio_buf_info.fragsize = 0; + audio_buf_info.fragstotal = 0; + + if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \ + sizeof(int))) + return -EFAULT; + break; +} +default: { + JOT(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd); + POUT; + return -ENOIOCTLCMD; +} +} +return 0; +} +/*****************************************************************************/ +int explain_ioctl(__u32 wot) +{ +int k; +/*---------------------------------------------------------------------------*/ +/* + * THE DATA FOR THE ARRAY mess BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING + * SHELL SCRIPT: + * # + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev2.h | \ + * grep "^#define VIDIOC_" - | grep -v "_OLD" - | \ + * sed -e "s,_IO.*$,,;p" | sed -e "N;s,\n,, " | \ + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ + * sed -e "s, ,,g;s, ,,g" >ioctl.tmp + * echo "{0xFFFFFFFF,\"\"}" >>ioctl.tmp + * exit 0 + * # + * AND REINSTATING THE EXCISED "_OLD" CASES WERE LATER MANUALLY. + * + * THE DATA FOR THE ARRAY mess1 BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING + * SHELL SCRIPT: + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev.h | \ + * grep "^#define VIDIOC" - | grep -v "_OLD" - | \ + * sed -e "s,_IO.*$,,;p" | sed -e "N;s,\n,, " | \ + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ + * sed -e "s, ,,g;s, ,,g" >ioctl.tmp + * echo "{0xFFFFFFFF,\"\"}" >>ioctl.tmp + * exit 0 + * # + */ +/*---------------------------------------------------------------------------*/ +static struct mess { + __u32 command; + char name[64]; +} mess[] = { +#if defined(VIDIOC_QUERYCAP) +{VIDIOC_QUERYCAP, "VIDIOC_QUERYCAP"}, +#endif +#if defined(VIDIOC_RESERVED) +{VIDIOC_RESERVED, "VIDIOC_RESERVED"}, +#endif +#if defined(VIDIOC_ENUM_FMT) +{VIDIOC_ENUM_FMT, "VIDIOC_ENUM_FMT"}, +#endif +#if defined(VIDIOC_G_FMT) +{VIDIOC_G_FMT, "VIDIOC_G_FMT"}, +#endif +#if defined(VIDIOC_S_FMT) +{VIDIOC_S_FMT, "VIDIOC_S_FMT"}, +#endif +#if defined(VIDIOC_REQBUFS) +{VIDIOC_REQBUFS, "VIDIOC_REQBUFS"}, +#endif +#if defined(VIDIOC_QUERYBUF) +{VIDIOC_QUERYBUF, "VIDIOC_QUERYBUF"}, +#endif +#if defined(VIDIOC_G_FBUF) +{VIDIOC_G_FBUF, "VIDIOC_G_FBUF"}, +#endif +#if defined(VIDIOC_S_FBUF) +{VIDIOC_S_FBUF, "VIDIOC_S_FBUF"}, +#endif +#if defined(VIDIOC_OVERLAY) +{VIDIOC_OVERLAY, "VIDIOC_OVERLAY"}, +#endif +#if defined(VIDIOC_QBUF) +{VIDIOC_QBUF, "VIDIOC_QBUF"}, +#endif +#if defined(VIDIOC_DQBUF) +{VIDIOC_DQBUF, "VIDIOC_DQBUF"}, +#endif +#if defined(VIDIOC_STREAMON) +{VIDIOC_STREAMON, "VIDIOC_STREAMON"}, +#endif +#if defined(VIDIOC_STREAMOFF) +{VIDIOC_STREAMOFF, "VIDIOC_STREAMOFF"}, +#endif +#if defined(VIDIOC_G_PARM) +{VIDIOC_G_PARM, "VIDIOC_G_PARM"}, +#endif +#if defined(VIDIOC_S_PARM) +{VIDIOC_S_PARM, "VIDIOC_S_PARM"}, +#endif +#if defined(VIDIOC_G_STD) +{VIDIOC_G_STD, "VIDIOC_G_STD"}, +#endif +#if defined(VIDIOC_S_STD) +{VIDIOC_S_STD, "VIDIOC_S_STD"}, +#endif +#if defined(VIDIOC_ENUMSTD) +{VIDIOC_ENUMSTD, "VIDIOC_ENUMSTD"}, +#endif +#if defined(VIDIOC_ENUMINPUT) +{VIDIOC_ENUMINPUT, "VIDIOC_ENUMINPUT"}, +#endif +#if defined(VIDIOC_G_CTRL) +{VIDIOC_G_CTRL, "VIDIOC_G_CTRL"}, +#endif +#if defined(VIDIOC_S_CTRL) +{VIDIOC_S_CTRL, "VIDIOC_S_CTRL"}, +#endif +#if defined(VIDIOC_G_TUNER) +{VIDIOC_G_TUNER, "VIDIOC_G_TUNER"}, +#endif +#if defined(VIDIOC_S_TUNER) +{VIDIOC_S_TUNER, "VIDIOC_S_TUNER"}, +#endif +#if defined(VIDIOC_G_AUDIO) +{VIDIOC_G_AUDIO, "VIDIOC_G_AUDIO"}, +#endif +#if defined(VIDIOC_S_AUDIO) +{VIDIOC_S_AUDIO, "VIDIOC_S_AUDIO"}, +#endif +#if defined(VIDIOC_QUERYCTRL) +{VIDIOC_QUERYCTRL, "VIDIOC_QUERYCTRL"}, +#endif +#if defined(VIDIOC_QUERYMENU) +{VIDIOC_QUERYMENU, "VIDIOC_QUERYMENU"}, +#endif +#if defined(VIDIOC_G_INPUT) +{VIDIOC_G_INPUT, "VIDIOC_G_INPUT"}, +#endif +#if defined(VIDIOC_S_INPUT) +{VIDIOC_S_INPUT, "VIDIOC_S_INPUT"}, +#endif +#if defined(VIDIOC_G_OUTPUT) +{VIDIOC_G_OUTPUT, "VIDIOC_G_OUTPUT"}, +#endif +#if defined(VIDIOC_S_OUTPUT) +{VIDIOC_S_OUTPUT, "VIDIOC_S_OUTPUT"}, +#endif +#if defined(VIDIOC_ENUMOUTPUT) +{VIDIOC_ENUMOUTPUT, "VIDIOC_ENUMOUTPUT"}, +#endif +#if defined(VIDIOC_G_AUDOUT) +{VIDIOC_G_AUDOUT, "VIDIOC_G_AUDOUT"}, +#endif +#if defined(VIDIOC_S_AUDOUT) +{VIDIOC_S_AUDOUT, "VIDIOC_S_AUDOUT"}, +#endif +#if defined(VIDIOC_G_MODULATOR) +{VIDIOC_G_MODULATOR, "VIDIOC_G_MODULATOR"}, +#endif +#if defined(VIDIOC_S_MODULATOR) +{VIDIOC_S_MODULATOR, "VIDIOC_S_MODULATOR"}, +#endif +#if defined(VIDIOC_G_FREQUENCY) +{VIDIOC_G_FREQUENCY, "VIDIOC_G_FREQUENCY"}, +#endif +#if defined(VIDIOC_S_FREQUENCY) +{VIDIOC_S_FREQUENCY, "VIDIOC_S_FREQUENCY"}, +#endif +#if defined(VIDIOC_CROPCAP) +{VIDIOC_CROPCAP, "VIDIOC_CROPCAP"}, +#endif +#if defined(VIDIOC_G_CROP) +{VIDIOC_G_CROP, "VIDIOC_G_CROP"}, +#endif +#if defined(VIDIOC_S_CROP) +{VIDIOC_S_CROP, "VIDIOC_S_CROP"}, +#endif +#if defined(VIDIOC_G_JPEGCOMP) +{VIDIOC_G_JPEGCOMP, "VIDIOC_G_JPEGCOMP"}, +#endif +#if defined(VIDIOC_S_JPEGCOMP) +{VIDIOC_S_JPEGCOMP, "VIDIOC_S_JPEGCOMP"}, +#endif +#if defined(VIDIOC_QUERYSTD) +{VIDIOC_QUERYSTD, "VIDIOC_QUERYSTD"}, +#endif +#if defined(VIDIOC_TRY_FMT) +{VIDIOC_TRY_FMT, "VIDIOC_TRY_FMT"}, +#endif +#if defined(VIDIOC_ENUMAUDIO) +{VIDIOC_ENUMAUDIO, "VIDIOC_ENUMAUDIO"}, +#endif +#if defined(VIDIOC_ENUMAUDOUT) +{VIDIOC_ENUMAUDOUT, "VIDIOC_ENUMAUDOUT"}, +#endif +#if defined(VIDIOC_G_PRIORITY) +{VIDIOC_G_PRIORITY, "VIDIOC_G_PRIORITY"}, +#endif +#if defined(VIDIOC_S_PRIORITY) +{VIDIOC_S_PRIORITY, "VIDIOC_S_PRIORITY"}, +#endif +#if defined(VIDIOC_G_SLICED_VBI_CAP) +{VIDIOC_G_SLICED_VBI_CAP, "VIDIOC_G_SLICED_VBI_CAP"}, +#endif +#if defined(VIDIOC_LOG_STATUS) +{VIDIOC_LOG_STATUS, "VIDIOC_LOG_STATUS"}, +#endif +#if defined(VIDIOC_G_EXT_CTRLS) +{VIDIOC_G_EXT_CTRLS, "VIDIOC_G_EXT_CTRLS"}, +#endif +#if defined(VIDIOC_S_EXT_CTRLS) +{VIDIOC_S_EXT_CTRLS, "VIDIOC_S_EXT_CTRLS"}, +#endif +#if defined(VIDIOC_TRY_EXT_CTRLS) +{VIDIOC_TRY_EXT_CTRLS, "VIDIOC_TRY_EXT_CTRLS"}, +#endif +#if defined(VIDIOC_ENUM_FRAMESIZES) +{VIDIOC_ENUM_FRAMESIZES, "VIDIOC_ENUM_FRAMESIZES"}, +#endif +#if defined(VIDIOC_ENUM_FRAMEINTERVALS) +{VIDIOC_ENUM_FRAMEINTERVALS, "VIDIOC_ENUM_FRAMEINTERVALS"}, +#endif +#if defined(VIDIOC_G_ENC_INDEX) +{VIDIOC_G_ENC_INDEX, "VIDIOC_G_ENC_INDEX"}, +#endif +#if defined(VIDIOC_ENCODER_CMD) +{VIDIOC_ENCODER_CMD, "VIDIOC_ENCODER_CMD"}, +#endif +#if defined(VIDIOC_TRY_ENCODER_CMD) +{VIDIOC_TRY_ENCODER_CMD, "VIDIOC_TRY_ENCODER_CMD"}, +#endif +#if defined(VIDIOC_G_CHIP_IDENT) +{VIDIOC_G_CHIP_IDENT, "VIDIOC_G_CHIP_IDENT"}, +#endif + +#if defined(VIDIOC_OVERLAY_OLD) +{VIDIOC_OVERLAY_OLD, "VIDIOC_OVERLAY_OLD"}, +#endif +#if defined(VIDIOC_S_PARM_OLD) +{VIDIOC_S_PARM_OLD, "VIDIOC_S_PARM_OLD"}, +#endif +#if defined(VIDIOC_S_CTRL_OLD) +{VIDIOC_S_CTRL_OLD, "VIDIOC_S_CTRL_OLD"}, +#endif +#if defined(VIDIOC_G_AUDIO_OLD) +{VIDIOC_G_AUDIO_OLD, "VIDIOC_G_AUDIO_OLD"}, +#endif +#if defined(VIDIOC_G_AUDOUT_OLD) +{VIDIOC_G_AUDOUT_OLD, "VIDIOC_G_AUDOUT_OLD"}, +#endif +#if defined(VIDIOC_CROPCAP_OLD) +{VIDIOC_CROPCAP_OLD, "VIDIOC_CROPCAP_OLD"}, +#endif +{0xFFFFFFFF, ""} +}; + +static struct mess mess1[] = \ +{ +#if defined(VIDIOCGCAP) +{VIDIOCGCAP, "VIDIOCGCAP"}, +#endif +#if defined(VIDIOCGCHAN) +{VIDIOCGCHAN, "VIDIOCGCHAN"}, +#endif +#if defined(VIDIOCSCHAN) +{VIDIOCSCHAN, "VIDIOCSCHAN"}, +#endif +#if defined(VIDIOCGTUNER) +{VIDIOCGTUNER, "VIDIOCGTUNER"}, +#endif +#if defined(VIDIOCSTUNER) +{VIDIOCSTUNER, "VIDIOCSTUNER"}, +#endif +#if defined(VIDIOCGPICT) +{VIDIOCGPICT, "VIDIOCGPICT"}, +#endif +#if defined(VIDIOCSPICT) +{VIDIOCSPICT, "VIDIOCSPICT"}, +#endif +#if defined(VIDIOCCAPTURE) +{VIDIOCCAPTURE, "VIDIOCCAPTURE"}, +#endif +#if defined(VIDIOCGWIN) +{VIDIOCGWIN, "VIDIOCGWIN"}, +#endif +#if defined(VIDIOCSWIN) +{VIDIOCSWIN, "VIDIOCSWIN"}, +#endif +#if defined(VIDIOCGFBUF) +{VIDIOCGFBUF, "VIDIOCGFBUF"}, +#endif +#if defined(VIDIOCSFBUF) +{VIDIOCSFBUF, "VIDIOCSFBUF"}, +#endif +#if defined(VIDIOCKEY) +{VIDIOCKEY, "VIDIOCKEY"}, +#endif +#if defined(VIDIOCGFREQ) +{VIDIOCGFREQ, "VIDIOCGFREQ"}, +#endif +#if defined(VIDIOCSFREQ) +{VIDIOCSFREQ, "VIDIOCSFREQ"}, +#endif +#if defined(VIDIOCGAUDIO) +{VIDIOCGAUDIO, "VIDIOCGAUDIO"}, +#endif +#if defined(VIDIOCSAUDIO) +{VIDIOCSAUDIO, "VIDIOCSAUDIO"}, +#endif +#if defined(VIDIOCSYNC) +{VIDIOCSYNC, "VIDIOCSYNC"}, +#endif +#if defined(VIDIOCMCAPTURE) +{VIDIOCMCAPTURE, "VIDIOCMCAPTURE"}, +#endif +#if defined(VIDIOCGMBUF) +{VIDIOCGMBUF, "VIDIOCGMBUF"}, +#endif +#if defined(VIDIOCGUNIT) +{VIDIOCGUNIT, "VIDIOCGUNIT"}, +#endif +#if defined(VIDIOCGCAPTURE) +{VIDIOCGCAPTURE, "VIDIOCGCAPTURE"}, +#endif +#if defined(VIDIOCSCAPTURE) +{VIDIOCSCAPTURE, "VIDIOCSCAPTURE"}, +#endif +#if defined(VIDIOCSPLAYMODE) +{VIDIOCSPLAYMODE, "VIDIOCSPLAYMODE"}, +#endif +#if defined(VIDIOCSWRITEMODE) +{VIDIOCSWRITEMODE, "VIDIOCSWRITEMODE"}, +#endif +#if defined(VIDIOCGPLAYINFO) +{VIDIOCGPLAYINFO, "VIDIOCGPLAYINFO"}, +#endif +#if defined(VIDIOCSMICROCODE) +{VIDIOCSMICROCODE, "VIDIOCSMICROCODE"}, +#endif +{0xFFFFFFFF, ""} +}; + +k = 0; +while (mess[k].name[0]) { + if (wot == mess[k].command) { + JOT(8, "ioctl 0x%08X is %s\n", \ + mess[k].command, &mess[k].name[0]); + return 0; + } + k++; +} +JOT(8, "ioctl 0x%08X is not in videodev2.h\n", wot); + +k = 0; +while (mess1[k].name[0]) { + if (wot == mess1[k].command) { + JOT(8, "ioctl 0x%08X is %s (V4L1)\n", \ + mess1[k].command, &mess1[k].name[0]); + return 0; + } + k++; +} +JOT(8, "ioctl 0x%08X is not in videodev.h\n", wot); +return -1; +} +/*****************************************************************************/ +int explain_cid(__u32 wot) +{ +int k; +/*---------------------------------------------------------------------------*/ +/* + * THE DATA FOR THE ARRAY mess BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING + * SHELL SCRIPT: + * # + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev2.h | \ + * grep "^#define V4L2_CID_" | \ + * sed -e "s,(.*$,,;p" | sed -e "N;s,\n,, " | \ + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ + * sed -e "s, ,,g;s, ,,g" | grep -v "_BASE" | grep -v "MPEG" >cid.tmp + * echo "{0xFFFFFFFF,\"\"}" >>cid.tmp + * exit 0 + * # + */ +/*---------------------------------------------------------------------------*/ +static struct mess +{ +__u32 command; +char name[64]; +} mess[] = { +#if defined(V4L2_CID_USER_CLASS) +{V4L2_CID_USER_CLASS, "V4L2_CID_USER_CLASS"}, +#endif +#if defined(V4L2_CID_BRIGHTNESS) +{V4L2_CID_BRIGHTNESS, "V4L2_CID_BRIGHTNESS"}, +#endif +#if defined(V4L2_CID_CONTRAST) +{V4L2_CID_CONTRAST, "V4L2_CID_CONTRAST"}, +#endif +#if defined(V4L2_CID_SATURATION) +{V4L2_CID_SATURATION, "V4L2_CID_SATURATION"}, +#endif +#if defined(V4L2_CID_HUE) +{V4L2_CID_HUE, "V4L2_CID_HUE"}, +#endif +#if defined(V4L2_CID_AUDIO_VOLUME) +{V4L2_CID_AUDIO_VOLUME, "V4L2_CID_AUDIO_VOLUME"}, +#endif +#if defined(V4L2_CID_AUDIO_BALANCE) +{V4L2_CID_AUDIO_BALANCE, "V4L2_CID_AUDIO_BALANCE"}, +#endif +#if defined(V4L2_CID_AUDIO_BASS) +{V4L2_CID_AUDIO_BASS, "V4L2_CID_AUDIO_BASS"}, +#endif +#if defined(V4L2_CID_AUDIO_TREBLE) +{V4L2_CID_AUDIO_TREBLE, "V4L2_CID_AUDIO_TREBLE"}, +#endif +#if defined(V4L2_CID_AUDIO_MUTE) +{V4L2_CID_AUDIO_MUTE, "V4L2_CID_AUDIO_MUTE"}, +#endif +#if defined(V4L2_CID_AUDIO_LOUDNESS) +{V4L2_CID_AUDIO_LOUDNESS, "V4L2_CID_AUDIO_LOUDNESS"}, +#endif +#if defined(V4L2_CID_BLACK_LEVEL) +{V4L2_CID_BLACK_LEVEL, "V4L2_CID_BLACK_LEVEL"}, +#endif +#if defined(V4L2_CID_AUTO_WHITE_BALANCE) +{V4L2_CID_AUTO_WHITE_BALANCE, "V4L2_CID_AUTO_WHITE_BALANCE"}, +#endif +#if defined(V4L2_CID_DO_WHITE_BALANCE) +{V4L2_CID_DO_WHITE_BALANCE, "V4L2_CID_DO_WHITE_BALANCE"}, +#endif +#if defined(V4L2_CID_RED_BALANCE) +{V4L2_CID_RED_BALANCE, "V4L2_CID_RED_BALANCE"}, +#endif +#if defined(V4L2_CID_BLUE_BALANCE) +{V4L2_CID_BLUE_BALANCE, "V4L2_CID_BLUE_BALANCE"}, +#endif +#if defined(V4L2_CID_GAMMA) +{V4L2_CID_GAMMA, "V4L2_CID_GAMMA"}, +#endif +#if defined(V4L2_CID_WHITENESS) +{V4L2_CID_WHITENESS, "V4L2_CID_WHITENESS"}, +#endif +#if defined(V4L2_CID_EXPOSURE) +{V4L2_CID_EXPOSURE, "V4L2_CID_EXPOSURE"}, +#endif +#if defined(V4L2_CID_AUTOGAIN) +{V4L2_CID_AUTOGAIN, "V4L2_CID_AUTOGAIN"}, +#endif +#if defined(V4L2_CID_GAIN) +{V4L2_CID_GAIN, "V4L2_CID_GAIN"}, +#endif +#if defined(V4L2_CID_HFLIP) +{V4L2_CID_HFLIP, "V4L2_CID_HFLIP"}, +#endif +#if defined(V4L2_CID_VFLIP) +{V4L2_CID_VFLIP, "V4L2_CID_VFLIP"}, +#endif +#if defined(V4L2_CID_HCENTER) +{V4L2_CID_HCENTER, "V4L2_CID_HCENTER"}, +#endif +#if defined(V4L2_CID_VCENTER) +{V4L2_CID_VCENTER, "V4L2_CID_VCENTER"}, +#endif +#if defined(V4L2_CID_POWER_LINE_FREQUENCY) +{V4L2_CID_POWER_LINE_FREQUENCY, "V4L2_CID_POWER_LINE_FREQUENCY"}, +#endif +#if defined(V4L2_CID_HUE_AUTO) +{V4L2_CID_HUE_AUTO, "V4L2_CID_HUE_AUTO"}, +#endif +#if defined(V4L2_CID_WHITE_BALANCE_TEMPERATURE) +{V4L2_CID_WHITE_BALANCE_TEMPERATURE, "V4L2_CID_WHITE_BALANCE_TEMPERATURE"}, +#endif +#if defined(V4L2_CID_SHARPNESS) +{V4L2_CID_SHARPNESS, "V4L2_CID_SHARPNESS"}, +#endif +#if defined(V4L2_CID_BACKLIGHT_COMPENSATION) +{V4L2_CID_BACKLIGHT_COMPENSATION, "V4L2_CID_BACKLIGHT_COMPENSATION"}, +#endif +#if defined(V4L2_CID_CHROMA_AGC) +{V4L2_CID_CHROMA_AGC, "V4L2_CID_CHROMA_AGC"}, +#endif +#if defined(V4L2_CID_COLOR_KILLER) +{V4L2_CID_COLOR_KILLER, "V4L2_CID_COLOR_KILLER"}, +#endif +#if defined(V4L2_CID_LASTP1) +{V4L2_CID_LASTP1, "V4L2_CID_LASTP1"}, +#endif +#if defined(V4L2_CID_CAMERA_CLASS) +{V4L2_CID_CAMERA_CLASS, "V4L2_CID_CAMERA_CLASS"}, +#endif +#if defined(V4L2_CID_EXPOSURE_AUTO) +{V4L2_CID_EXPOSURE_AUTO, "V4L2_CID_EXPOSURE_AUTO"}, +#endif +#if defined(V4L2_CID_EXPOSURE_ABSOLUTE) +{V4L2_CID_EXPOSURE_ABSOLUTE, "V4L2_CID_EXPOSURE_ABSOLUTE"}, +#endif +#if defined(V4L2_CID_EXPOSURE_AUTO_PRIORITY) +{V4L2_CID_EXPOSURE_AUTO_PRIORITY, "V4L2_CID_EXPOSURE_AUTO_PRIORITY"}, +#endif +#if defined(V4L2_CID_PAN_RELATIVE) +{V4L2_CID_PAN_RELATIVE, "V4L2_CID_PAN_RELATIVE"}, +#endif +#if defined(V4L2_CID_TILT_RELATIVE) +{V4L2_CID_TILT_RELATIVE, "V4L2_CID_TILT_RELATIVE"}, +#endif +#if defined(V4L2_CID_PAN_RESET) +{V4L2_CID_PAN_RESET, "V4L2_CID_PAN_RESET"}, +#endif +#if defined(V4L2_CID_TILT_RESET) +{V4L2_CID_TILT_RESET, "V4L2_CID_TILT_RESET"}, +#endif +#if defined(V4L2_CID_PAN_ABSOLUTE) +{V4L2_CID_PAN_ABSOLUTE, "V4L2_CID_PAN_ABSOLUTE"}, +#endif +#if defined(V4L2_CID_TILT_ABSOLUTE) +{V4L2_CID_TILT_ABSOLUTE, "V4L2_CID_TILT_ABSOLUTE"}, +#endif +#if defined(V4L2_CID_FOCUS_ABSOLUTE) +{V4L2_CID_FOCUS_ABSOLUTE, "V4L2_CID_FOCUS_ABSOLUTE"}, +#endif +#if defined(V4L2_CID_FOCUS_RELATIVE) +{V4L2_CID_FOCUS_RELATIVE, "V4L2_CID_FOCUS_RELATIVE"}, +#endif +#if defined(V4L2_CID_FOCUS_AUTO) +{V4L2_CID_FOCUS_AUTO, "V4L2_CID_FOCUS_AUTO"}, +#endif +{0xFFFFFFFF, ""} +}; + +k = 0; +while (mess[k].name[0]) { + if (wot == mess[k].command) { + JOT(8, "ioctl 0x%08X is %s\n", \ + mess[k].command, &mess[k].name[0]); + return 0; + } + k++; +} +JOT(8, "cid 0x%08X is not in videodev2.h\n", wot); +return -1; +} +/*****************************************************************************/ diff --git a/drivers/staging/easycap/easycap_ioctl.h b/drivers/staging/easycap/easycap_ioctl.h new file mode 100644 index 000000000000..7cab0943d913 --- /dev/null +++ b/drivers/staging/easycap/easycap_ioctl.h @@ -0,0 +1,29 @@ +/***************************************************************************** +* * +* easycap_ioctl.h * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +extern struct easycap_format easycap_format[]; +extern struct v4l2_queryctrl easycap_control[]; +extern unsigned int audio_bytes_per_fragment; diff --git a/drivers/staging/easycap/easycap_low.c b/drivers/staging/easycap/easycap_low.c new file mode 100644 index 000000000000..e7c189af1476 --- /dev/null +++ b/drivers/staging/easycap/easycap_low.c @@ -0,0 +1,1057 @@ +/***************************************************************************** +* * +* * +* easycap_low.c * +* * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +/* + * ACKNOWLEGEMENTS AND REFERENCES + * ------------------------------ + * This driver makes use of register information contained in the Syntek + * Semicon DC-1125 driver hosted at + * http://sourceforge.net/projects/syntekdriver/. + * Particularly useful has been a patch to the latter driver provided by + * Ivor Hewitt in January 2009. The NTSC implementation is taken from the + * work of Ben Trask. +*/ +/****************************************************************************/ + +#include "easycap_debug.h" +#include "easycap.h" + +/*--------------------------------------------------------------------------*/ +const struct stk1160config { int reg; int set; } stk1160config[256] = { + {0x000, 0x0098}, + {0x002, 0x0093}, + + {0x001, 0x0003}, + {0x003, 0x0080}, + {0x00D, 0x0000}, + {0x00F, 0x0002}, + {0x018, 0x0010}, + {0x019, 0x0000}, + {0x01A, 0x0014}, + {0x01B, 0x000E}, + {0x01C, 0x0046}, + + {0x100, 0x0033}, + {0x103, 0x0000}, + {0x104, 0x0000}, + {0x105, 0x0000}, + {0x106, 0x0000}, + +#if defined(PREFER_NTSC) + +#undef OLDMARGIN +#if defined(OLDMARGIN) + {0x110, 0x0008}, +#else + {0x110, 0x0014}, +#endif /*OLDMARGIN*/ + + {0x111, 0x0000}, + {0x112, 0x0003}, + {0x113, 0x0000}, + +#if defined(OLDMARGIN) + {0x114, 0x0508}, +#else + {0x114, 0x0514}, +#endif /*OLDMARGIN*/ + + {0x115, 0x0005}, + {0x116, 0x00F3}, + {0x117, 0x0000}, + +#else /* ! PREFER_NTSC*/ + +#if defined(OLDMARGIN) + {0x110, 0x0008}, +#else + {0x110, 0x0014}, +#endif /*OLDMARGIN*/ + + {0x111, 0x0000}, + {0x112, 0x0020}, + {0x113, 0x0000}, + +#if defined(OLDMARGIN) + {0x114, 0x0508}, +#else + {0x114, 0x0514}, +#endif /*OLDMARGIN*/ + + {0x115, 0x0005}, + {0x116, 0x0110}, + {0x117, 0x0001}, + +#endif /* ! PREFER_NTSC*/ + + {0x202, 0x000F}, + {0x203, 0x004A}, + {0x2FF, 0x0000}, +/*---------------------------------------------------------------------------*/ + {0xFFF, 0xFFFF} + }; +/*--------------------------------------------------------------------------*/ +const struct saa7113config { int reg; int set; } saa7113config[256] = { + {0x01, 0x08}, + {0x02, 0x80}, + {0x03, 0x33}, + {0x04, 0x00}, + {0x05, 0x00}, + {0x06, 0xE9}, + {0x07, 0x0D}, +#if defined(PREFER_NTSC) + {0x08, 0x78}, +#else + {0x08, 0x38}, +#endif /* ! PREFER_NTSC*/ + {0x09, 0x00}, + {0x0A, SAA_0A_DEFAULT}, + {0x0B, SAA_0B_DEFAULT}, + {0x0C, SAA_0C_DEFAULT}, + {0x0D, SAA_0D_DEFAULT}, + {0x0E, 0x01}, + {0x0F, 0x36}, + {0x10, 0x00}, + {0x11, 0x0C}, + {0x12, 0xE7}, + {0x13, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, +#if defined(PREFER_NTSC) + {0x40, 0x82}, +#else + {0x40, 0x02}, +#endif /* ! PREFER_NTSC*/ + {0x41, 0xFF}, + {0x42, 0xFF}, + {0x43, 0xFF}, + {0x44, 0xFF}, + {0x45, 0xFF}, + {0x46, 0xFF}, + {0x47, 0xFF}, + {0x48, 0xFF}, + {0x49, 0xFF}, + {0x4A, 0xFF}, + {0x4B, 0xFF}, + {0x4C, 0xFF}, + {0x4D, 0xFF}, + {0x4E, 0xFF}, + {0x4F, 0xFF}, + {0x50, 0xFF}, + {0x51, 0xFF}, + {0x52, 0xFF}, + {0x53, 0xFF}, + {0x54, 0xFF}, + {0x55, 0xFF}, + {0x56, 0xFF}, + {0x57, 0xFF}, + {0x58, 0x40}, + {0x59, 0x54}, +#if defined(PREFER_NTSC) + {0x5A, 0x0A}, +#else + {0x5A, 0x07}, +#endif /* ! PREFER_NTSC*/ + {0x5B, 0x83}, + {0xFF, 0xFF} + }; +/*--------------------------------------------------------------------------*/ + +/****************************************************************************/ +int +confirm_resolution(struct usb_device *p) +{ +__u8 get0, get1, get2, get3, get4, get5, get6, get7; +GET(p, 0x0110, &get0); +GET(p, 0x0111, &get1); +GET(p, 0x0112, &get2); +GET(p, 0x0113, &get3); +GET(p, 0x0114, &get4); +GET(p, 0x0115, &get5); +GET(p, 0x0116, &get6); +GET(p, 0x0117, &get7); +JOT(8, "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X\n", \ + get0, get1, get2, get3, get4, get5, get6, get7); +JOT(8, "....cf PAL_720x526: " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X\n", \ + 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001); +JOT(8, "....cf PAL_704x526: " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X\n", \ + 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001); +JOT(8, "....cf VGA_640x480: " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X, " \ + "0x%03X, 0x%03X\n", \ + 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001); +return 0; +} +/****************************************************************************/ +int +confirm_stream(struct usb_device *p) +{ +__u16 get2; +__u8 igot; + +GET(p, 0x0100, &igot); get2 = 0x80 & igot; +if (0x80 == get2) + JOT(8, "confirm_stream: OK\n"); +else + JOT(8, "confirm_stream: STUCK\n"); +return 0; +} +/****************************************************************************/ +int +setup_stk(struct usb_device *p) +{ +int i0; + +i0 = 0; +while (0xFFF != stk1160config[i0].reg) { + SET(p, stk1160config[i0].reg, stk1160config[i0].set); + i0++; + } + +write_300(p); + +return 0; +} +/****************************************************************************/ +int +setup_saa(struct usb_device *p) +{ +int i0, ir; + + +set2to78(p); + + +i0 = 0; +while (0xFF != saa7113config[i0].reg) { + ir = write_saa(p, saa7113config[i0].reg, saa7113config[i0].set); + i0++; + } +return 0; +} +/****************************************************************************/ +int +write_000(struct usb_device *p, __u16 set2, __u16 set0) +{ +__u8 igot0, igot2; + +GET(p, 0x0002, &igot2); +GET(p, 0x0000, &igot0); +SET(p, 0x0002, set2); +SET(p, 0x0000, set0); +return 0; +} +/****************************************************************************/ +int +write_saa(struct usb_device *p, __u16 reg0, __u16 set0) +{ +SET(p, 0x200, 0x00); +SET(p, 0x204, reg0); +SET(p, 0x205, set0); +SET(p, 0x200, 0x01); +return wait_i2c(p); +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) + * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A + * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET + * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET + * REGISTER 504: TARGET ADDRESS ON VT1612A + */ +/*--------------------------------------------------------------------------*/ +int +write_vt(struct usb_device *p, __u16 reg0, __u16 set0) +{ +__u8 igot; +__u16 got502, got503; +__u16 set502, set503; + +SET(p, 0x0504, reg0); +SET(p, 0x0500, 0x008B); + +GET(p, 0x0502, &igot); got502 = (0xFF & igot); +GET(p, 0x0503, &igot); got503 = (0xFF & igot); + +JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n", \ + reg0, set0, ((got503 << 8) | got502)); + +set502 = (0x00FF & set0); +set503 = ((0xFF00 & set0) >> 8); + +SET(p, 0x0504, reg0); +SET(p, 0x0502, set502); +SET(p, 0x0503, set503); +SET(p, 0x0500, 0x008C); + +return 0; +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) + * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A + * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET + * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET + * REGISTER 504: TARGET ADDRESS ON VT1612A + */ +/*--------------------------------------------------------------------------*/ +int +read_vt(struct usb_device *p, __u16 reg0) +{ +__u8 igot; +__u16 got502, got503; + +SET(p, 0x0504, reg0); +SET(p, 0x0500, 0x008B); + +GET(p, 0x0502, &igot); got502 = (0xFF & igot); +GET(p, 0x0503, &igot); got503 = (0xFF & igot); + +JOT(16, "read_vt(., 0x%04X): has 0x%04X\n", reg0, ((got503 << 8) | got502)); + +return (got503 << 8) | got502; +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO. + */ +/*--------------------------------------------------------------------------*/ +int +write_300(struct usb_device *p) +{ +SET(p, 0x300, 0x0012); +SET(p, 0x350, 0x002D); +SET(p, 0x351, 0x0001); +SET(p, 0x352, 0x0000); +SET(p, 0x353, 0x0000); +SET(p, 0x300, 0x0080); +return 0; +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * NOTE: THE FOLLOWING IS NOT CHECKED: + * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL. + */ +/*--------------------------------------------------------------------------*/ +int +check_saa(struct usb_device *p) +{ +int i0, ir, rc; +i0 = 0; + +rc = 0; +while (0xFF != saa7113config[i0].reg) { + if (0x0F == saa7113config[i0].reg) { + i0++; continue; + } + + ir = read_saa(p, saa7113config[i0].reg); + if (ir != saa7113config[i0].set) { + SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", \ + saa7113config[i0].reg, ir, saa7113config[i0].set); + rc--; + } + i0++; +} +if (-8 > rc) + return rc; +else + return 0; +} +/****************************************************************************/ +int +merit_saa(struct usb_device *p) +{ +int rc; + +rc = read_saa(p, 0x1F); +if ((0 > rc) || (0x02 & rc)) + return 1 ; +else + return 0; +} +/****************************************************************************/ +int +ready_saa(struct usb_device *p) +{ +int j, rc; +static int max = 10; + +j = 0; +while (max > j) { + rc = read_saa(p, 0x1F); + if (0 <= rc) { + if ((1 == (0x01 & rc))&&(0 == (0x40 & rc))) + break; + } + msleep(100); j++; +} +if (max == j) + return -1; +else { + if (0x20 & rc) + JOT(8, "hardware detects 60 Hz\n"); + else + JOT(8, "hardware detects 50 Hz\n"); + if (0x80 & rc) + JOT(8, "hardware detects interlacing\n"); + else + JOT(8, "hardware detects no interlacing\n"); +} +return 0; +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * NOTE: THE FOLLOWING ARE NOT CHECKED: + * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN + * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config[.].set) + */ +/*--------------------------------------------------------------------------*/ +int +check_stk(struct usb_device *p) +{ +int i0, ir; +i0 = 0; +while (0xFFF != stk1160config[i0].reg) { + if (0x000 == stk1160config[i0].reg) { + i0++; continue; + } + if (0x002 == stk1160config[i0].reg) { + i0++; continue; + } + + ir = read_stk(p, stk1160config[i0].reg); + + if (0x100 == stk1160config[i0].reg) { + if ((ir != (0xFF & stk1160config[i0].set)) && \ + (ir != (0x80 | (0xFF & stk1160config[i0].set))) && \ + (0xFFFF != stk1160config[i0].set)) { + SAY("STK register 0x%03X has 0x%02X, " \ + "expected 0x%02X\n", \ + stk1160config[i0].reg, ir, \ + stk1160config[i0].set); + } + i0++; continue; + } + + if ((ir != (0xFF & stk1160config[i0].set)) && \ + (0xFFFF != stk1160config[i0].set)) { + SAY("STK register 0x%03X has 0x%02X, " \ + "expected 0x%02X\n", \ + stk1160config[i0].reg, ir, \ + stk1160config[i0].set); + } + i0++; + } +return 0; +} +/****************************************************************************/ +int +read_saa(struct usb_device *p, __u16 reg0) +{ +__u8 igot; + +SET(p, 0x208, reg0); +SET(p, 0x200, 0x20); +if (0 != wait_i2c(p)) + return -1; +igot = 0; +GET(p, 0x0209, &igot); +return igot; +} +/****************************************************************************/ +int +read_stk(struct usb_device *p, __u32 reg0) +{ +__u8 igot; + +igot = 0; +GET(p, reg0, &igot); +return igot; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE + * + * CVBS+S-VIDEO 0 or 1 CVBS 1 + * FOUR-CVBS 0 or 1 CVBS1 1 + * FOUR-CVBS 2 CVBS2 2 + * FOUR-CVBS 3 CVBS3 3 + * FOUR-CVBS 4 CVBS4 4 + * CVBS+S-VIDEO 5 S-VIDEO 5 + * + * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED: + * + * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED) + * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT) + * +*/ +/*---------------------------------------------------------------------------*/ +int +select_input(struct usb_device *p, int input, int mode) +{ + +stop_100(p); + +msleep(20); +switch (input) { +case 0: +case 1: { + SET(p, 0x0000, 0x0098); break; +} +case 2: { + SET(p, 0x0000, 0x0090); break; +} +case 3: { + SET(p, 0x0000, 0x0088); break; +} +case 4: { + SET(p, 0x0000, 0x0080); break; +} +case 5: { + if (9 != mode) + mode = 7; + switch (mode) { + case 7: + { + if (0 != write_saa(p, 0x02, 0x87)) { + SAY("ERROR: failed to set SAA " \ + "register 0x02 for input " \ + "%i\n", input); + } + if (0 != write_saa(p, 0x05, 0xFF)) { + SAY("ERROR: failed to set SAA " \ + "register 0x05 for input " \ + "%i\n", input); + } + break; + } + case 9: + { + if (0 != write_saa(p, 0x02, 0x89)) { + SAY("ERROR: failed to set SAA " \ + "register 0x02 for input " \ + "%i\n", input); + } + if (0 != write_saa(p, 0x05, 0x00)) { + SAY("ERROR: failed to set SAA " \ + "register 0x05 for input " \ + "%i\n", input); + } + break; + } + default: + { + SAY("MISTAKE: bad mode: %i\n", mode); + return -1; + } + } + if (0 != write_saa(p, 0x04, 0x00)) { + SAY("ERROR: failed to set SAA register 0x04 " \ + "for input %i\n", input); + } + if (0 != write_saa(p, 0x09, 0x80)) { + SAY("ERROR: failed to set SAA register 0x09 " \ + "for input %i\n", input); + } + break; +} +default: + { + SAY("ERROR: bad input: %i\n", input); + return -1; +} +} +msleep(20); +SET(p, 0x0002, 0x0093); +msleep(20); + +start_100(p); + +return 0; +} +/****************************************************************************/ +int +set_resolution(struct usb_device *p, \ + __u16 set0, __u16 set1, __u16 set2, __u16 set3) +{ +__u16 u0x0111, u0x0113, u0x0115, u0x0117; + +u0x0111 = ((0xFF00 & set0) >> 8); +u0x0113 = ((0xFF00 & set1) >> 8); +u0x0115 = ((0xFF00 & set2) >> 8); +u0x0117 = ((0xFF00 & set3) >> 8); + +SET(p, 0x0110, (0x00FF & set0)); +SET(p, 0x0111, u0x0111); +SET(p, 0x0112, (0x00FF & set1)); +SET(p, 0x0113, u0x0113); +SET(p, 0x0114, (0x00FF & set2)); +SET(p, 0x0115, u0x0115); +SET(p, 0x0116, (0x00FF & set3)); +SET(p, 0x0117, u0x0117); + +return 0; +} +/****************************************************************************/ +int +start_100(struct usb_device *p) +{ +__u16 get0; +__u8 igot; + +GET(p, 0x0100, &igot); get0 = igot; +msleep(0x1f4); +SET(p, 0x0100, (0x80 | get0)); +msleep(0x1f4); +return 0; +} +/****************************************************************************/ +int +stop_100(struct usb_device *p) +{ +__u16 get0; +__u8 igot; + +GET(p, 0x0100, &igot); get0 = igot; +msleep(0x1f4); +SET(p, 0x0100, (0x7F & get0)); +msleep(0x1f4); +return 0; +} +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS +*/ +/*--------------------------------------------------------------------------*/ +int +wait_i2c(struct usb_device *p) +{ +__u16 get0; +__u8 igot; +const int max = 4; +int k; + +for (k = 0; k < max; k++) { + GET(p, 0x0201, &igot); get0 = igot; + switch (get0) { + case 0x04: + case 0x01: { + return 0; + } + case 0x00: { + msleep(10); + continue; + } + default: { + return get0 - 1; + } + } +} +return -1; +} +/****************************************************************************/ +int +regset(struct usb_device *pusb_device, __u16 index, __u16 value) +{ +__u16 igot; +int rc0, rc1; + +if (!pusb_device) + return -EFAULT; + +rc1 = 0; igot = 0; +rc0 = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ + (__u8)0x01, \ + (__u8)(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ + (__u16)value, \ + (__u16)index, \ + (void *)NULL, \ + (__u16)0, \ + (int)500); + +#if defined(NOREADBACK) +# +#else +rc1 = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \ + (__u8)0x00, \ + (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ + (__u16)0x00, \ + (__u16)index, \ + (void *)&igot, \ + (__u16)sizeof(__u16), \ + (int)50000); +igot = 0xFF & igot; +switch (index) { +case 0x000: +case 0x500: +case 0x502: +case 0x503: +case 0x504: +case 0x506: +case 0x507: { + break; +} +case 0x204: +case 0x205: +case 0x350: +case 0x351: { + if (0 != igot) { + JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \ + igot, index); + } +break; +} +case 0x114: +case 0x116: { + if ((0xFF & value) != igot) { + JOT(8, "unexpected 0x%02X != 0x%02X " \ + "for STK register 0x%03X\n", \ + igot, value, index); + } +break; +} +case 0x200: { + if (0 == igot) + break; +} +default: { + if (value != igot) { + JOT(8, "unexpected 0x%02X != 0x%02X " \ + "for STK register 0x%03X\n", \ + igot, value, index); + } +break; +} +} +#endif /* ! NOREADBACK*/ + +return (0 > rc0) ? rc0 : rc1; +} +/*****************************************************************************/ +int +regget(struct usb_device *pusb_device, __u16 index, void *pvoid) +{ +int ir; + +if (!pusb_device) + return -EFAULT; + +ir = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \ + (__u8)0x00, \ + (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ + (__u16)0x00, \ + (__u16)index, \ + (void *)pvoid, \ + sizeof(__u8), \ + (int)50000); +return 0xFF & ir; +} +/*****************************************************************************/ +int +wakeup_device(struct usb_device *pusb_device) +{ +return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ + (__u8)USB_REQ_SET_FEATURE, \ + (__u8)(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE), \ + USB_DEVICE_REMOTE_WAKEUP, \ + (__u16)0, \ + (void *) NULL, \ + (__u16)0, \ + (int)50000); +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * IMPORTANT: + * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) + * CAUSES MUTING IF THE VALUE 0x0100 IS SENT. + * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT. + */ +/*---------------------------------------------------------------------------*/ +int +audio_setup(struct easycap *peasycap) +{ +struct usb_device *pusb_device; +static __u8 request = 0x01; +static __u8 requesttype = \ + (__u8)(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); + +static __u16 value_unmute = 0x0200; +static __u16 index = 0x0301; + +static unsigned char buffer[1]; +static __u16 length = 1; +int rc; + +if (NULL == peasycap) + return -EFAULT; + +pusb_device = peasycap->pusb_device; +if (NULL == pusb_device) + return -EFAULT; + +JOT(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", \ + requesttype, request, \ + (0x00FF & value_unmute), \ + (0xFF00 & value_unmute) >> 8, \ + (0x00FF & index), \ + (0xFF00 & index) >> 8, \ + (0x00FF & length), \ + (0xFF00 & length) >> 8); + +buffer[0] = 0x01; + +rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ + (__u8)request, \ + (__u8)requesttype, \ + (__u16)value_unmute, \ + (__u16)index, \ + (void *)&buffer[0], \ + (__u16)length, \ + (int)50000); + +JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0])); +if (rc != (int)length) + SAY("ERROR: usb_control_msg returned %i\n", rc); + +/*--------------------------------------------------------------------------*/ +/* + * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ??? + * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ??? + * FOR THE CVBS+S-VIDEO HARDWARE: + * SETTING VALUE TO 0x0000 GIVES QUIET SOUND. + * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. + * FOR THE FOUR-CVBS HARDWARE: + * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT. + * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ??? + * FOR THE CVBS-S-VIDEO HARDWARE: + * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND. + * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. + */ +/*--------------------------------------------------------------------------*/ + +SET(pusb_device, 0x0500, 0x0094); + +SET(pusb_device, 0x0500, 0x008C); + +SET(pusb_device, 0x0506, 0x0001); +SET(pusb_device, 0x0507, 0x0000); + +if (false == peasycap->microphone) { + /*-------------------------------------------------------------------*/ + /* + * SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0dB. + */ + /*-------------------------------------------------------------------*/ + write_vt(pusb_device, 0x0002, 0x8000); + write_vt(pusb_device, 0x001C, 0x8000); + + write_vt(pusb_device, 0x000E, 0x0000); + write_vt(pusb_device, 0x0010, 0x0000); + write_vt(pusb_device, 0x0012, 0x8000); + write_vt(pusb_device, 0x0016, 0x0000); + + write_vt(pusb_device, 0x001A, 0x0404); + write_vt(pusb_device, 0x0002, 0x0000); + write_vt(pusb_device, 0x001C, 0x0000); +} else { + /*-------------------------------------------------------------------*/ + /* + * SELECT AUDIO SOURCE "MIC" AND SET DEFAULT GAIN TO 0 dB. + * + * REGISTER 0x000E CAN BE SET TO PROVIDE UP TO 34.5 dB ATTENTUATION, + * BUT THIS HAS NOT PROVED NECESSARY FOR THE FEW SIGNAL SOURCES + * TESTED HITHERTO. + */ + /*-------------------------------------------------------------------*/ + write_vt(pusb_device, 0x0006, 0x8000); + write_vt(pusb_device, 0x001C, 0x8000); + + write_vt(pusb_device, 0x000E, 0x0008); + + write_vt(pusb_device, 0x0010, 0x0000); + write_vt(pusb_device, 0x0012, 0x8000); + write_vt(pusb_device, 0x0016, 0x0000); + + write_vt(pusb_device, 0x001A, 0x0000); + write_vt(pusb_device, 0x0006, 0x0000); + write_vt(pusb_device, 0x001C, 0x0000); +} + +check_vt(pusb_device); + +return 0; +} +/*****************************************************************************/ +int +check_vt(struct usb_device *pusb_device) +{ +int igot; + +igot = read_vt(pusb_device, 0x0002); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x02\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x02); + +igot = read_vt(pusb_device, 0x000E); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x0E\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x0E); + +igot = read_vt(pusb_device, 0x0010); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x10\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x10); + +igot = read_vt(pusb_device, 0x0012); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x12\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x12); + +igot = read_vt(pusb_device, 0x0016); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x16\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x16); + +igot = read_vt(pusb_device, 0x001A); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x1A\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x1A); + +igot = read_vt(pusb_device, 0x001C); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x1C\n"); +if (0x8000 & igot) + SAY("register 0x%02X muted\n", 0x1C); + +return 0; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY: + * audio_gainset(pusb_device, 0x000F); + * + * IF 16 loud) + loud = 16; +u8 = 0x000F & (__u8)(loud - 16); + +write_vt(pusb_device, 0x0002, 0x8000); + +igot = read_vt(pusb_device, 0x001C); +if (0 > igot) { + SAY("ERROR: failed to read VT1612A register 0x1C\n"); + mute = 0x0000; +} else + mute = 0x8000 & ((unsigned int)igot); + +JOT(8, "0x%04X=(mute|u8|(u8<<8))\n", mute | u8 | (u8 << 8)); + +write_vt(pusb_device, 0x001C, 0x8000); +write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8))); +write_vt(pusb_device, 0x0002, 0x0000); + +return 0; +} +/*****************************************************************************/ +int +audio_gainget(struct usb_device *pusb_device) +{ +int igot; + +igot = read_vt(pusb_device, 0x001C); +if (0 > igot) + SAY("ERROR: failed to read VT1612A register 0x1C\n"); +return igot; +} +/*****************************************************************************/ +int +set2to78(struct usb_device *p) +{ +int ir; + +msleep(20); +ir = regset(p, 0x0002, 0x0078); +if (0 > ir) + SAY("ERROR: failed to set register 0x0002 to 0x0078\n"); +msleep(20); +return ir; +} +/*****************************************************************************/ +int +set2to93(struct usb_device *p) +{ +int ir; + +msleep(20); +ir = regset(p, 0x0002, 0x0093); +if (0 > ir) + SAY("ERROR: failed to set register 0x0002 to 0x0078\n"); +msleep(20); +return ir; +} +/*****************************************************************************/ diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c new file mode 100644 index 000000000000..18259df3fe7d --- /dev/null +++ b/drivers/staging/easycap/easycap_main.c @@ -0,0 +1,4342 @@ +/****************************************************************************** +* * +* easycap_main.c * +* * +* Video driver for EasyCAP USB2.0 Video Capture Device DC60 * +* * +* * +******************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ + +#include "easycap.h" +#include "easycap_standard.h" + +int easycap_debug; +module_param(easycap_debug, int, S_IRUGO | S_IWUSR); + +unsigned int audio_pages_per_fragment; +unsigned int audio_bytes_per_fragment; +unsigned int audio_buffer_page_many; + +/*---------------------------------------------------------------------------*/ +/* + * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO + */ +/*---------------------------------------------------------------------------*/ +struct usb_device_id easycap_usb_device_id_table[] = { +{ USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID) }, +{ } +}; +MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table); +struct usb_driver easycap_usb_driver = { +.name = "easycap", +.id_table = easycap_usb_device_id_table, +.probe = easycap_usb_probe, +.disconnect = easycap_usb_disconnect, +}; +/*---------------------------------------------------------------------------*/ +/* + * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE + * + * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY + * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253. + * THIS IS THE CASE FOR OpenSUSE. + */ +/*---------------------------------------------------------------------------*/ +const struct file_operations easycap_fops = { +.owner = THIS_MODULE, +.open = easycap_open, +.release = easycap_release, +.ioctl = easycap_ioctl, +.poll = easycap_poll, +.mmap = easycap_mmap, +.llseek = no_llseek, +}; +struct vm_operations_struct easycap_vm_ops = { +.open = easycap_vma_open, +.close = easycap_vma_close, +.fault = easycap_vma_fault, +}; +struct usb_class_driver easycap_class = { +.name = "usb/easycap%d", +.fops = &easycap_fops, +.minor_base = USB_SKEL_MINOR_BASE, +}; + +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +#if defined(EASYCAP_NEEDS_V4L2_FOPS) +struct v4l2_file_operations v4l2_fops = { +.owner = THIS_MODULE, +.open = easycap_open_noinode, +.release = easycap_release_noinode, +.ioctl = easycap_ioctl_noinode, +.poll = easycap_poll, +.mmap = easycap_mmap, +}; +#endif /*EASYCAP_NEEDS_V4L2_FOPS*/ +int video_device_many /*=0*/; +struct video_device *pvideo_array[VIDEO_DEVICE_MANY], *pvideo_device; +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +/*--------------------------------------------------------------------------*/ +/* + * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE + */ +/*--------------------------------------------------------------------------*/ +const struct file_operations easysnd_fops = { +.owner = THIS_MODULE, +.open = easysnd_open, +.release = easysnd_release, +.ioctl = easysnd_ioctl, +.read = easysnd_read, +.llseek = no_llseek, +}; +struct usb_class_driver easysnd_class = { +.name = "usb/easysnd%d", +.fops = &easysnd_fops, +.minor_base = USB_SKEL_MINOR_BASE, +}; +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * IT IS NOT APPROPRIATE FOR easycap_open() TO SUBMIT THE VIDEO URBS HERE, + * BECAUSE THERE WILL ALWAYS BE SUBSEQUENT NEGOTIATION OF TV STANDARD AND + * FORMAT BY IOCTL AND IT IS INADVISABLE TO HAVE THE URBS RUNNING WHILE + * REGISTERS OF THE SA7113H ARE BEING MANIPULATED. + * + * THE SUBMISSION OF VIDEO URBS IS THEREFORE DELAYED UNTIL THE IOCTL COMMAND + * STREAMON IS RECEIVED. + */ +/*--------------------------------------------------------------------------*/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +int +easycap_open_noinode(struct file *file) +{ +return easycap_open((struct inode *)NULL, file); +} +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +int +easycap_open(struct inode *inode, struct file *file) +{ +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) +struct usb_interface *pusb_interface; +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +struct usb_device *p; +struct easycap *peasycap; +int i, k, m, rc; + +JOT(4, "\n"); +SAY("==========OPEN=========\n"); + +peasycap = (struct easycap *)NULL; +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) +if ((struct inode *)NULL == inode) { + SAY("ERROR: inode is NULL.\n"); + return -EFAULT; +} +pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode)); +if (!pusb_interface) { + SAY("ERROR: pusb_interface is NULL.\n"); + return -EFAULT; +} +peasycap = usb_get_intfdata(pusb_interface); +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#else +for (i = 0; i < video_device_many; i++) { + pvideo_device = pvideo_array[i]; + if ((struct video_device *)NULL != pvideo_device) { + peasycap = (struct easycap *)video_get_drvdata(pvideo_device); + break; + } +} +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +if ((struct easycap *)NULL == peasycap) { + SAY("MISTAKE: peasycap is NULL\n"); + return -EFAULT; +} +file->private_data = peasycap; +/*---------------------------------------------------------------------------*/ +/* + * INITIALIZATION + */ +/*---------------------------------------------------------------------------*/ +JOT(4, "starting initialization\n"); + +for (k = 0; k < FRAME_BUFFER_MANY; k++) { + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) + memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE); +} +p = peasycap->pusb_device; +if ((struct usb_device *)NULL == p) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} else { + JOT(16, "0x%08lX=peasycap->pusb_device\n", \ + (long int)peasycap->pusb_device); +} +rc = wakeup_device(peasycap->pusb_device); +if (0 == rc) + JOT(8, "wakeup_device() OK\n"); +else { + SAY("ERROR: wakeup_device() returned %i\n", rc); + return -EFAULT; +} +rc = setup_stk(p); peasycap->input = 0; +if (0 == rc) + JOT(8, "setup_stk() OK\n"); +else { + SAY("ERROR: setup_stk() returned %i\n", rc); + return -EFAULT; +} +rc = setup_saa(p); +if (0 == rc) + JOT(8, "setup_saa() OK\n"); +else { + SAY("ERROR: setup_saa() returned %i\n", rc); + return -EFAULT; +} +rc = check_saa(p); +if (0 == rc) + JOT(8, "check_saa() OK\n"); +else if (-8 < rc) + SAY("check_saa() returned %i\n", rc); +else { + SAY("ERROR: check_saa() returned %i\n", rc); + return -EFAULT; +} +peasycap->standard_offset = -1; +/*---------------------------------------------------------------------------*/ +#if defined(PREFER_NTSC) + +rc = adjust_standard(peasycap, V4L2_STD_NTSC_M); +if (0 == rc) + JOT(8, "adjust_standard(.,NTSC_M) OK\n"); +else { + SAY("ERROR: adjust_standard(.,NTSC_M) returned %i\n", rc); + return -EFAULT; +} +rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \ + false); +if (0 <= rc) + JOT(8, "adjust_format(.,640,480,UYVY) OK\n"); +else { + SAY("ERROR: adjust_format(.,640,480,UYVY) returned %i\n", rc); + return -EFAULT; +} + +#else + +rc = adjust_standard(peasycap, \ + (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \ + V4L2_STD_PAL_I | V4L2_STD_PAL_N)); +if (0 == rc) + JOT(8, "adjust_standard(.,PAL_BGHIN) OK\n"); +else { + SAY("ERROR: adjust_standard(.,PAL_BGHIN) returned %i\n", rc); + return -EFAULT; +} +rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \ + false); +if (0 <= rc) + JOT(8, "adjust_format(.,640,480,uyvy,false) OK\n"); +else { + SAY("ERROR: adjust_format(.,640,480,uyvy,false) returned %i\n", rc); + return -EFAULT; +} + +#endif /* !PREFER_NTSC*/ +/*---------------------------------------------------------------------------*/ +rc = adjust_brightness(peasycap, -8192); +if (0 != rc) { + SAY("ERROR: adjust_brightness(default) returned %i\n", rc); + return -EFAULT; +} +rc = adjust_contrast(peasycap, -8192); +if (0 != rc) { + SAY("ERROR: adjust_contrast(default) returned %i\n", rc); + return -EFAULT; +} +rc = adjust_saturation(peasycap, -8192); +if (0 != rc) { + SAY("ERROR: adjust_saturation(default) returned %i\n", rc); + return -EFAULT; +} +rc = adjust_hue(peasycap, -8192); +if (0 != rc) { + SAY("ERROR: adjust_hue(default) returned %i\n", rc); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +rc = usb_set_interface(peasycap->pusb_device, peasycap->video_interface, \ + peasycap->video_altsetting_on); +if (0 == rc) + JOT(8, "usb_set_interface(.,%i,%i) OK\n", peasycap->video_interface, \ + peasycap->video_altsetting_on); +else { + SAY("ERROR: usb_set_interface() returned %i\n", rc); + return -EFAULT; +} +rc = start_100(p); +if (0 == rc) + JOT(8, "start_100() OK\n"); +else { + SAY("ERROR: start_100() returned %i\n", rc); + return -EFAULT; +} +peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1; +peasycap->video_idle = 0; +peasycap->video_junk = 0; +for (i = 0; i < 180; i++) + peasycap->merit[i] = 0; +peasycap->video_eof = 0; +peasycap->audio_eof = 0; + +do_gettimeofday(&peasycap->timeval7); + +peasycap->fudge = 0; + +JOT(4, "finished initialization\n"); +return 0; +} +/*****************************************************************************/ +int +submit_video_urbs(struct easycap *peasycap) +{ +struct data_urb *pdata_urb; +struct urb *purb; +struct list_head *plist_head; +int j, isbad, m, rc; +int isbuf; + +if ((struct list_head *)NULL == peasycap->purb_video_head) { + SAY("ERROR: peasycap->urb_video_head uninitialized\n"); + return -EFAULT; +} +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +if (!peasycap->video_isoc_streaming) { + + + + + + + + + JOT(4, "submission of all video urbs\n"); + if (0 != ready_saa(peasycap->pusb_device)) { + SAY("ERROR: not ready to capture after waiting " \ + "one second\n"); + SAY("..... continuing anyway\n"); + } + isbad = 0; m = 0; + list_for_each(plist_head, (peasycap->purb_video_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (NULL != pdata_urb) { + purb = pdata_urb->purb; + if (NULL != purb) { + isbuf = pdata_urb->isbuf; + purb->interval = 1; + purb->dev = peasycap->pusb_device; + purb->pipe = \ + usb_rcvisocpipe(peasycap->pusb_device,\ + peasycap->video_endpointnumber); + purb->transfer_flags = URB_ISO_ASAP; + purb->transfer_buffer = \ + peasycap->video_isoc_buffer[isbuf].pgo; + purb->transfer_buffer_length = \ + peasycap->video_isoc_buffer_size; + purb->complete = easycap_complete; + purb->context = peasycap; + purb->start_frame = 0; + purb->number_of_packets = \ + peasycap->video_isoc_framesperdesc; + + for (j = 0; j < peasycap->\ + video_isoc_framesperdesc; j++) { + purb->iso_frame_desc[j].\ + offset = j * \ + peasycap->\ + video_isoc_maxframesize; + purb->iso_frame_desc[j].\ + length = peasycap->\ + video_isoc_maxframesize; + } + + rc = usb_submit_urb(purb, GFP_KERNEL); + if (0 != rc) { + isbad++; + SAY("ERROR: usb_submit_urb() failed " \ + "for urb with rc:\n"); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); + break; + } + case -ENODEV: { + SAY("ENODEV\n"); + break; + } + case -ENXIO: { + SAY("ENXIO\n"); + break; + } + case -EINVAL: { + SAY("EINVAL\n"); + break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); + break; + } + case -EFBIG: { + SAY("EFBIG\n"); + break; + } + case -EPIPE: { + SAY("EPIPE\n"); + break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); + break; + } + default: { + SAY("unknown error code %i\n",\ + rc); + break; + } + } + } else { + m++; + } + } else { + isbad++; + } + } else { + isbad++; + } + } + if (isbad) { + JOT(4, "attempting cleanup instead of submitting\n"); + list_for_each(plist_head, (peasycap->purb_video_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, \ + list_head); + if (NULL != pdata_urb) { + purb = pdata_urb->purb; + if (NULL != purb) + usb_kill_urb(purb); + } + } + peasycap->video_isoc_streaming = 0; + } else { + peasycap->video_isoc_streaming = 1; + JOT(4, "submitted %i video urbs\n", m); + } + + + + + + +} else { + JOT(4, "already streaming video urbs\n"); +} +return 0; +} +/*****************************************************************************/ +int +kill_video_urbs(struct easycap *peasycap) +{ +int m; +struct list_head *plist_head; +struct data_urb *pdata_urb; + +if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; +} +if (peasycap->video_isoc_streaming) { + + + + if ((struct list_head *)NULL != peasycap->purb_video_head) { + peasycap->video_isoc_streaming = 0; + JOT(4, "killing video urbs\n"); + m = 0; + list_for_each(plist_head, (peasycap->purb_video_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, \ + list_head); + if ((struct data_urb *)NULL != pdata_urb) { + if ((struct urb *)NULL != pdata_urb->purb) { + usb_kill_urb(pdata_urb->purb); + m++; + } + } + } + JOT(4, "%i video urbs killed\n", m); + } else { + SAY("ERROR: peasycap->purb_video_head is NULL\n"); + return -EFAULT; + } +} else { + JOT(8, "%i=video_isoc_streaming, no video urbs killed\n", \ + peasycap->video_isoc_streaming); +} +return 0; +} +/****************************************************************************/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +int +easycap_release_noinode(struct file *file) +{ +return easycap_release((struct inode *)NULL, file); +} +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*--------------------------------------------------------------------------*/ +int +easycap_release(struct inode *inode, struct file *file) +{ +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) +struct easycap *peasycap; + +JOT(4, "\n"); + +peasycap = (struct easycap *)file->private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL.\n"); + SAY("ending unsuccessfully\n"); + return -EFAULT; +} +if (0 != kill_video_urbs(peasycap)) { + SAY("ERROR: kill_video_urbs() failed\n"); + return -EFAULT; +} +JOT(4, "ending successfully\n"); +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#else +# +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ + +return 0; +} +/****************************************************************************/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +int +videodev_release(struct video_device *pvd) +{ +struct easycap *peasycap; +int i, j, k; + +JOT(4, "\n"); + +k = 0; +for (i = 0; i < video_device_many; i++) { + pvideo_device = pvideo_array[i]; + if ((struct video_device *)NULL != pvideo_device) { + if (pvd->minor == pvideo_device->minor) { + peasycap = (struct easycap *)\ + video_get_drvdata(pvideo_device); + if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + SAY("ending unsuccessfully\n"); + return -EFAULT; + } + if (0 != kill_video_urbs(peasycap)) { + SAY("ERROR: kill_video_urbs() failed\n"); + return -EFAULT; + } + JOT(4, "freeing video_device structure: " \ + "/dev/video%i\n", i); + kfree((void *)pvideo_device); + for (j = i; j < (VIDEO_DEVICE_MANY - 1); j++) + pvideo_array[j] = pvideo_array[j + 1]; + video_device_many--; k++; + break; + } + } +} +if (!k) { + SAY("ERROR: lost video_device structure for %i=minor\n", pvd->minor); + SAY("cannot free: may cause memory leak\n"); + SAY("ending unsuccessfully\n"); + return -EFAULT; +} + +JOT(4, "ending successfully\n"); +return 0; +} +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/****************************************************************************/ +/*--------------------------------------------------------------------------*/ +/* + * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect(). + * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED. + * peasycap->pusb_device IS NO LONGER VALID AND SHOULD HAVE BEEN SET TO NULL. + */ +/*---------------------------------------------------------------------------*/ +void +easycap_delete(struct kref *pkref) +{ +int k, m, lost; +int allocation_video_urb, allocation_video_page, allocation_video_struct; +int allocation_audio_urb, allocation_audio_page, allocation_audio_struct; +int registered_video, registered_audio; +struct easycap *peasycap; +struct data_urb *pdata_urb; +struct list_head *plist_head, *plist_next; + +JOT(4, "\n"); + +peasycap = container_of(pkref, struct easycap, kref); +if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap is NULL: cannot perform deletions\n"); + return; +} +/*---------------------------------------------------------------------------*/ +/* + * FREE VIDEO. + */ +/*---------------------------------------------------------------------------*/ +if ((struct list_head *)NULL != peasycap->purb_video_head) { + JOT(4, "freeing video urbs\n"); + m = 0; + list_for_each(plist_head, (peasycap->purb_video_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (NULL == pdata_urb) + JOT(4, "ERROR: pdata_urb is NULL\n"); + else { + if ((struct urb *)NULL != pdata_urb->purb) { + usb_free_urb(pdata_urb->purb); + pdata_urb->purb = (struct urb *)NULL; + peasycap->allocation_video_urb -= 1; + m++; + } + } + } + + JOT(4, "%i video urbs freed\n", m); +/*---------------------------------------------------------------------------*/ + JOT(4, "freeing video data_urb structures.\n"); + m = 0; + list_for_each_safe(plist_head, plist_next, peasycap->purb_video_head) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if ((struct data_urb *)NULL != pdata_urb) { + kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL; + peasycap->allocation_video_struct -= \ + sizeof(struct data_urb); + m++; + } + } + JOT(4, "%i video data_urb structures freed\n", m); + JOT(4, "setting peasycap->purb_video_head=NULL\n"); + peasycap->purb_video_head = (struct list_head *)NULL; + } else { +JOT(4, "peasycap->purb_video_head is NULL\n"); +} +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing video isoc buffers.\n"); +m = 0; +for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { + if ((void *)NULL != peasycap->video_isoc_buffer[k].pgo) { + free_pages((unsigned long)\ + (peasycap->video_isoc_buffer[k].pgo), \ + VIDEO_ISOC_ORDER); + peasycap->video_isoc_buffer[k].pgo = (void *)NULL; + peasycap->allocation_video_page -= \ + ((unsigned int)(0x01 << VIDEO_ISOC_ORDER)); + m++; + } +} +JOT(4, "isoc video buffers freed: %i pages\n", m * (0x01 << VIDEO_ISOC_ORDER)); +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing video field buffers.\n"); +lost = 0; +for (k = 0; k < FIELD_BUFFER_MANY; k++) { + for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { + if ((void *)NULL != peasycap->field_buffer[k][m].pgo) { + free_page((unsigned long)\ + (peasycap->field_buffer[k][m].pgo)); + peasycap->field_buffer[k][m].pgo = (void *)NULL; + peasycap->allocation_video_page -= 1; + lost++; + } + } +} +JOT(4, "video field buffers freed: %i pages\n", lost); +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing video frame buffers.\n"); +lost = 0; +for (k = 0; k < FRAME_BUFFER_MANY; k++) { + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { + if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) { + free_page((unsigned long)\ + (peasycap->frame_buffer[k][m].pgo)); + peasycap->frame_buffer[k][m].pgo = (void *)NULL; + peasycap->allocation_video_page -= 1; + lost++; + } + } +} +JOT(4, "video frame buffers freed: %i pages\n", lost); +/*---------------------------------------------------------------------------*/ +/* + * FREE AUDIO. + */ +/*---------------------------------------------------------------------------*/ +if ((struct list_head *)NULL != peasycap->purb_audio_head) { + JOT(4, "freeing audio urbs\n"); + m = 0; + list_for_each(plist_head, (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (NULL == pdata_urb) + JOT(4, "ERROR: pdata_urb is NULL\n"); + else { + if ((struct urb *)NULL != pdata_urb->purb) { + usb_free_urb(pdata_urb->purb); + pdata_urb->purb = (struct urb *)NULL; + peasycap->allocation_audio_urb -= 1; + m++; + } + } + } + JOT(4, "%i audio urbs freed\n", m); +/*---------------------------------------------------------------------------*/ + JOT(4, "freeing audio data_urb structures.\n"); + m = 0; + list_for_each_safe(plist_head, plist_next, peasycap->purb_audio_head) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if ((struct data_urb *)NULL != pdata_urb) { + kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL; + peasycap->allocation_audio_struct -= \ + sizeof(struct data_urb); + m++; + } + } +JOT(4, "%i audio data_urb structures freed\n", m); +JOT(4, "setting peasycap->purb_audio_head=NULL\n"); +peasycap->purb_audio_head = (struct list_head *)NULL; +} else { +JOT(4, "peasycap->purb_audio_head is NULL\n"); +} +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing audio isoc buffers.\n"); +m = 0; +for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { + if ((void *)NULL != peasycap->audio_isoc_buffer[k].pgo) { + free_pages((unsigned long)\ + (peasycap->audio_isoc_buffer[k].pgo), \ + AUDIO_ISOC_ORDER); + peasycap->audio_isoc_buffer[k].pgo = (void *)NULL; + peasycap->allocation_audio_page -= \ + ((unsigned int)(0x01 << AUDIO_ISOC_ORDER)); + m++; + } +} +JOT(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \ + m * (0x01 << AUDIO_ISOC_ORDER)); +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing audio buffers.\n"); +lost = 0; +for (k = 0; k < audio_buffer_page_many; k++) { + if ((void *)NULL != peasycap->audio_buffer[k].pgo) { + free_page((unsigned long)(peasycap->audio_buffer[k].pgo)); + peasycap->audio_buffer[k].pgo = (void *)NULL; + peasycap->allocation_audio_page -= 1; + lost++; + } +} +JOT(4, "easysnd_delete(): audio buffers freed: %i pages\n", lost); +/*---------------------------------------------------------------------------*/ +JOT(4, "freeing easycap structure.\n"); +allocation_video_urb = peasycap->allocation_video_urb; +allocation_video_page = peasycap->allocation_video_page; +allocation_video_struct = peasycap->allocation_video_struct; +registered_video = peasycap->registered_video; +allocation_audio_urb = peasycap->allocation_audio_urb; +allocation_audio_page = peasycap->allocation_audio_page; +allocation_audio_struct = peasycap->allocation_audio_struct; +registered_audio = peasycap->registered_audio; +m = 0; +if ((struct easycap *)NULL != peasycap) { + kfree(peasycap); peasycap = (struct easycap *)NULL; + allocation_video_struct -= sizeof(struct easycap); + m++; +} +JOT(4, "%i easycap structure freed\n", m); +/*---------------------------------------------------------------------------*/ + +SAY("%8i= video urbs after all deletions\n", allocation_video_urb); +SAY("%8i= video pages after all deletions\n", allocation_video_page); +SAY("%8i= video structs after all deletions\n", allocation_video_struct); +SAY("%8i= video devices after all deletions\n", registered_video); +SAY("%8i= audio urbs after all deletions\n", allocation_audio_urb); +SAY("%8i= audio pages after all deletions\n", allocation_audio_page); +SAY("%8i= audio structs after all deletions\n", allocation_audio_struct); +SAY("%8i= audio devices after all deletions\n", registered_audio); + +JOT(4, "ending.\n"); +return; +} +/*****************************************************************************/ +unsigned int easycap_poll(struct file *file, poll_table *wait) +{ +struct easycap *peasycap; + +JOT(8, "\n"); + +if (NULL == ((poll_table *)wait)) + JOT(8, "WARNING: poll table pointer is NULL ... continuing\n"); +if (NULL == ((struct file *)file)) { + SAY("ERROR: file pointer is NULL\n"); + return -EFAULT; +} +peasycap = (struct easycap *)file->private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; +} +peasycap->polled = 1; + +if (0 == easycap_dqbuf(peasycap, 0)) + return POLLIN | POLLRDNORM; +else + return POLLERR; + +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING. + */ +/*---------------------------------------------------------------------------*/ +int +easycap_dqbuf(struct easycap *peasycap, int mode) +{ +int miss, rc; + +JOT(8, "\n"); + +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +/* + * WAIT FOR FIELD 0 + */ +/*---------------------------------------------------------------------------*/ +miss = 0; +if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) + return -ERESTARTSYS; +while ((peasycap->field_read == peasycap->field_fill) || \ + (0 != (0xFF00 & peasycap->field_buffer\ + [peasycap->field_read][0].kount)) || \ + (0 != (0x00FF & peasycap->field_buffer\ + [peasycap->field_read][0].kount))) { + mutex_unlock(&(peasycap->mutex_mmap_video[0])); + + if (mode) + return -EAGAIN; + + JOT(8, "first wait on wq_video, " \ + "%i=field_read %i=field_fill\n", \ + peasycap->field_read, peasycap->field_fill); + + msleep(1); + if (0 != (wait_event_interruptible(peasycap->wq_video, \ + (peasycap->video_idle || peasycap->video_eof || \ + ((peasycap->field_read != peasycap->field_fill) && \ + (0 == (0xFF00 & peasycap->field_buffer\ + [peasycap->field_read][0].kount)) && \ + (0 == (0x00FF & peasycap->field_buffer\ + [peasycap->field_read][0].kount))))))){ + SAY("aborted by signal\n"); + return -EIO; + } + if (peasycap->video_idle) { + JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle); + return -EIO; + } + if (peasycap->video_eof) { + JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof); + debrief(peasycap); + kill_video_urbs(peasycap); + return -EIO; + } +miss++; +if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) + return -ERESTARTSYS; +} +mutex_unlock(&(peasycap->mutex_mmap_video[0])); +JOT(8, "first awakening on wq_video after %i waits\n", miss); + +rc = field2frame(peasycap); +if (0 != rc) + SAY("ERROR: field2frame() returned %i\n", rc); + +if (true == peasycap->offerfields) { + peasycap->frame_read = peasycap->frame_fill; + (peasycap->frame_fill)++; + if (peasycap->frame_buffer_many <= peasycap->frame_fill) + peasycap->frame_fill = 0; + + if (0x01 & easycap_standard[peasycap->standard_offset].mask) { + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ + V4L2_FIELD_BOTTOM; + } else { + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ + V4L2_FIELD_TOP; + } +JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read); +JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill); +} +/*---------------------------------------------------------------------------*/ +/* + * WAIT FOR FIELD 1 + */ +/*---------------------------------------------------------------------------*/ +miss = 0; +if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) + return -ERESTARTSYS; +while ((peasycap->field_read == peasycap->field_fill) || \ + (0 != (0xFF00 & peasycap->field_buffer\ + [peasycap->field_read][0].kount)) || \ + (0 == (0x00FF & peasycap->field_buffer\ + [peasycap->field_read][0].kount))) { + mutex_unlock(&(peasycap->mutex_mmap_video[0])); + + if (mode) + return -EAGAIN; + + JOT(8, "second wait on wq_video, " \ + "%i=field_read %i=field_fill\n", \ + peasycap->field_read, peasycap->field_fill); + msleep(1); + if (0 != (wait_event_interruptible(peasycap->wq_video, \ + (peasycap->video_idle || peasycap->video_eof || \ + ((peasycap->field_read != peasycap->field_fill) && \ + (0 == (0xFF00 & peasycap->field_buffer\ + [peasycap->field_read][0].kount)) && \ + (0 != (0x00FF & peasycap->field_buffer\ + [peasycap->field_read][0].kount))))))){ + SAY("aborted by signal\n"); + return -EIO; + } + if (peasycap->video_idle) { + JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle); + return -EIO; + } + if (peasycap->video_eof) { + JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof); + debrief(peasycap); + kill_video_urbs(peasycap); + return -EIO; + } +miss++; +if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) + return -ERESTARTSYS; +} +mutex_unlock(&(peasycap->mutex_mmap_video[0])); +JOT(8, "second awakening on wq_video after %i waits\n", miss); + +rc = field2frame(peasycap); +if (0 != rc) + SAY("ERROR: field2frame() returned %i\n", rc); + +peasycap->frame_read = peasycap->frame_fill; +peasycap->queued[peasycap->frame_read] = 0; +peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE; + +(peasycap->frame_fill)++; +if (peasycap->frame_buffer_many <= peasycap->frame_fill) + peasycap->frame_fill = 0; + +if (0x01 & easycap_standard[peasycap->standard_offset].mask) { + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ + V4L2_FIELD_TOP; +} else { + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ + V4L2_FIELD_BOTTOM; +} + +JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read); +JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill); + +return 0; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479 + * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478 + * + * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH + * odd==false IS TRANSFERRED TO THE FRAME BUFFER. + * + * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM + * CHOOSES THE OPTION V4L2_FIELD_ALTERNATE. NO USERSPACE PROGRAM TESTED + * TO DATE HAS DONE THIS. BUGS ARE LIKELY. + */ +/*---------------------------------------------------------------------------*/ +int +field2frame(struct easycap *peasycap) +{ +static struct timeval timeval0; +struct timeval timeval; +long long int above, below; +__u32 remainder; +struct signed_div_result sdr; + +void *pex, *pad; +int kex, kad, mex, mad, rex, rad, rad2; +int c2, c3, w2, w3, cz, wz; +int rc, bytesperpixel, multiplier, much, more, over, rump, caches; +__u8 mask, margin; +bool odd, isuy, decimatepixel, offerfields; + +JOT(8, "===== parity %i, field buffer %i --> frame buffer %i\n", \ + peasycap->field_buffer[peasycap->field_read][0].kount,\ + peasycap->field_read, peasycap->frame_fill); +JOT(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel); +if (true == peasycap->offerfields) + JOT(8, "===== offerfields\n"); + +/*---------------------------------------------------------------------------*/ +/* + * REJECT OR CLEAN BAD FIELDS + */ +/*---------------------------------------------------------------------------*/ +if (peasycap->field_read == peasycap->field_fill) { + SAY("ERROR: on entry, still filling field buffer %i\n", \ + peasycap->field_read); + return 0; +} +#if defined(EASYCAP_TESTCARD) +easycap_testcard(peasycap, peasycap->field_read); +#else +if (0 != (0x0400 & peasycap->field_buffer[peasycap->field_read][0].kount)) + easycap_testcard(peasycap, peasycap->field_read); +#endif /*EASYCAP_TESTCARD*/ +/*---------------------------------------------------------------------------*/ + +offerfields = peasycap->offerfields; +bytesperpixel = peasycap->bytesperpixel; +decimatepixel = peasycap->decimatepixel; + +if ((2 != bytesperpixel) && \ + (3 != bytesperpixel) && \ + (4 != bytesperpixel)) { + SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel); + return -EFAULT; +} +if (true == decimatepixel) + multiplier = 2; +else + multiplier = 1; + +w2 = 2 * multiplier * (peasycap->width); +w3 = bytesperpixel * \ + multiplier * \ + (peasycap->width); +wz = multiplier * \ + (peasycap->height) * \ + multiplier * \ + (peasycap->width); + +kex = peasycap->field_read; mex = 0; +kad = peasycap->frame_fill; mad = 0; + +pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE; +pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE; +if (peasycap->field_buffer[kex][0].kount) + odd = true; +else + odd = false; + +if ((true == odd) && (false == offerfields) &&(false == decimatepixel)) { + JOT(8, " initial skipping %4i bytes p.%4i\n", \ + w3/multiplier, mad); + pad += (w3 / multiplier); rad -= (w3 / multiplier); +} +isuy = true; +mask = 0; rump = 0; caches = 0; + +cz = 0; +while (cz < wz) { + /*-------------------------------------------------------------------*/ + /* + ** PROCESS ONE LINE OF FRAME AT FULL RESOLUTION: + ** READ w2 BYTES FROM FIELD BUFFER, + ** WRITE w3 BYTES TO FRAME BUFFER + **/ + /*-------------------------------------------------------------------*/ + if (false == decimatepixel) { + over = w2; + do { + much = over; more = 0; margin = 0; mask = 0x00; + if (rex < much) + much = rex; + rump = 0; + + if (much % 2) { + SAY("MISTAKE: much is odd\n"); + return -EFAULT; + } + + more = (bytesperpixel * \ + much) / 2; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + if (1 < bytesperpixel) { + if ((rad * \ + 2) < (much * \ + bytesperpixel)) { + /* + ** INJUDICIOUS ALTERATION OF THIS + ** BLOCK WILL CAUSE BREAKAGE. + ** BEWARE. + **/ + rad2 = rad + bytesperpixel - 1; + much = ((((2 * \ + rad2)/bytesperpixel)/2) * 2); + rump = ((bytesperpixel * \ + much) / 2) - rad; + more = rad; + } + mask = (__u8)rump; + margin = 0; + if (much == rex) { + mask |= 0x04; + if ((mex + 1) < FIELD_BUFFER_SIZE/ \ + PAGE_SIZE) { + margin = *((__u8 *)(peasycap->\ + field_buffer\ + [kex][mex + 1].pgo)); + } else + mask |= 0x08; + } +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + } else { + SAY("MISTAKE: %i=bytesperpixel\n", \ + bytesperpixel); + return -EFAULT; + } +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + if (rump) + caches++; + + rc = redaub(peasycap, pad, pex, much, more, \ + mask, margin, isuy); + if (0 > rc) { + SAY("ERROR: redaub() failed\n"); + return -EFAULT; + } + if (much % 4) { + if (isuy) + isuy = false; + else + isuy = true; + } + over -= much; cz += much; + pex += much; rex -= much; + if (!rex) { + mex++; + pex = peasycap->field_buffer[kex][mex].pgo; + rex = PAGE_SIZE; + } + pad += more; + rad -= more; + if (!rad) { + mad++; + pad = peasycap->frame_buffer[kad][mad].pgo; + rad = PAGE_SIZE; + if (rump) { + pad += rump; + rad -= rump; + } + } + } while (over); +/*---------------------------------------------------------------------------*/ +/* + * SKIP w3 BYTES IN TARGET FRAME BUFFER, + * UNLESS IT IS THE LAST LINE OF AN ODD FRAME + */ +/*---------------------------------------------------------------------------*/ + if (((false == odd) || (cz != wz))&&(false == offerfields)) { + over = w3; + do { + if (!rad) { + mad++; + pad = peasycap->frame_buffer\ + [kad][mad].pgo; + rad = PAGE_SIZE; + } + more = over; + if (rad < more) + more = rad; + over -= more; + pad += more; + rad -= more; + } while (over); + } +/*---------------------------------------------------------------------------*/ +/* + * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION: + * ONLY IF false==odd, + * READ w2 BYTES FROM FIELD BUFFER, + * WRITE w3 / 2 BYTES TO FRAME BUFFER + */ +/*---------------------------------------------------------------------------*/ + } else if (false == odd) { + over = w2; + do { + much = over; more = 0; margin = 0; mask = 0x00; + if (rex < much) + much = rex; + rump = 0; + + if (much % 2) { + SAY("MISTAKE: much is odd\n"); + return -EFAULT; + } + + more = (bytesperpixel * \ + much) / 4; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + if (1 < bytesperpixel) { + if ((rad * 4) < (much * \ + bytesperpixel)) { + /* + ** INJUDICIOUS ALTERATION OF THIS + ** BLOCK WILL CAUSE BREAKAGE. + ** BEWARE. + **/ + rad2 = rad + bytesperpixel - 1; + much = ((((2 * rad2)/bytesperpixel)/2)\ + * 4); + rump = ((bytesperpixel * \ + much) / 4) - rad; + more = rad; + } + mask = (__u8)rump; + margin = 0; + if (much == rex) { + mask |= 0x04; + if ((mex + 1) < FIELD_BUFFER_SIZE/ \ + PAGE_SIZE) { + margin = *((__u8 *)(peasycap->\ + field_buffer\ + [kex][mex + 1].pgo)); + } + else + mask |= 0x08; + } +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + } else { + SAY("MISTAKE: %i=bytesperpixel\n", \ + bytesperpixel); + return -EFAULT; + } +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + if (rump) + caches++; + + rc = redaub(peasycap, pad, pex, much, more, \ + mask, margin, isuy); + if (0 > rc) { + SAY("ERROR: redaub() failed\n"); + return -EFAULT; + } + over -= much; cz += much; + pex += much; rex -= much; + if (!rex) { + mex++; + pex = peasycap->field_buffer[kex][mex].pgo; + rex = PAGE_SIZE; + } + pad += more; + rad -= more; + if (!rad) { + mad++; + pad = peasycap->frame_buffer[kad][mad].pgo; + rad = PAGE_SIZE; + if (rump) { + pad += rump; + rad -= rump; + } + } + } while (over); +/*---------------------------------------------------------------------------*/ +/* + * OTHERWISE JUST + * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM + */ +/*---------------------------------------------------------------------------*/ + } else { + over = w2; + do { + if (!rex) { + mex++; + pex = peasycap->field_buffer[kex][mex].pgo; + rex = PAGE_SIZE; + } + much = over; + if (rex < much) + much = rex; + over -= much; + cz += much; + pex += much; + rex -= much; + } while (over); + } +} +/*---------------------------------------------------------------------------*/ +/* + * SANITY CHECKS + */ +/*---------------------------------------------------------------------------*/ +c2 = (mex + 1)*PAGE_SIZE - rex; +if (cz != c2) + SAY("ERROR: discrepancy %i in bytes read\n", c2 - cz); +c3 = (mad + 1)*PAGE_SIZE - rad; + +if (false == decimatepixel) { + if (bytesperpixel * \ + cz != c3) \ + SAY("ERROR: discrepancy %i in bytes written\n", \ + c3 - (bytesperpixel * \ + cz)); +} else { + if (false == odd) { + if (bytesperpixel * \ + cz != (4 * c3)) + SAY("ERROR: discrepancy %i in bytes written\n", \ + (2*c3)-(bytesperpixel * \ + cz)); + } else { + if (0 != c3) + SAY("ERROR: discrepancy %i " \ + "in bytes written\n", c3); + } +} +if (rump) + SAY("ERROR: undischarged cache at end of line in frame buffer\n"); + +JOT(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3); +JOT(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad); + +if (true == odd) + JOT(8, "+++++ field2frame(): frame buffer %i is full\n", kad); + +if (peasycap->field_read == peasycap->field_fill) + SAY("WARNING: on exit, filling field buffer %i\n", \ + peasycap->field_read); +/*---------------------------------------------------------------------------*/ +/* + * CALCULATE VIDEO STREAMING RATE + */ +/*---------------------------------------------------------------------------*/ +do_gettimeofday(&timeval); +if (timeval0.tv_sec) { + below = ((long long int)(1000000)) * \ + ((long long int)(timeval.tv_sec - timeval0.tv_sec)) + \ + (long long int)(timeval.tv_usec - timeval0.tv_usec); + above = (long long int)1000000; + + sdr = signed_div(above, below); + above = sdr.quotient; + remainder = (__u32)sdr.remainder; + + JOT(8, "video streaming at %3lli.%03i fields per second\n", above, \ + (remainder/1000)); +} +timeval0 = timeval; + +if (caches) + JOT(8, "%i=caches\n", caches); +return 0; +} +/*****************************************************************************/ +struct signed_div_result +signed_div(long long int above, long long int below) +{ +struct signed_div_result sdr; + +if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) { + sdr.remainder = (unsigned long long int) do_div(above, below); + sdr.quotient = (long long int) above; +} else { + if (0 > above) + above = -above; + if (0 > below) + below = -below; + sdr.remainder = (unsigned long long int) do_div(above, below); + sdr.quotient = -((long long int) above); +} +return sdr; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * DECIMATION AND COLOURSPACE CONVERSION. + * + * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE + * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE. + * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST + * ALSO ENSURE THAT much IS EVEN. + * + * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN + * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION. + * + * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS: + * 0x03 & mask = number of bytes to be written to cache instead of to + * frame buffer + * 0x04 & mask => use argument margin to set the chrominance for last pixel + * 0x08 & mask => do not set the chrominance for last pixel + * + * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601. + * + * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID + * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO + * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE. + */ +/*---------------------------------------------------------------------------*/ +int +redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more, \ + __u8 mask, __u8 margin, bool isuy) +{ +static __s32 ay[256], bu[256], rv[256], gu[256], gv[256]; +static __u8 cache[8], *pcache; +__u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr; +int bytesperpixel; +bool byteswaporder, decimatepixel, last; +int j, rump; +__s32 s32; + +if (much % 2) { + SAY("MISTAKE: much is odd\n"); + return -EFAULT; +} +bytesperpixel = peasycap->bytesperpixel; +byteswaporder = peasycap->byteswaporder; +decimatepixel = peasycap->decimatepixel; + +/*---------------------------------------------------------------------------*/ +if (!bu[255]) { + for (j = 0; j < 112; j++) { + s32 = (0xFF00 & (453 * j)) >> 8; + bu[j + 128] = s32; bu[127 - j] = -s32; + s32 = (0xFF00 & (359 * j)) >> 8; + rv[j + 128] = s32; rv[127 - j] = -s32; + s32 = (0xFF00 & (88 * j)) >> 8; + gu[j + 128] = s32; gu[127 - j] = -s32; + s32 = (0xFF00 & (183 * j)) >> 8; + gv[j + 128] = s32; gv[127 - j] = -s32; + } + for (j = 0; j < 16; j++) { + bu[j] = bu[16]; rv[j] = rv[16]; + gu[j] = gu[16]; gv[j] = gv[16]; + } + for (j = 240; j < 256; j++) { + bu[j] = bu[239]; rv[j] = rv[239]; + gu[j] = gu[239]; gv[j] = gv[239]; + } + for (j = 16; j < 236; j++) + ay[j] = j; + for (j = 0; j < 16; j++) + ay[j] = ay[16]; + for (j = 236; j < 256; j++) + ay[j] = ay[235]; + JOT(8, "lookup tables are prepared\n"); +} +if ((__u8 *)NULL == pcache) + pcache = &cache[0]; +/*---------------------------------------------------------------------------*/ +/* + * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER + */ +/*---------------------------------------------------------------------------*/ +if (!pcache) { + SAY("MISTAKE: pcache is NULL\n"); + return -EFAULT; +} + +if (pcache != &cache[0]) + JOT(16, "cache has %i bytes\n", (int)(pcache - &cache[0])); +p2 = &cache[0]; +p3 = (__u8 *)pad - (int)(pcache - &cache[0]); +while (p2 < pcache) { + *p3++ = *p2; p2++; +} +pcache = &cache[0]; +if (p3 != pad) { + SAY("MISTAKE: pointer misalignment\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +rump = (int)(0x03 & mask); +u = 0; v = 0; +p2 = (__u8 *)pex; pz = p2 + much; pr = p3 + more; last = false; +p2++; + +if (true == isuy) + u = *(p2 - 1); +else + v = *(p2 - 1); + +if (rump) + JOT(16, "%4i=much %4i=more %i=rump\n", much, more, rump); + +/*---------------------------------------------------------------------------*/ +switch (bytesperpixel) { +case 2: { + if (false == decimatepixel) { + memcpy(pad, pex, (size_t)much); + if (false == byteswaporder) + /*---------------------------------------------------*/ + /* + ** UYVY + */ + /*---------------------------------------------------*/ + return 0; + else { + /*---------------------------------------------------*/ + /* + ** YUYV + */ + /*---------------------------------------------------*/ + p3 = (__u8 *)pad; pz = p3 + much; + while (pz > p3) { + c = *p3; + *p3 = *(p3 + 1); + *(p3 + 1) = c; + p3 += 2; + } + return 0; + } + } else { + if (false == byteswaporder) { + /*---------------------------------------------------*/ + /* + ** UYVY DECIMATED + */ + /*---------------------------------------------------*/ + p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much; + while (pz > p2) { + *p3 = *p2; + *(p3 + 1) = *(p2 + 1); + *(p3 + 2) = *(p2 + 2); + *(p3 + 3) = *(p2 + 3); + p3 += 4; p2 += 8; + } + return 0; + } else { + /*---------------------------------------------------*/ + /* + ** YUYV DECIMATED + **/ + /*---------------------------------------------------*/ + p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much; + while (pz > p2) { + *p3 = *(p2 + 1); + *(p3 + 1) = *p2; + *(p3 + 2) = *(p2 + 3); + *(p3 + 3) = *(p2 + 2); + p3 += 4; p2 += 8; + } + return 0; + } + } + break; + } +case 3: + { + if (false == decimatepixel) { + if (false == byteswaporder) { + /*---------------------------------------------------*/ + /* + ** RGB + **/ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = r; + *pcache++ = g; + *pcache++ = b; + break; + } + case 2: { + *p3 = r; + *(p3 + 1) = g; + *pcache++ = b; + break; + } + default: { + SAY("MISTAKE: %i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + } + p2 += 2; + if (true == isuy) + isuy = false; + else + isuy = true; + p3 += bytesperpixel; + } + return 0; + } else { + /*---------------------------------------------------*/ + /* + ** BGR + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } + else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = b; + *pcache++ = g; + *pcache++ = r; + break; + } + case 2: { + *p3 = b; + *(p3 + 1) = g; + *pcache++ = r; + break; + } + default: { + SAY("MISTAKE: %i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + } + p2 += 2; + if (true == isuy) + isuy = false; + else + isuy = true; + p3 += bytesperpixel; + } + } + return 0; + } else { + if (false == byteswaporder) { + /*---------------------------------------------------*/ + /* + ** RGB DECIMATED + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + if (true == isuy) { + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - \ + gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = r; + *pcache++ = g; + *pcache++ = b; + break; + } + case 2: { + *p3 = r; + *(p3 + 1) = g; + *pcache++ = b; + break; + } + default: { + SAY("MISTAKE: " \ + "%i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + } + isuy = false; + p3 += bytesperpixel; + } else { + isuy = true; + } + p2 += 2; + } + return 0; + } else { + /*---------------------------------------------------*/ + /* + * BGR DECIMATED + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + if (true == isuy) { + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - \ + gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = b; + *pcache++ = g; + *pcache++ = r; + break; + } + case 2: { + *p3 = b; + *(p3 + 1) = g; + *pcache++ = r; + break; + } + default: { + SAY("MISTAKE: " \ + "%i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + } + isuy = false; + p3 += bytesperpixel; + } + else + isuy = true; + p2 += 2; + } + return 0; + } + } + break; + } +case 4: + { + if (false == decimatepixel) { + if (false == byteswaporder) { + /*---------------------------------------------------*/ + /* + ** RGBA + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = r; + *pcache++ = g; + *pcache++ = b; + *pcache++ = 0; + break; + } + case 2: { + *p3 = r; + *(p3 + 1) = g; + *pcache++ = b; + *pcache++ = 0; + break; + } + case 3: { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + *pcache++ = 0; + break; + } + default: { + SAY("MISTAKE: %i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + *(p3 + 3) = 0; + } + p2 += 2; + if (true == isuy) + isuy = false; + else + isuy = true; + p3 += bytesperpixel; + } + return 0; + } else { + /*---------------------------------------------------*/ + /* + ** BGRA + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = b; + *pcache++ = g; + *pcache++ = r; + *pcache++ = 0; + break; + } + case 2: { + *p3 = b; + *(p3 + 1) = g; + *pcache++ = r; + *pcache++ = 0; + break; + } + case 3: { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + *pcache++ = 0; + break; + } + default: { + SAY("MISTAKE: %i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + *(p3 + 3) = 0; + } + p2 += 2; + if (true == isuy) + isuy = false; + else + isuy = true; + p3 += bytesperpixel; + } + } + return 0; + } else { + if (false == byteswaporder) { + /*---------------------------------------------------*/ + /* + ** RGBA DECIMATED + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + if (true == isuy) { + + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - \ + gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = r; + *pcache++ = g; + *pcache++ = b; + *pcache++ = 0; + break; + } + case 2: { + *p3 = r; + *(p3 + 1) = g; + *pcache++ = b; + *pcache++ = 0; + break; + } + case 3: { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + *pcache++ = 0; + break; + } + default: { + SAY("MISTAKE: " \ + "%i=rump\n", \ + bytesperpixel - \ + rump); + return -EFAULT; + } + } + } else { + *p3 = r; + *(p3 + 1) = g; + *(p3 + 2) = b; + *(p3 + 3) = 0; + } + isuy = false; + p3 += bytesperpixel; + } else + isuy = true; + p2 += 2; + } + return 0; + } else { + /*---------------------------------------------------*/ + /* + ** BGRA DECIMATED + */ + /*---------------------------------------------------*/ + while (pz > p2) { + if (pr <= (p3 + bytesperpixel)) + last = true; + else + last = false; + y = *p2; + if ((true == last) && (0x0C & mask)) { + if (0x04 & mask) { + if (true == isuy) + v = margin; + else + u = margin; + } else + if (0x08 & mask) + ; + } else { + if (true == isuy) + v = *(p2 + 1); + else + u = *(p2 + 1); + } + + if (true == isuy) { + s32 = ay[(int)y] + rv[(int)v]; + r = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] - gu[(int)u] - \ + gv[(int)v]; + g = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + s32 = ay[(int)y] + bu[(int)u]; + b = (255 < s32) ? 255 : ((0 > s32) ? \ + 0 : (__u8)s32); + + if ((true == last) && rump) { + pcache = &cache[0]; + switch (bytesperpixel - rump) { + case 1: { + *p3 = b; + *pcache++ = g; + *pcache++ = r; + *pcache++ = 0; + break; + } + case 2: { + *p3 = b; + *(p3 + 1) = g; + *pcache++ = r; + *pcache++ = 0; + break; + } + case 3: { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + *pcache++ = 0; + break; + } + default: { + SAY("MISTAKE: " \ + "%i=rump\n", \ + bytesperpixel - rump); + return -EFAULT; + } + } + } else { + *p3 = b; + *(p3 + 1) = g; + *(p3 + 2) = r; + *(p3 + 3) = 0; + } + isuy = false; + p3 += bytesperpixel; + } else + isuy = true; + p2 += 2; + } + return 0; + } + } + break; + } +default: { + SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel); + return -EFAULT; + } +} +return 0; +} +/*****************************************************************************/ +void +debrief(struct easycap *peasycap) +{ +if ((struct usb_device *)NULL != peasycap->pusb_device) { + check_stk(peasycap->pusb_device); + check_saa(peasycap->pusb_device); + sayreadonly(peasycap); + SAY("%i=peasycap->field_fill\n", peasycap->field_fill); + SAY("%i=peasycap->field_read\n", peasycap->field_read); + SAY("%i=peasycap->frame_fill\n", peasycap->frame_fill); + SAY("%i=peasycap->frame_read\n", peasycap->frame_read); +} +return; +} +/*****************************************************************************/ +void +sayreadonly(struct easycap *peasycap) +{ +static int done; +int got00, got1F, got60, got61, got62; + +if ((!done) && ((struct usb_device *)NULL != peasycap->pusb_device)) { + done = 1; + got00 = read_saa(peasycap->pusb_device, 0x00); + got1F = read_saa(peasycap->pusb_device, 0x1F); + got60 = read_saa(peasycap->pusb_device, 0x60); + got61 = read_saa(peasycap->pusb_device, 0x61); + got62 = read_saa(peasycap->pusb_device, 0x62); + SAY("0x%02X=reg0x00 0x%02X=reg0x1F\n", got00, got1F); + SAY("0x%02X=reg0x60 0x%02X=reg0x61 0x%02X=reg0x62\n", \ + got60, got61, got62); +} +return; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434 + */ +/*---------------------------------------------------------------------------*/ +int easycap_mmap(struct file *file, struct vm_area_struct *pvma) +{ + +JOT(8, "\n"); + +pvma->vm_ops = &easycap_vm_ops; +pvma->vm_flags |= VM_RESERVED; +if (NULL != file) + pvma->vm_private_data = file->private_data; +easycap_vma_open(pvma); +return 0; +} +/*****************************************************************************/ +void +easycap_vma_open(struct vm_area_struct *pvma) +{ +struct easycap *peasycap; + +peasycap = pvma->vm_private_data; +if (NULL != peasycap) + peasycap->vma_many++; + +JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); + +return; +} +/*****************************************************************************/ +void +easycap_vma_close(struct vm_area_struct *pvma) +{ +struct easycap *peasycap; + +peasycap = pvma->vm_private_data; +if (NULL != peasycap) { + peasycap->vma_many--; + JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); +} +return; +} +/*****************************************************************************/ +int +easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf) +{ +int k, m, retcode; +void *pbuf; +struct page *page; +struct easycap *peasycap; + +retcode = VM_FAULT_NOPAGE; +pbuf = (void *)NULL; +page = (struct page *)NULL; + +if (NULL == pvma) { + SAY("pvma is NULL\n"); + return retcode; +} +if (NULL == pvmf) { + SAY("pvmf is NULL\n"); + return retcode; +} + +k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE); +m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE); + +if (!m) + JOT(4, "%4i=k, %4i=m\n", k, m); +else + JOT(16, "%4i=k, %4i=m\n", k, m); + +if ((0 > k) || (FRAME_BUFFER_MANY <= k)) { + SAY("ERROR: buffer index %i out of range\n", k); + return retcode; +} +if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) { + SAY("ERROR: page number %i out of range\n", m); + return retcode; +} +peasycap = pvma->vm_private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return retcode; +} +mutex_lock(&(peasycap->mutex_mmap_video[0])); +/*---------------------------------------------------------------------------*/ +pbuf = peasycap->frame_buffer[k][m].pgo; +if (NULL == pbuf) { + SAY("ERROR: pbuf is NULL\n"); + goto finish; +} +page = virt_to_page(pbuf); +if (NULL == page) { + SAY("ERROR: page is NULL\n"); + goto finish; +} +get_page(page); +/*---------------------------------------------------------------------------*/ +finish: +mutex_unlock(&(peasycap->mutex_mmap_video[0])); +if (NULL == page) { + SAY("ERROR: page is NULL after get_page(page)\n"); +} else { + pvmf->page = page; + retcode = VM_FAULT_MINOR; +} +return retcode; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS + * PROVIDED peasycap->video_idle IS ZER0. REGARDLESS OF THIS BEING TRUE, + * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO. + * + * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP. + * + * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE + * STORED IN THE TWO-BYTE STATUS PARAMETER + * peasycap->field_buffer[peasycap->field_fill][0].kount + * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER. + * + * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H + * CHIP. + * + * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE: + * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS + * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA + * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA + * 0 != (kount & 0x0400) => FIELD WAS SUBMITTED BY BRIDGER ROUTINE + * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED + * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY? + */ +/*---------------------------------------------------------------------------*/ +void +easycap_complete(struct urb *purb) +{ +static int mt; +struct easycap *peasycap; +struct data_buffer *pfield_buffer; +char errbuf[16]; +int i, more, much, leap, rc, last; +int videofieldamount; +unsigned int override; +int framestatus, framelength, frameactual, frameoffset; +__u8 *pu; +#if defined(BRIDGER) +struct timeval timeval; +long long usec; +#endif /*BRIDGER*/ + +if (NULL == purb) { + SAY("ERROR: easycap_complete(): purb is NULL\n"); + return; +} +peasycap = purb->context; +if (NULL == peasycap) { + SAY("ERROR: easycap_complete(): peasycap is NULL\n"); + return; +} + +if (peasycap->video_eof) + return; + +for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) + if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) + break; +JOT(16, "%2i=urb\n", i); +last = peasycap->video_isoc_sequence; +if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \ + (0 != i)) || \ + (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \ + ((last + 1) != i))) { + SAY("ERROR: out-of-order urbs %i,%i ... continuing\n", last, i); +} +peasycap->video_isoc_sequence = i; + +if (peasycap->video_idle) { + JOT(16, "%i=video_idle %i=video_isoc_streaming\n", \ + peasycap->video_idle, peasycap->video_isoc_streaming); + if (peasycap->video_isoc_streaming) { + rc = usb_submit_urb(purb, GFP_ATOMIC); + if (0 != rc) { + SAY("ERROR: while %i=video_idle, " \ + "usb_submit_urb() failed with rc:\n", \ + peasycap->video_idle); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); + break; + } + case -ENODEV: { + SAY("ENODEV\n"); + break; + } + case -ENXIO: { + SAY("ENXIO\n"); + break; + } + case -EINVAL: { + SAY("EINVAL\n"); + break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); + break; + } + case -EFBIG: { + SAY("EFBIG\n"); + break; + } + case -EPIPE: { + SAY("EPIPE\n"); + break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); + break; + } + default: { + SAY("0x%08X\n", rc); + break; + } + } + } + } +return; +} +override = 0; +/*---------------------------------------------------------------------------*/ +if (FIELD_BUFFER_MANY <= peasycap->field_fill) { + SAY("ERROR: bad peasycap->field_fill\n"); + return; +} +if (purb->status) { + if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) { + JOT(8, "urb status -ESHUTDOWN or -ENOENT\n"); + return; + } + + (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ; + SAY("ERROR: bad urb status:\n"); + switch (purb->status) { + case -EINPROGRESS: { + SAY("-EINPROGRESS\n"); break; + } + case -ENOSR: { + SAY("-ENOSR\n"); break; + } + case -EPIPE: { + SAY("-EPIPE\n"); break; + } + case -EOVERFLOW: { + SAY("-EOVERFLOW\n"); break; + } + case -EPROTO: { + SAY("-EPROTO\n"); break; + } + case -EILSEQ: { + SAY("-EILSEQ\n"); break; + } + case -ETIMEDOUT: { + SAY("-ETIMEDOUT\n"); break; + } + case -EMSGSIZE: { + SAY("-EMSGSIZE\n"); break; + } + case -EOPNOTSUPP: { + SAY("-EOPNOTSUPP\n"); break; + } + case -EPFNOSUPPORT: { + SAY("-EPFNOSUPPORT\n"); break; + } + case -EAFNOSUPPORT: { + SAY("-EAFNOSUPPORT\n"); break; + } + case -EADDRINUSE: { + SAY("-EADDRINUSE\n"); break; + } + case -EADDRNOTAVAIL: { + SAY("-EADDRNOTAVAIL\n"); break; + } + case -ENOBUFS: { + SAY("-ENOBUFS\n"); break; + } + case -EISCONN: { + SAY("-EISCONN\n"); break; + } + case -ENOTCONN: { + SAY("-ENOTCONN\n"); break; + } + case -ESHUTDOWN: { + SAY("-ESHUTDOWN\n"); break; + } + case -ENOENT: { + SAY("-ENOENT\n"); break; + } + case -ECONNRESET: { + SAY("-ECONNRESET\n"); break; + } + default: { + SAY("unknown error code 0x%08X\n", purb->status); break; + } + } +/*---------------------------------------------------------------------------*/ +} else { + for (i = 0; i < purb->number_of_packets; i++) { + if (0 != purb->iso_frame_desc[i].status) { + (peasycap->field_buffer\ + [peasycap->field_fill][0].kount) |= 0x8000 ; + switch (purb->iso_frame_desc[i].status) { + case 0: { + strcpy(&errbuf[0], "OK"); break; + } + case -ENOENT: { + strcpy(&errbuf[0], "-ENOENT"); break; + } + case -EINPROGRESS: { + strcpy(&errbuf[0], "-EINPROGRESS"); break; + } + case -EPROTO: { + strcpy(&errbuf[0], "-EPROTO"); break; + } + case -EILSEQ: { + strcpy(&errbuf[0], "-EILSEQ"); break; + } + case -ETIME: { + strcpy(&errbuf[0], "-ETIME"); break; + } + case -ETIMEDOUT: { + strcpy(&errbuf[0], "-ETIMEDOUT"); break; + } + case -EPIPE: { + strcpy(&errbuf[0], "-EPIPE"); break; + } + case -ECOMM: { + strcpy(&errbuf[0], "-ECOMM"); break; + } + case -ENOSR: { + strcpy(&errbuf[0], "-ENOSR"); break; + } + case -EOVERFLOW: { + strcpy(&errbuf[0], "-EOVERFLOW"); break; + } + case -EREMOTEIO: { + strcpy(&errbuf[0], "-EREMOTEIO"); break; + } + case -ENODEV: { + strcpy(&errbuf[0], "-ENODEV"); break; + } + case -EXDEV: { + strcpy(&errbuf[0], "-EXDEV"); break; + } + case -EINVAL: { + strcpy(&errbuf[0], "-EINVAL"); break; + } + case -ECONNRESET: { + strcpy(&errbuf[0], "-ECONNRESET"); break; + } + case -ESHUTDOWN: { + strcpy(&errbuf[0], "-ESHUTDOWN"); break; + } + default: { + strcpy(&errbuf[0], "unknown error"); break; + } + } + } + framestatus = purb->iso_frame_desc[i].status; + framelength = purb->iso_frame_desc[i].length; + frameactual = purb->iso_frame_desc[i].actual_length; + frameoffset = purb->iso_frame_desc[i].offset; + + JOT(16, "frame[%2i]:" \ + "%4i=status " \ + "%4i=actual " \ + "%4i=length " \ + "%5i=offset\n", \ + i, framestatus, frameactual, framelength, frameoffset); + if (!purb->iso_frame_desc[i].status) { + more = purb->iso_frame_desc[i].actual_length; + pfield_buffer = &peasycap->field_buffer\ + [peasycap->field_fill][peasycap->field_page]; + videofieldamount = (peasycap->field_page * \ + PAGE_SIZE) + \ + (int)(pfield_buffer->pto - pfield_buffer->pgo); + if (4 == more) + mt++; + if (4 < more) { + if (mt) { + JOT(8, "%4i empty video urb frames\n", mt); + mt = 0; + } + if (FIELD_BUFFER_MANY <= peasycap->field_fill) { + SAY("ERROR: bad peasycap->field_fill\n"); + return; + } + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ + peasycap->field_page) { + SAY("ERROR: bad peasycap->field_page\n"); + return; + } + pfield_buffer = &peasycap->field_buffer\ + [peasycap->field_fill][peasycap->field_page]; + pu = (__u8 *)(purb->transfer_buffer + \ + purb->iso_frame_desc[i].offset); + if (0x80 & *pu) + leap = 8; + else + leap = 4; +/*--------------------------------------------------------------------------*/ +/* + * EIGHT-BYTE END-OF-VIDEOFIELD MARKER. + * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY, + * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD. + * + * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER + * BYTE OF + * peasycap->field_buffer[peasycap->field_fill][0].kount + * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS + * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA + * NOTHING IS OFFERED TO dqbuf(). + * + * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT + * RESTS WITH dqbuf(). + */ +/*---------------------------------------------------------------------------*/ + if ((8 == more) || override) { + if (videofieldamount > \ + peasycap->videofieldamount) { + if (2 == videofieldamount - \ + peasycap->\ + videofieldamount) + (peasycap->field_buffer\ + [peasycap->field_fill]\ + [0].kount) |= 0x0100; + else + (peasycap->field_buffer\ + [peasycap->field_fill]\ + [0].kount) |= 0x4000; + } else if (videofieldamount < \ + peasycap->\ + videofieldamount) { + (peasycap->field_buffer\ + [peasycap->field_fill]\ + [0].kount) |= 0x2000; + } + if (!(0xFF00 & peasycap->field_buffer\ + [peasycap->field_fill]\ + [0].kount)) { + (peasycap->video_junk)--; + if (-16 > peasycap->video_junk) + peasycap->video_junk = -16; + peasycap->field_read = \ + (peasycap->\ + field_fill)++; + + if (FIELD_BUFFER_MANY <= \ + peasycap->field_fill) + peasycap->field_fill = 0; + peasycap->field_page = 0; + pfield_buffer = &peasycap->\ + field_buffer\ + [peasycap->field_fill]\ + [peasycap->field_page]; + pfield_buffer->pto = \ + pfield_buffer->pgo; + + JOT(8, "bumped to: %i=peasycap->" \ + "field_fill %i=parity\n", \ + peasycap->field_fill, \ + 0x00FF & pfield_buffer->kount); + JOT(8, "field buffer %i has %i " \ + "bytes fit to be read\n", \ + peasycap->field_read, \ + videofieldamount); + JOT(8, "wakeup call to wq_video, " \ + "%i=field_read %i=field_fill "\ + "%i=parity\n", \ + peasycap->field_read, \ + peasycap->field_fill, \ + 0x00FF & peasycap->\ + field_buffer[peasycap->\ + field_read][0].kount); + wake_up_interruptible(&(peasycap->\ + wq_video)); + do_gettimeofday(&peasycap->timeval7); + } else { + peasycap->video_junk++; + JOT(8, "field buffer %i had %i " \ + "bytes, now discarded\n", \ + peasycap->field_fill, \ + videofieldamount); + + (peasycap->field_fill)++; + + if (FIELD_BUFFER_MANY <= \ + peasycap->field_fill) + peasycap->field_fill = 0; + peasycap->field_page = 0; + pfield_buffer = \ + &peasycap->field_buffer\ + [peasycap->field_fill]\ + [peasycap->field_page]; + pfield_buffer->pto = \ + pfield_buffer->pgo; + + JOT(8, "bumped to: %i=peasycap->" \ + "field_fill %i=parity\n", \ + peasycap->field_fill, \ + 0x00FF & pfield_buffer->kount); + } + if (8 == more) { + JOT(8, "end-of-field: received " \ + "parity byte 0x%02X\n", \ + (0xFF & *pu)); + if (0x40 & *pu) + pfield_buffer->kount = 0x0000; + else + pfield_buffer->kount = 0x0001; + JOT(8, "end-of-field: 0x%02X=kount\n",\ + 0xFF & pfield_buffer->kount); + } + } +/*---------------------------------------------------------------------------*/ +/* + * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER + */ +/*---------------------------------------------------------------------------*/ + pu += leap; + more -= leap; + + if (FIELD_BUFFER_MANY <= peasycap->field_fill) { + SAY("ERROR: bad peasycap->field_fill\n"); + return; + } + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ + peasycap->field_page) { + SAY("ERROR: bad peasycap->field_page\n"); + return; + } + pfield_buffer = &peasycap->field_buffer\ + [peasycap->field_fill][peasycap->field_page]; + while (more) { + pfield_buffer = &peasycap->field_buffer\ + [peasycap->field_fill]\ + [peasycap->field_page]; + if (PAGE_SIZE < (pfield_buffer->pto - \ + pfield_buffer->pgo)) { + SAY("ERROR: bad pfield_buffer->pto\n"); + return; + } + if (PAGE_SIZE == (pfield_buffer->pto - \ + pfield_buffer->pgo)) { + (peasycap->field_page)++; + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ + peasycap->field_page) { + JOT(16, "wrapping peasycap->" \ + "field_page\n"); + peasycap->field_page = 0; + } + pfield_buffer = &peasycap->\ + field_buffer\ + [peasycap->field_fill]\ + [peasycap->field_page]; + pfield_buffer->pto = \ + pfield_buffer->pgo; + } + + much = PAGE_SIZE - (int)(pfield_buffer->pto - \ + pfield_buffer->pgo); + + if (much > more) + much = more; + memcpy(pfield_buffer->pto, pu, much); + pu += much; + (pfield_buffer->pto) += much; + more -= much; + } + } + } + } +} +/*---------------------------------------------------------------------------*/ +/* + * + * + * *** UNDER DEVELOPMENT/TESTING - NOT READY YET! *** + * + * + * + * VIDEOTAPES MAY HAVE BEEN MANUALLY PAUSED AND RESTARTED DURING RECORDING. + * THIS CAUSES LOSS OF SYNC, CONFUSING DOWNSTREAM USERSPACE PROGRAMS WHICH + * MAY INTERPRET THE INTERRUPTION AS A SYMPTOM OF LATENCY. TO OVERCOME THIS + * THE DRIVER BRIDGES THE HIATUS BY SENDING DUMMY VIDEO FRAMES AT ROUGHLY + * THE RIGHT TIME INTERVALS IN THE HOPE OF PERSUADING THE DOWNSTREAM USERSPACE + * PROGRAM TO RESUME NORMAL SERVICE WHEN THE INTERRUPTION IS OVER. + */ +/*---------------------------------------------------------------------------*/ +#if defined(BRIDGER) +do_gettimeofday(&timeval); +if (peasycap->timeval7.tv_sec) { + usec = 1000000*(timeval.tv_sec - peasycap->timeval7.tv_sec) + \ + (timeval.tv_usec - peasycap->timeval7.tv_usec); + if (usec > (peasycap->usec + peasycap->tolerate)) { + JOT(8, "bridging hiatus\n"); + peasycap->video_junk = 0; + peasycap->field_buffer[peasycap->field_fill][0].kount |= 0x0400; + + peasycap->field_read = (peasycap->field_fill)++; + + if (FIELD_BUFFER_MANY <= peasycap->field_fill) \ + peasycap->field_fill = 0; + peasycap->field_page = 0; + pfield_buffer = &peasycap->field_buffer\ + [peasycap->field_fill][peasycap->field_page]; + pfield_buffer->pto = pfield_buffer->pgo; + + JOT(8, "bumped to: %i=peasycap->field_fill %i=parity\n", \ + peasycap->field_fill, 0x00FF & pfield_buffer->kount); + JOT(8, "field buffer %i has %i bytes to be overwritten\n", \ + peasycap->field_read, videofieldamount); + JOT(8, "wakeup call to wq_video, " \ + "%i=field_read %i=field_fill %i=parity\n", \ + peasycap->field_read, peasycap->field_fill, \ + 0x00FF & \ + peasycap->field_buffer[peasycap->field_read][0].kount); + wake_up_interruptible(&(peasycap->wq_video)); + do_gettimeofday(&peasycap->timeval7); + } +} +#endif /*BRIDGER*/ +/*---------------------------------------------------------------------------*/ +/* + * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS. + * + * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION + * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. + */ +/*---------------------------------------------------------------------------*/ +if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) { + SAY("easycap driver shutting down on condition green\n"); + peasycap->video_eof = 1; + peasycap->audio_eof = 1; + peasycap->video_junk = -VIDEO_ISOC_BUFFER_MANY; + wake_up_interruptible(&(peasycap->wq_video)); + wake_up_interruptible(&(peasycap->wq_audio)); + return; +} +if (peasycap->video_isoc_streaming) { + rc = usb_submit_urb(purb, GFP_ATOMIC); + if (0 != rc) { + SAY("ERROR: while %i=video_idle, usb_submit_urb() failed " \ + "with rc:\n", peasycap->video_idle); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); break; + } + case -ENODEV: { + SAY("ENODEV\n"); break; + } + case -ENXIO: { + SAY("ENXIO\n"); break; + } + case -EINVAL: { + SAY("EINVAL\n"); break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); break; + } + case -EFBIG: { + SAY("EFBIG\n"); break; + } + case -EPIPE: { + SAY("EPIPE\n"); break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); break; + } + default: { + SAY("0x%08X\n", rc); break; + } + } + } +} +return; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * + * FIXME + * + * + * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE DEVICE IS + * PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST. + * IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops. + * + * THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE. + */ +/*---------------------------------------------------------------------------*/ +int +easycap_usb_probe(struct usb_interface *pusb_interface, \ + const struct usb_device_id *id) +{ +struct usb_device *pusb_device, *pusb_device1; +struct usb_host_interface *pusb_host_interface; +struct usb_endpoint_descriptor *pepd; +struct usb_interface_descriptor *pusb_interface_descriptor; +struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor; +struct urb *purb; +static struct easycap *peasycap /*=NULL*/; +struct data_urb *pdata_urb; +size_t wMaxPacketSize; +int ISOCwMaxPacketSize; +int BULKwMaxPacketSize; +int INTwMaxPacketSize; +int CTRLwMaxPacketSize; +__u8 bEndpointAddress; +__u8 ISOCbEndpointAddress; +__u8 INTbEndpointAddress; +int isin, i, j, k, m; +__u8 bInterfaceNumber; +__u8 bInterfaceClass; +__u8 bInterfaceSubClass; +void *pbuf; +int okalt[8], isokalt; +int okepn[8], isokepn; +int okmps[8], isokmps; +int maxpacketsize; +int rc; + +JOT(4, "\n"); + +if ((struct usb_interface *)NULL == pusb_interface) { + SAY("ERROR: pusb_interface is NULL\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +/* + * GET POINTER TO STRUCTURE usb_device + */ +/*---------------------------------------------------------------------------*/ +pusb_device1 = container_of(pusb_interface->dev.parent, \ + struct usb_device, dev); +if ((struct usb_device *)NULL == pusb_device1) { + SAY("ERROR: pusb_device1 is NULL\n"); + return -EFAULT; +} +pusb_device = usb_get_dev(pusb_device1); +if ((struct usb_device *)NULL == pusb_device) { + SAY("ERROR: pusb_device is NULL\n"); + return -EFAULT; +} +if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) { + JOT(4, "ERROR: pusb_device1 != pusb_device\n"); + return -EFAULT; +} + +JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations); + +/*---------------------------------------------------------------------------*/ +pusb_host_interface = pusb_interface->cur_altsetting; +if (NULL == pusb_host_interface) { + SAY("ERROR: pusb_host_interface is NULL\n"); + return -EFAULT; +} +pusb_interface_descriptor = &(pusb_host_interface->desc); +if (NULL == pusb_interface_descriptor) { + SAY("ERROR: pusb_interface_descriptor is NULL\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +/* + * GET PROPERTIES OF PROBED INTERFACE + */ +/*---------------------------------------------------------------------------*/ +bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber; +bInterfaceClass = pusb_interface_descriptor->bInterfaceClass; +bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass; + +JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n", \ + bInterfaceNumber, pusb_interface->num_altsetting); +JOT(4, "intf[%i]: pusb_interface->cur_altsetting - " \ + "pusb_interface->altsetting=%li\n", bInterfaceNumber, \ + (long int)(pusb_interface->cur_altsetting - \ + pusb_interface->altsetting)); +switch (bInterfaceClass) { +case USB_CLASS_AUDIO: { + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n", \ + bInterfaceNumber, bInterfaceClass); break; + } +case USB_CLASS_VIDEO: { + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n", \ + bInterfaceNumber, bInterfaceClass); break; + } +case USB_CLASS_VENDOR_SPEC: { + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n", \ + bInterfaceNumber, bInterfaceClass); break; + } +default: + break; +} +switch (bInterfaceSubClass) { +case 0x01: { + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n", \ + bInterfaceNumber, bInterfaceSubClass); break; +} +case 0x02: { + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n", \ + bInterfaceNumber, bInterfaceSubClass); break; +} +case 0x03: { + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n", \ + bInterfaceNumber, bInterfaceSubClass); break; +} +default: + break; +} +/*---------------------------------------------------------------------------*/ +pusb_interface_assoc_descriptor = pusb_interface->intf_assoc; +if (NULL != pusb_interface_assoc_descriptor) { + JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n", \ + bInterfaceNumber, \ + pusb_interface_assoc_descriptor->bFirstInterface, \ + pusb_interface_assoc_descriptor->bInterfaceCount); +} else { +JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \ + bInterfaceNumber); +} +/*---------------------------------------------------------------------------*/ +/* + * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED. + * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS + * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE DEVICE WAS PHYSICALLY + * UNPLUGGED. + */ +/*---------------------------------------------------------------------------*/ +if (0 == bInterfaceNumber) { + peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); + if (NULL == peasycap) { + SAY("ERROR: Could not allocate peasycap\n"); + return -ENOMEM; + } else { + peasycap->allocation_video_struct = sizeof(struct easycap); + peasycap->allocation_video_page = 0; + peasycap->allocation_video_urb = 0; + peasycap->allocation_audio_struct = 0; + peasycap->allocation_audio_page = 0; + peasycap->allocation_audio_urb = 0; + } +/*---------------------------------------------------------------------------*/ +/* + * INITIALIZE THE NEW easycap STRUCTURE. + * NO PARAMETERS ARE SPECIFIED HERE REQUIRING THE SETTING OF REGISTERS. + * THAT IS DONE FIRST BY easycap_open() AND LATER BY easycap_ioctl(). + */ +/*---------------------------------------------------------------------------*/ + peasycap->pusb_device = pusb_device; + peasycap->pusb_interface = pusb_interface; + + kref_init(&peasycap->kref); + JOT(8, "intf[%i]: after kref_init(..._video) " \ + "%i=peasycap->kref.refcount.counter\n", \ + bInterfaceNumber, peasycap->kref.refcount.counter); + + init_waitqueue_head(&(peasycap->wq_video)); + init_waitqueue_head(&(peasycap->wq_audio)); + + mutex_init(&(peasycap->mutex_timeval0)); + mutex_init(&(peasycap->mutex_timeval1)); + + for (k = 0; k < FRAME_BUFFER_MANY; k++) + mutex_init(&(peasycap->mutex_mmap_video[k])); + + peasycap->ilk = 0; + peasycap->microphone = false; + + peasycap->video_interface = -1; + peasycap->video_altsetting_on = -1; + peasycap->video_altsetting_off = -1; + peasycap->video_endpointnumber = -1; + peasycap->video_isoc_maxframesize = -1; + peasycap->video_isoc_buffer_size = -1; + + peasycap->audio_interface = -1; + peasycap->audio_altsetting_on = -1; + peasycap->audio_altsetting_off = -1; + peasycap->audio_endpointnumber = -1; + peasycap->audio_isoc_maxframesize = -1; + peasycap->audio_isoc_buffer_size = -1; + + peasycap->frame_buffer_many = FRAME_BUFFER_MANY; + + if ((struct mutex *)NULL == &(peasycap->mutex_mmap_video[0])) { + SAY("ERROR: &(peasycap->mutex_mmap_video[%i]) is NULL\n", 0); + return -EFAULT; + } +/*---------------------------------------------------------------------------*/ +/* + * DYNAMICALLY FILL IN THE AVAILABLE FORMATS. + */ +/*---------------------------------------------------------------------------*/ + rc = fillin_formats(); + if (0 > rc) { + SAY("ERROR: fillin_formats() returned %i\n", rc); + return -EFAULT; + } + JOT(4, "%i formats available\n", rc); + } else { +/*---------------------------------------------------------------------------*/ + if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap is NULL " \ + "when probing interface %i\n", \ + bInterfaceNumber); + return -EFAULT; + } + + JOT(8, "kref_get() with %i=peasycap->kref.refcount.counter\n", \ + (int)peasycap->kref.refcount.counter); + kref_get(&peasycap->kref); +} +/*---------------------------------------------------------------------------*/ +if ((USB_CLASS_VIDEO == bInterfaceClass) || \ + (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) { + if (-1 == peasycap->video_interface) { + peasycap->video_interface = bInterfaceNumber; + JOT(4, "setting peasycap->video_interface=%i\n", \ + peasycap->video_interface); + } else { + if (peasycap->video_interface != bInterfaceNumber) { + SAY("ERROR: attempting to reset " \ + "peasycap->video_interface\n"); + SAY("...... continuing with " \ + "%i=peasycap->video_interface\n", \ + peasycap->video_interface); + } + } +} else if ((USB_CLASS_AUDIO == bInterfaceClass) && \ + (0x02 == bInterfaceSubClass)) { + if (-1 == peasycap->audio_interface) { + peasycap->audio_interface = bInterfaceNumber; + JOT(4, "setting peasycap->audio_interface=%i\n", \ + peasycap->audio_interface); + } else { + if (peasycap->audio_interface != bInterfaceNumber) { + SAY("ERROR: attempting to reset " \ + "peasycap->audio_interface\n"); + SAY("...... continuing with " \ + "%i=peasycap->audio_interface\n", \ + peasycap->audio_interface); + } + } +} +/*---------------------------------------------------------------------------*/ +/* + * INVESTIGATE ALL ALTSETTINGS. + * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS. + */ +/*---------------------------------------------------------------------------*/ +isokalt = 0; +isokepn = 0; +isokmps = 0; + +for (i = 0; i < pusb_interface->num_altsetting; i++) { + pusb_host_interface = &(pusb_interface->altsetting[i]); + if ((struct usb_host_interface *)NULL == pusb_host_interface) { + SAY("ERROR: pusb_host_interface is NULL\n"); + return -EFAULT; + } + pusb_interface_descriptor = &(pusb_host_interface->desc); + if ((struct usb_interface_descriptor *)NULL == \ + pusb_interface_descriptor) { + SAY("ERROR: pusb_interface_descriptor is NULL\n"); + return -EFAULT; + } + + JOT(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType); + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber); + JOT(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting); + JOT(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints); + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass); + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass); + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol); + JOT(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n", \ + bInterfaceNumber, i, pusb_interface_descriptor->iInterface); + + ISOCwMaxPacketSize = -1; + BULKwMaxPacketSize = -1; + INTwMaxPacketSize = -1; + CTRLwMaxPacketSize = -1; + ISOCbEndpointAddress = 0; + INTbEndpointAddress = 0; + + if (0 == pusb_interface_descriptor->bNumEndpoints) + JOT(4, "intf[%i]alt[%i] has no endpoints\n", \ + bInterfaceNumber, i); +/*---------------------------------------------------------------------------*/ + for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) { + pepd = &(pusb_host_interface->endpoint[j].desc); + if ((struct usb_endpoint_descriptor *)NULL == pepd) { + SAY("ERROR: pepd is NULL.\n"); + SAY("...... skipping\n"); + continue; + } + wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize); + bEndpointAddress = pepd->bEndpointAddress; + + JOT(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n", \ + bInterfaceNumber, i, j, \ + pepd->bEndpointAddress); + JOT(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n", \ + bInterfaceNumber, i, j, \ + pepd->bmAttributes); + JOT(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n", \ + bInterfaceNumber, i, j, \ + pepd->wMaxPacketSize); + JOT(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n", + bInterfaceNumber, i, j, \ + pepd->bInterval); + + if (pepd->bEndpointAddress & USB_DIR_IN) { + JOT(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",\ + bInterfaceNumber, i, j); + isin = 1; + } else { + JOT(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",\ + bInterfaceNumber, i, j); + SAY("ERROR: OUT endpoint unexpected\n"); + SAY("...... continuing\n"); + isin = 0; + } + if ((pepd->bmAttributes & \ + USB_ENDPOINT_XFERTYPE_MASK) == \ + USB_ENDPOINT_XFER_ISOC) { + JOT(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",\ + bInterfaceNumber, i, j); + if (isin) { + switch (bInterfaceClass) { + case USB_CLASS_VIDEO: + case USB_CLASS_VENDOR_SPEC: { + if (!peasycap) { + SAY("MISTAKE: " \ + "peasycap is NULL\n"); + return -EFAULT; + } + if (pepd->wMaxPacketSize) { + if (8 > isokalt) { + okalt[isokalt] = i; + JOT(4,\ + "%i=okalt[%i]\n", \ + okalt[isokalt], \ + isokalt); + isokalt++; + } + if (8 > isokepn) { + okepn[isokepn] = \ + pepd->\ + bEndpointAddress & \ + 0x0F; + JOT(4,\ + "%i=okepn[%i]\n", \ + okepn[isokepn], \ + isokepn); + isokepn++; + } + if (8 > isokmps) { + okmps[isokmps] = \ + le16_to_cpu(pepd->\ + wMaxPacketSize); + JOT(4,\ + "%i=okmps[%i]\n", \ + okmps[isokmps], \ + isokmps); + isokmps++; + } + } else { + if (-1 == peasycap->\ + video_altsetting_off) { + peasycap->\ + video_altsetting_off =\ + i; + JOT(4, "%i=video_" \ + "altsetting_off " \ + "<====\n", \ + peasycap->\ + video_altsetting_off); + } else { + SAY("ERROR: peasycap" \ + "->video_altsetting_" \ + "off already set\n"); + SAY("...... " \ + "continuing with " \ + "%i=peasycap->video_" \ + "altsetting_off\n", \ + peasycap->\ + video_altsetting_off); + } + } + break; + } + case USB_CLASS_AUDIO: { + if (0x02 != bInterfaceSubClass) + break; + if (!peasycap) { + SAY("MISTAKE: " \ + "peasycap is NULL\n"); + return -EFAULT; + } + if (pepd->wMaxPacketSize) { + if (8 > isokalt) { + okalt[isokalt] = i ; + JOT(4,\ + "%i=okalt[%i]\n", \ + okalt[isokalt], \ + isokalt); + isokalt++; + } + if (8 > isokepn) { + okepn[isokepn] = \ + pepd->\ + bEndpointAddress & \ + 0x0F; + JOT(4,\ + "%i=okepn[%i]\n", \ + okepn[isokepn], \ + isokepn); + isokepn++; + } + if (8 > isokmps) { + okmps[isokmps] = \ + le16_to_cpu(pepd->\ + wMaxPacketSize); + JOT(4,\ + "%i=okmps[%i]\n",\ + okmps[isokmps], \ + isokmps); + isokmps++; + } + } else { + if (-1 == peasycap->\ + audio_altsetting_off) { + peasycap->\ + audio_altsetting_off =\ + i; + JOT(4, "%i=audio_" \ + "altsetting_off " \ + "<====\n", \ + peasycap->\ + audio_altsetting_off); + } else { + SAY("ERROR: peasycap" \ + "->audio_altsetting_" \ + "off already set\n"); + SAY("...... " \ + "continuing with " \ + "%i=peasycap->\ + audio_altsetting_" \ + "off\n", + peasycap->\ + audio_altsetting_off); + } + } + break; + } + default: + break; + } + } + } else if ((pepd->bmAttributes & \ + USB_ENDPOINT_XFERTYPE_MASK) ==\ + USB_ENDPOINT_XFER_BULK) { + JOT(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",\ + bInterfaceNumber, i, j); + } else if ((pepd->bmAttributes & \ + USB_ENDPOINT_XFERTYPE_MASK) ==\ + USB_ENDPOINT_XFER_INT) { + JOT(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",\ + bInterfaceNumber, i, j); + } else { + JOT(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",\ + bInterfaceNumber, i, j); + } + if (0 == pepd->wMaxPacketSize) { + JOT(4, "intf[%i]alt[%i]end[%i] " \ + "has zero packet size\n", \ + bInterfaceNumber, i, j); + } + } +} +/*---------------------------------------------------------------------------*/ +/* + * PERFORM INITIALIZATION OF THE PROBED INTERFACE + */ +/*---------------------------------------------------------------------------*/ +JOT(4, "initialization begins for interface %i\n", \ + pusb_interface_descriptor->bInterfaceNumber); +switch (bInterfaceNumber) { +/*---------------------------------------------------------------------------*/ +/* + * INTERFACE 0 IS THE VIDEO INTERFACE + */ +/*---------------------------------------------------------------------------*/ +case 0: { + if (!peasycap) { + SAY("MISTAKE: peasycap is NULL\n"); + return -EFAULT; + } + if (!isokalt) { + SAY("ERROR: no viable video_altsetting_on\n"); + return -ENOENT; + } else { + peasycap->video_altsetting_on = okalt[isokalt - 1]; + JOT(4, "%i=video_altsetting_on <====\n", \ + peasycap->video_altsetting_on); + } + if (!isokepn) { + SAY("ERROR: no viable video_endpointnumber\n"); + return -ENOENT; + } else { + peasycap->video_endpointnumber = okepn[isokepn - 1]; + JOT(4, "%i=video_endpointnumber\n", \ + peasycap->video_endpointnumber); + } + if (!isokmps) { + SAY("ERROR: no viable video_maxpacketsize\n"); + return -ENOENT; +/*---------------------------------------------------------------------------*/ +/* + * DECIDE THE VIDEO STREAMING PARAMETERS + */ +/*---------------------------------------------------------------------------*/ + } else { + maxpacketsize = okmps[isokmps - 1] - 1024; + if (USB_2_0_MAXPACKETSIZE > maxpacketsize) { + peasycap->video_isoc_maxframesize = maxpacketsize; + } else { + peasycap->video_isoc_maxframesize = \ + USB_2_0_MAXPACKETSIZE; + } + JOT(4, "%i=video_isoc_maxframesize\n", \ + peasycap->video_isoc_maxframesize); + if (0 >= peasycap->video_isoc_maxframesize) { + SAY("ERROR: bad video_isoc_maxframesize\n"); + return -ENOENT; + } + peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC; + JOT(4, "%i=video_isoc_framesperdesc\n", \ + peasycap->video_isoc_framesperdesc); + if (0 >= peasycap->video_isoc_framesperdesc) { + SAY("ERROR: bad video_isoc_framesperdesc\n"); + return -ENOENT; + } + peasycap->video_isoc_buffer_size = \ + peasycap->video_isoc_maxframesize * \ + peasycap->video_isoc_framesperdesc; + JOT(4, "%i=video_isoc_buffer_size\n", \ + peasycap->video_isoc_buffer_size); + if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < \ + peasycap->video_isoc_buffer_size) { + SAY("MISTAKE: " \ + "peasycap->video_isoc_buffer_size too big\n"); + return -EFAULT; + } + } +/*---------------------------------------------------------------------------*/ + if (-1 == peasycap->video_interface) { + SAY("MISTAKE: video_interface is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->video_altsetting_on) { + SAY("MISTAKE: video_altsetting_on is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->video_altsetting_off) { + SAY("MISTAKE: video_interface_off is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->video_endpointnumber) { + SAY("MISTAKE: video_endpointnumber is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->video_isoc_maxframesize) { + SAY("MISTAKE: video_isoc_maxframesize is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->video_isoc_buffer_size) { + SAY("MISTAKE: video_isoc_buffer_size is unset\n"); + return -EFAULT; + } +/*---------------------------------------------------------------------------*/ +/* + * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST. + */ +/*---------------------------------------------------------------------------*/ + INIT_LIST_HEAD(&(peasycap->urb_video_head)); + peasycap->purb_video_head = &(peasycap->urb_video_head); +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i frame buffers of size %li\n", \ + FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE); + JOT(4, ".... each scattered over %li pages\n", \ + FRAME_BUFFER_SIZE/PAGE_SIZE); + + for (k = 0; k < FRAME_BUFFER_MANY; k++) { + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { + if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) + SAY("attempting to reallocate frame " \ + " buffers\n"); + else { + pbuf = (void *)__get_free_page(GFP_KERNEL); + if ((void *)NULL == pbuf) { + SAY("ERROR: Could not allocate frame "\ + "buffer %i page %i\n", k, m); + return -ENOMEM; + } else + peasycap->allocation_video_page += 1; + peasycap->frame_buffer[k][m].pgo = pbuf; + } + peasycap->frame_buffer[k][m].pto = \ + peasycap->frame_buffer[k][m].pgo; + } + } + + peasycap->frame_fill = 0; + peasycap->frame_read = 0; + JOT(4, "allocation of frame buffers done: %i pages\n", k * \ + m); +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i field buffers of size %li\n", \ + FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE); + JOT(4, ".... each scattered over %li pages\n", \ + FIELD_BUFFER_SIZE/PAGE_SIZE); + + for (k = 0; k < FIELD_BUFFER_MANY; k++) { + for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { + if ((void *)NULL != peasycap->field_buffer[k][m].pgo) { + SAY("ERROR: attempting to reallocate " \ + "field buffers\n"); + } else { + pbuf = (void *) __get_free_page(GFP_KERNEL); + if ((void *)NULL == pbuf) { + SAY("ERROR: Could not allocate field" \ + " buffer %i page %i\n", k, m); + return -ENOMEM; + } + else + peasycap->allocation_video_page += 1; + peasycap->field_buffer[k][m].pgo = pbuf; + } + peasycap->field_buffer[k][m].pto = \ + peasycap->field_buffer[k][m].pgo; + } + peasycap->field_buffer[k][0].kount = 0x0200; + } + peasycap->field_fill = 0; + peasycap->field_page = 0; + peasycap->field_read = 0; + JOT(4, "allocation of field buffers done: %i pages\n", k * \ + m); +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i isoc video buffers of size %i\n", \ + VIDEO_ISOC_BUFFER_MANY, \ + peasycap->video_isoc_buffer_size); + JOT(4, ".... each occupying contiguous memory pages\n"); + + for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { + pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER); + if (NULL == pbuf) { + SAY("ERROR: Could not allocate isoc video buffer " \ + "%i\n", k); + return -ENOMEM; + } else + peasycap->allocation_video_page += \ + ((unsigned int)(0x01 << VIDEO_ISOC_ORDER)); + + peasycap->video_isoc_buffer[k].pgo = pbuf; + peasycap->video_isoc_buffer[k].pto = pbuf + \ + peasycap->video_isoc_buffer_size; + peasycap->video_isoc_buffer[k].kount = k; + } + JOT(4, "allocation of isoc video buffers done: %i pages\n", \ + k * (0x01 << VIDEO_ISOC_ORDER)); +/*---------------------------------------------------------------------------*/ +/* + * ALLOCATE AND INITIALIZE MULTIPLE struct urb ... + */ +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY); + JOT(4, "using %i=peasycap->video_isoc_framesperdesc\n", \ + peasycap->video_isoc_framesperdesc); + JOT(4, "using %i=peasycap->video_isoc_maxframesize\n", \ + peasycap->video_isoc_maxframesize); + JOT(4, "using %i=peasycap->video_isoc_buffer_sizen", \ + peasycap->video_isoc_buffer_size); + + for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { + purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, \ + GFP_KERNEL); + if (NULL == purb) { + SAY("ERROR: usb_alloc_urb returned NULL for buffer " \ + "%i\n", k); + return -ENOMEM; + } else + peasycap->allocation_video_urb += 1; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); + if (NULL == pdata_urb) { + SAY("ERROR: Could not allocate struct data_urb.\n"); + return -ENOMEM; + } else + peasycap->allocation_video_struct += \ + sizeof(struct data_urb); + + pdata_urb->purb = purb; + pdata_urb->isbuf = k; + pdata_urb->length = 0; + list_add_tail(&(pdata_urb->list_head), \ + peasycap->purb_video_head); +/*---------------------------------------------------------------------------*/ +/* + * ... AND INITIALIZE THEM + */ +/*---------------------------------------------------------------------------*/ + if (!k) { + JOT(4, "initializing video urbs thus:\n"); + JOT(4, " purb->interval = 1;\n"); + JOT(4, " purb->dev = peasycap->pusb_device;\n"); + JOT(4, " purb->pipe = usb_rcvisocpipe" \ + "(peasycap->pusb_device,%i);\n", \ + peasycap->video_endpointnumber); + JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); + JOT(4, " purb->transfer_buffer = peasycap->" \ + "video_isoc_buffer[.].pgo;\n"); + JOT(4, " purb->transfer_buffer_length = %i;\n", \ + peasycap->video_isoc_buffer_size); + JOT(4, " purb->complete = easycap_complete;\n"); + JOT(4, " purb->context = peasycap;\n"); + JOT(4, " purb->start_frame = 0;\n"); + JOT(4, " purb->number_of_packets = %i;\n", \ + peasycap->video_isoc_framesperdesc); + JOT(4, " for (j = 0; j < %i; j++)\n", \ + peasycap->video_isoc_framesperdesc); + JOT(4, " {\n"); + JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\ + peasycap->video_isoc_maxframesize); + JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \ + peasycap->video_isoc_maxframesize); + JOT(4, " }\n"); + } + + purb->interval = 1; + purb->dev = peasycap->pusb_device; + purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \ + peasycap->video_endpointnumber); + purb->transfer_flags = URB_ISO_ASAP; + purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo; + purb->transfer_buffer_length = \ + peasycap->video_isoc_buffer_size; + purb->complete = easycap_complete; + purb->context = peasycap; + purb->start_frame = 0; + purb->number_of_packets = peasycap->video_isoc_framesperdesc; + for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) { + purb->iso_frame_desc[j].offset = j * \ + peasycap->video_isoc_maxframesize; + purb->iso_frame_desc[j].length = \ + peasycap->video_isoc_maxframesize; + } + } + JOT(4, "allocation of %i struct urb done.\n", k); +/*--------------------------------------------------------------------------*/ +/* + * SAVE POINTER peasycap IN THIS INTERFACE. + */ +/*--------------------------------------------------------------------------*/ + usb_set_intfdata(pusb_interface, peasycap); +/*--------------------------------------------------------------------------*/ +/* + * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. + */ +/*--------------------------------------------------------------------------*/ +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) + if (0 != (usb_register_dev(pusb_interface, &easycap_class))) { + err("Not able to get a minor for this device"); + usb_set_intfdata(pusb_interface, NULL); + return -ENODEV; + } else + (peasycap->registered_video)++; + SAY("easycap attached to minor #%d\n", pusb_interface->minor); + break; +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#else + pvideo_device = (struct video_device *)\ + kzalloc(sizeof(struct video_device), GFP_KERNEL); + if ((struct video_device *)NULL == pvideo_device) { + SAY("ERROR: Could not allocate structure video_device\n"); + return -ENOMEM; + } + if (VIDEO_DEVICE_MANY <= video_device_many) { + SAY("ERROR: Too many /dev/videos\n"); + return -ENOMEM; + } + pvideo_array[video_device_many] = pvideo_device; video_device_many++; + + strcpy(&pvideo_device->name[0], "easycapdc60"); +#if defined(EASYCAP_NEEDS_V4L2_FOPS) + pvideo_device->fops = &v4l2_fops; +#else + pvideo_device->fops = &easycap_fops; +#endif /*EASYCAP_NEEDS_V4L2_FOPS*/ + pvideo_device->minor = -1; + pvideo_device->release = (void *)(&videodev_release); + + video_set_drvdata(pvideo_device, (void *)peasycap); + + rc = video_register_device(pvideo_device, VFL_TYPE_GRABBER, -1); + if (0 != rc) { + err("Not able to register with videodev"); + videodev_release(pvideo_device); + return -ENODEV; + } else { + peasycap->pvideo_device = pvideo_device; + (peasycap->registered_video)++; + JOT(4, "registered with videodev: %i=minor\n", \ + pvideo_device->minor); + } +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ + break; +} +/*--------------------------------------------------------------------------*/ +/* + * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE + * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE + */ +/*--------------------------------------------------------------------------*/ +case 1: { +/*--------------------------------------------------------------------------*/ +/* + * SAVE POINTER peasycap IN INTERFACE 1 + */ +/*--------------------------------------------------------------------------*/ + usb_set_intfdata(pusb_interface, peasycap); + JOT(4, "no initialization required for interface %i\n", \ + pusb_interface_descriptor->bInterfaceNumber); + break; +} +/*--------------------------------------------------------------------------*/ +case 2: { + if (!peasycap) { + SAY("MISTAKE: peasycap is NULL\n"); + return -EFAULT; + } + if (!isokalt) { + SAY("ERROR: no viable audio_altsetting_on\n"); + return -ENOENT; + } else { + peasycap->audio_altsetting_on = okalt[isokalt - 1]; + JOT(4, "%i=audio_altsetting_on <====\n", \ + peasycap->audio_altsetting_on); + } + if (!isokepn) { + SAY("ERROR: no viable audio_endpointnumber\n"); + return -ENOENT; + } else { + peasycap->audio_endpointnumber = okepn[isokepn - 1]; + JOT(4, "%i=audio_endpointnumber\n", \ + peasycap->audio_endpointnumber); + } + if (!isokmps) { + SAY("ERROR: no viable audio_maxpacketsize\n"); + return -ENOENT; + } else { + peasycap->audio_isoc_maxframesize = okmps[isokmps - 1]; + JOT(4, "%i=audio_isoc_maxframesize\n", \ + peasycap->audio_isoc_maxframesize); + if (0 >= peasycap->audio_isoc_maxframesize) { + SAY("ERROR: bad audio_isoc_maxframesize\n"); + return -ENOENT; + } + if (9 == peasycap->audio_isoc_maxframesize) { + peasycap->ilk |= 0x02; + SAY("hardware is FOUR-CVBS\n"); + peasycap->microphone = true; + audio_pages_per_fragment = 2; + } else if (256 == peasycap->audio_isoc_maxframesize) { + peasycap->ilk &= ~0x02; + SAY("hardware is CVBS+S-VIDEO\n"); + peasycap->microphone = false; + audio_pages_per_fragment = 4; + } else { + SAY("hardware is unidentified:\n"); + SAY("%i=audio_isoc_maxframesize\n", \ + peasycap->audio_isoc_maxframesize); + return -ENOENT; + } + + audio_bytes_per_fragment = audio_pages_per_fragment * \ + PAGE_SIZE ; + audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * \ + audio_pages_per_fragment); + + JOT(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY); + JOT(4, "%6i=audio_pages_per_fragment\n", \ + audio_pages_per_fragment); + JOT(4, "%6i=audio_bytes_per_fragment\n", \ + audio_bytes_per_fragment); + JOT(4, "%6i=audio_buffer_page_many\n", audio_buffer_page_many); + + peasycap->audio_isoc_framesperdesc = 128; + + JOT(4, "%i=audio_isoc_framesperdesc\n", \ + peasycap->audio_isoc_framesperdesc); + if (0 >= peasycap->audio_isoc_framesperdesc) { + SAY("ERROR: bad audio_isoc_framesperdesc\n"); + return -ENOENT; + } + + peasycap->audio_isoc_buffer_size = \ + peasycap->audio_isoc_maxframesize * \ + peasycap->audio_isoc_framesperdesc; + JOT(4, "%i=audio_isoc_buffer_size\n", \ + peasycap->audio_isoc_buffer_size); + if (AUDIO_ISOC_BUFFER_SIZE < \ + peasycap->audio_isoc_buffer_size) { + SAY("MISTAKE: audio_isoc_buffer_size bigger " + "than %li=AUDIO_ISOC_BUFFER_SIZE\n", \ + AUDIO_ISOC_BUFFER_SIZE); + return -EFAULT; + } + } + + if (-1 == peasycap->audio_interface) { + SAY("MISTAKE: audio_interface is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->audio_altsetting_on) { + SAY("MISTAKE: audio_altsetting_on is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->audio_altsetting_off) { + SAY("MISTAKE: audio_interface_off is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->audio_endpointnumber) { + SAY("MISTAKE: audio_endpointnumber is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->audio_isoc_maxframesize) { + SAY("MISTAKE: audio_isoc_maxframesize is unset\n"); + return -EFAULT; + } + if (-1 == peasycap->audio_isoc_buffer_size) { + SAY("MISTAKE: audio_isoc_buffer_size is unset\n"); + return -EFAULT; + } +/*---------------------------------------------------------------------------*/ +/* + * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST. + */ +/*---------------------------------------------------------------------------*/ + INIT_LIST_HEAD(&(peasycap->urb_audio_head)); + peasycap->purb_audio_head = &(peasycap->urb_audio_head); + + JOT(4, "allocating an audio buffer\n"); + JOT(4, ".... scattered over %i pages\n", audio_buffer_page_many); + + for (k = 0; k < audio_buffer_page_many; k++) { + if ((void *)NULL != peasycap->audio_buffer[k].pgo) { + SAY("ERROR: attempting to reallocate audio buffers\n"); + } else { + pbuf = (void *) __get_free_page(GFP_KERNEL); + if ((void *)NULL == pbuf) { + SAY("ERROR: Could not allocate audio " \ + "buffer page %i\n", k); + return -ENOMEM; + } else + peasycap->allocation_audio_page += 1; + + peasycap->audio_buffer[k].pgo = pbuf; + } + peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo; + } + + peasycap->audio_fill = 0; + peasycap->audio_read = 0; + JOT(4, "allocation of audio buffer done: %i pages\n", k); +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i isoc audio buffers of size %i\n", \ + AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size); + JOT(4, ".... each occupying contiguous memory pages\n"); + + for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { + pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER); + if (NULL == pbuf) { + SAY("ERROR: Could not allocate isoc audio buffer " \ + "%i\n", k); + return -ENOMEM; + } else + peasycap->allocation_audio_page += \ + ((unsigned int)(0x01 << AUDIO_ISOC_ORDER)); + + peasycap->audio_isoc_buffer[k].pgo = pbuf; + peasycap->audio_isoc_buffer[k].pto = pbuf + \ + peasycap->audio_isoc_buffer_size; + peasycap->audio_isoc_buffer[k].kount = k; + } + JOT(4, "allocation of isoc audio buffers done.\n"); +/*---------------------------------------------------------------------------*/ +/* + * ALLOCATE AND INITIALIZE MULTIPLE struct urb ... + */ +/*---------------------------------------------------------------------------*/ + JOT(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY); + JOT(4, "using %i=peasycap->audio_isoc_framesperdesc\n", \ + peasycap->audio_isoc_framesperdesc); + JOT(4, "using %i=peasycap->audio_isoc_maxframesize\n", \ + peasycap->audio_isoc_maxframesize); + JOT(4, "using %i=peasycap->audio_isoc_buffer_size\n", \ + peasycap->audio_isoc_buffer_size); + + for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { + purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, \ + GFP_KERNEL); + if (NULL == purb) { + SAY("ERROR: usb_alloc_urb returned NULL for buffer " \ + "%i\n", k); + return -ENOMEM; + } else + peasycap->allocation_audio_urb += 1 ; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); + if (NULL == pdata_urb) { + SAY("ERROR: Could not allocate struct data_urb.\n"); + return -ENOMEM; + } else + peasycap->allocation_audio_struct += \ + sizeof(struct data_urb); + + pdata_urb->purb = purb; + pdata_urb->isbuf = k; + pdata_urb->length = 0; + list_add_tail(&(pdata_urb->list_head), \ + peasycap->purb_audio_head); +/*---------------------------------------------------------------------------*/ +/* + * ... AND INITIALIZE THEM + */ +/*---------------------------------------------------------------------------*/ + if (!k) { + JOT(4, "initializing audio urbs thus:\n"); + JOT(4, " purb->interval = 1;\n"); + JOT(4, " purb->dev = peasycap->pusb_device;\n"); + JOT(4, " purb->pipe = usb_rcvisocpipe(peasycap->" \ + "pusb_device,%i);\n", \ + peasycap->audio_endpointnumber); + JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); + JOT(4, " purb->transfer_buffer = " \ + "peasycap->audio_isoc_buffer[.].pgo;\n"); + JOT(4, " purb->transfer_buffer_length = %i;\n", \ + peasycap->audio_isoc_buffer_size); + JOT(4, " purb->complete = easysnd_complete;\n"); + JOT(4, " purb->context = peasycap;\n"); + JOT(4, " purb->start_frame = 0;\n"); + JOT(4, " purb->number_of_packets = %i;\n", \ + peasycap->audio_isoc_framesperdesc); + JOT(4, " for (j = 0; j < %i; j++)\n", \ + peasycap->audio_isoc_framesperdesc); + JOT(4, " {\n"); + JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\ + peasycap->audio_isoc_maxframesize); + JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \ + peasycap->audio_isoc_maxframesize); + JOT(4, " }\n"); + } + + purb->interval = 1; + purb->dev = peasycap->pusb_device; + purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \ + peasycap->audio_endpointnumber); + purb->transfer_flags = URB_ISO_ASAP; + purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo; + purb->transfer_buffer_length = \ + peasycap->audio_isoc_buffer_size; + purb->complete = easysnd_complete; + purb->context = peasycap; + purb->start_frame = 0; + purb->number_of_packets = peasycap->audio_isoc_framesperdesc; + for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { + purb->iso_frame_desc[j].offset = j * \ + peasycap->audio_isoc_maxframesize; + purb->iso_frame_desc[j].length = \ + peasycap->audio_isoc_maxframesize; + } + } + JOT(4, "allocation of %i struct urb done.\n", k); +/*---------------------------------------------------------------------------*/ +/* + * SAVE POINTER peasycap IN THIS INTERFACE. + */ +/*---------------------------------------------------------------------------*/ + usb_set_intfdata(pusb_interface, peasycap); +/*---------------------------------------------------------------------------*/ +/* + * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. + */ +/*---------------------------------------------------------------------------*/ + rc = usb_register_dev(pusb_interface, &easysnd_class); + if (0 != rc) { + err("Not able to get a minor for this device."); + usb_set_intfdata(pusb_interface, NULL); + return -ENODEV; + } else + (peasycap->registered_audio)++; +/*---------------------------------------------------------------------------*/ +/* + * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO. + */ +/*---------------------------------------------------------------------------*/ + SAY("easysnd attached to minor #%d\n", pusb_interface->minor); + break; +} +/*---------------------------------------------------------------------------*/ +/* + * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED + */ +/*---------------------------------------------------------------------------*/ +default: { + JOT(4, "ERROR: unexpected interface %i\n", bInterfaceNumber); + return -EINVAL; +} +} +JOT(4, "ends successfully for interface %i\n", \ + pusb_interface_descriptor->bInterfaceNumber); +return 0; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * WHEN THIS FUNCTION IS CALLED THE DEVICE HAS ALREADY BEEN PHYSICALLY + * UNPLUGGED. + * HENCE peasycap->pusb_device IS NO LONGER VALID AND MUST BE SET TO NULL. + */ +/*---------------------------------------------------------------------------*/ +void +easycap_usb_disconnect(struct usb_interface *pusb_interface) +{ +struct usb_host_interface *pusb_host_interface; +struct usb_interface_descriptor *pusb_interface_descriptor; +__u8 bInterfaceNumber; +struct easycap *peasycap; + +struct list_head *plist_head; +struct data_urb *pdata_urb; +int minor, m; + +JOT(4, "\n"); + +if ((struct usb_interface *)NULL == pusb_interface) { + JOT(4, "ERROR: pusb_interface is NULL\n"); + return; +} +pusb_host_interface = pusb_interface->cur_altsetting; +if ((struct usb_host_interface *)NULL == pusb_host_interface) { + JOT(4, "ERROR: pusb_host_interface is NULL\n"); + return; +} +pusb_interface_descriptor = &(pusb_host_interface->desc); +if ((struct usb_interface_descriptor *)NULL == pusb_interface_descriptor) { + JOT(4, "ERROR: pusb_interface_descriptor is NULL\n"); + return; +} +bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber; +minor = pusb_interface->minor; +JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor); + +peasycap = usb_get_intfdata(pusb_interface); +if ((struct easycap *)NULL == peasycap) + SAY("ERROR: peasycap is NULL\n"); +else { + peasycap->pusb_device = (struct usb_device *)NULL; + switch (bInterfaceNumber) { +/*---------------------------------------------------------------------------*/ + case 0: { + if ((struct list_head *)NULL != peasycap->purb_video_head) { + JOT(4, "killing video urbs\n"); + m = 0; + list_for_each(plist_head, (peasycap->purb_video_head)) + { + pdata_urb = list_entry(plist_head, \ + struct data_urb, list_head); + if ((struct data_urb *)NULL != pdata_urb) { + if ((struct urb *)NULL != \ + pdata_urb->purb) { + usb_kill_urb(pdata_urb->purb); + m++; + } + } + } + JOT(4, "%i video urbs killed\n", m); + } else + SAY("ERROR: peasycap->purb_video_head is NULL\n"); + break; + } +/*---------------------------------------------------------------------------*/ + case 2: { + if ((struct list_head *)NULL != peasycap->purb_audio_head) { + JOT(4, "killing audio urbs\n"); + m = 0; + list_for_each(plist_head, \ + (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, \ + struct data_urb, list_head); + if ((struct data_urb *)NULL != pdata_urb) { + if ((struct urb *)NULL != \ + pdata_urb->purb) { + usb_kill_urb(pdata_urb->purb); + m++; + } + } + } + JOT(4, "%i audio urbs killed\n", m); + } else + SAY("ERROR: peasycap->purb_audio_head is NULL\n"); + break; + } +/*---------------------------------------------------------------------------*/ + default: + break; + } +} +/*--------------------------------------------------------------------------*/ +/* + * DEREGISTER + */ +/*--------------------------------------------------------------------------*/ +switch (bInterfaceNumber) { +case 0: { +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) + if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap has become NULL\n"); + } else { + lock_kernel(); + usb_deregister_dev(pusb_interface, &easycap_class); + (peasycap->registered_video)--; + + JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); + unlock_kernel(); + SAY("easycap detached from minor #%d\n", minor); + } +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#else + if ((struct easycap *)NULL == peasycap) + SAY("ERROR: peasycap has become NULL\n"); + else { + lock_kernel(); + video_unregister_device(peasycap->pvideo_device); + (peasycap->registered_video)--; + unlock_kernel(); + JOT(4, "unregistered with videodev: %i=minor\n", \ + pvideo_device->minor); + } +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ + break; +} +case 2: { + lock_kernel(); + + usb_deregister_dev(pusb_interface, &easysnd_class); + if ((struct easycap *)NULL != peasycap) + (peasycap->registered_audio)--; + + JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); + unlock_kernel(); + + SAY("easysnd detached from minor #%d\n", minor); + break; +} +default: + break; +} +/*---------------------------------------------------------------------------*/ +/* + * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap + */ +/*---------------------------------------------------------------------------*/ +if ((struct easycap *)NULL == peasycap) { + SAY("ERROR: peasycap has become NULL\n"); + SAY("cannot call kref_put()\n"); + SAY("ending unsuccessfully: may cause memory leak\n"); + return; +} +if (!peasycap->kref.refcount.counter) { + SAY("ERROR: peasycap->kref.refcount.counter is zero " \ + "so cannot call kref_put()\n"); + SAY("ending unsuccessfully: may cause memory leak\n"); + return; +} +JOT(4, "intf[%i]: kref_put() with %i=peasycap->kref.refcount.counter\n", \ + bInterfaceNumber, (int)peasycap->kref.refcount.counter); +kref_put(&peasycap->kref, easycap_delete); +JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); +/*---------------------------------------------------------------------------*/ + +JOT(4, "ends\n"); +return; +} +/*****************************************************************************/ +int __init +easycap_module_init(void) +{ +int result; + +SAY("========easycap=======\n"); +JOT(4, "begins. %i=debug\n", easycap_debug); +SAY("version: " EASYCAP_DRIVER_VERSION "\n"); +/*---------------------------------------------------------------------------*/ +/* + * REGISTER THIS DRIVER WITH THE USB SUBSYTEM. + */ +/*---------------------------------------------------------------------------*/ +JOT(4, "registering driver easycap\n"); + +result = usb_register(&easycap_usb_driver); +if (0 != result) + SAY("ERROR: usb_register returned %i\n", result); + +JOT(4, "ends\n"); +return result; +} +/*****************************************************************************/ +void __exit +easycap_module_exit(void) +{ +JOT(4, "begins\n"); + +/*---------------------------------------------------------------------------*/ +/* + * DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM. + */ +/*---------------------------------------------------------------------------*/ +usb_deregister(&easycap_usb_driver); + +JOT(4, "ends\n"); +} +/*****************************************************************************/ + +module_init(easycap_module_init); +module_exit(easycap_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("R.M. Thomas "); +MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); +MODULE_VERSION(EASYCAP_DRIVER_VERSION); +#if defined(EASYCAP_DEBUG) +MODULE_PARM_DESC(easycap_debug, "debug: 0 (default), 1, 2,..."); +#endif /*EASYCAP_DEBUG*/ +/*****************************************************************************/ diff --git a/drivers/staging/easycap/easycap_settings.c b/drivers/staging/easycap/easycap_settings.c new file mode 100644 index 000000000000..1e4eb23885e3 --- /dev/null +++ b/drivers/staging/easycap/easycap_settings.c @@ -0,0 +1,489 @@ +/****************************************************************************** +* * +* easycap_settings.c * +* * +******************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ + +#include "easycap.h" +#include "easycap_debug.h" + +/*---------------------------------------------------------------------------*/ +/* + * THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING: + * 0 => 25 fps + * 1 => 30 fps + */ +/*---------------------------------------------------------------------------*/ +struct easycap_standard easycap_standard[] = { +{ +.mask = 0x000F & PAL_BGHIN , +.v4l2_standard = { + .index = PAL_BGHIN, + .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \ + V4L2_STD_PAL_I | V4L2_STD_PAL_N), + .name = "PAL_BGHIN", + .frameperiod = {1, 25}, + .framelines = 625, + .reserved = {0, 0, 0, 0} + } +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & NTSC_N_443 , +.v4l2_standard = { + .index = NTSC_N_443, + .id = V4L2_STD_UNKNOWN, + .name = "NTSC_N_443", + .frameperiod = {1, 25}, + .framelines = 480, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & PAL_Nc , +.v4l2_standard = { + .index = PAL_Nc, + .id = V4L2_STD_PAL_Nc, + .name = "PAL_Nc", + .frameperiod = {1, 25}, + .framelines = 625, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & NTSC_N , +.v4l2_standard = { + .index = NTSC_N, + .id = V4L2_STD_UNKNOWN, + .name = "NTSC_N", + .frameperiod = {1, 25}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & SECAM , +.v4l2_standard = { + .index = SECAM, + .id = V4L2_STD_SECAM, + .name = "SECAM", + .frameperiod = {1, 25}, + .framelines = 625, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & NTSC_M , +.v4l2_standard = { + .index = NTSC_M, + .id = V4L2_STD_NTSC_M, + .name = "NTSC_M", + .frameperiod = {1, 30}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & NTSC_M_JP , +.v4l2_standard = { + .index = NTSC_M_JP, + .id = V4L2_STD_NTSC_M_JP, + .name = "NTSC_M_JP", + .frameperiod = {1, 30}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & PAL_60 , +.v4l2_standard = { + .index = PAL_60, + .id = V4L2_STD_PAL_60, + .name = "PAL_60", + .frameperiod = {1, 30}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & NTSC_443 , +.v4l2_standard = { + .index = NTSC_443, + .id = V4L2_STD_NTSC_443, + .name = "NTSC_443", + .frameperiod = {1, 30}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0x000F & PAL_M , +.v4l2_standard = { + .index = PAL_M, + .id = V4L2_STD_PAL_M, + .name = "PAL_M", + .frameperiod = {1, 30}, + .framelines = 525, + .reserved = {0, 0, 0, 0} +} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.mask = 0xFFFF +} +}; +/*---------------------------------------------------------------------------*/ +/* + * THE 16-BIT easycap_format.mask HAS MEANING: + * (least significant) BIT 0: 0 => PAL, 25 FPS; 1 => NTSC, 30 FPS + * BITS 1-3: RESERVED FOR DIFFERENTIATING STANDARDS + * BITS 4-7: NUMBER OF BYTES PER PIXEL + * BIT 8: 0 => NATIVE BYTE ORDER; 1 => SWAPPED + * BITS 9-10: RESERVED FOR OTHER BYTE PERMUTATIONS + * BIT 11: 0 => UNDECIMATED; 1 => DECIMATED + * BIT 12: 0 => OFFER FRAMES; 1 => OFFER FIELDS + * (most significant) BITS 13-15: RESERVED FOR OTHER FIELD ORDER OPTIONS + * IT FOLLOWS THAT: + * bytesperpixel IS ((0x00F0 & easycap_format.mask) >> 4) + * byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask)) + * + * decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask)) + * + * offerfields IS true IF (0 != (0x1000 & easycap_format.mask)) + */ +/*---------------------------------------------------------------------------*/ + +struct easycap_format easycap_format[1 + SETTINGS_MANY]; + +int +fillin_formats(void) +{ +int i, j, k, m, n; +__u32 width, height, pixelformat, bytesperline, sizeimage; +__u32 field, colorspace; +__u16 mask1, mask2, mask3, mask4; +char name1[32], name2[32], name3[32], name4[32]; + +for (i = 0, n = 0; i < STANDARD_MANY; i++) { + mask1 = 0x0000; + switch (i) { + case PAL_BGHIN: { + mask1 = PAL_BGHIN; + strcpy(&name1[0], "PAL_BGHIN"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case SECAM: { + mask1 = SECAM; + strcpy(&name1[0], "SECAM"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case PAL_Nc: { + mask1 = PAL_Nc; + strcpy(&name1[0], "PAL_Nc"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case PAL_60: { + mask1 = PAL_60; + strcpy(&name1[0], "PAL_60"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case PAL_M: { + mask1 = PAL_M; + strcpy(&name1[0], "PAL_M"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case NTSC_M: { + mask1 = NTSC_M; + strcpy(&name1[0], "NTSC_M"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + } + case NTSC_443: { + mask1 = NTSC_443; + strcpy(&name1[0], "NTSC_443"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + } + case NTSC_M_JP: { + mask1 = NTSC_M_JP; + strcpy(&name1[0], "NTSC_M_JP"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + } + case NTSC_N: { + mask1 = NTSC_M; + strcpy(&name1[0], "NTSC_N"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + } + case NTSC_N_443: { + mask1 = NTSC_N_443; + strcpy(&name1[0], "NTSC_N_443"); + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; + break; + } + default: + return -1; + } + + for (j = 0; j < RESOLUTION_MANY; j++) { + mask2 = 0x0000; + switch (j) { + case AT_720x576: { + if (0x1 & mask1) + continue; + strcpy(&name2[0], "_AT_720x576"); + width = 720; height = 576; break; + } + case AT_704x576: { + if (0x1 & mask1) + continue; + strcpy(&name2[0], "_AT_704x576"); + width = 704; height = 576; break; + } + case AT_640x480: { + strcpy(&name2[0], "_AT_640x480"); + width = 640; height = 480; break; + } + case AT_720x480: { + if (!(0x1 & mask1)) + continue; + strcpy(&name2[0], "_AT_720x480"); + width = 720; height = 480; break; + } + case AT_360x288: { + if (0x1 & mask1) + continue; + strcpy(&name2[0], "_AT_360x288"); + width = 360; height = 288; mask2 = 0x0800; break; + } + case AT_320x240: { + strcpy(&name2[0], "_AT_320x240"); + width = 320; height = 240; mask2 = 0x0800; break; + } + case AT_360x240: { + if (!(0x1 & mask1)) + continue; + strcpy(&name2[0], "_AT_360x240"); + width = 360; height = 240; mask2 = 0x0800; break; + } + default: + return -2; + } + + for (k = 0; k < PIXELFORMAT_MANY; k++) { + mask3 = 0x0000; + switch (k) { + case FMT_UYVY: { + strcpy(&name3[0], "_" STRINGIZE(FMT_UYVY)); + pixelformat = V4L2_PIX_FMT_UYVY; + mask3 |= (0x02 << 4); + break; + } + case FMT_YUY2: { + strcpy(&name3[0], "_" STRINGIZE(FMT_YUY2)); + pixelformat = V4L2_PIX_FMT_YUYV; + mask3 |= (0x02 << 4); + mask3 |= 0x0100; + break; + } + case FMT_RGB24: { + strcpy(&name3[0], "_" STRINGIZE(FMT_RGB24)); + pixelformat = V4L2_PIX_FMT_RGB24; + mask3 |= (0x03 << 4); + break; + } + case FMT_RGB32: { + strcpy(&name3[0], "_" STRINGIZE(FMT_RGB32)); + pixelformat = V4L2_PIX_FMT_RGB32; + mask3 |= (0x04 << 4); + break; + } + case FMT_BGR24: { + strcpy(&name3[0], "_" STRINGIZE(FMT_BGR24)); + pixelformat = V4L2_PIX_FMT_BGR24; + mask3 |= (0x03 << 4); + mask3 |= 0x0100; + break; + } + case FMT_BGR32: { + strcpy(&name3[0], "_" STRINGIZE(FMT_BGR32)); + pixelformat = V4L2_PIX_FMT_BGR32; + mask3 |= (0x04 << 4); + mask3 |= 0x0100; + break; + } + default: + return -3; + } + bytesperline = width * ((mask3 & 0x00F0) >> 4); + sizeimage = bytesperline * height; + + for (m = 0; m < INTERLACE_MANY; m++) { + mask4 = 0x0000; + switch (m) { + case FIELD_NONE: { + strcpy(&name4[0], "-n"); + field = V4L2_FIELD_NONE; + break; + } + case FIELD_INTERLACED: { + strcpy(&name4[0], "-i"); + field = V4L2_FIELD_INTERLACED; + break; + } + case FIELD_ALTERNATE: { + strcpy(&name4[0], "-a"); + mask4 |= 0x1000; + field = V4L2_FIELD_ALTERNATE; + break; + } + default: + return -4; + } + if (SETTINGS_MANY <= n) + return -5; + strcpy(&easycap_format[n].name[0], &name1[0]); + strcat(&easycap_format[n].name[0], &name2[0]); + strcat(&easycap_format[n].name[0], &name3[0]); + strcat(&easycap_format[n].name[0], &name4[0]); + easycap_format[n].mask = \ + mask1 | mask2 | mask3 | mask4; + easycap_format[n].v4l2_format\ + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + easycap_format[n].v4l2_format\ + .fmt.pix.width = width; + easycap_format[n].v4l2_format\ + .fmt.pix.height = height; + easycap_format[n].v4l2_format\ + .fmt.pix.pixelformat = pixelformat; + easycap_format[n].v4l2_format\ + .fmt.pix.field = field; + easycap_format[n].v4l2_format\ + .fmt.pix.bytesperline = bytesperline; + easycap_format[n].v4l2_format\ + .fmt.pix.sizeimage = sizeimage; + easycap_format[n].v4l2_format\ + .fmt.pix.colorspace = colorspace; + easycap_format[n].v4l2_format\ + .fmt.pix.priv = 0; + n++; + } + } + } +} +if ((1 + SETTINGS_MANY) <= n) + return -6; +easycap_format[n].mask = 0xFFFF; +return n; +} +/*---------------------------------------------------------------------------*/ +struct v4l2_queryctrl easycap_control[] = \ + {{ +.id = V4L2_CID_BRIGHTNESS, +.type = V4L2_CTRL_TYPE_INTEGER, +.name = "Brightness", +.minimum = 0, +.maximum = 255, +.step = 1, +.default_value = SAA_0A_DEFAULT, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = V4L2_CID_CONTRAST, +.type = V4L2_CTRL_TYPE_INTEGER, +.name = "Contrast", +.minimum = 0, +.maximum = 255, +.step = 1, +.default_value = SAA_0B_DEFAULT + 128, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = V4L2_CID_SATURATION, +.type = V4L2_CTRL_TYPE_INTEGER, +.name = "Saturation", +.minimum = 0, +.maximum = 255, +.step = 1, +.default_value = SAA_0C_DEFAULT + 128, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = V4L2_CID_HUE, +.type = V4L2_CTRL_TYPE_INTEGER, +.name = "Hue", +.minimum = 0, +.maximum = 255, +.step = 1, +.default_value = SAA_0D_DEFAULT + 128, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = V4L2_CID_AUDIO_VOLUME, +.type = V4L2_CTRL_TYPE_INTEGER, +.name = "Volume", +.minimum = 0, +.maximum = 31, +.step = 1, +.default_value = 16, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = V4L2_CID_AUDIO_MUTE, +.type = V4L2_CTRL_TYPE_BOOLEAN, +.name = "Mute", +.default_value = true, +.flags = 0, +.reserved = {0, 0} +}, +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +{ +.id = 0xFFFFFFFF +} + }; +/*****************************************************************************/ diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c new file mode 100644 index 000000000000..532c4105738a --- /dev/null +++ b/drivers/staging/easycap/easycap_sound.c @@ -0,0 +1,973 @@ +/****************************************************************************** +* * +* easycap_sound.c * +* * +* Audio driver for EasyCAP USB2.0 Video Capture Device DC60 * +* * +* * +******************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ + +#include "easycap.h" +#include "easycap_debug.h" +#include "easycap_sound.h" + +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS + * PROVIDED peasycap->audio_idle IS ZER0. REGARDLESS OF THIS BEING TRUE, + * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO. + */ +/*---------------------------------------------------------------------------*/ +void +easysnd_complete(struct urb *purb) +{ +static int mt; +struct easycap *peasycap; +struct data_buffer *paudio_buffer; +char errbuf[16]; +__u8 *p1, *p2; +__s16 s16; +int i, j, more, much, leap, rc; + +JOT(16, "\n"); + +if (NULL == purb) { + SAY("ERROR: purb is NULL\n"); + return; +} +peasycap = purb->context; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return; +} +much = 0; + + +if (peasycap->audio_idle) { + JOT(16, "%i=audio_idle %i=audio_isoc_streaming\n", \ + peasycap->audio_idle, peasycap->audio_isoc_streaming); + if (peasycap->audio_isoc_streaming) { + rc = usb_submit_urb(purb, GFP_ATOMIC); + if (0 != rc) { + SAY("ERROR: while %i=audio_idle, " \ + "usb_submit_urb() failed with rc:\n", \ + peasycap->audio_idle); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); break; + } + case -ENODEV: { + SAY("ENODEV\n"); break; + } + case -ENXIO: { + SAY("ENXIO\n"); break; + } + case -EINVAL: { + SAY("EINVAL\n"); break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); break; + } + case -EFBIG: { + SAY("EFBIG\n"); break; + } + case -EPIPE: { + SAY("EPIPE\n"); break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); break; + } + default: { + SAY("0x%08X\n", rc); break; + } + } + } + } +return; +} +/*---------------------------------------------------------------------------*/ +if (purb->status) { + if (-ESHUTDOWN == purb->status) { + JOT(16, "immediate return because -ESHUTDOWN=purb->status\n"); + return; + } + SAY("ERROR: non-zero urb status:\n"); + switch (purb->status) { + case -EINPROGRESS: { + SAY("-EINPROGRESS\n"); break; + } + case -ENOSR: { + SAY("-ENOSR\n"); break; + } + case -EPIPE: { + SAY("-EPIPE\n"); break; + } + case -EOVERFLOW: { + SAY("-EOVERFLOW\n"); break; + } + case -EPROTO: { + SAY("-EPROTO\n"); break; + } + case -EILSEQ: { + SAY("-EILSEQ\n"); break; + } + case -ETIMEDOUT: { + SAY("-ETIMEDOUT\n"); break; + } + case -EMSGSIZE: { + SAY("-EMSGSIZE\n"); break; + } + case -EOPNOTSUPP: { + SAY("-EOPNOTSUPP\n"); break; + } + case -EPFNOSUPPORT: { + SAY("-EPFNOSUPPORT\n"); break; + } + case -EAFNOSUPPORT: { + SAY("-EAFNOSUPPORT\n"); break; + } + case -EADDRINUSE: { + SAY("-EADDRINUSE\n"); break; + } + case -EADDRNOTAVAIL: { + SAY("-EADDRNOTAVAIL\n"); break; + } + case -ENOBUFS: { + SAY("-ENOBUFS\n"); break; + } + case -EISCONN: { + SAY("-EISCONN\n"); break; + } + case -ENOTCONN: { + SAY("-ENOTCONN\n"); break; + } + case -ESHUTDOWN: { + SAY("-ESHUTDOWN\n"); break; + } + case -ENOENT: { + SAY("-ENOENT\n"); break; + } + case -ECONNRESET: { + SAY("-ECONNRESET\n"); break; + } + default: { + SAY("unknown error code 0x%08X\n", purb->status); break; + } + } +/*---------------------------------------------------------------------------*/ +/* + * RESUBMIT THIS URB AFTER AN ERROR + * + * (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH) + */ +/*---------------------------------------------------------------------------*/ + if (peasycap->audio_isoc_streaming) { + rc = usb_submit_urb(purb, GFP_ATOMIC); + if (0 != rc) { + SAY("ERROR: while %i=audio_idle, usb_submit_urb() " + "failed with rc:\n", peasycap->audio_idle); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); break; + } + case -ENODEV: { + SAY("ENODEV\n"); break; + } + case -ENXIO: { + SAY("ENXIO\n"); break; + } + case -EINVAL: { + SAY("EINVAL\n"); break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); break; + } + case -EFBIG: { + SAY("EFBIG\n"); break; + } + case -EPIPE: { + SAY("EPIPE\n"); break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); break; + } + default: { + SAY("0x%08X\n", rc); break; + } + } + } + } + return; +} +/*---------------------------------------------------------------------------*/ +/* + * PROCEED HERE WHEN NO ERROR + */ +/*---------------------------------------------------------------------------*/ +for (i = 0; i < purb->number_of_packets; i++) { + switch (purb->iso_frame_desc[i].status) { + case 0: { + strcpy(&errbuf[0], "OK"); break; + } + case -ENOENT: { + strcpy(&errbuf[0], "-ENOENT"); break; + } + case -EINPROGRESS: { + strcpy(&errbuf[0], "-EINPROGRESS"); break; + } + case -EPROTO: { + strcpy(&errbuf[0], "-EPROTO"); break; + } + case -EILSEQ: { + strcpy(&errbuf[0], "-EILSEQ"); break; + } + case -ETIME: { + strcpy(&errbuf[0], "-ETIME"); break; + } + case -ETIMEDOUT: { + strcpy(&errbuf[0], "-ETIMEDOUT"); break; + } + case -EPIPE: { + strcpy(&errbuf[0], "-EPIPE"); break; + } + case -ECOMM: { + strcpy(&errbuf[0], "-ECOMM"); break; + } + case -ENOSR: { + strcpy(&errbuf[0], "-ENOSR"); break; + } + case -EOVERFLOW: { + strcpy(&errbuf[0], "-EOVERFLOW"); break; + } + case -EREMOTEIO: { + strcpy(&errbuf[0], "-EREMOTEIO"); break; + } + case -ENODEV: { + strcpy(&errbuf[0], "-ENODEV"); break; + } + case -EXDEV: { + strcpy(&errbuf[0], "-EXDEV"); break; + } + case -EINVAL: { + strcpy(&errbuf[0], "-EINVAL"); break; + } + case -ECONNRESET: { + strcpy(&errbuf[0], "-ECONNRESET"); break; + } + case -ESHUTDOWN: { + strcpy(&errbuf[0], "-ESHUTDOWN"); break; + } + default: { + strcpy(&errbuf[0], "UNKNOWN"); break; + } + } + if ((!purb->iso_frame_desc[i].status) && 0) { + JOT(16, "frame[%2i]: %i=status{=%16s} " \ + "%5i=actual " \ + "%5i=length " \ + "%3i=offset\n", \ + i, purb->iso_frame_desc[i].status, &errbuf[0], + purb->iso_frame_desc[i].actual_length, + purb->iso_frame_desc[i].length, + purb->iso_frame_desc[i].offset); + } + if (!purb->iso_frame_desc[i].status) { + more = purb->iso_frame_desc[i].actual_length; + +#if defined(TESTTONE) + if (!more) + more = purb->iso_frame_desc[i].length; +#endif + + if (!more) + mt++; + else { + if (mt) { + JOT(16, "%4i empty audio urb frames\n", mt); + mt = 0; + } + + p1 = (__u8 *)(purb->transfer_buffer + \ + purb->iso_frame_desc[i].offset); + + leap = 0; + p1 += leap; + more -= leap; +/*---------------------------------------------------------------------------*/ +/* + * COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER, + * CONVERTING 8-BIT SAMPLES TO 16-BIT SIGNED LITTLE-ENDED SAMPLES IF NECESSARY + */ +/*---------------------------------------------------------------------------*/ + while (more) { + if (0 > more) { + SAY("easysnd_complete: MISTAKE: " \ + "more is negative\n"); + return; + } + if (audio_buffer_page_many <= \ + peasycap->audio_fill) { + SAY("ERROR: bad " \ + "peasycap->audio_fill\n"); + return; + } + + paudio_buffer = &peasycap->audio_buffer\ + [peasycap->audio_fill]; + if (PAGE_SIZE < (paudio_buffer->pto - \ + paudio_buffer->pgo)) { + SAY("ERROR: bad paudio_buffer->pto\n"); + return; + } + if (PAGE_SIZE == (paudio_buffer->pto - \ + paudio_buffer->pgo)) { + +#if defined(TESTTONE) + easysnd_testtone(peasycap, \ + peasycap->audio_fill); +#endif /*TESTTONE*/ + + paudio_buffer->pto = \ + paudio_buffer->pgo; + (peasycap->audio_fill)++; + if (audio_buffer_page_many <= \ + peasycap->audio_fill) + peasycap->audio_fill = 0; + + JOT(12, "bumped peasycap->" \ + "audio_fill to %i\n", \ + peasycap->audio_fill); + + paudio_buffer = &peasycap->\ + audio_buffer\ + [peasycap->audio_fill]; + paudio_buffer->pto = \ + paudio_buffer->pgo; + + if (!(peasycap->audio_fill % \ + audio_pages_per_fragment)) { + JOT(12, "wakeup call on wq_" \ + "audio, %i=frag reading %i" \ + "=fragment fill\n", \ + (peasycap->audio_read / \ + audio_pages_per_fragment), \ + (peasycap->audio_fill / \ + audio_pages_per_fragment)); + wake_up_interruptible\ + (&(peasycap->wq_audio)); + } + } + + much = PAGE_SIZE - (int)(paudio_buffer->pto -\ + paudio_buffer->pgo); + if (much % 2) + JOT(8, "MISTAKE? much is odd\n"); + + if (false == peasycap->microphone) { + if (much > more) + much = more; + + memcpy(paudio_buffer->pto, p1, much); + p1 += much; + more -= much; + } else { + if (much > (2 * more)) + much = 2 * more; + p2 = (__u8 *)paudio_buffer->pto; + + for (j = 0; j < (much / 2); j++) { + s16 = ((int) *p1) - 128; + *p2 = (0xFF00 & s16) >> 8; + *(p2 + 1) = (0x00FF & s16); + p1++; p2 += 2; + more--; + } + } + (paudio_buffer->pto) += much; + } + } + } else { + JOT(12, "discarding audio samples because " \ + "%i=purb->iso_frame_desc[i].status\n", \ + purb->iso_frame_desc[i].status); + } +} +/*---------------------------------------------------------------------------*/ +/* + * RESUBMIT THIS URB AFTER NO ERROR + */ +/*---------------------------------------------------------------------------*/ +if (peasycap->audio_isoc_streaming) { + rc = usb_submit_urb(purb, GFP_ATOMIC); + if (0 != rc) { + SAY("ERROR: while %i=audio_idle, usb_submit_urb() failed " \ + "with rc:\n", peasycap->audio_idle); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); break; + } + case -ENODEV: { + SAY("ENODEV\n"); break; + } + case -ENXIO: { + SAY("ENXIO\n"); break; + } + case -EINVAL: { + SAY("EINVAL\n"); break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); break; + } + case -EFBIG: { + SAY("EFBIG\n"); break; + } + case -EPIPE: { + SAY("EPIPE\n"); break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); break; + } + default: { + SAY("0x%08X\n", rc); break; + } + } + } +} +return; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO + * STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT + * HAVE AN IOCTL INTERFACE. THE VIDEO URBS, BY CONTRAST, MUST BE SUBMITTED + * MUCH LATER: SEE COMMENTS IN FILE easycap_main.c. + */ +/*---------------------------------------------------------------------------*/ +int +easysnd_open(struct inode *inode, struct file *file) +{ +struct usb_interface *pusb_interface; +struct easycap *peasycap; +int subminor, rc; + +JOT(4, "begins.\n"); + +subminor = iminor(inode); + +pusb_interface = usb_find_interface(&easycap_usb_driver, subminor); +if (NULL == pusb_interface) { + SAY("ERROR: pusb_interface is NULL\n"); + SAY("ending unsuccessfully\n"); + return -1; +} +peasycap = usb_get_intfdata(pusb_interface); +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + SAY("ending unsuccessfully\n"); + return -1; +} + +file->private_data = peasycap; + +/*---------------------------------------------------------------------------*/ +/* + * INITIALIZATION. + */ +/*---------------------------------------------------------------------------*/ +JOT(4, "starting initialization\n"); + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} else { + JOT(16, "0x%08lX=peasycap->pusb_device\n", \ + (long int)peasycap->pusb_device); +} + +rc = audio_setup(peasycap); +if (0 <= rc) + JOT(8, "audio_setup() returned %i\n", rc); +else + JOT(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc); + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device has become NULL\n"); + return -EFAULT; +} +rc = adjust_volume(peasycap, -8192); +if (0 != rc) { + SAY("ERROR: adjust_volume(default) returned %i\n", rc); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device has become NULL\n"); + return -EFAULT; +} +rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ + peasycap->audio_altsetting_on); +JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \ + peasycap->audio_altsetting_on, rc); + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device has become NULL\n"); + return -EFAULT; +} +rc = wakeup_device(peasycap->pusb_device); +if (0 == rc) + JOT(8, "wakeup_device() returned %i\n", rc); +else + JOT(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc); + +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device has become NULL\n"); + return -EFAULT; +} +submit_audio_urbs(peasycap); +peasycap->audio_idle = 0; + +peasycap->timeval1.tv_sec = 0; +peasycap->timeval1.tv_usec = 0; + +JOT(4, "finished initialization\n"); +return 0; +} +/*****************************************************************************/ +int +easysnd_release(struct inode *inode, struct file *file) +{ +struct easycap *peasycap; + +JOT(4, "begins\n"); + +peasycap = (struct easycap *)file->private_data; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL.\n"); + return -EFAULT; +} +if (0 != kill_audio_urbs(peasycap)) { + SAY("ERROR: kill_audio_urbs() failed\n"); + return -EFAULT; +} +JOT(4, "ending successfully\n"); +return 0; +} +/*****************************************************************************/ +ssize_t +easysnd_read(struct file *file, char __user *puserspacebuffer, \ + size_t kount, loff_t *poff) +{ +struct timeval timeval; +static struct timeval timeval1; +static long long int audio_bytes, above, below, mean; +struct signed_div_result sdr; +unsigned char *p0; +long int kount1, more, rc, l0, lm; +int fragment; +struct easycap *peasycap; +struct data_buffer *pdata_buffer; +size_t szret; + +/*---------------------------------------------------------------------------*/ +/* + * DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE. + * + ****************************************************************************** + ***** N.B. IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ****** + ***** THIS CONDITION SIGNIFIES END-OF-FILE. ****** + ****************************************************************************** + */ +/*---------------------------------------------------------------------------*/ + +JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); + +peasycap = (struct easycap *)(file->private_data); +if (NULL == peasycap) { + SAY("ERROR in easysnd_read(): peasycap is NULL\n"); + return -EFAULT; +} +/*---------------------------------------------------------------------------*/ +if ((0 > peasycap->audio_read) || \ + (audio_buffer_page_many <= peasycap->audio_read)) { + SAY("ERROR: peasycap->audio_read out of range\n"); + return -EFAULT; +} +pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; +if ((struct data_buffer *)NULL == pdata_buffer) { + SAY("ERROR: pdata_buffer is NULL\n"); + return -EFAULT; +} +JOT(12, "before wait, %i=frag read %i=frag fill\n", \ + (peasycap->audio_read / audio_pages_per_fragment), \ + (peasycap->audio_fill / audio_pages_per_fragment)); +fragment = (peasycap->audio_read / audio_pages_per_fragment); +while ((fragment == (peasycap->audio_fill / audio_pages_per_fragment)) || \ + (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) { + if (file->f_flags & O_NONBLOCK) { + JOT(16, "returning -EAGAIN as instructed\n"); + return -EAGAIN; + } + rc = wait_event_interruptible(peasycap->wq_audio, \ + (peasycap->audio_idle || peasycap->audio_eof || \ + ((fragment != (peasycap->audio_fill / \ + audio_pages_per_fragment)) && \ + (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))))); + if (0 != rc) { + SAY("aborted by signal\n"); + return -ERESTARTSYS; + } + if (peasycap->audio_eof) { + JOT(8, "returning 0 because %i=audio_eof\n", \ + peasycap->audio_eof); + kill_audio_urbs(peasycap); + msleep(500); + return 0; + } + if (peasycap->audio_idle) { + JOT(16, "returning 0 because %i=audio_idle\n", \ + peasycap->audio_idle); + return 0; + } + if (!peasycap->audio_isoc_streaming) { + JOT(16, "returning 0 because audio urbs not streaming\n"); + return 0; + } +} +JOT(12, "after wait, %i=frag read %i=frag fill\n", \ + (peasycap->audio_read / audio_pages_per_fragment), \ + (peasycap->audio_fill / audio_pages_per_fragment)); +szret = (size_t)0; +while (fragment == (peasycap->audio_read / audio_pages_per_fragment)) { + if (NULL == pdata_buffer->pgo) { + SAY("ERROR: pdata_buffer->pgo is NULL\n"); + return -EFAULT; + } + if (NULL == pdata_buffer->pto) { + SAY("ERROR: pdata_buffer->pto is NULL\n"); + return -EFAULT; + } + kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); + if (0 > kount1) { + SAY("easysnd_read: MISTAKE: kount1 is negative\n"); + return -ERESTARTSYS; + } + if (!kount1) { + (peasycap->audio_read)++; + if (audio_buffer_page_many <= peasycap->audio_read) + peasycap->audio_read = 0; + JOT(12, "bumped peasycap->audio_read to %i\n", \ + peasycap->audio_read); + + if (fragment != (peasycap->audio_read / \ + audio_pages_per_fragment)) + break; + + if ((0 > peasycap->audio_read) || \ + (audio_buffer_page_many <= peasycap->audio_read)) { + SAY("ERROR: peasycap->audio_read out of range\n"); + return -EFAULT; + } + pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; + if ((struct data_buffer *)NULL == pdata_buffer) { + SAY("ERROR: pdata_buffer is NULL\n"); + return -EFAULT; + } + if (NULL == pdata_buffer->pgo) { + SAY("ERROR: pdata_buffer->pgo is NULL\n"); + return -EFAULT; + } + if (NULL == pdata_buffer->pto) { + SAY("ERROR: pdata_buffer->pto is NULL\n"); + return -EFAULT; + } + kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); + } + JOT(12, "ready to send %li bytes\n", (long int) kount1); + JOT(12, "still to send %li bytes\n", (long int) kount); + more = kount1; + if (more > kount) + more = kount; + JOT(12, "agreed to send %li bytes from page %i\n", \ + more, peasycap->audio_read); + if (!more) + break; + +/*---------------------------------------------------------------------------*/ +/* + * ACCUMULATE DYNAMIC-RANGE INFORMATION + */ +/*---------------------------------------------------------------------------*/ + p0 = (unsigned char *)pdata_buffer->pgo; l0 = 0; lm = more/2; + while (l0 < lm) { + SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \ + &peasycap->audio_square); l0++; p0 += 2; + } +/*---------------------------------------------------------------------------*/ + rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more); + if (0 != rc) { + SAY("ERROR: copy_to_user() returned %li\n", rc); + return -EFAULT; + } + *poff += (loff_t)more; + szret += (size_t)more; + pdata_buffer->pto += more; + puserspacebuffer += more; + kount -= (size_t)more; +} +JOT(12, "after read, %i=frag read %i=frag fill\n", \ + (peasycap->audio_read / audio_pages_per_fragment), \ + (peasycap->audio_fill / audio_pages_per_fragment)); +if (kount < 0) { + SAY("MISTAKE: %li=kount %li=szret\n", \ + (long int)kount, (long int)szret); +} +/*---------------------------------------------------------------------------*/ +/* + * CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL + */ +/*---------------------------------------------------------------------------*/ +if (peasycap->audio_sample) { + below = peasycap->audio_sample; + above = peasycap->audio_square; + sdr = signed_div(above, below); + above = sdr.quotient; + mean = peasycap->audio_niveau; + sdr = signed_div(mean, peasycap->audio_sample); + + JOT(12, "%8lli=mean %8lli=meansquare after %lli samples, =>\n", \ + sdr.quotient, above, peasycap->audio_sample); + + sdr = signed_div(above, 32768); + JOT(8, "audio dynamic range is roughly %lli\n", sdr.quotient); +} +/*---------------------------------------------------------------------------*/ +/* + * UPDATE THE AUDIO CLOCK + */ +/*---------------------------------------------------------------------------*/ +do_gettimeofday(&timeval); +if (!peasycap->timeval1.tv_sec) { + audio_bytes = 0; + timeval1 = timeval; + + if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) + return -ERESTARTSYS; + peasycap->timeval1 = timeval1; + mutex_unlock(&(peasycap->mutex_timeval1)); + sdr.quotient = 192000; +} else { + audio_bytes += (long long int) szret; + below = ((long long int)(1000000)) * \ + ((long long int)(timeval.tv_sec - timeval1.tv_sec)) + \ + (long long int)(timeval.tv_usec - timeval1.tv_usec); + above = 1000000 * ((long long int) audio_bytes); + + if (below) + sdr = signed_div(above, below); + else + sdr.quotient = 192000; +} +JOT(8, "audio streaming at %lli bytes/second\n", sdr.quotient); +if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) + return -ERESTARTSYS; +peasycap->dnbydt = sdr.quotient; +mutex_unlock(&(peasycap->mutex_timeval1)); + +JOT(8, "returning %li\n", (long int)szret); +return szret; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * SUBMIT ALL AUDIO URBS. + */ +/*---------------------------------------------------------------------------*/ +int +submit_audio_urbs(struct easycap *peasycap) +{ +struct data_urb *pdata_urb; +struct urb *purb; +struct list_head *plist_head; +int j, isbad, m, rc; +int isbuf; + +if ((struct list_head *)NULL == peasycap->purb_audio_head) { + SAY("ERROR: peasycap->urb_audio_head uninitialized\n"); + return -EFAULT; +} +if ((struct usb_device *)NULL == peasycap->pusb_device) { + SAY("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; +} +if (!peasycap->audio_isoc_streaming) { + JOT(4, "initial submission of all audio urbs\n"); + rc = usb_set_interface(peasycap->pusb_device, + peasycap->audio_interface, \ + peasycap->audio_altsetting_on); + JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", \ + peasycap->audio_interface, \ + peasycap->audio_altsetting_on, rc); + + isbad = 0; m = 0; + list_for_each(plist_head, (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (NULL != pdata_urb) { + purb = pdata_urb->purb; + if (NULL != purb) { + isbuf = pdata_urb->isbuf; + + purb->interval = 1; + purb->dev = peasycap->pusb_device; + purb->pipe = \ + usb_rcvisocpipe(peasycap->pusb_device,\ + peasycap->audio_endpointnumber); + purb->transfer_flags = URB_ISO_ASAP; + purb->transfer_buffer = \ + peasycap->audio_isoc_buffer[isbuf].pgo; + purb->transfer_buffer_length = \ + peasycap->audio_isoc_buffer_size; + purb->complete = easysnd_complete; + purb->context = peasycap; + purb->start_frame = 0; + purb->number_of_packets = \ + peasycap->audio_isoc_framesperdesc; + for (j = 0; j < peasycap->\ + audio_isoc_framesperdesc; \ + j++) { + purb->iso_frame_desc[j].offset = j * \ + peasycap->\ + audio_isoc_maxframesize; + purb->iso_frame_desc[j].length = \ + peasycap->\ + audio_isoc_maxframesize; + } + + rc = usb_submit_urb(purb, GFP_KERNEL); + if (0 != rc) { + isbad++; + SAY("ERROR: usb_submit_urb() failed" \ + " for urb with rc:\n"); + switch (rc) { + case -ENOMEM: { + SAY("ENOMEM\n"); break; + } + case -ENODEV: { + SAY("ENODEV\n"); break; + } + case -ENXIO: { + SAY("ENXIO\n"); break; + } + case -EINVAL: { + SAY("EINVAL\n"); break; + } + case -EAGAIN: { + SAY("EAGAIN\n"); break; + } + case -EFBIG: { + SAY("EFBIG\n"); break; + } + case -EPIPE: { + SAY("EPIPE\n"); break; + } + case -EMSGSIZE: { + SAY("EMSGSIZE\n"); break; + } + default: { + SAY("unknown error code %i\n",\ + rc); break; + } + } + } else { + m++; + } + } else { + isbad++; + } + } else { + isbad++; + } + } + if (isbad) { + JOT(4, "attempting cleanup instead of submitting\n"); + list_for_each(plist_head, (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, \ + list_head); + if (NULL != pdata_urb) { + purb = pdata_urb->purb; + if (NULL != purb) + usb_kill_urb(purb); + } + } + peasycap->audio_isoc_streaming = 0; + } else { + peasycap->audio_isoc_streaming = 1; + JOT(4, "submitted %i audio urbs\n", m); + } +} else + JOT(4, "already streaming audio urbs\n"); + +return 0; +} +/*****************************************************************************/ +/*---------------------------------------------------------------------------*/ +/* + * KILL ALL AUDIO URBS. + */ +/*---------------------------------------------------------------------------*/ +int +kill_audio_urbs(struct easycap *peasycap) +{ +int m; +struct list_head *plist_head; +struct data_urb *pdata_urb; + +if (peasycap->audio_isoc_streaming) { + if ((struct list_head *)NULL != peasycap->purb_audio_head) { + peasycap->audio_isoc_streaming = 0; + JOT(4, "killing audio urbs\n"); + m = 0; + list_for_each(plist_head, (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, + list_head); + if ((struct data_urb *)NULL != pdata_urb) { + if ((struct urb *)NULL != pdata_urb->purb) { + usb_kill_urb(pdata_urb->purb); + m++; + } + } + } + JOT(4, "%i audio urbs killed\n", m); + } else { + SAY("ERROR: peasycap->purb_audio_head is NULL\n"); + return -EFAULT; + } +} else { + JOT(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \ + peasycap->audio_isoc_streaming); +} +return 0; +} +/*****************************************************************************/ diff --git a/drivers/staging/easycap/easycap_sound.h b/drivers/staging/easycap/easycap_sound.h new file mode 100644 index 000000000000..a6e2a9d22319 --- /dev/null +++ b/drivers/staging/easycap/easycap_sound.h @@ -0,0 +1,30 @@ +/***************************************************************************** +* * +* easycap_sound.h * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +extern struct easycap *peasycap; +extern struct usb_driver easycap_usb_driver; +extern unsigned int audio_buffer_page_many; +extern unsigned int audio_pages_per_fragment; diff --git a/drivers/staging/easycap/easycap_standard.h b/drivers/staging/easycap/easycap_standard.h new file mode 100644 index 000000000000..cadc8d27a856 --- /dev/null +++ b/drivers/staging/easycap/easycap_standard.h @@ -0,0 +1,27 @@ +/***************************************************************************** +* * +* easycap_standard.h * +* * +*****************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ +extern struct easycap_standard easycap_standard[]; diff --git a/drivers/staging/easycap/easycap_testcard.c b/drivers/staging/easycap/easycap_testcard.c new file mode 100644 index 000000000000..3c2ce28fab95 --- /dev/null +++ b/drivers/staging/easycap/easycap_testcard.c @@ -0,0 +1,392 @@ +/****************************************************************************** +* * +* easycap_testcard.c * +* * +******************************************************************************/ +/* + * + * Copyright (C) 2010 R.M. Thomas + * + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ +/*****************************************************************************/ + +#include "easycap.h" +#include "easycap_debug.h" + +/*****************************************************************************/ +#define TESTCARD_BYTESPERLINE (2 * 1440) +void +easycap_testcard(struct easycap *peasycap, int field_fill) +{ +int total; +int y, u, v, r, g, b; +unsigned char uyvy[4]; + +int i1, line, k, m, n, more, much, barwidth; +unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2; +struct data_buffer *pfield_buffer; + +JOT(8, "%i=field_fill\n", field_fill); + +if ((TESTCARD_BYTESPERLINE / 2) < peasycap->width) { + SAY("ERROR: image is too wide\n"); + return; +} +if (peasycap->width % 16) { + SAY("ERROR: indivisible image width\n"); + return; +} + +total = 0; +barwidth = (2 * peasycap->width) / 8; + +k = field_fill; +m = 0; +n = 0; + +for (line = 0; line < (peasycap->height / 2); line++) { + for (i1 = 0; i1 < 8; i1++) { + r = (i1 * 256)/8; + g = (i1 * 256)/8; + b = (i1 * 256)/8; + + y = 299*r/1000 + 587*g/1000 + 114*b/1000 ; + u = -147*r/1000 - 289*g/1000 + 436*b/1000 ; u = u + 128; + v = 615*r/1000 - 515*g/1000 - 100*b/1000 ; v = v + 128; + + uyvy[0] = 0xFF & u ; + uyvy[1] = 0xFF & y ; + uyvy[2] = 0xFF & v ; + uyvy[3] = 0xFF & y ; + + p1 = &bfbar[0]; + while (p1 < &bfbar[barwidth]) { + *p1++ = uyvy[0] ; + *p1++ = uyvy[1] ; + *p1++ = uyvy[2] ; + *p1++ = uyvy[3] ; + total += 4; + } + + p1 = &bfbar[0]; + more = barwidth; + + while (more) { + if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) { + SAY("ERROR: bad m reached\n"); + return; + } + if (PAGE_SIZE < n) { + SAY("ERROR: bad n reached\n"); return; + } + + if (0 > more) { + SAY("ERROR: internal fault\n"); + return; + } + + much = PAGE_SIZE - n; + if (much > more) + much = more; + pfield_buffer = &peasycap->field_buffer[k][m]; + p2 = pfield_buffer->pgo + n; + memcpy(p2, p1, much); + + p1 += much; + n += much; + more -= much; + if (PAGE_SIZE == n) { + m++; + n = 0; + } + } + } +} + +JOT(8, "%i=total\n", total); +if (total != peasycap->width * peasycap->height) + SAY("ERROR: wrong number of bytes written: %i\n", total); +return; +} +/*****************************************************************************/ +#if defined(EASYCAP_TESTTONE) +/*----------------------------------------------------------------------------- +THE tones[] ARRAY BELOW IS THE OUTPUT OF THIS PROGRAM, +COMPILED gcc -o prog -lm prog.c +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include +#include + +int main(void); +int +main(void) +{ +int i1, i2, last; +double d1, d2; + +last = 1024 - 1; +d1 = 10.0*3.14159265/1024.0; +printf("int tones[2048] =\n{\n"); +for (i1 = 0; i1 <= last; i1++) + { + d2 = ((double)i1) * d1; + i2 = (int)(16384.0*sin(d2)); + + if (last != i1) + { + printf("%6i, ", i2); printf("%6i, ", i2); + if (!((i1 + 1)%5)) printf("\n"); + } + else + { + printf("%6i, ", i2); printf("%6i\n};\n", i2); + } + } +return(0); +} +-----------------------------------------------------------------------------*/ +int tones[2048] = { + 0, 0, 502, 502, 1004, 1004, 1505, 1505, 2005, 2005, + 2503, 2503, 2998, 2998, 3491, 3491, 3980, 3980, 4466, 4466, + 4948, 4948, 5424, 5424, 5896, 5896, 6362, 6362, 6822, 6822, + 7276, 7276, 7723, 7723, 8162, 8162, 8594, 8594, 9018, 9018, + 9434, 9434, 9840, 9840, 10237, 10237, 10625, 10625, 11002, 11002, + 11370, 11370, 11726, 11726, 12072, 12072, 12406, 12406, 12728, 12728, + 13038, 13038, 13337, 13337, 13622, 13622, 13895, 13895, 14155, 14155, + 14401, 14401, 14634, 14634, 14853, 14853, 15058, 15058, 15249, 15249, + 15426, 15426, 15588, 15588, 15735, 15735, 15868, 15868, 15985, 15985, + 16088, 16088, 16175, 16175, 16248, 16248, 16305, 16305, 16346, 16346, + 16372, 16372, 16383, 16383, 16379, 16379, 16359, 16359, 16323, 16323, + 16272, 16272, 16206, 16206, 16125, 16125, 16028, 16028, 15917, 15917, + 15790, 15790, 15649, 15649, 15492, 15492, 15322, 15322, 15136, 15136, + 14937, 14937, 14723, 14723, 14496, 14496, 14255, 14255, 14001, 14001, + 13733, 13733, 13452, 13452, 13159, 13159, 12854, 12854, 12536, 12536, + 12207, 12207, 11866, 11866, 11513, 11513, 11150, 11150, 10777, 10777, + 10393, 10393, 10000, 10000, 9597, 9597, 9185, 9185, 8765, 8765, + 8336, 8336, 7900, 7900, 7456, 7456, 7005, 7005, 6547, 6547, + 6083, 6083, 5614, 5614, 5139, 5139, 4659, 4659, 4175, 4175, + 3687, 3687, 3196, 3196, 2701, 2701, 2204, 2204, 1705, 1705, + 1205, 1205, 703, 703, 201, 201, -301, -301, -803, -803, + -1305, -1305, -1805, -1805, -2304, -2304, -2801, -2801, -3294, -3294, + -3785, -3785, -4272, -4272, -4756, -4756, -5234, -5234, -5708, -5708, + -6176, -6176, -6639, -6639, -7095, -7095, -7545, -7545, -7988, -7988, + -8423, -8423, -8850, -8850, -9268, -9268, -9679, -9679, -10079, -10079, +-10471, -10471, -10853, -10853, -11224, -11224, -11585, -11585, -11935, -11935, +-12273, -12273, -12600, -12600, -12916, -12916, -13219, -13219, -13510, -13510, +-13788, -13788, -14053, -14053, -14304, -14304, -14543, -14543, -14767, -14767, +-14978, -14978, -15175, -15175, -15357, -15357, -15525, -15525, -15678, -15678, +-15817, -15817, -15940, -15940, -16049, -16049, -16142, -16142, -16221, -16221, +-16284, -16284, -16331, -16331, -16364, -16364, -16381, -16381, -16382, -16382, +-16368, -16368, -16339, -16339, -16294, -16294, -16234, -16234, -16159, -16159, +-16069, -16069, -15963, -15963, -15842, -15842, -15707, -15707, -15557, -15557, +-15392, -15392, -15212, -15212, -15018, -15018, -14810, -14810, -14589, -14589, +-14353, -14353, -14104, -14104, -13842, -13842, -13566, -13566, -13278, -13278, +-12977, -12977, -12665, -12665, -12340, -12340, -12003, -12003, -11656, -11656, +-11297, -11297, -10928, -10928, -10548, -10548, -10159, -10159, -9759, -9759, + -9351, -9351, -8934, -8934, -8509, -8509, -8075, -8075, -7634, -7634, + -7186, -7186, -6731, -6731, -6269, -6269, -5802, -5802, -5329, -5329, + -4852, -4852, -4369, -4369, -3883, -3883, -3393, -3393, -2900, -2900, + -2404, -2404, -1905, -1905, -1405, -1405, -904, -904, -402, -402, + 100, 100, 603, 603, 1105, 1105, 1605, 1605, 2105, 2105, + 2602, 2602, 3097, 3097, 3589, 3589, 4078, 4078, 4563, 4563, + 5043, 5043, 5519, 5519, 5990, 5990, 6455, 6455, 6914, 6914, + 7366, 7366, 7811, 7811, 8249, 8249, 8680, 8680, 9102, 9102, + 9516, 9516, 9920, 9920, 10315, 10315, 10701, 10701, 11077, 11077, + 11442, 11442, 11796, 11796, 12139, 12139, 12471, 12471, 12791, 12791, + 13099, 13099, 13395, 13395, 13678, 13678, 13948, 13948, 14205, 14205, + 14449, 14449, 14679, 14679, 14895, 14895, 15098, 15098, 15286, 15286, + 15459, 15459, 15618, 15618, 15763, 15763, 15892, 15892, 16007, 16007, + 16107, 16107, 16191, 16191, 16260, 16260, 16314, 16314, 16353, 16353, + 16376, 16376, 16384, 16384, 16376, 16376, 16353, 16353, 16314, 16314, + 16260, 16260, 16191, 16191, 16107, 16107, 16007, 16007, 15892, 15892, + 15763, 15763, 15618, 15618, 15459, 15459, 15286, 15286, 15098, 15098, + 14895, 14895, 14679, 14679, 14449, 14449, 14205, 14205, 13948, 13948, + 13678, 13678, 13395, 13395, 13099, 13099, 12791, 12791, 12471, 12471, + 12139, 12139, 11796, 11796, 11442, 11442, 11077, 11077, 10701, 10701, + 10315, 10315, 9920, 9920, 9516, 9516, 9102, 9102, 8680, 8680, + 8249, 8249, 7811, 7811, 7366, 7366, 6914, 6914, 6455, 6455, + 5990, 5990, 5519, 5519, 5043, 5043, 4563, 4563, 4078, 4078, + 3589, 3589, 3097, 3097, 2602, 2602, 2105, 2105, 1605, 1605, + 1105, 1105, 603, 603, 100, 100, -402, -402, -904, -904, + -1405, -1405, -1905, -1905, -2404, -2404, -2900, -2900, -3393, -3393, + -3883, -3883, -4369, -4369, -4852, -4852, -5329, -5329, -5802, -5802, + -6269, -6269, -6731, -6731, -7186, -7186, -7634, -7634, -8075, -8075, + -8509, -8509, -8934, -8934, -9351, -9351, -9759, -9759, -10159, -10159, +-10548, -10548, -10928, -10928, -11297, -11297, -11656, -11656, -12003, -12003, +-12340, -12340, -12665, -12665, -12977, -12977, -13278, -13278, -13566, -13566, +-13842, -13842, -14104, -14104, -14353, -14353, -14589, -14589, -14810, -14810, +-15018, -15018, -15212, -15212, -15392, -15392, -15557, -15557, -15707, -15707, +-15842, -15842, -15963, -15963, -16069, -16069, -16159, -16159, -16234, -16234, +-16294, -16294, -16339, -16339, -16368, -16368, -16382, -16382, -16381, -16381, +-16364, -16364, -16331, -16331, -16284, -16284, -16221, -16221, -16142, -16142, +-16049, -16049, -15940, -15940, -15817, -15817, -15678, -15678, -15525, -15525, +-15357, -15357, -15175, -15175, -14978, -14978, -14767, -14767, -14543, -14543, +-14304, -14304, -14053, -14053, -13788, -13788, -13510, -13510, -13219, -13219, +-12916, -12916, -12600, -12600, -12273, -12273, -11935, -11935, -11585, -11585, +-11224, -11224, -10853, -10853, -10471, -10471, -10079, -10079, -9679, -9679, + -9268, -9268, -8850, -8850, -8423, -8423, -7988, -7988, -7545, -7545, + -7095, -7095, -6639, -6639, -6176, -6176, -5708, -5708, -5234, -5234, + -4756, -4756, -4272, -4272, -3785, -3785, -3294, -3294, -2801, -2801, + -2304, -2304, -1805, -1805, -1305, -1305, -803, -803, -301, -301, + 201, 201, 703, 703, 1205, 1205, 1705, 1705, 2204, 2204, + 2701, 2701, 3196, 3196, 3687, 3687, 4175, 4175, 4659, 4659, + 5139, 5139, 5614, 5614, 6083, 6083, 6547, 6547, 7005, 7005, + 7456, 7456, 7900, 7900, 8336, 8336, 8765, 8765, 9185, 9185, + 9597, 9597, 10000, 10000, 10393, 10393, 10777, 10777, 11150, 11150, + 11513, 11513, 11866, 11866, 12207, 12207, 12536, 12536, 12854, 12854, + 13159, 13159, 13452, 13452, 13733, 13733, 14001, 14001, 14255, 14255, + 14496, 14496, 14723, 14723, 14937, 14937, 15136, 15136, 15322, 15322, + 15492, 15492, 15649, 15649, 15790, 15790, 15917, 15917, 16028, 16028, + 16125, 16125, 16206, 16206, 16272, 16272, 16323, 16323, 16359, 16359, + 16379, 16379, 16383, 16383, 16372, 16372, 16346, 16346, 16305, 16305, + 16248, 16248, 16175, 16175, 16088, 16088, 15985, 15985, 15868, 15868, + 15735, 15735, 15588, 15588, 15426, 15426, 15249, 15249, 15058, 15058, + 14853, 14853, 14634, 14634, 14401, 14401, 14155, 14155, 13895, 13895, + 13622, 13622, 13337, 13337, 13038, 13038, 12728, 12728, 12406, 12406, + 12072, 12072, 11726, 11726, 11370, 11370, 11002, 11002, 10625, 10625, + 10237, 10237, 9840, 9840, 9434, 9434, 9018, 9018, 8594, 8594, + 8162, 8162, 7723, 7723, 7276, 7276, 6822, 6822, 6362, 6362, + 5896, 5896, 5424, 5424, 4948, 4948, 4466, 4466, 3980, 3980, + 3491, 3491, 2998, 2998, 2503, 2503, 2005, 2005, 1505, 1505, + 1004, 1004, 502, 502, 0, 0, -502, -502, -1004, -1004, + -1505, -1505, -2005, -2005, -2503, -2503, -2998, -2998, -3491, -3491, + -3980, -3980, -4466, -4466, -4948, -4948, -5424, -5424, -5896, -5896, + -6362, -6362, -6822, -6822, -7276, -7276, -7723, -7723, -8162, -8162, + -8594, -8594, -9018, -9018, -9434, -9434, -9840, -9840, -10237, -10237, +-10625, -10625, -11002, -11002, -11370, -11370, -11726, -11726, -12072, -12072, +-12406, -12406, -12728, -12728, -13038, -13038, -13337, -13337, -13622, -13622, +-13895, -13895, -14155, -14155, -14401, -14401, -14634, -14634, -14853, -14853, +-15058, -15058, -15249, -15249, -15426, -15426, -15588, -15588, -15735, -15735, +-15868, -15868, -15985, -15985, -16088, -16088, -16175, -16175, -16248, -16248, +-16305, -16305, -16346, -16346, -16372, -16372, -16383, -16383, -16379, -16379, +-16359, -16359, -16323, -16323, -16272, -16272, -16206, -16206, -16125, -16125, +-16028, -16028, -15917, -15917, -15790, -15790, -15649, -15649, -15492, -15492, +-15322, -15322, -15136, -15136, -14937, -14937, -14723, -14723, -14496, -14496, +-14255, -14255, -14001, -14001, -13733, -13733, -13452, -13452, -13159, -13159, +-12854, -12854, -12536, -12536, -12207, -12207, -11866, -11866, -11513, -11513, +-11150, -11150, -10777, -10777, -10393, -10393, -10000, -10000, -9597, -9597, + -9185, -9185, -8765, -8765, -8336, -8336, -7900, -7900, -7456, -7456, + -7005, -7005, -6547, -6547, -6083, -6083, -5614, -5614, -5139, -5139, + -4659, -4659, -4175, -4175, -3687, -3687, -3196, -3196, -2701, -2701, + -2204, -2204, -1705, -1705, -1205, -1205, -703, -703, -201, -201, + 301, 301, 803, 803, 1305, 1305, 1805, 1805, 2304, 2304, + 2801, 2801, 3294, 3294, 3785, 3785, 4272, 4272, 4756, 4756, + 5234, 5234, 5708, 5708, 6176, 6176, 6639, 6639, 7095, 7095, + 7545, 7545, 7988, 7988, 8423, 8423, 8850, 8850, 9268, 9268, + 9679, 9679, 10079, 10079, 10471, 10471, 10853, 10853, 11224, 11224, + 11585, 11585, 11935, 11935, 12273, 12273, 12600, 12600, 12916, 12916, + 13219, 13219, 13510, 13510, 13788, 13788, 14053, 14053, 14304, 14304, + 14543, 14543, 14767, 14767, 14978, 14978, 15175, 15175, 15357, 15357, + 15525, 15525, 15678, 15678, 15817, 15817, 15940, 15940, 16049, 16049, + 16142, 16142, 16221, 16221, 16284, 16284, 16331, 16331, 16364, 16364, + 16381, 16381, 16382, 16382, 16368, 16368, 16339, 16339, 16294, 16294, + 16234, 16234, 16159, 16159, 16069, 16069, 15963, 15963, 15842, 15842, + 15707, 15707, 15557, 15557, 15392, 15392, 15212, 15212, 15018, 15018, + 14810, 14810, 14589, 14589, 14353, 14353, 14104, 14104, 13842, 13842, + 13566, 13566, 13278, 13278, 12977, 12977, 12665, 12665, 12340, 12340, + 12003, 12003, 11656, 11656, 11297, 11297, 10928, 10928, 10548, 10548, + 10159, 10159, 9759, 9759, 9351, 9351, 8934, 8934, 8509, 8509, + 8075, 8075, 7634, 7634, 7186, 7186, 6731, 6731, 6269, 6269, + 5802, 5802, 5329, 5329, 4852, 4852, 4369, 4369, 3883, 3883, + 3393, 3393, 2900, 2900, 2404, 2404, 1905, 1905, 1405, 1405, + 904, 904, 402, 402, -100, -100, -603, -603, -1105, -1105, + -1605, -1605, -2105, -2105, -2602, -2602, -3097, -3097, -3589, -3589, + -4078, -4078, -4563, -4563, -5043, -5043, -5519, -5519, -5990, -5990, + -6455, -6455, -6914, -6914, -7366, -7366, -7811, -7811, -8249, -8249, + -8680, -8680, -9102, -9102, -9516, -9516, -9920, -9920, -10315, -10315, +-10701, -10701, -11077, -11077, -11442, -11442, -11796, -11796, -12139, -12139, +-12471, -12471, -12791, -12791, -13099, -13099, -13395, -13395, -13678, -13678, +-13948, -13948, -14205, -14205, -14449, -14449, -14679, -14679, -14895, -14895, +-15098, -15098, -15286, -15286, -15459, -15459, -15618, -15618, -15763, -15763, +-15892, -15892, -16007, -16007, -16107, -16107, -16191, -16191, -16260, -16260, +-16314, -16314, -16353, -16353, -16376, -16376, -16383, -16383, -16376, -16376, +-16353, -16353, -16314, -16314, -16260, -16260, -16191, -16191, -16107, -16107, +-16007, -16007, -15892, -15892, -15763, -15763, -15618, -15618, -15459, -15459, +-15286, -15286, -15098, -15098, -14895, -14895, -14679, -14679, -14449, -14449, +-14205, -14205, -13948, -13948, -13678, -13678, -13395, -13395, -13099, -13099, +-12791, -12791, -12471, -12471, -12139, -12139, -11796, -11796, -11442, -11442, +-11077, -11077, -10701, -10701, -10315, -10315, -9920, -9920, -9516, -9516, + -9102, -9102, -8680, -8680, -8249, -8249, -7811, -7811, -7366, -7366, + -6914, -6914, -6455, -6455, -5990, -5990, -5519, -5519, -5043, -5043, + -4563, -4563, -4078, -4078, -3589, -3589, -3097, -3097, -2602, -2602, + -2105, -2105, -1605, -1605, -1105, -1105, -603, -603, -100, -100, + 402, 402, 904, 904, 1405, 1405, 1905, 1905, 2404, 2404, + 2900, 2900, 3393, 3393, 3883, 3883, 4369, 4369, 4852, 4852, + 5329, 5329, 5802, 5802, 6269, 6269, 6731, 6731, 7186, 7186, + 7634, 7634, 8075, 8075, 8509, 8509, 8934, 8934, 9351, 9351, + 9759, 9759, 10159, 10159, 10548, 10548, 10928, 10928, 11297, 11297, + 11656, 11656, 12003, 12003, 12340, 12340, 12665, 12665, 12977, 12977, + 13278, 13278, 13566, 13566, 13842, 13842, 14104, 14104, 14353, 14353, + 14589, 14589, 14810, 14810, 15018, 15018, 15212, 15212, 15392, 15392, + 15557, 15557, 15707, 15707, 15842, 15842, 15963, 15963, 16069, 16069, + 16159, 16159, 16234, 16234, 16294, 16294, 16339, 16339, 16368, 16368, + 16382, 16382, 16381, 16381, 16364, 16364, 16331, 16331, 16284, 16284, + 16221, 16221, 16142, 16142, 16049, 16049, 15940, 15940, 15817, 15817, + 15678, 15678, 15525, 15525, 15357, 15357, 15175, 15175, 14978, 14978, + 14767, 14767, 14543, 14543, 14304, 14304, 14053, 14053, 13788, 13788, + 13510, 13510, 13219, 13219, 12916, 12916, 12600, 12600, 12273, 12273, + 11935, 11935, 11585, 11585, 11224, 11224, 10853, 10853, 10471, 10471, + 10079, 10079, 9679, 9679, 9268, 9268, 8850, 8850, 8423, 8423, + 7988, 7988, 7545, 7545, 7095, 7095, 6639, 6639, 6176, 6176, + 5708, 5708, 5234, 5234, 4756, 4756, 4272, 4272, 3785, 3785, + 3294, 3294, 2801, 2801, 2304, 2304, 1805, 1805, 1305, 1305, + 803, 803, 301, 301, -201, -201, -703, -703, -1205, -1205, + -1705, -1705, -2204, -2204, -2701, -2701, -3196, -3196, -3687, -3687, + -4175, -4175, -4659, -4659, -5139, -5139, -5614, -5614, -6083, -6083, + -6547, -6547, -7005, -7005, -7456, -7456, -7900, -7900, -8336, -8336, + -8765, -8765, -9185, -9185, -9597, -9597, -10000, -10000, -10393, -10393, +-10777, -10777, -11150, -11150, -11513, -11513, -11866, -11866, -12207, -12207, +-12536, -12536, -12854, -12854, -13159, -13159, -13452, -13452, -13733, -13733, +-14001, -14001, -14255, -14255, -14496, -14496, -14723, -14723, -14937, -14937, +-15136, -15136, -15322, -15322, -15492, -15492, -15649, -15649, -15790, -15790, +-15917, -15917, -16028, -16028, -16125, -16125, -16206, -16206, -16272, -16272, +-16323, -16323, -16359, -16359, -16379, -16379, -16383, -16383, -16372, -16372, +-16346, -16346, -16305, -16305, -16248, -16248, -16175, -16175, -16088, -16088, +-15985, -15985, -15868, -15868, -15735, -15735, -15588, -15588, -15426, -15426, +-15249, -15249, -15058, -15058, -14853, -14853, -14634, -14634, -14401, -14401, +-14155, -14155, -13895, -13895, -13622, -13622, -13337, -13337, -13038, -13038, +-12728, -12728, -12406, -12406, -12072, -12072, -11726, -11726, -11370, -11370, +-11002, -11002, -10625, -10625, -10237, -10237, -9840, -9840, -9434, -9434, + -9018, -9018, -8594, -8594, -8162, -8162, -7723, -7723, -7276, -7276, + -6822, -6822, -6362, -6362, -5896, -5896, -5424, -5424, -4948, -4948, + -4466, -4466, -3980, -3980, -3491, -3491, -2998, -2998, -2503, -2503, + -2005, -2005, -1505, -1505, -1004, -1004, -502, -502 +}; +/*****************************************************************************/ +void +easysnd_testtone(struct easycap *peasycap, int audio_fill) +{ +int i1; +unsigned char *p2; +struct data_buffer *paudio_buffer; + +JOT(8, "%i=audio_fill\n", audio_fill); + +paudio_buffer = &peasycap->audio_buffer[audio_fill]; + +p2 = (unsigned char *)(paudio_buffer->pgo); +for (i1 = 0; i1 < PAGE_SIZE; i1 += 4, p2 += 4) { + *p2 = (unsigned char) (0x00FF & tones[i1/2]); + *(p2 + 1) = (unsigned char)((0xFF00 & tones[i1/2]) >> 8); + *(p2 + 2) = (unsigned char) (0x00FF & tones[i1/2 + 1]); + *(p2 + 3) = (unsigned char)((0xFF00 & tones[i1/2 + 1]) >> 8); + } +return; +} +#endif /*EASYCAP_TESTTONE*/ +/*****************************************************************************/ -- cgit v1.2.3 From 4f62e69b2b346053e581b11d7374c5082833a6a9 Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Mon, 24 May 2010 19:44:09 +0530 Subject: Staging: Update TI-ST's TODO Update the TODO of TI-ST to make sure it reflects current list of activities that need to be done. Also point it out to the user-space app code relevant to it. Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ti-st/TODO | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ti-st/TODO b/drivers/staging/ti-st/TODO index 2c4fe583901d..26f3ae3f2dcd 100644 --- a/drivers/staging/ti-st/TODO +++ b/drivers/staging/ti-st/TODO @@ -2,9 +2,16 @@ TODO: 1. A per-device/tty port context required to support multiple devices on same platform. +Plan: Each BT, FM and GPS device would be a platform-device with its platform-data +mentioning which of the ST device it wants to attach itself onto. -2. REMOVE the sysfs entry PID passing mechanism, since there should -be a better way to request user-space to install line discipline. +There by each of the ST device which is also a platform device upon receiving +a st_register() would know whether the registration from BT/FM or GPS was intended for it. + +2. Improve upon the way requirement of line discipline is communicated to +user-space, The current user-space application which open/installs ldisc +as and when required can be found at, +http://git.omapzoom.org/?pÿatform/hardware/ti/omap3.git;aÿob;fÿ_st/uim/uim.c;ha16c2c2b5085eb54a1bbc7096d779d7594eb11;hbìlair 3. Re-view/Re-work on the locking. -- cgit v1.2.3 From b38fc2d965c3182c1855f868144a41a137e07983 Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Wed, 9 Jun 2010 03:45:32 -0500 Subject: Staging: ti-st: cleanup sysfs code Remove the older way of communicating with user-space daemon UIM. The older way involved creating of a new kobj and pid sysfs file under it, and sending signal using that pid. Now we communicate via rfkill to user-space UIM. Background: UIM is the user-space daemon which upon notification from ldisc driver, opens the tty, sets default baud and then installs (tiocsetd) the ldisc. Signed-off-by: Naveen Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ti-st/st_kim.c | 49 ++++++------------------------------------ drivers/staging/ti-st/st_kim.h | 4 ---- 2 files changed, 6 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ti-st/st_kim.c b/drivers/staging/ti-st/st_kim.c index 98cbabba3844..cfba5f88abe1 100644 --- a/drivers/staging/ti-st/st_kim.c +++ b/drivers/staging/ti-st/st_kim.c @@ -55,7 +55,6 @@ static struct platform_driver kim_platform_driver = { }, }; -#ifndef LEGACY_RFKILL_SUPPORT static ssize_t show_pid(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t store_pid(struct device *dev, struct device_attribute @@ -80,12 +79,11 @@ static struct attribute *uim_attrs[] = { static struct attribute_group uim_attr_grp = { .attrs = uim_attrs, }; -#else + static int kim_toggle_radio(void*, bool); static const struct rfkill_ops kim_rfkill_ops = { .set_block = kim_toggle_radio, }; -#endif /* LEGACY_RFKILL_SUPPORT */ /* strings to be used for rfkill entries and by * ST Core to be used for sysfs debug entry @@ -436,13 +434,11 @@ long st_kim_start(void) pr_info(" %s", __func__); do { -#ifdef LEGACY_RFKILL_SUPPORT /* TODO: this is only because rfkill sub-system * doesn't send events to user-space if the state * isn't changed */ rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1); -#endif /* Configure BT nShutdown to HIGH state */ gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW); mdelay(5); /* FIXME: a proper toggle */ @@ -450,7 +446,7 @@ long st_kim_start(void) mdelay(100); /* re-initialize the completion */ INIT_COMPLETION(kim_gdata->ldisc_installed); -#ifndef LEGACY_RFKILL_SUPPORT +#if 0 /* older way of signalling user-space UIM */ /* send signal to UIM */ err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 0); if (err != 0) { @@ -458,10 +454,9 @@ long st_kim_start(void) err = ST_ERR_FAILURE; continue; } -#else +#endif /* unblock and send event to UIM via /dev/rfkill */ rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 0); -#endif /* wait for ldisc to be installed */ err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); @@ -491,17 +486,16 @@ long st_kim_stop(void) long err = ST_SUCCESS; INIT_COMPLETION(kim_gdata->ldisc_installed); -#ifndef LEGACY_RFKILL_SUPPORT +#if 0 /* older way of signalling user-space UIM */ /* send signal to UIM */ err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 1); if (err != 0) { pr_err("sending SIGUSR2 to uim failed %ld", err); return ST_ERR_FAILURE; } -#else +#endif /* set BT rfkill to be blocked */ err = rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1); -#endif /* wait for ldisc to be un-installed */ err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, @@ -523,7 +517,6 @@ long st_kim_stop(void) /**********************************************************************/ /* functions called from subsystems */ -#ifndef LEGACY_RFKILL_SUPPORT /* called when sysfs entry is written to */ static ssize_t store_pid(struct device *dev, struct device_attribute *devattr, char *buf, size_t count) @@ -551,8 +544,6 @@ static ssize_t show_list(struct device *dev, struct device_attribute return strlen(buf); } -#else /* LEGACY_RFKILL_SUPPORT */ - /* function called from rfkill subsystem, when someone from * user space would write 0/1 on the sysfs entry * /sys/class/rfkill/rfkill0,1,3/state @@ -580,8 +571,6 @@ static int kim_toggle_radio(void *data, bool blocked) return ST_SUCCESS; } -#endif /* LEGACY_RFKILL_SUPPORT */ - void st_kim_ref(struct st_data_s **core_data) { *core_data = kim_gdata->core_data; @@ -639,30 +628,12 @@ static int kim_probe(struct platform_device *pdev) return status; } } -#ifndef LEGACY_RFKILL_SUPPORT - /* pdev to contain BT, FM and GPS enable/N-Shutdown GPIOs - * execute request_gpio, set output direction - */ - kim_gdata->kim_kobj = kobject_create_and_add("uim", NULL); - /* create the sysfs entry for UIM to put in pid */ - if (sysfs_create_group(kim_gdata->kim_kobj, &uim_attr_grp)) { - pr_err(" sysfs entry creation failed"); - kobject_put(kim_gdata->kim_kobj); - /* free requested GPIOs and fail probe */ - for (proto = ST_BT; proto < ST_MAX; proto++) { - if (gpios[proto] != -1) - gpio_free(gpios[proto]); - } - return -1; /* fail insmod */ - } - pr_info(" sysfs entry created "); -#endif /* get reference of pdev for request_firmware */ kim_gdata->kim_pdev = pdev; init_completion(&kim_gdata->kim_rcvd); init_completion(&kim_gdata->ldisc_installed); -#ifdef LEGACY_RFKILL_SUPPORT + for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) { /* TODO: should all types be rfkill_type_bt ? */ kim_gdata->rf_protos[proto] = proto; @@ -685,7 +656,6 @@ static int kim_probe(struct platform_device *pdev) } pr_info("rfkill entry created for %ld", gpios[proto]); } -#endif return ST_SUCCESS; } @@ -701,18 +671,11 @@ static int kim_remove(struct platform_device *pdev) * nShutdown gpio from the system */ gpio_free(gpios[proto]); -#ifdef LEGACY_RFKILL_SUPPORT rfkill_unregister(kim_gdata->rfkill[proto]); rfkill_destroy(kim_gdata->rfkill[proto]); kim_gdata->rfkill[proto] = NULL; -#endif } pr_info("kim: GPIO Freed"); -#ifndef LEGACY_RFKILL_SUPPORT - /* delete the sysfs entries */ - sysfs_remove_group(kim_gdata->kim_kobj, &uim_attr_grp); - kobject_put(kim_gdata->kim_kobj); -#endif kim_gdata->kim_pdev = NULL; st_core_exit(kim_gdata->core_data); return ST_SUCCESS; diff --git a/drivers/staging/ti-st/st_kim.h b/drivers/staging/ti-st/st_kim.h index ff3270ec7847..49c42aedb456 100644 --- a/drivers/staging/ti-st/st_kim.h +++ b/drivers/staging/ti-st/st_kim.h @@ -48,7 +48,6 @@ * devices are created for the 3 gpios * that ST has requested */ -#define LEGACY_RFKILL_SUPPORT /* * header file for ST provided by KIM */ @@ -60,15 +59,12 @@ struct kim_data_s { char resp_buffer[30]; const struct firmware *fw_entry; long gpios[ST_MAX]; - struct kobject *kim_kobj; /* used by kim_int_recv to validate fw response */ unsigned long rx_state; unsigned long rx_count; struct sk_buff *rx_skb; -#ifdef LEGACY_RFKILL_SUPPORT struct rfkill *rfkill[ST_MAX]; enum proto_type rf_protos[ST_MAX]; -#endif struct st_data_s *core_data; }; -- cgit v1.2.3 From e2a53282859fab0e428a243cbe9ca8d727d9d840 Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Wed, 9 Jun 2010 03:45:33 -0500 Subject: Staging: ti-st: add version info to sysfs Add version information to be available under the sysfs group for kim. Signed-off-by: Naveen Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ti-st/st_kim.c | 40 +++++++++++++++++++++++++++++++++++----- drivers/staging/ti-st/st_kim.h | 11 +++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ti-st/st_kim.c b/drivers/staging/ti-st/st_kim.c index cfba5f88abe1..d015ad3c4600 100644 --- a/drivers/staging/ti-st/st_kim.c +++ b/drivers/staging/ti-st/st_kim.c @@ -56,12 +56,13 @@ static struct platform_driver kim_platform_driver = { }; static ssize_t show_pid(struct device *dev, struct device_attribute - *attr, char *buf); + *attr, char *buf); static ssize_t store_pid(struct device *dev, struct device_attribute - *devattr, char *buf, size_t count); + *devattr, char *buf, size_t count); static ssize_t show_list(struct device *dev, struct device_attribute - *attr, char *buf); - + *attr, char *buf); +static ssize_t show_version(struct device *dev, struct device_attribute + *attr, char *buf); /* structures specific for sysfs entries */ static struct kobj_attribute pid_attr = __ATTR(pid, 0644, (void *)show_pid, (void *)store_pid); @@ -69,10 +70,14 @@ __ATTR(pid, 0644, (void *)show_pid, (void *)store_pid); static struct kobj_attribute list_protocols = __ATTR(protocols, 0444, (void *)show_list, NULL); +static struct kobj_attribute chip_version = +__ATTR(version, 0444, (void *)show_version, NULL); + static struct attribute *uim_attrs[] = { &pid_attr.attr, /* add more debug sysfs entries */ &list_protocols.attr, + &chip_version.attr, NULL, }; @@ -251,7 +256,8 @@ static long read_local_version(char *bts_scr_name) } version = - MAKEWORD(kim_gdata->resp_buffer[13], kim_gdata->resp_buffer[14]); + MAKEWORD(kim_gdata->resp_buffer[13], + kim_gdata->resp_buffer[14]); chip = (version & 0x7C00) >> 10; min_ver = (version & 0x007F); maj_ver = (version & 0x0380) >> 7; @@ -260,6 +266,13 @@ static long read_local_version(char *bts_scr_name) maj_ver |= 0x0008; sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver); + + /* to be accessed later via sysfs entry */ + kim_gdata->version.full = version; + kim_gdata->version.chip = chip; + kim_gdata->version.maj_ver = maj_ver; + kim_gdata->version.min_ver = min_ver; + pr_info("%s", bts_scr_name); return ST_SUCCESS; } @@ -516,6 +529,16 @@ long st_kim_stop(void) /**********************************************************************/ /* functions called from subsystems */ +/* called when sysfs entry is read from */ + +static ssize_t show_version(struct device *dev, struct device_attribute + *attr, char *buf) +{ + sprintf(buf, "%04X %d.%d.%d", kim_gdata->version.full, + kim_gdata->version.chip, kim_gdata->version.maj_ver, + kim_gdata->version.min_ver); + return strlen(buf); +} /* called when sysfs entry is written to */ static ssize_t store_pid(struct device *dev, struct device_attribute @@ -656,6 +679,12 @@ static int kim_probe(struct platform_device *pdev) } pr_info("rfkill entry created for %ld", gpios[proto]); } + + if (sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp)) { + pr_err(" sysfs entry creation failed"); + return -1; + } + pr_info(" sysfs entries created "); return ST_SUCCESS; } @@ -676,6 +705,7 @@ static int kim_remove(struct platform_device *pdev) kim_gdata->rfkill[proto] = NULL; } pr_info("kim: GPIO Freed"); + sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); kim_gdata->kim_pdev = NULL; st_core_exit(kim_gdata->core_data); return ST_SUCCESS; diff --git a/drivers/staging/ti-st/st_kim.h b/drivers/staging/ti-st/st_kim.h index 49c42aedb456..a5ea8d7c680c 100644 --- a/drivers/staging/ti-st/st_kim.h +++ b/drivers/staging/ti-st/st_kim.h @@ -48,6 +48,16 @@ * devices are created for the 3 gpios * that ST has requested */ + +/* chip version storage + */ +struct chip_version { + unsigned short full; + unsigned short chip; + unsigned short min_ver; + unsigned short maj_ver; +}; + /* * header file for ST provided by KIM */ @@ -66,6 +76,7 @@ struct kim_data_s { struct rfkill *rfkill[ST_MAX]; enum proto_type rf_protos[ST_MAX]; struct st_data_s *core_data; + struct chip_version version; }; long st_kim_start(void); -- cgit v1.2.3 From 36e574fed5578aeee0ce4c7359bc17cc0b8e0b57 Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Wed, 9 Jun 2010 07:20:40 -0500 Subject: Staging: ti-st: fix protocol counting Older mechanism of counting the number of protocols registered with ST was slow, in-efficient. It used to check the protocol data for NULL for each registration/unregistration. With this change, counting protocols in maintained by a single counter protos_registered. Counting protocols is not just for debug purposes Signed-off-by: Naveen Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ti-st/st_core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ti-st/st_core.c b/drivers/staging/ti-st/st_core.c index 4e93694e1c21..a49236903375 100644 --- a/drivers/staging/ti-st/st_core.c +++ b/drivers/staging/ti-st/st_core.c @@ -584,10 +584,11 @@ void kim_st_list_protocols(struct st_data_s *st_gdata, char *buf) } sprintf(buf, "%s\n", buf); #else /* limited info */ - sprintf(buf, "BT=%c\nFM=%c\nGPS=%c\n", - st_gdata->list[ST_BT] != NULL ? 'R' : 'U', - st_gdata->list[ST_FM] != NULL ? 'R' : 'U', - st_gdata->list[ST_GPS] != NULL ? 'R' : 'U'); + sprintf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n", + st_gdata->protos_registered, + st_gdata->list[ST_BT] != NULL ? 'R' : 'U', + st_gdata->list[ST_FM] != NULL ? 'R' : 'U', + st_gdata->list[ST_GPS] != NULL ? 'R' : 'U'); #endif spin_unlock_irqrestore(&st_gdata->lock, flags); } @@ -630,6 +631,7 @@ long st_register(struct st_proto_s *new_proto) st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE); st_gdata->list[new_proto->type] = new_proto; + st_gdata->protos_registered++; new_proto->write = st_write; set_bit(ST_REG_PENDING, &st_gdata->st_state); @@ -673,7 +675,6 @@ long st_register(struct st_proto_s *new_proto) if ((st_gdata->protos_registered != ST_EMPTY) && (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { pr_info(" call reg complete callback "); - st_gdata->protos_registered++; st_reg_complete(st_gdata, ST_SUCCESS); } clear_bit(ST_REG_PENDING, &st_gdata->st_state); @@ -689,6 +690,7 @@ long st_register(struct st_proto_s *new_proto) spin_lock_irqsave(&st_gdata->lock, flags); st_gdata->list[new_proto->type] = new_proto; + st_gdata->protos_registered++; new_proto->write = st_write; spin_unlock_irqrestore(&st_gdata->lock, flags); return err; @@ -712,6 +714,7 @@ long st_register(struct st_proto_s *new_proto) break; } st_gdata->list[new_proto->type] = new_proto; + st_gdata->protos_registered++; new_proto->write = st_write; /* lock already held before entering else */ -- cgit v1.2.3 From a1dd52afa94238d361d70502b219409ea115e235 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Tue, 1 Jun 2010 13:31:23 +0530 Subject: Staging: ramzswap: Support generic I/O requests Currently, ramzwap devices (/dev/ramzswapX) can only be used as swap disks since it was hard-coded to consider only the first request in bio vector. Now, we iterate over all the segments in an incoming bio which allows us to handle all kinds of I/O requests. ramzswap devices can still handle PAGE_SIZE aligned and multiple of PAGE_SIZE sized I/O requests only. To ensure that we get always get such requests only, we set following request_queue attributes to PAGE_SIZE: - physical_block_size - logical_block_size - io_min - io_opt Note: physical and logical block sizes were already set equal to PAGE_SIZE and that seems to be sufficient to get PAGE_SIZE aligned I/O. Since we are no longer limited to handling swap requests only, the next few patches rename ramzswap to zram. So, the devices will then be called /dev/zram{0, 1, 2, ...} Usage/Examples: 1) Use as /tmp storage - mkfs.ext4 /dev/zram0 - mount /dev/zram0 /tmp 2) Use as swap: - mkswap /dev/zram0 - swapon /dev/zram0 -p 10 # give highest priority to zram0 Performance: - I/O benchamark done with 'dd' command. Details can be found here: http://code.google.com/p/compcache/wiki/zramperf Summary: - Maximum read speed (approx): - ram disk: 1200 MB/sec - zram disk: 600 MB/sec - Maximum write speed (approx): - ram disk: 500 MB/sec - zram disk: 160 MB/sec Issues: - Double caching: We can potentially waste memory by having two copies of a page -- one in page cache (uncompress) and second in the device memory (compressed). However, during reclaim, clean page cache pages are quickly freed, so this does not seem to be a big problem. - Stale data: Not all filesystems support issuing 'discard' requests to underlying block devices. So, if such filesystems are used over zram devices, we can accumulate lot of stale data in memory. Even for filesystems to do support discard (example, ext4), we need to see how effective it is. - Scalability: There is only one (per-device) de/compression buffer stats. This can lead to significant contention, especially when used for generic (non-swap) purposes. Signed-off-by: Nitin Gupta Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ramzswap/ramzswap_drv.c | 326 ++++++++++++++------------------ drivers/staging/ramzswap/ramzswap_drv.h | 3 +- 2 files changed, 149 insertions(+), 180 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c index d14bf9129e36..7b5cc61b3d69 100644 --- a/drivers/staging/ramzswap/ramzswap_drv.c +++ b/drivers/staging/ramzswap/ramzswap_drv.c @@ -101,20 +101,6 @@ static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) rzs->disksize &= PAGE_MASK; } -/* - * Swap header (1st page of swap device) contains information - * about a swap file/partition. Prepare such a header for the - * given ramzswap device so that swapon can identify it as a - * swap partition. - */ -static void setup_swap_header(struct ramzswap *rzs, union swap_header *s) -{ - s->info.version = 1; - s->info.last_page = (rzs->disksize >> PAGE_SHIFT) - 1; - s->info.nr_badpages = 0; - memcpy(s->magic.magic, "SWAPSPACE2", 10); -} - static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, struct ramzswap_ioctl_stats *s) { @@ -202,31 +188,22 @@ out: rzs->table[index].offset = 0; } -static int handle_zero_page(struct bio *bio) +static void handle_zero_page(struct page *page) { void *user_mem; - struct page *page = bio->bi_io_vec[0].bv_page; user_mem = kmap_atomic(page, KM_USER0); memset(user_mem, 0, PAGE_SIZE); kunmap_atomic(user_mem, KM_USER0); flush_dcache_page(page); - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; } -static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio) +static void handle_uncompressed_page(struct ramzswap *rzs, + struct page *page, u32 index) { - u32 index; - struct page *page; unsigned char *user_mem, *cmem; - page = bio->bi_io_vec[0].bv_page; - index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - user_mem = kmap_atomic(page, KM_USER0); cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + rzs->table[index].offset; @@ -236,79 +213,71 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio) kunmap_atomic(cmem, KM_USER1); flush_dcache_page(page); - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; -} - -/* - * Called when request page is not present in ramzswap. - * This is an attempt to read before any previous write - * to this location - this happens due to readahead when - * swap device is read from user-space (e.g. during swapon) - */ -static int handle_ramzswap_fault(struct ramzswap *rzs, struct bio *bio) -{ - pr_debug("Read before write on swap device: " - "sector=%lu, size=%u, offset=%u\n", - (ulong)(bio->bi_sector), bio->bi_size, - bio->bi_io_vec[0].bv_offset); - - /* Do nothing. Just return success */ - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; } static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) { - int ret; + + int i; u32 index; - size_t clen; - struct page *page; - struct zobj_header *zheader; - unsigned char *user_mem, *cmem; + struct bio_vec *bvec; rzs_stat64_inc(rzs, &rzs->stats.num_reads); - page = bio->bi_io_vec[0].bv_page; index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + bio_for_each_segment(bvec, bio, i) { + int ret; + size_t clen; + struct page *page; + struct zobj_header *zheader; + unsigned char *user_mem, *cmem; - if (rzs_test_flag(rzs, index, RZS_ZERO)) - return handle_zero_page(bio); + page = bvec->bv_page; - /* Requested page is not present in compressed area */ - if (!rzs->table[index].page) - return handle_ramzswap_fault(rzs, bio); + if (rzs_test_flag(rzs, index, RZS_ZERO)) { + handle_zero_page(page); + continue; + } - /* Page is stored uncompressed since it's incompressible */ - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) - return handle_uncompressed_page(rzs, bio); + /* Requested page is not present in compressed area */ + if (unlikely(!rzs->table[index].page)) { + pr_debug("Read before write: sector=%lu, size=%u", + (ulong)(bio->bi_sector), bio->bi_size); + /* Do nothing */ + continue; + } - user_mem = kmap_atomic(page, KM_USER0); - clen = PAGE_SIZE; + /* Page is stored uncompressed since it's incompressible */ + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { + handle_uncompressed_page(rzs, page, index); + continue; + } - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; + user_mem = kmap_atomic(page, KM_USER0); + clen = PAGE_SIZE; - ret = lzo1x_decompress_safe( - cmem + sizeof(*zheader), - xv_get_object_size(cmem) - sizeof(*zheader), - user_mem, &clen); + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; - kunmap_atomic(user_mem, KM_USER0); - kunmap_atomic(cmem, KM_USER1); + ret = lzo1x_decompress_safe( + cmem + sizeof(*zheader), + xv_get_object_size(cmem) - sizeof(*zheader), + user_mem, &clen); - /* should NEVER happen */ - if (unlikely(ret != LZO_E_OK)) { - pr_err("Decompression failed! err=%d, page=%u\n", - ret, index); - rzs_stat64_inc(rzs, &rzs->stats.failed_reads); - goto out; - } + kunmap_atomic(user_mem, KM_USER0); + kunmap_atomic(cmem, KM_USER1); - flush_dcache_page(page); + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { + pr_err("Decompression failed! err=%d, page=%u\n", + ret, index); + rzs_stat64_inc(rzs, &rzs->stats.failed_reads); + goto out; + } + + flush_dcache_page(page); + index++; + } set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); @@ -321,108 +290,120 @@ out: static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) { - int ret; - u32 offset, index; - size_t clen; - struct zobj_header *zheader; - struct page *page, *page_store; - unsigned char *user_mem, *cmem, *src; + int i; + u32 index; + struct bio_vec *bvec; rzs_stat64_inc(rzs, &rzs->stats.num_writes); - page = bio->bi_io_vec[0].bv_page; index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - src = rzs->compress_buffer; + bio_for_each_segment(bvec, bio, i) { + int ret; + u32 offset; + size_t clen; + struct zobj_header *zheader; + struct page *page, *page_store; + unsigned char *user_mem, *cmem, *src; - mutex_lock(&rzs->lock); + page = bvec->bv_page; + src = rzs->compress_buffer; - user_mem = kmap_atomic(page, KM_USER0); - if (page_zero_filled(user_mem)) { - kunmap_atomic(user_mem, KM_USER0); - mutex_unlock(&rzs->lock); - rzs_stat_inc(&rzs->stats.pages_zero); - rzs_set_flag(rzs, index, RZS_ZERO); + /* + * System overwrites unused sectors. Free memory associated + * with this sector now. + */ + if (rzs->table[index].page || + rzs_test_flag(rzs, index, RZS_ZERO)) + ramzswap_free_page(rzs, index); - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; - } + mutex_lock(&rzs->lock); - ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, - rzs->compress_workmem); + user_mem = kmap_atomic(page, KM_USER0); + if (page_zero_filled(user_mem)) { + kunmap_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs->lock); + rzs_stat_inc(&rzs->stats.pages_zero); + rzs_set_flag(rzs, index, RZS_ZERO); + continue; + } - kunmap_atomic(user_mem, KM_USER0); + ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, + rzs->compress_workmem); - if (unlikely(ret != LZO_E_OK)) { - mutex_unlock(&rzs->lock); - pr_err("Compression failed! err=%d\n", ret); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); - goto out; - } + kunmap_atomic(user_mem, KM_USER0); - /* - * Page is incompressible. Store it as-is (uncompressed) - * since we do not want to return too many swap write - * errors which has side effect of hanging the system. - */ - if (unlikely(clen > max_zpage_size)) { - clen = PAGE_SIZE; - page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); - if (unlikely(!page_store)) { + if (unlikely(ret != LZO_E_OK)) { mutex_unlock(&rzs->lock); - pr_info("Error allocating memory for incompressible " - "page: %u\n", index); + pr_err("Compression failed! err=%d\n", ret); rzs_stat64_inc(rzs, &rzs->stats.failed_writes); goto out; } - offset = 0; - rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_inc(&rzs->stats.pages_expand); - rzs->table[index].page = page_store; - src = kmap_atomic(page, KM_USER0); - goto memstore; - } + /* + * Page is incompressible. Store it as-is (uncompressed) + * since we do not want to return too many swap write + * errors which has side effect of hanging the system. + */ + if (unlikely(clen > max_zpage_size)) { + clen = PAGE_SIZE; + page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); + if (unlikely(!page_store)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for " + "incompressible page: %u\n", index); + rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + goto out; + } + + offset = 0; + rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); + rzs_stat_inc(&rzs->stats.pages_expand); + rzs->table[index].page = page_store; + src = kmap_atomic(page, KM_USER0); + goto memstore; + } - if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), - &rzs->table[index].page, &offset, - GFP_NOIO | __GFP_HIGHMEM)) { - mutex_unlock(&rzs->lock); - pr_info("Error allocating memory for compressed " - "page: %u, size=%zu\n", index, clen); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); - goto out; - } + if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), + &rzs->table[index].page, &offset, + GFP_NOIO | __GFP_HIGHMEM)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for compressed " + "page: %u, size=%zu\n", index, clen); + rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + goto out; + } memstore: - rzs->table[index].offset = offset; + rzs->table[index].offset = offset; - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; #if 0 - /* Back-reference needed for memory defragmentation */ - if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { - zheader = (struct zobj_header *)cmem; - zheader->table_idx = index; - cmem += sizeof(*zheader); - } + /* Back-reference needed for memory defragmentation */ + if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { + zheader = (struct zobj_header *)cmem; + zheader->table_idx = index; + cmem += sizeof(*zheader); + } #endif - memcpy(cmem, src, clen); + memcpy(cmem, src, clen); - kunmap_atomic(cmem, KM_USER1); - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) - kunmap_atomic(src, KM_USER0); + kunmap_atomic(cmem, KM_USER1); + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + kunmap_atomic(src, KM_USER0); - /* Update stats */ - rzs->stats.compr_size += clen; - rzs_stat_inc(&rzs->stats.pages_stored); - if (clen <= PAGE_SIZE / 2) - rzs_stat_inc(&rzs->stats.good_compress); + /* Update stats */ + rzs->stats.compr_size += clen; + rzs_stat_inc(&rzs->stats.pages_stored); + if (clen <= PAGE_SIZE / 2) + rzs_stat_inc(&rzs->stats.good_compress); - mutex_unlock(&rzs->lock); + mutex_unlock(&rzs->lock); + index++; + } set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); @@ -436,19 +417,17 @@ out: /* * Check if request is within bounds and page aligned. */ -static inline int valid_swap_request(struct ramzswap *rzs, struct bio *bio) +static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio) { if (unlikely( (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) || (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || - (bio->bi_vcnt != 1) || - (bio->bi_size != PAGE_SIZE) || - (bio->bi_io_vec[0].bv_offset != 0))) { + (bio->bi_size & (PAGE_SIZE - 1)))) { return 0; } - /* swap request is valid */ + /* I/O request is valid */ return 1; } @@ -465,7 +444,7 @@ static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) return 0; } - if (!valid_swap_request(rzs, bio)) { + if (!valid_io_request(rzs, bio)) { rzs_stat64_inc(rzs, &rzs->stats.invalid_io); bio_io_error(bio); return 0; @@ -531,8 +510,6 @@ static int ramzswap_ioctl_init_device(struct ramzswap *rzs) { int ret; size_t num_pages; - struct page *page; - union swap_header *swap_header; if (rzs->init_done) { pr_info("Device already initialized!\n"); @@ -566,19 +543,6 @@ static int ramzswap_ioctl_init_device(struct ramzswap *rzs) } memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); - page = alloc_page(__GFP_ZERO); - if (!page) { - pr_err("Error allocating swap header page\n"); - ret = -ENOMEM; - goto fail; - } - rzs->table[0].page = page; - rzs_set_flag(rzs, 0, RZS_UNCOMPRESSED); - - swap_header = kmap(page); - setup_swap_header(rzs, swap_header); - kunmap(page); - set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); /* ramzswap devices sort of resembles non-rotational disks */ @@ -689,11 +653,9 @@ void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index) rzs = bdev->bd_disk->private_data; ramzswap_free_page(rzs, index); rzs_stat64_inc(rzs, &rzs->stats.notify_free); - - return; } -static struct block_device_operations ramzswap_devops = { +static const struct block_device_operations ramzswap_devops = { .ioctl = ramzswap_ioctl, .swap_slot_free_notify = ramzswap_slot_free_notify, .owner = THIS_MODULE @@ -737,8 +699,14 @@ static int create_device(struct ramzswap *rzs, int device_id) /* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */ set_capacity(rzs->disk, 0); + /* + * To ensure that we always get PAGE_SIZE aligned + * and n*PAGE_SIZED sized I/O requests. + */ blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE); blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE); + blk_queue_io_min(rzs->disk->queue, PAGE_SIZE); + blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE); add_disk(rzs->disk); diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h index 63c30420df21..ad91726013bb 100644 --- a/drivers/staging/ramzswap/ramzswap_drv.h +++ b/drivers/staging/ramzswap/ramzswap_drv.h @@ -112,7 +112,8 @@ struct ramzswap { void *compress_buffer; struct table *table; spinlock_t stat64_lock; /* protect 64-bit stats */ - struct mutex lock; + struct mutex lock; /* protect compression buffers against + * concurrent writes */ struct request_queue *queue; struct gendisk *disk; int init_done; -- cgit v1.2.3 From 16a4bfb9e9dfefbd28ee170fa3e259bc88d81eb5 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Tue, 1 Jun 2010 13:31:24 +0530 Subject: Staging: Rename ramzswap files to zram Related changes: - Modify revelant Kconfig and Makefile accordingly. - Change include filenames in code. - Remove dependency on CONFIG_SWAP in Kconfig as zram usage is no longer limited to swap disks. Signed-off-by: Nitin Gupta Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 +- drivers/staging/Makefile | 2 +- drivers/staging/ramzswap/Kconfig | 21 - drivers/staging/ramzswap/Makefile | 3 - drivers/staging/ramzswap/ramzswap.txt | 51 -- drivers/staging/ramzswap/ramzswap_drv.c | 805 ------------------------------ drivers/staging/ramzswap/ramzswap_drv.h | 168 ------- drivers/staging/ramzswap/ramzswap_ioctl.h | 42 -- drivers/staging/ramzswap/xvmalloc.c | 507 ------------------- drivers/staging/ramzswap/xvmalloc.h | 30 -- drivers/staging/ramzswap/xvmalloc_int.h | 86 ---- drivers/staging/zram/Kconfig | 28 ++ drivers/staging/zram/Makefile | 3 + drivers/staging/zram/xvmalloc.c | 507 +++++++++++++++++++ drivers/staging/zram/xvmalloc.h | 30 ++ drivers/staging/zram/xvmalloc_int.h | 86 ++++ drivers/staging/zram/zram.txt | 51 ++ drivers/staging/zram/zram_drv.c | 805 ++++++++++++++++++++++++++++++ drivers/staging/zram/zram_drv.h | 168 +++++++ drivers/staging/zram/zram_ioctl.h | 42 ++ 20 files changed, 1722 insertions(+), 1715 deletions(-) delete mode 100644 drivers/staging/ramzswap/Kconfig delete mode 100644 drivers/staging/ramzswap/Makefile delete mode 100644 drivers/staging/ramzswap/ramzswap.txt delete mode 100644 drivers/staging/ramzswap/ramzswap_drv.c delete mode 100644 drivers/staging/ramzswap/ramzswap_drv.h delete mode 100644 drivers/staging/ramzswap/ramzswap_ioctl.h delete mode 100644 drivers/staging/ramzswap/xvmalloc.c delete mode 100644 drivers/staging/ramzswap/xvmalloc.h delete mode 100644 drivers/staging/ramzswap/xvmalloc_int.h create mode 100644 drivers/staging/zram/Kconfig create mode 100644 drivers/staging/zram/Makefile create mode 100644 drivers/staging/zram/xvmalloc.c create mode 100644 drivers/staging/zram/xvmalloc.h create mode 100644 drivers/staging/zram/xvmalloc_int.h create mode 100644 drivers/staging/zram/zram.txt create mode 100644 drivers/staging/zram/zram_drv.c create mode 100644 drivers/staging/zram/zram_drv.h create mode 100644 drivers/staging/zram/zram_ioctl.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d5b827ccecf8..cdd3ea348319 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -119,7 +119,7 @@ source "drivers/staging/sep/Kconfig" source "drivers/staging/iio/Kconfig" -source "drivers/staging/ramzswap/Kconfig" +source "drivers/staging/zram/Kconfig" source "drivers/staging/wlags49_h2/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 2c14f89387be..beceaff3dfdf 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_RAR_REGISTER) += rar_register/ obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ -obj-$(CONFIG_RAMZSWAP) += ramzswap/ +obj-$(CONFIG_ZRAM) += zram/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ obj-$(CONFIG_BATMAN_ADV) += batman-adv/ diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig deleted file mode 100644 index 127b3c6c9596..000000000000 --- a/drivers/staging/ramzswap/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -config RAMZSWAP - tristate "Compressed in-memory swap device (ramzswap)" - depends on SWAP - select LZO_COMPRESS - select LZO_DECOMPRESS - default n - help - Creates virtual block devices which can (only) be used as swap - disks. Pages swapped to these disks are compressed and stored in - memory itself. - - See ramzswap.txt for more information. - Project home: http://compcache.googlecode.com/ - -config RAMZSWAP_STATS - bool "Enable ramzswap stats" - depends on RAMZSWAP - default y - help - Enable statistics collection for ramzswap. This adds only a minimal - overhead. In unsure, say Y. diff --git a/drivers/staging/ramzswap/Makefile b/drivers/staging/ramzswap/Makefile deleted file mode 100644 index 507d7dc3b864..000000000000 --- a/drivers/staging/ramzswap/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -ramzswap-objs := ramzswap_drv.o xvmalloc.o - -obj-$(CONFIG_RAMZSWAP) += ramzswap.o diff --git a/drivers/staging/ramzswap/ramzswap.txt b/drivers/staging/ramzswap/ramzswap.txt deleted file mode 100644 index 9694acfeb43f..000000000000 --- a/drivers/staging/ramzswap/ramzswap.txt +++ /dev/null @@ -1,51 +0,0 @@ -ramzswap: Compressed RAM based swap device -------------------------------------------- - -Project home: http://compcache.googlecode.com/ - -* Introduction - -The ramzswap module creates RAM based block devices which can (only) be used as -swap disks. Pages swapped to these devices are compressed and stored in memory -itself. See project home for use cases, performance numbers and a lot more. - -Individual ramzswap devices are configured and initialized using rzscontrol -userspace utility as shown in examples below. See rzscontrol man page for more -details. - -* Usage - -Following shows a typical sequence of steps for using ramzswap. - -1) Load Modules: - modprobe ramzswap num_devices=4 - This creates 4 (uninitialized) devices: /dev/ramzswap{0,1,2,3} - (num_devices parameter is optional. Default: 1) - -2) Initialize: - Use rzscontrol utility to configure and initialize individual - ramzswap devices. Example: - rzscontrol /dev/ramzswap2 --init # uses default value of disksize_kb - - *See rzscontrol man page for more details and examples* - -3) Activate: - swapon /dev/ramzswap2 # or any other initialized ramzswap device - -4) Stats: - rzscontrol /dev/ramzswap2 --stats - -5) Deactivate: - swapoff /dev/ramzswap2 - -6) Reset: - rzscontrol /dev/ramzswap2 --reset - (This frees all the memory allocated for this device). - - -Please report any problems at: - - Mailing list: linux-mm-cc at laptop dot org - - Issue tracker: http://code.google.com/p/compcache/issues/list - -Nitin Gupta -ngupta@vflare.org diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c deleted file mode 100644 index 7b5cc61b3d69..000000000000 --- a/drivers/staging/ramzswap/ramzswap_drv.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#define KMSG_COMPONENT "ramzswap" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ramzswap_drv.h" - -/* Globals */ -static int ramzswap_major; -static struct ramzswap *devices; - -/* Module params (documentation at end) */ -static unsigned int num_devices; - -static int rzs_test_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) -{ - return rzs->table[index].flags & BIT(flag); -} - -static void rzs_set_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) -{ - rzs->table[index].flags |= BIT(flag); -} - -static void rzs_clear_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) -{ - rzs->table[index].flags &= ~BIT(flag); -} - -static int page_zero_filled(void *ptr) -{ - unsigned int pos; - unsigned long *page; - - page = (unsigned long *)ptr; - - for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { - if (page[pos]) - return 0; - } - - return 1; -} - -static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) -{ - if (!rzs->disksize) { - pr_info( - "disk size not provided. You can use disksize_kb module " - "param to specify size.\nUsing default: (%u%% of RAM).\n", - default_disksize_perc_ram - ); - rzs->disksize = default_disksize_perc_ram * - (totalram_bytes / 100); - } - - if (rzs->disksize > 2 * (totalram_bytes)) { - pr_info( - "There is little point creating a ramzswap of greater than " - "twice the size of memory since we expect a 2:1 compression " - "ratio. Note that ramzswap uses about 0.1%% of the size of " - "the swap device when not in use so a huge ramzswap is " - "wasteful.\n" - "\tMemory Size: %zu kB\n" - "\tSize you selected: %zu kB\n" - "Continuing anyway ...\n", - totalram_bytes >> 10, rzs->disksize - ); - } - - rzs->disksize &= PAGE_MASK; -} - -static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, - struct ramzswap_ioctl_stats *s) -{ - s->disksize = rzs->disksize; - -#if defined(CONFIG_RAMZSWAP_STATS) - { - struct ramzswap_stats *rs = &rzs->stats; - size_t succ_writes, mem_used; - unsigned int good_compress_perc = 0, no_compress_perc = 0; - - mem_used = xv_get_total_size_bytes(rzs->mem_pool) - + (rs->pages_expand << PAGE_SHIFT); - succ_writes = rzs_stat64_read(rzs, &rs->num_writes) - - rzs_stat64_read(rzs, &rs->failed_writes); - - if (succ_writes && rs->pages_stored) { - good_compress_perc = rs->good_compress * 100 - / rs->pages_stored; - no_compress_perc = rs->pages_expand * 100 - / rs->pages_stored; - } - - s->num_reads = rzs_stat64_read(rzs, &rs->num_reads); - s->num_writes = rzs_stat64_read(rzs, &rs->num_writes); - s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads); - s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes); - s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io); - s->notify_free = rzs_stat64_read(rzs, &rs->notify_free); - s->pages_zero = rs->pages_zero; - - s->good_compress_pct = good_compress_perc; - s->pages_expand_pct = no_compress_perc; - - s->pages_stored = rs->pages_stored; - s->pages_used = mem_used >> PAGE_SHIFT; - s->orig_data_size = rs->pages_stored << PAGE_SHIFT; - s->compr_data_size = rs->compr_size; - s->mem_used_total = mem_used; - } -#endif /* CONFIG_RAMZSWAP_STATS */ -} - -static void ramzswap_free_page(struct ramzswap *rzs, size_t index) -{ - u32 clen; - void *obj; - - struct page *page = rzs->table[index].page; - u32 offset = rzs->table[index].offset; - - if (unlikely(!page)) { - /* - * No memory is allocated for zero filled pages. - * Simply clear zero page flag. - */ - if (rzs_test_flag(rzs, index, RZS_ZERO)) { - rzs_clear_flag(rzs, index, RZS_ZERO); - rzs_stat_dec(&rzs->stats.pages_zero); - } - return; - } - - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { - clen = PAGE_SIZE; - __free_page(page); - rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_dec(&rzs->stats.pages_expand); - goto out; - } - - obj = kmap_atomic(page, KM_USER0) + offset; - clen = xv_get_object_size(obj) - sizeof(struct zobj_header); - kunmap_atomic(obj, KM_USER0); - - xv_free(rzs->mem_pool, page, offset); - if (clen <= PAGE_SIZE / 2) - rzs_stat_dec(&rzs->stats.good_compress); - -out: - rzs->stats.compr_size -= clen; - rzs_stat_dec(&rzs->stats.pages_stored); - - rzs->table[index].page = NULL; - rzs->table[index].offset = 0; -} - -static void handle_zero_page(struct page *page) -{ - void *user_mem; - - user_mem = kmap_atomic(page, KM_USER0); - memset(user_mem, 0, PAGE_SIZE); - kunmap_atomic(user_mem, KM_USER0); - - flush_dcache_page(page); -} - -static void handle_uncompressed_page(struct ramzswap *rzs, - struct page *page, u32 index) -{ - unsigned char *user_mem, *cmem; - - user_mem = kmap_atomic(page, KM_USER0); - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; - - memcpy(user_mem, cmem, PAGE_SIZE); - kunmap_atomic(user_mem, KM_USER0); - kunmap_atomic(cmem, KM_USER1); - - flush_dcache_page(page); -} - -static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) -{ - - int i; - u32 index; - struct bio_vec *bvec; - - rzs_stat64_inc(rzs, &rzs->stats.num_reads); - - index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - bio_for_each_segment(bvec, bio, i) { - int ret; - size_t clen; - struct page *page; - struct zobj_header *zheader; - unsigned char *user_mem, *cmem; - - page = bvec->bv_page; - - if (rzs_test_flag(rzs, index, RZS_ZERO)) { - handle_zero_page(page); - continue; - } - - /* Requested page is not present in compressed area */ - if (unlikely(!rzs->table[index].page)) { - pr_debug("Read before write: sector=%lu, size=%u", - (ulong)(bio->bi_sector), bio->bi_size); - /* Do nothing */ - continue; - } - - /* Page is stored uncompressed since it's incompressible */ - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { - handle_uncompressed_page(rzs, page, index); - continue; - } - - user_mem = kmap_atomic(page, KM_USER0); - clen = PAGE_SIZE; - - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; - - ret = lzo1x_decompress_safe( - cmem + sizeof(*zheader), - xv_get_object_size(cmem) - sizeof(*zheader), - user_mem, &clen); - - kunmap_atomic(user_mem, KM_USER0); - kunmap_atomic(cmem, KM_USER1); - - /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret != LZO_E_OK)) { - pr_err("Decompression failed! err=%d, page=%u\n", - ret, index); - rzs_stat64_inc(rzs, &rzs->stats.failed_reads); - goto out; - } - - flush_dcache_page(page); - index++; - } - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; - -out: - bio_io_error(bio); - return 0; -} - -static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) -{ - int i; - u32 index; - struct bio_vec *bvec; - - rzs_stat64_inc(rzs, &rzs->stats.num_writes); - - index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - - bio_for_each_segment(bvec, bio, i) { - int ret; - u32 offset; - size_t clen; - struct zobj_header *zheader; - struct page *page, *page_store; - unsigned char *user_mem, *cmem, *src; - - page = bvec->bv_page; - src = rzs->compress_buffer; - - /* - * System overwrites unused sectors. Free memory associated - * with this sector now. - */ - if (rzs->table[index].page || - rzs_test_flag(rzs, index, RZS_ZERO)) - ramzswap_free_page(rzs, index); - - mutex_lock(&rzs->lock); - - user_mem = kmap_atomic(page, KM_USER0); - if (page_zero_filled(user_mem)) { - kunmap_atomic(user_mem, KM_USER0); - mutex_unlock(&rzs->lock); - rzs_stat_inc(&rzs->stats.pages_zero); - rzs_set_flag(rzs, index, RZS_ZERO); - continue; - } - - ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, - rzs->compress_workmem); - - kunmap_atomic(user_mem, KM_USER0); - - if (unlikely(ret != LZO_E_OK)) { - mutex_unlock(&rzs->lock); - pr_err("Compression failed! err=%d\n", ret); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); - goto out; - } - - /* - * Page is incompressible. Store it as-is (uncompressed) - * since we do not want to return too many swap write - * errors which has side effect of hanging the system. - */ - if (unlikely(clen > max_zpage_size)) { - clen = PAGE_SIZE; - page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); - if (unlikely(!page_store)) { - mutex_unlock(&rzs->lock); - pr_info("Error allocating memory for " - "incompressible page: %u\n", index); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); - goto out; - } - - offset = 0; - rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_inc(&rzs->stats.pages_expand); - rzs->table[index].page = page_store; - src = kmap_atomic(page, KM_USER0); - goto memstore; - } - - if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), - &rzs->table[index].page, &offset, - GFP_NOIO | __GFP_HIGHMEM)) { - mutex_unlock(&rzs->lock); - pr_info("Error allocating memory for compressed " - "page: %u, size=%zu\n", index, clen); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); - goto out; - } - -memstore: - rzs->table[index].offset = offset; - - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; - -#if 0 - /* Back-reference needed for memory defragmentation */ - if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { - zheader = (struct zobj_header *)cmem; - zheader->table_idx = index; - cmem += sizeof(*zheader); - } -#endif - - memcpy(cmem, src, clen); - - kunmap_atomic(cmem, KM_USER1); - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) - kunmap_atomic(src, KM_USER0); - - /* Update stats */ - rzs->stats.compr_size += clen; - rzs_stat_inc(&rzs->stats.pages_stored); - if (clen <= PAGE_SIZE / 2) - rzs_stat_inc(&rzs->stats.good_compress); - - mutex_unlock(&rzs->lock); - index++; - } - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return 0; - -out: - bio_io_error(bio); - return 0; -} - -/* - * Check if request is within bounds and page aligned. - */ -static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio) -{ - if (unlikely( - (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) || - (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || - (bio->bi_size & (PAGE_SIZE - 1)))) { - - return 0; - } - - /* I/O request is valid */ - return 1; -} - -/* - * Handler function for all ramzswap I/O requests. - */ -static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) -{ - int ret = 0; - struct ramzswap *rzs = queue->queuedata; - - if (unlikely(!rzs->init_done)) { - bio_io_error(bio); - return 0; - } - - if (!valid_io_request(rzs, bio)) { - rzs_stat64_inc(rzs, &rzs->stats.invalid_io); - bio_io_error(bio); - return 0; - } - - switch (bio_data_dir(bio)) { - case READ: - ret = ramzswap_read(rzs, bio); - break; - - case WRITE: - ret = ramzswap_write(rzs, bio); - break; - } - - return ret; -} - -static void reset_device(struct ramzswap *rzs) -{ - size_t index; - - /* Do not accept any new I/O request */ - rzs->init_done = 0; - - /* Free various per-device buffers */ - kfree(rzs->compress_workmem); - free_pages((unsigned long)rzs->compress_buffer, 1); - - rzs->compress_workmem = NULL; - rzs->compress_buffer = NULL; - - /* Free all pages that are still in this ramzswap device */ - for (index = 0; index < rzs->disksize >> PAGE_SHIFT; index++) { - struct page *page; - u16 offset; - - page = rzs->table[index].page; - offset = rzs->table[index].offset; - - if (!page) - continue; - - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) - __free_page(page); - else - xv_free(rzs->mem_pool, page, offset); - } - - vfree(rzs->table); - rzs->table = NULL; - - xv_destroy_pool(rzs->mem_pool); - rzs->mem_pool = NULL; - - /* Reset stats */ - memset(&rzs->stats, 0, sizeof(rzs->stats)); - - rzs->disksize = 0; -} - -static int ramzswap_ioctl_init_device(struct ramzswap *rzs) -{ - int ret; - size_t num_pages; - - if (rzs->init_done) { - pr_info("Device already initialized!\n"); - return -EBUSY; - } - - ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT); - - rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); - if (!rzs->compress_workmem) { - pr_err("Error allocating compressor working memory!\n"); - ret = -ENOMEM; - goto fail; - } - - rzs->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1); - if (!rzs->compress_buffer) { - pr_err("Error allocating compressor buffer space\n"); - ret = -ENOMEM; - goto fail; - } - - num_pages = rzs->disksize >> PAGE_SHIFT; - rzs->table = vmalloc(num_pages * sizeof(*rzs->table)); - if (!rzs->table) { - pr_err("Error allocating ramzswap address table\n"); - /* To prevent accessing table entries during cleanup */ - rzs->disksize = 0; - ret = -ENOMEM; - goto fail; - } - memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); - - set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); - - /* ramzswap devices sort of resembles non-rotational disks */ - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue); - - rzs->mem_pool = xv_create_pool(); - if (!rzs->mem_pool) { - pr_err("Error creating memory pool\n"); - ret = -ENOMEM; - goto fail; - } - - rzs->init_done = 1; - - pr_debug("Initialization done!\n"); - return 0; - -fail: - reset_device(rzs); - - pr_err("Initialization failed: err=%d\n", ret); - return ret; -} - -static int ramzswap_ioctl_reset_device(struct ramzswap *rzs) -{ - if (rzs->init_done) - reset_device(rzs); - - return 0; -} - -static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int ret = 0; - size_t disksize_kb; - - struct ramzswap *rzs = bdev->bd_disk->private_data; - - switch (cmd) { - case RZSIO_SET_DISKSIZE_KB: - if (rzs->init_done) { - ret = -EBUSY; - goto out; - } - if (copy_from_user(&disksize_kb, (void *)arg, - _IOC_SIZE(cmd))) { - ret = -EFAULT; - goto out; - } - rzs->disksize = disksize_kb << 10; - pr_info("Disk size set to %zu kB\n", disksize_kb); - break; - - case RZSIO_GET_STATS: - { - struct ramzswap_ioctl_stats *stats; - if (!rzs->init_done) { - ret = -ENOTTY; - goto out; - } - stats = kzalloc(sizeof(*stats), GFP_KERNEL); - if (!stats) { - ret = -ENOMEM; - goto out; - } - ramzswap_ioctl_get_stats(rzs, stats); - if (copy_to_user((void *)arg, stats, sizeof(*stats))) { - kfree(stats); - ret = -EFAULT; - goto out; - } - kfree(stats); - break; - } - case RZSIO_INIT: - ret = ramzswap_ioctl_init_device(rzs); - break; - - case RZSIO_RESET: - /* Do not reset an active device! */ - if (bdev->bd_holders) { - ret = -EBUSY; - goto out; - } - - /* Make sure all pending I/O is finished */ - if (bdev) - fsync_bdev(bdev); - - ret = ramzswap_ioctl_reset_device(rzs); - break; - - default: - pr_info("Invalid ioctl %u\n", cmd); - ret = -ENOTTY; - } - -out: - return ret; -} - -void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index) -{ - struct ramzswap *rzs; - - rzs = bdev->bd_disk->private_data; - ramzswap_free_page(rzs, index); - rzs_stat64_inc(rzs, &rzs->stats.notify_free); -} - -static const struct block_device_operations ramzswap_devops = { - .ioctl = ramzswap_ioctl, - .swap_slot_free_notify = ramzswap_slot_free_notify, - .owner = THIS_MODULE -}; - -static int create_device(struct ramzswap *rzs, int device_id) -{ - int ret = 0; - - mutex_init(&rzs->lock); - spin_lock_init(&rzs->stat64_lock); - - rzs->queue = blk_alloc_queue(GFP_KERNEL); - if (!rzs->queue) { - pr_err("Error allocating disk queue for device %d\n", - device_id); - ret = -ENOMEM; - goto out; - } - - blk_queue_make_request(rzs->queue, ramzswap_make_request); - rzs->queue->queuedata = rzs; - - /* gendisk structure */ - rzs->disk = alloc_disk(1); - if (!rzs->disk) { - blk_cleanup_queue(rzs->queue); - pr_warning("Error allocating disk structure for device %d\n", - device_id); - ret = -ENOMEM; - goto out; - } - - rzs->disk->major = ramzswap_major; - rzs->disk->first_minor = device_id; - rzs->disk->fops = &ramzswap_devops; - rzs->disk->queue = rzs->queue; - rzs->disk->private_data = rzs; - snprintf(rzs->disk->disk_name, 16, "ramzswap%d", device_id); - - /* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */ - set_capacity(rzs->disk, 0); - - /* - * To ensure that we always get PAGE_SIZE aligned - * and n*PAGE_SIZED sized I/O requests. - */ - blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE); - blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE); - blk_queue_io_min(rzs->disk->queue, PAGE_SIZE); - blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE); - - add_disk(rzs->disk); - - rzs->init_done = 0; - -out: - return ret; -} - -static void destroy_device(struct ramzswap *rzs) -{ - if (rzs->disk) { - del_gendisk(rzs->disk); - put_disk(rzs->disk); - } - - if (rzs->queue) - blk_cleanup_queue(rzs->queue); -} - -static int __init ramzswap_init(void) -{ - int ret, dev_id; - - if (num_devices > max_num_devices) { - pr_warning("Invalid value for num_devices: %u\n", - num_devices); - ret = -EINVAL; - goto out; - } - - ramzswap_major = register_blkdev(0, "ramzswap"); - if (ramzswap_major <= 0) { - pr_warning("Unable to get major number\n"); - ret = -EBUSY; - goto out; - } - - if (!num_devices) { - pr_info("num_devices not specified. Using default: 1\n"); - num_devices = 1; - } - - /* Allocate the device array and initialize each one */ - pr_info("Creating %u devices ...\n", num_devices); - devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL); - if (!devices) { - ret = -ENOMEM; - goto unregister; - } - - for (dev_id = 0; dev_id < num_devices; dev_id++) { - ret = create_device(&devices[dev_id], dev_id); - if (ret) - goto free_devices; - } - - return 0; - -free_devices: - while (dev_id) - destroy_device(&devices[--dev_id]); -unregister: - unregister_blkdev(ramzswap_major, "ramzswap"); -out: - return ret; -} - -static void __exit ramzswap_exit(void) -{ - int i; - struct ramzswap *rzs; - - for (i = 0; i < num_devices; i++) { - rzs = &devices[i]; - - destroy_device(rzs); - if (rzs->init_done) - reset_device(rzs); - } - - unregister_blkdev(ramzswap_major, "ramzswap"); - - kfree(devices); - pr_debug("Cleanup done!\n"); -} - -module_param(num_devices, uint, 0); -MODULE_PARM_DESC(num_devices, "Number of ramzswap devices"); - -module_init(ramzswap_init); -module_exit(ramzswap_exit); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Nitin Gupta "); -MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h deleted file mode 100644 index ad91726013bb..000000000000 --- a/drivers/staging/ramzswap/ramzswap_drv.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#ifndef _RAMZSWAP_DRV_H_ -#define _RAMZSWAP_DRV_H_ - -#include -#include - -#include "ramzswap_ioctl.h" -#include "xvmalloc.h" - -/* - * Some arbitrary value. This is just to catch - * invalid value for num_devices module parameter. - */ -static const unsigned max_num_devices = 32; - -/* - * Stored at beginning of each compressed object. - * - * It stores back-reference to table entry which points to this - * object. This is required to support memory defragmentation. - */ -struct zobj_header { -#if 0 - u32 table_idx; -#endif -}; - -/*-- Configurable parameters */ - -/* Default ramzswap disk size: 25% of total RAM */ -static const unsigned default_disksize_perc_ram = 25; - -/* - * Pages that compress to size greater than this are stored - * uncompressed in memory. - */ -static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3; - -/* - * NOTE: max_zpage_size must be less than or equal to: - * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) - * otherwise, xv_malloc() would always return failure. - */ - -/*-- End of configurable params */ - -#define SECTOR_SHIFT 9 -#define SECTOR_SIZE (1 << SECTOR_SHIFT) -#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) -#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) - -/* Flags for ramzswap pages (table[page_no].flags) */ -enum rzs_pageflags { - /* Page is stored uncompressed */ - RZS_UNCOMPRESSED, - - /* Page consists entirely of zeros */ - RZS_ZERO, - - __NR_RZS_PAGEFLAGS, -}; - -/*-- Data structures */ - -/* - * Allocated for each swap slot, indexed by page no. - * These table entries must fit exactly in a page. - */ -struct table { - struct page *page; - u16 offset; - u8 count; /* object ref count (not yet used) */ - u8 flags; -} __attribute__((aligned(4))); - -struct ramzswap_stats { - /* basic stats */ - size_t compr_size; /* compressed size of pages stored - - * needed to enforce memlimit */ - /* more stats */ -#if defined(CONFIG_RAMZSWAP_STATS) - u64 num_reads; /* failed + successful */ - u64 num_writes; /* --do-- */ - u64 failed_reads; /* should NEVER! happen */ - u64 failed_writes; /* can happen when memory is too low */ - u64 invalid_io; /* non-swap I/O requests */ - u64 notify_free; /* no. of swap slot free notifications */ - u32 pages_zero; /* no. of zero filled pages */ - u32 pages_stored; /* no. of pages currently stored */ - u32 good_compress; /* % of pages with compression ratio<=50% */ - u32 pages_expand; /* % of incompressible pages */ -#endif -}; - -struct ramzswap { - struct xv_pool *mem_pool; - void *compress_workmem; - void *compress_buffer; - struct table *table; - spinlock_t stat64_lock; /* protect 64-bit stats */ - struct mutex lock; /* protect compression buffers against - * concurrent writes */ - struct request_queue *queue; - struct gendisk *disk; - int init_done; - /* - * This is limit on amount of *uncompressed* worth of data - * we can hold. When backing swap device is provided, it is - * set equal to device size. - */ - size_t disksize; /* bytes */ - - struct ramzswap_stats stats; -}; - -/*-- */ - -/* Debugging and Stats */ -#if defined(CONFIG_RAMZSWAP_STATS) -static void rzs_stat_inc(u32 *v) -{ - *v = *v + 1; -} - -static void rzs_stat_dec(u32 *v) -{ - *v = *v - 1; -} - -static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v) -{ - spin_lock(&rzs->stat64_lock); - *v = *v + 1; - spin_unlock(&rzs->stat64_lock); -} - -static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v) -{ - u64 val; - - spin_lock(&rzs->stat64_lock); - val = *v; - spin_unlock(&rzs->stat64_lock); - - return val; -} -#else -#define rzs_stat_inc(v) -#define rzs_stat_dec(v) -#define rzs_stat64_inc(r, v) -#define rzs_stat64_read(r, v) -#endif /* CONFIG_RAMZSWAP_STATS */ - -#endif diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/ramzswap/ramzswap_ioctl.h deleted file mode 100644 index db94bcb42967..000000000000 --- a/drivers/staging/ramzswap/ramzswap_ioctl.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Compressed RAM based swap device - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - * - * Project home: http://compcache.googlecode.com - */ - -#ifndef _RAMZSWAP_IOCTL_H_ -#define _RAMZSWAP_IOCTL_H_ - -struct ramzswap_ioctl_stats { - u64 disksize; /* user specified or equal to backing swap - * size (if present) */ - u64 num_reads; /* failed + successful */ - u64 num_writes; /* --do-- */ - u64 failed_reads; /* should NEVER! happen */ - u64 failed_writes; /* can happen when memory is too low */ - u64 invalid_io; /* non-swap I/O requests */ - u64 notify_free; /* no. of swap slot free notifications */ - u32 pages_zero; /* no. of zero filled pages */ - u32 good_compress_pct; /* no. of pages with compression ratio<=50% */ - u32 pages_expand_pct; /* no. of incompressible pages */ - u32 pages_stored; - u32 pages_used; - u64 orig_data_size; - u64 compr_data_size; - u64 mem_used_total; -} __attribute__ ((packed, aligned(4))); - -#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) -#define RZSIO_GET_STATS _IOR('z', 1, struct ramzswap_ioctl_stats) -#define RZSIO_INIT _IO('z', 2) -#define RZSIO_RESET _IO('z', 3) - -#endif diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/ramzswap/xvmalloc.c deleted file mode 100644 index 3fdbb8ada827..000000000000 --- a/drivers/staging/ramzswap/xvmalloc.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include "xvmalloc.h" -#include "xvmalloc_int.h" - -static void stat_inc(u64 *value) -{ - *value = *value + 1; -} - -static void stat_dec(u64 *value) -{ - *value = *value - 1; -} - -static int test_flag(struct block_header *block, enum blockflags flag) -{ - return block->prev & BIT(flag); -} - -static void set_flag(struct block_header *block, enum blockflags flag) -{ - block->prev |= BIT(flag); -} - -static void clear_flag(struct block_header *block, enum blockflags flag) -{ - block->prev &= ~BIT(flag); -} - -/* - * Given pair, provide a derefrencable pointer. - * This is called from xv_malloc/xv_free path, so it - * needs to be fast. - */ -static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type) -{ - unsigned char *base; - - base = kmap_atomic(page, type); - return base + offset; -} - -static void put_ptr_atomic(void *ptr, enum km_type type) -{ - kunmap_atomic(ptr, type); -} - -static u32 get_blockprev(struct block_header *block) -{ - return block->prev & PREV_MASK; -} - -static void set_blockprev(struct block_header *block, u16 new_offset) -{ - block->prev = new_offset | (block->prev & FLAGS_MASK); -} - -static struct block_header *BLOCK_NEXT(struct block_header *block) -{ - return (struct block_header *) - ((char *)block + block->size + XV_ALIGN); -} - -/* - * Get index of free list containing blocks of maximum size - * which is less than or equal to given size. - */ -static u32 get_index_for_insert(u32 size) -{ - if (unlikely(size > XV_MAX_ALLOC_SIZE)) - size = XV_MAX_ALLOC_SIZE; - size &= ~FL_DELTA_MASK; - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/* - * Get index of free list having blocks of size greater than - * or equal to requested size. - */ -static u32 get_index(u32 size) -{ - if (unlikely(size < XV_MIN_ALLOC_SIZE)) - size = XV_MIN_ALLOC_SIZE; - size = ALIGN(size, FL_DELTA); - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/** - * find_block - find block of at least given size - * @pool: memory pool to search from - * @size: size of block required - * @page: page containing required block - * @offset: offset within the page where block is located. - * - * Searches two level bitmap to locate block of at least - * the given size. If such a block is found, it provides - * to identify this block and returns index - * in freelist where we found this block. - * Otherwise, returns 0 and params are not touched. - */ -static u32 find_block(struct xv_pool *pool, u32 size, - struct page **page, u32 *offset) -{ - ulong flbitmap, slbitmap; - u32 flindex, slindex, slbitstart; - - /* There are no free blocks in this pool */ - if (!pool->flbitmap) - return 0; - - /* Get freelist index correspoding to this size */ - slindex = get_index(size); - slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; - slbitstart = slindex % BITS_PER_LONG; - - /* - * If freelist is not empty at this index, we found the - * block - head of this list. This is approximate best-fit match. - */ - if (test_bit(slbitstart, &slbitmap)) { - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* - * No best-fit found. Search a bit further in bitmap for a free block. - * Second level bitmap consists of series of 32-bit chunks. Search - * further in the chunk where we expected a best-fit, starting from - * index location found above. - */ - slbitstart++; - slbitmap >>= slbitstart; - - /* Skip this search if we were already at end of this bitmap chunk */ - if ((slbitstart != BITS_PER_LONG) && slbitmap) { - slindex += __ffs(slbitmap) + 1; - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* Now do a full two-level bitmap search to find next nearest fit */ - flindex = slindex / BITS_PER_LONG; - - flbitmap = (pool->flbitmap) >> (flindex + 1); - if (!flbitmap) - return 0; - - flindex += __ffs(flbitmap) + 1; - slbitmap = pool->slbitmap[flindex]; - slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - - return slindex; -} - -/* - * Insert block at in freelist of given pool. - * freelist used depends on block size. - */ -static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block) -{ - u32 flindex, slindex; - struct block_header *nextblock; - - slindex = get_index_for_insert(block->size); - flindex = slindex / BITS_PER_LONG; - - block->link.prev_page = 0; - block->link.prev_offset = 0; - block->link.next_page = pool->freelist[slindex].page; - block->link.next_offset = pool->freelist[slindex].offset; - pool->freelist[slindex].page = page; - pool->freelist[slindex].offset = offset; - - if (block->link.next_page) { - nextblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - nextblock->link.prev_page = page; - nextblock->link.prev_offset = offset; - put_ptr_atomic(nextblock, KM_USER1); - } - - __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); - __set_bit(flindex, &pool->flbitmap); -} - -/* - * Remove block from head of freelist. Index 'slindex' identifies the freelist. - */ -static void remove_block_head(struct xv_pool *pool, - struct block_header *block, u32 slindex) -{ - struct block_header *tmpblock; - u32 flindex = slindex / BITS_PER_LONG; - - pool->freelist[slindex].page = block->link.next_page; - pool->freelist[slindex].offset = block->link.next_offset; - block->link.prev_page = 0; - block->link.prev_offset = 0; - - if (!pool->freelist[slindex].page) { - __clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); - if (!pool->slbitmap[flindex]) - __clear_bit(flindex, &pool->flbitmap); - } else { - /* - * DEBUG ONLY: We need not reinitialize freelist head previous - * pointer to 0 - we never depend on its value. But just for - * sanity, lets do it. - */ - tmpblock = get_ptr_atomic(pool->freelist[slindex].page, - pool->freelist[slindex].offset, KM_USER1); - tmpblock->link.prev_page = 0; - tmpblock->link.prev_offset = 0; - put_ptr_atomic(tmpblock, KM_USER1); - } -} - -/* - * Remove block from freelist. Index 'slindex' identifies the freelist. - */ -static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block, u32 slindex) -{ - u32 flindex; - struct block_header *tmpblock; - - if (pool->freelist[slindex].page == page - && pool->freelist[slindex].offset == offset) { - remove_block_head(pool, block, slindex); - return; - } - - flindex = slindex / BITS_PER_LONG; - - if (block->link.prev_page) { - tmpblock = get_ptr_atomic(block->link.prev_page, - block->link.prev_offset, KM_USER1); - tmpblock->link.next_page = block->link.next_page; - tmpblock->link.next_offset = block->link.next_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } - - if (block->link.next_page) { - tmpblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - tmpblock->link.prev_page = block->link.prev_page; - tmpblock->link.prev_offset = block->link.prev_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } -} - -/* - * Allocate a page and add it to freelist of given pool. - */ -static int grow_pool(struct xv_pool *pool, gfp_t flags) -{ - struct page *page; - struct block_header *block; - - page = alloc_page(flags); - if (unlikely(!page)) - return -ENOMEM; - - stat_inc(&pool->total_pages); - - spin_lock(&pool->lock); - block = get_ptr_atomic(page, 0, KM_USER0); - - block->size = PAGE_SIZE - XV_ALIGN; - set_flag(block, BLOCK_FREE); - clear_flag(block, PREV_FREE); - set_blockprev(block, 0); - - insert_block(pool, page, 0, block); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - return 0; -} - -/* - * Create a memory pool. Allocates freelist, bitmaps and other - * per-pool metadata. - */ -struct xv_pool *xv_create_pool(void) -{ - u32 ovhd_size; - struct xv_pool *pool; - - ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); - pool = kzalloc(ovhd_size, GFP_KERNEL); - if (!pool) - return NULL; - - spin_lock_init(&pool->lock); - - return pool; -} - -void xv_destroy_pool(struct xv_pool *pool) -{ - kfree(pool); -} - -/** - * xv_malloc - Allocate block of given size from pool. - * @pool: pool to allocate from - * @size: size of block to allocate - * @page: page no. that holds the object - * @offset: location of object within page - * - * On success, identifies block allocated - * and 0 is returned. On failure, is set to - * 0 and -ENOMEM is returned. - * - * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. - */ -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags) -{ - int error; - u32 index, tmpsize, origsize, tmpoffset; - struct block_header *block, *tmpblock; - - *page = NULL; - *offset = 0; - origsize = size; - - if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) - return -ENOMEM; - - size = ALIGN(size, XV_ALIGN); - - spin_lock(&pool->lock); - - index = find_block(pool, size, page, offset); - - if (!*page) { - spin_unlock(&pool->lock); - if (flags & GFP_NOWAIT) - return -ENOMEM; - error = grow_pool(pool, flags); - if (unlikely(error)) - return error; - - spin_lock(&pool->lock); - index = find_block(pool, size, page, offset); - } - - if (!*page) { - spin_unlock(&pool->lock); - return -ENOMEM; - } - - block = get_ptr_atomic(*page, *offset, KM_USER0); - - remove_block_head(pool, block, index); - - /* Split the block if required */ - tmpoffset = *offset + size + XV_ALIGN; - tmpsize = block->size - size; - tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); - if (tmpsize) { - tmpblock->size = tmpsize - XV_ALIGN; - set_flag(tmpblock, BLOCK_FREE); - clear_flag(tmpblock, PREV_FREE); - - set_blockprev(tmpblock, *offset); - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, *page, tmpoffset, tmpblock); - - if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(tmpblock); - set_blockprev(tmpblock, tmpoffset); - } - } else { - /* This block is exact fit */ - if (tmpoffset != PAGE_SIZE) - clear_flag(tmpblock, PREV_FREE); - } - - block->size = origsize; - clear_flag(block, BLOCK_FREE); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - *offset += XV_ALIGN; - - return 0; -} - -/* - * Free block identified with - */ -void xv_free(struct xv_pool *pool, struct page *page, u32 offset) -{ - void *page_start; - struct block_header *block, *tmpblock; - - offset -= XV_ALIGN; - - spin_lock(&pool->lock); - - page_start = get_ptr_atomic(page, 0, KM_USER0); - block = (struct block_header *)((char *)page_start + offset); - - /* Catch double free bugs */ - BUG_ON(test_flag(block, BLOCK_FREE)); - - block->size = ALIGN(block->size, XV_ALIGN); - - tmpblock = BLOCK_NEXT(block); - if (offset + block->size + XV_ALIGN == PAGE_SIZE) - tmpblock = NULL; - - /* Merge next block if its free */ - if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { - /* - * Blocks smaller than XV_MIN_ALLOC_SIZE - * are not inserted in any free list. - */ - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { - remove_block(pool, page, - offset + block->size + XV_ALIGN, tmpblock, - get_index_for_insert(tmpblock->size)); - } - block->size += tmpblock->size + XV_ALIGN; - } - - /* Merge previous block if its free */ - if (test_flag(block, PREV_FREE)) { - tmpblock = (struct block_header *)((char *)(page_start) + - get_blockprev(block)); - offset = offset - tmpblock->size - XV_ALIGN; - - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - remove_block(pool, page, offset, tmpblock, - get_index_for_insert(tmpblock->size)); - - tmpblock->size += block->size + XV_ALIGN; - block = tmpblock; - } - - /* No used objects in this page. Free it. */ - if (block->size == PAGE_SIZE - XV_ALIGN) { - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); - - __free_page(page); - stat_dec(&pool->total_pages); - return; - } - - set_flag(block, BLOCK_FREE); - if (block->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, page, offset, block); - - if (offset + block->size + XV_ALIGN != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(block); - set_flag(tmpblock, PREV_FREE); - set_blockprev(tmpblock, offset); - } - - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); -} - -u32 xv_get_object_size(void *obj) -{ - struct block_header *blk; - - blk = (struct block_header *)((char *)(obj) - XV_ALIGN); - return blk->size; -} - -/* - * Returns total memory used by allocator (userdata + metadata) - */ -u64 xv_get_total_size_bytes(struct xv_pool *pool) -{ - return pool->total_pages << PAGE_SHIFT; -} diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/ramzswap/xvmalloc.h deleted file mode 100644 index 5b1a81aa5faf..000000000000 --- a/drivers/staging/ramzswap/xvmalloc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_H_ -#define _XV_MALLOC_H_ - -#include - -struct xv_pool; - -struct xv_pool *xv_create_pool(void); -void xv_destroy_pool(struct xv_pool *pool); - -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags); -void xv_free(struct xv_pool *pool, struct page *page, u32 offset); - -u32 xv_get_object_size(void *obj); -u64 xv_get_total_size_bytes(struct xv_pool *pool); - -#endif diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/ramzswap/xvmalloc_int.h deleted file mode 100644 index e23ed5c8b8e4..000000000000 --- a/drivers/staging/ramzswap/xvmalloc_int.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_INT_H_ -#define _XV_MALLOC_INT_H_ - -#include -#include - -/* User configurable params */ - -/* Must be power of two */ -#define XV_ALIGN_SHIFT 2 -#define XV_ALIGN (1 << XV_ALIGN_SHIFT) -#define XV_ALIGN_MASK (XV_ALIGN - 1) - -/* This must be greater than sizeof(link_free) */ -#define XV_MIN_ALLOC_SIZE 32 -#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) - -/* Free lists are separated by FL_DELTA bytes */ -#define FL_DELTA_SHIFT 3 -#define FL_DELTA (1 << FL_DELTA_SHIFT) -#define FL_DELTA_MASK (FL_DELTA - 1) -#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ - / FL_DELTA + 1) - -#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) - -/* End of user params */ - -enum blockflags { - BLOCK_FREE, - PREV_FREE, - __NR_BLOCKFLAGS, -}; - -#define FLAGS_MASK XV_ALIGN_MASK -#define PREV_MASK (~FLAGS_MASK) - -struct freelist_entry { - struct page *page; - u16 offset; - u16 pad; -}; - -struct link_free { - struct page *prev_page; - struct page *next_page; - u16 prev_offset; - u16 next_offset; -}; - -struct block_header { - union { - /* This common header must be XV_ALIGN bytes */ - u8 common[XV_ALIGN]; - struct { - u16 size; - u16 prev; - }; - }; - struct link_free link; -}; - -struct xv_pool { - ulong flbitmap; - ulong slbitmap[MAX_FLI]; - spinlock_t lock; - - struct freelist_entry freelist[NUM_FREE_LISTS]; - - /* stats */ - u64 total_pages; -}; - -#endif diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig new file mode 100644 index 000000000000..5bcfe16feb19 --- /dev/null +++ b/drivers/staging/zram/Kconfig @@ -0,0 +1,28 @@ +config ZRAM + tristate "Compressed RAM block device support" + select LZO_COMPRESS + select LZO_DECOMPRESS + default n + help + Creates virtual block devices called /dev/zramX (X = 0, 1, ...). + Pages written to these disks are compressed and stored in memory + itself. These disks allow very fast I/O and compression provides + good amounts of memory savings. + + It has several use cases, for example: /tmp storage, use as swap + disks and maybe many more. + + See zram.txt for more information. + Project home: http://compcache.googlecode.com/ + +config ZRAM_STATS + bool "Enable statistics for compressed RAM disks" + depends on ZRAM + default y + help + Enable statistics collection for compressed RAM devices. Statistics + are exported through ioctl interface, so you have to use zramconfig + program to get them. This adds only a minimal overhead. + + If unsure, say Y. + diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile new file mode 100644 index 000000000000..b2c087aa105e --- /dev/null +++ b/drivers/staging/zram/Makefile @@ -0,0 +1,3 @@ +zram-objs := zram_drv.o xvmalloc.o + +obj-$(CONFIG_ZRAM) += zram.o diff --git a/drivers/staging/zram/xvmalloc.c b/drivers/staging/zram/xvmalloc.c new file mode 100644 index 000000000000..3fdbb8ada827 --- /dev/null +++ b/drivers/staging/zram/xvmalloc.c @@ -0,0 +1,507 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "xvmalloc.h" +#include "xvmalloc_int.h" + +static void stat_inc(u64 *value) +{ + *value = *value + 1; +} + +static void stat_dec(u64 *value) +{ + *value = *value - 1; +} + +static int test_flag(struct block_header *block, enum blockflags flag) +{ + return block->prev & BIT(flag); +} + +static void set_flag(struct block_header *block, enum blockflags flag) +{ + block->prev |= BIT(flag); +} + +static void clear_flag(struct block_header *block, enum blockflags flag) +{ + block->prev &= ~BIT(flag); +} + +/* + * Given pair, provide a derefrencable pointer. + * This is called from xv_malloc/xv_free path, so it + * needs to be fast. + */ +static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type) +{ + unsigned char *base; + + base = kmap_atomic(page, type); + return base + offset; +} + +static void put_ptr_atomic(void *ptr, enum km_type type) +{ + kunmap_atomic(ptr, type); +} + +static u32 get_blockprev(struct block_header *block) +{ + return block->prev & PREV_MASK; +} + +static void set_blockprev(struct block_header *block, u16 new_offset) +{ + block->prev = new_offset | (block->prev & FLAGS_MASK); +} + +static struct block_header *BLOCK_NEXT(struct block_header *block) +{ + return (struct block_header *) + ((char *)block + block->size + XV_ALIGN); +} + +/* + * Get index of free list containing blocks of maximum size + * which is less than or equal to given size. + */ +static u32 get_index_for_insert(u32 size) +{ + if (unlikely(size > XV_MAX_ALLOC_SIZE)) + size = XV_MAX_ALLOC_SIZE; + size &= ~FL_DELTA_MASK; + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/* + * Get index of free list having blocks of size greater than + * or equal to requested size. + */ +static u32 get_index(u32 size) +{ + if (unlikely(size < XV_MIN_ALLOC_SIZE)) + size = XV_MIN_ALLOC_SIZE; + size = ALIGN(size, FL_DELTA); + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/** + * find_block - find block of at least given size + * @pool: memory pool to search from + * @size: size of block required + * @page: page containing required block + * @offset: offset within the page where block is located. + * + * Searches two level bitmap to locate block of at least + * the given size. If such a block is found, it provides + * to identify this block and returns index + * in freelist where we found this block. + * Otherwise, returns 0 and params are not touched. + */ +static u32 find_block(struct xv_pool *pool, u32 size, + struct page **page, u32 *offset) +{ + ulong flbitmap, slbitmap; + u32 flindex, slindex, slbitstart; + + /* There are no free blocks in this pool */ + if (!pool->flbitmap) + return 0; + + /* Get freelist index correspoding to this size */ + slindex = get_index(size); + slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; + slbitstart = slindex % BITS_PER_LONG; + + /* + * If freelist is not empty at this index, we found the + * block - head of this list. This is approximate best-fit match. + */ + if (test_bit(slbitstart, &slbitmap)) { + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* + * No best-fit found. Search a bit further in bitmap for a free block. + * Second level bitmap consists of series of 32-bit chunks. Search + * further in the chunk where we expected a best-fit, starting from + * index location found above. + */ + slbitstart++; + slbitmap >>= slbitstart; + + /* Skip this search if we were already at end of this bitmap chunk */ + if ((slbitstart != BITS_PER_LONG) && slbitmap) { + slindex += __ffs(slbitmap) + 1; + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* Now do a full two-level bitmap search to find next nearest fit */ + flindex = slindex / BITS_PER_LONG; + + flbitmap = (pool->flbitmap) >> (flindex + 1); + if (!flbitmap) + return 0; + + flindex += __ffs(flbitmap) + 1; + slbitmap = pool->slbitmap[flindex]; + slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); + *page = pool->freelist[slindex].page; + *offset = pool->freelist[slindex].offset; + + return slindex; +} + +/* + * Insert block at in freelist of given pool. + * freelist used depends on block size. + */ +static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block) +{ + u32 flindex, slindex; + struct block_header *nextblock; + + slindex = get_index_for_insert(block->size); + flindex = slindex / BITS_PER_LONG; + + block->link.prev_page = 0; + block->link.prev_offset = 0; + block->link.next_page = pool->freelist[slindex].page; + block->link.next_offset = pool->freelist[slindex].offset; + pool->freelist[slindex].page = page; + pool->freelist[slindex].offset = offset; + + if (block->link.next_page) { + nextblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset, KM_USER1); + nextblock->link.prev_page = page; + nextblock->link.prev_offset = offset; + put_ptr_atomic(nextblock, KM_USER1); + } + + __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + __set_bit(flindex, &pool->flbitmap); +} + +/* + * Remove block from head of freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block_head(struct xv_pool *pool, + struct block_header *block, u32 slindex) +{ + struct block_header *tmpblock; + u32 flindex = slindex / BITS_PER_LONG; + + pool->freelist[slindex].page = block->link.next_page; + pool->freelist[slindex].offset = block->link.next_offset; + block->link.prev_page = 0; + block->link.prev_offset = 0; + + if (!pool->freelist[slindex].page) { + __clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + if (!pool->slbitmap[flindex]) + __clear_bit(flindex, &pool->flbitmap); + } else { + /* + * DEBUG ONLY: We need not reinitialize freelist head previous + * pointer to 0 - we never depend on its value. But just for + * sanity, lets do it. + */ + tmpblock = get_ptr_atomic(pool->freelist[slindex].page, + pool->freelist[slindex].offset, KM_USER1); + tmpblock->link.prev_page = 0; + tmpblock->link.prev_offset = 0; + put_ptr_atomic(tmpblock, KM_USER1); + } +} + +/* + * Remove block from freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, + struct block_header *block, u32 slindex) +{ + u32 flindex; + struct block_header *tmpblock; + + if (pool->freelist[slindex].page == page + && pool->freelist[slindex].offset == offset) { + remove_block_head(pool, block, slindex); + return; + } + + flindex = slindex / BITS_PER_LONG; + + if (block->link.prev_page) { + tmpblock = get_ptr_atomic(block->link.prev_page, + block->link.prev_offset, KM_USER1); + tmpblock->link.next_page = block->link.next_page; + tmpblock->link.next_offset = block->link.next_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } + + if (block->link.next_page) { + tmpblock = get_ptr_atomic(block->link.next_page, + block->link.next_offset, KM_USER1); + tmpblock->link.prev_page = block->link.prev_page; + tmpblock->link.prev_offset = block->link.prev_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } +} + +/* + * Allocate a page and add it to freelist of given pool. + */ +static int grow_pool(struct xv_pool *pool, gfp_t flags) +{ + struct page *page; + struct block_header *block; + + page = alloc_page(flags); + if (unlikely(!page)) + return -ENOMEM; + + stat_inc(&pool->total_pages); + + spin_lock(&pool->lock); + block = get_ptr_atomic(page, 0, KM_USER0); + + block->size = PAGE_SIZE - XV_ALIGN; + set_flag(block, BLOCK_FREE); + clear_flag(block, PREV_FREE); + set_blockprev(block, 0); + + insert_block(pool, page, 0, block); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + return 0; +} + +/* + * Create a memory pool. Allocates freelist, bitmaps and other + * per-pool metadata. + */ +struct xv_pool *xv_create_pool(void) +{ + u32 ovhd_size; + struct xv_pool *pool; + + ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); + pool = kzalloc(ovhd_size, GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + return pool; +} + +void xv_destroy_pool(struct xv_pool *pool) +{ + kfree(pool); +} + +/** + * xv_malloc - Allocate block of given size from pool. + * @pool: pool to allocate from + * @size: size of block to allocate + * @page: page no. that holds the object + * @offset: location of object within page + * + * On success, identifies block allocated + * and 0 is returned. On failure, is set to + * 0 and -ENOMEM is returned. + * + * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. + */ +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags) +{ + int error; + u32 index, tmpsize, origsize, tmpoffset; + struct block_header *block, *tmpblock; + + *page = NULL; + *offset = 0; + origsize = size; + + if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) + return -ENOMEM; + + size = ALIGN(size, XV_ALIGN); + + spin_lock(&pool->lock); + + index = find_block(pool, size, page, offset); + + if (!*page) { + spin_unlock(&pool->lock); + if (flags & GFP_NOWAIT) + return -ENOMEM; + error = grow_pool(pool, flags); + if (unlikely(error)) + return error; + + spin_lock(&pool->lock); + index = find_block(pool, size, page, offset); + } + + if (!*page) { + spin_unlock(&pool->lock); + return -ENOMEM; + } + + block = get_ptr_atomic(*page, *offset, KM_USER0); + + remove_block_head(pool, block, index); + + /* Split the block if required */ + tmpoffset = *offset + size + XV_ALIGN; + tmpsize = block->size - size; + tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); + if (tmpsize) { + tmpblock->size = tmpsize - XV_ALIGN; + set_flag(tmpblock, BLOCK_FREE); + clear_flag(tmpblock, PREV_FREE); + + set_blockprev(tmpblock, *offset); + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, *page, tmpoffset, tmpblock); + + if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(tmpblock); + set_blockprev(tmpblock, tmpoffset); + } + } else { + /* This block is exact fit */ + if (tmpoffset != PAGE_SIZE) + clear_flag(tmpblock, PREV_FREE); + } + + block->size = origsize; + clear_flag(block, BLOCK_FREE); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + *offset += XV_ALIGN; + + return 0; +} + +/* + * Free block identified with + */ +void xv_free(struct xv_pool *pool, struct page *page, u32 offset) +{ + void *page_start; + struct block_header *block, *tmpblock; + + offset -= XV_ALIGN; + + spin_lock(&pool->lock); + + page_start = get_ptr_atomic(page, 0, KM_USER0); + block = (struct block_header *)((char *)page_start + offset); + + /* Catch double free bugs */ + BUG_ON(test_flag(block, BLOCK_FREE)); + + block->size = ALIGN(block->size, XV_ALIGN); + + tmpblock = BLOCK_NEXT(block); + if (offset + block->size + XV_ALIGN == PAGE_SIZE) + tmpblock = NULL; + + /* Merge next block if its free */ + if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { + /* + * Blocks smaller than XV_MIN_ALLOC_SIZE + * are not inserted in any free list. + */ + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { + remove_block(pool, page, + offset + block->size + XV_ALIGN, tmpblock, + get_index_for_insert(tmpblock->size)); + } + block->size += tmpblock->size + XV_ALIGN; + } + + /* Merge previous block if its free */ + if (test_flag(block, PREV_FREE)) { + tmpblock = (struct block_header *)((char *)(page_start) + + get_blockprev(block)); + offset = offset - tmpblock->size - XV_ALIGN; + + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + remove_block(pool, page, offset, tmpblock, + get_index_for_insert(tmpblock->size)); + + tmpblock->size += block->size + XV_ALIGN; + block = tmpblock; + } + + /* No used objects in this page. Free it. */ + if (block->size == PAGE_SIZE - XV_ALIGN) { + put_ptr_atomic(page_start, KM_USER0); + spin_unlock(&pool->lock); + + __free_page(page); + stat_dec(&pool->total_pages); + return; + } + + set_flag(block, BLOCK_FREE); + if (block->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, page, offset, block); + + if (offset + block->size + XV_ALIGN != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(block); + set_flag(tmpblock, PREV_FREE); + set_blockprev(tmpblock, offset); + } + + put_ptr_atomic(page_start, KM_USER0); + spin_unlock(&pool->lock); +} + +u32 xv_get_object_size(void *obj) +{ + struct block_header *blk; + + blk = (struct block_header *)((char *)(obj) - XV_ALIGN); + return blk->size; +} + +/* + * Returns total memory used by allocator (userdata + metadata) + */ +u64 xv_get_total_size_bytes(struct xv_pool *pool) +{ + return pool->total_pages << PAGE_SHIFT; +} diff --git a/drivers/staging/zram/xvmalloc.h b/drivers/staging/zram/xvmalloc.h new file mode 100644 index 000000000000..5b1a81aa5faf --- /dev/null +++ b/drivers/staging/zram/xvmalloc.h @@ -0,0 +1,30 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_H_ +#define _XV_MALLOC_H_ + +#include + +struct xv_pool; + +struct xv_pool *xv_create_pool(void); +void xv_destroy_pool(struct xv_pool *pool); + +int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, + u32 *offset, gfp_t flags); +void xv_free(struct xv_pool *pool, struct page *page, u32 offset); + +u32 xv_get_object_size(void *obj); +u64 xv_get_total_size_bytes(struct xv_pool *pool); + +#endif diff --git a/drivers/staging/zram/xvmalloc_int.h b/drivers/staging/zram/xvmalloc_int.h new file mode 100644 index 000000000000..e23ed5c8b8e4 --- /dev/null +++ b/drivers/staging/zram/xvmalloc_int.h @@ -0,0 +1,86 @@ +/* + * xvmalloc memory allocator + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _XV_MALLOC_INT_H_ +#define _XV_MALLOC_INT_H_ + +#include +#include + +/* User configurable params */ + +/* Must be power of two */ +#define XV_ALIGN_SHIFT 2 +#define XV_ALIGN (1 << XV_ALIGN_SHIFT) +#define XV_ALIGN_MASK (XV_ALIGN - 1) + +/* This must be greater than sizeof(link_free) */ +#define XV_MIN_ALLOC_SIZE 32 +#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) + +/* Free lists are separated by FL_DELTA bytes */ +#define FL_DELTA_SHIFT 3 +#define FL_DELTA (1 << FL_DELTA_SHIFT) +#define FL_DELTA_MASK (FL_DELTA - 1) +#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ + / FL_DELTA + 1) + +#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) + +/* End of user params */ + +enum blockflags { + BLOCK_FREE, + PREV_FREE, + __NR_BLOCKFLAGS, +}; + +#define FLAGS_MASK XV_ALIGN_MASK +#define PREV_MASK (~FLAGS_MASK) + +struct freelist_entry { + struct page *page; + u16 offset; + u16 pad; +}; + +struct link_free { + struct page *prev_page; + struct page *next_page; + u16 prev_offset; + u16 next_offset; +}; + +struct block_header { + union { + /* This common header must be XV_ALIGN bytes */ + u8 common[XV_ALIGN]; + struct { + u16 size; + u16 prev; + }; + }; + struct link_free link; +}; + +struct xv_pool { + ulong flbitmap; + ulong slbitmap[MAX_FLI]; + spinlock_t lock; + + struct freelist_entry freelist[NUM_FREE_LISTS]; + + /* stats */ + u64 total_pages; +}; + +#endif diff --git a/drivers/staging/zram/zram.txt b/drivers/staging/zram/zram.txt new file mode 100644 index 000000000000..9694acfeb43f --- /dev/null +++ b/drivers/staging/zram/zram.txt @@ -0,0 +1,51 @@ +ramzswap: Compressed RAM based swap device +------------------------------------------- + +Project home: http://compcache.googlecode.com/ + +* Introduction + +The ramzswap module creates RAM based block devices which can (only) be used as +swap disks. Pages swapped to these devices are compressed and stored in memory +itself. See project home for use cases, performance numbers and a lot more. + +Individual ramzswap devices are configured and initialized using rzscontrol +userspace utility as shown in examples below. See rzscontrol man page for more +details. + +* Usage + +Following shows a typical sequence of steps for using ramzswap. + +1) Load Modules: + modprobe ramzswap num_devices=4 + This creates 4 (uninitialized) devices: /dev/ramzswap{0,1,2,3} + (num_devices parameter is optional. Default: 1) + +2) Initialize: + Use rzscontrol utility to configure and initialize individual + ramzswap devices. Example: + rzscontrol /dev/ramzswap2 --init # uses default value of disksize_kb + + *See rzscontrol man page for more details and examples* + +3) Activate: + swapon /dev/ramzswap2 # or any other initialized ramzswap device + +4) Stats: + rzscontrol /dev/ramzswap2 --stats + +5) Deactivate: + swapoff /dev/ramzswap2 + +6) Reset: + rzscontrol /dev/ramzswap2 --reset + (This frees all the memory allocated for this device). + + +Please report any problems at: + - Mailing list: linux-mm-cc at laptop dot org + - Issue tracker: http://code.google.com/p/compcache/issues/list + +Nitin Gupta +ngupta@vflare.org diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c new file mode 100644 index 000000000000..e9b064c21484 --- /dev/null +++ b/drivers/staging/zram/zram_drv.c @@ -0,0 +1,805 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#define KMSG_COMPONENT "ramzswap" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zram_drv.h" + +/* Globals */ +static int ramzswap_major; +static struct ramzswap *devices; + +/* Module params (documentation at end) */ +static unsigned int num_devices; + +static int rzs_test_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + return rzs->table[index].flags & BIT(flag); +} + +static void rzs_set_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + rzs->table[index].flags |= BIT(flag); +} + +static void rzs_clear_flag(struct ramzswap *rzs, u32 index, + enum rzs_pageflags flag) +{ + rzs->table[index].flags &= ~BIT(flag); +} + +static int page_zero_filled(void *ptr) +{ + unsigned int pos; + unsigned long *page; + + page = (unsigned long *)ptr; + + for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { + if (page[pos]) + return 0; + } + + return 1; +} + +static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) +{ + if (!rzs->disksize) { + pr_info( + "disk size not provided. You can use disksize_kb module " + "param to specify size.\nUsing default: (%u%% of RAM).\n", + default_disksize_perc_ram + ); + rzs->disksize = default_disksize_perc_ram * + (totalram_bytes / 100); + } + + if (rzs->disksize > 2 * (totalram_bytes)) { + pr_info( + "There is little point creating a ramzswap of greater than " + "twice the size of memory since we expect a 2:1 compression " + "ratio. Note that ramzswap uses about 0.1%% of the size of " + "the swap device when not in use so a huge ramzswap is " + "wasteful.\n" + "\tMemory Size: %zu kB\n" + "\tSize you selected: %zu kB\n" + "Continuing anyway ...\n", + totalram_bytes >> 10, rzs->disksize + ); + } + + rzs->disksize &= PAGE_MASK; +} + +static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, + struct ramzswap_ioctl_stats *s) +{ + s->disksize = rzs->disksize; + +#if defined(CONFIG_RAMZSWAP_STATS) + { + struct ramzswap_stats *rs = &rzs->stats; + size_t succ_writes, mem_used; + unsigned int good_compress_perc = 0, no_compress_perc = 0; + + mem_used = xv_get_total_size_bytes(rzs->mem_pool) + + (rs->pages_expand << PAGE_SHIFT); + succ_writes = rzs_stat64_read(rzs, &rs->num_writes) - + rzs_stat64_read(rzs, &rs->failed_writes); + + if (succ_writes && rs->pages_stored) { + good_compress_perc = rs->good_compress * 100 + / rs->pages_stored; + no_compress_perc = rs->pages_expand * 100 + / rs->pages_stored; + } + + s->num_reads = rzs_stat64_read(rzs, &rs->num_reads); + s->num_writes = rzs_stat64_read(rzs, &rs->num_writes); + s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads); + s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes); + s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io); + s->notify_free = rzs_stat64_read(rzs, &rs->notify_free); + s->pages_zero = rs->pages_zero; + + s->good_compress_pct = good_compress_perc; + s->pages_expand_pct = no_compress_perc; + + s->pages_stored = rs->pages_stored; + s->pages_used = mem_used >> PAGE_SHIFT; + s->orig_data_size = rs->pages_stored << PAGE_SHIFT; + s->compr_data_size = rs->compr_size; + s->mem_used_total = mem_used; + } +#endif /* CONFIG_RAMZSWAP_STATS */ +} + +static void ramzswap_free_page(struct ramzswap *rzs, size_t index) +{ + u32 clen; + void *obj; + + struct page *page = rzs->table[index].page; + u32 offset = rzs->table[index].offset; + + if (unlikely(!page)) { + /* + * No memory is allocated for zero filled pages. + * Simply clear zero page flag. + */ + if (rzs_test_flag(rzs, index, RZS_ZERO)) { + rzs_clear_flag(rzs, index, RZS_ZERO); + rzs_stat_dec(&rzs->stats.pages_zero); + } + return; + } + + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { + clen = PAGE_SIZE; + __free_page(page); + rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED); + rzs_stat_dec(&rzs->stats.pages_expand); + goto out; + } + + obj = kmap_atomic(page, KM_USER0) + offset; + clen = xv_get_object_size(obj) - sizeof(struct zobj_header); + kunmap_atomic(obj, KM_USER0); + + xv_free(rzs->mem_pool, page, offset); + if (clen <= PAGE_SIZE / 2) + rzs_stat_dec(&rzs->stats.good_compress); + +out: + rzs->stats.compr_size -= clen; + rzs_stat_dec(&rzs->stats.pages_stored); + + rzs->table[index].page = NULL; + rzs->table[index].offset = 0; +} + +static void handle_zero_page(struct page *page) +{ + void *user_mem; + + user_mem = kmap_atomic(page, KM_USER0); + memset(user_mem, 0, PAGE_SIZE); + kunmap_atomic(user_mem, KM_USER0); + + flush_dcache_page(page); +} + +static void handle_uncompressed_page(struct ramzswap *rzs, + struct page *page, u32 index) +{ + unsigned char *user_mem, *cmem; + + user_mem = kmap_atomic(page, KM_USER0); + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + + memcpy(user_mem, cmem, PAGE_SIZE); + kunmap_atomic(user_mem, KM_USER0); + kunmap_atomic(cmem, KM_USER1); + + flush_dcache_page(page); +} + +static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) +{ + + int i; + u32 index; + struct bio_vec *bvec; + + rzs_stat64_inc(rzs, &rzs->stats.num_reads); + + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + bio_for_each_segment(bvec, bio, i) { + int ret; + size_t clen; + struct page *page; + struct zobj_header *zheader; + unsigned char *user_mem, *cmem; + + page = bvec->bv_page; + + if (rzs_test_flag(rzs, index, RZS_ZERO)) { + handle_zero_page(page); + continue; + } + + /* Requested page is not present in compressed area */ + if (unlikely(!rzs->table[index].page)) { + pr_debug("Read before write: sector=%lu, size=%u", + (ulong)(bio->bi_sector), bio->bi_size); + /* Do nothing */ + continue; + } + + /* Page is stored uncompressed since it's incompressible */ + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { + handle_uncompressed_page(rzs, page, index); + continue; + } + + user_mem = kmap_atomic(page, KM_USER0); + clen = PAGE_SIZE; + + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + + ret = lzo1x_decompress_safe( + cmem + sizeof(*zheader), + xv_get_object_size(cmem) - sizeof(*zheader), + user_mem, &clen); + + kunmap_atomic(user_mem, KM_USER0); + kunmap_atomic(cmem, KM_USER1); + + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { + pr_err("Decompression failed! err=%d, page=%u\n", + ret, index); + rzs_stat64_inc(rzs, &rzs->stats.failed_reads); + goto out; + } + + flush_dcache_page(page); + index++; + } + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + +out: + bio_io_error(bio); + return 0; +} + +static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) +{ + int i; + u32 index; + struct bio_vec *bvec; + + rzs_stat64_inc(rzs, &rzs->stats.num_writes); + + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + bio_for_each_segment(bvec, bio, i) { + int ret; + u32 offset; + size_t clen; + struct zobj_header *zheader; + struct page *page, *page_store; + unsigned char *user_mem, *cmem, *src; + + page = bvec->bv_page; + src = rzs->compress_buffer; + + /* + * System overwrites unused sectors. Free memory associated + * with this sector now. + */ + if (rzs->table[index].page || + rzs_test_flag(rzs, index, RZS_ZERO)) + ramzswap_free_page(rzs, index); + + mutex_lock(&rzs->lock); + + user_mem = kmap_atomic(page, KM_USER0); + if (page_zero_filled(user_mem)) { + kunmap_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs->lock); + rzs_stat_inc(&rzs->stats.pages_zero); + rzs_set_flag(rzs, index, RZS_ZERO); + continue; + } + + ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, + rzs->compress_workmem); + + kunmap_atomic(user_mem, KM_USER0); + + if (unlikely(ret != LZO_E_OK)) { + mutex_unlock(&rzs->lock); + pr_err("Compression failed! err=%d\n", ret); + rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + goto out; + } + + /* + * Page is incompressible. Store it as-is (uncompressed) + * since we do not want to return too many swap write + * errors which has side effect of hanging the system. + */ + if (unlikely(clen > max_zpage_size)) { + clen = PAGE_SIZE; + page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); + if (unlikely(!page_store)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for " + "incompressible page: %u\n", index); + rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + goto out; + } + + offset = 0; + rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); + rzs_stat_inc(&rzs->stats.pages_expand); + rzs->table[index].page = page_store; + src = kmap_atomic(page, KM_USER0); + goto memstore; + } + + if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), + &rzs->table[index].page, &offset, + GFP_NOIO | __GFP_HIGHMEM)) { + mutex_unlock(&rzs->lock); + pr_info("Error allocating memory for compressed " + "page: %u, size=%zu\n", index, clen); + rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + goto out; + } + +memstore: + rzs->table[index].offset = offset; + + cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + + rzs->table[index].offset; + +#if 0 + /* Back-reference needed for memory defragmentation */ + if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { + zheader = (struct zobj_header *)cmem; + zheader->table_idx = index; + cmem += sizeof(*zheader); + } +#endif + + memcpy(cmem, src, clen); + + kunmap_atomic(cmem, KM_USER1); + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + kunmap_atomic(src, KM_USER0); + + /* Update stats */ + rzs->stats.compr_size += clen; + rzs_stat_inc(&rzs->stats.pages_stored); + if (clen <= PAGE_SIZE / 2) + rzs_stat_inc(&rzs->stats.good_compress); + + mutex_unlock(&rzs->lock); + index++; + } + + set_bit(BIO_UPTODATE, &bio->bi_flags); + bio_endio(bio, 0); + return 0; + +out: + bio_io_error(bio); + return 0; +} + +/* + * Check if request is within bounds and page aligned. + */ +static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio) +{ + if (unlikely( + (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) || + (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || + (bio->bi_size & (PAGE_SIZE - 1)))) { + + return 0; + } + + /* I/O request is valid */ + return 1; +} + +/* + * Handler function for all ramzswap I/O requests. + */ +static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) +{ + int ret = 0; + struct ramzswap *rzs = queue->queuedata; + + if (unlikely(!rzs->init_done)) { + bio_io_error(bio); + return 0; + } + + if (!valid_io_request(rzs, bio)) { + rzs_stat64_inc(rzs, &rzs->stats.invalid_io); + bio_io_error(bio); + return 0; + } + + switch (bio_data_dir(bio)) { + case READ: + ret = ramzswap_read(rzs, bio); + break; + + case WRITE: + ret = ramzswap_write(rzs, bio); + break; + } + + return ret; +} + +static void reset_device(struct ramzswap *rzs) +{ + size_t index; + + /* Do not accept any new I/O request */ + rzs->init_done = 0; + + /* Free various per-device buffers */ + kfree(rzs->compress_workmem); + free_pages((unsigned long)rzs->compress_buffer, 1); + + rzs->compress_workmem = NULL; + rzs->compress_buffer = NULL; + + /* Free all pages that are still in this ramzswap device */ + for (index = 0; index < rzs->disksize >> PAGE_SHIFT; index++) { + struct page *page; + u16 offset; + + page = rzs->table[index].page; + offset = rzs->table[index].offset; + + if (!page) + continue; + + if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + __free_page(page); + else + xv_free(rzs->mem_pool, page, offset); + } + + vfree(rzs->table); + rzs->table = NULL; + + xv_destroy_pool(rzs->mem_pool); + rzs->mem_pool = NULL; + + /* Reset stats */ + memset(&rzs->stats, 0, sizeof(rzs->stats)); + + rzs->disksize = 0; +} + +static int ramzswap_ioctl_init_device(struct ramzswap *rzs) +{ + int ret; + size_t num_pages; + + if (rzs->init_done) { + pr_info("Device already initialized!\n"); + return -EBUSY; + } + + ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT); + + rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); + if (!rzs->compress_workmem) { + pr_err("Error allocating compressor working memory!\n"); + ret = -ENOMEM; + goto fail; + } + + rzs->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1); + if (!rzs->compress_buffer) { + pr_err("Error allocating compressor buffer space\n"); + ret = -ENOMEM; + goto fail; + } + + num_pages = rzs->disksize >> PAGE_SHIFT; + rzs->table = vmalloc(num_pages * sizeof(*rzs->table)); + if (!rzs->table) { + pr_err("Error allocating ramzswap address table\n"); + /* To prevent accessing table entries during cleanup */ + rzs->disksize = 0; + ret = -ENOMEM; + goto fail; + } + memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); + + set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); + + /* ramzswap devices sort of resembles non-rotational disks */ + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue); + + rzs->mem_pool = xv_create_pool(); + if (!rzs->mem_pool) { + pr_err("Error creating memory pool\n"); + ret = -ENOMEM; + goto fail; + } + + rzs->init_done = 1; + + pr_debug("Initialization done!\n"); + return 0; + +fail: + reset_device(rzs); + + pr_err("Initialization failed: err=%d\n", ret); + return ret; +} + +static int ramzswap_ioctl_reset_device(struct ramzswap *rzs) +{ + if (rzs->init_done) + reset_device(rzs); + + return 0; +} + +static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + size_t disksize_kb; + + struct ramzswap *rzs = bdev->bd_disk->private_data; + + switch (cmd) { + case RZSIO_SET_DISKSIZE_KB: + if (rzs->init_done) { + ret = -EBUSY; + goto out; + } + if (copy_from_user(&disksize_kb, (void *)arg, + _IOC_SIZE(cmd))) { + ret = -EFAULT; + goto out; + } + rzs->disksize = disksize_kb << 10; + pr_info("Disk size set to %zu kB\n", disksize_kb); + break; + + case RZSIO_GET_STATS: + { + struct ramzswap_ioctl_stats *stats; + if (!rzs->init_done) { + ret = -ENOTTY; + goto out; + } + stats = kzalloc(sizeof(*stats), GFP_KERNEL); + if (!stats) { + ret = -ENOMEM; + goto out; + } + ramzswap_ioctl_get_stats(rzs, stats); + if (copy_to_user((void *)arg, stats, sizeof(*stats))) { + kfree(stats); + ret = -EFAULT; + goto out; + } + kfree(stats); + break; + } + case RZSIO_INIT: + ret = ramzswap_ioctl_init_device(rzs); + break; + + case RZSIO_RESET: + /* Do not reset an active device! */ + if (bdev->bd_holders) { + ret = -EBUSY; + goto out; + } + + /* Make sure all pending I/O is finished */ + if (bdev) + fsync_bdev(bdev); + + ret = ramzswap_ioctl_reset_device(rzs); + break; + + default: + pr_info("Invalid ioctl %u\n", cmd); + ret = -ENOTTY; + } + +out: + return ret; +} + +void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index) +{ + struct ramzswap *rzs; + + rzs = bdev->bd_disk->private_data; + ramzswap_free_page(rzs, index); + rzs_stat64_inc(rzs, &rzs->stats.notify_free); +} + +static const struct block_device_operations ramzswap_devops = { + .ioctl = ramzswap_ioctl, + .swap_slot_free_notify = ramzswap_slot_free_notify, + .owner = THIS_MODULE +}; + +static int create_device(struct ramzswap *rzs, int device_id) +{ + int ret = 0; + + mutex_init(&rzs->lock); + spin_lock_init(&rzs->stat64_lock); + + rzs->queue = blk_alloc_queue(GFP_KERNEL); + if (!rzs->queue) { + pr_err("Error allocating disk queue for device %d\n", + device_id); + ret = -ENOMEM; + goto out; + } + + blk_queue_make_request(rzs->queue, ramzswap_make_request); + rzs->queue->queuedata = rzs; + + /* gendisk structure */ + rzs->disk = alloc_disk(1); + if (!rzs->disk) { + blk_cleanup_queue(rzs->queue); + pr_warning("Error allocating disk structure for device %d\n", + device_id); + ret = -ENOMEM; + goto out; + } + + rzs->disk->major = ramzswap_major; + rzs->disk->first_minor = device_id; + rzs->disk->fops = &ramzswap_devops; + rzs->disk->queue = rzs->queue; + rzs->disk->private_data = rzs; + snprintf(rzs->disk->disk_name, 16, "ramzswap%d", device_id); + + /* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */ + set_capacity(rzs->disk, 0); + + /* + * To ensure that we always get PAGE_SIZE aligned + * and n*PAGE_SIZED sized I/O requests. + */ + blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE); + blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE); + blk_queue_io_min(rzs->disk->queue, PAGE_SIZE); + blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE); + + add_disk(rzs->disk); + + rzs->init_done = 0; + +out: + return ret; +} + +static void destroy_device(struct ramzswap *rzs) +{ + if (rzs->disk) { + del_gendisk(rzs->disk); + put_disk(rzs->disk); + } + + if (rzs->queue) + blk_cleanup_queue(rzs->queue); +} + +static int __init ramzswap_init(void) +{ + int ret, dev_id; + + if (num_devices > max_num_devices) { + pr_warning("Invalid value for num_devices: %u\n", + num_devices); + ret = -EINVAL; + goto out; + } + + ramzswap_major = register_blkdev(0, "ramzswap"); + if (ramzswap_major <= 0) { + pr_warning("Unable to get major number\n"); + ret = -EBUSY; + goto out; + } + + if (!num_devices) { + pr_info("num_devices not specified. Using default: 1\n"); + num_devices = 1; + } + + /* Allocate the device array and initialize each one */ + pr_info("Creating %u devices ...\n", num_devices); + devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL); + if (!devices) { + ret = -ENOMEM; + goto unregister; + } + + for (dev_id = 0; dev_id < num_devices; dev_id++) { + ret = create_device(&devices[dev_id], dev_id); + if (ret) + goto free_devices; + } + + return 0; + +free_devices: + while (dev_id) + destroy_device(&devices[--dev_id]); +unregister: + unregister_blkdev(ramzswap_major, "ramzswap"); +out: + return ret; +} + +static void __exit ramzswap_exit(void) +{ + int i; + struct ramzswap *rzs; + + for (i = 0; i < num_devices; i++) { + rzs = &devices[i]; + + destroy_device(rzs); + if (rzs->init_done) + reset_device(rzs); + } + + unregister_blkdev(ramzswap_major, "ramzswap"); + + kfree(devices); + pr_debug("Cleanup done!\n"); +} + +module_param(num_devices, uint, 0); +MODULE_PARM_DESC(num_devices, "Number of ramzswap devices"); + +module_init(ramzswap_init); +module_exit(ramzswap_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h new file mode 100644 index 000000000000..4d2e48a23474 --- /dev/null +++ b/drivers/staging/zram/zram_drv.h @@ -0,0 +1,168 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#ifndef _RAMZSWAP_DRV_H_ +#define _RAMZSWAP_DRV_H_ + +#include +#include + +#include "zram_ioctl.h" +#include "xvmalloc.h" + +/* + * Some arbitrary value. This is just to catch + * invalid value for num_devices module parameter. + */ +static const unsigned max_num_devices = 32; + +/* + * Stored at beginning of each compressed object. + * + * It stores back-reference to table entry which points to this + * object. This is required to support memory defragmentation. + */ +struct zobj_header { +#if 0 + u32 table_idx; +#endif +}; + +/*-- Configurable parameters */ + +/* Default ramzswap disk size: 25% of total RAM */ +static const unsigned default_disksize_perc_ram = 25; + +/* + * Pages that compress to size greater than this are stored + * uncompressed in memory. + */ +static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3; + +/* + * NOTE: max_zpage_size must be less than or equal to: + * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) + * otherwise, xv_malloc() would always return failure. + */ + +/*-- End of configurable params */ + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) +#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) +#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) + +/* Flags for ramzswap pages (table[page_no].flags) */ +enum rzs_pageflags { + /* Page is stored uncompressed */ + RZS_UNCOMPRESSED, + + /* Page consists entirely of zeros */ + RZS_ZERO, + + __NR_RZS_PAGEFLAGS, +}; + +/*-- Data structures */ + +/* + * Allocated for each swap slot, indexed by page no. + * These table entries must fit exactly in a page. + */ +struct table { + struct page *page; + u16 offset; + u8 count; /* object ref count (not yet used) */ + u8 flags; +} __attribute__((aligned(4))); + +struct ramzswap_stats { + /* basic stats */ + size_t compr_size; /* compressed size of pages stored - + * needed to enforce memlimit */ + /* more stats */ +#if defined(CONFIG_RAMZSWAP_STATS) + u64 num_reads; /* failed + successful */ + u64 num_writes; /* --do-- */ + u64 failed_reads; /* should NEVER! happen */ + u64 failed_writes; /* can happen when memory is too low */ + u64 invalid_io; /* non-swap I/O requests */ + u64 notify_free; /* no. of swap slot free notifications */ + u32 pages_zero; /* no. of zero filled pages */ + u32 pages_stored; /* no. of pages currently stored */ + u32 good_compress; /* % of pages with compression ratio<=50% */ + u32 pages_expand; /* % of incompressible pages */ +#endif +}; + +struct ramzswap { + struct xv_pool *mem_pool; + void *compress_workmem; + void *compress_buffer; + struct table *table; + spinlock_t stat64_lock; /* protect 64-bit stats */ + struct mutex lock; /* protect compression buffers against + * concurrent writes */ + struct request_queue *queue; + struct gendisk *disk; + int init_done; + /* + * This is limit on amount of *uncompressed* worth of data + * we can hold. When backing swap device is provided, it is + * set equal to device size. + */ + size_t disksize; /* bytes */ + + struct ramzswap_stats stats; +}; + +/*-- */ + +/* Debugging and Stats */ +#if defined(CONFIG_RAMZSWAP_STATS) +static void rzs_stat_inc(u32 *v) +{ + *v = *v + 1; +} + +static void rzs_stat_dec(u32 *v) +{ + *v = *v - 1; +} + +static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v) +{ + spin_lock(&rzs->stat64_lock); + *v = *v + 1; + spin_unlock(&rzs->stat64_lock); +} + +static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v) +{ + u64 val; + + spin_lock(&rzs->stat64_lock); + val = *v; + spin_unlock(&rzs->stat64_lock); + + return val; +} +#else +#define rzs_stat_inc(v) +#define rzs_stat_dec(v) +#define rzs_stat64_inc(r, v) +#define rzs_stat64_read(r, v) +#endif /* CONFIG_RAMZSWAP_STATS */ + +#endif diff --git a/drivers/staging/zram/zram_ioctl.h b/drivers/staging/zram/zram_ioctl.h new file mode 100644 index 000000000000..db94bcb42967 --- /dev/null +++ b/drivers/staging/zram/zram_ioctl.h @@ -0,0 +1,42 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#ifndef _RAMZSWAP_IOCTL_H_ +#define _RAMZSWAP_IOCTL_H_ + +struct ramzswap_ioctl_stats { + u64 disksize; /* user specified or equal to backing swap + * size (if present) */ + u64 num_reads; /* failed + successful */ + u64 num_writes; /* --do-- */ + u64 failed_reads; /* should NEVER! happen */ + u64 failed_writes; /* can happen when memory is too low */ + u64 invalid_io; /* non-swap I/O requests */ + u64 notify_free; /* no. of swap slot free notifications */ + u32 pages_zero; /* no. of zero filled pages */ + u32 good_compress_pct; /* no. of pages with compression ratio<=50% */ + u32 pages_expand_pct; /* no. of incompressible pages */ + u32 pages_stored; + u32 pages_used; + u64 orig_data_size; + u64 compr_data_size; + u64 mem_used_total; +} __attribute__ ((packed, aligned(4))); + +#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) +#define RZSIO_GET_STATS _IOR('z', 1, struct ramzswap_ioctl_stats) +#define RZSIO_INIT _IO('z', 2) +#define RZSIO_RESET _IO('z', 3) + +#endif -- cgit v1.2.3 From f1e3cfff4d58767a76fe71e18bffdeed10318b4e Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Tue, 1 Jun 2010 13:31:25 +0530 Subject: Staging: zram: Rename ramzswap to zram in code Automated renames in code: - rzs* -> zram* - RZS* -> ZRAM* - ramzswap* -> zram* Manual changes: - Edited comments/messages mentioning "swap" Signed-off-by: Nitin Gupta Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 431 +++++++++++++++++++------------------- drivers/staging/zram/zram_drv.h | 66 +++--- drivers/staging/zram/zram_ioctl.h | 21 +- 3 files changed, 256 insertions(+), 262 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index e9b064c21484..3f778434dc9b 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -1,5 +1,5 @@ /* - * Compressed RAM based swap device + * Compressed RAM block device * * Copyright (C) 2008, 2009, 2010 Nitin Gupta * @@ -12,7 +12,7 @@ * Project home: http://compcache.googlecode.com */ -#define KMSG_COMPONENT "ramzswap" +#define KMSG_COMPONENT "zram" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include @@ -26,35 +26,33 @@ #include #include #include -#include -#include #include #include "zram_drv.h" /* Globals */ -static int ramzswap_major; -static struct ramzswap *devices; +static int zram_major; +static struct zram *devices; /* Module params (documentation at end) */ static unsigned int num_devices; -static int rzs_test_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) +static int zram_test_flag(struct zram *zram, u32 index, + enum zram_pageflags flag) { - return rzs->table[index].flags & BIT(flag); + return zram->table[index].flags & BIT(flag); } -static void rzs_set_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) +static void zram_set_flag(struct zram *zram, u32 index, + enum zram_pageflags flag) { - rzs->table[index].flags |= BIT(flag); + zram->table[index].flags |= BIT(flag); } -static void rzs_clear_flag(struct ramzswap *rzs, u32 index, - enum rzs_pageflags flag) +static void zram_clear_flag(struct zram *zram, u32 index, + enum zram_pageflags flag) { - rzs->table[index].flags &= ~BIT(flag); + zram->table[index].flags &= ~BIT(flag); } static int page_zero_filled(void *ptr) @@ -72,50 +70,50 @@ static int page_zero_filled(void *ptr) return 1; } -static void ramzswap_set_disksize(struct ramzswap *rzs, size_t totalram_bytes) +static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) { - if (!rzs->disksize) { + if (!zram->disksize) { pr_info( "disk size not provided. You can use disksize_kb module " "param to specify size.\nUsing default: (%u%% of RAM).\n", default_disksize_perc_ram ); - rzs->disksize = default_disksize_perc_ram * + zram->disksize = default_disksize_perc_ram * (totalram_bytes / 100); } - if (rzs->disksize > 2 * (totalram_bytes)) { + if (zram->disksize > 2 * (totalram_bytes)) { pr_info( - "There is little point creating a ramzswap of greater than " + "There is little point creating a zram of greater than " "twice the size of memory since we expect a 2:1 compression " - "ratio. Note that ramzswap uses about 0.1%% of the size of " - "the swap device when not in use so a huge ramzswap is " + "ratio. Note that zram uses about 0.1%% of the size of " + "the disk when not in use so a huge zram is " "wasteful.\n" "\tMemory Size: %zu kB\n" "\tSize you selected: %zu kB\n" "Continuing anyway ...\n", - totalram_bytes >> 10, rzs->disksize + totalram_bytes >> 10, zram->disksize ); } - rzs->disksize &= PAGE_MASK; + zram->disksize &= PAGE_MASK; } -static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, - struct ramzswap_ioctl_stats *s) +static void zram_ioctl_get_stats(struct zram *zram, + struct zram_ioctl_stats *s) { - s->disksize = rzs->disksize; + s->disksize = zram->disksize; -#if defined(CONFIG_RAMZSWAP_STATS) +#if defined(CONFIG_ZRAM_STATS) { - struct ramzswap_stats *rs = &rzs->stats; + struct zram_stats *rs = &zram->stats; size_t succ_writes, mem_used; unsigned int good_compress_perc = 0, no_compress_perc = 0; - mem_used = xv_get_total_size_bytes(rzs->mem_pool) + mem_used = xv_get_total_size_bytes(zram->mem_pool) + (rs->pages_expand << PAGE_SHIFT); - succ_writes = rzs_stat64_read(rzs, &rs->num_writes) - - rzs_stat64_read(rzs, &rs->failed_writes); + succ_writes = zram_stat64_read(zram, &rs->num_writes) - + zram_stat64_read(zram, &rs->failed_writes); if (succ_writes && rs->pages_stored) { good_compress_perc = rs->good_compress * 100 @@ -124,12 +122,12 @@ static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, / rs->pages_stored; } - s->num_reads = rzs_stat64_read(rzs, &rs->num_reads); - s->num_writes = rzs_stat64_read(rzs, &rs->num_writes); - s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads); - s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes); - s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io); - s->notify_free = rzs_stat64_read(rzs, &rs->notify_free); + s->num_reads = zram_stat64_read(zram, &rs->num_reads); + s->num_writes = zram_stat64_read(zram, &rs->num_writes); + s->failed_reads = zram_stat64_read(zram, &rs->failed_reads); + s->failed_writes = zram_stat64_read(zram, &rs->failed_writes); + s->invalid_io = zram_stat64_read(zram, &rs->invalid_io); + s->notify_free = zram_stat64_read(zram, &rs->notify_free); s->pages_zero = rs->pages_zero; s->good_compress_pct = good_compress_perc; @@ -141,34 +139,34 @@ static void ramzswap_ioctl_get_stats(struct ramzswap *rzs, s->compr_data_size = rs->compr_size; s->mem_used_total = mem_used; } -#endif /* CONFIG_RAMZSWAP_STATS */ +#endif /* CONFIG_ZRAM_STATS */ } -static void ramzswap_free_page(struct ramzswap *rzs, size_t index) +static void zram_free_page(struct zram *zram, size_t index) { u32 clen; void *obj; - struct page *page = rzs->table[index].page; - u32 offset = rzs->table[index].offset; + struct page *page = zram->table[index].page; + u32 offset = zram->table[index].offset; if (unlikely(!page)) { /* * No memory is allocated for zero filled pages. * Simply clear zero page flag. */ - if (rzs_test_flag(rzs, index, RZS_ZERO)) { - rzs_clear_flag(rzs, index, RZS_ZERO); - rzs_stat_dec(&rzs->stats.pages_zero); + if (zram_test_flag(zram, index, ZRAM_ZERO)) { + zram_clear_flag(zram, index, ZRAM_ZERO); + zram_stat_dec(&zram->stats.pages_zero); } return; } - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { + if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { clen = PAGE_SIZE; __free_page(page); - rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_dec(&rzs->stats.pages_expand); + zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED); + zram_stat_dec(&zram->stats.pages_expand); goto out; } @@ -176,16 +174,16 @@ static void ramzswap_free_page(struct ramzswap *rzs, size_t index) clen = xv_get_object_size(obj) - sizeof(struct zobj_header); kunmap_atomic(obj, KM_USER0); - xv_free(rzs->mem_pool, page, offset); + xv_free(zram->mem_pool, page, offset); if (clen <= PAGE_SIZE / 2) - rzs_stat_dec(&rzs->stats.good_compress); + zram_stat_dec(&zram->stats.good_compress); out: - rzs->stats.compr_size -= clen; - rzs_stat_dec(&rzs->stats.pages_stored); + zram->stats.compr_size -= clen; + zram_stat_dec(&zram->stats.pages_stored); - rzs->table[index].page = NULL; - rzs->table[index].offset = 0; + zram->table[index].page = NULL; + zram->table[index].offset = 0; } static void handle_zero_page(struct page *page) @@ -199,14 +197,14 @@ static void handle_zero_page(struct page *page) flush_dcache_page(page); } -static void handle_uncompressed_page(struct ramzswap *rzs, +static void handle_uncompressed_page(struct zram *zram, struct page *page, u32 index) { unsigned char *user_mem, *cmem; user_mem = kmap_atomic(page, KM_USER0); - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; + cmem = kmap_atomic(zram->table[index].page, KM_USER1) + + zram->table[index].offset; memcpy(user_mem, cmem, PAGE_SIZE); kunmap_atomic(user_mem, KM_USER0); @@ -215,14 +213,14 @@ static void handle_uncompressed_page(struct ramzswap *rzs, flush_dcache_page(page); } -static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) +static int zram_read(struct zram *zram, struct bio *bio) { int i; u32 index; struct bio_vec *bvec; - rzs_stat64_inc(rzs, &rzs->stats.num_reads); + zram_stat64_inc(zram, &zram->stats.num_reads); index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; bio_for_each_segment(bvec, bio, i) { @@ -234,13 +232,13 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) page = bvec->bv_page; - if (rzs_test_flag(rzs, index, RZS_ZERO)) { + if (zram_test_flag(zram, index, ZRAM_ZERO)) { handle_zero_page(page); continue; } /* Requested page is not present in compressed area */ - if (unlikely(!rzs->table[index].page)) { + if (unlikely(!zram->table[index].page)) { pr_debug("Read before write: sector=%lu, size=%u", (ulong)(bio->bi_sector), bio->bi_size); /* Do nothing */ @@ -248,16 +246,16 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) } /* Page is stored uncompressed since it's incompressible */ - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) { - handle_uncompressed_page(rzs, page, index); + if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { + handle_uncompressed_page(zram, page, index); continue; } user_mem = kmap_atomic(page, KM_USER0); clen = PAGE_SIZE; - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; + cmem = kmap_atomic(zram->table[index].page, KM_USER1) + + zram->table[index].offset; ret = lzo1x_decompress_safe( cmem + sizeof(*zheader), @@ -271,7 +269,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) if (unlikely(ret != LZO_E_OK)) { pr_err("Decompression failed! err=%d, page=%u\n", ret, index); - rzs_stat64_inc(rzs, &rzs->stats.failed_reads); + zram_stat64_inc(zram, &zram->stats.failed_reads); goto out; } @@ -288,13 +286,13 @@ out: return 0; } -static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) +static int zram_write(struct zram *zram, struct bio *bio) { int i; u32 index; struct bio_vec *bvec; - rzs_stat64_inc(rzs, &rzs->stats.num_writes); + zram_stat64_inc(zram, &zram->stats.num_writes); index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; @@ -307,82 +305,83 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio) unsigned char *user_mem, *cmem, *src; page = bvec->bv_page; - src = rzs->compress_buffer; + src = zram->compress_buffer; /* * System overwrites unused sectors. Free memory associated * with this sector now. */ - if (rzs->table[index].page || - rzs_test_flag(rzs, index, RZS_ZERO)) - ramzswap_free_page(rzs, index); + if (zram->table[index].page || + zram_test_flag(zram, index, ZRAM_ZERO)) + zram_free_page(zram, index); - mutex_lock(&rzs->lock); + mutex_lock(&zram->lock); user_mem = kmap_atomic(page, KM_USER0); if (page_zero_filled(user_mem)) { kunmap_atomic(user_mem, KM_USER0); - mutex_unlock(&rzs->lock); - rzs_stat_inc(&rzs->stats.pages_zero); - rzs_set_flag(rzs, index, RZS_ZERO); + mutex_unlock(&zram->lock); + zram_stat_inc(&zram->stats.pages_zero); + zram_set_flag(zram, index, ZRAM_ZERO); continue; } ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, - rzs->compress_workmem); + zram->compress_workmem); kunmap_atomic(user_mem, KM_USER0); if (unlikely(ret != LZO_E_OK)) { - mutex_unlock(&rzs->lock); + mutex_unlock(&zram->lock); pr_err("Compression failed! err=%d\n", ret); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + zram_stat64_inc(zram, &zram->stats.failed_writes); goto out; } /* * Page is incompressible. Store it as-is (uncompressed) - * since we do not want to return too many swap write + * since we do not want to return too many disk write * errors which has side effect of hanging the system. */ if (unlikely(clen > max_zpage_size)) { clen = PAGE_SIZE; page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); if (unlikely(!page_store)) { - mutex_unlock(&rzs->lock); + mutex_unlock(&zram->lock); pr_info("Error allocating memory for " "incompressible page: %u\n", index); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + zram_stat64_inc(zram, + &zram->stats.failed_writes); goto out; } offset = 0; - rzs_set_flag(rzs, index, RZS_UNCOMPRESSED); - rzs_stat_inc(&rzs->stats.pages_expand); - rzs->table[index].page = page_store; + zram_set_flag(zram, index, ZRAM_UNCOMPRESSED); + zram_stat_inc(&zram->stats.pages_expand); + zram->table[index].page = page_store; src = kmap_atomic(page, KM_USER0); goto memstore; } - if (xv_malloc(rzs->mem_pool, clen + sizeof(*zheader), - &rzs->table[index].page, &offset, + if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader), + &zram->table[index].page, &offset, GFP_NOIO | __GFP_HIGHMEM)) { - mutex_unlock(&rzs->lock); + mutex_unlock(&zram->lock); pr_info("Error allocating memory for compressed " "page: %u, size=%zu\n", index, clen); - rzs_stat64_inc(rzs, &rzs->stats.failed_writes); + zram_stat64_inc(zram, &zram->stats.failed_writes); goto out; } memstore: - rzs->table[index].offset = offset; + zram->table[index].offset = offset; - cmem = kmap_atomic(rzs->table[index].page, KM_USER1) + - rzs->table[index].offset; + cmem = kmap_atomic(zram->table[index].page, KM_USER1) + + zram->table[index].offset; #if 0 /* Back-reference needed for memory defragmentation */ - if (!rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)) { + if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) { zheader = (struct zobj_header *)cmem; zheader->table_idx = index; cmem += sizeof(*zheader); @@ -392,16 +391,16 @@ memstore: memcpy(cmem, src, clen); kunmap_atomic(cmem, KM_USER1); - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) kunmap_atomic(src, KM_USER0); /* Update stats */ - rzs->stats.compr_size += clen; - rzs_stat_inc(&rzs->stats.pages_stored); + zram->stats.compr_size += clen; + zram_stat_inc(&zram->stats.pages_stored); if (clen <= PAGE_SIZE / 2) - rzs_stat_inc(&rzs->stats.good_compress); + zram_stat_inc(&zram->stats.good_compress); - mutex_unlock(&rzs->lock); + mutex_unlock(&zram->lock); index++; } @@ -417,10 +416,10 @@ out: /* * Check if request is within bounds and page aligned. */ -static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio) +static inline int valid_io_request(struct zram *zram, struct bio *bio) { if (unlikely( - (bio->bi_sector >= (rzs->disksize >> SECTOR_SHIFT)) || + (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) || (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || (bio->bi_size & (PAGE_SIZE - 1)))) { @@ -432,160 +431,160 @@ static inline int valid_io_request(struct ramzswap *rzs, struct bio *bio) } /* - * Handler function for all ramzswap I/O requests. + * Handler function for all zram I/O requests. */ -static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) +static int zram_make_request(struct request_queue *queue, struct bio *bio) { int ret = 0; - struct ramzswap *rzs = queue->queuedata; + struct zram *zram = queue->queuedata; - if (unlikely(!rzs->init_done)) { + if (unlikely(!zram->init_done)) { bio_io_error(bio); return 0; } - if (!valid_io_request(rzs, bio)) { - rzs_stat64_inc(rzs, &rzs->stats.invalid_io); + if (!valid_io_request(zram, bio)) { + zram_stat64_inc(zram, &zram->stats.invalid_io); bio_io_error(bio); return 0; } switch (bio_data_dir(bio)) { case READ: - ret = ramzswap_read(rzs, bio); + ret = zram_read(zram, bio); break; case WRITE: - ret = ramzswap_write(rzs, bio); + ret = zram_write(zram, bio); break; } return ret; } -static void reset_device(struct ramzswap *rzs) +static void reset_device(struct zram *zram) { size_t index; /* Do not accept any new I/O request */ - rzs->init_done = 0; + zram->init_done = 0; /* Free various per-device buffers */ - kfree(rzs->compress_workmem); - free_pages((unsigned long)rzs->compress_buffer, 1); + kfree(zram->compress_workmem); + free_pages((unsigned long)zram->compress_buffer, 1); - rzs->compress_workmem = NULL; - rzs->compress_buffer = NULL; + zram->compress_workmem = NULL; + zram->compress_buffer = NULL; - /* Free all pages that are still in this ramzswap device */ - for (index = 0; index < rzs->disksize >> PAGE_SHIFT; index++) { + /* Free all pages that are still in this zram device */ + for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) { struct page *page; u16 offset; - page = rzs->table[index].page; - offset = rzs->table[index].offset; + page = zram->table[index].page; + offset = zram->table[index].offset; if (!page) continue; - if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED))) + if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) __free_page(page); else - xv_free(rzs->mem_pool, page, offset); + xv_free(zram->mem_pool, page, offset); } - vfree(rzs->table); - rzs->table = NULL; + vfree(zram->table); + zram->table = NULL; - xv_destroy_pool(rzs->mem_pool); - rzs->mem_pool = NULL; + xv_destroy_pool(zram->mem_pool); + zram->mem_pool = NULL; /* Reset stats */ - memset(&rzs->stats, 0, sizeof(rzs->stats)); + memset(&zram->stats, 0, sizeof(zram->stats)); - rzs->disksize = 0; + zram->disksize = 0; } -static int ramzswap_ioctl_init_device(struct ramzswap *rzs) +static int zram_ioctl_init_device(struct zram *zram) { int ret; size_t num_pages; - if (rzs->init_done) { + if (zram->init_done) { pr_info("Device already initialized!\n"); return -EBUSY; } - ramzswap_set_disksize(rzs, totalram_pages << PAGE_SHIFT); + zram_set_disksize(zram, totalram_pages << PAGE_SHIFT); - rzs->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); - if (!rzs->compress_workmem) { + zram->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); + if (!zram->compress_workmem) { pr_err("Error allocating compressor working memory!\n"); ret = -ENOMEM; goto fail; } - rzs->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1); - if (!rzs->compress_buffer) { + zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1); + if (!zram->compress_buffer) { pr_err("Error allocating compressor buffer space\n"); ret = -ENOMEM; goto fail; } - num_pages = rzs->disksize >> PAGE_SHIFT; - rzs->table = vmalloc(num_pages * sizeof(*rzs->table)); - if (!rzs->table) { - pr_err("Error allocating ramzswap address table\n"); + num_pages = zram->disksize >> PAGE_SHIFT; + zram->table = vmalloc(num_pages * sizeof(*zram->table)); + if (!zram->table) { + pr_err("Error allocating zram address table\n"); /* To prevent accessing table entries during cleanup */ - rzs->disksize = 0; + zram->disksize = 0; ret = -ENOMEM; goto fail; } - memset(rzs->table, 0, num_pages * sizeof(*rzs->table)); + memset(zram->table, 0, num_pages * sizeof(*zram->table)); - set_capacity(rzs->disk, rzs->disksize >> SECTOR_SHIFT); + set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); - /* ramzswap devices sort of resembles non-rotational disks */ - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs->disk->queue); + /* zram devices sort of resembles non-rotational disks */ + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue); - rzs->mem_pool = xv_create_pool(); - if (!rzs->mem_pool) { + zram->mem_pool = xv_create_pool(); + if (!zram->mem_pool) { pr_err("Error creating memory pool\n"); ret = -ENOMEM; goto fail; } - rzs->init_done = 1; + zram->init_done = 1; pr_debug("Initialization done!\n"); return 0; fail: - reset_device(rzs); + reset_device(zram); pr_err("Initialization failed: err=%d\n", ret); return ret; } -static int ramzswap_ioctl_reset_device(struct ramzswap *rzs) +static int zram_ioctl_reset_device(struct zram *zram) { - if (rzs->init_done) - reset_device(rzs); + if (zram->init_done) + reset_device(zram); return 0; } -static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, +static int zram_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { int ret = 0; size_t disksize_kb; - struct ramzswap *rzs = bdev->bd_disk->private_data; + struct zram *zram = bdev->bd_disk->private_data; switch (cmd) { - case RZSIO_SET_DISKSIZE_KB: - if (rzs->init_done) { + case ZRAMIO_SET_DISKSIZE_KB: + if (zram->init_done) { ret = -EBUSY; goto out; } @@ -594,14 +593,14 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, ret = -EFAULT; goto out; } - rzs->disksize = disksize_kb << 10; + zram->disksize = disksize_kb << 10; pr_info("Disk size set to %zu kB\n", disksize_kb); break; - case RZSIO_GET_STATS: + case ZRAMIO_GET_STATS: { - struct ramzswap_ioctl_stats *stats; - if (!rzs->init_done) { + struct zram_ioctl_stats *stats; + if (!zram->init_done) { ret = -ENOTTY; goto out; } @@ -610,7 +609,7 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, ret = -ENOMEM; goto out; } - ramzswap_ioctl_get_stats(rzs, stats); + zram_ioctl_get_stats(zram, stats); if (copy_to_user((void *)arg, stats, sizeof(*stats))) { kfree(stats); ret = -EFAULT; @@ -619,11 +618,11 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, kfree(stats); break; } - case RZSIO_INIT: - ret = ramzswap_ioctl_init_device(rzs); + case ZRAMIO_INIT: + ret = zram_ioctl_init_device(zram); break; - case RZSIO_RESET: + case ZRAMIO_RESET: /* Do not reset an active device! */ if (bdev->bd_holders) { ret = -EBUSY; @@ -634,7 +633,7 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode, if (bdev) fsync_bdev(bdev); - ret = ramzswap_ioctl_reset_device(rzs); + ret = zram_ioctl_reset_device(zram); break; default: @@ -646,88 +645,88 @@ out: return ret; } -void ramzswap_slot_free_notify(struct block_device *bdev, unsigned long index) +void zram_slot_free_notify(struct block_device *bdev, unsigned long index) { - struct ramzswap *rzs; + struct zram *zram; - rzs = bdev->bd_disk->private_data; - ramzswap_free_page(rzs, index); - rzs_stat64_inc(rzs, &rzs->stats.notify_free); + zram = bdev->bd_disk->private_data; + zram_free_page(zram, index); + zram_stat64_inc(zram, &zram->stats.notify_free); } -static const struct block_device_operations ramzswap_devops = { - .ioctl = ramzswap_ioctl, - .swap_slot_free_notify = ramzswap_slot_free_notify, +static const struct block_device_operations zram_devops = { + .ioctl = zram_ioctl, + .swap_slot_free_notify = zram_slot_free_notify, .owner = THIS_MODULE }; -static int create_device(struct ramzswap *rzs, int device_id) +static int create_device(struct zram *zram, int device_id) { int ret = 0; - mutex_init(&rzs->lock); - spin_lock_init(&rzs->stat64_lock); + mutex_init(&zram->lock); + spin_lock_init(&zram->stat64_lock); - rzs->queue = blk_alloc_queue(GFP_KERNEL); - if (!rzs->queue) { + zram->queue = blk_alloc_queue(GFP_KERNEL); + if (!zram->queue) { pr_err("Error allocating disk queue for device %d\n", device_id); ret = -ENOMEM; goto out; } - blk_queue_make_request(rzs->queue, ramzswap_make_request); - rzs->queue->queuedata = rzs; + blk_queue_make_request(zram->queue, zram_make_request); + zram->queue->queuedata = zram; /* gendisk structure */ - rzs->disk = alloc_disk(1); - if (!rzs->disk) { - blk_cleanup_queue(rzs->queue); + zram->disk = alloc_disk(1); + if (!zram->disk) { + blk_cleanup_queue(zram->queue); pr_warning("Error allocating disk structure for device %d\n", device_id); ret = -ENOMEM; goto out; } - rzs->disk->major = ramzswap_major; - rzs->disk->first_minor = device_id; - rzs->disk->fops = &ramzswap_devops; - rzs->disk->queue = rzs->queue; - rzs->disk->private_data = rzs; - snprintf(rzs->disk->disk_name, 16, "ramzswap%d", device_id); + zram->disk->major = zram_major; + zram->disk->first_minor = device_id; + zram->disk->fops = &zram_devops; + zram->disk->queue = zram->queue; + zram->disk->private_data = zram; + snprintf(zram->disk->disk_name, 16, "zram%d", device_id); - /* Actual capacity set using RZSIO_SET_DISKSIZE_KB ioctl */ - set_capacity(rzs->disk, 0); + /* Actual capacity set using ZRAMIO_SET_DISKSIZE_KB ioctl */ + set_capacity(zram->disk, 0); /* * To ensure that we always get PAGE_SIZE aligned * and n*PAGE_SIZED sized I/O requests. */ - blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE); - blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE); - blk_queue_io_min(rzs->disk->queue, PAGE_SIZE); - blk_queue_io_opt(rzs->disk->queue, PAGE_SIZE); + blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE); + blk_queue_logical_block_size(zram->disk->queue, PAGE_SIZE); + blk_queue_io_min(zram->disk->queue, PAGE_SIZE); + blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); - add_disk(rzs->disk); + add_disk(zram->disk); - rzs->init_done = 0; + zram->init_done = 0; out: return ret; } -static void destroy_device(struct ramzswap *rzs) +static void destroy_device(struct zram *zram) { - if (rzs->disk) { - del_gendisk(rzs->disk); - put_disk(rzs->disk); + if (zram->disk) { + del_gendisk(zram->disk); + put_disk(zram->disk); } - if (rzs->queue) - blk_cleanup_queue(rzs->queue); + if (zram->queue) + blk_cleanup_queue(zram->queue); } -static int __init ramzswap_init(void) +static int __init zram_init(void) { int ret, dev_id; @@ -738,8 +737,8 @@ static int __init ramzswap_init(void) goto out; } - ramzswap_major = register_blkdev(0, "ramzswap"); - if (ramzswap_major <= 0) { + zram_major = register_blkdev(0, "zram"); + if (zram_major <= 0) { pr_warning("Unable to get major number\n"); ret = -EBUSY; goto out; @@ -752,7 +751,7 @@ static int __init ramzswap_init(void) /* Allocate the device array and initialize each one */ pr_info("Creating %u devices ...\n", num_devices); - devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL); + devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL); if (!devices) { ret = -ENOMEM; goto unregister; @@ -770,36 +769,36 @@ free_devices: while (dev_id) destroy_device(&devices[--dev_id]); unregister: - unregister_blkdev(ramzswap_major, "ramzswap"); + unregister_blkdev(zram_major, "zram"); out: return ret; } -static void __exit ramzswap_exit(void) +static void __exit zram_exit(void) { int i; - struct ramzswap *rzs; + struct zram *zram; for (i = 0; i < num_devices; i++) { - rzs = &devices[i]; + zram = &devices[i]; - destroy_device(rzs); - if (rzs->init_done) - reset_device(rzs); + destroy_device(zram); + if (zram->init_done) + reset_device(zram); } - unregister_blkdev(ramzswap_major, "ramzswap"); + unregister_blkdev(zram_major, "zram"); kfree(devices); pr_debug("Cleanup done!\n"); } module_param(num_devices, uint, 0); -MODULE_PARM_DESC(num_devices, "Number of ramzswap devices"); +MODULE_PARM_DESC(num_devices, "Number of zram devices"); -module_init(ramzswap_init); -module_exit(ramzswap_exit); +module_init(zram_init); +module_exit(zram_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Nitin Gupta "); -MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); +MODULE_DESCRIPTION("Compressed RAM Block Device"); diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index 4d2e48a23474..945f9740442f 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h @@ -1,5 +1,5 @@ /* - * Compressed RAM based swap device + * Compressed RAM block device * * Copyright (C) 2008, 2009, 2010 Nitin Gupta * @@ -12,8 +12,8 @@ * Project home: http://compcache.googlecode.com */ -#ifndef _RAMZSWAP_DRV_H_ -#define _RAMZSWAP_DRV_H_ +#ifndef _ZRAM_DRV_H_ +#define _ZRAM_DRV_H_ #include #include @@ -41,7 +41,7 @@ struct zobj_header { /*-- Configurable parameters */ -/* Default ramzswap disk size: 25% of total RAM */ +/* Default zram disk size: 25% of total RAM */ static const unsigned default_disksize_perc_ram = 25; /* @@ -63,23 +63,20 @@ static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3; #define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) #define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) -/* Flags for ramzswap pages (table[page_no].flags) */ -enum rzs_pageflags { +/* Flags for zram pages (table[page_no].flags) */ +enum zram_pageflags { /* Page is stored uncompressed */ - RZS_UNCOMPRESSED, + ZRAM_UNCOMPRESSED, /* Page consists entirely of zeros */ - RZS_ZERO, + ZRAM_ZERO, - __NR_RZS_PAGEFLAGS, + __NR_ZRAM_PAGEFLAGS, }; /*-- Data structures */ -/* - * Allocated for each swap slot, indexed by page no. - * These table entries must fit exactly in a page. - */ +/* Allocated for each disk page */ struct table { struct page *page; u16 offset; @@ -87,17 +84,17 @@ struct table { u8 flags; } __attribute__((aligned(4))); -struct ramzswap_stats { +struct zram_stats { /* basic stats */ size_t compr_size; /* compressed size of pages stored - * needed to enforce memlimit */ /* more stats */ -#if defined(CONFIG_RAMZSWAP_STATS) +#if defined(CONFIG_ZRAM_STATS) u64 num_reads; /* failed + successful */ u64 num_writes; /* --do-- */ u64 failed_reads; /* should NEVER! happen */ u64 failed_writes; /* can happen when memory is too low */ - u64 invalid_io; /* non-swap I/O requests */ + u64 invalid_io; /* non-page-aligned I/O requests */ u64 notify_free; /* no. of swap slot free notifications */ u32 pages_zero; /* no. of zero filled pages */ u32 pages_stored; /* no. of pages currently stored */ @@ -106,7 +103,7 @@ struct ramzswap_stats { #endif }; -struct ramzswap { +struct zram { struct xv_pool *mem_pool; void *compress_workmem; void *compress_buffer; @@ -118,51 +115,50 @@ struct ramzswap { struct gendisk *disk; int init_done; /* - * This is limit on amount of *uncompressed* worth of data - * we can hold. When backing swap device is provided, it is - * set equal to device size. + * This is the limit on amount of *uncompressed* worth of data + * we can store in a disk. */ size_t disksize; /* bytes */ - struct ramzswap_stats stats; + struct zram_stats stats; }; /*-- */ /* Debugging and Stats */ -#if defined(CONFIG_RAMZSWAP_STATS) -static void rzs_stat_inc(u32 *v) +#if defined(CONFIG_ZRAM_STATS) +static void zram_stat_inc(u32 *v) { *v = *v + 1; } -static void rzs_stat_dec(u32 *v) +static void zram_stat_dec(u32 *v) { *v = *v - 1; } -static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v) +static void zram_stat64_inc(struct zram *zram, u64 *v) { - spin_lock(&rzs->stat64_lock); + spin_lock(&zram->stat64_lock); *v = *v + 1; - spin_unlock(&rzs->stat64_lock); + spin_unlock(&zram->stat64_lock); } -static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v) +static u64 zram_stat64_read(struct zram *zram, u64 *v) { u64 val; - spin_lock(&rzs->stat64_lock); + spin_lock(&zram->stat64_lock); val = *v; - spin_unlock(&rzs->stat64_lock); + spin_unlock(&zram->stat64_lock); return val; } #else -#define rzs_stat_inc(v) -#define rzs_stat_dec(v) -#define rzs_stat64_inc(r, v) -#define rzs_stat64_read(r, v) -#endif /* CONFIG_RAMZSWAP_STATS */ +#define zram_stat_inc(v) +#define zram_stat_dec(v) +#define zram_stat64_inc(r, v) +#define zram_stat64_read(r, v) +#endif /* CONFIG_ZRAM_STATS */ #endif diff --git a/drivers/staging/zram/zram_ioctl.h b/drivers/staging/zram/zram_ioctl.h index db94bcb42967..5c415fa4f17b 100644 --- a/drivers/staging/zram/zram_ioctl.h +++ b/drivers/staging/zram/zram_ioctl.h @@ -1,5 +1,5 @@ /* - * Compressed RAM based swap device + * Compressed RAM block device * * Copyright (C) 2008, 2009, 2010 Nitin Gupta * @@ -12,17 +12,16 @@ * Project home: http://compcache.googlecode.com */ -#ifndef _RAMZSWAP_IOCTL_H_ -#define _RAMZSWAP_IOCTL_H_ +#ifndef _ZRAM_IOCTL_H_ +#define _ZRAM_IOCTL_H_ -struct ramzswap_ioctl_stats { - u64 disksize; /* user specified or equal to backing swap - * size (if present) */ +struct zram_ioctl_stats { + u64 disksize; /* disksize in bytes (user specifies in KB) */ u64 num_reads; /* failed + successful */ u64 num_writes; /* --do-- */ u64 failed_reads; /* should NEVER! happen */ u64 failed_writes; /* can happen when memory is too low */ - u64 invalid_io; /* non-swap I/O requests */ + u64 invalid_io; /* non-page-aligned I/O requests */ u64 notify_free; /* no. of swap slot free notifications */ u32 pages_zero; /* no. of zero filled pages */ u32 good_compress_pct; /* no. of pages with compression ratio<=50% */ @@ -34,9 +33,9 @@ struct ramzswap_ioctl_stats { u64 mem_used_total; } __attribute__ ((packed, aligned(4))); -#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) -#define RZSIO_GET_STATS _IOR('z', 1, struct ramzswap_ioctl_stats) -#define RZSIO_INIT _IO('z', 2) -#define RZSIO_RESET _IO('z', 3) +#define ZRAMIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) +#define ZRAMIO_GET_STATS _IOR('z', 1, struct zram_ioctl_stats) +#define ZRAMIO_INIT _IO('z', 2) +#define ZRAMIO_RESET _IO('z', 3) #endif -- cgit v1.2.3 From 00ac9ba01d1868de1fc4645d952381966afa3ec2 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Tue, 1 Jun 2010 13:31:26 +0530 Subject: Staging: zram: Rename ramzswap to zram in documentation Related changes: - Included example to show usage as generic (non-swap) disk with ext4 filesystem. - Renamed rzscontrol to zramconfig to match with new device naming. Signed-off-by: Nitin Gupta Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram.txt | 51 ++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zram/zram.txt b/drivers/staging/zram/zram.txt index 9694acfeb43f..520edc1bea73 100644 --- a/drivers/staging/zram/zram.txt +++ b/drivers/staging/zram/zram.txt @@ -1,46 +1,57 @@ -ramzswap: Compressed RAM based swap device -------------------------------------------- +zram: Compressed RAM based block devices +---------------------------------------- Project home: http://compcache.googlecode.com/ * Introduction -The ramzswap module creates RAM based block devices which can (only) be used as -swap disks. Pages swapped to these devices are compressed and stored in memory -itself. See project home for use cases, performance numbers and a lot more. +The zram module creates RAM based block devices: /dev/ramX (X = 0, 1, ...). +Pages written to these disks are compressed and stored in memory itself. +These disks allow very fast I/O and compression provides good amounts of +memory savings. -Individual ramzswap devices are configured and initialized using rzscontrol -userspace utility as shown in examples below. See rzscontrol man page for more -details. +See project home for use cases, performance numbers and a lot more. + +Individual zram devices are configured and initialized using zramconfig +userspace utility as shown in examples below. See zramconfig man page for +more details. * Usage -Following shows a typical sequence of steps for using ramzswap. +Following shows a typical sequence of steps for using zram. 1) Load Modules: - modprobe ramzswap num_devices=4 - This creates 4 (uninitialized) devices: /dev/ramzswap{0,1,2,3} + modprobe zram num_devices=4 + This creates 4 (uninitialized) devices: /dev/zram{0,1,2,3} (num_devices parameter is optional. Default: 1) 2) Initialize: - Use rzscontrol utility to configure and initialize individual - ramzswap devices. Example: - rzscontrol /dev/ramzswap2 --init # uses default value of disksize_kb + Use zramconfig utility to configure and initialize individual + zram devices. For example: + zramconfig /dev/zram0 --init # uses default value of disksize_kb + zramconfig /dev/zram1 --disksize_kb=102400 # 100MB /dev/zram1 - *See rzscontrol man page for more details and examples* + *See zramconfig man page for more details and examples* 3) Activate: - swapon /dev/ramzswap2 # or any other initialized ramzswap device + mkswap /dev/zram0 + swapon /dev/zram0 + + mkfs.ext4 /dev/zram1 + mount /dev/zram1 /tmp 4) Stats: - rzscontrol /dev/ramzswap2 --stats + zramconfig /dev/zram0 --stats + zramconfig /dev/zram1 --stats 5) Deactivate: - swapoff /dev/ramzswap2 + swapoff /dev/zram0 + umount /dev/zram1 6) Reset: - rzscontrol /dev/ramzswap2 --reset - (This frees all the memory allocated for this device). + zramconfig /dev/zram0 --reset + zramconfig /dev/zram1 --reset + (This frees memory allocated for the given device). Please report any problems at: -- cgit v1.2.3 From 98a62bb7bc55c239c6ecc21e2fdbfa5df7690b30 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 23 May 2010 03:00:02 -0400 Subject: Staging: iio: standardize kconfig/makefile spacing/style Standardize the spacing/style across the IIO build files: - comment block in Kconfigs - newlines at ends of files - trailing lines at ends of files - indent with one tab, not spaces or mixed Signed-off-by: Mike Frysinger Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Makefile | 3 +-- drivers/staging/iio/accel/Kconfig | 50 ++++++++++++++++++------------------ drivers/staging/iio/accel/Makefile | 3 ++- drivers/staging/iio/adc/Makefile | 2 +- drivers/staging/iio/gyro/Makefile | 2 +- drivers/staging/iio/imu/Kconfig | 8 +++--- drivers/staging/iio/imu/Makefile | 3 ++- drivers/staging/iio/light/Kconfig | 1 - drivers/staging/iio/trigger/Makefile | 3 ++- 9 files changed, 38 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 3502b39f0847..fff717e38366 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -14,5 +14,4 @@ obj-y += adc/ obj-y += gyro/ obj-y += imu/ obj-y += light/ - -obj-y += trigger/ \ No newline at end of file +obj-y += trigger/ diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index b4e57d1bc87d..5926c03be1a5 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -4,29 +4,29 @@ comment "Accelerometers" config ADIS16209 - tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" - depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER - help - Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer - and accelerometer. + tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer + and accelerometer. config ADIS16220 - tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor driver" - depends on SPI - help - Say yes here to build support for Analog Devices adis16220 programmable - digital vibration sensor. + tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor" + depends on SPI + help + Say yes here to build support for Analog Devices adis16220 programmable + digital vibration sensor. config ADIS16240 - tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" - depends on SPI - select IIO_TRIGGER if IIO_RING_BUFFER - select IIO_SW_RING if IIO_RING_BUFFER - help - Say yes here to build support for Analog Devices adis16240 programmable - impact Sensor and recorder. + tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices adis16240 programmable + impact Sensor and recorder. config KXSD9 tristate "Kionix KXSD9 Accelerometer Driver" @@ -46,9 +46,9 @@ config LIS3L02DQ and an event interface via a character device. config SCA3000 - depends on IIO_RING_BUFFER - depends on SPI - tristate "VTI SCA3000 series accelerometers" - help - Say yes here to build support for the VTI SCA3000 series of SPI - accelerometers. These devices use a hardware ring buffer. \ No newline at end of file + depends on IIO_RING_BUFFER + depends on SPI + tristate "VTI SCA3000 series accelerometers" + help + Say yes here to build support for the VTI SCA3000 series of SPI + accelerometers. These devices use a hardware ring buffer. diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index c34b13634c2d..ff84703a16f6 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -1,6 +1,7 @@ # # Makefile for industrial I/O accelerometer drivers # + adis16209-y := adis16209_core.o adis16209-$(CONFIG_IIO_RING_BUFFER) += adis16209_ring.o adis16209_trigger.o obj-$(CONFIG_ADIS16209) += adis16209.o @@ -19,4 +20,4 @@ lis3l02dq-$(CONFIG_IIO_RING_BUFFER) += lis3l02dq_ring.o obj-$(CONFIG_LIS3L02DQ) += lis3l02dq.o sca3000-y := sca3000_core.o sca3000_ring.o -obj-$(CONFIG_SCA3000) += sca3000.o \ No newline at end of file +obj-$(CONFIG_SCA3000) += sca3000.o diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index 18c9376ecbb2..688510fd8bbb 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -1,4 +1,4 @@ - +# # Makefile for industrial I/O ADC drivers # diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile index 6d2c547686cb..b5f0dc01122c 100644 --- a/drivers/staging/iio/gyro/Makefile +++ b/drivers/staging/iio/gyro/Makefile @@ -1,4 +1,4 @@ - +# # Makefile for digital gyroscope sensor drivers # diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig index 6308d6faad57..48a712e74f98 100644 --- a/drivers/staging/iio/imu/Kconfig +++ b/drivers/staging/iio/imu/Kconfig @@ -24,10 +24,10 @@ config ADIS16350 config ADIS16400 tristate "Analog Devices ADIS16400/5 IMU SPI driver" - depends on SPI + depends on SPI select IIO_SW_RING select IIO_RING_BUFFER select IIO_TRIGGER - help - Say yes here to build support for Analog Devices adis16400/5 triaxial - inertial sensor with Magnetometer. \ No newline at end of file + help + Say yes here to build support for Analog Devices adis16400/5 triaxial + inertial sensor with Magnetometer. diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile index 31df7359e20f..f3b450b66113 100644 --- a/drivers/staging/iio/imu/Makefile +++ b/drivers/staging/iio/imu/Makefile @@ -1,6 +1,7 @@ # # Makefile for Inertial Measurement Units # + adis16300-y := adis16300_core.o adis16300-$(CONFIG_IIO_RING_BUFFER) += adis16300_ring.o adis16300_trigger.o obj-$(CONFIG_ADIS16300) += adis16300.o @@ -11,4 +12,4 @@ obj-$(CONFIG_ADIS16350) += adis16350.o adis16400-y := adis16400_core.o adis16400-$(CONFIG_IIO_RING_BUFFER) += adis16400_ring.o adis16400_trigger.o -obj-$(CONFIG_ADIS16400) += adis16400.o \ No newline at end of file +obj-$(CONFIG_ADIS16400) += adis16400.o diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index 80cb6e590fbb..3ddc478e6182 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -12,4 +12,3 @@ config SENSORS_TSL2563 This driver can also be built as a module. If so, the module will be called tsl2563. - diff --git a/drivers/staging/iio/trigger/Makefile b/drivers/staging/iio/trigger/Makefile index e5f96d2fe64a..10aeca5e347a 100644 --- a/drivers/staging/iio/trigger/Makefile +++ b/drivers/staging/iio/trigger/Makefile @@ -1,5 +1,6 @@ # # Makefile for triggers not associated with iio-devices # + obj-$(CONFIG_IIO_PERIODIC_RTC_TRIGGER) += iio-trig-periodic-rtc.o -obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o \ No newline at end of file +obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o -- cgit v1.2.3 From c608cb012e150d5c24b400ea89000105134bd564 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 23 May 2010 03:10:30 -0400 Subject: Staging: iio: kill off spurious semicolons A bunch of IIO files contain spurious semicolons after function definitions and case statements and if statements. Guess people really like this thing, but kill them anyways so they'll stop spreading via copy & paste with new drivers. Signed-off-by: Mike Frysinger Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/lis3l02dq.h | 19 ++++++++++++------- drivers/staging/iio/accel/sca3000.h | 14 +++++++++----- drivers/staging/iio/accel/sca3000_core.c | 14 +++++++------- drivers/staging/iio/adc/max1363.h | 14 ++++++++------ drivers/staging/iio/adc/max1363_core.c | 4 ++-- drivers/staging/iio/adc/max1363_ring.c | 4 ++-- 6 files changed, 40 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index e76a97937a36..0ffa0bbdcd4f 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -199,11 +199,13 @@ int lis3l02dq_initialize_ring(struct iio_ring_buffer *ring); void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring); #else /* CONFIG_IIO_RING_BUFFER */ -static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) {}; +static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) +{ +} static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) { return 0; -}; +} static inline ssize_t lis3l02dq_read_accel_from_ring(struct device *dev, @@ -211,18 +213,21 @@ lis3l02dq_read_accel_from_ring(struct device *dev, char *buf) { return 0; -}; +} static int lis3l02dq_configure_ring(struct iio_dev *indio_dev) { return 0; -}; +} static inline void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev) -{}; +{ +} static inline int lis3l02dq_initialize_ring(struct iio_ring_buffer *ring) { return 0; -}; -static inline void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring) {}; +} +static inline void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} #endif /* CONFIG_IIO_RING_BUFFER */ #endif /* SPI_LIS3L02DQ_H_ */ diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index e5321999b263..09d9470bb9a0 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -242,7 +242,7 @@ static inline int sca3000_11bit_convert(uint8_t msb, uint8_t lsb) val |= (val & (1 << 12)) ? 0xE000 : 0; return val; -}; +} static inline int sca3000_13bit_convert(uint8_t msb, uint8_t lsb) { @@ -253,7 +253,7 @@ static inline int sca3000_13bit_convert(uint8_t msb, uint8_t lsb) val |= (val & (1 << 12)) ? 0xE000 : 0; return val; -}; +} #ifdef CONFIG_IIO_RING_BUFFER @@ -286,15 +286,19 @@ void sca3000_unconfigure_ring(struct iio_dev *indio_dev); void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring); #else -static inline void sca3000_register_ring_funcs(struct iio_dev *indio_dev) {}; +static inline void sca3000_register_ring_funcs(struct iio_dev *indio_dev) +{ +} static inline int sca3000_register_ring_access_and_init(struct iio_dev *indio_dev) { return 0; -}; +} -static inline void sca3000_ring_int_process(u8 val, void *ring) {}; +static inline void sca3000_ring_int_process(u8 val, void *ring) +{ +} #endif diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index d4f82c39f335..b78b6b66ffe0 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -387,7 +387,7 @@ sca3000_show_available_measurement_modes(struct device *dev, case SCA3000_OP_MODE_BYPASS: len += sprintf(buf + len, ", 1 - bypass mode"); break; - }; + } switch (st->info->option_mode_2) { case SCA3000_OP_MODE_WIDE: len += sprintf(buf + len, ", 2 - wide mode"); @@ -433,7 +433,7 @@ sca3000_show_measurement_mode(struct device *dev, case SCA3000_OP_MODE_BYPASS: len += sprintf(buf + len, "1 - bypass mode\n"); break; - }; + } break; case SCA3000_MEAS_MODE_OP_2: switch (st->info->option_mode_2) { @@ -442,7 +442,7 @@ sca3000_show_measurement_mode(struct device *dev, break; } break; - }; + } error_ret: mutex_unlock(&st->lock); @@ -559,7 +559,7 @@ static ssize_t sca3000_read_av_freq(struct device *dev, st->info->option_mode_2_freq/2, st->info->option_mode_2_freq/4); break; - }; + } kfree(rx); return len; error_ret: @@ -590,7 +590,7 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st, case SCA3000_MEAS_MODE_OP_2: *base_freq = info->option_mode_2_freq; break; - }; + } kfree(rx); error_ret: return ret; @@ -627,8 +627,8 @@ static ssize_t sca3000_read_frequency(struct device *dev, case 0x02: len = sprintf(buf, "%d\n", base_freq/4); break; - }; - kfree(rx); + } + kfree(rx); return len; error_ret_mut: mutex_unlock(&st->lock); diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h index 72cf36709368..6da468bf7d6f 100644 --- a/drivers/staging/iio/adc/max1363.h +++ b/drivers/staging/iio/adc/max1363.h @@ -147,7 +147,7 @@ enum max1363_channels { max1363_in1min0, max1363_in3min2, max1363_in5min4, max1363_in7min6, max1363_in9min8, max1363_in11min10, - }; +}; /* This must be maintained along side the max1363_mode_table in max1363_core */ enum max1363_modes { @@ -237,25 +237,27 @@ void max1363_uninitialize_ring(struct iio_ring_buffer *ring); static inline void max1363_uninitialize_ring(struct iio_ring_buffer *ring) { -}; +} static inline int max1363_initialize_ring(struct iio_ring_buffer *ring) { return 0; -}; +} int max1363_single_channel_from_ring(long mask, struct max1363_state *st) { return -EINVAL; -}; +} static inline int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) { return 0; -}; +} -static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) {}; +static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) +{ +} #endif /* CONFIG_MAX1363_RING_BUFFER */ #endif /* _MAX1363_H_ */ diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 905f8560d31f..fc980146e2ba 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -148,7 +148,7 @@ const struct max1363_mode mask)) return &max1363_mode_table[ci->mode_list[i]]; return NULL; -}; +} static ssize_t max1363_show_precision(struct device *dev, struct device_attribute *attr, @@ -935,7 +935,7 @@ static int __devinit max1363_probe(struct i2c_client *client, if (!strcmp(max1363_chip_info_tbl[i].name, id->name)) { st->chip_info = &max1363_chip_info_tbl[i]; break; - }; + } /* Unsupported chip */ if (!st->chip_info) { dev_err(&client->dev, "%s is not supported\n", id->name); diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index 56688dc9c92f..a49b3d7aae9f 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -262,9 +262,9 @@ void max1363_ring_cleanup(struct iio_dev *indio_dev) void max1363_uninitialize_ring(struct iio_ring_buffer *ring) { iio_ring_buffer_unregister(ring); -}; +} int max1363_initialize_ring(struct iio_ring_buffer *ring) { return iio_ring_buffer_register(ring, 0); -}; +} -- cgit v1.2.3 From 1cb6c1f59431f16e46f0d07398cc789ee0a26731 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 23 May 2010 03:10:35 -0400 Subject: Staging: iio: pull in slab.h for kmalloc funcs These drivers use kzalloc() but don't include slab.h. They currently build though because the spi.h header will pull in slab.h for us. But rather than rely on that behavior forever, include slab.h explicitly. Signed-off-by: Mike Frysinger Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16209_core.c | 2 +- drivers/staging/iio/accel/adis16209_ring.c | 1 + drivers/staging/iio/accel/adis16220_core.c | 2 +- drivers/staging/iio/accel/adis16240_core.c | 2 +- drivers/staging/iio/accel/adis16240_ring.c | 1 + drivers/staging/iio/gyro/adis16260_core.c | 2 +- drivers/staging/iio/gyro/adis16260_ring.c | 1 + drivers/staging/iio/imu/adis16300_core.c | 2 +- drivers/staging/iio/imu/adis16300_ring.c | 1 + drivers/staging/iio/imu/adis16350_core.c | 2 +- drivers/staging/iio/imu/adis16350_ring.c | 1 + drivers/staging/iio/imu/adis16400_core.c | 2 +- drivers/staging/iio/imu/adis16400_ring.c | 1 + 13 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index ac375c50f56f..b3acdc37e354 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 533e28574910..8959ad85bbac 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 6de439fd1675..fefeca281cb9 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 54fd6d77412f..316022f25b19 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index 26b677bd84c0..490d80eafbaa 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index c93f4d580fce..f0246a424739 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index 4c4390ca6d73..2fe7f02d3a21 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c index 5a7e5ef9bc5d..bf02fbedee9f 100644 --- a/drivers/staging/iio/imu/adis16300_core.c +++ b/drivers/staging/iio/imu/adis16300_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c index 76cf8a6f3c3f..9c01994f40d4 100644 --- a/drivers/staging/iio/imu/adis16300_ring.c +++ b/drivers/staging/iio/imu/adis16300_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/iio/imu/adis16350_core.c b/drivers/staging/iio/imu/adis16350_core.c index 0edde73ce5c2..145966b04d4c 100644 --- a/drivers/staging/iio/imu/adis16350_core.c +++ b/drivers/staging/iio/imu/adis16350_core.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/imu/adis16350_ring.c b/drivers/staging/iio/imu/adis16350_ring.c index 5e9716ea7c77..2a0a465a42cb 100644 --- a/drivers/staging/iio/imu/adis16350_ring.c +++ b/drivers/staging/iio/imu/adis16350_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index e69e2ce47da3..8957985358d0 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -21,7 +21,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 5529b32bd2e3..66a91ada954a 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From de6c37ad2a602d0123699774cf4b2e3f561846bd Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 7 Jun 2010 20:54:07 +0100 Subject: Staging: iio: Add mailing list to the TODO file. As suggested by Charles Clement Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO index 15da0c2bb784..898cba1c939f 100644 --- a/drivers/staging/iio/TODO +++ b/drivers/staging/iio/TODO @@ -66,4 +66,4 @@ Documentation 2) Some device require indvidual docs. Contact: Jonathan Cameron . -Mailing list: LKML. +Mailing list: linux-iio@vger.kernel.org -- cgit v1.2.3 From 794e7d9df26a42b05320a92cef76cd2c150a91e6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Jun 2010 15:32:07 +0200 Subject: Staging: iio: add file pointer to sysfs callbacks The sysfs attribute call backs take a file pointer these days. This was added in 2c3c8bea6088 "sysfs: add struct file* to bin_attr callbacks" Signed-off-by: Dan Carpenter Cc: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16220_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index fefeca281cb9..7daa3d72286c 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -414,7 +414,7 @@ static ssize_t adis16220_capture_buffer_read(struct adis16220_state *st, return count; } -static ssize_t adis16220_accel_bin_read(struct kobject *kobj, +static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, @@ -438,7 +438,7 @@ static struct bin_attribute accel_bin = { .size = ADIS16220_CAPTURE_SIZE, }; -static ssize_t adis16220_adc1_bin_read(struct kobject *kobj, +static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) @@ -461,7 +461,7 @@ static struct bin_attribute adc1_bin = { .size = ADIS16220_CAPTURE_SIZE, }; -static ssize_t adis16220_adc2_bin_read(struct kobject *kobj, +static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) -- cgit v1.2.3 From ee9a691e08360a22a8eaefb1289bc2e9cfd493a0 Mon Sep 17 00:00:00 2001 From: Barry Song <21cnbao@gmail.com> Date: Fri, 4 Jun 2010 17:19:52 +0800 Subject: Staging: iio: adis16300: fix some minor issues and clean-up 1. add delay between spi transfers 2. move burst read to ring function 3. clean-up Signed-off-by: Barry Song <21cnbao@gmail.com> Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16300.h | 6 -- drivers/staging/iio/imu/adis16300_core.c | 151 ++++++++++++++----------------- drivers/staging/iio/imu/adis16300_ring.c | 54 ++++++++++- 3 files changed, 117 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/imu/adis16300.h b/drivers/staging/iio/imu/adis16300.h index 1c7ea5c840ef..b050067d502b 100644 --- a/drivers/staging/iio/imu/adis16300.h +++ b/drivers/staging/iio/imu/adis16300.h @@ -115,14 +115,8 @@ struct adis16300_state { struct mutex buf_lock; }; -int adis16300_spi_read_burst(struct device *dev, u8 *rx); - int adis16300_set_irq(struct device *dev, bool enable); -int adis16300_reset(struct device *dev); - -int adis16300_check_status(struct device *dev); - #ifdef CONFIG_IIO_RING_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c index bf02fbedee9f..28667e8f26cd 100644 --- a/drivers/staging/iio/imu/adis16300_core.c +++ b/drivers/staging/iio/imu/adis16300_core.c @@ -29,10 +29,7 @@ #define DRIVER_NAME "adis16300" -/* At the moment the spi framework doesn't allow global setting of cs_change. - * It's in the likely to be added comment at the top of spi.h. - * This means that use cannot be made of spi_write etc. - */ +static int adis16300_check_status(struct device *dev); /** * adis16300_spi_write_reg_8() - write single byte to a register @@ -79,11 +76,13 @@ static int adis16300_spi_write_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, + .delay_usecs = 75, }, { .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, + .delay_usecs = 75, }, }; @@ -122,12 +121,14 @@ static int adis16300_spi_read_reg_16(struct device *dev, .tx_buf = st->tx, .bits_per_word = 8, .len = 2, - .cs_change = 0, + .cs_change = 1, + .delay_usecs = 75, }, { .rx_buf = st->rx, .bits_per_word = 8, .len = 2, - .cs_change = 0, + .cs_change = 1, + .delay_usecs = 75, }, }; @@ -154,54 +155,6 @@ error_ret: return ret; } -/** - * adis16300_spi_read_burst() - read all data registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read (min size is 24 bytes) - **/ -int adis16300_spi_read_burst(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - u32 old_speed_hz = st->us->max_speed_hz; - int ret; - - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 0, - }, { - .rx_buf = rx, - .bits_per_word = 8, - .len = 18, - .cs_change = 0, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16300_READ_REG(ADIS16300_GLOB_CMD); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - - st->us->max_speed_hz = min(ADIS16300_SPI_BURST, old_speed_hz); - spi_setup(st->us); - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - st->us->max_speed_hz = old_speed_hz; - spi_setup(st->us); - mutex_unlock(&st->buf_lock); - return ret; -} - static ssize_t adis16300_spi_read_signed(struct device *dev, struct device_attribute *attr, char *buf, @@ -240,6 +193,24 @@ static ssize_t adis16300_read_12bit_unsigned(struct device *dev, return sprintf(buf, "%u\n", val & 0x0FFF); } +static ssize_t adis16300_read_14bit_unsigned(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + if (val & ADIS16300_ERROR_ACTIVE) + adis16300_check_status(dev); + + return sprintf(buf, "%u\n", val & 0x3FFF); +} + static ssize_t adis16300_read_14bit_signed(struct device *dev, struct device_attribute *attr, char *buf) @@ -356,6 +327,18 @@ static ssize_t adis16300_write_frequency(struct device *dev, return ret ? ret : len; } +static int adis16300_reset(struct device *dev) +{ + int ret; + ret = adis16300_spi_write_reg_8(dev, + ADIS16300_GLOB_CMD, + ADIS16300_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + static ssize_t adis16300_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -371,8 +354,6 @@ static ssize_t adis16300_write_reset(struct device *dev, return -1; } - - int adis16300_set_irq(struct device *dev, bool enable) { int ret; @@ -396,32 +377,37 @@ error_ret: return ret; } -int adis16300_reset(struct device *dev) +/* Power down the device */ +static int adis16300_stop_device(struct device *dev) { int ret; - ret = adis16300_spi_write_reg_8(dev, - ADIS16300_GLOB_CMD, - ADIS16300_GLOB_CMD_SW_RESET); + u16 val = ADIS16300_SLP_CNT_POWER_OFF; + + ret = adis16300_spi_write_reg_16(dev, ADIS16300_SLP_CNT, val); if (ret) - dev_err(dev, "problem resetting device"); + dev_err(dev, "problem with turning device off: SLP_CNT"); return ret; } -/* Power down the device */ -static int adis16300_stop_device(struct device *dev) +static int adis16300_self_test(struct device *dev) { int ret; - u16 val = ADIS16300_SLP_CNT_POWER_OFF; + ret = adis16300_spi_write_reg_16(dev, + ADIS16300_MSC_CTRL, + ADIS16300_MSC_CTRL_MEM_TEST); + if (ret) { + dev_err(dev, "problem starting self test"); + goto err_ret; + } - ret = adis16300_spi_write_reg_16(dev, ADIS16300_SLP_CNT, val); - if (ret) - dev_err(dev, "problem with turning device off: SLP_CNT"); + adis16300_check_status(dev); +err_ret: return ret; } -int adis16300_check_status(struct device *dev) +static int adis16300_check_status(struct device *dev) { u16 status; int ret; @@ -483,6 +469,11 @@ static int adis16300_initial_setup(struct adis16300_state *st) } /* Do self test */ + ret = adis16300_self_test(dev); + if (ret) { + dev_err(dev, "self test failure"); + goto err_ret; + } /* Read status register to check the result */ ret = adis16300_check_status(dev); @@ -526,7 +517,7 @@ static IIO_DEV_ATTR_ACCEL_Z_OFFSET(S_IWUSR | S_IRUGO, adis16300_write_16bit, ADIS16300_ZACCL_OFF); -static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16300_read_14bit_signed, +static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16300_read_14bit_unsigned, ADIS16300_SUPPLY_OUT); static IIO_CONST_ATTR(in_supply_scale, "0.00242"); @@ -548,7 +539,7 @@ static IIO_DEV_ATTR_INCLI_Y(adis16300_read_13bit_signed, ADIS16300_YINCLI_OUT); static IIO_CONST_ATTR(incli_scale, "0.044 d"); -static IIO_DEV_ATTR_TEMP_RAW(adis16300_read_12bit_signed); +static IIO_DEV_ATTR_TEMP_RAW(adis16300_read_12bit_unsigned); static IIO_CONST_ATTR(temp_offset, "198.16 K"); static IIO_CONST_ATTR(temp_scale, "0.14 K"); @@ -659,15 +650,7 @@ static int __devinit adis16300_probe(struct spi_device *spi) goto error_unreg_ring_funcs; } - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { -#if 0 /* fixme: here we should support */ - iio_init_work_cont(&st->work_cont_thresh, - NULL, - adis16300_thresh_handler_bh_no_check, - 0, - 0, - st); -#endif + if (spi->irq) { ret = iio_register_interrupt_line(spi->irq, st->indio_dev, 0, @@ -688,10 +671,9 @@ static int __devinit adis16300_probe(struct spi_device *spi) return 0; error_remove_trigger: - if (st->indio_dev->modes & INDIO_RING_TRIGGERED) - adis16300_remove_trigger(st->indio_dev); + adis16300_remove_trigger(st->indio_dev); error_unregister_line: - if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + if (spi->irq) iio_unregister_interrupt_line(st->indio_dev, 0); error_uninitialize_ring: adis16300_uninitialize_ring(st->indio_dev->ring); @@ -712,7 +694,6 @@ error_ret: return ret; } -/* fixme, confirm ordering in this function */ static int adis16300_remove(struct spi_device *spi) { int ret; @@ -726,12 +707,12 @@ static int adis16300_remove(struct spi_device *spi) flush_scheduled_work(); adis16300_remove_trigger(indio_dev); - if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + if (spi->irq) iio_unregister_interrupt_line(indio_dev, 0); adis16300_uninitialize_ring(indio_dev->ring); - adis16300_unconfigure_ring(indio_dev); iio_device_unregister(indio_dev); + adis16300_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); kfree(st); diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c index 9c01994f40d4..17ceb72e0bfe 100644 --- a/drivers/staging/iio/imu/adis16300_ring.c +++ b/drivers/staging/iio/imu/adis16300_ring.c @@ -27,7 +27,7 @@ static inline u16 combine_8_to_16(u8 lower, u8 upper) return _lower | (_upper << 8); } -static IIO_SCAN_EL_C(supply, ADIS16300_SCAN_SUPPLY, IIO_SIGNED(14), +static IIO_SCAN_EL_C(supply, ADIS16300_SCAN_SUPPLY, IIO_UNSIGNED(14), ADIS16300_SUPPLY_OUT, NULL); static IIO_SCAN_EL_C(gyro_x, ADIS16300_SCAN_GYRO_X, IIO_SIGNED(14), @@ -40,9 +40,9 @@ static IIO_SCAN_EL_C(accel_y, ADIS16300_SCAN_ACC_Y, IIO_SIGNED(14), static IIO_SCAN_EL_C(accel_z, ADIS16300_SCAN_ACC_Z, IIO_SIGNED(14), ADIS16300_ZACCL_OUT, NULL); -static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_SIGNED(12), +static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_UNSIGNED(12), ADIS16300_TEMP_OUT, NULL); -static IIO_SCAN_EL_C(adc_0, ADIS16300_SCAN_ADC_0, IIO_SIGNED(12), +static IIO_SCAN_EL_C(adc_0, ADIS16300_SCAN_ADC_0, IIO_UNSIGNED(12), ADIS16300_AUX_ADC, NULL); static IIO_SCAN_EL_C(incli_x, ADIS16300_SCAN_INCLI_X, IIO_SIGNED(12), @@ -88,6 +88,54 @@ static void adis16300_poll_func_th(struct iio_dev *indio_dev) */ } +/** + * adis16300_spi_read_burst() - read all data registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read (min size is 24 bytes) + **/ +static int adis16300_spi_read_burst(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16300_state *st = iio_dev_get_devdata(indio_dev); + u32 old_speed_hz = st->us->max_speed_hz; + int ret; + + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 0, + }, { + .rx_buf = rx, + .bits_per_word = 8, + .len = 18, + .cs_change = 0, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16300_READ_REG(ADIS16300_GLOB_CMD); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + + st->us->max_speed_hz = ADIS16300_SPI_BURST; + spi_setup(st->us); + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + st->us->max_speed_hz = old_speed_hz; + spi_setup(st->us); + mutex_unlock(&st->buf_lock); + return ret; +} + /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device * specific to be rolled into the core. */ -- cgit v1.2.3 From 3fd66da1d529c65488a84f54d8da7bed972fd14f Mon Sep 17 00:00:00 2001 From: Barry Song <21cnbao@gmail.com> Date: Fri, 4 Jun 2010 17:19:53 +0800 Subject: Staging: iio: adis16400: fix some minor issues and clean-up 1. move adis16400_spi_read_burst() to adis16400_ring.c since it is only called there 2. add the lost calling to adis16400_self_test() 3. codes cleanup Signed-off-by: Barry Song <21cnbao@gmail.com> Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400.h | 6 --- drivers/staging/iio/imu/adis16400_core.c | 84 ++++++++------------------------ drivers/staging/iio/imu/adis16400_ring.c | 48 ++++++++++++++++++ 3 files changed, 68 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index 5a69a7ab91ce..04bae36ed5ab 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -147,14 +147,8 @@ struct adis16400_state { struct mutex buf_lock; }; -int adis16400_spi_read_burst(struct device *dev, u8 *rx); - int adis16400_set_irq(struct device *dev, bool enable); -int adis16400_reset(struct device *dev); - -int adis16400_check_status(struct device *dev); - #ifdef CONFIG_IIO_RING_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 8957985358d0..a668a90beb4f 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -36,6 +36,8 @@ #define DRIVER_NAME "adis16400" +static int adis16400_check_status(struct device *dev); + /* At the moment the spi framework doesn't allow global setting of cs_change. * It's in the likely to be added comment at the top of spi.h. * This means that use cannot be made of spi_write etc. @@ -161,54 +163,6 @@ error_ret: return ret; } -/** - * adis16400_spi_read_burst() - read all data registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read (min size is 24 bytes) - **/ -int adis16400_spi_read_burst(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16400_state *st = iio_dev_get_devdata(indio_dev); - u32 old_speed_hz = st->us->max_speed_hz; - int ret; - - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 0, - }, { - .rx_buf = rx, - .bits_per_word = 8, - .len = 24, - .cs_change = 1, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16400_READ_REG(ADIS16400_GLOB_CMD); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - - st->us->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz); - spi_setup(st->us); - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - st->us->max_speed_hz = old_speed_hz; - spi_setup(st->us); - mutex_unlock(&st->buf_lock); - return ret; -} - static ssize_t adis16400_spi_read_signed(struct device *dev, struct device_attribute *attr, char *buf, @@ -277,7 +231,6 @@ static ssize_t adis16400_read_12bit_signed(struct device *dev, return ret; } - static ssize_t adis16400_write_16bit(struct device *dev, struct device_attribute *attr, const char *buf, @@ -349,6 +302,18 @@ static ssize_t adis16400_write_frequency(struct device *dev, return ret ? ret : len; } +static int adis16400_reset(struct device *dev) +{ + int ret; + ret = adis16400_spi_write_reg_8(dev, + ADIS16400_GLOB_CMD, + ADIS16400_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + static ssize_t adis16400_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -364,8 +329,6 @@ static ssize_t adis16400_write_reset(struct device *dev, return -1; } - - int adis16400_set_irq(struct device *dev, bool enable) { int ret; @@ -388,18 +351,6 @@ error_ret: return ret; } -int adis16400_reset(struct device *dev) -{ - int ret; - ret = adis16400_spi_write_reg_8(dev, - ADIS16400_GLOB_CMD, - ADIS16400_GLOB_CMD_SW_RESET); - if (ret) - dev_err(dev, "problem resetting device"); - - return ret; -} - /* Power down the device */ static int adis16400_stop_device(struct device *dev) { @@ -430,7 +381,7 @@ err_ret: return ret; } -int adis16400_check_status(struct device *dev) +static int adis16400_check_status(struct device *dev) { u16 status; int ret; @@ -496,6 +447,11 @@ static int adis16400_initial_setup(struct adis16400_state *st) } /* Do self test */ + ret = adis16400_self_test(dev); + if (ret) { + dev_err(dev, "self test failure"); + goto err_ret; + } /* Read status register to check the result */ ret = adis16400_check_status(dev); diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 66a91ada954a..5d94cdc2ea2d 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -97,6 +97,54 @@ static void adis16400_poll_func_th(struct iio_dev *indio_dev) */ } +/** + * adis16400_spi_read_burst() - read all data registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read (min size is 24 bytes) + **/ +static int adis16400_spi_read_burst(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16400_state *st = iio_dev_get_devdata(indio_dev); + u32 old_speed_hz = st->us->max_speed_hz; + int ret; + + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 0, + }, { + .rx_buf = rx, + .bits_per_word = 8, + .len = 24, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16400_READ_REG(ADIS16400_GLOB_CMD); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + + st->us->max_speed_hz = min(ADIS16400_SPI_BURST, old_speed_hz); + spi_setup(st->us); + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + st->us->max_speed_hz = old_speed_hz; + spi_setup(st->us); + mutex_unlock(&st->buf_lock); + return ret; +} + /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device * specific to be rolled into the core. */ -- cgit v1.2.3 From 00ae79463e026b8bc45c93a87aadf118f04069e0 Mon Sep 17 00:00:00 2001 From: Barry Song <21cnbao@gmail.com> Date: Fri, 4 Jun 2010 17:19:54 +0800 Subject: Staging: iio: adis16209/220/240/350: tuning spi delay to make hardware more stable Signed-off-by: Barry Song <21cnbao@gmail.com> Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16209_core.c | 6 ++++-- drivers/staging/iio/accel/adis16220_core.c | 12 ++++++------ drivers/staging/iio/accel/adis16240_core.c | 8 ++++---- drivers/staging/iio/imu/adis16350_core.c | 8 ++++---- 4 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b3acdc37e354..c696160fc2a0 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -76,11 +76,13 @@ static int adis16209_spi_write_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, + .delay_usecs = 30, }, { .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, + .delay_usecs = 30, }, }; @@ -120,13 +122,13 @@ static int adis16209_spi_read_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 20, + .delay_usecs = 30, }, { .rx_buf = st->rx, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 20, + .delay_usecs = 30, }, }; diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 7daa3d72286c..bb7d76539cd7 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -72,13 +72,13 @@ static int adis16220_spi_write_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; @@ -118,13 +118,13 @@ static int adis16220_spi_read_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .rx_buf = st->rx, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; @@ -291,9 +291,9 @@ static int adis16220_check_status(struct device *dev) if (status & ADIS16220_DIAG_STAT_FLASH_UPT) dev_err(dev, "Flash update failed\n"); if (status & ADIS16220_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 5.25V\n"); + dev_err(dev, "Power supply above 3.625V\n"); if (status & ADIS16220_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 4.75V\n"); + dev_err(dev, "Power supply below 3.15V\n"); error_ret: return ret; diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 316022f25b19..ba336cbea809 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -74,13 +74,13 @@ static int adis16240_spi_write_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; @@ -120,13 +120,13 @@ static int adis16240_spi_read_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .rx_buf = st->rx, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; diff --git a/drivers/staging/iio/imu/adis16350_core.c b/drivers/staging/iio/imu/adis16350_core.c index 145966b04d4c..0bb19a9d12f5 100644 --- a/drivers/staging/iio/imu/adis16350_core.c +++ b/drivers/staging/iio/imu/adis16350_core.c @@ -75,13 +75,13 @@ static int adis16350_spi_write_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; @@ -121,13 +121,13 @@ static int adis16350_spi_read_reg_16(struct device *dev, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, { .rx_buf = st->rx, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = 25, + .delay_usecs = 35, }, }; -- cgit v1.2.3 From e3613299b53dd35b99610d26779064965e0f091a Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Thu, 20 May 2010 23:54:34 +0200 Subject: Staging: adis16255: missing spacess in log messages added Signed-off-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/adis16255/adis16255.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/adis16255/adis16255.c b/drivers/staging/adis16255/adis16255.c index 55d66e290f7d..c3e6a4d5f334 100644 --- a/drivers/staging/adis16255/adis16255.c +++ b/drivers/staging/adis16255/adis16255.c @@ -303,7 +303,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis) if (status != 0) goto err; if (value != 0x0800) { - dev_warn(&spiadis->spi->dev, "Scale factor is none default" + dev_warn(&spiadis->spi->dev, "Scale factor is none default " "value (%.4x)\n", value); } @@ -338,7 +338,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis) status = -ENODEV; goto err; } else if (value & 0x3) { - dev_warn(&spiadis->spi->dev, "Sensor voltage" + dev_warn(&spiadis->spi->dev, "Sensor voltage " "out of range.\n"); status = -ENODEV; goto err; -- cgit v1.2.3 From 45f9f018967c3fc112a03a99a8fdfad3621407a7 Mon Sep 17 00:00:00 2001 From: Nanakos Chrysostomos Date: Fri, 28 May 2010 10:54:45 +0000 Subject: Staging: vme: devices: vme_user.c: Fix checkpatch.pl issues. Fix resolves checkpatch.pl issues for vme_user.c file. Signed-off-by: Nanakos Chrysostomos Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/devices/vme_user.c | 92 +++++++++++++++++----------------- 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index bc16fc070fd3..326991c7d47b 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -34,8 +34,8 @@ #include #include -#include -#include +#include +#include #include "../vme.h" #include "vme_user.h" @@ -48,19 +48,19 @@ static int bus_num; /* Currently Documentation/devices.txt defines the following for VME: * * 221 char VME bus - * 0 = /dev/bus/vme/m0 First master image - * 1 = /dev/bus/vme/m1 Second master image - * 2 = /dev/bus/vme/m2 Third master image - * 3 = /dev/bus/vme/m3 Fourth master image - * 4 = /dev/bus/vme/s0 First slave image - * 5 = /dev/bus/vme/s1 Second slave image - * 6 = /dev/bus/vme/s2 Third slave image - * 7 = /dev/bus/vme/s3 Fourth slave image - * 8 = /dev/bus/vme/ctl Control + * 0 = /dev/bus/vme/m0 First master image + * 1 = /dev/bus/vme/m1 Second master image + * 2 = /dev/bus/vme/m2 Third master image + * 3 = /dev/bus/vme/m3 Fourth master image + * 4 = /dev/bus/vme/s0 First slave image + * 5 = /dev/bus/vme/s1 Second slave image + * 6 = /dev/bus/vme/s2 Third slave image + * 7 = /dev/bus/vme/s3 Fourth slave image + * 8 = /dev/bus/vme/ctl Control * - * It is expected that all VME bus drivers will use the - * same interface. For interface documentation see - * http://www.vmelinux.org/. + * It is expected that all VME bus drivers will use the + * same interface. For interface documentation see + * http://www.vmelinux.org/. * * However the VME driver at http://www.vmelinux.org/ is rather old and doesn't * even support the tsi148 chipset (which has 8 master and 8 slave windows). @@ -137,12 +137,12 @@ static int __init vme_user_probe(struct device *, int, int); static int __exit vme_user_remove(struct device *, int, int); static struct file_operations vme_user_fops = { - .open = vme_user_open, - .release = vme_user_release, - .read = vme_user_read, - .write = vme_user_write, - .llseek = vme_user_llseek, - .unlocked_ioctl = vme_user_unlocked_ioctl, + .open = vme_user_open, + .release = vme_user_release, + .read = vme_user_read, + .write = vme_user_write, + .llseek = vme_user_llseek, + .unlocked_ioctl = vme_user_unlocked_ioctl, }; @@ -151,13 +151,13 @@ static struct file_operations vme_user_fops = { */ static void reset_counters(void) { - statistics.reads = 0; - statistics.writes = 0; - statistics.ioctls = 0; - statistics.irqs = 0; - statistics.berrs = 0; - statistics.dmaErrors = 0; - statistics.timeouts = 0; + statistics.reads = 0; + statistics.writes = 0; + statistics.ioctls = 0; + statistics.irqs = 0; + statistics.berrs = 0; + statistics.dmaErrors = 0; + statistics.timeouts = 0; } static int vme_user_open(struct inode *inode, struct file *file) @@ -216,21 +216,20 @@ static ssize_t resource_to_user(int minor, char __user *buf, size_t count, /* We copy to kernel buffer */ copied = vme_master_read(image[minor].resource, image[minor].kern_buf, count, *ppos); - if (copied < 0) { + if (copied < 0) return (int)copied; - } retval = __copy_to_user(buf, image[minor].kern_buf, (unsigned long)copied); if (retval != 0) { copied = (copied - retval); - printk("User copy failed\n"); + printk(KERN_INFO "User copy failed\n"); return -EINVAL; } } else { /* XXX Need to write this */ - printk("Currently don't support large transfers\n"); + printk(KERN_INFO "Currently don't support large transfers\n"); /* Map in pages from userspace */ /* Call vme_master_read to do the transfer */ @@ -264,7 +263,7 @@ static ssize_t resource_from_user(unsigned int minor, const char *buf, image[minor].kern_buf, copied, *ppos); } else { /* XXX Need to write this */ - printk("Currently don't support large transfers\n"); + printk(KERN_INFO "Currently don't support large transfers\n"); /* Map in pages from userspace */ /* Call vme_master_write to do the transfer */ @@ -313,7 +312,7 @@ static ssize_t buffer_from_user(unsigned int minor, const char *buf, } static ssize_t vme_user_read(struct file *file, char *buf, size_t count, - loff_t * ppos) + loff_t *ppos) { unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); ssize_t retval; @@ -337,7 +336,7 @@ static ssize_t vme_user_read(struct file *file, char *buf, size_t count, else okcount = count; - switch (type[minor]){ + switch (type[minor]) { case MASTER_MINOR: retval = resource_to_user(minor, buf, okcount, ppos); break; @@ -380,7 +379,7 @@ static ssize_t vme_user_write(struct file *file, const char *buf, size_t count, else okcount = count; - switch (type[minor]){ + switch (type[minor]) { case MASTER_MINOR: retval = resource_from_user(minor, buf, okcount, ppos); break; @@ -571,7 +570,7 @@ vme_user_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* * Unallocate a previously allocated buffer */ -static void buf_unalloc (int num) +static void buf_unalloc(int num) { if (image[num].kern_buf) { #ifdef VME_DEBUG @@ -594,8 +593,8 @@ static void buf_unalloc (int num) } static struct vme_driver vme_user_driver = { - .name = driver_name, - .probe = vme_user_probe, + .name = driver_name, + .probe = vme_user_probe, .remove = vme_user_remove, }; @@ -770,16 +769,16 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot) } /* Add sysfs Entries */ - for (i=0; i 0){ + while (i > 0) { i--; device_destroy(vme_user_sysfs_class, MKDEV(VME_MAJOR, i)); } @@ -845,9 +844,8 @@ static int __exit vme_user_remove(struct device *dev, int cur_bus, int cur_slot) int i; /* Remove sysfs Entries */ - for(i=0; i Date: Wed, 26 May 2010 17:59:11 +0200 Subject: Staging: vme: bridges: Add missing unlocks Add a spin_unlock and mutex_unlock missing on the error path. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E1; @@ * spin_lock(E1,...); <+... when != E1 if (...) { ... when != E1 * return ...; } ...+> * spin_unlock(E1,...); // Signed-off-by: Julia Lawall Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/bridges/vme_ca91cx42.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 0f9ea58ff717..16cf53e38a74 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -900,7 +900,8 @@ unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, /* Address must be 4-byte aligned */ if (pci_addr & 0x3) { dev_err(dev, "RMW Address not 4-byte aligned\n"); - return -EINVAL; + result = -EINVAL; + goto out; } /* Ensure RMW Disabled whilst configuring */ @@ -921,6 +922,7 @@ unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, /* Disable RMW */ iowrite32(0, bridge->base + SCYC_CTL); +out: spin_unlock(&(image->lock)); mutex_unlock(&(bridge->vme_rmw)); -- cgit v1.2.3 From 37a18632b00f0d1627556c532f719ad5a08b369f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 22 May 2010 10:27:02 +0200 Subject: Staging: dream: camera: Use memdup_user Use memdup_user when user data is immediately copied into the allocated region. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to,size,flag; position p; identifier l1,l2; @@ - to = \(kmalloc@p\|kzalloc@p\)(size,flag); + to = memdup_user(from,size); if ( - to==NULL + IS_ERR(to) || ...) { <+... when != goto l1; - -ENOMEM + PTR_ERR(to) ...+> } - if (copy_from_user(to, from, size) != 0) { - <+... when != goto l2; - -EFAULT - ...+> - } // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dream/camera/msm_vfe8x.c | 45 +++++++++----------------------- 1 file changed, 12 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dream/camera/msm_vfe8x.c b/drivers/staging/dream/camera/msm_vfe8x.c index e61fdba62838..d87d56f914de 100644 --- a/drivers/staging/dream/camera/msm_vfe8x.c +++ b/drivers/staging/dream/camera/msm_vfe8x.c @@ -644,17 +644,10 @@ static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) if (!axid) return -EFAULT; - axio = - kmalloc(sizeof(struct vfe_cmd_axi_output_config), - GFP_ATOMIC); - if (!axio) - return -ENOMEM; - - if (copy_from_user(axio, (void __user *)(vfecmd.value), - sizeof(struct vfe_cmd_axi_output_config))) { - kfree(axio); - return -EFAULT; - } + axio = memdup_user((void __user *)(vfecmd.value), + sizeof(struct vfe_cmd_axi_output_config)); + if (IS_ERR(axio)) + return PTR_ERR(axio); vfe_config_axi(OUTPUT_1, axid, axio); vfe_axi_output_config(axio); @@ -669,17 +662,10 @@ static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) if (!axid) return -EFAULT; - axio = - kmalloc(sizeof(struct vfe_cmd_axi_output_config), - GFP_ATOMIC); - if (!axio) - return -ENOMEM; - - if (copy_from_user(axio, (void __user *)(vfecmd.value), - sizeof(struct vfe_cmd_axi_output_config))) { - kfree(axio); - return -EFAULT; - } + axio = memdup_user((void __user *)(vfecmd.value), + sizeof(struct vfe_cmd_axi_output_config)); + if (IS_ERR(axio)) + return PTR_ERR(axio); vfe_config_axi(OUTPUT_2, axid, axio); @@ -694,17 +680,10 @@ static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) if (!axid) return -EFAULT; - axio = - kmalloc(sizeof(struct vfe_cmd_axi_output_config), - GFP_ATOMIC); - if (!axio) - return -ENOMEM; - - if (copy_from_user(axio, (void __user *)(vfecmd.value), - sizeof(struct vfe_cmd_axi_output_config))) { - kfree(axio); - return -EFAULT; - } + axio = memdup_user((void __user *)(vfecmd.value), + sizeof(struct vfe_cmd_axi_output_config)); + if (IS_ERR(axio)) + return PTR_ERR(axio); vfe_config_axi(OUTPUT_1_AND_2, axid, axio); -- cgit v1.2.3 From 9a3dfa0555130952517b9a9c3918729495aa709a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 25 May 2010 04:20:30 +0100 Subject: Staging: rtl8192su: Clean up in case of an error in module initialisation Currently various resources may be leaked in case of an error. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192su/r8192U_core.c | 43 +++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 447d6474a70c..1b4ff90f43ac 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -990,10 +990,11 @@ static int proc_get_stats_rx(char *page, char **start, return len; } -void rtl8192_proc_module_init(void) +int rtl8192_proc_module_init(void) { RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); + return rtl8192_proc ? 0 : -ENOMEM; } @@ -7473,35 +7474,63 @@ static int __init rtl8192_usb_module_init(void) ret = ieee80211_crypto_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret); - return ret; + goto fail_crypto; } ret = ieee80211_crypto_tkip_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret); - return ret; + goto fail_crypto_tkip; } ret = ieee80211_crypto_ccmp_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret); - return ret; + goto fail_crypto_ccmp; } ret = ieee80211_crypto_wep_init(); if (ret) { printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret); - return ret; + goto fail_crypto_wep; } printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n"); printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n"); RT_TRACE(COMP_INIT, "Initializing module"); RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT); - rtl8192_proc_module_init(); - return usb_register(&rtl8192_usb_driver); + + ret = rtl8192_proc_module_init(); + if (ret) { + pr_err("rtl8192_proc_module_init() failed %d\n", ret); + goto fail_proc; + } + + ret = usb_register(&rtl8192_usb_driver); + if (ret) { + pr_err("usb_register() failed %d\n", ret); + goto fail_usb; + } + + return 0; + +fail_usb: + rtl8192_proc_module_remove(); +fail_proc: + ieee80211_crypto_wep_exit(); +fail_crypto_wep: + ieee80211_crypto_ccmp_exit(); +fail_crypto_ccmp: + ieee80211_crypto_tkip_exit(); +fail_crypto_tkip: + ieee80211_crypto_deinit(); +fail_crypto: +#ifdef CONFIG_IEEE80211_DEBUG + ieee80211_debug_exit(); +#endif + return ret; } -- cgit v1.2.3 From 41a38d9e632f7c9ec5ad8fc627567d97f4302c4a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 25 May 2010 04:25:57 +0100 Subject: Staging: rtl8192su: Fix procfs code for interfaces not named wlan0 The current code creates directories in procfs named after interfaces, but doesn't handle renaming. This can result in name collisions and consequent WARNINGs. It also means that the interface name cannot reliably be used to remove the directory - in fact the current code doesn't even try, and always uses "wlan0"! Since the name of a proc_dir_entry is embedded in it, use that when removing it. Add a netdev notifier to catch interface renaming, and remove and re-add the directory at this point. Signed-off-by: Ben Hutchings --- drivers/staging/rtl8192su/r8192U_core.c | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 1b4ff90f43ac..a076f56df7c4 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -27,6 +27,7 @@ #include #include #include +#include #undef LOOP_TEST #undef DUMP_RX @@ -161,6 +162,8 @@ MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); static int __devinit rtl8192_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf); +static const struct net_device_ops rtl8192_netdev_ops; +static struct notifier_block proc_netdev_notifier; static struct usb_driver rtl8192_usb_driver = { .name = RTL819xU_MODULE_NAME, /* Driver name */ @@ -992,14 +995,22 @@ static int proc_get_stats_rx(char *page, char **start, int rtl8192_proc_module_init(void) { + int ret; + RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net); - return rtl8192_proc ? 0 : -ENOMEM; + if (!rtl8192_proc) + return -ENOMEM; + ret = register_netdevice_notifier(&proc_netdev_notifier); + if (ret) + remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); + return ret; } void rtl8192_proc_module_remove(void) { + unregister_netdevice_notifier(&proc_netdev_notifier); remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net); } @@ -1027,8 +1038,7 @@ void rtl8192_proc_remove_one(struct net_device *dev) remove_proc_entry("registers-e", priv->dir_dev); // remove_proc_entry("cck-registers",priv->dir_dev); // remove_proc_entry("ofdm-registers",priv->dir_dev); - //remove_proc_entry(dev->name, rtl8192_proc); - remove_proc_entry("wlan0", rtl8192_proc); + remove_proc_entry(priv->dir_dev->name, rtl8192_proc); priv->dir_dev = NULL; } } @@ -1145,6 +1155,25 @@ void rtl8192_proc_init_one(struct net_device *dev) dev->name); } } + +static int proc_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *net_dev = ptr; + + if (net_dev->netdev_ops == &rtl8192_netdev_ops && + event == NETDEV_CHANGENAME) { + rtl8192_proc_remove_one(net_dev); + rtl8192_proc_init_one(net_dev); + } + + return NOTIFY_DONE; +} + +static struct notifier_block proc_netdev_notifier = { + .notifier_call = proc_netdev_event, +}; + /**************************************************************************** -----------------------------MISC STUFF------------------------- *****************************************************************************/ -- cgit v1.2.3 From 5749df14aef6d3fd7146f17e4f0c61526a53766e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 26 May 2010 13:39:04 +0200 Subject: Staging: cxt1e1: remove all code dependent on LINUX_VERSION_CODE Remove all code which is dead for in-kernel driver due to being ifdefed by LINUX_VERSION_CODE. While at it, also remove surrounding code which is commented out, or '#if 1' nops. Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/functions.c | 12 -- drivers/staging/cxt1e1/hwprobe.c | 6 - drivers/staging/cxt1e1/linux.c | 123 ---------------- drivers/staging/cxt1e1/musycc.c | 204 --------------------------- drivers/staging/cxt1e1/pmc93x6_eeprom.c | 4 - drivers/staging/cxt1e1/pmcc4.h | 6 - drivers/staging/cxt1e1/pmcc4_drv.c | 158 --------------------- drivers/staging/cxt1e1/sbecom_inline_linux.h | 11 -- 8 files changed, 524 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/functions.c b/drivers/staging/cxt1e1/functions.c index 86b498090265..23ea101d7a89 100644 --- a/drivers/staging/cxt1e1/functions.c +++ b/drivers/staging/cxt1e1/functions.c @@ -122,19 +122,7 @@ watchdog_func (unsigned long arg) pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state); return; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - /* Initialize the tq entry only the first time */ - if (wd->init_tq) - { - wd->init_tq = 0; - wd->tq.routine = wd->func; - wd->tq.sync = 0; - wd->tq.data = wd->softc; - } - schedule_task (&wd->tq); -#else schedule_work (&wd->work); -#endif mod_timer (&wd->h, jiffies + wd->ticks); } diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c index 4c8610293fcc..89200e7af26c 100644 --- a/drivers/staging/cxt1e1/hwprobe.c +++ b/drivers/staging/cxt1e1/hwprobe.c @@ -305,15 +305,9 @@ c4hw_attach_all (void) error_flag = 0; prep_hdw_info (); /*** scan PCI bus for all possible boards */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT, - PCI_DEVICE_ID_CN8474, - pdev))) -#else - while ((pdev = pci_find_device (PCI_VENDOR_ID_CONEXANT, PCI_DEVICE_ID_CN8474, pdev))) -#endif { if (c4_hdw_init (pdev, found)) found++; diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c index 134e7568024b..4088347a80e6 100644 --- a/drivers/staging/cxt1e1/linux.c +++ b/drivers/staging/cxt1e1/linux.c @@ -142,10 +142,6 @@ getuserbychan (int channum) } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#define DEV_TO_PRIV(dev) ( * (struct c4_priv **) ((hdlc_device*)(dev)+1)) -#else - char * get_hdlc_name (hdlc_device * hdlc) { @@ -154,7 +150,6 @@ get_hdlc_name (hdlc_device * hdlc) return dev->name; } -#endif static status_t @@ -167,7 +162,6 @@ mkret (int bsd) } /***************************************************************************/ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) #include /*** @@ -259,7 +253,6 @@ c4_wq_port_cleanup (mpi_t * pi) pi->wq_port = 0; } } -#endif /***************************************************************************/ @@ -291,48 +284,6 @@ void_open (struct net_device * ndev) } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) - -/** Linux 2.4.18-19 **/ -STATIC int -chan_open (hdlc_device * hdlc) -{ - status_t ret; - - if ((ret = c4_chan_up (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum))) - return -ret; - MOD_INC_USE_COUNT; - netif_start_queue (hdlc_to_dev (hdlc)); - return 0; /* no error = success */ -} - -#else - -/** Linux 2.4.20 and higher **/ -STATIC int -chan_open (struct net_device * ndev) -{ - hdlc_device *hdlc = dev_to_hdlc (ndev); - status_t ret; - - hdlc->proto = IF_PROTO_HDLC; - if ((ret = hdlc_open (hdlc))) - { - pr_info("hdlc_open failure, err %d.\n", ret); - return ret; - } - if ((ret = c4_chan_up (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum))) - return -ret; - MOD_INC_USE_COUNT; - netif_start_queue (hdlc_to_dev (hdlc)); - return 0; /* no error = success */ -} -#endif - -#else - -/** Linux 2.6 **/ STATIC int chan_open (struct net_device * ndev) { @@ -351,39 +302,8 @@ chan_open (struct net_device * ndev) netif_start_queue (ndev); return 0; /* no error = success */ } -#endif - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) - -/** Linux 2.4.18-19 **/ -STATIC void -chan_close (hdlc_device * hdlc) -{ - netif_stop_queue (hdlc_to_dev (hdlc)); - musycc_chan_down ((ci_t *) 0, DEV_TO_PRIV (hdlc)->channum); - MOD_DEC_USE_COUNT; -} -#else -/** Linux 2.4.20 and higher **/ -STATIC int -chan_close (struct net_device * ndev) -{ - hdlc_device *hdlc = dev_to_hdlc (ndev); - netif_stop_queue (hdlc_to_dev (hdlc)); - musycc_chan_down ((ci_t *) 0, DEV_TO_PRIV (hdlc)->channum); - hdlc_close (hdlc); - MOD_DEC_USE_COUNT; - return 0; -} -#endif - -#else - -/** Linux 2.6 **/ STATIC int chan_close (struct net_device * ndev) { @@ -396,7 +316,6 @@ chan_close (struct net_device * ndev) module_put (THIS_MODULE); return 0; } -#endif #if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) @@ -435,11 +354,7 @@ chan_dev_ioctl (struct net_device * dev, struct ifreq * ifr, int cmd) STATIC int -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -chan_attach_noop (hdlc_device * hdlc, unsigned short foo_1, unsigned short foo_2) -#else chan_attach_noop (struct net_device * ndev, unsigned short foo_1, unsigned short foo_2) -#endif { return 0; /* our driver has nothing to do here, show's * over, go home */ @@ -455,16 +370,12 @@ chan_get_stats (struct net_device * ndev) struct sbecom_chan_stats *stats; int channum; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - channum = DEV_TO_PRIV (ndev)->channum; -#else { struct c4_priv *priv; priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv; channum = priv->channum; } -#endif ch = c4_find_chan (channum); if (ch == NULL) @@ -527,13 +438,9 @@ c4_linux_xmit (struct sk_buff * skb, struct net_device * ndev) const struct c4_priv *priv; int rval; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - priv = DEV_TO_PRIV (ndev); -#else hdlc_device *hdlc = dev_to_hdlc (ndev); priv = hdlc->priv; -#endif rval = musycc_start_xmit (priv->ci, priv->channum, skb); return -rval; @@ -823,18 +730,10 @@ do_create_chan (struct net_device * ndev, void *data) ret = mkret (c4_new_chan (ci, cp.port, cp.channum, dev)); if (ret) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - rtnl_unlock (); /* needed due to Ioctl calling sequence */ - V7 (unregister_hdlc_device) (dev_to_hdlc (dev)); - rtnl_lock (); /* needed due to Ioctl calling sequence */ - OS_kfree (DEV_TO_PRIV (dev)); - OS_kfree (dev); -#else rtnl_unlock (); /* needed due to Ioctl calling sequence */ unregister_hdlc_device (dev); rtnl_lock (); /* needed due to Ioctl calling sequence */ free_netdev (dev); -#endif } return ret; } @@ -883,11 +782,7 @@ do_deluser (struct net_device * ndev, int lockit) const struct c4_priv *priv; int channum; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - priv = DEV_TO_PRIV (ndev); -#else priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv; -#endif ci = priv->ci; channum = priv->channum; @@ -897,22 +792,12 @@ do_deluser (struct net_device * ndev, int lockit) ch->user = 0; /* will be freed, below */ } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if (lockit) - rtnl_unlock (); /* needed if Ioctl calling sequence */ - V7 (unregister_hdlc_device) (dev_to_hdlc (ndev)); - if (lockit) - rtnl_lock (); /* needed if Ioctl calling sequence */ - OS_kfree (DEV_TO_PRIV (ndev)); - OS_kfree (ndev); -#else if (lockit) rtnl_unlock (); /* needed if Ioctl calling sequence */ unregister_hdlc_device (ndev); if (lockit) rtnl_lock (); /* needed if Ioctl calling sequence */ free_netdev (ndev); -#endif return 0; } @@ -1339,14 +1224,6 @@ c4_mod_remove (void) module_init (c4_mod_init); module_exit (c4_mod_remove); -#ifndef SBE_INCLUDE_SYMBOLS -#ifndef CONFIG_SBE_WANC24_NCOMM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -EXPORT_NO_SYMBOLS; -#endif -#endif -#endif - MODULE_AUTHOR ("SBE Technical Services "); MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module"); #ifdef MODULE_LICENSE diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c index d3f5a5b52dc3..12c76a553e0f 100644 --- a/drivers/staging/cxt1e1/musycc.c +++ b/drivers/staging/cxt1e1/musycc.c @@ -405,7 +405,6 @@ musycc_update_tx_thp (mch_t * ch) } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) /* * This is the workq task executed by the OS when our queue_work() is * scheduled and run. It can fire off either RX or TX ACTIVATION depending @@ -515,7 +514,6 @@ musycc_wq_chan_restart (void *arg) /* channel private structure */ #endif } } -#endif /* @@ -531,7 +529,6 @@ musycc_chan_restart (mch_t * ch) ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) /* 2.6 - find next unprocessed message, then set TX thp to it */ #ifdef RLD_RESTART_DEBUG pr_info(">> musycc_chan_restart: scheduling Chan %x workQ @ %p\n", ch->channum, &ch->ch_work); @@ -539,51 +536,9 @@ musycc_chan_restart (mch_t * ch) c4_wk_chan_restart (ch); /* work queue mechanism fires off: Ref: * musycc_wq_chan_restart () */ -#else - - - /* 2.4 - find next unprocessed message, then set TX thp to it */ -#ifdef RLD_RESTART_DEBUG - pr_info(">> musycc_chan_restart: scheduling Chan %x start_tx %x\n", ch->channum, ch->ch_start_tx); -#endif - /* restart transmission from background loop */ - ch->up->up->wd_notify = WD_NOTIFY_1TX; -#endif } -#if 0 -void -musycc_cleanup (ci_t * ci) -{ - mpi_t *pi; - int i, j; - - /* free up driver resources */ - ci->state = C_INIT; /* mark as hardware not available */ - - for (i = 0; i < ci->max_ports; i++) - { - pi = &ci->port[i]; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) - c4_wq_port_cleanup (pi); -#endif - for (j = 0; j < MUSYCC_NCHANS; j++) - { - if (pi->chan[j]) - OS_kfree (pi->chan[j]); /* free mch_t struct */ - } - OS_kfree (pi->regram_saved); - } -#if 0 - /* obsolete - watchdog is now static w/in ci_t */ - OS_free_watchdog (ci->wd); -#endif - OS_kfree (ci->iqd_p_saved); - OS_kfree (ci); -} -#endif - void rld_put_led (mpi_t * pi, u_int32_t ledval) { @@ -2008,37 +1963,13 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token) atomic_add (len, &ci->tx_pending); ch->s.tx_packets++; ch->s.tx_bytes += len; -#if 0 - spin_unlock_irqrestore (&ch->ch_txlock, flags); /* allow pending - * interrupt to sneak - * thru */ -#endif - /* * If an ONR was seen, then channel requires poking to restart * transmission. */ if (ch->ch_start_tx) { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,41) - SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_"); /* only 1 thru here, per - * board */ - if ((ch->ch_start_tx == CH_START_TX_ONR) && (ch->p.chan_mode == CFG_CH_PROTO_TRANS)) - { - /* ONR restart transmission from background loop */ - ci->wd_notify = WD_NOTIFY_ONR; /* enabled global watchdog - * scan-thru */ - } else - { - /* start first transmission from background loop */ - ci->wd_notify = WD_NOTIFY_1TX; /* enabled global watchdog - * scan-thru */ - } musycc_chan_restart (ch); - SD_SEM_GIVE (&ci->sem_wdbusy); -#else - musycc_chan_restart (ch); -#endif } #ifdef SBE_WAN256T3_ENABLE wan256t3_led (ci, LED_TX, LEDV_G); @@ -2047,139 +1978,4 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token) } -#if 0 -int -musycc_set_chan (ci_t * ci, int channum, struct sbecom_chan_param * p) -{ - mch_t *ch; - int rok = 0; - int n = 0; - - if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS)) /* sanity chk param */ - return ECHRNG; - if (!(ch = sd_find_chan (ci, channum))) - return ENOENT; - if (ch->channum != p->channum) - return EINVAL; - if (sd_line_is_ok (ch->user)) - { - rok = 1; - sd_line_is_down (ch->user); - } - if (ch->state == UP && /* bring down in current configuration */ - (ch->p.status != p->status || - ch->p.chan_mode != p->chan_mode || - ch->p.intr_mask != p->intr_mask || - ch->txd_free < ch->txd_num)) - { - if ((n = musycc_chan_down (ci, channum))) - return n; - if (ch->p.mode_56k != p->mode_56k) - { - ch->p = *p; /* copy in new parameters */ - musycc_update_timeslots (&ci->port[ch->channum / MUSYCC_NCHANS]); - } else - ch->p = *p; /* copy in new parameters */ - if ((n = musycc_chan_up (ci, channum))) - return n; - sd_enable_xmit (ch->user); /* re-enable to catch flow controlled - * channel */ - } else - { - if (ch->p.mode_56k != p->mode_56k) - { - ch->p = *p; /* copy in new parameters */ - musycc_update_timeslots (&ci->port[ch->channum / MUSYCC_NCHANS]); - } else - ch->p = *p; /* copy in new parameters */ - } - - if (rok) - sd_line_is_up (ch->user); - return 0; -} -#endif - - -int -musycc_get_chan (ci_t * ci, int channum, struct sbecom_chan_param * p) -{ - mch_t *ch; - -#if 0 - if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS)) /* sanity chk param */ - return ECHRNG; -#endif - if (!(ch = sd_find_chan (ci, channum))) - return ENOENT; - *p = ch->p; - return 0; -} - - -int -musycc_get_chan_stats (ci_t * ci, int channum, struct sbecom_chan_stats * p) -{ - mch_t *ch; - - if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS)) /* sanity chk param */ - return ECHRNG; - if (!(ch = sd_find_chan (ci, channum))) - return ENOENT; - *p = ch->s; - p->tx_pending = atomic_read (&ch->tx_pending); - return 0; -} - - - -#ifdef SBE_WAN256T3_ENABLE -int -musycc_chan_down (ci_t * ci, int channum) -{ - mch_t *ch; - mpi_t *pi; - int i, gchan; - - if (!(ch = sd_find_chan (ci, channum))) - return EINVAL; - pi = ch->up; - gchan = ch->gchan; - - /* Deactivate the channel */ - musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan); - ch->ch_start_rx = 0; - musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan); - ch->ch_start_tx = 0; - - if (ch->state == DOWN) - return 0; - ch->state = DOWN; - - pi->regram->thp[gchan] = 0; - pi->regram->tmp[gchan] = 0; - pi->regram->rhp[gchan] = 0; - pi->regram->rmp[gchan] = 0; - FLUSH_MEM_WRITE (); - for (i = 0; i < ch->txd_num; i++) - { - if (ch->mdt[i].mem_token != 0) - OS_mem_token_free (ch->mdt[i].mem_token); - } - - for (i = 0; i < ch->rxd_num; i++) - { - if (ch->mdr[i].mem_token != 0) - OS_mem_token_free (ch->mdr[i].mem_token); - } - - OS_kfree (ch->mdt); - ch->mdt = 0; - OS_kfree (ch->mdr); - ch->mdr = 0; - - return 0; -} -#endif - /*** End-of-File ***/ diff --git a/drivers/staging/cxt1e1/pmc93x6_eeprom.c b/drivers/staging/cxt1e1/pmc93x6_eeprom.c index 1c8dfb80e7d7..62b12fb45fcc 100644 --- a/drivers/staging/cxt1e1/pmc93x6_eeprom.c +++ b/drivers/staging/cxt1e1/pmc93x6_eeprom.c @@ -500,11 +500,7 @@ pmc_init_seeprom (u_int32_t addr, u_int32_t serialNum) time_t createTime; int i; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - createTime = CURRENT_TIME; -#else createTime = get_seconds (); -#endif /* use template data */ for (i = 0; i < sizeof (FLD_TYPE2); ++i) diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h index 26c1f0ea72e9..e288a0a91882 100644 --- a/drivers/staging/cxt1e1/pmcc4.h +++ b/drivers/staging/cxt1e1/pmcc4.h @@ -117,12 +117,6 @@ extern "C" #include "pmcc4_private.h" -#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -char *get_hdlc_name (hdlc_device *); - -#endif - - /* * external interface */ diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c index 333cf2687dd1..9f730e68526c 100644 --- a/drivers/staging/cxt1e1/pmcc4_drv.c +++ b/drivers/staging/cxt1e1/pmcc4_drv.c @@ -119,12 +119,10 @@ char OSSIid_pmcc4_drvc[] = #define KERN_WARN KERN_WARNING /* forward references */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) status_t c4_wk_chan_init (mpi_t *, mch_t *); void c4_wq_port_cleanup (mpi_t *); status_t c4_wq_port_init (mpi_t *); -#endif int c4_loop_port (ci_t *, int, u_int8_t); status_t c4_set_port (ci_t *, int); status_t musycc_chan_down (ci_t *, int); @@ -533,145 +531,15 @@ checkPorts (ci_t * ci) STATIC void c4_watchdog (ci_t * ci) { -#if 0 - //unsigned long flags; -#endif - if (drvr_state != SBE_DRVR_AVAILABLE) { if (log_level >= LOG_MONITOR) pr_info("drvr not available (%x)\n", drvr_state); return; } -#if 0 - SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_"); /* only 1 thru here, per - * board */ -#endif - ci->wdcount++; checkPorts (ci); -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,41) - if (ci->wd_notify) - { /* is there a state change to search for */ - int port, gchan; - - ci->wd_notify = 0; /* reset notification */ - for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++) - { - for (port = 0; port < ci->max_port; port++) - { - mch_t *ch = ci->port[port].chan[gchan]; - - if (!ch || ci->state != C_RUNNING) /* state changed while - * acquiring semaphore */ - break; - if (ch->state == UP)/* channel must be set up */ - { -#if 0 -#ifdef RLD_TRANS_DEBUG - if (1 || log_level >= LOG_MONITOR) -#else - if (log_level >= LOG_MONITOR) -#endif - pr_info("%s: watchdog reviving Port %d Channel %d [%d] sts %x/%x, start_TX %x free %x start_RX %x\n", - ci->devname, ch->channum, port, gchan, ch->channum, - ch->p.status, ch->status, - ch->ch_start_tx, ch->txd_free, ch->ch_start_rx); -#endif - - /**********************************/ - /** check for RX restart request **/ - /**********************************/ - - if (ch->ch_start_rx && - (ch->status & RX_ENABLED)) /* requires start on - * enabled RX */ - { - ch->ch_start_rx = 0; /* we are restarting RX... */ -#ifdef RLD_TRANS_DEBUG - pr_info("++ c4_watchdog() CHAN RX ACTIVATE: chan %d\n", - ch->channum); -#endif -#ifdef RLD_RXACT_DEBUG - { - struct mdesc *md; - static int hereb4 = 7; - - if (hereb4) - { - hereb4--; - md = &ch->mdr[ch->rxix_irq_srv]; - pr_info("++ c4_watchdog[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n", - ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status), ch->s.rx_packets); - musycc_dump_rxbuffer_ring (ch, 1); /* RLD DEBUG */ - } - } -#endif - musycc_serv_req (ch->up, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan); - } - /**********************************/ - /** check for TX restart request **/ - /**********************************/ - - if (ch->ch_start_tx && - (ch->status & TX_ENABLED)) /* requires start on - * enabled TX */ - { - struct mdesc *md; - - /* - * find next unprocessed message, then set TX thp to - * it - */ - musycc_update_tx_thp (ch); - -#if 0 - spin_lock_irqsave (&ch->ch_txlock, flags); -#endif - md = ch->txd_irq_srv; - if (!md) - { - pr_info("-- c4_watchdog[%d]: WARNING, starting NULL md\n", - ch->channum); - pr_info("-- chan %d txd_irq_srv %p sts %x usr_add %p sts %x, txpkt %lu\n", - ch->channum, ch->txd_irq_srv, le32_to_cpu ((struct mdesc *) (ch->txd_irq_srv)->status), - ch->txd_usr_add, le32_to_cpu ((struct mdesc *) (ch->txd_usr_add)->status), - ch->s.tx_packets); -#if 0 - spin_unlock_irqrestore (&ch->ch_txlock, flags); -#endif - } else if (md->data && ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED)) - { -#ifdef RLD_TRANS_DEBUG - pr_info("++ c4_watchdog[%d] CHAN TX ACTIVATE: start_tx %x\n", - ch->channum, ch->ch_start_tx); -#endif - ch->ch_start_tx = 0; /* we are restarting - * TX... */ -#if 0 - spin_unlock_irqrestore (&ch->ch_txlock, flags); /* allow interrupts for - * service request */ -#endif - musycc_serv_req (ch->up, SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION | gchan); -#ifdef RLD_TRANS_DEBUG - if (1 || log_level >= LOG_MONITOR) -#else - if (log_level >= LOG_MONITOR) -#endif - pr_info("++ SACK[P%d/C%d] ack'd, continuing...\n", - ch->up->portnum, ch->channum); - } - } - } - } - } - } -#else ci->wd_notify = 0; -#endif -#if 0 - SD_SEM_GIVE (&ci->sem_wdbusy);/* release per-board hold */ -#endif } @@ -690,9 +558,7 @@ c4_cleanup (void) for (portnum = 0; portnum < ci->max_port; portnum++) { pi = &ci->port[portnum]; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) c4_wq_port_cleanup (pi); -#endif for (j = 0; j < MUSYCC_NCHANS; j++) { if (pi->chan[j]) @@ -700,10 +566,6 @@ c4_cleanup (void) } OS_kfree (pi->regram_saved); } -#if 0 - /* obsolete - watchdog is now static w/in ci_t */ - OS_free_watchdog (ci->wd); -#endif OS_kfree (ci->iqd_p_saved); OS_kfree (ci); ci = next; /* cleanup next board, if any */ @@ -1145,7 +1007,6 @@ c4_set_port (ci_t * ci, int portnum) return EBUSY; /* group needs initialization only for * first channel of a group */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) { status_t ret; @@ -1153,7 +1014,6 @@ c4_set_port (ci_t * ci, int portnum) * workqueue_struct */ return (ret); } -#endif init_comet (ci, pi->cometbase, pp->port_mode, 1 /* clockmaster == true */ , pp->portP); clck = pci_read_32 ((u_int32_t *) &ci->cpldbase->mclk) & PMCC4_CPLD_MCLK_MASK; @@ -1269,14 +1129,12 @@ c4_new_chan (ci_t * ci, int portnum, int channum, void *user) spin_lock_init (&ch->ch_rxlock); spin_lock_init (&ch->ch_txlock); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) { status_t ret; if ((ret = c4_wk_chan_init (pi, ch))) return ret; } -#endif /* save off interface assignments which bound a board */ if (ci->first_if == 0) /* first channel registered is assumed to @@ -1705,31 +1563,23 @@ sbecom_get_brdinfo (ci_t * ci, struct sbe_brd_info * bip, u_int8_t *bsn) if (ci->first_if) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - np = (char *) hdlc_to_name (ci->first_if); -#else { struct net_device *dev; dev = (struct net_device *) ci->first_if; np = (char *) dev->name; } -#endif strncpy (bip->first_iname, np, CHNM_STRLEN - 1); } else strcpy (bip->first_iname, ""); if (ci->last_if) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - np = (char *) hdlc_to_name (ci->last_if); -#else { struct net_device *dev; dev = (struct net_device *) ci->last_if; np = (char *) dev->name; } -#endif strncpy (bip->last_iname, np, CHNM_STRLEN - 1); } else strcpy (bip->last_iname, ""); @@ -1763,11 +1613,7 @@ c4_get_iidinfo (ci_t * ci, struct sbe_iid_info * iip) if (!(dev = getuserbychan (iip->channum))) return ENOENT; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - np = (char *) hdlc_to_name (dev_to_hdlc (dev)); -#else np = dev->name; -#endif strncpy (iip->iname, np, CHNM_STRLEN - 1); return 0; } @@ -1826,11 +1672,7 @@ c4_ebus_intr_th_handler (void *devp) pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE); #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,20) - return; -#else return IRQ_RETVAL (handled); -#endif } diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h index c65172db2ad8..5a72cb5cff42 100644 --- a/drivers/staging/cxt1e1/sbecom_inline_linux.h +++ b/drivers/staging/cxt1e1/sbecom_inline_linux.h @@ -48,9 +48,6 @@ #else #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#include -#endif #if defined(CONFIG_SMP) && ! defined(__SMP__) #define __SMP__ #endif @@ -60,12 +57,8 @@ #ifdef MODULE #ifdef MODVERSIONS -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include -#else #include #endif -#endif #include #endif #endif @@ -260,11 +253,7 @@ OS_sem_free (void *sem) struct watchdog { struct timer_list h; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - struct tq_struct tq; -#else struct work_struct work; -#endif void *softc; void (*func) (void *softc); int ticks; -- cgit v1.2.3 From bb71770cdb19f2cabb77afb329025ba460d05ebc Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 26 May 2010 13:33:55 +0200 Subject: Staging: rtl8192su: remove all code dependent on LINUX_VERSION_CODE Remove all code which is dead for in-kernel driver due to being ifdefed by LINUX_VERSION_CODE. While at it, also remove surrounding code which is commented out, or '#if 1' nops. Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192su/r8192SU_led.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/r8192SU_led.c b/drivers/staging/rtl8192su/r8192SU_led.c index 609dba67eb4e..5d96b356bf12 100644 --- a/drivers/staging/rtl8192su/r8192SU_led.c +++ b/drivers/staging/rtl8192su/r8192SU_led.c @@ -1087,22 +1087,13 @@ BlinkTimerCallback( struct net_device *dev = (struct net_device *)data; struct r8192_priv *priv = ieee80211_priv(dev); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) schedule_work(&(priv->BlinkWorkItem)); -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) void BlinkWorkItemCallback(struct work_struct *work) { struct r8192_priv *priv = container_of(work, struct r8192_priv, BlinkWorkItem); -#else -void BlinkWorkItemCallback(void * Context) -{ - struct net_device *dev = (struct net_device *)Context; - struct r8192_priv *priv = ieee80211_priv(dev); -#endif PLED_819xUsb pLed = priv->pLed; -- cgit v1.2.3 From 9c770f3b881c5066ff014968473ffbbafee82247 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 26 May 2010 16:20:41 +0200 Subject: Staging: cxt1e1: remove code guarded by GENERIC_HDLC_VERSION Current linux kernel has GENERIC_HDLC_VERSION equal to 4, no need to have dead code in-kernel which was there for ancient kernel versions. Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/linux.c | 40 ---------------------------------------- drivers/staging/cxt1e1/pmcc4.h | 2 ++ 2 files changed, 2 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c index 4088347a80e6..eb0f4bdf6273 100644 --- a/drivers/staging/cxt1e1/linux.c +++ b/drivers/staging/cxt1e1/linux.c @@ -318,34 +318,6 @@ chan_close (struct net_device * ndev) } -#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) - -/** Linux 2.4.18-19 **/ -STATIC int -chan_ioctl (hdlc_device * hdlc, struct ifreq * ifr, int cmd) -{ - if (cmd == HDLCSCLOCK) - { - ifr->ifr_ifru.ifru_ivalue = LINE_DEFAULT; - return 0; - } - return -EINVAL; -} -#endif - - -#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) -STATIC int -chan_dev_ioctl (struct net_device * hdlc, struct ifreq * ifr, int cmd) -{ - if (cmd == HDLCSCLOCK) - { - ifr->ifr_ifru.ifru_ivalue = LINE_DEFAULT; - return 0; - } - return -EINVAL; -} -#else STATIC int chan_dev_ioctl (struct net_device * dev, struct ifreq * ifr, int cmd) { @@ -359,7 +331,6 @@ chan_attach_noop (struct net_device * ndev, unsigned short foo_1, unsigned short return 0; /* our driver has nothing to do here, show's * over, go home */ } -#endif STATIC struct net_device_stats * @@ -422,16 +393,6 @@ get_ci_by_dev (struct net_device * ndev) } -#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4) -STATIC int -c4_linux_xmit (hdlc_device * hdlc, struct sk_buff * skb) -{ - int rval; - - rval = musycc_start_xmit (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum, skb); - return -rval; -} -#else /* new */ STATIC int c4_linux_xmit (struct sk_buff * skb, struct net_device * ndev) { @@ -445,7 +406,6 @@ c4_linux_xmit (struct sk_buff * skb, struct net_device * ndev) rval = musycc_start_xmit (priv->ci, priv->channum, skb); return -rval; } -#endif /* GENERIC_HDLC_VERSION */ static const struct net_device_ops chan_ops = { .ndo_open = chan_open, diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h index e288a0a91882..ef6ac7fe7ddd 100644 --- a/drivers/staging/cxt1e1/pmcc4.h +++ b/drivers/staging/cxt1e1/pmcc4.h @@ -117,6 +117,8 @@ extern "C" #include "pmcc4_private.h" +char *get_hdlc_name (hdlc_device *); + /* * external interface */ -- cgit v1.2.3 From cb3126e60ffc1b7658a6ff4f6874585098bf9887 Mon Sep 17 00:00:00 2001 From: Karl Relton Date: Thu, 3 Jun 2010 23:04:06 +0100 Subject: Staging: wlan-ng: Switch from wext to cfg80211 Switch driver over from wext to cfg80211 interface. Some Notes: - This patch moves the driver wholesale from wext to cfg80211. Wext support is still provided through the cfg80211 provided wext compatability layer. - Currently only infrastructure mode is implemented. Ad hoc mode is not yet implemented, but can be added. - It does not support connecting to a specified bssid, instead roaming is handled by the card itself. This matches the behaviour of the existing driver. - It has been tested using NetworkManager (via wpa_supplicant) configured to use the wext compatability layer, and then again with the native nl80211 layer. Signed-off-by: Karl Relton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/Makefile | 1 - drivers/staging/wlan-ng/cfg80211.c | 735 ++++++++++++ drivers/staging/wlan-ng/hfa384x.h | 2 + drivers/staging/wlan-ng/p80211metastruct.h | 2 + drivers/staging/wlan-ng/p80211netdev.c | 49 +- drivers/staging/wlan-ng/p80211netdev.h | 3 +- drivers/staging/wlan-ng/p80211wext.c | 1690 ---------------------------- drivers/staging/wlan-ng/prism2mgmt.c | 2 + drivers/staging/wlan-ng/prism2sta.c | 64 +- drivers/staging/wlan-ng/prism2usb.c | 2 +- 10 files changed, 825 insertions(+), 1725 deletions(-) create mode 100644 drivers/staging/wlan-ng/cfg80211.c delete mode 100644 drivers/staging/wlan-ng/p80211wext.c (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/Makefile b/drivers/staging/wlan-ng/Makefile index 5edac5c8d4ee..db5d597563f8 100644 --- a/drivers/staging/wlan-ng/Makefile +++ b/drivers/staging/wlan-ng/Makefile @@ -4,5 +4,4 @@ prism2_usb-objs := prism2usb.o \ p80211conv.o \ p80211req.o \ p80211wep.o \ - p80211wext.o \ p80211netdev.o diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c new file mode 100644 index 000000000000..b0792f78ac96 --- /dev/null +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -0,0 +1,735 @@ +/* cfg80211 Interface for prism2_usb module */ + + +/* Prism2 channell/frequency/bitrate declarations */ +static const struct ieee80211_channel prism2_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +static const struct ieee80211_rate prism2_rates[] = { + { .bitrate = 10 }, + { .bitrate = 20 }, + { .bitrate = 55 }, + { .bitrate = 110 } +}; + +#define PRISM2_NUM_CIPHER_SUITES 2 +static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104 +}; + + +/* prism2 device private data */ +struct prism2_wiphy_private { + wlandevice_t *wlandev; + + struct ieee80211_supported_band band; + struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)]; + struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)]; + + struct cfg80211_scan_request *scan_request; +}; + +static const void * const prism2_wiphy_privid = &prism2_wiphy_privid; + + +/* Helper Functions */ +static int prism2_result2err(int prism2_result) +{ + int err = 0; + + switch (prism2_result) { + case P80211ENUM_resultcode_invalid_parameters: + err = -EINVAL; + break; + case P80211ENUM_resultcode_implementation_failure: + err = -EIO; + break; + case P80211ENUM_resultcode_not_supported: + err = -EOPNOTSUPP; + break; + default: + err = 0; + break; + } + + return err; +} + +static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem->did = did; + mibitem->data = data; + + return p80211req_dorequest(wlandev, (u8 *) & msg); +} + +static int prism2_domibset_pstr32(wlandevice_t *wlandev, + u32 did, u8 len, u8 *data) +{ + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data; + + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem->did = did; + mibitem->data.len = len; + memcpy(mibitem->data.data, data, len); + + return p80211req_dorequest(wlandev, (u8 *) & msg); +} + + +/* The interface functions, called by the cfg80211 layer */ +int prism2_change_virtual_intf(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + wlandevice_t *wlandev = dev->ml_priv; + u32 data; + int result; + int err = 0; + + switch (type) { + case NL80211_IFTYPE_ADHOC: + if (wlandev->macmode == WLAN_MACMODE_IBSS_STA) goto exit; + wlandev->macmode = WLAN_MACMODE_IBSS_STA; + data = 0; + break; + case NL80211_IFTYPE_STATION: + if (wlandev->macmode == WLAN_MACMODE_ESS_STA) goto exit; + wlandev->macmode = WLAN_MACMODE_ESS_STA; + data = 1; + break; + default: + printk(KERN_WARNING "Operation mode: %d not support\n", type); + return -EOPNOTSUPP; + } + + /* Set Operation mode to the PORT TYPE RID */ + result = prism2_domibset_uint32(wlandev, DIDmib_p2_p2Static_p2CnfPortType, data); + + if (result) + err = -EFAULT; + + dev->ieee80211_ptr->iftype = type; + +exit: + return err; +} + +int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr, + struct key_params *params) { + wlandevice_t *wlandev = dev->ml_priv; + u32 did; + + int err = 0; + int result = 0; + + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + key_index); + if (result) goto exit; + + /* send key to driver */ + switch (key_index) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key); + if (result) goto exit; + break; + + default: + pr_debug("Unsupported cipher suite\n"); + result = 1; + } + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*)) { + wlandevice_t *wlandev = dev->ml_priv; + struct key_params params; + int len; + + if(key_index >= NUM_WEPKEYS) return -EINVAL; + + len = wlandev->wep_keylens[key_index]; + memset(¶ms, 0, sizeof(params)); + + if (len == 13) { + params.cipher = WLAN_CIPHER_SUITE_WEP104; + } else if (len == 5) { + params.cipher = WLAN_CIPHER_SUITE_WEP104; + } else return -ENOENT; + params.key_len = len; + params.key = wlandev->wep_keys[key_index]; + + callback(cookie, ¶ms); + return 0; +} + +int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, const u8 *mac_addr) { + wlandevice_t *wlandev = dev->ml_priv; + u32 did; + int err = 0; + int result = 0; + + /* There is no direct way in the hardware (AFAIK) of removing + a key, so we will cheat by setting the key to a bogus value */ + /* send key to driver */ + switch (key_index) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index) { + wlandevice_t *wlandev = dev->ml_priv; + + int err = 0; + int result = 0; + + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + key_index); + + if (result) err = -EFAULT; + + return err; +} + + +int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) { + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_lnxreq_commsquality_t quality; + int result; + + memset(sinfo, 0, sizeof(*sinfo)); + + if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) + return -EOPNOTSUPP; + + /* build request message */ + quality.msgcode = DIDmsg_lnxreq_commsquality; + quality.dbm.data = P80211ENUM_truth_true; + quality.dbm.status = P80211ENUM_msgitem_status_data_ok; + + /* send message to nsd */ + if (wlandev->mlmerequest == NULL) + return -EOPNOTSUPP; + + result = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality); + + + if (result == 0) { + sinfo->txrate.legacy = quality.txrate.data; + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->signal = quality.level.data; + sinfo->filled |= STATION_INFO_SIGNAL; + } + + return result; +} + +int prism2_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_dot11req_scan_t msg1; + p80211msg_dot11req_scan_results_t msg2; + int result; + int err = 0; + int numbss = 0; + int i = 0; + u8 ie_buf[46]; + int ie_len; + + if (!request) + return -EINVAL; + + if (priv->scan_request && priv->scan_request != request) + return -EBUSY; + + if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { + printk(KERN_ERR "Can't scan in AP mode\n"); + return -EOPNOTSUPP; + } + + priv->scan_request = request; + + memset(&msg1, 0x00, sizeof(p80211msg_dot11req_scan_t)); + msg1.msgcode = DIDmsg_dot11req_scan; + msg1.bsstype.data = P80211ENUM_bsstype_any; + + memset(&(msg1.bssid.data), 0xFF, sizeof(p80211item_pstr6_t)); + msg1.bssid.data.len = 6; + + if (request->n_ssids > 0) { + msg1.scantype.data = P80211ENUM_scantype_active; + msg1.ssid.data.len = request->ssids->ssid_len; + memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len); + } else { + msg1.scantype.data = 0; + } + msg1.probedelay.data = 0; + + for (i = 0; + (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels); + i++) + msg1.channellist.data.data[i] = + ieee80211_frequency_to_channel(request->channels[i]->center_freq); + msg1.channellist.data.len = request->n_channels; + + msg1.maxchanneltime.data = 250; + msg1.minchanneltime.data = 200; + + result = p80211req_dorequest(wlandev, (u8 *) &msg1); + if (result) { + err = prism2_result2err(msg1.resultcode.data); + goto exit; + } + /* Now retrieve scan results */ + numbss = msg1.numbss.data; + + for (i = 0; i < numbss; i++) { + memset(&msg2, 0, sizeof(msg2)); + msg2.msgcode = DIDmsg_dot11req_scan_results; + msg2.bssindex.data = i; + + result = p80211req_dorequest(wlandev, (u8 *) &msg2); + if ((result != 0) || + (msg2.resultcode.data != P80211ENUM_resultcode_success)) { + break; + } + + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = msg2.ssid.data.len; + ie_len = ie_buf[1] + 2; + memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); + cfg80211_inform_bss(wiphy, + ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)), + (const u8 *) &(msg2.bssid.data.data), + msg2.timestamp.data, msg2.capinfo.data, + msg2.beaconperiod.data, + ie_buf, + ie_len, + (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ + GFP_KERNEL + ); + } + + if (result) { + err = prism2_result2err(msg2.resultcode.data); + } + +exit: + cfg80211_scan_done(request, err ? 1 : 0); + priv->scan_request = NULL; + return err; +} + +int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + u32 data; + int result; + int err = 0; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + if (wiphy->rts_threshold == -1) + data = 2347; + else + data = wiphy->rts_threshold; + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + data); + if (result) { + err = -EFAULT; + goto exit; + } + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + + if (wiphy->frag_threshold == -1) + data = 2346; + else + data = wiphy->frag_threshold; + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + data); + if (result) { + err = -EFAULT; + goto exit; + } + } + +exit: + return err; +} + +int prism2_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) { + wlandevice_t *wlandev = dev->ml_priv; + struct ieee80211_channel *channel = sme->channel; + p80211msg_lnxreq_autojoin_t msg_join; + u32 did; + int length = sme->ssid_len; + int chan = -1; + int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || + (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104); + int result; + int err = 0; + + /* Set the channel */ + if (channel) { + chan = ieee80211_frequency_to_channel(channel->center_freq); + + result = + prism2_domibset_uint32(wlandev, + DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + chan); + + if (result) goto exit; + } + + /* Set the authorisation */ + if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_opensystem; + else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) || + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_sharedkey; + else printk(KERN_WARNING "Unhandled authorisation type for connect (%d)\n", sme->auth_type); + + /* Set the encryption - we only support wep */ + if (is_wep) { + + if (sme->key) { + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + sme->key_idx); + if (result) goto exit; + + /* send key to driver */ + switch (sme->key_idx) { + case 0: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + + case 1: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + + case 2: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + + case 3: + did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + + default: + err = -EINVAL; + goto exit; + } + + result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *) sme->key); + if (result) goto exit; + + } + + /* Assume we should set privacy invoked and exclude unencrypted + We could possibly use sme->privacy here, but the assumption + seems reasonable anyway */ + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_true); + if (result) goto exit; + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_true); + if (result) goto exit; + + } else { + /* Assume we should unset privacy invoked and exclude unencrypted */ + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_false); + if (result) goto exit; + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_false); + if (result) goto exit; + + } + + /* Now do the actual join. Note there is no way that I can + see to request a specific bssid */ + msg_join.msgcode = DIDmsg_lnxreq_autojoin; + + memcpy(msg_join.ssid.data.data, sme->ssid, length); + msg_join.ssid.data.len = length; + + result = p80211req_dorequest(wlandev, (u8 *) & msg_join); + +exit: + if (result) err = -EFAULT; + + return err; +} + +int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) { + wlandevice_t *wlandev = dev->ml_priv; + p80211msg_lnxreq_autojoin_t msg_join; + int result; + int err = 0; + + + /* Do a join, with a bogus ssid. Thats the only way I can think of */ + msg_join.msgcode = DIDmsg_lnxreq_autojoin; + + memcpy(msg_join.ssid.data.data, "---", 3); + msg_join.ssid.data.len = 3; + + result = p80211req_dorequest(wlandev, (u8 *) & msg_join); + + if (result) err = -EFAULT; + + return err; +} + + +int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) { + return -EOPNOTSUPP; +} + +int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { + return -EOPNOTSUPP; +} + + +int prism2_set_tx_power(struct wiphy *wiphy, + enum tx_power_setting type, int dbm) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + u32 data; + int result; + int err = 0; + + if (type == TX_POWER_AUTOMATIC) + data = 30; + else + data = dbm; + + result = prism2_domibset_uint32(wlandev, + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, + data); + + if (result) { + err = -EFAULT; + goto exit; + } + +exit: + return err; +} + +int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) { + struct prism2_wiphy_private *priv = wiphy_priv(wiphy); + wlandevice_t *wlandev = priv->wlandev; + p80211msg_dot11req_mibget_t msg; + p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + int result; + int err = 0; + + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem->did = + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + + result = p80211req_dorequest(wlandev, (u8 *) & msg); + + if (result) { + err = -EFAULT; + goto exit; + } + + *dbm = mibitem->data; + +exit: + return err; +} + + + + +/* Interface callback functions, passing data back up to the cfg80211 layer */ +void prism2_connect_result(wlandevice_t *wlandev, u8 failed) { + + cfg80211_connect_result(wlandev->netdev, wlandev->bssid, + NULL, 0, NULL, 0, + failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS, GFP_KERNEL); +} + +void prism2_disconnected(wlandevice_t *wlandev) { + + cfg80211_disconnected(wlandev->netdev, 0, NULL, + 0, GFP_KERNEL); +} + +void prism2_roamed(wlandevice_t *wlandev) { + + cfg80211_roamed(wlandev->netdev, wlandev->bssid, + NULL, 0, NULL, 0, GFP_KERNEL); +} + + +/* Structures for declaring wiphy interface */ +static const struct cfg80211_ops prism2_usb_cfg_ops = { + .change_virtual_intf = prism2_change_virtual_intf, + .add_key = prism2_add_key, + .get_key = prism2_get_key, + .del_key = prism2_del_key, + .set_default_key = prism2_set_default_key, + .get_station = prism2_get_station, + .scan = prism2_scan, + .set_wiphy_params = prism2_set_wiphy_params, + .connect = prism2_connect, + .disconnect = prism2_disconnect, + .join_ibss = prism2_join_ibss, + .leave_ibss = prism2_leave_ibss, + .set_tx_power = prism2_set_tx_power, + .get_tx_power = prism2_get_tx_power, +}; + + +/* Functions to create/free wiphy interface */ +struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) +{ + struct wiphy *wiphy; + struct prism2_wiphy_private *priv; + wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(struct prism2_wiphy_private)); + if (!wiphy) + return NULL; + + priv = wiphy_priv(wiphy); + priv->wlandev = wlandev; + memcpy(priv->channels, prism2_channels, sizeof(prism2_channels)); + memcpy(priv->rates, prism2_rates, sizeof(prism2_rates)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(prism2_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); + wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + set_wiphy_dev(wiphy, dev); + wiphy->privid = prism2_wiphy_privid; + wiphy->max_scan_ssids = 1; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES; + wiphy->cipher_suites = prism2_cipher_suites; + + if (wiphy_register(wiphy) < 0) + return NULL; + + return wiphy; +} + + +void wlan_free_wiphy(struct wiphy *wiphy) +{ + wiphy_unregister(wiphy); + wiphy_free(wiphy); +} diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1fa42e01e8cb..ab9bfaab8b6b 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1284,6 +1284,8 @@ typedef struct hfa384x { u16 link_status_new; struct sk_buff_head authq; + u32 txrate; + /* And here we have stuff that used to be in priv */ /* State variables */ diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index db12713eeaa9..e2e344c4ed82 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -113,6 +113,7 @@ typedef struct p80211msg_dot11req_scan_results { p80211item_uint32_t cfpollable; p80211item_uint32_t cfpollreq; p80211item_uint32_t privacy; + p80211item_uint32_t capinfo; p80211item_uint32_t basicrate1; p80211item_uint32_t basicrate2; p80211item_uint32_t basicrate3; @@ -209,6 +210,7 @@ typedef struct p80211msg_lnxreq_commsquality { p80211item_uint32_t link; p80211item_uint32_t level; p80211item_uint32_t noise; + p80211item_uint32_t txrate; } __attribute__ ((packed)) p80211msg_lnxreq_commsquality_t; typedef struct p80211msg_lnxreq_autojoin { diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 763ab1187a1c..31308b434344 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -75,6 +75,7 @@ #include #include +#include #include "p80211types.h" #include "p80211hdr.h" @@ -87,6 +88,8 @@ #include "p80211metastruct.h" #include "p80211metadef.h" +#include "cfg80211.c" + /* Support functions */ static void p80211netdev_rx_bh(unsigned long arg); @@ -732,6 +735,7 @@ static const struct net_device_ops p80211_netdev_ops = { * Arguments: * wlandev ptr to the wlandev structure for the * interface. +* physdev ptr to usb device * Returns: * zero on success, non-zero otherwise. * Call Context: @@ -740,10 +744,12 @@ static const struct net_device_ops p80211_netdev_ops = { * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -int wlan_setup(wlandevice_t *wlandev) +int wlan_setup(wlandevice_t *wlandev, struct device *physdev) { int result = 0; - netdevice_t *dev; + netdevice_t *netdev; + struct wiphy *wiphy; + struct wireless_dev *wdev; /* Set up the wlandev */ wlandev->state = WLAN_DEVICE_CLOSED; @@ -755,20 +761,30 @@ int wlan_setup(wlandevice_t *wlandev) tasklet_init(&wlandev->rx_bh, p80211netdev_rx_bh, (unsigned long)wlandev); + /* Allocate and initialize the wiphy struct */ + wiphy = wlan_create_wiphy(physdev, wlandev); + if (wiphy == NULL) { + printk(KERN_ERR "Failed to alloc wiphy.\n"); + return 1; + } + /* Allocate and initialize the struct device */ - dev = alloc_netdev(0, "wlan%d", ether_setup); - if (dev == NULL) { + netdev = alloc_netdev(sizeof(struct wireless_dev), "wlan%d", ether_setup); + if (netdev == NULL) { printk(KERN_ERR "Failed to alloc netdev.\n"); + wlan_free_wiphy(wiphy); result = 1; } else { - wlandev->netdev = dev; - dev->ml_priv = wlandev; - dev->netdev_ops = &p80211_netdev_ops; - - dev->wireless_handlers = &p80211wext_handler_def; - - netif_stop_queue(dev); - netif_carrier_off(dev); + wlandev->netdev = netdev; + netdev->ml_priv = wlandev; + netdev->netdev_ops = &p80211_netdev_ops; + wdev = netdev_priv(netdev); + wdev->wiphy = wiphy; + wdev->iftype = NL80211_IFTYPE_STATION; + netdev->ieee80211_ptr = wdev; + + netif_stop_queue(netdev); + netif_carrier_off(netdev); } return result; @@ -797,14 +813,13 @@ int wlan_setup(wlandevice_t *wlandev) ----------------------------------------------------------------*/ int wlan_unsetup(wlandevice_t *wlandev) { - int result = 0; + struct wireless_dev *wdev; tasklet_kill(&wlandev->rx_bh); - if (wlandev->netdev == NULL) { - printk(KERN_ERR "called without wlandev->netdev set.\n"); - result = 1; - } else { + if (wlandev->netdev) { + wdev = netdev_priv(wlandev->netdev); + if(wdev->wiphy) wlan_free_wiphy(wdev->wiphy); free_netdev(wlandev->netdev); wlandev->netdev = NULL; } diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 3c8c64800567..098ccf71e035 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -148,6 +148,7 @@ int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); #define MAX_KEYLEN 32 #define HOSTWEP_DEFAULTKEY_MASK (BIT(1)|BIT(0)) +#define HOSTWEP_SHAREDKEY BIT(3) #define HOSTWEP_DECRYPT BIT(4) #define HOSTWEP_ENCRYPT BIT(5) #define HOSTWEP_PRIVACYINVOKED BIT(6) @@ -233,7 +234,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv); -int wlan_setup(wlandevice_t *wlandev); +int wlan_setup(wlandevice_t *wlandev, struct device *physdev); int wlan_unsetup(wlandevice_t *wlandev); int register_wlandev(wlandevice_t *wlandev); int unregister_wlandev(wlandevice_t *wlandev); diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c deleted file mode 100644 index 387194d4a6eb..000000000000 --- a/drivers/staging/wlan-ng/p80211wext.c +++ /dev/null @@ -1,1690 +0,0 @@ -/* src/p80211/p80211wext.c -* -* Glue code to make linux-wlan-ng a happy wireless extension camper. -* -* original author: Reyk Floeter -* Completely re-written by Solomon Peachy -* -* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -*/ - -/*================================================================*/ -/* System Includes */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "p80211types.h" -#include "p80211hdr.h" -#include "p80211conv.h" -#include "p80211mgmt.h" -#include "p80211msg.h" -#include "p80211metastruct.h" -#include "p80211metadef.h" -#include "p80211netdev.h" -#include "p80211ioctl.h" -#include "p80211req.h" - -static int p80211wext_giwrate(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra); -static int p80211wext_giwessid(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid); - -static u8 p80211_mhz_to_channel(u16 mhz) -{ - if (mhz >= 5000) - return (mhz - 5000) / 5; - - if (mhz == 2484) - return 14; - - if (mhz >= 2407) - return (mhz - 2407) / 5; - - return 0; -} - -static u16 p80211_channel_to_mhz(u8 ch, int dot11a) -{ - - if (ch == 0) - return 0; - if (ch > 200) - return 0; - - /* 5G */ - if (dot11a) - return 5000 + (5 * ch); - - /* 2.4G */ - if (ch == 14) - return 2484; - - if ((ch < 14) && (ch > 0)) - return 2407 + (5 * ch); - - return 0; -} - -/* taken from orinoco.c ;-) */ -static const long p80211wext_channel_freq[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -#define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq) - -/* steal a spare bit to store the shared/opensystems state. - should default to open if not set */ -#define HOSTWEP_SHAREDKEY BIT(3) - -static int qual_as_percent(int snr) -{ - if (snr <= 0) - return 0; - if (snr <= 40) - return snr * 5 / 2; - return 100; -} - -static int p80211wext_setmib(wlandevice_t *wlandev, u32 did, u32 data) -{ - p80211msg_dot11req_mibset_t msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; - int result; - - msg.msgcode = DIDmsg_dot11req_mibset; - memset(mibitem, 0, sizeof(*mibitem)); - mibitem->did = did; - mibitem->data = data; - result = p80211req_dorequest(wlandev, (u8 *) &msg); - - return result; -} - -/* - * get a 32 bit mib value - */ -static int p80211wext_getmib(wlandevice_t *wlandev, u32 did, u32 *data) -{ - p80211msg_dot11req_mibset_t msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; - int result; - - msg.msgcode = DIDmsg_dot11req_mibget; - memset(mibitem, 0, sizeof(*mibitem)); - mibitem->did = did; - result = p80211req_dorequest(wlandev, (u8 *) &msg); - if (!result) - *data = mibitem->data; - - return result; -} - -static int p80211wext_autojoin(wlandevice_t *wlandev) -{ - p80211msg_lnxreq_autojoin_t msg; - struct iw_point data; - char ssid[IW_ESSID_MAX_SIZE]; - - int result; - int err = 0; - - /* Get ESSID */ - result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid); - - if (result) { - err = -EFAULT; - goto exit; - } - - if (wlandev->hostwep & HOSTWEP_SHAREDKEY) - msg.authtype.data = P80211ENUM_authalg_sharedkey; - else - msg.authtype.data = P80211ENUM_authalg_opensystem; - - msg.msgcode = DIDmsg_lnxreq_autojoin; - - /* Trim the last '\0' to fit the SSID format */ - - if (data.length && ssid[data.length - 1] == '\0') - data.length = data.length - 1; - - memcpy(msg.ssid.data.data, ssid, data.length); - msg.ssid.data.len = data.length; - - result = p80211req_dorequest(wlandev, (u8 *) &msg); - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - - return err; - -} - -/* called by /proc/net/wireless */ -struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev) -{ - p80211msg_lnxreq_commsquality_t quality; - wlandevice_t *wlandev = dev->ml_priv; - struct iw_statistics *wstats = &wlandev->wstats; - int retval; - - /* Check */ - if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) - return NULL; - - /* XXX Only valid in station mode */ - wstats->status = 0; - - /* build request message */ - quality.msgcode = DIDmsg_lnxreq_commsquality; - quality.dbm.data = P80211ENUM_truth_true; - quality.dbm.status = P80211ENUM_msgitem_status_data_ok; - - /* send message to nsd */ - if (wlandev->mlmerequest == NULL) - return NULL; - - retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) &quality); - - wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */ - wstats->qual.level = quality.level.data; /* instant signal level */ - wstats->qual.noise = quality.noise.data; /* instant noise level */ - - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - wstats->discard.code = wlandev->rx.decrypt_err; - wstats->discard.nwid = 0; - wstats->discard.misc = 0; - - wstats->discard.fragment = 0; /* incomplete fragments */ - wstats->discard.retries = 0; /* tx retries. */ - wstats->miss.beacon = 0; - - return wstats; -} - -static int p80211wext_giwname(netdevice_t *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - struct iw_param rate; - int result; - int err = 0; - - result = p80211wext_giwrate(dev, NULL, &rate, NULL); - - if (result) { - err = -EFAULT; - goto exit; - } - - switch (rate.value) { - case 1000000: - case 2000000: - strcpy(name, "IEEE 802.11-DS"); - break; - case 5500000: - case 11000000: - strcpy(name, "IEEE 802.11-b"); - break; - } -exit: - return err; -} - -static int p80211wext_giwfreq(netdevice_t *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - if (value > NUM_CHANNELS) { - err = -EFAULT; - goto exit; - } - - /* convert into frequency instead of a channel */ - freq->e = 1; - freq->m = p80211_channel_to_mhz(value, 0) * 100000; - -exit: - return err; -} - -static int p80211wext_siwfreq(netdevice_t *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - if (!wlan_wext_write) { - err = -EOPNOTSUPP; - goto exit; - } - - if ((freq->e == 0) && (freq->m <= 1000)) - value = freq->m; - else - value = p80211_mhz_to_channel(freq->m); - - result = p80211wext_setmib(wlandev, - DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, - value); - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int p80211wext_giwmode(netdevice_t *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - - switch (wlandev->macmode) { - case WLAN_MACMODE_IBSS_STA: - *mode = IW_MODE_ADHOC; - break; - case WLAN_MACMODE_ESS_STA: - *mode = IW_MODE_INFRA; - break; - case WLAN_MACMODE_ESS_AP: - *mode = IW_MODE_MASTER; - break; - default: - /* Not set yet. */ - *mode = IW_MODE_AUTO; - } - - return 0; -} - -static int p80211wext_siwmode(netdevice_t *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - - if (!wlan_wext_write) { - err = -EOPNOTSUPP; - goto exit; - } - - if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && - *mode != IW_MODE_MASTER) { - err = (-EOPNOTSUPP); - goto exit; - } - - /* Operation mode is the same with current mode */ - if (*mode == wlandev->macmode) - goto exit; - - switch (*mode) { - case IW_MODE_ADHOC: - wlandev->macmode = WLAN_MACMODE_IBSS_STA; - break; - case IW_MODE_INFRA: - wlandev->macmode = WLAN_MACMODE_ESS_STA; - break; - case IW_MODE_MASTER: - wlandev->macmode = WLAN_MACMODE_ESS_AP; - break; - default: - /* Not set yet. */ - printk(KERN_INFO "Operation mode: %d not support\n", *mode); - return -EOPNOTSUPP; - } - - /* Set Operation mode to the PORT TYPE RID */ - result = p80211wext_setmib(wlandev, - DIDmib_p2_p2Static_p2CnfPortType, - (*mode == IW_MODE_ADHOC) ? 0 : 1); - if (result) - err = -EFAULT; -exit: - return err; -} - -static int p80211wext_giwrange(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - int i, val; - - /* for backward compatability set size and zero everything we don't understand */ - data->length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - range->txpower_capa = IW_TXPOW_DBM; - /* XXX what about min/max_pmp, min/max_pmt, etc. */ - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 13; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */ - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */ - range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | - IW_EVENT_CAPA_MASK(IWEVCUSTOM)); - - range->num_channels = NUM_CHANNELS; - - /* XXX need to filter against the regulatory domain &| active set */ - val = 0; - for (i = 0; i < NUM_CHANNELS; i++) { - range->freq[val].i = i + 1; - range->freq[val].m = p80211wext_channel_freq[i] * 100000; - range->freq[val].e = 1; - val++; - } - - range->num_frequency = val; - - /* Max of /proc/net/wireless */ - range->max_qual.qual = 100; - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->sensitivity = 3; - /* XXX these need to be nsd-specific! */ - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->max_encoding_tokens = NUM_WEPKEYS; - range->num_encoding_sizes = 2; - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - - /* XXX what about num_bitrates/throughput? */ - range->num_bitrates = 0; - - /* estimated max throughput */ - /* XXX need to cap it if we're running at ~2Mbps.. */ - range->throughput = 5500000; - - return 0; -} - -static int p80211wext_giwap(netdevice_t *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - - wlandevice_t *wlandev = dev->ml_priv; - - memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN); - ap_addr->sa_family = ARPHRD_ETHER; - - return 0; -} - -static int p80211wext_giwencode(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - wlandevice_t *wlandev = dev->ml_priv; - int err = 0; - int i; - - i = (erq->flags & IW_ENCODE_INDEX) - 1; - erq->flags = 0; - - if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - erq->flags |= IW_ENCODE_ENABLED; - else - erq->flags |= IW_ENCODE_DISABLED; - - if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - i = (erq->flags & IW_ENCODE_INDEX) - 1; - - if (i == -1) - i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; - - if ((i < 0) || (i >= NUM_WEPKEYS)) { - err = -EINVAL; - goto exit; - } - - erq->flags |= i + 1; - - /* copy the key from the driver cache as the keys are read-only MIBs */ - erq->length = wlandev->wep_keylens[i]; - memcpy(key, wlandev->wep_keys[i], erq->length); - -exit: - return err; -} - -static int p80211wext_siwencode(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_mibset_t msg; - p80211item_pstr32_t pstr; - - int err = 0; - int result = 0; - int i; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - /* Check the Key index first. */ - i = (erq->flags & IW_ENCODE_INDEX); - if (i) { - if ((i < 1) || (i > NUM_WEPKEYS)) { - err = -EINVAL; - goto exit; - } else { - i--; - } - /* Set current key number only if no keys are given */ - if (erq->flags & IW_ENCODE_NOKEY) { - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, - i); - - if (result) { - err = -EFAULT; - goto exit; - } - } - - } else { - /* Use defaultkey if no Key Index */ - i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; - } - - /* Check if there is no key information in the iwconfig request */ - if ((erq->flags & IW_ENCODE_NOKEY) == 0) { - - /*------------------------------------------------------------ - * If there is WEP Key for setting, check the Key Information - * and then set it to the firmware. - -------------------------------------------------------------*/ - - if (erq->length > 0) { - /* copy the key from the driver cache as the keys are read-only MIBs */ - wlandev->wep_keylens[i] = erq->length; - memcpy(wlandev->wep_keys[i], key, erq->length); - - /* Prepare data struture for p80211req_dorequest. */ - memcpy(pstr.data.data, key, erq->length); - pstr.data.len = erq->length; - - switch (i) { - case 0: - pstr.did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - pstr.did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - pstr.did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - pstr.did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } - - msg.msgcode = DIDmsg_dot11req_mibset; - memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr)); - result = p80211req_dorequest(wlandev, (u8 *) &msg); - - if (result) { - err = -EFAULT; - goto exit; - } - } - - } - - /* Check the PrivacyInvoked flag */ - if (erq->flags & IW_ENCODE_DISABLED) { - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, - P80211ENUM_truth_false); - } else { - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, - P80211ENUM_truth_true); - } - - if (result) { - err = -EFAULT; - goto exit; - } - - /* The security mode may be open or restricted, and its meaning - depends on the card used. With most cards, in open mode no - authentication is used and the card may also accept non- - encrypted sessions, whereas in restricted mode only encrypted - sessions are accepted and the card will use authentication if - available. - */ - if (erq->flags & IW_ENCODE_RESTRICTED) { - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, - P80211ENUM_truth_true); - } else if (erq->flags & IW_ENCODE_OPEN) { - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, - P80211ENUM_truth_false); - } - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - - return err; -} - -static int p80211wext_giwessid(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - wlandevice_t *wlandev = dev->ml_priv; - - if (wlandev->ssid.len) { - data->length = wlandev->ssid.len; - data->flags = 1; - memcpy(essid, wlandev->ssid.data, data->length); - essid[data->length] = 0; - } else { - memset(essid, 0, sizeof(wlandev->ssid.data)); - data->length = 0; - data->flags = 0; - } - - return 0; -} - -static int p80211wext_siwessid(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211msg_lnxreq_autojoin_t msg; - - int result; - int err = 0; - int length = data->length; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - if (wlandev->hostwep & HOSTWEP_SHAREDKEY) - msg.authtype.data = P80211ENUM_authalg_sharedkey; - else - msg.authtype.data = P80211ENUM_authalg_opensystem; - - msg.msgcode = DIDmsg_lnxreq_autojoin; - - /* Trim the last '\0' to fit the SSID format */ - if (length && essid[length - 1] == '\0') - length--; - - memcpy(msg.ssid.data.data, essid, length); - msg.ssid.data.len = length; - - pr_debug("autojoin_ssid for %s \n", essid); - result = p80211req_dorequest(wlandev, (u8 *) &msg); - pr_debug("autojoin_ssid %d\n", result); - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int p80211wext_siwcommit(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - wlandevice_t *wlandev = dev->ml_priv; - int err = 0; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - /* Auto Join */ - err = p80211wext_autojoin(wlandev); - -exit: - return err; -} - -static int p80211wext_giwrate(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - result = p80211wext_getmib(wlandev, DIDmib_p2_p2MAC_p2CurrentTxRate, &value); - if (result) { - err = -EFAULT; - goto exit; - } - - rrq->fixed = 0; /* can it change? */ - rrq->disabled = 0; - rrq->value = 0; - -#define HFA384x_RATEBIT_1 ((u16)1) -#define HFA384x_RATEBIT_2 ((u16)2) -#define HFA384x_RATEBIT_5dot5 ((u16)4) -#define HFA384x_RATEBIT_11 ((u16)8) - - switch (value) { - case HFA384x_RATEBIT_1: - rrq->value = 1000000; - break; - case HFA384x_RATEBIT_2: - rrq->value = 2000000; - break; - case HFA384x_RATEBIT_5dot5: - rrq->value = 5500000; - break; - case HFA384x_RATEBIT_11: - rrq->value = 11000000; - break; - default: - err = -EINVAL; - } -exit: - return err; -} - -static int p80211wext_giwrts(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - rts->value = value; - rts->disabled = (rts->value == 2347); - rts->fixed = 1; - -exit: - return err; -} - -static int p80211wext_siwrts(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - if (!wlan_wext_write) { - err = -EOPNOTSUPP; - goto exit; - } - - if (rts->disabled) - value = 2347; - else - value = rts->value; - - result = p80211wext_setmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, - value); - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int p80211wext_giwfrag(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - frag->value = value; - frag->disabled = (frag->value == 2346); - frag->fixed = 1; - -exit: - return err; -} - -static int p80211wext_siwfrag(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - int value; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - if (frag->disabled) - value = 2346; - else - value = frag->value; - - result = p80211wext_setmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, - value); - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -#ifndef IW_RETRY_LONG -#define IW_RETRY_LONG IW_RETRY_MAX -#endif - -#ifndef IW_RETRY_SHORT -#define IW_RETRY_SHORT IW_RETRY_MIN -#endif - -static int p80211wext_giwretry(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - u16 shortretry, longretry, lifetime; - unsigned int value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - shortretry = value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - longretry = value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, - &value); - if (result) { - err = -EFAULT; - goto exit; - } - - lifetime = value; - - rrq->disabled = 0; - - if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - rrq->flags = IW_RETRY_LIFETIME; - rrq->value = lifetime * 1024; - } else { - if (rrq->flags & IW_RETRY_LONG) { - rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - rrq->value = longretry; - } else { - rrq->flags = IW_RETRY_LIMIT; - rrq->value = shortretry; - if (shortretry != longretry) - rrq->flags |= IW_RETRY_SHORT; - } - } - -exit: - return err; - -} - -static int p80211wext_siwretry(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; - int result; - int err = 0; - unsigned int value; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - if (rrq->disabled) { - err = -EINVAL; - goto exit; - } - - msg.msgcode = DIDmsg_dot11req_mibset; - - if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - - value = rrq->value /= 1024; - result = p80211wext_setmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, - value); - if (result) { - err = -EFAULT; - goto exit; - } - } else { - if (rrq->flags & IW_RETRY_LONG) { - result = p80211wext_setmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, - rrq->value); - - if (result) { - err = -EFAULT; - goto exit; - } - } - - if (rrq->flags & IW_RETRY_SHORT) { - result = p80211wext_setmib(wlandev, - DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, - rrq->value); - - if (result) { - err = -EFAULT; - goto exit; - } - } - } - -exit: - return err; - -} - -static int p80211wext_siwtxpow(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; - int result; - int err = 0; - unsigned int value; - - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - if (rrq->fixed == 0) - value = 30; - else - value = rrq->value; - result = p80211wext_setmib(wlandev, - DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, - value); - - if (result) { - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int p80211wext_giwtxpow(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - int result; - int err = 0; - unsigned int value; - - result = p80211wext_getmib(wlandev, - DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, - &value); - - if (result) { - err = -EFAULT; - goto exit; - } - - /* XXX handle OFF by setting disabled = 1; */ - - rrq->flags = 0; /* IW_TXPOW_DBM; */ - rrq->disabled = 0; - rrq->fixed = 0; - rrq->value = value; - -exit: - return err; -} - -static int p80211wext_siwspy(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct sockaddr address[IW_MAX_SPY]; - int number = srq->length; - int i; - - /* Copy the data from the input buffer */ - memcpy(address, extra, sizeof(struct sockaddr) * number); - - wlandev->spy_number = 0; - - if (number > 0) { - - /* extract the addresses */ - for (i = 0; i < number; i++) { - - memcpy(wlandev->spy_address[i], address[i].sa_data, - ETH_ALEN); - } - - /* reset stats */ - memset(wlandev->spy_stat, 0, - sizeof(struct iw_quality) * IW_MAX_SPY); - - /* set number of addresses */ - wlandev->spy_number = number; - } - - return 0; -} - -/* jkriegl: from orinoco, modified */ -static int p80211wext_giwspy(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - - struct sockaddr address[IW_MAX_SPY]; - struct iw_quality spy_stat[IW_MAX_SPY]; - int number; - int i; - - number = wlandev->spy_number; - - if (number > 0) { - - /* populate address and spy struct's */ - for (i = 0; i < number; i++) { - memcpy(address[i].sa_data, wlandev->spy_address[i], - ETH_ALEN); - address[i].sa_family = AF_UNIX; - memcpy(&spy_stat[i], &wlandev->spy_stat[i], - sizeof(struct iw_quality)); - } - - /* reset update flag */ - for (i = 0; i < number; i++) - wlandev->spy_stat[i].updated = 0; - } - - /* push stuff to user space */ - srq->length = number; - memcpy(extra, address, sizeof(struct sockaddr) * number); - memcpy(extra + sizeof(struct sockaddr) * number, spy_stat, - sizeof(struct iw_quality) * number); - - return 0; -} - -static int prism2_result2err(int prism2_result) -{ - int err = 0; - - switch (prism2_result) { - case P80211ENUM_resultcode_invalid_parameters: - err = -EINVAL; - break; - case P80211ENUM_resultcode_implementation_failure: - err = -EIO; - break; - case P80211ENUM_resultcode_not_supported: - err = -EOPNOTSUPP; - break; - default: - err = 0; - break; - } - - return err; -} - -static int p80211wext_siwscan(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_scan_t msg; - int result; - int err = 0; - int i = 0; - - if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { - printk(KERN_ERR "Can't scan in AP mode\n"); - err = (-EOPNOTSUPP); - goto exit; - } - - memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t)); - msg.msgcode = DIDmsg_dot11req_scan; - msg.bsstype.data = P80211ENUM_bsstype_any; - - memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t)); - msg.bssid.data.len = 6; - - msg.scantype.data = P80211ENUM_scantype_active; - msg.probedelay.data = 0; - - for (i = 1; i <= 14; i++) - msg.channellist.data.data[i - 1] = i; - msg.channellist.data.len = 14; - - msg.maxchanneltime.data = 250; - msg.minchanneltime.data = 200; - - result = p80211req_dorequest(wlandev, (u8 *) &msg); - if (result) - err = prism2_result2err(msg.resultcode.data); - -exit: - return err; -} - -/* Helper to translate scan into Wireless Extensions scan results. - * Inspired by the prism54 code, which was in turn inspired by the - * airo driver code. - */ -static char *wext_translate_bss(struct iw_request_info *info, char *current_ev, - char *end_buf, - p80211msg_dot11req_scan_results_t *bss) -{ - struct iw_event iwe; /* Temporary buffer */ - - /* The first entry must be the MAC address */ - memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN); - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - iwe.cmd = SIOCGIWAP; - current_ev = - iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - /* The following entries will be displayed in the same order we give them */ - - /* The ESSID. */ - if (bss->ssid.data.len > 0) { - char essid[IW_ESSID_MAX_SIZE + 1]; - int size; - - size = - min_t(unsigned short, IW_ESSID_MAX_SIZE, - bss->ssid.data.len); - memset(&essid, 0, sizeof(essid)); - memcpy(&essid, bss->ssid.data.data, size); - pr_debug(" essid size = %d\n", size); - iwe.u.data.length = size; - iwe.u.data.flags = 1; - iwe.cmd = SIOCGIWESSID; - current_ev = - iwe_stream_add_point(info, current_ev, end_buf, &iwe, - &essid[0]); - pr_debug(" essid size OK.\n"); - } - - switch (bss->bsstype.data) { - case P80211ENUM_bsstype_infrastructure: - iwe.u.mode = IW_MODE_MASTER; - break; - - case P80211ENUM_bsstype_independent: - iwe.u.mode = IW_MODE_ADHOC; - break; - - default: - iwe.u.mode = 0; - break; - } - iwe.cmd = SIOCGIWMODE; - if (iwe.u.mode) - current_ev = - iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_UINT_LEN); - - /* Encryption capability */ - if (bss->privacy.data == P80211ENUM_truth_true) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - iwe.cmd = SIOCGIWENCODE; - current_ev = - iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL); - - /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = bss->dschannel.data; - iwe.u.freq.e = 0; - iwe.cmd = SIOCGIWFREQ; - current_ev = - iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - - /* Add quality statistics */ - iwe.u.qual.level = bss->signal.data; - iwe.u.qual.noise = bss->noise.data; - /* do a simple SNR for quality */ - iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data); - iwe.cmd = IWEVQUAL; - current_ev = - iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_QUAL_LEN); - - return current_ev; -} - -static int p80211wext_giwscan(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_scan_results_t msg; - int result = 0; - int err = 0; - int i = 0; - int scan_good = 0; - char *current_ev = extra; - - /* Since wireless tools doesn't really have a way of passing how - * many scan results results there were back here, keep grabbing them - * until we fail. - */ - do { - memset(&msg, 0, sizeof(msg)); - msg.msgcode = DIDmsg_dot11req_scan_results; - msg.bssindex.data = i; - - result = p80211req_dorequest(wlandev, (u8 *) &msg); - if ((result != 0) || - (msg.resultcode.data != P80211ENUM_resultcode_success)) { - break; - } - - current_ev = - wext_translate_bss(info, current_ev, - extra + IW_SCAN_MAX_DATA, &msg); - scan_good = 1; - i++; - } while (i < IW_MAX_AP); - - srq->length = (current_ev - extra); - srq->flags = 0; /* todo */ - - if (result && !scan_good) - err = prism2_result2err(msg.resultcode.data); - - return err; -} - -/* extra wireless extensions stuff to support NetworkManager (I hope) */ - -/* SIOCSIWENCODEEXT */ -static int p80211wext_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - p80211msg_dot11req_mibset_t msg; - p80211item_pstr32_t *pstr; - - int result = 0; - struct iw_point *encoding = &wrqu->encoding; - int idx = encoding->flags & IW_ENCODE_INDEX; - - pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n", - ext->ext_flags, (int)ext->alg, (int)ext->key_len); - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - /* set default key ? I'm not sure if this the the correct thing to do here */ - - if (idx) { - if (idx < 1 || idx > NUM_WEPKEYS) - return -EINVAL; - else - idx--; - } - pr_debug("setting default key (%d)\n", idx); - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, - idx); - if (result) - return -EFAULT; - } - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - if (ext->alg != IW_ENCODE_ALG_WEP) { - pr_debug("asked to set a non wep key :(\n"); - return -EINVAL; - } - if (idx) { - if (idx < 1 || idx > NUM_WEPKEYS) - return -EINVAL; - else - idx--; - } - pr_debug("Set WEP key (%d)\n", idx); - wlandev->wep_keylens[idx] = ext->key_len; - memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len); - - memset(&msg, 0, sizeof(msg)); - pstr = (p80211item_pstr32_t *) &msg.mibattribute.data; - memcpy(pstr->data.data, ext->key, ext->key_len); - pstr->data.len = ext->key_len; - switch (idx) { - case 0: - pstr->did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - case 1: - pstr->did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - case 2: - pstr->did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - case 3: - pstr->did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - default: - break; - } - msg.msgcode = DIDmsg_dot11req_mibset; - result = p80211req_dorequest(wlandev, (u8 *) &msg); - pr_debug("result (%d)\n", result); - } - return result; -} - -/* SIOCGIWENCODEEXT */ -static int p80211wext_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - - struct iw_point *encoding = &wrqu->encoding; - int result = 0; - int max_len; - int idx; - - pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n", - ext->ext_flags, (int)ext->alg, (int)ext->key_len); - - max_len = encoding->length - sizeof(*ext); - if (max_len <= 0) { - pr_debug("get_encodeext max_len [%d] invalid\n", max_len); - result = -EINVAL; - goto exit; - } - idx = encoding->flags & IW_ENCODE_INDEX; - - pr_debug("get_encode_ext index [%d]\n", idx); - - if (idx) { - if (idx < 1 || idx > NUM_WEPKEYS) { - pr_debug("get_encode_ext invalid key index [%d]\n", - idx); - result = -EINVAL; - goto exit; - } - idx--; - } else { - /* default key ? not sure what to do */ - /* will just use key[0] for now ! FIX ME */ - } - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - ext->alg = IW_ENCODE_ALG_WEP; - ext->key_len = wlandev->wep_keylens[idx]; - memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len); - - encoding->flags |= IW_ENCODE_ENABLED; -exit: - return result; -} - -/* SIOCSIWAUTH */ -static int p80211_wext_set_iwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct iw_param *param = &wrqu->param; - int result = 0; - - pr_debug("set_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX); - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - pr_debug("drop_unencrypted %d\n", param->value); - if (param->value) - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, - P80211ENUM_truth_true); - else - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, - P80211ENUM_truth_false); - break; - - case IW_AUTH_PRIVACY_INVOKED: - pr_debug("privacy invoked %d\n", param->value); - if (param->value) - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, - P80211ENUM_truth_true); - else - result = - p80211wext_setmib(wlandev, - DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, - P80211ENUM_truth_false); - - break; - - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - pr_debug("set open_system\n"); - wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; - } else if (param->value & IW_AUTH_ALG_SHARED_KEY) { - pr_debug("set shared key\n"); - wlandev->hostwep |= HOSTWEP_SHAREDKEY; - } else { - /* don't know what to do know */ - pr_debug("unknown AUTH_ALG (%d)\n", param->value); - result = -EINVAL; - } - break; - - default: - break; - } - - return result; -} - -/* SIOCSIWAUTH */ -static int p80211_wext_get_iwauth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct iw_param *param = &wrqu->param; - int result = 0; - - pr_debug("get_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX); - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - param->value = - wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0; - break; - - case IW_AUTH_PRIVACY_INVOKED: - param->value = - wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0; - break; - - case IW_AUTH_80211_AUTH_ALG: - param->value = - wlandev->hostwep & HOSTWEP_SHAREDKEY ? - IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; - break; - - default: - break; - } - - return result; -} - -#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] - -static iw_handler p80211wext_handlers[] = { - IW_IOCTL(SIOCSIWCOMMIT) = (iw_handler) p80211wext_siwcommit, - IW_IOCTL(SIOCGIWNAME) = (iw_handler) p80211wext_giwname, -/* SIOCSIWNWID,SIOCGIWNWID */ - IW_IOCTL(SIOCSIWFREQ) = (iw_handler) p80211wext_siwfreq, - IW_IOCTL(SIOCGIWFREQ) = (iw_handler) p80211wext_giwfreq, - IW_IOCTL(SIOCSIWMODE) = (iw_handler) p80211wext_siwmode, - IW_IOCTL(SIOCGIWMODE) = (iw_handler) p80211wext_giwmode, -/* SIOCSIWSENS,SIOCGIWSENS,SIOCSIWRANGE */ - IW_IOCTL(SIOCGIWRANGE) = (iw_handler) p80211wext_giwrange, -/* SIOCSIWPRIV,SIOCGIWPRIV,SIOCSIWSTATS,SIOCGIWSTATS */ - IW_IOCTL(SIOCSIWSPY) = (iw_handler) p80211wext_siwspy, - IW_IOCTL(SIOCGIWSPY) = (iw_handler) p80211wext_giwspy, -/* SIOCSIWAP */ - IW_IOCTL(SIOCGIWAP) = (iw_handler) p80211wext_giwap, -/* SIOCGIWAPLIST */ - IW_IOCTL(SIOCSIWSCAN) = (iw_handler) p80211wext_siwscan, - IW_IOCTL(SIOCGIWSCAN) = (iw_handler) p80211wext_giwscan, - IW_IOCTL(SIOCSIWESSID) = (iw_handler) p80211wext_siwessid, - IW_IOCTL(SIOCGIWESSID) = (iw_handler) p80211wext_giwessid, -/* SIOCSIWNICKN */ - IW_IOCTL(SIOCGIWNICKN) = (iw_handler) p80211wext_giwessid, -/* SIOCSIWRATE */ - IW_IOCTL(SIOCGIWRATE) = (iw_handler) p80211wext_giwrate, - IW_IOCTL(SIOCSIWRTS) = (iw_handler) p80211wext_siwrts, - IW_IOCTL(SIOCGIWRTS) = (iw_handler) p80211wext_giwrts, - IW_IOCTL(SIOCSIWFRAG) = (iw_handler) p80211wext_siwfrag, - IW_IOCTL(SIOCGIWFRAG) = (iw_handler) p80211wext_giwfrag, - IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) p80211wext_siwtxpow, - IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) p80211wext_giwtxpow, - IW_IOCTL(SIOCSIWRETRY) = (iw_handler) p80211wext_siwretry, - IW_IOCTL(SIOCGIWRETRY) = (iw_handler) p80211wext_giwretry, - IW_IOCTL(SIOCSIWENCODE) = (iw_handler) p80211wext_siwencode, - IW_IOCTL(SIOCGIWENCODE) = (iw_handler) p80211wext_giwencode, -/* SIOCSIWPOWER,SIOCGIWPOWER */ -/* WPA operations */ -/* SIOCSIWGENIE,SIOCGIWGENIE generic IE */ - IW_IOCTL(SIOCSIWAUTH) = (iw_handler) p80211_wext_set_iwauth, /*set authentication mode params */ - IW_IOCTL(SIOCGIWAUTH) = (iw_handler) p80211_wext_get_iwauth, /*get authentication mode params */ - IW_IOCTL(SIOCSIWENCODEEXT) = (iw_handler) p80211wext_set_encodeext, /*set encoding token & mode */ - IW_IOCTL(SIOCGIWENCODEEXT) = (iw_handler) p80211wext_get_encodeext, /*get encoding token & mode */ -/* SIOCSIWPMKSA PMKSA cache operation */ -}; - -struct iw_handler_def p80211wext_handler_def = { - .num_standard = ARRAY_SIZE(p80211wext_handlers), - .standard = p80211wext_handlers, - .get_wireless_stats = p80211wext_get_wireless_stats -}; - -int p80211wext_event_associated(wlandevice_t *wlandev, int assoc) -{ - union iwreq_data data; - - /* Send the association state first */ - data.ap_addr.sa_family = ARPHRD_ETHER; - if (assoc) - memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN); - else - memset(data.ap_addr.sa_data, 0, ETH_ALEN); - - if (wlan_wext_write) - wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL); - - if (!assoc) - goto done; - - /* XXX send association data, like IEs, etc etc. */ - -done: - return 0; -} diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 4d1cdfc35420..ef23f8b1454f 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -463,6 +463,8 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* capinfo bits */ count = le16_to_cpu(item->capinfo); + req->capinfo.status = P80211ENUM_msgitem_status_data_ok; + req->capinfo.data = count; /* privacy flag */ req->privacy.status = P80211ENUM_msgitem_status_data_ok; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 6cd09352f893..5ec5741b5eb1 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -124,6 +124,10 @@ MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms"); MODULE_LICENSE("Dual MPL/GPL"); +void prism2_connect_result(wlandevice_t *wlandev, u8 failed); +void prism2_disconnected(wlandevice_t *wlandev); +void prism2_roamed(wlandevice_t *wlandev); + static int prism2sta_open(wlandevice_t *wlandev); static int prism2sta_close(wlandevice_t *wlandev); static void prism2sta_reset(wlandevice_t *wlandev); @@ -401,6 +405,7 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) qualmsg->link.data = le16_to_cpu(hw->qual.CQ_currBSS); qualmsg->level.data = le16_to_cpu(hw->qual.ASL_currBSS); qualmsg->noise.data = le16_to_cpu(hw->qual.ANL_currFC); + qualmsg->txrate.data = hw->txrate; break; } @@ -1300,6 +1305,9 @@ void prism2sta_processing_defer(struct work_struct *data) (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; + /* signal back up to cfg80211 layer */ + prism2_connect_result(wlandev, P80211ENUM_truth_false); + /* Get the ball rolling on the comms quality stuff */ prism2sta_commsqual_defer(&hw->commsqual_bh); } @@ -1315,25 +1323,16 @@ void prism2sta_processing_defer(struct work_struct *data) * Indicate Deauthentication * Block Transmits, Ignore receives of data frames */ - if (hw->join_ap == 2) { - hfa384x_JoinRequest_data_t joinreq; - joinreq = hw->joinreq; - /* Send the join request */ - hfa384x_drvr_setconfig(hw, - HFA384x_RID_JOINREQUEST, - &joinreq, - HFA384x_RID_JOINREQUEST_LEN); + if (wlandev->netdev->type == ARPHRD_ETHER) printk(KERN_INFO - "linkstatus=DISCONNECTED (re-submitting join)\n"); - } else { - if (wlandev->netdev->type == ARPHRD_ETHER) - printk(KERN_INFO - "linkstatus=DISCONNECTED (unhandled)\n"); - } + "linkstatus=DISCONNECTED (unhandled)\n"); wlandev->macmode = WLAN_MACMODE_NONE; netif_carrier_off(wlandev->netdev); + /* signal back up to cfg80211 layer */ + prism2_disconnected(wlandev); + break; case HFA384x_LINK_AP_CHANGE: @@ -1376,6 +1375,9 @@ void prism2sta_processing_defer(struct work_struct *data) hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); + /* signal back up to cfg80211 layer */ + prism2_roamed(wlandev); + break; case HFA384x_LINK_AP_OUTOFRANGE: @@ -1435,6 +1437,9 @@ void prism2sta_processing_defer(struct work_struct *data) netif_carrier_off(wlandev->netdev); + /* signal back up to cfg80211 layer */ + prism2_connect_result(wlandev, P80211ENUM_truth_true); + break; default: @@ -1446,7 +1451,6 @@ void prism2sta_processing_defer(struct work_struct *data) } wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED); - p80211wext_event_associated(wlandev, wlandev->linkstatus); failed: return; @@ -1985,6 +1989,8 @@ void prism2sta_commsqual_defer(struct work_struct *data) hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); wlandevice_t *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; + p80211msg_dot11req_mibget_t msg; + p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; int result = 0; if (hw->wlandev->hwremoved) @@ -2013,6 +2019,34 @@ void prism2sta_commsqual_defer(struct work_struct *data) le16_to_cpu(hw->qual.ANL_currFC)); } + /* Get the signal rate */ + msg.msgcode = DIDmsg_dot11req_mibget; + mibitem->did = DIDmib_p2_p2MAC_p2CurrentTxRate; + result = p80211req_dorequest(wlandev, (u8 *) & msg); + + if (result) { + pr_debug("get signal rate failed, result = %d\n", + result); + goto done; + } + + switch (mibitem->data) { + case HFA384x_RATEBIT_1: + hw->txrate = 10; + break; + case HFA384x_RATEBIT_2: + hw->txrate = 20; + break; + case HFA384x_RATEBIT_5dot5: + hw->txrate = 55; + break; + case HFA384x_RATEBIT_11: + hw->txrate = 110; + break; + default: + pr_debug("Bad ratebit (%d)\n", mibitem->data); + } + /* Lastly, we need to make sure the BSSID didn't change on us */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index f5cff751db2f..4efa027a81e4 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -119,7 +119,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, } hw = wlandev->priv; - if (wlan_setup(wlandev) != 0) { + if (wlan_setup(wlandev, &(interface->dev)) != 0) { printk(KERN_ERR "%s: wlan_setup() failed.\n", dev_info); result = -EIO; goto failed; -- cgit v1.2.3 From 2e04bb7b284198f26e129b03e03459a7045cb8b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Jun 2010 15:30:28 -0700 Subject: Staging: winbond: fix build errors Some errors crept in due to a previous patch that I missed. This fixes them up so the driver continues to build, sorry about that. Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/phy_calibration.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c index 5eefea31948c..5c1f05392db9 100644 --- a/drivers/staging/winbond/phy_calibration.c +++ b/drivers/staging/winbond/phy_calibration.c @@ -32,7 +32,7 @@ static const s32 Angles[] = { FIXED(DEG2RAD(0.111906)), FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977)) }; -/****************** LOCAL FUNCTION DECLARATION SECTION ********************** +/****************** LOCAL FUNCTION DECLARATION SECTION **********************/ /* * void _phy_rf_write_delay(struct hw_data *phw_data); @@ -142,7 +142,6 @@ u32 _s32_to_s6(s32 data) data = 31; else if (data < -32) data = -32; - } val = data & 0x003F; @@ -1496,7 +1495,7 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) /******************/ void phy_set_rf_data(struct hw_data *pHwData, u32 index, u32 value) { - u32 ltmpi = 0; + u32 ltmp = 0; switch (pHwData->phy_type) { case RF_MAXIM_2825: -- cgit v1.2.3 From 594578979d0e25e178e0243eca9aa53499b89b05 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 17 Jun 2010 14:08:47 +0200 Subject: Staging: wlan-ng: silence a sparse warning This doesn't change the behavior. It just silences a sparse warning. drivers/staging/wlan-ng/hfa384x_usb.c:2810:62: warning: dubious: !x | !y The point of the bitwise OR is so that a logical OR could short circuit the second call to test_and_set_bit(). Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index a41db5dc8c7c..563017aaa363 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2805,11 +2805,13 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) spin_lock_irqsave(&hw->ctlxq.lock, flags); - if (!hw->wlandev->hwremoved && - /* Note the bitwise OR, not the logical OR. */ - (!test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) | - !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))) { - schedule_work(&hw->usb_work); + if (!hw->wlandev->hwremoved) { + int sched; + + sched = !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags); + sched |= !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags); + if (sched) + schedule_work(&hw->usb_work); } spin_unlock_irqrestore(&hw->ctlxq.lock, flags); -- cgit v1.2.3 From b55515cf729a33e49ecbc4f623ead33c735b5a65 Mon Sep 17 00:00:00 2001 From: Scott Kidder Date: Wed, 26 May 2010 22:36:15 -0500 Subject: Staging: otus: fix style issues in zdusb.c This is a patch to zdusb.c that fixes whitespace, C99 comment, and other style issues found by the checkpatch.pl tool Signed-off-by: Scott Kidder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/otus/zdusb.c | 251 ++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/otus/zdusb.c b/drivers/staging/otus/zdusb.c index 2c799a250294..4014b7472454 100644 --- a/drivers/staging/otus/zdusb.c +++ b/drivers/staging/otus/zdusb.c @@ -48,7 +48,7 @@ static const char driver_name[] = "Otus"; /* table of devices that work with this driver */ static const struct usb_device_id zd1221_ids[] = { { USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) }, - { USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) }, + { USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) }, { USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WNDA3100) }, { USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WN111v2) }, { } /* Terminating entry */ @@ -60,9 +60,9 @@ extern u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp); extern int usbdrv_close(struct net_device *dev); extern u8_t zfLnxClearStructs(struct net_device *dev); extern int zfWdsClose(struct net_device *dev); -extern int zfUnregisterWdsDev(struct net_device* parentDev, u16_t wdsId); +extern int zfUnregisterWdsDev(struct net_device *parentDev, u16_t wdsId); extern int zfLnxVapClose(struct net_device *dev); -extern int zfLnxUnregisterVapDev(struct net_device* parentDev, u16_t vapId); +extern int zfLnxUnregisterVapDev(struct net_device *parentDev, u16_t vapId); /* WDS */ extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; @@ -73,148 +73,135 @@ extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; static int zfLnxProbe(struct usb_interface *interface, const struct usb_device_id *id) { - struct usb_device *dev = interface_to_usbdev(interface); - - struct net_device *net = NULL; - struct usbdrv_private *macp = NULL; - int vendor_id, product_id; - int result = 0; - - usb_get_dev(dev); - - vendor_id = dev->descriptor.idVendor; - product_id = dev->descriptor.idProduct; - -#ifdef HMAC_DEBUG - printk(KERN_NOTICE "vendor_id = %04x\n", vendor_id); - printk(KERN_NOTICE "product_id = %04x\n", product_id); - - if (dev->speed == USB_SPEED_HIGH) - printk(KERN_NOTICE "USB 2.0 Host\n"); - else - printk(KERN_NOTICE "USB 1.1 Host\n"); -#endif - - macp = kzalloc(sizeof(struct usbdrv_private), GFP_KERNEL); - if (!macp) - { - printk(KERN_ERR "out of memory allocating device structure\n"); - result = -ENOMEM; - goto fail; - } - - net = alloc_etherdev(0); - - if (net == NULL) - { - printk(KERN_ERR "zfLnxProbe: Not able to alloc etherdev struct\n"); - result = -ENOMEM; - goto fail1; - } - - strcpy(net->name, "ath%d"); - - net->ml_priv = macp; //kernel 2.6 - macp->udev = dev; - macp->device = net; - - /* set up the endpoint information */ - /* check out the endpoints */ - macp->interface = interface; - - //init_waitqueue_head(&macp->regSet_wait); - //init_waitqueue_head(&macp->iorwRsp_wait); - //init_waitqueue_head(&macp->term_wait); - - if (!zfLnxAllocAllUrbs(macp)) - { - result = -ENOMEM; - goto fail2; - } - - if (!zfLnxInitSetup(net, macp)) - { - result = -EIO; - goto fail3; - } - else - { - usb_set_intfdata(interface, macp); - SET_NETDEV_DEV(net, &interface->dev); - - if (register_netdev(net) != 0) - { - usb_set_intfdata(interface, NULL); - goto fail3; - } - } - - netif_carrier_off(net); - goto done; - + struct usb_device *dev = interface_to_usbdev(interface); + + struct net_device *net = NULL; + struct usbdrv_private *macp = NULL; + int vendor_id, product_id; + int result = 0; + + usb_get_dev(dev); + + vendor_id = dev->descriptor.idVendor; + product_id = dev->descriptor.idProduct; + + #ifdef HMAC_DEBUG + printk(KERN_NOTICE "vendor_id = %04x\n", vendor_id); + printk(KERN_NOTICE "product_id = %04x\n", product_id); + + if (dev->speed == USB_SPEED_HIGH) + printk(KERN_NOTICE "USB 2.0 Host\n"); + else + printk(KERN_NOTICE "USB 1.1 Host\n"); + #endif + + macp = kzalloc(sizeof(struct usbdrv_private), GFP_KERNEL); + if (!macp) { + printk(KERN_ERR "out of memory allocating device structure\n"); + result = -ENOMEM; + goto fail; + } + + net = alloc_etherdev(0); + + if (net == NULL) { + printk(KERN_ERR "zfLnxProbe: Not able to alloc etherdev struct\n"); + result = -ENOMEM; + goto fail1; + } + + strcpy(net->name, "ath%d"); + + net->ml_priv = macp; /* kernel 2.6 */ + macp->udev = dev; + macp->device = net; + + /* set up the endpoint information */ + /* check out the endpoints */ + macp->interface = interface; + + /* init_waitqueue_head(&macp->regSet_wait); */ + /* init_waitqueue_head(&macp->iorwRsp_wait); */ + /* init_waitqueue_head(&macp->term_wait); */ + + if (!zfLnxAllocAllUrbs(macp)) { + result = -ENOMEM; + goto fail2; + } + + if (!zfLnxInitSetup(net, macp)) { + result = -EIO; + goto fail3; + } else { + usb_set_intfdata(interface, macp); + SET_NETDEV_DEV(net, &interface->dev); + + if (register_netdev(net) != 0) { + usb_set_intfdata(interface, NULL); + goto fail3; + } + } + + netif_carrier_off(net); + goto done; fail3: - zfLnxFreeAllUrbs(macp); + zfLnxFreeAllUrbs(macp); fail2: - free_netdev(net); //kernel 2.6 + free_netdev(net); /* kernel 2.6 */ fail1: - kfree(macp); - + kfree(macp); fail: - usb_put_dev(dev); - macp = NULL; - + usb_put_dev(dev); + macp = NULL; done: - return result; + return result; } static void zfLnxDisconnect(struct usb_interface *interface) { - struct usbdrv_private *macp = (struct usbdrv_private *) usb_get_intfdata(interface); - - printk(KERN_DEBUG "zfLnxDisconnect\n"); - - if (!macp) - { - printk(KERN_ERR "unregistering non-existant device\n"); - return; - } - - if (macp->driver_isolated) - { - if (macp->device->flags & IFF_UP) - usbdrv_close(macp->device); - } - -#if 0 - /* Close WDS */ - //zfWdsClose(wds[0].dev); - /* Unregister WDS */ - //zfUnregisterWdsDev(macp->device, 0); - - /* Close VAP */ - zfLnxVapClose(vap[0].dev); - /* Unregister VAP */ - zfLnxUnregisterVapDev(macp->device, 0); -#endif + struct usbdrv_private *macp = (struct usbdrv_private *) usb_get_intfdata(interface); + + printk(KERN_DEBUG "zfLnxDisconnect\n"); + + if (!macp) { + printk(KERN_ERR "unregistering non-existant device\n"); + return; + } + + if (macp->driver_isolated) + if (macp->device->flags & IFF_UP) + usbdrv_close(macp->device); + + #if 0 + /* Close WDS */ + /* zfWdsClose(wds[0].dev); */ + /* Unregister WDS */ + /* zfUnregisterWdsDev(macp->device, 0); */ + + /* Close VAP */ + zfLnxVapClose(vap[0].dev); + /* Unregister VAP */ + zfLnxUnregisterVapDev(macp->device, 0); + #endif - zfLnxClearStructs(macp->device); + zfLnxClearStructs(macp->device); - unregister_netdev(macp->device); + unregister_netdev(macp->device); - usb_put_dev(interface_to_usbdev(interface)); + usb_put_dev(interface_to_usbdev(interface)); - //printk(KERN_ERR "3. zfLnxUnlinkAllUrbs\n"); - //zfLnxUnlinkAllUrbs(macp); + /* printk(KERN_ERR "3. zfLnxUnlinkAllUrbs\n"); */ + /* zfLnxUnlinkAllUrbs(macp); */ - /* Free network interface */ - free_netdev(macp->device); + /* Free network interface */ + free_netdev(macp->device); - zfLnxFreeAllUrbs(macp); - //zfLnxClearStructs(macp->device); - kfree(macp); - macp = NULL; + zfLnxFreeAllUrbs(macp); + /* zfLnxClearStructs(macp->device); */ + kfree(macp); + macp = NULL; - usb_set_intfdata(interface, NULL); + usb_set_intfdata(interface, NULL); } static struct usb_driver zd1221_driver = { @@ -226,13 +213,13 @@ static struct usb_driver zd1221_driver = { int __init zfLnxIinit(void) { - printk(KERN_NOTICE "%s - version %s\n", DRIVER_NAME, VERSIONID); - return usb_register(&zd1221_driver); + printk(KERN_NOTICE "%s - version %s\n", DRIVER_NAME, VERSIONID); + return usb_register(&zd1221_driver); } void __exit zfLnxExit(void) { - usb_deregister(&zd1221_driver); + usb_deregister(&zd1221_driver); } module_init(zfLnxIinit); -- cgit v1.2.3 From 84f8008a7d1a44aa7c37d0ea367802e07e7daac0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 7 Jun 2010 12:11:35 -0700 Subject: Staging: otus: TODO: Don't bother, for documentation purposes only On Mon, 2010-06-07 at 12:02 -0700, Luis R. Rodriguez wrote: > this driver is unmaintained and its only purpose is as a > source of documentation for developers working on ar9170 and carl9170. > Once carl9170 gets 11n support and merged upstream then this driver > can be removed. Then the TODO file should be updated. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/otus/TODO | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/otus/TODO b/drivers/staging/otus/TODO index 4caf026a4915..6fea974fcc9f 100644 --- a/drivers/staging/otus/TODO +++ b/drivers/staging/otus/TODO @@ -2,15 +2,7 @@ I'm hesitant to add a TODO file here, as the wireless developers would really have people help them out on the "clean" ar9170 driver that can be found at the linux-wireless developer site. -But, if you wish to clean up this driver instead, here's a short list of -things that need to be done to get it into a more mergable shape: - -TODO: - - checkpatch.pl cleanups - - sparse cleanups - - port to in-kernel 80211 stack - - review by the wireless developer community - -Please send any patches to Greg Kroah-Hartman and -Luis Rodriguez and the -otus-devel@lists.madwifi-project.org mailing list. +This driver is unmaintained and its only purpose is as a +source of documentation for developers working on ar9170 and carl9170. +Once carl9170 gets 11n support and merged upstream then this driver +can be removed. -- cgit v1.2.3 From cc7e7d38e9170719f780dd16312eef216714ad35 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Jun 2010 23:44:57 +0200 Subject: Staging: otus: fix strcpy() overflow wrq->name is only 16 characters long but "IEEE 802.11-MIMO" is 16 characters + a NULL character, so it's too long. This patch changes it to "IEEE 802.11abgn". Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/otus/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/otus/ioctl.c b/drivers/staging/otus/ioctl.c index a48c8e4a9ea7..b85f1b29e3bc 100644 --- a/drivers/staging/otus/ioctl.c +++ b/drivers/staging/otus/ioctl.c @@ -507,7 +507,7 @@ int usbdrvwext_giwname(struct net_device *dev, { /* struct usbdrv_private *macp = dev->ml_priv; */ - strcpy(wrq->name, "IEEE 802.11-MIMO"); + strcpy(wrq->name, "IEEE 802.11abgn"); return 0; } -- cgit v1.2.3 From fa3620c515491ed94a403c1d4374fcc19350d7f3 Mon Sep 17 00:00:00 2001 From: Matti Lammi Date: Thu, 17 Jun 2010 11:41:33 +0300 Subject: Staging: otus: Removed one unnecessary space Nothing special really, just a small fix. Signed-off-by: Matti Lammi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/otus/apdbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/otus/apdbg.c b/drivers/staging/otus/apdbg.c index b59028e7e33c..32c26e59baf7 100644 --- a/drivers/staging/otus/apdbg.c +++ b/drivers/staging/otus/apdbg.c @@ -180,7 +180,7 @@ int main(int argc, char **argv) if (argc < 3) { fprintf(stderr, "%s: usage is \"%s " "[
] []\"\n", prgname, prgname); - fprintf(stderr, "valid operation : read, write, mem, reg, \n"); + fprintf(stderr, "valid operation : read, write, mem, reg,\n"); fprintf(stderr, " : txd, rxd, rmem, wmem\n"); fprintf(stderr, " : dmat, regt, test\n"); -- cgit v1.2.3 From 231ded903f2f30b2bcdbf6672c7197187e3bb1ee Mon Sep 17 00:00:00 2001 From: Scott Kidder Date: Fri, 28 May 2010 00:21:51 -0500 Subject: Staging: cx25821: added KERN_ facility levels Fixed issues found by checkpatch.pl including adding KERN_ facility levels to printk() calls and C99 comments. Signed-off-by: Scott Kidder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cx25821/cx25821-audups11.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index e49ead982f39..8debde1bb683 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c @@ -82,9 +82,8 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) } } - if (list_empty(&q->active)) { + if (list_empty(&q->active)) dprintk(2, "active queue empty!\n"); - } } static struct videobuf_queue_ops cx25821_video_qops = { @@ -101,7 +100,7 @@ static int video_open(struct file *file) struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - printk("open dev=%s type=%s\n", video_device_node_name(vdev), + printk(KERN_INFO "open dev=%s type=%s\n", video_device_node_name(vdev), v4l2_type_names[type]); /* allocate + initialize per filehandle data */ @@ -139,7 +138,7 @@ static int video_open(struct file *file) } static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) + loff_t *ppos) { struct cx25821_fh *fh = file->private_data; @@ -187,8 +186,8 @@ static int video_release(struct file *file) struct cx25821_fh *fh = file->private_data; struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - //cx_write(channel11->dma_ctl, 0); + /* stop the risc engine and fifo */ + /* cx_write(channel11->dma_ctl, 0); */ /* stop video capture */ if (cx25821_res_check(fh, RESOURCE_VIDEO11)) { @@ -216,17 +215,14 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) return -EINVAL; - } - if (unlikely(i != fh->type)) { + if (unlikely(i != fh->type)) return -EINVAL; - } - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO11)))) { + if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO11)))) return -EBUSY; - } return videobuf_streamon(get_queue(fh)); } @@ -297,9 +293,8 @@ static long video_ioctl_upstream11(struct file *file, unsigned int cmd, command = data_from_user->command; - if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) { + if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) return 0; - } dev->input_filename = data_from_user->input_filename; dev->input_audiofilename = data_from_user->input_filename; @@ -357,7 +352,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return 0; } -// exported stuff +/* exported stuff */ static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = video_open, -- cgit v1.2.3 From ef079a76fe78d713eb695a222601fccb3e706f0f Mon Sep 17 00:00:00 2001 From: Nanakos Chrysostomos Date: Thu, 27 May 2010 16:19:52 +0000 Subject: Staging: dream: pmem.c: Fix checkpatch.pl issues. This patch resolves checkpatch.pl issues in the pmem.c file. Signed-off-by: Nanakos Chrysostomos Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dream/pmem.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c index 6387365a833d..064b59e5b500 100644 --- a/drivers/staging/dream/pmem.c +++ b/drivers/staging/dream/pmem.c @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include #define PMEM_MAX_DEVICES 10 @@ -175,7 +175,7 @@ static int pmem_mmap(struct file *, struct vm_area_struct *); static int pmem_open(struct inode *, struct file *); static long pmem_ioctl(struct file *, unsigned int, unsigned long); -struct file_operations pmem_fops = { +const struct file_operations pmem_fops = { .release = pmem_release, .mmap = pmem_mmap, .open = pmem_open, @@ -399,8 +399,8 @@ static int pmem_allocate(int id, unsigned long len) DLOG("order %lx\n", order); /* look through the bitmap: - * if you find a free slot of the correct order use it - * otherwise, use the best fit (smallest with size > order) slot + * if you find a free slot of the correct order use it + * otherwise, use the best fit (smallest with size > order) slot */ while (curr < end) { if (PMEM_IS_FREE(id, curr)) { @@ -426,8 +426,8 @@ static int pmem_allocate(int id, unsigned long len) } /* now partition the best fit: - * split the slot into 2 buddies of order - 1 - * repeat until the slot is of the correct order + * split the slot into 2 buddies of order - 1 + * repeat until the slot is of the correct order */ while (PMEM_ORDER(id, best_fit) > (unsigned char)order) { int buddy; -- cgit v1.2.3 From 6167944d8a28c6a405babc4ae0f830be80a13fbb Mon Sep 17 00:00:00 2001 From: Scott Kidder Date: Wed, 26 May 2010 23:38:45 -0500 Subject: Staging: crystalhd: removed kfree(NULL) checks Removed kfree(NULL checks) that were not necessary Signed-off-by: Scott Kidder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/crystalhd/crystalhd_lnx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c index a4ec891328cd..9d2805a33fd6 100644 --- a/drivers/staging/crystalhd/crystalhd_lnx.c +++ b/drivers/staging/crystalhd/crystalhd_lnx.c @@ -152,10 +152,8 @@ static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, struct crystalhd_ioctl if (rc) { BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n", io->add_cdata_sz, (unsigned int)ua_off); - if (io->add_cdata) { - kfree(io->add_cdata); - io->add_cdata = NULL; - } + kfree(io->add_cdata); + io->add_cdata = NULL; return -ENODATA; } @@ -435,8 +433,7 @@ static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp) /* Clear iodata pool.. */ do { temp = chd_dec_alloc_iodata(adp, 0); - if (temp) - kfree(temp); + kfree(temp); } while (temp); crystalhd_delete_elem_pool(adp); -- cgit v1.2.3 From 0374e91c90ee74d4419ac91fb2030d96ee16d544 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 28 May 2010 13:59:52 +0200 Subject: Staging: rtl81xx: Fix build problems when CONFIG_CRYPTO=n Select CONFIG_CRYPTO for all rtl81xx wireless drivers ... to avoid build problems like: ERROR: "crypto_destroy_tfm" [drivers/staging/rtl8187se/r8187se.ko] undefined! ERROR: "crypto_alloc_base" [drivers/staging/rtl8187se/r8187se.ko] undefined! ERROR: "crypto_destroy_tfm" [drivers/staging/rtl8192u/r8192u_usb.ko] undefined! ERROR: "crypto_alloc_base" [drivers/staging/rtl8192u/r8192u_usb.ko] undefined! ERROR: "crypto_destroy_tfm" [drivers/staging/rtl8192su/r8192s_usb.ko] undefined! ERROR: "crypto_alloc_base" [drivers/staging/rtl8192su/r8192s_usb.ko] undefined! ERROR: "crypto_destroy_tfm" [drivers/staging/rtl8192e/r8192e_pci.ko] undefined! ERROR: "crypto_alloc_base" [drivers/staging/rtl8192e/r8192e_pci.ko] undefined! when drivers are built as modules but CONFIG_CRYPTO=n. Signed-off-by: Andreas Herrmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/Kconfig | 1 + drivers/staging/rtl8192e/Kconfig | 1 + drivers/staging/rtl8192su/Kconfig | 1 + drivers/staging/rtl8192u/Kconfig | 1 + 4 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 155a78e07405..1b3103fbf29c 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig @@ -4,6 +4,7 @@ config R8187SE select WIRELESS_EXT select WEXT_PRIV select EEPROM_93CX6 + select CRYPTO default N ---help--- If built as a module, it will be called r8187se.ko. diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig index 2ae3745f775f..2e64b239e241 100644 --- a/drivers/staging/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/Kconfig @@ -3,5 +3,6 @@ config RTL8192E depends on PCI && WLAN select WIRELESS_EXT select WEXT_PRIV + select CRYPTO default N ---help--- diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig index b422ea1ecf9c..27b89a432670 100644 --- a/drivers/staging/rtl8192su/Kconfig +++ b/drivers/staging/rtl8192su/Kconfig @@ -4,5 +4,6 @@ config RTL8192SU select WIRELESS_EXT select WEXT_PRIV select EEPROM_93CX6 + select CRYPTO default N ---help--- diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig index 0439c90b4163..28969198e7e2 100644 --- a/drivers/staging/rtl8192u/Kconfig +++ b/drivers/staging/rtl8192u/Kconfig @@ -3,5 +3,6 @@ config RTL8192U depends on PCI && WLAN && USB select WIRELESS_EXT select WEXT_PRIV + select CRYPTO default N ---help--- -- cgit v1.2.3 From 70eef90e494aa3a941cbc3c4e196dc367e01b089 Mon Sep 17 00:00:00 2001 From: Nanakos Chrysostomos Date: Thu, 27 May 2010 19:20:41 +0000 Subject: Staging: dt3155: dt3155_isr.c: Fix checkpatch.pl issues. Fix resolves checkpatch.pl issues. Signed-off-by: Nanakos Chrysostomos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dt3155/dt3155_isr.c | 47 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dt3155/dt3155_isr.c b/drivers/staging/dt3155/dt3155_isr.c index 33ddc9c057ff..59b7bfd535d6 100644 --- a/drivers/staging/dt3155/dt3155_isr.c +++ b/drivers/staging/dt3155/dt3155_isr.c @@ -153,10 +153,12 @@ void push_ready(int m, int index) *****************************************************/ static int get_tail(int m) { - return (dt3155_fbuffer[m]->ready_head - - dt3155_fbuffer[m]->ready_len + - dt3155_fbuffer[m]->nbuffers)% - (dt3155_fbuffer[m]->nbuffers); + int ncount; + ncount = (dt3155_fbuffer[m]->ready_head - + dt3155_fbuffer[m]->ready_len + + dt3155_fbuffer[m]->nbuffers)% + (dt3155_fbuffer[m]->nbuffers); + return ncount; } @@ -191,23 +193,23 @@ void printques(int m) tail = get_tail(m); - printk("\n R:"); + printk(KERN_INFO "\n R:"); for (index = tail; index != head; index++, index = index % (num)) { frame_index = dt3155_fbuffer[m]->ready_que[index]; printk(" %d ", frame_index); } - printk("\n E:"); + printk(KERN_INFO "\n E:"); for (index = 0; index < dt3155_fbuffer[m]->empty_len; index++) { frame_index = dt3155_fbuffer[m]->empty_buffers[index]; printk(" %d ", frame_index); } frame_index = dt3155_fbuffer[m]->active_buf; - printk("\n A: %d", frame_index); + printk(KERN_INFO "\n A: %d", frame_index); frame_index = dt3155_fbuffer[m]->locked_buf; - printk("\n L: %d\n", frame_index); + printk(KERN_INFO "\n L: %d\n", frame_index); } @@ -263,19 +265,21 @@ void allocate_buffers(u32 *buf_addr, u32* total_size_kbs, #endif size_kbs = full_size_kbs; *buf_addr = 0; - printk("DT3155: We would like to get: %d KB\n", full_size_kbs); - printk("DT3155: ...but need at least: %d KB\n", min_size_kbs); - printk("DT3155: ...the allocator has: %d KB\n", allocator_max); + printk(KERN_INFO "DT3155: We would like to get: %d KB\n", full_size_kbs); + printk(KERN_INFO "DT3155: ...but need at least: %d KB\n", min_size_kbs); + printk(KERN_INFO "DT3155: ...the allocator has: %d KB\n", allocator_max); size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max); if (size_kbs > min_size_kbs) { - if ((*buf_addr = allocator_allocate_dma(size_kbs, GFP_KERNEL)) != 0) { - printk("DT3155: Managed to allocate: %d KB\n", size_kbs); + *buf_addr = allocator_allocate_dma(size_kbs, GFP_KERNEL); + if (*buf_addr != 0) { + printk(KERN_INFO "DT3155: Managed to allocate: %d KB\n", + size_kbs); *total_size_kbs = size_kbs; return; } } /* If we got here, the allocation failed */ - printk("DT3155: Allocator failed!\n"); + printk(KERN_INFO "DT3155: Allocator failed!\n"); *buf_addr = 0; *total_size_kbs = 0; return; @@ -324,9 +328,9 @@ u32 dt3155_setup_buffers(u32 *allocatorAddr) /* allocate a large contiguous chunk of RAM */ allocate_buffers(&rambuff_addr, &rambuff_size, bufsize); - printk("DT3155: mem info\n"); - printk(" - rambuf_addr = 0x%x\n", rambuff_addr); - printk(" - length (kb) = %u\n", rambuff_size); + printk(KERN_INFO "DT3155: mem info\n"); + printk(KERN_INFO " - rambuf_addr = 0x%x\n", rambuff_addr); + printk(KERN_INFO " - length (kb) = %u\n", rambuff_size); if (rambuff_addr == 0) { printk(KERN_INFO "DT3155: Error setup_buffers() allocator dma failed\n"); @@ -339,7 +343,8 @@ u32 dt3155_setup_buffers(u32 *allocatorAddr) are so we can give an equal number to each device */ rambuff_acm = rambuff_addr; for (index = 0; index < MAXBUFFERS; index++) { - rambuff_acm = adjust_4MB(rambuff_acm, bufsize);/*avoid spanning 4MB bdry*/ + /*avoid spanning 4MB bdry*/ + rambuff_acm = adjust_4MB(rambuff_acm, bufsize); if (rambuff_acm + bufsize > rambuff_end) break; rambuff_acm += bufsize; @@ -347,7 +352,7 @@ u32 dt3155_setup_buffers(u32 *allocatorAddr) /* Following line is OK, will waste buffers if index * not evenly divisible by ndevices -NJC*/ numbufs = index / ndevices; - printk(" - numbufs = %u\n", numbufs); + printk(KERN_INFO " - numbufs = %u\n", numbufs); if (numbufs < 2) { printk(KERN_INFO "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n"); @@ -367,7 +372,7 @@ u32 dt3155_setup_buffers(u32 *allocatorAddr) rambuff_acm = adjust_4MB(rambuff_acm, bufsize); if (rambuff_acm + bufsize > rambuff_end) { /* Should never happen */ - printk("DT3155 PROGRAM ERROR (GCS)\n" + printk(KERN_INFO "DT3155 PROGRAM ERROR (GCS)\n" "Error distributing allocated buffers\n"); return -ENOMEM; } @@ -395,7 +400,7 @@ u32 dt3155_setup_buffers(u32 *allocatorAddr) /* setup the ready queue */ dt3155_fbuffer[m]->ready_head = 0; dt3155_fbuffer[m]->ready_len = 0; - printk("Available buffers for device %d: %d\n", + printk(KERN_INFO "Available buffers for device %d: %d\n", m, dt3155_fbuffer[m]->nbuffers); } -- cgit v1.2.3 From 616f58f6ec5e5777c343499ad65a34e671533e4b Mon Sep 17 00:00:00 2001 From: Mike Gilks Date: Thu, 3 Jun 2010 18:29:23 +0800 Subject: staging: rtl8192u: fix checkpatch.pl issues to line 514 Fixed most problems pointed out by checkpatch.pl in file r8192U_core.c up to line 500 Signed-off-by: Mike Gilks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_core.c | 73 +++++++++++++--------------------- 1 file changed, 28 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 2bede271a2f0..358013482fd4 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -408,14 +408,12 @@ u16 read_nic_word(struct net_device *dev, int indx) struct usb_device *udev = priv->udev; status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2); + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx&0xff)|0xff00, (indx>>8)&0x0f, + &data, 2, HZ / 2); if (status < 0) - { printk("read_nic_word TimeOut! status:%d\n", status); - } - return data; } @@ -429,13 +427,10 @@ u16 read_nic_word_E(struct net_device *dev, int indx) status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - indx|0xfe00, 0, &data, 2, HZ / 2); + indx|0xfe00, 0, &data, 2, HZ / 2); if (status < 0) - { printk("read_nic_word TimeOut! status:%d\n", status); - } - return data; } @@ -444,31 +439,29 @@ u32 read_nic_dword(struct net_device *dev, int indx) { u32 data; int status; -// int result; + /* int result; */ struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); struct usb_device *udev = priv->udev; status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2); -// if(0 != result) { -// printk(KERN_WARNING "read size of data = %d\, date = %d\n", result, data); -// } + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx&0xff)|0xff00, (indx>>8)&0x0f, + &data, 4, HZ / 2); + /* if(0 != result) { + * printk(KERN_WARNING "read size of data = %d\, date = %d\n", + * result, data); + * } + */ if (status < 0) - { printk("read_nic_dword TimeOut! status:%d\n", status); - } - - return data; } - -//u8 read_phy_cck(struct net_device *dev, u8 adr); -//u8 read_phy_ofdm(struct net_device *dev, u8 adr); +/* u8 read_phy_cck(struct net_device *dev, u8 adr); */ +/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */ /* this might still called in what was the PHY rtl8185/rtl8192 common code * plans are to possibilty turn it again in one common code... */ @@ -476,26 +469,22 @@ inline void force_pci_posting(struct net_device *dev) { } - static struct net_device_stats *rtl8192_stats(struct net_device *dev); void rtl8192_commit(struct net_device *dev); -//void rtl8192_restart(struct net_device *dev); +/* void rtl8192_restart(struct net_device *dev); */ void rtl8192_restart(struct work_struct *work); -//void rtl8192_rq_tx_ack(struct work_struct *work); - +/* void rtl8192_rq_tx_ack(struct work_struct *work); */ void watch_dog_timer_callback(unsigned long data); /**************************************************************************** - -----------------------------PROCFS STUFF------------------------- -*****************************************************************************/ - -static struct proc_dir_entry *rtl8192_proc = NULL; - + * -----------------------------PROCFS STUFF------------------------- +***************************************************************************** + */ +static struct proc_dir_entry *rtl8192_proc; -static int proc_get_stats_ap(char *page, char **start, - off_t offset, int count, - int *eof, void *data) +static int proc_get_stats_ap(char *page, char **start, off_t offset, int count, + int *eof, void *data) { struct net_device *dev = data; struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); @@ -506,18 +495,12 @@ static int proc_get_stats_ap(char *page, char **start, list_for_each_entry(target, &ieee->network_list, list) { - len += snprintf(page + len, count - len, - "%s ", target->ssid); - - if(target->wpa_ie_len>0 || target->rsn_ie_len>0){ - len += snprintf(page + len, count - len, - "WPA\n"); - } - else{ - len += snprintf(page + len, count - len, - "non_WPA\n"); - } + len += snprintf(page + len, count - len, "%s ", target->ssid); + if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0) + len += snprintf(page + len, count - len, "WPA\n"); + else + len += snprintf(page + len, count - len, "non_WPA\n"); } *eof = 1; -- cgit v1.2.3 From f932e3a361731b403b1c2982197cea7e3d8e0e66 Mon Sep 17 00:00:00 2001 From: Marin Mitov Date: Sun, 6 Jun 2010 14:16:07 +0300 Subject: Staging: dt3155v4l: correcting a pointer mismatch bug and cleanups The third argument of dma_alloc_coherent() is of type dma_addr_t and is defined as u64 for x86_64, while the member 'device_base' of struct dma_coherent_mem is defined as u32. While at it, clean up the code. Now if dev->dma_mem != NULL all the fields/members are already properly initialized. Signed-off-by: Marin Mitov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dt3155v4l/dt3155v4l.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dt3155v4l/dt3155v4l.c b/drivers/staging/dt3155v4l/dt3155v4l.c index 6dc3af622848..fd48b38e797c 100644 --- a/drivers/staging/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/dt3155v4l/dt3155v4l.c @@ -1008,6 +1008,8 @@ struct dma_coherent_mem { static int __devinit dt3155_alloc_coherent(struct device *dev, size_t size, int flags) { + struct dma_coherent_mem *mem; + dma_addr_t dev_base; int pages = size >> PAGE_SHIFT; int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); @@ -1018,25 +1020,28 @@ dt3155_alloc_coherent(struct device *dev, size_t size, int flags) if (dev->dma_mem) goto out; - dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); - if (!dev->dma_mem) + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) goto out; - dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!dev->dma_mem->bitmap) + mem->virt_base = dma_alloc_coherent(dev, size, &dev_base, + DT3155_COH_FLAGS); + if (!mem->virt_base) + goto err_alloc_coherent; + mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!mem->bitmap) goto err_bitmap; - dev->dma_mem->virt_base = dma_alloc_coherent(dev, size, - &dev->dma_mem->device_base, DT3155_COH_FLAGS); - if (!dev->dma_mem->virt_base) - goto err_coherent; - dev->dma_mem->size = pages; - dev->dma_mem->flags = flags; + /* coherent_dma_mask is already set to 32 bits */ + mem->device_base = dev_base; + mem->size = pages; + mem->flags = flags; + dev->dma_mem = mem; return DMA_MEMORY_MAP; -err_coherent: - kfree(dev->dma_mem->bitmap); err_bitmap: - kfree(dev->dma_mem); + dma_free_coherent(dev, size, mem->virt_base, dev_base); +err_alloc_coherent: + kfree(mem); out: return 0; } -- cgit v1.2.3 From 0f3ff30b9384ffa1b435f263234531582080b100 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 7 Jun 2010 13:25:37 -0500 Subject: Staging: dt3155: fix different address spaces noise in dt3155_drv.c This fixes the different address spaces noise when copying data to/from user space to kernel space. Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dt3155/dt3155_drv.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dt3155/dt3155_drv.c b/drivers/staging/dt3155/dt3155_drv.c index 40ef97f3feb5..3024d35ed348 100644 --- a/drivers/staging/dt3155/dt3155_drv.c +++ b/drivers/staging/dt3155/dt3155_drv.c @@ -521,6 +521,7 @@ static int dt3155_ioctl(struct inode *inode, unsigned long arg) { int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */ + void __user *up = (void __user *)arg; if (minor >= MAXBOARDS || minor < 0) return -ENODEV; @@ -547,7 +548,7 @@ static int dt3155_ioctl(struct inode *inode, { struct dt3155_config tmp; - if (copy_from_user((void *)&tmp, (void *) arg, sizeof(tmp))) + if (copy_from_user(&tmp, up, sizeof(tmp))) return -EFAULT; /* check for valid settings */ if (tmp.rows > DT3155_MAX_ROWS || @@ -565,7 +566,7 @@ static int dt3155_ioctl(struct inode *inode, } case DT3155_GET_CONFIG: { - if (copy_to_user((void *) arg, (void *) &dt3155_status[minor], + if (copy_to_user(up, &dt3155_status[minor], sizeof(struct dt3155_status))) return -EFAULT; return 0; @@ -586,7 +587,7 @@ static int dt3155_ioctl(struct inode *inode, return 0; quick_stop(minor); - if (copy_to_user((void *) arg, (void *) &dt3155_status[minor], + if (copy_to_user(up, &dt3155_status[minor], sizeof(struct dt3155_status))) return -EFAULT; return 0; @@ -610,7 +611,7 @@ static int dt3155_ioctl(struct inode *inode, } dt3155_init_isr(minor); - if (copy_to_user((void *) arg, (void *) &dt3155_status[minor], + if (copy_to_user(up, &dt3155_status[minor], sizeof(struct dt3155_status))) return -EFAULT; return 0; @@ -812,11 +813,11 @@ static ssize_t dt3155_read(struct file *filep, char __user *buf, /* make this an offset */ offset = frame_info->addr - dt3155_status[minor].mem_addr; - put_user(offset, (unsigned int *) buf); + put_user(offset, (unsigned int __user *)buf); buf += sizeof(u32); - put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int *) buf); + put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int __user *)buf); buf += sizeof(u32); - put_user(dt3155_status[minor].state, (unsigned int *) buf); + put_user(dt3155_status[minor].state, (unsigned int __user *)buf); buf += sizeof(u32); if (copy_to_user(buf, frame_info, sizeof(*frame_info))) return -EFAULT; -- cgit v1.2.3 From a46f9087e634224b3d0a6560e223425816846dff Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 8 Jun 2010 10:36:57 -0500 Subject: Staging: dt3155: remove DT_3155_* errno defines Remove the DT_3155_{SUCCESS/FAILURE} errno defines and use the kernel provided ones. Signed-off-by: H Hartley Sweeten Cc: Scott Smedley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dt3155/dt3155_drv.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dt3155/dt3155_drv.c b/drivers/staging/dt3155/dt3155_drv.c index 3024d35ed348..dcd384933319 100644 --- a/drivers/staging/dt3155/dt3155_drv.c +++ b/drivers/staging/dt3155/dt3155_drv.c @@ -97,9 +97,6 @@ int dt3155_errno = 0; /* wait queue for interrupts */ wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS]; -#define DT_3155_SUCCESS 0 -#define DT_3155_FAILURE -EIO - /* set to dynamicaly allocate, but it is tunable: */ /* insmod DT_3155 dt3155 dt3155_major=XX */ int dt3155_major = 0; @@ -942,11 +939,11 @@ static int find_PCI (void) } ndevices = pci_index; - return DT_3155_SUCCESS; + return 0; err: pci_dev_put(pci_dev); - return DT_3155_FAILURE; + return -EIO; } u32 allocatorAddr = 0; @@ -1000,7 +997,7 @@ int init_module(void) /* Now let's find the hardware. find_PCI() will set ndevices to the * number of cards found in this machine. */ { - if ((rcode = find_PCI()) != DT_3155_SUCCESS) + if ((rcode = find_PCI()) != 0) { printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n"); unregister_chrdev(dt3155_major, "dt3155"); -- cgit v1.2.3 From ab17a4ac32ac914cc6d65f25b21bdcaf453c35cf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sat, 5 Jun 2010 21:41:00 -0400 Subject: Staging: pohmelfs: fix compile warning A really trivial patch to solve a warning when compiling staging/pohmelfs Signed-off-by: Javier Martinez Canillas Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pohmelfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 643b413d9f0f..20b0c68aaa56 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c @@ -1266,7 +1266,7 @@ static void pohmelfs_put_super(struct super_block *sb) { struct pohmelfs_sb *psb = POHMELFS_SB(sb); struct pohmelfs_inode *pi; - unsigned int count; + unsigned int count = 0; unsigned int in_drop_list = 0; struct inode *inode, *tmp; -- cgit v1.2.3 From b8564d7b3855660e01faa7ba7a4e0303e5a13dfd Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 5 Jun 2010 22:43:09 +0800 Subject: Staging: XGI: remove duplicated #include Remove duplicated #include('s) in drivers/staging/xgifb/XGI_main_26.c drivers/staging/xgifb/vb_init.c Signed-off-by: Huang Weiyi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 1 - drivers/staging/xgifb/vb_init.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 867012b48a01..68bc1d839ad6 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "osdef.h" diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index b85ca9ba8076..08a02e3aaa5a 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -41,7 +41,6 @@ #ifdef LINUX_KERNEL #include -#include #endif -- cgit v1.2.3 From 7ddd5d02799e1bb7e14ccb87bff16261a80efa27 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 5 Jun 2010 22:42:59 +0800 Subject: Staging: MSM: remove duplicated #include Remove duplicated #include('s) in drivers/staging/msm/mddihost.h drivers/staging/msm/msm_fb_def.h drivers/staging/msm/staging-devices.c Signed-off-by: Huang Weiyi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/msm/mddihost.h | 2 -- drivers/staging/msm/msm_fb_def.h | 4 ---- drivers/staging/msm/staging-devices.c | 1 - 3 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h index 20b817841c4a..c46f24aea250 100644 --- a/drivers/staging/msm/mddihost.h +++ b/drivers/staging/msm/mddihost.h @@ -44,8 +44,6 @@ #include #include -#include -#include #include "msm_fb_panel.h" diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h index 6de440937422..c5f9e9e670fb 100644 --- a/drivers/staging/msm/msm_fb_def.h +++ b/drivers/staging/msm/msm_fb_def.h @@ -50,15 +50,11 @@ #include #include -#include #include #include -#include #include -#include "linux/proc_fs.h" #include #include -#include #include #include #include diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c index 0f8ec3e26013..2a5c459b1e5a 100644 --- a/drivers/staging/msm/staging-devices.c +++ b/drivers/staging/msm/staging-devices.c @@ -18,7 +18,6 @@ #include "msm_mdp.h" #include "memory_ll.h" //#include "android_pmem.h" -#include #ifdef CONFIG_MSM_SOC_REV_A #define MSM_SMI_BASE 0xE0000000 -- cgit v1.2.3 From 186305aa1284ac0cae88e18b837c33d5a4a84afc Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sun, 6 Jun 2010 21:28:13 +0200 Subject: Staging: batman-adv: remove redundant struct declaration The hardif_attr and the bat_attr struct share the same attributes, hence it is not necessary to specify 2 different structs. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_sysfs.c | 48 +++++++++------------------------- drivers/staging/batman-adv/bat_sysfs.h | 13 +++++++++ 2 files changed, 25 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index e2c000b80ca0..065a2123dbc6 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -28,22 +28,6 @@ #define to_dev(obj) container_of(obj, struct device, kobj) -struct bat_attribute { - struct attribute attr; - ssize_t (*show)(struct kobject *kobj, struct attribute *attr, - char *buf); - ssize_t (*store)(struct kobject *kobj, struct attribute *attr, - char *buf, size_t count); -}; - -struct hardif_attribute { - struct attribute attr; - ssize_t (*show)(struct kobject *kobj, struct attribute *attr, - char *buf); - ssize_t (*store)(struct kobject *kobj, struct attribute *attr, - char *buf, size_t count); -}; - #define BAT_ATTR(_name, _mode, _show, _store) \ struct bat_attribute bat_attr_##_name = { \ .attr = {.name = __stringify(_name), \ @@ -60,14 +44,6 @@ struct bin_attribute bat_attr_##_name = { \ .write = _write, \ }; -#define HARDIF_ATTR(_name, _mode, _show, _store) \ -struct hardif_attribute hardif_attr_##_name = { \ - .attr = {.name = __stringify(_name), \ - .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -433,20 +409,20 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr, } } -static HARDIF_ATTR(mesh_iface, S_IRUGO | S_IWUSR, - show_mesh_iface, store_mesh_iface); -static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); +static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR, + show_mesh_iface, store_mesh_iface); +static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); -static struct hardif_attribute *batman_attrs[] = { - &hardif_attr_mesh_iface, - &hardif_attr_iface_status, +static struct bat_attribute *batman_attrs[] = { + &bat_attr_mesh_iface, + &bat_attr_iface_status, NULL, }; int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) { struct kobject *hardif_kobject = &dev->dev.kobj; - struct hardif_attribute **hardif_attr; + struct bat_attribute **bat_attr; int err; *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR, @@ -458,12 +434,12 @@ int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) goto out; } - for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) { - err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr)); + for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) { + err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr)); if (err) { printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", dev->name, SYSFS_IF_BAT_SUBDIR, - ((*hardif_attr)->attr).name); + ((*bat_attr)->attr).name); goto rem_attr; } } @@ -471,8 +447,8 @@ int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) return 0; rem_attr: - for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) - sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr)); + for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) + sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); out: return -ENOMEM; } diff --git a/drivers/staging/batman-adv/bat_sysfs.h b/drivers/staging/batman-adv/bat_sysfs.h index e1893411871e..cb45a912738a 100644 --- a/drivers/staging/batman-adv/bat_sysfs.h +++ b/drivers/staging/batman-adv/bat_sysfs.h @@ -20,10 +20,23 @@ */ +#ifndef BAT_SYSFS_H +#define BAT_SYSFS_H + #define SYSFS_IF_MESH_SUBDIR "mesh" #define SYSFS_IF_BAT_SUBDIR "batman_adv" +struct bat_attribute { + struct attribute attr; + ssize_t (*show)(struct kobject *kobj, struct attribute *attr, + char *buf); + ssize_t (*store)(struct kobject *kobj, struct attribute *attr, + char *buf, size_t count); +}; + int sysfs_add_meshif(struct net_device *dev); void sysfs_del_meshif(struct net_device *dev); int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev); void sysfs_del_hardif(struct kobject **hardif_obj); + +#endif -- cgit v1.2.3 From 96d592ed599434d2d5f339a1d282871bc6377d2c Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Sun, 6 Jun 2010 21:28:17 +0200 Subject: Staging: batman-adv: Adding netfilter-bridge hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit batman-adv is receiving and sending the packets of its own ether type on a very early/low level. Therefore we need to add explicit hooks to give netfilter/ebtables a chance to filter them. Reported-by: Antonio Quartulli Signed-off-by: Linus Lüssing Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/hard-interface.c | 14 +++++++++++++- drivers/staging/batman-adv/send.c | 9 +++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 7a582e80de18..6939b8d4ec80 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -30,6 +30,7 @@ #include "hash.h" #include +#include #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -432,6 +433,11 @@ out: return NOTIFY_DONE; } +static int batman_skb_recv_finish(struct sk_buff *skb) +{ + return NF_ACCEPT; +} + /* receive a packet with the batman ethertype coming on a hard * interface */ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -451,6 +457,13 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (atomic_read(&module_state) != MODULE_ACTIVE) goto err_free; + /* if netfilter/ebtables wants to block incoming batman + * packets then give them a chance to do so here */ + ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL, + batman_skb_recv_finish); + if (ret != 1) + goto err_out; + /* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) goto err_free; @@ -530,7 +543,6 @@ err_out: return NET_RX_DROP; } - struct notifier_block hard_if_notifier = { .notifier_call = hard_if_event, }; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index ac69ed871a76..7365f6dbcb6b 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -29,6 +29,8 @@ #include "vis.h" #include "aggregation.h" +#include + /* apply hop penalty for a normal link */ static uint8_t hop_penalty(const uint8_t tq) { @@ -90,9 +92,12 @@ int send_skb_packet(struct sk_buff *skb, /* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP - * (which is > 0). This will not be treated as an error. */ + * (which is > 0). This will not be treated as an error. + * Also, if netfilter/ebtables wants to block outgoing batman + * packets then giving them a chance to do so here */ - return dev_queue_xmit(skb); + return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, + dev_queue_xmit); send_skb_err: kfree_skb(skb); return NET_XMIT_DROP; -- cgit v1.2.3 From 8af60a8cf06f071a85b6101c86249cce92fa4203 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sun, 6 Jun 2010 21:28:18 +0200 Subject: Staging: batman-adv: Add information about batman-adv sysfs entries Add documents about new sysfs entries in * /sys/class/net//batman-adv/mesh_iface * /sys/class/net//mesh/vis_mode Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- .../staging/batman-adv/sysfs-class-net-batman-adv | 14 ++++++++++++ drivers/staging/batman-adv/sysfs-class-net-mesh | 25 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 drivers/staging/batman-adv/sysfs-class-net-batman-adv create mode 100644 drivers/staging/batman-adv/sysfs-class-net-mesh (limited to 'drivers') diff --git a/drivers/staging/batman-adv/sysfs-class-net-batman-adv b/drivers/staging/batman-adv/sysfs-class-net-batman-adv new file mode 100644 index 000000000000..38dd762def4b --- /dev/null +++ b/drivers/staging/batman-adv/sysfs-class-net-batman-adv @@ -0,0 +1,14 @@ + +What: /sys/class/net//batman-adv/mesh_iface +Date: May 2010 +Contact: Marek Lindner +Description: + The /sys/class/net//batman-adv/mesh_iface file + displays the batman mesh interface this + currently is associated with. + +What: /sys/class/net//batman-adv/iface_status +Date: May 2010 +Contact: Marek Lindner +Description: + Indicates the status of as it is seen by batman. diff --git a/drivers/staging/batman-adv/sysfs-class-net-mesh b/drivers/staging/batman-adv/sysfs-class-net-mesh new file mode 100644 index 000000000000..c75a87b270e9 --- /dev/null +++ b/drivers/staging/batman-adv/sysfs-class-net-mesh @@ -0,0 +1,25 @@ + +What: /sys/class/net//mesh/aggregated_ogms +Date: May 2010 +Contact: Marek Lindner +Description: + Indicates whether the batman protocol messages of the + mesh shall be aggregated or not. + +What: /sys/class/net//mesh/orig_interval +Date: May 2010 +Contact: Marek Lindner +Description: + Defines the interval in milliseconds in which batman + sends its protocol messages. + +What: /sys/class/net//mesh/vis_mode +Date: May 2010 +Contact: Marek Lindner +Description: + Each batman node only maintains information about its + own local neighborhood, therefore generating graphs + showing the topology of the entire mesh is not easily + feasible without having a central instance to collect + the local topologies from all nodes. This file allows + to activate the collecting (server) mode. -- cgit v1.2.3 From e6dc269b402d9fa1562276345931943683e16ebd Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sun, 6 Jun 2010 21:28:20 +0200 Subject: Staging: batman-adv: convert vis_interval into define vis_interval does not neccesarily needs to be a variable, as there is no way to change it anyway (and probably no need to). We can therefore remove yet another global variable. Thanks Marek for pointing this out. Signed-off-by: Simon Wunderlich [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/main.c | 3 --- drivers/staging/batman-adv/main.h | 3 ++- drivers/staging/batman-adv/vis.c | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 74c70d589a93..14ab4a0a8805 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -41,7 +41,6 @@ DEFINE_SPINLOCK(orig_hash_lock); DEFINE_SPINLOCK(forw_bat_list_lock); DEFINE_SPINLOCK(forw_bcast_list_lock); -atomic_t vis_interval; atomic_t bcast_queue_left; atomic_t batman_queue_left; @@ -80,8 +79,6 @@ int init_module(void) atomic_set(&module_state, MODULE_INACTIVE); - atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only - * for debugging now. */ atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN); atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN); diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 5f8343d360f6..8b9e297b9d2b 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -57,6 +57,8 @@ #define LOG_BUF_LEN 8192 /* has to be a power of 2 */ #define ETH_STR_LEN 20 +#define VIS_INTERVAL 5000 /* 5 seconds */ + #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or * change the size of * forw_packet->direct_link_flags */ @@ -134,7 +136,6 @@ extern spinlock_t orig_hash_lock; extern spinlock_t forw_bat_list_lock; extern spinlock_t forw_bcast_list_lock; -extern atomic_t vis_interval; extern atomic_t bcast_queue_left; extern atomic_t batman_queue_left; extern int16_t num_hna; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 1d3d954847fd..d4fe87ecfbb2 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -701,7 +701,7 @@ int vis_init(void) } /* prefill the vis info */ - my_vis_info->first_seen = jiffies - atomic_read(&vis_interval); + my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL); INIT_LIST_HEAD(&my_vis_info->recv_list); INIT_LIST_HEAD(&my_vis_info->send_list); kref_init(&my_vis_info->refcount); @@ -764,5 +764,5 @@ void vis_quit(void) static void start_vis_timer(void) { queue_delayed_work(bat_event_workqueue, &vis_timer_wq, - (atomic_read(&vis_interval) * HZ) / 1000); + (VIS_INTERVAL * HZ) / 1000); } -- cgit v1.2.3 From 65b2742ac002f554f6ca0c2eab84cc62400eafdf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:26:51 +0200 Subject: firewire: 'add CSR_... support' addendum Add a comment on which of the conflicting NODE_IDS specifications we implement. Reduce a comment on rather irrelevant register bits that can all be looked up in the spec (or from now on in the code history). Directly include the required indirectly included bug.h. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 27 ++++++--------------------- drivers/firewire/ohci.c | 1 + 2 files changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 85a54da243e2..5069cfc75b50 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -984,29 +984,10 @@ static const struct fw_address_region registers_region = static u32 read_state_register(struct fw_card *card) { - /* - * Fixed bits (IEEE 1394-2008 8.3.2.2.1): - * Bits 0-1 (state) always read 00=running. - * Bits 2,3 (off, atn) are not implemented as per the spec. - * Bit 4 (elog) is not implemented because there is no error log. - * Bit 6 (dreq) cannot be set. It is intended to "disable requests - * from unreliable nodes"; however, IEEE 1212 states that devices - * may "clear their own dreq bit when it has been improperly set". - * Our implementation might be seen as an improperly extensive - * interpretation of "improperly", but the 1212-2001 revision - * dropped this bit altogether, so we're in the clear. :o) - * Bit 7 (lost) always reads 0 because a power reset has never occurred - * during normal operation. - * Bit 9 (linkoff) is not implemented because the PC is not powered - * from the FireWire cable. - * Bit 15 (gone) always reads 0. It must be set at a power/command/bus - * reset, but then cleared when the units are ready again, which - * happens immediately for us. - */ - u32 value = 0x0000; + u32 value; /* Bit 8 (cmstr): */ - value |= card->driver->read_csr_reg(card, CSR_STATE_CLEAR); + value = card->driver->read_csr_reg(card, CSR_STATE_CLEAR); /* Bit 10 (abdicate): */ if (card->csr_abdicate) @@ -1066,6 +1047,10 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, break; case CSR_NODE_IDS: + /* + * per IEEE 1394-2008 8.3.22.3, not IEEE 1394.1-2004 3.2.8 + * and 9.6, but interoperable with IEEE 1394.1-2004 bridges + */ if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->driver-> read_csr_reg(card, CSR_NODE_IDS)); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 51a55808d88a..2abdb3268a10 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -18,6 +18,7 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #include -- cgit v1.2.3 From e847cc832bab50aad939a0c30414cd986637564d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:29:07 +0200 Subject: firewire: drop sizeof expressions from some request size arguments In case of fw_card_bm_work()'s lock request, the present sizeof expression is going to be wrong if somebody changes the fw_card's DMA scratch buffer's size in the future. In case of quadlet write requests, sizeof(u32) is just silly; it's 4. In case of SBP-2 ORB pointer write requests, 8 is arguably quicker to understand as the correct and only possible value than sizeof(some_datum). Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 5 ++--- drivers/firewire/sbp2.c | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index ef6f2616cac7..156b098b0ada 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -296,8 +296,7 @@ static void fw_card_bm_work(struct work_struct *work) rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - card->bm_transaction_data, - sizeof(card->bm_transaction_data)); + card->bm_transaction_data, 8); if (rcode == RCODE_GENERATION) /* Another bus reset, BM work has been rescheduled. */ @@ -422,7 +421,7 @@ static void fw_card_bm_work(struct work_struct *work) rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, root_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_STATE_SET, - card->bm_transaction_data, sizeof(u32)); + card->bm_transaction_data, 4); if (rcode == RCODE_GENERATION) goto out; } diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 7e33b0b1704c..ae715c82da2e 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -508,8 +508,7 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, node_id, generation, device->max_speed, offset, - &orb->pointer, sizeof(orb->pointer), - complete_transaction, orb); + &orb->pointer, 8, complete_transaction, orb); } static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) @@ -654,7 +653,7 @@ static void sbp2_agent_reset(struct sbp2_logical_unit *lu) fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, lu->tgt->node_id, lu->generation, device->max_speed, lu->command_block_agent_address + SBP2_AGENT_RESET, - &d, sizeof(d)); + &d, 4); } static void complete_agent_reset_write_no_wait(struct fw_card *card, @@ -676,7 +675,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, lu->tgt->node_id, lu->generation, device->max_speed, lu->command_block_agent_address + SBP2_AGENT_RESET, - &d, sizeof(d), complete_agent_reset_write_no_wait, t); + &d, 4, complete_agent_reset_write_no_wait, t); } static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) @@ -866,8 +865,7 @@ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, lu->tgt->node_id, lu->generation, device->max_speed, - CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, - &d, sizeof(d)); + CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &d, 4); } static void sbp2_reconnect(struct work_struct *work); -- cgit v1.2.3 From db3c9cc105ee844f6cd7a1beb9926fb8e9a093ae Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:30:21 +0200 Subject: firewire: replace get_features card driver hook by feature variables in the fw_card struct. The hook appeared to be an unnecessary abstraction in the card driver interface. Cleaner would be to pass those feature flags as arguments to fw_card_initialize() or fw_card_add(), but the FairnessControl register is in the SCLK domain and may therefore not be accessible while Link Power Status is off, i.e. before the card->driver->enable call from fw_card_add(). Signed-off-by: Stefan Richter --- drivers/firewire/core-topology.c | 3 +-- drivers/firewire/core-transaction.c | 3 +-- drivers/firewire/core.h | 5 ----- drivers/firewire/ohci.c | 14 ++------------ include/linux/firewire.h | 3 +++ 5 files changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 00a556f3a585..3b9667c37b67 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -543,8 +543,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, spin_lock_irqsave(&card->lock, flags); - card->broadcast_channel_allocated = (card->driver->get_features(card) & - FEATURE_CHANNEL_31_ALLOCATED) != 0; + card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated; card->node_id = node_id; /* * Update node_id before generation to prevent anybody from using diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 5069cfc75b50..62bf30560a3e 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1129,8 +1129,7 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, break; case CSR_PRIORITY_BUDGET: - if (!(card->driver->get_features(card) & - FEATURE_PRIORITY_BUDGET)) + if (!card->priority_budget_implemented) rcode = RCODE_ADDRESS_ERROR; else if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->driver-> diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 3f9e39b60bca..8dc76d8711a5 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -38,9 +38,6 @@ struct fw_packet; #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) #define BROADCAST_CHANNEL_VALID (1 << 30) -#define FEATURE_PRIORITY_BUDGET 0x01 -#define FEATURE_CHANNEL_31_ALLOCATED 0x02 - #define CSR_STATE_BIT_CMSTR (1 << 8) #define CSR_STATE_BIT_ABDICATE (1 << 10) @@ -84,8 +81,6 @@ struct fw_card_driver { u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); - unsigned int (*get_features)(struct fw_card *card); - struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, int type, int channel, size_t header_size); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 2abdb3268a10..09bba9315de9 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -172,7 +172,6 @@ struct fw_ohci { int request_generation; /* for timestamping incoming requests */ unsigned quirks; unsigned int pri_req_max; - unsigned int features; u32 bus_time; bool is_root; @@ -1753,15 +1752,14 @@ static int ohci_enable(struct fw_card *card, if (version >= OHCI_VERSION_1_1) { reg_write(ohci, OHCI1394_InitialChannelsAvailableHi, 0xfffffffe); - ohci->features |= FEATURE_CHANNEL_31_ALLOCATED; + card->broadcast_channel_auto_allocated = true; } /* Get implemented bits of the priority arbitration request counter. */ reg_write(ohci, OHCI1394_FairnessControl, 0x3f); ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; reg_write(ohci, OHCI1394_FairnessControl, 0); - if (ohci->pri_req_max != 0) - ohci->features |= FEATURE_PRIORITY_BUDGET; + card->priority_budget_implemented = ohci->pri_req_max != 0; ar_context_run(&ohci->ar_request_ctx); ar_context_run(&ohci->ar_response_ctx); @@ -2132,13 +2130,6 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) } } -static unsigned int ohci_get_features(struct fw_card *card) -{ - struct fw_ohci *ohci = fw_ohci(card); - - return ohci->features; -} - static void copy_iso_headers(struct iso_context *ctx, void *p) { int i = ctx->header_length; @@ -2578,7 +2569,6 @@ static const struct fw_card_driver ohci_driver = { .enable_phys_dma = ohci_enable_phys_dma, .read_csr_reg = ohci_read_csr_reg, .write_csr_reg = ohci_write_csr_reg, - .get_features = ohci_get_features, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 4d22643215ef..5acb5fc19180 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -122,6 +122,9 @@ struct fw_card { bool bm_abdicate; /* value of csr_abdicate before last bus reset */ bool csr_abdicate; /* visible in CSR STATE_CLEAR/SET registers */ + bool priority_budget_implemented; /* controller feature */ + bool broadcast_channel_auto_allocated; /* controller feature */ + bool broadcast_channel_allocated; u32 broadcast_channel; __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; -- cgit v1.2.3 From c8a94ded57e9cc2498d401b2f5c856213a3e19fb Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:34:50 +0200 Subject: firewire: normalize STATE_CLEAR/SET CSR access interface Push the maintenance of STATE_CLEAR/SET.abdicate down into the card driver. This way, the read/write_csr_reg driver method works uniformly across all CSR offsets. Signed-off-by: Stefan Richter --- drivers/firewire/core-topology.c | 5 ++--- drivers/firewire/core-transaction.c | 41 +++++++++++-------------------------- drivers/firewire/core.h | 2 +- drivers/firewire/ohci.c | 19 ++++++++++++----- include/linux/firewire.h | 3 +-- 5 files changed, 30 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 3b9667c37b67..56e908ba43f1 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -524,7 +524,7 @@ static void update_topology_map(struct fw_card *card, } void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, - int self_id_count, u32 *self_ids) + int self_id_count, u32 *self_ids, bool bm_abdicate) { struct fw_node *local_node; unsigned long flags; @@ -552,8 +552,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, smp_wmb(); card->generation = generation; card->reset_jiffies = jiffies; - card->bm_abdicate = card->csr_abdicate; - card->csr_abdicate = false; + card->bm_abdicate = bm_abdicate; fw_schedule_bm_work(card, 0); local_node = build_tree(card, self_ids, self_id_count); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 62bf30560a3e..87d69cddb231 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -982,20 +982,6 @@ static const struct fw_address_region registers_region = { .start = CSR_REGISTER_BASE, .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; -static u32 read_state_register(struct fw_card *card) -{ - u32 value; - - /* Bit 8 (cmstr): */ - value = card->driver->read_csr_reg(card, CSR_STATE_CLEAR); - - /* Bit 10 (abdicate): */ - if (card->csr_abdicate) - value |= CSR_STATE_BIT_ABDICATE; - - return value; -} - static void update_split_timeout(struct fw_card *card) { unsigned int cycles; @@ -1021,29 +1007,25 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, switch (reg) { case CSR_STATE_CLEAR: - if (tcode == TCODE_READ_QUADLET_REQUEST) { - *data = cpu_to_be32(read_state_register(card)); - } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_STATE_CLEAR)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) card->driver->write_csr_reg(card, CSR_STATE_CLEAR, be32_to_cpu(*data)); - if (*data & cpu_to_be32(CSR_STATE_BIT_ABDICATE)) - card->csr_abdicate = false; - } else { + else rcode = RCODE_TYPE_ERROR; - } break; case CSR_STATE_SET: - if (tcode == TCODE_READ_QUADLET_REQUEST) { - *data = cpu_to_be32(read_state_register(card)); - } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { + if (tcode == TCODE_READ_QUADLET_REQUEST) + *data = cpu_to_be32(card->driver-> + read_csr_reg(card, CSR_STATE_SET)); + else if (tcode == TCODE_WRITE_QUADLET_REQUEST) card->driver->write_csr_reg(card, CSR_STATE_SET, be32_to_cpu(*data)); - if (*data & cpu_to_be32(CSR_STATE_BIT_ABDICATE)) - card->csr_abdicate = true; - } else { + else rcode = RCODE_TYPE_ERROR; - } break; case CSR_NODE_IDS: @@ -1063,7 +1045,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, case CSR_RESET_START: if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->csr_abdicate = false; + card->driver->write_csr_reg(card, CSR_STATE_CLEAR, + CSR_STATE_BIT_ABDICATE); else rcode = RCODE_TYPE_ERROR; break; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 8dc76d8711a5..8280c625170b 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -196,7 +196,7 @@ static inline void fw_node_put(struct fw_node *node) } void fw_core_handle_bus_reset(struct fw_card *card, int node_id, - int generation, int self_id_count, u32 *self_ids); + int generation, int self_id_count, u32 *self_ids, bool bm_abdicate); void fw_destroy_nodes(struct fw_card *card); /* diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 09bba9315de9..a55cf0911b72 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -174,6 +174,7 @@ struct fw_ohci { unsigned int pri_req_max; u32 bus_time; bool is_root; + bool csr_state_setclear_abdicate; /* * Spinlock for accessing fw_ohci data. Never call out of @@ -1529,7 +1530,9 @@ static void bus_reset_tasklet(unsigned long data) self_id_count, ohci->self_id_buffer); fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, - self_id_count, ohci->self_id_buffer); + self_id_count, ohci->self_id_buffer, + ohci->csr_state_setclear_abdicate); + ohci->csr_state_setclear_abdicate = false; } static irqreturn_t irq_handler(int irq, void *data) @@ -2032,13 +2035,16 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) switch (csr_offset) { case CSR_STATE_CLEAR: case CSR_STATE_SET: - /* the controller driver handles only the cmstr bit */ if (ohci->is_root && (reg_read(ohci, OHCI1394_LinkControlSet) & OHCI1394_LinkControl_cycleMaster)) - return CSR_STATE_BIT_CMSTR; + value = CSR_STATE_BIT_CMSTR; else - return 0; + value = 0; + if (ohci->csr_state_setclear_abdicate) + value |= CSR_STATE_BIT_ABDICATE; + + return value; case CSR_NODE_IDS: return reg_read(ohci, OHCI1394_NodeID) << 16; @@ -2078,12 +2084,13 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) switch (csr_offset) { case CSR_STATE_CLEAR: - /* the controller driver handles only the cmstr bit */ if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) { reg_write(ohci, OHCI1394_LinkControlClear, OHCI1394_LinkControl_cycleMaster); flush_writes(ohci); } + if (value & CSR_STATE_BIT_ABDICATE) + ohci->csr_state_setclear_abdicate = false; break; case CSR_STATE_SET: @@ -2092,6 +2099,8 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) OHCI1394_LinkControl_cycleMaster); flush_writes(ohci); } + if (value & CSR_STATE_BIT_ABDICATE) + ohci->csr_state_setclear_abdicate = true; break; case CSR_NODE_IDS: diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 5acb5fc19180..5553018d45d6 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -119,8 +119,7 @@ struct fw_card { int bm_retries; int bm_generation; __be32 bm_transaction_data[2]; - bool bm_abdicate; /* value of csr_abdicate before last bus reset */ - bool csr_abdicate; /* visible in CSR STATE_CLEAR/SET registers */ + bool bm_abdicate; bool priority_budget_implemented; /* controller feature */ bool broadcast_channel_auto_allocated; /* controller feature */ -- cgit v1.2.3 From b384cf18873da1ed100662aa7373edf5883a1c24 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:35:21 +0200 Subject: firewire: core: combine some repeated code All of these CSRs have the same read/ write/ aynthing-else handling, except for CSR_PRIORITY_BUDGET which might not be implemented. The CSR_CYCLE_TIME read handler implementation accepted 4-byte-sized block write requests before this change but this is just silly; the register is only required to support quadlet read and write requests like the other r/w CSR core and Serial-Bus-dependent registers. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 84 +++++++------------------------------ 1 file changed, 15 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 87d69cddb231..b8f6db6a0494 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1006,38 +1006,30 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, unsigned long flags; switch (reg) { - case CSR_STATE_CLEAR: - if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_STATE_CLEAR)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_STATE_CLEAR, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; - - case CSR_STATE_SET: - if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_STATE_SET)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_STATE_SET, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; + case CSR_PRIORITY_BUDGET: + if (!card->priority_budget_implemented) { + rcode = RCODE_ADDRESS_ERROR; + break; + } + /* else fall through */ case CSR_NODE_IDS: /* * per IEEE 1394-2008 8.3.22.3, not IEEE 1394.1-2004 3.2.8 * and 9.6, but interoperable with IEEE 1394.1-2004 bridges */ + /* fall through */ + + case CSR_STATE_CLEAR: + case CSR_STATE_SET: + case CSR_CYCLE_TIME: + case CSR_BUS_TIME: + case CSR_BUSY_TIMEOUT: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_NODE_IDS)); + read_csr_reg(card, reg)); else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_NODE_IDS, + card->driver->write_csr_reg(card, reg, be32_to_cpu(*data)); else rcode = RCODE_TYPE_ERROR; @@ -1078,52 +1070,6 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, } break; - case CSR_CYCLE_TIME: - if (TCODE_IS_READ_REQUEST(tcode) && length == 4) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_CYCLE_TIME)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_CYCLE_TIME, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; - - case CSR_BUS_TIME: - if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_BUS_TIME)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_BUS_TIME, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; - - case CSR_BUSY_TIMEOUT: - if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_BUSY_TIMEOUT)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_BUSY_TIMEOUT, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; - - case CSR_PRIORITY_BUDGET: - if (!card->priority_budget_implemented) - rcode = RCODE_ADDRESS_ERROR; - else if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, CSR_PRIORITY_BUDGET)); - else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_PRIORITY_BUDGET, - be32_to_cpu(*data)); - else - rcode = RCODE_TYPE_ERROR; - break; - case CSR_MAINT_UTILITY: if (tcode == TCODE_READ_QUADLET_REQUEST) *data = card->maint_utility_register; -- cgit v1.2.3 From 0fcff4e39323f466a47684d7c8ffa77e1be86c8a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:35:52 +0200 Subject: firewire: rename CSR access driver methods Rather than "read a Control and Status Registers (CSR) Architecture register" I prefer to say "read a Control and Status Register". Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 2 +- drivers/firewire/core-transaction.c | 10 ++++------ drivers/firewire/core.h | 4 ++-- drivers/firewire/ohci.c | 8 ++++---- 4 files changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2e62516a4b15..32a33da64991 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1044,7 +1044,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) local_irq_disable(); - cycle_time = card->driver->read_csr_reg(card, CSR_CYCLE_TIME); + cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME); switch (a->clk_id) { case CLOCK_REALTIME: getnstimeofday(&ts); break; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index b8f6db6a0494..182da69eae44 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1026,19 +1026,17 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, case CSR_BUS_TIME: case CSR_BUSY_TIMEOUT: if (tcode == TCODE_READ_QUADLET_REQUEST) - *data = cpu_to_be32(card->driver-> - read_csr_reg(card, reg)); + *data = cpu_to_be32(card->driver->read_csr(card, reg)); else if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, reg, - be32_to_cpu(*data)); + card->driver->write_csr(card, reg, be32_to_cpu(*data)); else rcode = RCODE_TYPE_ERROR; break; case CSR_RESET_START: if (tcode == TCODE_WRITE_QUADLET_REQUEST) - card->driver->write_csr_reg(card, CSR_STATE_CLEAR, - CSR_STATE_BIT_ABDICATE); + card->driver->write_csr(card, CSR_STATE_CLEAR, + CSR_STATE_BIT_ABDICATE); else rcode = RCODE_TYPE_ERROR; break; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 8280c625170b..3000dd74acfd 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -78,8 +78,8 @@ struct fw_card_driver { int (*enable_phys_dma)(struct fw_card *card, int node_id, int generation); - u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); - void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); + u32 (*read_csr)(struct fw_card *card, int csr_offset); + void (*write_csr)(struct fw_card *card, int csr_offset, u32 value); struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index a55cf0911b72..a4bbf3dadf58 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2026,7 +2026,7 @@ static int ohci_enable_phys_dma(struct fw_card *card, #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } -static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) +static u32 ohci_read_csr(struct fw_card *card, int csr_offset) { struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; @@ -2077,7 +2077,7 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) } } -static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) +static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value) { struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; @@ -2576,8 +2576,8 @@ static const struct fw_card_driver ohci_driver = { .send_response = ohci_send_response, .cancel_packet = ohci_cancel_packet, .enable_phys_dma = ohci_enable_phys_dma, - .read_csr_reg = ohci_read_csr_reg, - .write_csr_reg = ohci_write_csr_reg, + .read_csr = ohci_read_csr, + .write_csr = ohci_write_csr, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, -- cgit v1.2.3 From 5030c807907ae90ad21e9220c1a9d592558deba2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 15 Jun 2010 02:00:11 +0200 Subject: ieee1394: remove unused variables which caused gcc 4.6 to warn about variable 'XYZ' set but not used. sbp2.c, unit_characteristics: The underlying problem which was spotted here --- an incomplete implementation --- is already 50% fixed in drivers/firewire/sbp2.c which observes mgt_ORB_timeout but not yet ORB_size. raw1394.c, length_conflict; dv1394.c, ts_off: Impossible to tell why these variables are there. We can safely remove them though because we don't need a compiler warning to realize that we are dealing with (at least stylistically) flawed code here. dv1394.c, packet_time: This was used in debug macro that is only compiled in with DV1394_DEBUG_LEVEL >= 2 defined at compile-time. Just drop it since nobody debugs dv1394 anymore. Avoids noise in regular kernel builds. dv1394.c, ohci; eth1394.c, priv: These variables clearly can go away. Somebody wanted to use them but then didn't (or not anymore). Note, all of this code is considered to be at its end of life and is thus not really meant to receive janitorial updates anymore. But if we can easily remove noisy warnings from kernel builds, we should. Reported-by: Justin P. Mattock Signed-off-by: Stefan Richter --- drivers/ieee1394/dv1394.c | 14 ++------------ drivers/ieee1394/eth1394.c | 3 --- drivers/ieee1394/raw1394.c | 3 +-- drivers/ieee1394/sbp2.c | 11 ++++------- 4 files changed, 7 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index adaefabc40e9..f8fcbd048447 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -610,7 +610,7 @@ static void frame_prepare(struct video_card *video, unsigned int this_frame) } else { u32 transmit_sec, transmit_cyc; - u32 ts_cyc, ts_off; + u32 ts_cyc; /* DMA is stopped, so this is the very first frame */ video->active_frame = this_frame; @@ -636,7 +636,6 @@ static void frame_prepare(struct video_card *video, unsigned int this_frame) transmit_sec += transmit_cyc/8000; transmit_cyc %= 8000; - ts_off = ct_off; ts_cyc = transmit_cyc + 3; ts_cyc %= 8000; @@ -2004,7 +2003,7 @@ static void ir_tasklet_func(unsigned long data) int sof=0; /* start-of-frame flag */ struct frame *f; - u16 packet_length, packet_time; + u16 packet_length; int i, dbc=0; struct DMA_descriptor_block *block = NULL; u16 xferstatus; @@ -2024,11 +2023,6 @@ static void ir_tasklet_func(unsigned long data) sizeof(struct packet)); packet_length = le16_to_cpu(p->data_length); - packet_time = le16_to_cpu(p->timestamp); - - irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, - packet_time, packet_length, - p->data[0], p->data[1]); /* get the descriptor based on packet_buffer cursor */ f = video->frames[video->current_packet / MAX_PACKETS]; @@ -2320,7 +2314,6 @@ static void dv1394_add_host(struct hpsb_host *host) static void dv1394_host_reset(struct hpsb_host *host) { - struct ti_ohci *ohci; struct video_card *video = NULL, *tmp_vid; unsigned long flags; @@ -2328,9 +2321,6 @@ static void dv1394_host_reset(struct hpsb_host *host) if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) return; - ohci = (struct ti_ohci *)host->hostdata; - - /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); list_for_each_entry(tmp_vid, &dv1394_cards, list) { diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index a4e9dcb6d4a9..bc289e367e30 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -1258,7 +1258,6 @@ static void ether1394_iso(struct hpsb_iso *iso) char *buf; struct eth1394_host_info *hi; struct net_device *dev; - struct eth1394_priv *priv; unsigned int len; u32 specifier_id; u16 source_id; @@ -1288,8 +1287,6 @@ static void ether1394_iso(struct hpsb_iso *iso) (be32_to_cpu(data[1]) & 0xff000000) >> 24; source_id = be32_to_cpu(data[0]) >> 16; - priv = netdev_priv(dev); - if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) || specifier_id != ETHER1394_GASP_SPECIFIER_ID) { /* This packet is not for us */ diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index b563d5e9fa2e..2c417ae7622b 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -1015,7 +1015,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, struct arm_addr *arm_addr = NULL; struct arm_request *arm_req = NULL; struct arm_response *arm_resp = NULL; - int found = 0, size = 0, rcode = -1, length_conflict = 0; + int found = 0, size = 0, rcode = -1; struct arm_request_response *arm_req_resp = NULL; DBGMSG("arm_write called by node: %X " @@ -1054,7 +1054,6 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, } if (arm_addr->rec_length < length) { DBGMSG("arm_write blocklength too big -> rcode_data_error"); - length_conflict = 1; rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ } if (rcode == -1) { diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f199896c4113..d3a136c70c48 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1351,12 +1351,11 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu, struct csr1212_keyval *kv; struct csr1212_dentry *dentry; u64 management_agent_addr; - u32 unit_characteristics, firmware_revision, model; + u32 firmware_revision, model; unsigned workarounds; int i; management_agent_addr = 0; - unit_characteristics = 0; firmware_revision = SBP2_ROM_VALUE_MISSING; model = ud->flags & UNIT_DIRECTORY_MODEL_ID ? ud->model_id : SBP2_ROM_VALUE_MISSING; @@ -1373,17 +1372,15 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu, lu->lun = ORB_SET_LUN(kv->value.immediate); break; - case SBP2_UNIT_CHARACTERISTICS_KEY: - /* FIXME: This is ignored so far. - * See SBP-2 clause 7.4.8. */ - unit_characteristics = kv->value.immediate; - break; case SBP2_FIRMWARE_REVISION_KEY: firmware_revision = kv->value.immediate; break; default: + /* FIXME: Check for SBP2_UNIT_CHARACTERISTICS_KEY + * mgt_ORB_timeout and ORB_size, SBP-2 clause 7.4.8. */ + /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY. * Its "ordered" bit has consequences for command ORB * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */ -- cgit v1.2.3 From ae86e81e434072be28ff4e9c1be3cc2562be8749 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 15 Jun 2010 01:22:45 +0200 Subject: firewire: core: remove unused variable which caused gcc 4.6 to warn about variable 'destination' set but not used. Since the hardware ensures that we receive only response packets with proper destination node ID (in a given bus generation), we have no use for destination here in the core as well as in upper layers. (This is different with request packets. There we pass destination node ID to upper layers because they may for example need to check whether this was an unicast or broadcast request.) Reported-and-Tested-By: Justin P. Mattock Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 182da69eae44..cb6390fe3686 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -881,13 +881,12 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) unsigned long flags; u32 *data; size_t data_length; - int tcode, tlabel, destination, source, rcode; + int tcode, tlabel, source, rcode; - tcode = HEADER_GET_TCODE(p->header[0]); - tlabel = HEADER_GET_TLABEL(p->header[0]); - destination = HEADER_GET_DESTINATION(p->header[0]); - source = HEADER_GET_SOURCE(p->header[1]); - rcode = HEADER_GET_RCODE(p->header[1]); + tcode = HEADER_GET_TCODE(p->header[0]); + tlabel = HEADER_GET_TLABEL(p->header[0]); + source = HEADER_GET_SOURCE(p->header[1]); + rcode = HEADER_GET_RCODE(p->header[1]); spin_lock_irqsave(&card->lock, flags); list_for_each_entry(t, &card->transaction_list, link) { -- cgit v1.2.3 From 56d04cb189f955e5167c27944d61aa57ad69b598 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 8 Jun 2010 00:20:10 +0200 Subject: firewire: core: remove an unnecessary zero initialization All of the fields of the iso_interrupt_event instance are overwritten right after it was allocated. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 32a33da64991..ca72cdaa68c9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -847,7 +847,7 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle, struct client *client = data; struct iso_interrupt_event *e; - e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC); + e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC); if (e == NULL) return; -- cgit v1.2.3 From 33e553fe2b4a983ef34a57ab1440d8d33397bb12 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:50:35 +0200 Subject: firewire: remove an unused function argument void (*fw_address_callback_t)(..., int speed, ...) is the speed that a remote node chose to transmit a request to us. In case of split transactions, firewire-core will transmit the response at that speed. Upper layer drivers on the other hand (firewire-net, -sbp2, firedtv, and userspace drivers) cannot do anything useful with that speed datum, except log it for debug purposes. But data that is merely potentially (not even actually) used for debug purposes does not belong into the API. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 3 +-- drivers/firewire/core-transaction.c | 14 +++++++------- drivers/firewire/net.c | 4 ++-- drivers/firewire/sbp2.c | 3 +-- drivers/media/dvb/firewire/firedtv-fw.c | 4 ++-- include/linux/firewire.h | 2 +- 6 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index ca72cdaa68c9..4e0478d70d4d 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -632,8 +632,7 @@ static void release_request(struct client *client, static void handle_request(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, + int generation, unsigned long long offset, void *payload, size_t length, void *callback_data) { struct address_handler_resource *handler = callback_data; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index cb6390fe3686..2f67c8d5ce91 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -802,7 +802,7 @@ static void handle_exclusive_region_request(struct fw_card *card, else handler->address_callback(card, request, tcode, destination, source, - p->generation, p->speed, offset, + p->generation, offset, request->data, request->length, handler->callback_data); } @@ -840,8 +840,8 @@ static void handle_fcp_region_request(struct fw_card *card, if (is_enclosing_handler(handler, offset, request->length)) handler->address_callback(card, NULL, tcode, destination, source, - p->generation, p->speed, - offset, request->data, + p->generation, offset, + request->data, request->length, handler->callback_data); } @@ -951,8 +951,8 @@ static const struct fw_address_region topology_map_region = static void handle_topology_map(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, - int speed, unsigned long long offset, - void *payload, size_t length, void *callback_data) + unsigned long long offset, void *payload, size_t length, + void *callback_data) { int start; @@ -996,8 +996,8 @@ static void update_split_timeout(struct fw_card *card) static void handle_registers(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, - int speed, unsigned long long offset, - void *payload, size_t length, void *callback_data) + unsigned long long offset, void *payload, size_t length, + void *callback_data) { int reg = offset & ~CSR_REGISTER_BASE; __be32 *data = payload; diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 2d3dc7ded0a9..4bb3fb882f63 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -805,8 +805,8 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, int tcode, int destination, int source, int generation, - int speed, unsigned long long offset, void *payload, - size_t length, void *callback_data) + unsigned long long offset, void *payload, size_t length, + void *callback_data) { struct fwnet_device *dev = callback_data; int rcode; diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index ae715c82da2e..1931964c4fbf 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -410,8 +410,7 @@ static void free_orb(struct kref *kref) static void sbp2_status_write(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, + int generation, unsigned long long offset, void *payload, size_t length, void *callback_data) { struct sbp2_logical_unit *lu = callback_data; diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 4253b7ab0097..4dcae63f8cff 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -194,8 +194,8 @@ static const struct firedtv_backend backend = { static void handle_fcp(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, - int speed, unsigned long long offset, - void *payload, size_t length, void *callback_data) + unsigned long long offset, void *payload, size_t length, + void *callback_data) { struct firedtv *f, *fdtv = NULL; struct fw_device *device; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 5553018d45d6..e44b502c8341 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -265,7 +265,7 @@ typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, typedef void (*fw_address_callback_t)(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, - int generation, int speed, + int generation, unsigned long long offset, void *data, size_t length, void *callback_data); -- cgit v1.2.3 From bdfe273ee54b29498851fc8058516037d284270c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 14 Jun 2010 11:46:25 +0200 Subject: firewire: cdev: fix race in iso context creation Protect the client's iso context pointer against a race that can happen when more than one creation call is executed at the same time. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 4e0478d70d4d..ce8cb6fcbbcd 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -864,10 +864,6 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) struct fw_cdev_create_iso_context *a = &arg->create_iso_context; struct fw_iso_context *context; - /* We only support one context at this time. */ - if (client->iso_context != NULL) - return -EBUSY; - if (a->channel > 63) return -EINVAL; @@ -892,10 +888,17 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) if (IS_ERR(context)) return PTR_ERR(context); + /* We only support one context at this time. */ + spin_lock_irq(&client->lock); + if (client->iso_context != NULL) { + spin_unlock_irq(&client->lock); + fw_iso_context_destroy(context); + return -EBUSY; + } client->iso_closure = a->closure; client->iso_context = context; + spin_unlock_irq(&client->lock); - /* We only support one context at this time. */ a->handle = 0; return 0; -- cgit v1.2.3 From 08bd34c98d631fe85744d4c920c80f48a1d95f54 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Tue, 18 May 2010 14:02:45 -0400 Subject: firewire: cdev: fix responses to nodes at different card My box has two firewire cards in it: card0 and card1. My application opens /dev/fw0 (card 0) and allocates an address space. The core makes the address space available on both cards. Along comes the remote device, which sends a READ_QUADLET_REQUEST to card1. The request gets passed up to my application, which calls ioctl_send_response(). ioctl_send_response() then calls fw_send_response() with card0, because that's the card it's bound to. Card0's driver drops the response, because it isn't part of a transaction that it has outstanding. So in core-cdev: handle_request(), we need to stash the card of the inbound request in the struct inbound_transaction_resource and use that card to send the response to. The hard part will be refcounting the card correctly so it can't get deallocated while we hold a pointer to it. Here's a trivial patch, which does not do the card refcounting, but at least demonstrates what the problem is. Note that we can't depend on the fact that the core-cdev:client structure holds a card open, because in this case the card it holds open is not the card the request came in on. ..and there's no way for the core to tell cdev "this card is gone, kill any inbound transactions on it", while cdev holds the transaction open until userspace issues a SEND_RESPONSE ioctl, which may be a very, very long time. But when it does, it calls fw_send_response(), which will dereference the card... So how unhappy are we about userspace potentially holding a fw_card open forever? Signed-off-by: Jay Fenlason Reference counting to be addressed in a separate change. Signed-off-by: Stefan Richter (whitespace) --- drivers/firewire/core-cdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index ce8cb6fcbbcd..8cbc2b8a8272 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -106,6 +106,7 @@ struct outbound_transaction_resource { struct inbound_transaction_resource { struct client_resource resource; + struct fw_card *card; struct fw_request *request; void *data; size_t length; @@ -625,8 +626,7 @@ static void release_request(struct client *client, if (is_fcp_request(r->request)) kfree(r->data); else - fw_send_response(client->device->card, r->request, - RCODE_CONFLICT_ERROR); + fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR); kfree(r); } @@ -646,6 +646,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, if (r == NULL || e == NULL) goto failed; + r->card = card; r->request = request; r->data = payload; r->length = length; @@ -765,7 +766,7 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg) kfree(r->request); goto out; } - fw_send_response(client->device->card, r->request, a->rcode); + fw_send_response(r->card, r->request, a->rcode); out: kfree(r); -- cgit v1.2.3 From 0244f57302f7e8bebd2f1ab58767eac2e9f678a6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:52:27 +0200 Subject: firewire: cdev: count references of cards during inbound transactions If a request comes in to an address range managed by a userspace driver i.e. client, the card instance of request and response may differ from the card instance of the client device. Therefore we need to take a reference of the card until the response was sent. I thought about putting the reference counting into core-transaction.c, but the various high-level drivers besides cdev clients (firewire-net, firewire-sbp2, firedtv) use the card pointer in their fw_address_handler address_callback method only to look up devices of which they already hold the necessary references. So this seems to be a specific firewire-cdev issue which is better addressed locally. We do not need the reference - in case of FCP_REQUEST or FCP_RESPONSE requests because then the firewire-core will send the split transaction response for us already in the context of the request handler, - if it is the same card as the client device's because we hold a card reference indirectly via teh client->device reference. To keep things simple, we take the reference nevertheless. Jay Fenlason wrote: > there's no way for the core to tell cdev "this card is gone, > kill any inbound transactions on it", while cdev holds the transaction > open until userspace issues a SEND_RESPONSE ioctl, which may be a very, > very long time. But when it does, it calls fw_send_response(), which > will dereference the card... > > So how unhappy are we about userspace potentially holding a fw_card > open forever? While termination of inbound transcations at card removal could be implemented, it is IMO not worth the effort. Currently, the effect of holding a reference of a card that has been removed is to block the process that called the pci_remove of the card. This is - either a user process ran by root. Root can find and kill processes that have /dev/fw* open, if desired. - a kernel thread (which one?) in case of hot removal of a PCCard or ExpressCard. The latter case could be a problem indeed. firewire-core's card shutdown and card release should probably be improved not to block in shutdown, just to defer freeing of memory until release. This is not a new problem though; the same already always happens with the client->device->card without the need of inbound transactions or other special conditions involved, other than the client not closing the file. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 8cbc2b8a8272..8f8c8eeaf046 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -627,6 +627,8 @@ static void release_request(struct client *client, kfree(r->data); else fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR); + + fw_card_put(r->card); kfree(r); } @@ -641,6 +643,9 @@ static void handle_request(struct fw_card *card, struct fw_request *request, void *fcp_frame = NULL; int ret; + /* card may be different from handler->client->device->card */ + fw_card_get(card); + r = kmalloc(sizeof(*r), GFP_ATOMIC); e = kmalloc(sizeof(*e), GFP_ATOMIC); if (r == NULL || e == NULL) @@ -686,6 +691,8 @@ static void handle_request(struct fw_card *card, struct fw_request *request, if (!is_fcp_request(request)) fw_send_response(card, request, RCODE_CONFLICT_ERROR); + + fw_card_put(card); } static void release_address_handler(struct client *client, @@ -768,6 +775,7 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg) } fw_send_response(r->card, r->request, a->rcode); out: + fw_card_put(r->card); kfree(r); return ret; -- cgit v1.2.3 From 604f45167824e18ad5766e51ecf1d4d65f15118d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:52:55 +0200 Subject: firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug libraw1394 v2.0.0...v2.0.5 takes FW_CDEV_VERSION from an externally installed header file and uses it to declare its own implementation level in FW_CDEV_IOC_GET_INFO. This is wrong; it should set the real version for which it was actually written. If we add features to the kernel ABI that require the kernel to check a client's implementation level, we can not trust the client version if it was set from FW_CDEV_VERSION. Hence freeze FW_CDEV_VERSION at the current value (no damage has been done yet), clearly document FW_CDEV_VERSION as a dummy version and what clients are expected to do with fw_cdev_get_info.version, and use a new defined constant (which is not placed into the exported header file) as kernel implementation level. Note, in order to check in client program source code which features are present in an externally installed linux/firewire-cdev.h, use preprocessor directives like #ifdef FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE or #ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED instead of a check of FW_CDEV_VERSION. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 7 ++++++- include/linux/firewire-cdev.h | 22 ++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 8f8c8eeaf046..0cf86bcbeea2 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -46,6 +46,11 @@ #include "core.h" +/* + * ABI version history is documented in linux/firewire-cdev.h. + */ +#define FW_CDEV_KERNEL_VERSION 3 + struct client { u32 version; struct fw_device *device; @@ -395,7 +400,7 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) unsigned long ret = 0; client->version = a->version; - a->version = FW_CDEV_VERSION; + a->version = FW_CDEV_KERNEL_VERSION; a->card = client->device->card->index; down_read(&fw_device_rwsem); diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 6ffb24a1f2f2..0d0cc07358af 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -219,7 +219,7 @@ union fw_cdev_event { struct fw_cdev_event_response response; struct fw_cdev_event_request request; struct fw_cdev_event_iso_interrupt iso_interrupt; - struct fw_cdev_event_iso_resource iso_resource; + struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ }; /* available since kernel version 2.6.22 */ @@ -252,22 +252,32 @@ union fw_cdev_event { #define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2) /* - * FW_CDEV_VERSION History + * ABI version history * 1 (2.6.22) - initial version + * (2.6.24) - added %FW_CDEV_IOC_GET_CYCLE_TIMER * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if * &fw_cdev_create_iso_context.header_size is 8 or more + * - added %FW_CDEV_IOC_*_ISO_RESOURCE*, + * %FW_CDEV_IOC_GET_SPEED, %FW_CDEV_IOC_SEND_BROADCAST_REQUEST, + * %FW_CDEV_IOC_SEND_STREAM_PACKET * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt * (2.6.33) - IR has always packet-per-buffer semantics now, not one of * dual-buffer or packet-per-buffer depending on hardware * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable + * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 */ -#define FW_CDEV_VERSION 3 +#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ /** * struct fw_cdev_get_info - General purpose information ioctl - * @version: The version field is just a running serial number. - * We never break backwards compatibility, but may add more - * structs and ioctls in later revisions. + * @version: The version field is just a running serial number. Both an + * input parameter (ABI version implemented by the client) and + * output parameter (ABI version implemented by the kernel). + * A client must not fill in an %FW_CDEV_VERSION defined from an + * included kernel header file but the actual version for which + * the client was implemented. This is necessary for forward + * compatibility. We never break backwards compatibility, but + * may add more structs, events, and ioctls in later revisions. * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration * ROM will be copied into that user space address. In either * case, @rom_length is updated with the actual length of the -- cgit v1.2.3 From c82f91f2663e79b150afd896ec72e798ba4e243d Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Tue, 18 May 2010 10:57:33 -0400 Subject: firewire: expose extended tcode of incoming lock requests to (userspace) drivers When a remote device does a LOCK_REQUEST, the core does not pass the extended tcode to userspace. This patch makes it use the juju-specific tcodes listed in firewire-constants.h for incoming requests. Signed-off-by: Jay Fenlason This matches how tcode in the API for outbound requests is treated. Affects kernelspace and userspace drivers alike, but at the moment there are no kernespace drivers that receive lock requests. Split out from a combo patch, slightly reordered, changelog reworded. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 2f67c8d5ce91..fcb455c08200 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -780,9 +780,11 @@ static void handle_exclusive_region_request(struct fw_card *card, unsigned long flags; int tcode, destination, source; - tcode = HEADER_GET_TCODE(p->header[0]); destination = HEADER_GET_DESTINATION(p->header[0]); source = HEADER_GET_SOURCE(p->header[1]); + tcode = HEADER_GET_TCODE(p->header[0]); + if (tcode == TCODE_LOCK_REQUEST) + tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]); spin_lock_irqsave(&address_handler_lock, flags); handler = lookup_enclosing_address_handler(&address_handler_list, -- cgit v1.2.3 From e205597d188a9ea69ce43f740a14f07b3f5b996a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:53:55 +0200 Subject: firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2 The problem: A target-like userspace driver, e.g. AV/C target or SBP-2/3 target, needs to be able to act as responder and requester. In the latter role, it needs to send requests to nods from which it received requests. This is currently impossible because fw_cdev_event_request lacks information about sender node ID. Reported-by: Jay Fenlason Libffado + libraw1394 + firewire-core is currently unable to drive two or more audio devices on the same bus. Reported-by: Arnold Krille This is because libffado requires destination node ID of FCP requests and sender node ID of FCP responses to match. It even prohibits libffado from working with a bus on which libraw1394 opens a /dev/fw* as default ioctl device that does not correspond with the audio device. This is because libraw1394 does not receive the sender node ID from the kernel. Moreover, fw_cdev_event_request makes it impossible to tell unicast and broadcast write requests apart. The fix: Add a replacement of struct fw_cdev_event_request request, boringly called struct fw_cdev_event_request2. The new event will be sent to a userspace client instead of the old one if the client claims compatibility with ABI version 4 or later. libraw1394 needs to be extended to make use of the new event, in order to properly support libffado and other FCP or address range mapping users who require correct sender node IDs. Further notes: While we are at it, change back the range of possible values of fw_cdev_event_request.tcode to 0x0...0xb like in ABI version <= 3. The preceding change "firewire: expose extended tcode of incoming lock requests to (userspace) drivers" expanded it to 0x0...0x17 which could catch sloppily coded clients by surprise. The extended range of codes is only used in the new fw_cdev_event_request2.tcode. Jay and I also suggested an alternative approach to fix the ABI for incoming requests: Add an FW_CDEV_IOC_GET_REQUEST_INFO ioctl which can be called after reception of an fw_cdev_event_request, before issuing of the closing FW_CDEV_IOC_SEND_RESPONSE ioctl. The new ioctl would reveal the vital information about a request that fw_cdev_event_request lacks. Jay showed an implementation of this approach. The former event approach adds 27 LOC of rather trivial code to core-cdev.c, the ioctl approach 34 LOC, some of which is nontrivial. The ioctl approach would certainly also add more LOC to userspace programs which require the expanded information on inbound requests. This approach is probably only on the lighter-weight side in case of clients that want to be compatible with kernels that lack the new capability, like libraw1394. However, the code to be added to such libraw1394-like clients in case of the event approach is a straight- forward additional switch () case in its event handler. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 45 ++++++++++++++++++++----- include/linux/firewire-cdev.h | 76 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 0cf86bcbeea2..9b8df2039155 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -49,7 +49,8 @@ /* * ABI version history is documented in linux/firewire-cdev.h. */ -#define FW_CDEV_KERNEL_VERSION 3 +#define FW_CDEV_KERNEL_VERSION 4 +#define FW_CDEV_VERSION_EVENT_REQUEST2 4 struct client { u32 version; @@ -176,7 +177,10 @@ struct outbound_transaction_event { struct inbound_transaction_event { struct event event; - struct fw_cdev_event_request request; + union { + struct fw_cdev_event_request request; + struct fw_cdev_event_request2 request2; + } req; }; struct iso_interrupt_event { @@ -645,6 +649,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, struct address_handler_resource *handler = callback_data; struct inbound_transaction_resource *r; struct inbound_transaction_event *e; + size_t event_size0; void *fcp_frame = NULL; int ret; @@ -678,15 +683,37 @@ static void handle_request(struct fw_card *card, struct fw_request *request, if (ret < 0) goto failed; - e->request.type = FW_CDEV_EVENT_REQUEST; - e->request.tcode = tcode; - e->request.offset = offset; - e->request.length = length; - e->request.handle = r->resource.handle; - e->request.closure = handler->closure; + if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) { + struct fw_cdev_event_request *req = &e->req.request; + + if (tcode & 0x10) + tcode = TCODE_LOCK_REQUEST; + + req->type = FW_CDEV_EVENT_REQUEST; + req->tcode = tcode; + req->offset = offset; + req->length = length; + req->handle = r->resource.handle; + req->closure = handler->closure; + event_size0 = sizeof(*req); + } else { + struct fw_cdev_event_request2 *req = &e->req.request2; + + req->type = FW_CDEV_EVENT_REQUEST2; + req->tcode = tcode; + req->offset = offset; + req->source_node_id = source; + req->destination_node_id = destination; + req->card = card->index; + req->generation = generation; + req->length = length; + req->handle = r->resource.handle; + req->closure = handler->closure; + event_size0 = sizeof(*req); + } queue_event(handler->client, &e->event, - &e->request, sizeof(e->request), r->data, length); + &e->req, event_size0, r->data, length); return; failed: diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 0d0cc07358af..52c7ffe934ad 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -32,6 +32,9 @@ #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 +/* available since kernel version 2.6.36 */ +#define FW_CDEV_EVENT_REQUEST2 0x06 + /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types * @closure: For arbitrary use by userspace @@ -98,11 +101,46 @@ struct fw_cdev_event_response { }; /** - * struct fw_cdev_event_request - Sent on incoming request to an address region + * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST + * @tcode: See &fw_cdev_event_request2 + * @offset: See &fw_cdev_event_request2 + * @handle: See &fw_cdev_event_request2 + * @length: See &fw_cdev_event_request2 + * @data: See &fw_cdev_event_request2 + * + * This event is sent instead of &fw_cdev_event_request2 if the kernel or + * the client implements ABI version <= 3. + * + * Unlike &fw_cdev_event_request2, the sender identity cannot be established, + * broadcast write requests cannot be distinguished from unicast writes, and + * @tcode of lock requests is %TCODE_LOCK_REQUEST. + * + * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as + * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send + * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl. + */ +struct fw_cdev_event_request { + __u64 closure; + __u32 type; + __u32 tcode; + __u64 offset; + __u32 handle; + __u32 length; + __u32 data[0]; +}; + +/** + * struct fw_cdev_event_request2 - Sent on incoming request to an address region + * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl + * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2 * @tcode: Transaction code of the incoming request * @offset: The offset into the 48-bit per-node address space + * @source_node_id: Sender node ID + * @destination_node_id: Destination node ID + * @card: The index of the card from which the request came + * @generation: Bus generation in which the request is valid * @handle: Reference to the kernel-side pending request * @length: Data length, i.e. the request's payload size in bytes * @data: Incoming data, if any @@ -115,12 +153,42 @@ struct fw_cdev_event_response { * * The payload data for requests carrying data (write and lock requests) * follows immediately and can be accessed through the @data field. + * + * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the + * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT, + * i.e. encodes the extended transaction code. + * + * @card may differ from &fw_cdev_get_info.card because requests are received + * from all cards of the Linux host. @source_node_id, @destination_node_id, and + * @generation pertain to that card. Destination node ID and bus generation may + * therefore differ from the corresponding fields of the last + * &fw_cdev_event_bus_reset. + * + * @destination_node_id may also differ from the current node ID because of a + * non-local bus ID part or in case of a broadcast write request. Note, a + * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a + * broadcast write request; the kernel will then release the kernel-side pending + * request but will not actually send a response packet. + * + * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already + * sent a write response immediately after the request was received; in this + * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to + * release the kernel-side pending request, though another response won't be + * sent. + * + * If the client subsequently needs to initiate requests to the sender node of + * an &fw_cdev_event_request2, it needs to use a device file with matching + * card index, node ID, and generation for outbound requests. */ -struct fw_cdev_event_request { +struct fw_cdev_event_request2 { __u64 closure; __u32 type; __u32 tcode; __u64 offset; + __u32 source_node_id; + __u32 destination_node_id; + __u32 card; + __u32 generation; __u32 handle; __u32 length; __u32 data[0]; @@ -200,6 +268,7 @@ struct fw_cdev_event_iso_resource { * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST + * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2 * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT * @iso_resource: Valid if @common.type == * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or @@ -218,6 +287,7 @@ union fw_cdev_event { struct fw_cdev_event_bus_reset bus_reset; struct fw_cdev_event_response response; struct fw_cdev_event_request request; + struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ struct fw_cdev_event_iso_interrupt iso_interrupt; struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ }; @@ -263,8 +333,10 @@ union fw_cdev_event { * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt * (2.6.33) - IR has always packet-per-buffer semantics now, not one of * dual-buffer or packet-per-buffer depending on hardware + * - shared use and auto-response for FCP registers * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ -- cgit v1.2.3 From cf2d3fc9786ba005f9bde50a4e72a1d0b70472ff Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 6 Jun 2010 21:03:04 +0200 Subject: Staging: batman-adv: return -EFAULT on copy_to_user errors copy_to_user() returns the number of bites remaining but we want to return a negative error code here. Signed-off-by: Dan Carpenter Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 7eb6559e0315..32204b5572d0 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, kfree(device_packet); if (error) - return error; + return -EFAULT; return sizeof(struct icmp_packet); } -- cgit v1.2.3 From 1bd2c2159a32313ae1f872b6225601aed397524c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sun, 6 Jun 2010 21:03:05 +0200 Subject: Staging: batman-adv: fix function prototype In today linux-next I got a compile warning in staging/batman-adv. This is due a struct bin_attribute read function prototype change and the driver was not updated. This patch solves the issue Signed-off-by: Javier Martinez Canillas Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_sysfs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index 065a2123dbc6..ffb8ea2702a2 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -201,9 +201,9 @@ static struct bat_attribute *mesh_attrs[] = { NULL, }; -static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -211,9 +211,9 @@ static ssize_t transtable_local_read(struct kobject *kobj, return hna_local_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -221,9 +221,9 @@ static ssize_t transtable_global_read(struct kobject *kobj, return hna_global_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t originators_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -231,9 +231,9 @@ static ssize_t originators_read(struct kobject *kobj, return orig_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t vis_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); -- cgit v1.2.3 From c41214328a7635dc35aa81d89ea579c8a2eb2769 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Jun 2010 01:25:42 +0200 Subject: Staging: batman-adv: Move device for icmp injection to debugfs batctl uses /dev/batman-adv to send special batman-adv icmp packets to other nodes in the mesh. To get it working with multiple batX devices we must ensure that every mesh device can have their own socket which is used to inject those packets in exactly one mesh. The current implementation still doesn't allow to use complete separated meshes as we rely on structures which are not part of the private data of a batman device. Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/Makefile | 2 +- drivers/staging/batman-adv/bat_debugfs.c | 77 +++++++ drivers/staging/batman-adv/bat_debugfs.h | 33 +++ drivers/staging/batman-adv/device.c | 354 ------------------------------- drivers/staging/batman-adv/device.h | 36 ---- drivers/staging/batman-adv/icmp_socket.c | 328 ++++++++++++++++++++++++++++ drivers/staging/batman-adv/icmp_socket.h | 28 +++ drivers/staging/batman-adv/main.c | 21 +- drivers/staging/batman-adv/routing.c | 4 +- drivers/staging/batman-adv/types.h | 5 +- 10 files changed, 486 insertions(+), 402 deletions(-) create mode 100644 drivers/staging/batman-adv/bat_debugfs.c create mode 100644 drivers/staging/batman-adv/bat_debugfs.h delete mode 100644 drivers/staging/batman-adv/device.c delete mode 100644 drivers/staging/batman-adv/device.h create mode 100644 drivers/staging/batman-adv/icmp_socket.c create mode 100644 drivers/staging/batman-adv/icmp_socket.h (limited to 'drivers') diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile index f25068c0fae6..654c4d2b9726 100644 --- a/drivers/staging/batman-adv/Makefile +++ b/drivers/staging/batman-adv/Makefile @@ -19,4 +19,4 @@ # obj-m += batman-adv.o -batman-adv-objs := main.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_sysfs.o +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c new file mode 100644 index 000000000000..d5b28eb1c69c --- /dev/null +++ b/drivers/staging/batman-adv/bat_debugfs.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include + +#include "main.h" +#include "bat_debugfs.h" +#include "translation-table.h" +#include "originator.h" +#include "hard-interface.h" +#include "vis.h" +#include "icmp_socket.h" + +static struct dentry *bat_debugfs; + +void debugfs_init(void) +{ + bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); +} + +void debugfs_destroy(void) +{ + if (bat_debugfs) { + debugfs_remove_recursive(bat_debugfs); + bat_debugfs = NULL; + } +} + +int debugfs_add_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (!bat_debugfs) + goto out; + + bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs); + if (!bat_priv->debug_dir) + goto out; + + bat_socket_setup(bat_priv); + + return 0; +out: +#ifdef CONFIG_DEBUG_FS + return -ENOMEM; +#else + return 0; +#endif /* CONFIG_DEBUG_FS */ +} + +void debugfs_del_meshif(struct net_device *dev) +{ + struct bat_priv *bat_priv = netdev_priv(dev); + + if (bat_debugfs) { + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; + } +} diff --git a/drivers/staging/batman-adv/bat_debugfs.h b/drivers/staging/batman-adv/bat_debugfs.h new file mode 100644 index 000000000000..5cdd3327d98c --- /dev/null +++ b/drivers/staging/batman-adv/bat_debugfs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + + +#ifndef BAT_DEBUGFS_H +#define BAT_DEBUGFS_H + +#define DEBUGFS_BAT_SUBDIR "batman_adv" + +void debugfs_init(void); +void debugfs_destroy(void); +int debugfs_add_meshif(struct net_device *dev); +void debugfs_del_meshif(struct net_device *dev); + +#endif diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c deleted file mode 100644 index 32204b5572d0..000000000000 --- a/drivers/staging/batman-adv/device.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include -#include -#include "main.h" -#include "device.h" -#include "send.h" -#include "types.h" -#include "hash.h" -#include "hard-interface.h" - -static struct class *batman_class; - -static int Major; /* Major number assigned to our device driver */ - -static const struct file_operations fops = { - .open = bat_device_open, - .release = bat_device_release, - .read = bat_device_read, - .write = bat_device_write, - .poll = bat_device_poll, -}; - -static struct device_client *device_client_hash[256]; - -void bat_device_init(void) -{ - memset(device_client_hash, 0, sizeof(device_client_hash)); -} - -int bat_device_setup(void) -{ - int tmp_major; - - if (Major) - return 1; - - /* register our device - kernel assigns a free major number */ - tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops); - if (tmp_major < 0) { - printk(KERN_ERR "batman-adv:" - "Registering the character device failed with %d\n", - tmp_major); - return 0; - } - - batman_class = class_create(THIS_MODULE, "batman-adv"); - - if (IS_ERR(batman_class)) { - printk(KERN_ERR "batman-adv:" - "Could not register class 'batman-adv'\n"); - return 0; - } - - device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, - "batman-adv"); - - Major = tmp_major; - return 1; -} - -void bat_device_destroy(void) -{ - if (!Major) - return; - - device_destroy(batman_class, MKDEV(Major, 0)); - class_destroy(batman_class); - - /* Unregister the device */ - unregister_chrdev(Major, DRIVER_DEVICE); - - Major = 0; -} - -int bat_device_open(struct inode *inode, struct file *file) -{ - unsigned int i; - struct device_client *device_client; - - device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL); - - if (!device_client) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) { - if (!device_client_hash[i]) { - device_client_hash[i] = device_client; - break; - } - } - - if (i == ARRAY_SIZE(device_client_hash)) { - printk(KERN_ERR "batman-adv:" - "Error - can't add another packet client: " - "maximum number of clients reached\n"); - kfree(device_client); - return -EXFULL; - } - - INIT_LIST_HEAD(&device_client->queue_list); - device_client->queue_len = 0; - device_client->index = i; - spin_lock_init(&device_client->lock); - init_waitqueue_head(&device_client->queue_wait); - - file->private_data = device_client; - - inc_module_count(); - return 0; -} - -int bat_device_release(struct inode *inode, struct file *file) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - struct list_head *list_pos, *list_pos_tmp; - unsigned long flags; - - spin_lock_irqsave(&device_client->lock, flags); - - /* for all packets in the queue ... */ - list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { - device_packet = list_entry(list_pos, - struct device_packet, list); - - list_del(list_pos); - kfree(device_packet); - } - - device_client_hash[device_client->index] = NULL; - spin_unlock_irqrestore(&device_client->lock, flags); - - kfree(device_client); - dec_module_count(); - - return 0; -} - -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct device_packet *device_packet; - int error; - unsigned long flags; - - if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) - return -EAGAIN; - - if ((!buf) || (count < sizeof(struct icmp_packet))) - return -EINVAL; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - error = wait_event_interruptible(device_client->queue_wait, - device_client->queue_len); - - if (error) - return error; - - spin_lock_irqsave(&device_client->lock, flags); - - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - list_del(&device_packet->list); - device_client->queue_len--; - - spin_unlock_irqrestore(&device_client->lock, flags); - - error = __copy_to_user(buf, &device_packet->icmp_packet, - sizeof(struct icmp_packet)); - - kfree(device_packet); - - if (error) - return -EFAULT; - - return sizeof(struct icmp_packet); -} - -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - struct icmp_packet icmp_packet; - struct orig_node *orig_node; - struct batman_if *batman_if; - uint8_t dstaddr[ETH_ALEN]; - unsigned long flags; - - if (len < sizeof(struct icmp_packet)) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "invalid packet size\n"); - return -EINVAL; - } - - if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) - return -EFAULT; - - if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) - return -EFAULT; - - if (icmp_packet.packet_type != BAT_ICMP) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; - } - - if (icmp_packet.msg_type != ECHO_REQUEST) { - bat_dbg(DBG_BATMAN, "batman-adv:" - "Error - can't send packet from char device: " - "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; - } - - icmp_packet.uid = device_client->index; - - if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_device_add_packet(device_client, &icmp_packet); - goto out; - } - - if (atomic_read(&module_state) != MODULE_ACTIVE) - goto dst_unreach; - - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); - - if (!orig_node) - goto unlock; - - if (!orig_node->router) - goto unlock; - - batman_if = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - - spin_unlock_irqrestore(&orig_hash_lock, flags); - - if (!batman_if) - goto dst_unreach; - - if (batman_if->if_status != IF_ACTIVE) - goto dst_unreach; - - memcpy(icmp_packet.orig, - batman_if->net_dev->dev_addr, - ETH_ALEN); - - send_raw_packet((unsigned char *)&icmp_packet, - sizeof(struct icmp_packet), - batman_if, dstaddr); - - goto out; - -unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); -dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_device_add_packet(device_client, &icmp_packet); -out: - return len; -} - -unsigned int bat_device_poll(struct file *file, poll_table *wait) -{ - struct device_client *device_client = - (struct device_client *)file->private_data; - - poll_wait(file, &device_client->queue_wait, wait); - - if (device_client->queue_len > 0) - return POLLIN | POLLRDNORM; - - return 0; -} - -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet *icmp_packet) -{ - struct device_packet *device_packet; - unsigned long flags; - - device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC); - - if (!device_packet) - return; - - INIT_LIST_HEAD(&device_packet->list); - memcpy(&device_packet->icmp_packet, icmp_packet, - sizeof(struct icmp_packet)); - - spin_lock_irqsave(&device_client->lock, flags); - - /* while waiting for the lock the device_client could have been - * deleted */ - if (!device_client_hash[icmp_packet->uid]) { - spin_unlock_irqrestore(&device_client->lock, flags); - kfree(device_packet); - return; - } - - list_add_tail(&device_packet->list, &device_client->queue_list); - device_client->queue_len++; - - if (device_client->queue_len > 100) { - device_packet = list_first_entry(&device_client->queue_list, - struct device_packet, list); - - list_del(&device_packet->list); - kfree(device_packet); - device_client->queue_len--; - } - - spin_unlock_irqrestore(&device_client->lock, flags); - - wake_up(&device_client->queue_wait); -} - -void bat_device_receive_packet(struct icmp_packet *icmp_packet) -{ - struct device_client *hash = device_client_hash[icmp_packet->uid]; - - if (hash) - bat_device_add_packet(hash, icmp_packet); -} diff --git a/drivers/staging/batman-adv/device.h b/drivers/staging/batman-adv/device.h deleted file mode 100644 index eb14b371cea9..000000000000 --- a/drivers/staging/batman-adv/device.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include "types.h" - -void bat_device_init(void); -int bat_device_setup(void); -void bat_device_destroy(void); -int bat_device_open(struct inode *inode, struct file *file); -int bat_device_release(struct inode *inode, struct file *file); -ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos); -ssize_t bat_device_write(struct file *file, const char __user *buff, - size_t len, loff_t *off); -unsigned int bat_device_poll(struct file *file, poll_table *wait); -void bat_device_add_packet(struct device_client *device_client, - struct icmp_packet *icmp_packet); -void bat_device_receive_packet(struct icmp_packet *icmp_packet); diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c new file mode 100644 index 000000000000..d4411cbe350c --- /dev/null +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include +#include +#include "main.h" +#include "icmp_socket.h" +#include "send.h" +#include "types.h" +#include "hash.h" +#include "hard-interface.h" + + +static struct socket_client *socket_client_hash[256]; + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet *icmp_packet); + +void bat_socket_init(void) +{ + memset(socket_client_hash, 0, sizeof(socket_client_hash)); +} + +static int bat_socket_open(struct inode *inode, struct file *file) +{ + unsigned int i; + struct socket_client *socket_client; + + socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL); + + if (!socket_client) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) { + if (!socket_client_hash[i]) { + socket_client_hash[i] = socket_client; + break; + } + } + + if (i == ARRAY_SIZE(socket_client_hash)) { + printk(KERN_ERR "batman-adv:" + "Error - can't add another packet client: " + "maximum number of clients reached\n"); + kfree(socket_client); + return -EXFULL; + } + + INIT_LIST_HEAD(&socket_client->queue_list); + socket_client->queue_len = 0; + socket_client->index = i; + spin_lock_init(&socket_client->lock); + init_waitqueue_head(&socket_client->queue_wait); + + file->private_data = socket_client; + + inc_module_count(); + return 0; +} + +static int bat_socket_release(struct inode *inode, struct file *file) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + struct list_head *list_pos, *list_pos_tmp; + unsigned long flags; + + spin_lock_irqsave(&socket_client->lock, flags); + + /* for all packets in the queue ... */ + list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) { + socket_packet = list_entry(list_pos, + struct socket_packet, list); + + list_del(list_pos); + kfree(socket_packet); + } + + socket_client_hash[socket_client->index] = NULL; + spin_unlock_irqrestore(&socket_client->lock, flags); + + kfree(socket_client); + dec_module_count(); + + return 0; +} + +static ssize_t bat_socket_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct socket_packet *socket_packet; + int error; + unsigned long flags; + + if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0)) + return -EAGAIN; + + if ((!buf) || (count < sizeof(struct icmp_packet))) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + error = wait_event_interruptible(socket_client->queue_wait, + socket_client->queue_len); + + if (error) + return error; + + spin_lock_irqsave(&socket_client->lock, flags); + + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + list_del(&socket_packet->list); + socket_client->queue_len--; + + spin_unlock_irqrestore(&socket_client->lock, flags); + + error = __copy_to_user(buf, &socket_packet->icmp_packet, + sizeof(struct icmp_packet)); + + kfree(socket_packet); + + if (error) + return -EFAULT; + + return sizeof(struct icmp_packet); +} + +static ssize_t bat_socket_write(struct file *file, const char __user *buff, + size_t len, loff_t *off) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + struct icmp_packet icmp_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + uint8_t dstaddr[ETH_ALEN]; + unsigned long flags; + + if (len < sizeof(struct icmp_packet)) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "invalid packet size\n"); + return -EINVAL; + } + + if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) + return -EFAULT; + + if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) + return -EFAULT; + + if (icmp_packet.packet_type != BAT_ICMP) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus packet type (expected: BAT_ICMP)\n"); + return -EINVAL; + } + + if (icmp_packet.msg_type != ECHO_REQUEST) { + bat_dbg(DBG_BATMAN, "batman-adv:" + "Error - can't send packet from char device: " + "got bogus message type (expected: ECHO_REQUEST)\n"); + return -EINVAL; + } + + icmp_packet.uid = socket_client->index; + + if (icmp_packet.version != COMPAT_VERSION) { + icmp_packet.msg_type = PARAMETER_PROBLEM; + icmp_packet.ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, &icmp_packet); + goto out; + } + + if (atomic_read(&module_state) != MODULE_ACTIVE) + goto dst_unreach; + + spin_lock_irqsave(&orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + + if (!orig_node) + goto unlock; + + if (!orig_node->router) + goto unlock; + + batman_if = orig_node->router->if_incoming; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags); + + if (!batman_if) + goto dst_unreach; + + if (batman_if->if_status != IF_ACTIVE) + goto dst_unreach; + + memcpy(icmp_packet.orig, + batman_if->net_dev->dev_addr, + ETH_ALEN); + + send_raw_packet((unsigned char *)&icmp_packet, + sizeof(struct icmp_packet), + batman_if, dstaddr); + + goto out; + +unlock: + spin_unlock_irqrestore(&orig_hash_lock, flags); +dst_unreach: + icmp_packet.msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, &icmp_packet); +out: + return len; +} + +static unsigned int bat_socket_poll(struct file *file, poll_table *wait) +{ + struct socket_client *socket_client = + (struct socket_client *)file->private_data; + + poll_wait(file, &socket_client->queue_wait, wait); + + if (socket_client->queue_len > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = bat_socket_open, + .release = bat_socket_release, + .read = bat_socket_read, + .write = bat_socket_write, + .poll = bat_socket_poll, +}; + +int bat_socket_setup(struct bat_priv *bat_priv) +{ + struct dentry *d; + + if (!bat_priv->debug_dir) + goto err; + + d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR, + bat_priv->debug_dir, NULL, &fops); + if (d) + goto err; + + return 0; + +err: + return 1; +} + +static void bat_socket_add_packet(struct socket_client *socket_client, + struct icmp_packet *icmp_packet) +{ + struct socket_packet *socket_packet; + unsigned long flags; + + socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC); + + if (!socket_packet) + return; + + INIT_LIST_HEAD(&socket_packet->list); + memcpy(&socket_packet->icmp_packet, icmp_packet, + sizeof(struct icmp_packet)); + + spin_lock_irqsave(&socket_client->lock, flags); + + /* while waiting for the lock the socket_client could have been + * deleted */ + if (!socket_client_hash[icmp_packet->uid]) { + spin_unlock_irqrestore(&socket_client->lock, flags); + kfree(socket_packet); + return; + } + + list_add_tail(&socket_packet->list, &socket_client->queue_list); + socket_client->queue_len++; + + if (socket_client->queue_len > 100) { + socket_packet = list_first_entry(&socket_client->queue_list, + struct socket_packet, list); + + list_del(&socket_packet->list); + kfree(socket_packet); + socket_client->queue_len--; + } + + spin_unlock_irqrestore(&socket_client->lock, flags); + + wake_up(&socket_client->queue_wait); +} + +void bat_socket_receive_packet(struct icmp_packet *icmp_packet) +{ + struct socket_client *hash = socket_client_hash[icmp_packet->uid]; + + if (hash) + bat_socket_add_packet(hash, icmp_packet); +} diff --git a/drivers/staging/batman-adv/icmp_socket.h b/drivers/staging/batman-adv/icmp_socket.h new file mode 100644 index 000000000000..5ad73daa08ca --- /dev/null +++ b/drivers/staging/batman-adv/icmp_socket.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "types.h" + +#define ICMP_SOCKET "socket" + +void bat_socket_init(void); +int bat_socket_setup(struct bat_priv *bat_priv); +void bat_socket_receive_packet(struct icmp_packet *icmp_packet); diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 14ab4a0a8805..ed18b08e704b 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -21,11 +21,12 @@ #include "main.h" #include "bat_sysfs.h" +#include "bat_debugfs.h" #include "routing.h" #include "send.h" #include "originator.h" #include "soft-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "hard-interface.h" #include "types.h" @@ -89,7 +90,8 @@ int init_module(void) if (!bat_event_workqueue) return -ENOMEM; - bat_device_init(); + bat_socket_init(); + debugfs_init(); /* initialize layer 2 interface */ soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", @@ -114,6 +116,11 @@ int init_module(void) if (retval < 0) goto unreg_soft_device; + retval = debugfs_add_meshif(soft_device); + + if (retval < 0) + goto unreg_sysfs; + register_netdevice_notifier(&hard_if_notifier); dev_add_pack(&batman_adv_packet_type); @@ -123,6 +130,8 @@ int init_module(void) return 0; +unreg_sysfs: + sysfs_del_meshif(soft_device); unreg_soft_device: unregister_netdev(soft_device); soft_device = NULL; @@ -143,6 +152,7 @@ void cleanup_module(void) hardif_remove_interfaces(); if (soft_device) { + debugfs_del_meshif(soft_device); sysfs_del_meshif(soft_device); unregister_netdev(soft_device); soft_device = NULL; @@ -154,7 +164,7 @@ void cleanup_module(void) bat_event_workqueue = NULL; } -/* activates the module, creates bat device, starts timer ... */ +/* activates the module, starts timer ... */ void activate_module(void) { if (originator_init() < 1) @@ -168,9 +178,6 @@ void activate_module(void) hna_local_add(soft_device->dev_addr); - if (bat_device_setup() < 1) - goto end; - if (vis_init() < 1) goto err; @@ -205,7 +212,7 @@ void deactivate_module(void) hna_global_free(); synchronize_net(); - bat_device_destroy(); + debugfs_destroy(); synchronize_rcu(); atomic_set(&module_state, MODULE_INACTIVE); diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 066dc8b38817..d4bdca9c1260 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -25,7 +25,7 @@ #include "hash.h" #include "soft-interface.h" #include "hard-interface.h" -#include "device.h" +#include "icmp_socket.h" #include "translation-table.h" #include "originator.h" #include "types.h" @@ -668,7 +668,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb) /* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { - bat_device_receive_packet(icmp_packet); + bat_socket_receive_packet(icmp_packet); return NET_RX_DROP; } diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 86007c7eb443..751cd6322813 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -106,9 +106,10 @@ struct bat_priv { char num_ifaces; struct batman_if *primary_if; struct kobject *mesh_obj; + struct dentry *debug_dir; }; -struct device_client { +struct socket_client { struct list_head queue_list; unsigned int queue_len; unsigned char index; @@ -116,7 +117,7 @@ struct device_client { wait_queue_head_t queue_wait; }; -struct device_packet { +struct socket_packet { struct list_head list; struct icmp_packet icmp_packet; }; -- cgit v1.2.3 From 4caecbc03931522bd4af165edb1cfcfc4d3d7887 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Jun 2010 01:25:43 +0200 Subject: Staging: batman-adv: Move tables from sysfs to debugfs Files which represent more than a single attribute aren't allowed in sysfs. As we have some files which aren't essential and are lists or tables aggregated from data from different places inside batman-adv, we must place them in a filesystem without such a restriction. Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_debugfs.c | 71 ++++++++++++ drivers/staging/batman-adv/bat_sysfs.c | 79 ------------- drivers/staging/batman-adv/main.h | 3 +- drivers/staging/batman-adv/originator.c | 64 ++++------- drivers/staging/batman-adv/originator.h | 3 +- drivers/staging/batman-adv/translation-table.c | 149 +++++++++++++------------ drivers/staging/batman-adv/translation-table.h | 6 +- drivers/staging/batman-adv/vis.c | 111 +++++++++++++----- drivers/staging/batman-adv/vis.h | 3 +- 9 files changed, 251 insertions(+), 238 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c index d5b28eb1c69c..a8fe1c91fa4c 100644 --- a/drivers/staging/batman-adv/bat_debugfs.c +++ b/drivers/staging/batman-adv/bat_debugfs.c @@ -31,6 +31,60 @@ static struct dentry *bat_debugfs; +static int originators_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, orig_seq_print_text, net_dev); +} + +static int transtable_global_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_global_seq_print_text, net_dev); +} + +static int transtable_local_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, hna_local_seq_print_text, net_dev); +} + +static int vis_data_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, vis_seq_print_text, net_dev); +} + +struct bat_debuginfo { + struct attribute attr; + const struct file_operations fops; +}; + +#define BAT_DEBUGINFO(_name, _mode, _open) \ +struct bat_debuginfo bat_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } \ +}; + +static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); +static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); +static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); +static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); + +static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_originators, + &bat_debuginfo_transtable_global, + &bat_debuginfo_transtable_local, + &bat_debuginfo_vis_data, + NULL, +}; + void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); @@ -47,6 +101,8 @@ void debugfs_destroy(void) int debugfs_add_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_debuginfo **bat_debug; + struct dentry *file; if (!bat_debugfs) goto out; @@ -57,7 +113,22 @@ int debugfs_add_meshif(struct net_device *dev) bat_socket_setup(bat_priv); + for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) { + file = debugfs_create_file(((*bat_debug)->attr).name, + S_IFREG | ((*bat_debug)->attr).mode, + bat_priv->debug_dir, + dev, &(*bat_debug)->fops); + if (!file) { + printk(KERN_ERR "batman-adv:Can't add debugfs file: " + "%s/%s\n", dev->name, ((*bat_debug)->attr).name); + goto rem_attr; + } + } + return 0; +rem_attr: + debugfs_remove_recursive(bat_priv->debug_dir); + bat_priv->debug_dir = NULL; out: #ifdef CONFIG_DEBUG_FS return -ENOMEM; diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index ffb8ea2702a2..651bdb4b6699 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -36,14 +36,6 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ }; -#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ -struct bin_attribute bat_attr_##_name = { \ - .attr = { .name = __stringify(_name), \ - .mode = _mode, }, \ - .read = _read, \ - .write = _write, \ -}; - static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -201,65 +193,11 @@ static struct bat_attribute *mesh_attrs[] = { NULL, }; -static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_local_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return hna_global_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t originators_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return orig_fill_buffer_text(net_dev, buff, count, off); -} - -static ssize_t vis_data_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) -{ - struct device *dev = to_dev(kobj->parent); - struct net_device *net_dev = to_net_dev(dev); - - return vis_fill_buffer_text(net_dev, buff, count, off); -} - -static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL); -static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL); -static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL); -static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL); - -static struct bin_attribute *mesh_bin_attrs[] = { - &bat_attr_transtable_local, - &bat_attr_transtable_global, - &bat_attr_originators, - &bat_attr_vis_data, - NULL, -}; - int sysfs_add_meshif(struct net_device *dev) { struct kobject *batif_kobject = &dev->dev.kobj; struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; int err; /* FIXME: should be done in the general mesh setup @@ -289,21 +227,8 @@ int sysfs_add_meshif(struct net_device *dev) } } - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) { - err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr)); - if (err) { - printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", - dev->name, SYSFS_IF_MESH_SUBDIR, - ((*bin_attr)->attr).name); - goto rem_bin_attr; - } - } - return 0; -rem_bin_attr: - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); rem_attr: for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); @@ -318,10 +243,6 @@ void sysfs_del_meshif(struct net_device *dev) { struct bat_priv *bat_priv = netdev_priv(dev); struct bat_attribute **bat_attr; - struct bin_attribute **bin_attr; - - for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) - sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr)); for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 8b9e297b9d2b..7cb0b185de19 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -72,7 +72,7 @@ #define MODULE_ACTIVE 1 #define MODULE_DEACTIVATING 2 -#define BCAST_QUEUE_LEN 256 +#define BCAST_QUEUE_LEN 256 #define BATMAN_QUEUE_LEN 256 /* @@ -119,6 +119,7 @@ extern int bat_debug_type(int type); #include #include /* struct sock */ #include +#include #include "types.h" #ifndef REVISION_VERSION diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 568aef8371be..c15970704c8b 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -271,39 +271,31 @@ void purge_orig(struct work_struct *work) start_purge_timer(); } -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int orig_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct orig_node *orig_node; struct neigh_node *neigh_node; - size_t hdr_len, tmp_len; - int batman_count = 0, bytes_written = 0; + int batman_count = 0; unsigned long flags; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; - if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " + if ((!bat_priv->primary_if) || + (bat_priv->primary_if->if_status != IF_ACTIVE)) { + if (!bat_priv->primary_if) + return seq_printf(seq, "BATMAN mesh %s disabled - " "please specify interfaces to enable it\n", net_dev->name); - return 0; + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); } - if (bat_priv->primary_if->if_status != IF_ACTIVE && off == 0) - return sprintf(buff, - "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); - else if (bat_priv->primary_if->if_status != IF_ACTIVE) - return 0; - rcu_read_lock(); - hdr_len = sprintf(buff, - " %-14s (%s/%i) %17s [%10s]: %20s " + seq_printf(seq, " %-14s (%s/%i) %17s [%10s]: %20s " "... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, @@ -311,9 +303,6 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, net_dev->name); rcu_read_unlock(); - if (off < hdr_len) - bytes_written = hdr_len; - spin_lock_irqsave(&orig_hash_lock, flags); while (hash_iterate(orig_hash, &hashit)) { @@ -326,44 +315,29 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, if (orig_node->router->tq_avg == 0) continue; - /* estimated line length */ - if (count < bytes_written + 200) - break; - addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr); - tmp_len = sprintf(buff + bytes_written, - "%-17s (%3i) %17s [%10s]:", - orig_str, orig_node->router->tq_avg, - router_str, - orig_node->router->if_incoming->dev); + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + orig_str, orig_node->router->tq_avg, router_str, + orig_node->router->if_incoming->dev); list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); - tmp_len += sprintf(buff + bytes_written + tmp_len, - " %17s (%3i)", orig_str, + seq_printf(seq, " %17s (%3i)", orig_str, neigh_node->tq_avg); } - tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); - + seq_printf(seq, "\n"); batman_count++; - hdr_len += tmp_len; - - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; } spin_unlock_irqrestore(&orig_hash_lock, flags); - if ((batman_count == 0) && (off == 0)) - bytes_written += sprintf(buff + bytes_written, - "No batman nodes in range ...\n"); + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n"); - return bytes_written; + return 0; } static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h index afbc7c0e8aa3..e91e8a1f4adb 100644 --- a/drivers/staging/batman-adv/originator.h +++ b/drivers/staging/batman-adv/originator.h @@ -28,7 +28,6 @@ struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); -ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index e01ff2151f76..604122c59660 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -160,59 +160,59 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) return i; } -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_local_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_local_entry *hna_local_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff; if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); } - hdr_len = sprintf(buff, - "Locally retrieved addresses (from %s) " - "announced via HNA:\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Locally retrieved addresses (from %s) " + "announced via HNA:\n", + net_dev->name); spin_lock_irqsave(&hna_local_hash_lock, flags); - while (hash_iterate(hna_local_hash, &hashit)) { - hdr_len += 21; - - if (count < bytes_written + 22) - break; + buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ + while (hash_iterate(hna_local_hash, &hashit_count)) + buf_size += 21; - if (off >= hdr_len) - continue; + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_local_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_local_hash, &hashit)) { hna_local_entry = hashit.bucket->data; - bytes_written += snprintf(buff + bytes_written, 22, - " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + pos += snprintf(buff + pos, 22, " * " MAC_FMT "\n", + hna_local_entry->addr[0], + hna_local_entry->addr[1], + hna_local_entry->addr[2], + hna_local_entry->addr[3], + hna_local_entry->addr[4], + hna_local_entry->addr[5]); } spin_unlock_irqrestore(&hna_local_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; } static void _hna_local_del(void *data) @@ -378,65 +378,66 @@ void hna_global_add_orig(struct orig_node *orig_node, spin_unlock_irqrestore(&hna_global_hash_lock, flags); } -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int hna_global_seq_print_text(struct seq_file *seq, void *offset) { + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hna_global_entry *hna_global_entry; HASHIT(hashit); - int bytes_written = 0; + HASHIT(hashit_count); unsigned long flags; - size_t hdr_len; + size_t buf_size, pos; + char *buff; if (!bat_priv->primary_if) { - if (off == 0) - return sprintf(buff, - "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); - - return 0; + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); } - hdr_len = sprintf(buff, - "Globally announced HNAs received via the mesh %s " - "(translation table):\n", - net_dev->name); - - if (off < hdr_len) - bytes_written = hdr_len; + seq_printf(seq, "Globally announced HNAs received via the mesh %s " + "(translation table):\n", + net_dev->name); spin_lock_irqsave(&hna_global_hash_lock, flags); - while (hash_iterate(hna_global_hash, &hashit)) { - hdr_len += 43; - - if (count < bytes_written + 44) - break; + buf_size = 1; + /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ + while (hash_iterate(hna_global_hash, &hashit_count)) + buf_size += 43; - if (off >= hdr_len) - continue; + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&hna_global_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + pos = 0; + while (hash_iterate(hna_global_hash, &hashit)) { hna_global_entry = hashit.bucket->data; - bytes_written += snprintf(buff + bytes_written, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + pos += snprintf(buff + pos, 44, + " * " MAC_FMT " via " MAC_FMT "\n", + hna_global_entry->addr[0], + hna_global_entry->addr[1], + hna_global_entry->addr[2], + hna_global_entry->addr[3], + hna_global_entry->addr[4], + hna_global_entry->addr[5], + hna_global_entry->orig_node->orig[0], + hna_global_entry->orig_node->orig[1], + hna_global_entry->orig_node->orig[2], + hna_global_entry->orig_node->orig[3], + hna_global_entry->orig_node->orig[4], + hna_global_entry->orig_node->orig[5]); } spin_unlock_irqrestore(&hna_global_hash_lock, flags); - return bytes_written; + + seq_printf(seq, "%s", buff); + kfree(buff); + return 0; } void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h index 8f412fca87f1..8b3429e96af2 100644 --- a/drivers/staging/batman-adv/translation-table.h +++ b/drivers/staging/batman-adv/translation-table.h @@ -25,15 +25,13 @@ int hna_local_init(void); void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); -int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); -int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int hna_global_seq_print_text(struct seq_file *seq, void *offset); void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index d4fe87ecfbb2..c73774b16b88 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -115,7 +115,7 @@ static void vis_data_insert_interface(const uint8_t *interface, } /* its a new address, add it to the list */ - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) return; memcpy(entry->addr, interface, ETH_ALEN); @@ -142,12 +142,29 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) return len; } +static size_t vis_data_count_prim_sec(struct hlist_head *if_list) +{ + struct if_list_entry *entry; + struct hlist_node *pos; + size_t count = 0; + + hlist_for_each_entry(entry, pos, if_list, list) { + if (entry->primary) + count += 9; + else + count += 23; + } + + return count; +} + /* read an entry */ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, uint8_t *src, bool primary) { - char to[40]; + char to[18]; + /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ addr_to_string(to, entry->dest); if (primary && entry->quality == 0) return sprintf(buff, "HNA %s, ", to); @@ -157,38 +174,74 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, return 0; } -ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off) +int vis_seq_print_text(struct seq_file *seq, void *offset) { HASHIT(hashit); + HASHIT(hashit_count); struct vis_info *info; struct vis_info_entry *entries; + struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - size_t hdr_len, tmp_len; - int i, bytes_written = 0; + int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); + size_t buff_pos, buf_size; + char *buff; if ((!bat_priv->primary_if) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) return 0; - hdr_len = 0; - + buf_size = 1; + /* Estimate length */ spin_lock_irqsave(&vis_hash_lock, flags); + while (hash_iterate(vis_hash, &hashit_count)) { + info = hashit_count.bucket->data; + entries = (struct vis_info_entry *) + ((char *)info + sizeof(struct vis_info)); + + for (i = 0; i < info->packet.entries; i++) { + if (entries[i].quality == 0) + continue; + vis_data_insert_interface(entries[i].src, &vis_if_list, + compare_orig(entries[i].src, + info->packet.vis_orig)); + } + + hlist_for_each_entry(entry, pos, &vis_if_list, list) { + buf_size += 18 + 26 * info->packet.entries; + + /* add primary/secondary records */ + if (compare_orig(entry->addr, info->packet.vis_orig)) + buf_size += + vis_data_count_prim_sec(&vis_if_list); + + buf_size += 1; + } + + hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { + hlist_del(&entry->list); + kfree(entry); + } + } + + buff = kmalloc(buf_size, GFP_ATOMIC); + if (!buff) { + spin_unlock_irqrestore(&vis_hash_lock, flags); + return -ENOMEM; + } + buff[0] = '\0'; + buff_pos = 0; + while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info)); - /* estimated line length */ - if (count < bytes_written + 200) - break; - for (i = 0; i < info->packet.entries; i++) { if (entries[i].quality == 0) continue; @@ -199,30 +252,22 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, hlist_for_each_entry(entry, pos, &vis_if_list, list) { addr_to_string(tmp_addr_str, entry->addr); - tmp_len = sprintf(buff + bytes_written, - "%s,", tmp_addr_str); + buff_pos += sprintf(buff + buff_pos, "%s,", + tmp_addr_str); for (i = 0; i < info->packet.entries; i++) - tmp_len += vis_data_read_entry( - buff + bytes_written + tmp_len, - &entries[i], entry->addr, - entry->primary); + buff_pos += vis_data_read_entry(buff + buff_pos, + &entries[i], + entry->addr, + entry->primary); /* add primary/secondary records */ if (compare_orig(entry->addr, info->packet.vis_orig)) - tmp_len += vis_data_read_prim_sec( - buff + bytes_written + tmp_len, - &vis_if_list); - - tmp_len += sprintf(buff + bytes_written + tmp_len, - "\n"); - - hdr_len += tmp_len; + buff_pos += + vis_data_read_prim_sec(buff + buff_pos, + &vis_if_list); - if (off >= hdr_len) - continue; - - bytes_written += tmp_len; + buff_pos += sprintf(buff + buff_pos, "\n"); } hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { @@ -230,9 +275,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, kfree(entry); } } + spin_unlock_irqrestore(&vis_hash_lock, flags); - return bytes_written; + seq_printf(seq, "%s", buff); + kfree(buff); + + return 0; } /* add the info packet to the send list, if it was not diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index 9c1fd771cbae..5dd6521cd7d1 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -47,8 +47,7 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock; -ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, - size_t count, loff_t off); +int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len); -- cgit v1.2.3 From 3a632cc71a8a0aea00db14c22f75d1a3846f9c4f Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Tue, 22 Jun 2010 01:25:44 +0200 Subject: Staging: batman-adv: convert all sysfs files to single value files This patch removes the extra usage output which came when the sysfs files were read. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_sysfs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index 651bdb4b6699..b9618176a605 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -36,18 +36,18 @@ struct bat_attribute bat_attr_##_name = { \ .store = _store, \ }; -static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr, +static ssize_t show_aggr_ogms(struct kobject *kobj, struct attribute *attr, char *buff) { struct device *dev = to_dev(kobj->parent); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); int aggr_status = atomic_read(&bat_priv->aggregation_enabled); - return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1\n", + return sprintf(buff, "%s\n", aggr_status == 0 ? "disabled" : "enabled"); } -static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr, +static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr, char *buff, size_t count) { struct device *dev = to_dev(kobj->parent); @@ -91,10 +91,9 @@ static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); int vis_mode = atomic_read(&bat_priv->vis_mode); - return sprintf(buff, "status: %s\ncommands: client, server, %d, %d\n", + return sprintf(buff, "%s\n", vis_mode == VIS_TYPE_CLIENT_UPDATE ? - "client" : "server", - VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE); + "client" : "server"); } static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, @@ -109,7 +108,8 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, ret = strict_strtoul(buff, 10, &val); if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || - (strncmp(buff, "client", 6) == 0)) + (strncmp(buff, "client", 6) == 0) || + (strncmp(buff, "off", 3) == 0)) vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE; if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) || @@ -143,7 +143,7 @@ static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr, struct device *dev = to_dev(kobj->parent); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); - return sprintf(buff, "status: %i\n", + return sprintf(buff, "%i\n", atomic_read(&bat_priv->orig_interval)); } @@ -180,14 +180,14 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr, return count; } -static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR, - show_aggr_ogm, store_aggr_ogm); +static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR, + show_aggr_ogms, store_aggr_ogms); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, show_orig_interval, store_orig_interval); static struct bat_attribute *mesh_attrs[] = { - &bat_attr_aggregate_ogm, + &bat_attr_aggregated_ogms, &bat_attr_vis_mode, &bat_attr_orig_interval, NULL, @@ -261,7 +261,7 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr, if (!batman_if) return 0; - return sprintf(buff, "status: %s\ncommands: none, bat0\n", + return sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ? "none" : "bat0"); } -- cgit v1.2.3 From 1bcb164e5d28b316512cd06c5092bc6a03506417 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Tue, 22 Jun 2010 01:25:45 +0200 Subject: Staging: batman-adv: remove superfluous hint to "translation table" Signed-off-by: Marek Lindner [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/translation-table.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 604122c59660..5a0264aac1e8 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -395,8 +395,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) net_dev->name); } - seq_printf(seq, "Globally announced HNAs received via the mesh %s " - "(translation table):\n", + seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", net_dev->name); spin_lock_irqsave(&hna_global_hash_lock, flags); -- cgit v1.2.3 From 516c9a777819150bf3a9b709cd93325cf29a93bf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 22 Jun 2010 01:25:46 +0200 Subject: Staging: batman-adv: Convert MAC_FMT to %pM Remove the last uses of MAC_FMT Signed-off-by: Joe Perches [sven.eckelmann@gmx.de: Adapted for current batman-adv version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/main.c | 3 +-- drivers/staging/batman-adv/translation-table.c | 24 ++++-------------------- 2 files changed, 5 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index ed18b08e704b..72fccb1c5236 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -230,8 +230,7 @@ void dec_module_count(void) int addr_to_string(char *buff, uint8_t *addr) { - return sprintf(buff, MAC_FMT, - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + return sprintf(buff, "%pM", addr); } /* returns 1 if they are the same originator */ diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 5a0264aac1e8..d9233b06f131 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -199,13 +199,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) while (hash_iterate(hna_local_hash, &hashit)) { hna_local_entry = hashit.bucket->data; - pos += snprintf(buff + pos, 22, " * " MAC_FMT "\n", - hna_local_entry->addr[0], - hna_local_entry->addr[1], - hna_local_entry->addr[2], - hna_local_entry->addr[3], - hna_local_entry->addr[4], - hna_local_entry->addr[5]); + pos += snprintf(buff + pos, 22, " * %pM\n", + hna_local_entry->addr); } spin_unlock_irqrestore(&hna_local_hash_lock, flags); @@ -417,19 +412,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) hna_global_entry = hashit.bucket->data; pos += snprintf(buff + pos, 44, - " * " MAC_FMT " via " MAC_FMT "\n", - hna_global_entry->addr[0], - hna_global_entry->addr[1], - hna_global_entry->addr[2], - hna_global_entry->addr[3], - hna_global_entry->addr[4], - hna_global_entry->addr[5], - hna_global_entry->orig_node->orig[0], - hna_global_entry->orig_node->orig[1], - hna_global_entry->orig_node->orig[2], - hna_global_entry->orig_node->orig[3], - hna_global_entry->orig_node->orig[4], - hna_global_entry->orig_node->orig[5]); + " * %pM via %pM\n", hna_global_entry->addr, + hna_global_entry->orig_node->orig); } spin_unlock_irqrestore(&hna_global_hash_lock, flags); -- cgit v1.2.3 From 42fa1b92ab3261ef60ef4f60ff6eff2a0585348d Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Jun 2010 01:25:47 +0200 Subject: Staging: batman-adv: Mark locally used symbols as static Functions and variables which are used only inside one object file can be declared as static. This helped to find unused functions/variables * mainIfAddr_default * main_if_was_up and functions with declarations but missing definitions * hash_debug * orig_find * send_own_packet_work Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bitarray.c | 2 +- drivers/staging/batman-adv/bitarray.h | 3 - drivers/staging/batman-adv/hash.c | 2 +- drivers/staging/batman-adv/hash.h | 6 -- drivers/staging/batman-adv/originator.c | 32 ++++---- drivers/staging/batman-adv/originator.h | 2 - drivers/staging/batman-adv/routing.c | 2 +- drivers/staging/batman-adv/routing.h | 2 - drivers/staging/batman-adv/send.c | 4 +- drivers/staging/batman-adv/send.h | 2 - drivers/staging/batman-adv/soft-interface.c | 104 ++++++++++++------------- drivers/staging/batman-adv/soft-interface.h | 6 -- drivers/staging/batman-adv/translation-table.c | 9 ++- drivers/staging/batman-adv/translation-table.h | 3 - drivers/staging/batman-adv/vis.c | 4 +- drivers/staging/batman-adv/vis.h | 3 - 16 files changed, 79 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c index 2fef6e35f8c3..cfca0339220b 100644 --- a/drivers/staging/batman-adv/bitarray.c +++ b/drivers/staging/batman-adv/bitarray.c @@ -63,7 +63,7 @@ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n) } /* shift the packet array by n places. */ -void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n) +static void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n) { int32_t word_offset, word_num; int32_t i; diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h index 76ad24c9f3de..4dd1e7cf9486 100644 --- a/drivers/staging/batman-adv/bitarray.h +++ b/drivers/staging/batman-adv/bitarray.h @@ -32,9 +32,6 @@ uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, /* turn corresponding bit on, so we can remember that we got the packet */ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n); -/* shift the packet array by n places. */ -void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n); - /* receive and process one packet, returns 1 if received seq_num is considered * new, 0 if old */ diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c index d4a4adc57042..1286f8ff44f4 100644 --- a/drivers/staging/batman-adv/hash.c +++ b/drivers/staging/batman-adv/hash.c @@ -23,7 +23,7 @@ #include "hash.h" /* clears the hash */ -void hash_init(struct hashtable_t *hash) +static void hash_init(struct hashtable_t *hash) { int i; diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h index ea6d21e01251..05055957f124 100644 --- a/drivers/staging/batman-adv/hash.h +++ b/drivers/staging/batman-adv/hash.h @@ -56,9 +56,6 @@ struct hashtable_t { * argument and the size the second */ }; -/* clears the hash */ -void hash_init(struct hashtable_t *hash); - /* allocates and clears the hash */ struct hashtable_t *hash_new(int size, hashdata_compare_cb compare, hashdata_choose_cb choose); @@ -98,7 +95,4 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size); * the returned iterator to access the elements until hash_it_t returns NULL. */ struct hash_it_t *hash_iterate(struct hashtable_t *hash, struct hash_it_t *iter_in); - -/* print the hash table for debugging */ -void hash_debug(struct hashtable_t *hash); #endif diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index c15970704c8b..1f6cbe8f8f0b 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -56,21 +56,6 @@ err: return 0; } -void originator_free(void) -{ - unsigned long flags; - - if (!orig_hash) - return; - - cancel_delayed_work_sync(&purge_orig_wq); - - spin_lock_irqsave(&orig_hash_lock, flags); - hash_delete(orig_hash, free_orig_node); - orig_hash = NULL; - spin_unlock_irqrestore(&orig_hash_lock, flags); -} - struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming) @@ -93,7 +78,7 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, return neigh_node; } -void free_orig_node(void *data) +static void free_orig_node(void *data) { struct list_head *list_pos, *list_pos_tmp; struct neigh_node *neigh_node; @@ -114,6 +99,21 @@ void free_orig_node(void *data) kfree(orig_node); } +void originator_free(void) +{ + unsigned long flags; + + if (!orig_hash) + return; + + cancel_delayed_work_sync(&purge_orig_wq); + + spin_lock_irqsave(&orig_hash_lock, flags); + hash_delete(orig_hash, free_orig_node); + orig_hash = NULL; + spin_unlock_irqrestore(&orig_hash_lock, flags); +} + /* this function finds or creates an originator entry for the given * address if it does not exits */ struct orig_node *get_orig_node(uint8_t *addr) diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h index e91e8a1f4adb..6632538d12fc 100644 --- a/drivers/staging/batman-adv/originator.h +++ b/drivers/staging/batman-adv/originator.h @@ -20,10 +20,8 @@ */ int originator_init(void); -void free_orig_node(void *data); void originator_free(void); void purge_orig(struct work_struct *work); -struct orig_node *orig_find(char *mac); struct orig_node *get_orig_node(uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index d4bdca9c1260..480c645e3a61 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -33,7 +33,7 @@ #include "vis.h" #include "aggregation.h" -DECLARE_WAIT_QUEUE_HEAD(thread_wait); +static DECLARE_WAIT_QUEUE_HEAD(thread_wait); void slide_own_bcast_window(struct batman_if *batman_if) { diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 8288decea370..c6850d26779c 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -21,8 +21,6 @@ #include "types.h" -extern wait_queue_head_t thread_wait; - void slide_own_bcast_window(struct batman_if *batman_if); void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 7365f6dbcb6b..e8f0e2a7b421 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -31,6 +31,8 @@ #include +static void send_outstanding_bcast_packet(struct work_struct *work); + /* apply hop penalty for a normal link */ static uint8_t hop_penalty(const uint8_t tq) { @@ -431,7 +433,7 @@ out: return NETDEV_TX_BUSY; } -void send_outstanding_bcast_packet(struct work_struct *work) +static void send_outstanding_bcast_packet(struct work_struct *work) { struct batman_if *batman_if; struct delayed_work *delayed_work = diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h index feaa2fc7f9a1..0a0990d6483b 100644 --- a/drivers/staging/batman-adv/send.h +++ b/drivers/staging/batman-adv/send.h @@ -21,7 +21,6 @@ #include "types.h" -void send_own_packet_work(struct work_struct *work); int send_skb_packet(struct sk_buff *skb, struct batman_if *batman_if, uint8_t *dst_addr); @@ -34,6 +33,5 @@ void schedule_forward_packet(struct orig_node *orig_node, uint8_t directlink, int hna_buff_len, struct batman_if *if_outgoing); int add_bcast_packet_to_list(struct sk_buff *skb); -void send_outstanding_bcast_packet(struct work_struct *work); void send_outstanding_bat_packet(struct work_struct *work); void purge_outstanding_packets(struct batman_if *batman_if); diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 51c40b77c8d7..c483693d5944 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -36,7 +36,6 @@ static int32_t skb_packets; static int32_t skb_bad_packets; unsigned char mainIfAddr[ETH_ALEN]; -static unsigned char mainIfAddr_default[ETH_ALEN]; static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); static void bat_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); @@ -61,11 +60,6 @@ void set_main_if_addr(uint8_t *addr) memcpy(mainIfAddr, addr, ETH_ALEN); } -int main_if_was_up(void) -{ - return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0); -} - int my_skb_push(struct sk_buff *skb, unsigned int len) { int result = 0; @@ -83,69 +77,25 @@ int my_skb_push(struct sk_buff *skb, unsigned int len) return 0; } -#ifdef HAVE_NET_DEVICE_OPS -static const struct net_device_ops bat_netdev_ops = { - .ndo_open = interface_open, - .ndo_stop = interface_release, - .ndo_get_stats = interface_stats, - .ndo_set_mac_address = interface_set_mac_addr, - .ndo_change_mtu = interface_change_mtu, - .ndo_start_xmit = interface_tx, - .ndo_validate_addr = eth_validate_addr -}; -#endif - -void interface_setup(struct net_device *dev) -{ - struct bat_priv *priv = netdev_priv(dev); - char dev_addr[ETH_ALEN]; - - ether_setup(dev); - -#ifdef HAVE_NET_DEVICE_OPS - dev->netdev_ops = &bat_netdev_ops; -#else - dev->open = interface_open; - dev->stop = interface_release; - dev->get_stats = interface_stats; - dev->set_mac_address = interface_set_mac_addr; - dev->change_mtu = interface_change_mtu; - dev->hard_start_xmit = interface_tx; -#endif - dev->destructor = free_netdev; - - dev->mtu = hardif_min_mtu(); - dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the - * skbuff for our header */ - - /* generate random address */ - random_ether_addr(dev_addr); - memcpy(dev->dev_addr, dev_addr, ETH_ALEN); - - SET_ETHTOOL_OPS(dev, &bat_ethtool_ops); - - memset(priv, 0, sizeof(struct bat_priv)); -} - -int interface_open(struct net_device *dev) +static int interface_open(struct net_device *dev) { netif_start_queue(dev); return 0; } -int interface_release(struct net_device *dev) +static int interface_release(struct net_device *dev) { netif_stop_queue(dev); return 0; } -struct net_device_stats *interface_stats(struct net_device *dev) +static struct net_device_stats *interface_stats(struct net_device *dev) { struct bat_priv *priv = netdev_priv(dev); return &priv->stats; } -int interface_set_mac_addr(struct net_device *dev, void *p) +static int interface_set_mac_addr(struct net_device *dev, void *p) { struct sockaddr *addr = p; @@ -163,7 +113,7 @@ int interface_set_mac_addr(struct net_device *dev, void *p) return 0; } -int interface_change_mtu(struct net_device *dev, int new_mtu) +static int interface_change_mtu(struct net_device *dev, int new_mtu) { /* check ranges */ if ((new_mtu < 68) || (new_mtu > hardif_min_mtu())) @@ -315,6 +265,50 @@ void interface_rx(struct sk_buff *skb, int hdr_size) netif_rx(skb); } +#ifdef HAVE_NET_DEVICE_OPS +static const struct net_device_ops bat_netdev_ops = { + .ndo_open = interface_open, + .ndo_stop = interface_release, + .ndo_get_stats = interface_stats, + .ndo_set_mac_address = interface_set_mac_addr, + .ndo_change_mtu = interface_change_mtu, + .ndo_start_xmit = interface_tx, + .ndo_validate_addr = eth_validate_addr +}; +#endif + +void interface_setup(struct net_device *dev) +{ + struct bat_priv *priv = netdev_priv(dev); + char dev_addr[ETH_ALEN]; + + ether_setup(dev); + +#ifdef HAVE_NET_DEVICE_OPS + dev->netdev_ops = &bat_netdev_ops; +#else + dev->open = interface_open; + dev->stop = interface_release; + dev->get_stats = interface_stats; + dev->set_mac_address = interface_set_mac_addr; + dev->change_mtu = interface_change_mtu; + dev->hard_start_xmit = interface_tx; +#endif + dev->destructor = free_netdev; + + dev->mtu = hardif_min_mtu(); + dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the + * skbuff for our header */ + + /* generate random address */ + random_ether_addr(dev_addr); + memcpy(dev->dev_addr, dev_addr, ETH_ALEN); + + SET_ETHTOOL_OPS(dev, &bat_ethtool_ops); + + memset(priv, 0, sizeof(struct bat_priv)); +} + /* ethtool */ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h index e7f59af7df33..3852c573221e 100644 --- a/drivers/staging/batman-adv/soft-interface.h +++ b/drivers/staging/batman-adv/soft-interface.h @@ -20,13 +20,7 @@ */ void set_main_if_addr(uint8_t *addr); -int main_if_was_up(void); void interface_setup(struct net_device *dev); -int interface_open(struct net_device *dev); -int interface_release(struct net_device *dev); -struct net_device_stats *interface_stats(struct net_device *dev); -int interface_set_mac_addr(struct net_device *dev, void *addr); -int interface_change_mtu(struct net_device *dev, int new_mtu); int interface_tx(struct sk_buff *skb, struct net_device *dev); void interface_rx(struct sk_buff *skb, int hdr_size); int my_skb_push(struct sk_buff *skb, unsigned int len); diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index d9233b06f131..9fd32a979324 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -32,7 +32,10 @@ atomic_t hna_local_changed; DEFINE_SPINLOCK(hna_local_hash_lock); static DEFINE_SPINLOCK(hna_global_hash_lock); +static void hna_local_purge(struct work_struct *work); static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge); +static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, + char *message); static void hna_local_start_timer(void) { @@ -242,7 +245,7 @@ void hna_local_remove(uint8_t *addr, char *message) spin_unlock_irqrestore(&hna_local_hash_lock, flags); } -void hna_local_purge(struct work_struct *work) +static void hna_local_purge(struct work_struct *work) { struct hna_local_entry *hna_local_entry; HASHIT(hashit); @@ -423,8 +426,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) return 0; } -void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, - char *message) +static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, + char *message) { bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s\n", hna_global_entry->addr, hna_global_entry->orig_node->orig, diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h index 8b3429e96af2..232208fedef5 100644 --- a/drivers/staging/batman-adv/translation-table.h +++ b/drivers/staging/batman-adv/translation-table.h @@ -26,14 +26,11 @@ void hna_local_add(uint8_t *addr); void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); int hna_local_seq_print_text(struct seq_file *seq, void *offset); -void hna_local_purge(struct work_struct *work); void hna_local_free(void); int hna_global_init(void); void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); int hna_global_seq_print_text(struct seq_file *seq, void *offset); -void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, - char *orig_str); void hna_global_del_orig(struct orig_node *orig_node, char *message); void hna_global_free(void); struct orig_node *transtable_search(uint8_t *addr); diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index c73774b16b88..7bd553a5cd39 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -43,8 +43,8 @@ _dummy > smallest_signed_int(_dummy); }) #define seq_after(x, y) seq_before(y, x) -struct hashtable_t *vis_hash; -DEFINE_SPINLOCK(vis_hash_lock); +static struct hashtable_t *vis_hash; +static DEFINE_SPINLOCK(vis_hash_lock); static DEFINE_SPINLOCK(recv_list_lock); static struct vis_info *my_vis_info; static struct list_head send_list; /* always locked with vis_hash_lock */ diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index 5dd6521cd7d1..1cfadce59325 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -44,9 +44,6 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; }; -extern struct hashtable_t *vis_hash; -extern spinlock_t vis_hash_lock; - int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, -- cgit v1.2.3 From 8bfe3638747b2c2f842edf9eb2a407a22a9d537d Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Jun 2010 01:25:48 +0200 Subject: Staging: batman-adv: Ignore debugfs on kernels without debugfs support All code for debugfs is ignored when the creation of the batman-adv root directory in debugfs fails. It must also be ignored when the debugfs_create_dir tells us that debugfs is not implemented to prevent possible crashes in the future. Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_debugfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c index a8fe1c91fa4c..fafca9f0a33c 100644 --- a/drivers/staging/batman-adv/bat_debugfs.c +++ b/drivers/staging/batman-adv/bat_debugfs.c @@ -88,6 +88,8 @@ static struct bat_debuginfo *mesh_debuginfos[] = { void debugfs_init(void) { bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL); + if (bat_debugfs == ERR_PTR(-ENODEV)) + bat_debugfs = NULL; } void debugfs_destroy(void) -- cgit v1.2.3 From 5a39195769febbc29a1d60d02f655ee32c252813 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Tue, 22 Jun 2010 01:25:49 +0200 Subject: Staging: batman-adv: permit setting ogm interval to JITTER*2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to set the originator interval to 40ms, we are asked to set it to a minimum value of 40ms. This patch permits setting an originator interval of JITTER*2 (40ms by default) now. Signed-off-by: Linus Lüssing Signed-off-by: Simon Wunderlich Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index b9618176a605..b8ccb7511ef5 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -163,7 +163,7 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr, return -EINVAL; } - if (orig_interval_tmp <= JITTER * 2) { + if (orig_interval_tmp < JITTER * 2) { printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n", orig_interval_tmp, JITTER * 2); return -EINVAL; -- cgit v1.2.3 From 6856ba1f44522b381c9a60b7972dd0fb52c54093 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 22 Jun 2010 01:25:50 +0200 Subject: Staging: batman-adv: Add release information for version 2010.0.0 Signed-off-by: Simon Wunderlich Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/CHANGELOG | 12 ++++++++++++ drivers/staging/batman-adv/README | 2 +- drivers/staging/batman-adv/main.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/CHANGELOG b/drivers/staging/batman-adv/CHANGELOG index c8f9d9e06bb4..86450b4f7d76 100644 --- a/drivers/staging/batman-adv/CHANGELOG +++ b/drivers/staging/batman-adv/CHANGELOG @@ -1,3 +1,15 @@ +batman-adv 2010.0.0: + +* support latest kernels (2.6.21 - 2.6.35) +* further code refactoring and cleaning for coding style +* move from procfs based configuration to sysfs +* reorganized sequence number handling +* limit queue lengths for batman and broadcast packets +* many bugs (endless loop and rogue packets on shutdown, wrong tcpdump output, + missing frees in error situations, sleeps in atomic contexts) squashed + + -- Fri, 18 Jun 2010 21:34:26 +0200 + batman-adv 0.2.1: * support latest kernels (2.6.20 - 2.6.33) diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README index 14244a2c4e4f..7192b7fa2183 100644 --- a/drivers/staging/batman-adv/README +++ b/drivers/staging/batman-adv/README @@ -1,4 +1,4 @@ -[state: 03-05-2010] +[state: 12-06-2010] BATMAN-ADV ---------- diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 7cb0b185de19..f70d99af4289 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -27,7 +27,7 @@ #define DRIVER_DESC "B.A.T.M.A.N. advanced" #define DRIVER_DEVICE "batman-adv" -#define SOURCE_VERSION "0.2.2-beta" +#define SOURCE_VERSION "2010.0.0" /* B.A.T.M.A.N. parameters */ -- cgit v1.2.3 From cf2d72ec5c66ac3ebe9d28c3d88314a958cc180e Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 22 Jun 2010 01:25:51 +0200 Subject: Staging: batman-adv: 32bit sequence number and TTL for broadcasts This patch changes the sequence number range from 8 or 16 bit to 32 bit. This should avoid problems with the sequence number sliding window algorithm which we had seen in the past for broadcast floods or malicious packet injections. We can not assure 100% security with this patch, but it is quite an improvement over the old 16 bit sequence numbers: * expected window size can be increased (4096 -> 65536) * 64k packets in the right order would now be needed to cause a loop, which seems practically impossible. Furthermore, a TTL field has been added to the broadcast packet type, just to make sure. These changes required to increase the compatibility level once again. Signed-off-by: Simon Wunderlich [sven.eckelmann@gmx.de: Change atomic64_* back to atomic_*, Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/aggregation.c | 4 ++-- drivers/staging/batman-adv/bitarray.c | 8 ++++---- drivers/staging/batman-adv/bitarray.h | 6 +++--- drivers/staging/batman-adv/main.h | 2 +- drivers/staging/batman-adv/packet.h | 9 +++++---- drivers/staging/batman-adv/routing.c | 17 ++++++++++------- drivers/staging/batman-adv/send.c | 15 ++++++++++----- drivers/staging/batman-adv/soft-interface.c | 5 +++-- drivers/staging/batman-adv/types.h | 6 +++--- drivers/staging/batman-adv/vis.c | 5 +++-- 10 files changed, 44 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index ce8b8a6e5ae6..3a5c3499ca06 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -252,9 +252,9 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, while (aggregated_packet(buff_pos, packet_len, batman_packet->num_hna)) { - /* network to host order for our 16bit seqno, and the + /* network to host order for our 32bit seqno, and the orig_interval. */ - batman_packet->seqno = ntohs(batman_packet->seqno); + batman_packet->seqno = ntohl(batman_packet->seqno); hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; receive_bat_packet(ethhdr, batman_packet, diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c index cfca0339220b..c10fe03ec63b 100644 --- a/drivers/staging/batman-adv/bitarray.c +++ b/drivers/staging/batman-adv/bitarray.c @@ -24,10 +24,10 @@ /* returns true if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno */ -uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, - uint16_t curr_seqno) +uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno, + uint32_t curr_seqno) { - int16_t diff, word_offset, word_num; + int32_t diff, word_offset, word_num; diff = last_seqno - curr_seqno; if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) { @@ -125,7 +125,7 @@ static void bit_reset_window(TYPE_OF_WORD *seq_bits) * 1 if the window was moved (either new or very old) * 0 if the window was not moved/shifted. */ -char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, +char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff, int8_t set_mark) { /* sequence number is slightly older. We already got a sequence number diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h index 4dd1e7cf9486..dad13bf473d0 100644 --- a/drivers/staging/batman-adv/bitarray.h +++ b/drivers/staging/batman-adv/bitarray.h @@ -26,8 +26,8 @@ /* returns true if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno */ -uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, - uint16_t curr_seqno); +uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno, + uint32_t curr_seqno); /* turn corresponding bit on, so we can remember that we got the packet */ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n); @@ -35,7 +35,7 @@ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n); /* receive and process one packet, returns 1 if received seq_num is considered * new, 0 if old */ -char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, +char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff, int8_t set_mark); /* count the hamming weight, how many good packets did we receive? */ diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index f70d99af4289..145ac5131bf8 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -65,7 +65,7 @@ #define MAX_AGGREGATION_MS 100 #define RESET_PROTECTION_MS 30000 -#define EXPECTED_SEQNO_RANGE 4096 +#define EXPECTED_SEQNO_RANGE 65536 /* don't reset again within 30 seconds */ #define MODULE_INACTIVE 0 diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index 152f57b1c6c5..f0387babfa69 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h @@ -28,7 +28,7 @@ #define BAT_VIS 0x05 /* this file is included by batctl which needs these defines */ -#define COMPAT_VERSION 8 +#define COMPAT_VERSION 11 #define DIRECTLINK 0x40 #define VIS_SERVER 0x20 @@ -48,7 +48,7 @@ struct batman_packet { uint8_t version; /* batman version field */ uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ uint8_t tq; - uint16_t seqno; + uint32_t seqno; uint8_t orig[6]; uint8_t prev_sender[6]; uint8_t ttl; @@ -79,15 +79,16 @@ struct bcast_packet { uint8_t packet_type; uint8_t version; /* batman version field */ uint8_t orig[6]; - uint16_t seqno; + uint8_t ttl; + uint32_t seqno; } __attribute__((packed)); struct vis_packet { uint8_t packet_type; uint8_t version; /* batman version field */ uint8_t vis_type; /* which type of vis-participant sent this? */ - uint8_t seqno; /* sequence number */ uint8_t entries; /* number of entries behind this struct */ + uint32_t seqno; /* sequence number */ uint8_t ttl; /* TTL */ uint8_t vis_orig[6]; /* originator that informs about its * neighbors */ diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 480c645e3a61..9dbfabeb9704 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -318,7 +318,7 @@ update_hna: * 0 if the packet is to be accepted * 1 if the packet is to be ignored. */ -static int window_protected(int16_t seq_num_diff, +static int window_protected(int32_t seq_num_diff, unsigned long *last_reset) { if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) @@ -352,7 +352,7 @@ static char count_real_packets(struct ethhdr *ethhdr, struct orig_node *orig_node; struct neigh_node *tmp_neigh_node; char is_duplicate = 0; - int16_t seq_diff; + int32_t seq_diff; int need_update = 0; int set_mark; @@ -406,7 +406,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; char is_duplicate; - unsigned short if_incoming_seqno; + uint32_t if_incoming_seqno; /* Silently drop when the batman packet is actually not a * correct packet. @@ -950,7 +950,7 @@ int recv_bcast_packet(struct sk_buff *skb) struct bcast_packet *bcast_packet; struct ethhdr *ethhdr; int hdr_size = sizeof(struct bcast_packet); - int16_t seq_diff; + int32_t seq_diff; unsigned long flags; /* drop packet if it has not necessary minimum size */ @@ -977,6 +977,9 @@ int recv_bcast_packet(struct sk_buff *skb) if (is_my_mac(bcast_packet->orig)) return NET_RX_DROP; + if (bcast_packet->ttl < 2) + return NET_RX_DROP; + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, bcast_packet->orig)); @@ -989,12 +992,12 @@ int recv_bcast_packet(struct sk_buff *skb) /* check whether the packet is a duplicate */ if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, - ntohs(bcast_packet->seqno))) { + ntohl(bcast_packet->seqno))) { spin_unlock_irqrestore(&orig_hash_lock, flags); return NET_RX_DROP; } - seq_diff = ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno; + seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; /* check whether the packet is old and the host just restarted. */ if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) { @@ -1005,7 +1008,7 @@ int recv_bcast_packet(struct sk_buff *skb) /* mark broadcast in flood history, update window position * if required. */ if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1)) - orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno); + orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno); spin_unlock_irqrestore(&orig_hash_lock, flags); /* rebroadcast packet */ diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index e8f0e2a7b421..f2653dd37c07 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -159,7 +159,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," " IDF %s) on interface %s [%s]\n", fwd_str, (packet_num > 0 ? "aggregated " : ""), - batman_packet->orig, ntohs(batman_packet->seqno), + batman_packet->orig, ntohl(batman_packet->seqno), batman_packet->tq, batman_packet->ttl, (batman_packet->flags & DIRECTLINK ? "on" : "off"), @@ -204,7 +204,7 @@ static void send_packet(struct forw_packet *forw_packet) "%s packet (originator %pM, seqno %d, TTL %d) " "on interface %s [%s]\n", (forw_packet->own ? "Sending own" : "Forwarding"), - batman_packet->orig, ntohs(batman_packet->seqno), + batman_packet->orig, ntohl(batman_packet->seqno), batman_packet->ttl, forw_packet->if_incoming->dev, forw_packet->if_incoming->addr_str); @@ -283,14 +283,14 @@ void schedule_own_packet(struct batman_if *batman_if) batman_packet = (struct batman_packet *)batman_if->packet_buff; /* change sequence number to network order */ - batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno)); + batman_packet->seqno = + htonl((uint32_t)atomic_read(&batman_if->seqno)); if (vis_server == VIS_TYPE_SERVER_SYNC) batman_packet->flags = VIS_SERVER; else batman_packet->flags &= ~VIS_SERVER; - /* could be read by receive_bat_packet() */ atomic_inc(&batman_if->seqno); slide_own_bcast_window(batman_if); @@ -347,7 +347,7 @@ void schedule_forward_packet(struct orig_node *orig_node, in_tq, tq_avg, batman_packet->tq, in_ttl - 1, batman_packet->ttl); - batman_packet->seqno = htons(batman_packet->seqno); + batman_packet->seqno = htonl(batman_packet->seqno); if (directlink) batman_packet->flags |= DIRECTLINK; @@ -399,6 +399,7 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, int add_bcast_packet_to_list(struct sk_buff *skb) { struct forw_packet *forw_packet; + struct bcast_packet *bcast_packet; if (!atomic_dec_not_zero(&bcast_queue_left)) { bat_dbg(DBG_BATMAN, "bcast packet queue full\n"); @@ -414,6 +415,10 @@ int add_bcast_packet_to_list(struct sk_buff *skb) if (!skb) goto packet_free; + /* as we have a copy now, it is safe to decrease the TTL */ + bcast_packet = (struct bcast_packet *)skb->data; + bcast_packet->ttl--; + skb_reset_mac_header(skb); forw_packet->skb = skb; diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index c483693d5944..ce789a755739 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -30,7 +30,7 @@ #include #include -static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid +static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid * broadcast storms */ static int32_t skb_packets; static int32_t skb_bad_packets; @@ -155,6 +155,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) bcast_packet = (struct bcast_packet *)skb->data; bcast_packet->version = COMPAT_VERSION; + bcast_packet->ttl = TTL; /* batman packet type: broadcast */ bcast_packet->packet_type = BAT_BCAST; @@ -164,7 +165,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN); /* set broadcast sequence number */ - bcast_packet->seqno = htons(bcast_seqno); + bcast_packet->seqno = htonl(bcast_seqno); /* broadcast packet. on success, increase seqno. */ if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK) diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 751cd6322813..d0af4893686a 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -72,11 +72,11 @@ struct orig_node { unsigned long batman_seqno_reset; uint8_t flags; unsigned char *hna_buff; - int16_t hna_buff_len; - uint16_t last_real_seqno; + int16_t hna_buff_len; + uint32_t last_real_seqno; uint8_t last_ttl; TYPE_OF_WORD bcast_bits[NUM_WORDS]; - uint16_t last_bcast_seqno; + uint32_t last_bcast_seqno; struct list_head neigh_list; }; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 7bd553a5cd39..d9ab981d9571 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -357,7 +357,8 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, old_info = hash_find(vis_hash, &search_elem); if (old_info != NULL) { - if (!seq_after(vis_packet->seqno, old_info->packet.seqno)) { + if (!seq_after(ntohl(vis_packet->seqno), + ntohl(old_info->packet.seqno))) { if (old_info->packet.seqno == vis_packet->seqno) { recv_list_add(&old_info->recv_list, vis_packet->sender_orig); @@ -525,7 +526,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) spin_lock_irqsave(&orig_hash_lock, flags); memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); info->packet.ttl = TTL; - info->packet.seqno++; + info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1); info->packet.entries = 0; if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) { -- cgit v1.2.3 From e35fd5ecde2ef0b247a607bc82c4b8f1de06d53b Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 22 Jun 2010 01:25:52 +0200 Subject: Staging: batman-adv: Add bonding functionality This patch introduces bonding functionality to batman-advanced, targeted for the 0.3 release. As we are able to route the payload traffic as we want, we may use multiple interfaces on multihomed hosts to transfer data to achieve higher bandwidth. This can be considered as "light Multi Path Routing" for single hop connections. To detect which interfaces of a peer node belong to the same host, a new flag PRIMARIES_FIRST_HOP is introduced. This flag is set on the first hop of OGMs of the primary (first) interface, which is broadcasted on all interfaces. When receiving such an OGM, we can learn which interfaces belong to the same host (by assigning them to the primary originator). Bonding works by sending packets in a round-robin fashion to the available interfaces of a neighbor host, if multiple interfaces are available. The neighbor interfaces should be almost equally good to reach. To avoid interferences (i.e. sending on the same channel), only neighbor interfaces with different mac addresses and different outgoing interfaces are considered as candidates. Bonding is deactivated by default, and can be activated by echo 1 > /sys/class/net/bat0/mesh/bonding for each individual node. Signed-off-by: Simon Wunderlich [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/bat_sysfs.c | 52 ++++++ drivers/staging/batman-adv/hard-interface.c | 2 +- drivers/staging/batman-adv/main.h | 5 + drivers/staging/batman-adv/originator.c | 8 +- drivers/staging/batman-adv/packet.h | 1 + drivers/staging/batman-adv/routing.c | 238 +++++++++++++++++++++++++--- drivers/staging/batman-adv/routing.h | 3 + drivers/staging/batman-adv/send.c | 4 +- drivers/staging/batman-adv/soft-interface.c | 50 +++--- drivers/staging/batman-adv/types.h | 11 ++ 10 files changed, 320 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index b8ccb7511ef5..4e9c71d5a969 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -84,6 +84,55 @@ static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr, return count; } +static ssize_t show_bond(struct kobject *kobj, struct attribute *attr, + char *buff) +{ + struct device *dev = to_dev(kobj->parent); + struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); + int bond_status = atomic_read(&bat_priv->bonding_enabled); + + return sprintf(buff, "%s\n", + bond_status == 0 ? "disabled" : "enabled"); +} + +static ssize_t store_bond(struct kobject *kobj, struct attribute *attr, + char *buff, size_t count) +{ + struct device *dev = to_dev(kobj->parent); + struct net_device *net_dev = to_net_dev(dev); + struct bat_priv *bat_priv = netdev_priv(net_dev); + int bonding_enabled_tmp = -1; + + if (((count == 2) && (buff[0] == '1')) || + (strncmp(buff, "enable", 6) == 0)) + bonding_enabled_tmp = 1; + + if (((count == 2) && (buff[0] == '0')) || + (strncmp(buff, "disable", 7) == 0)) + bonding_enabled_tmp = 0; + + if (bonding_enabled_tmp < 0) { + if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + printk(KERN_ERR "batman-adv:Invalid parameter for 'bonding' setting on mesh %s received: %s\n", + net_dev->name, buff); + return -EINVAL; + } + + if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp) + return count; + + printk(KERN_INFO "batman-adv:Changing bonding from: %s to: %s on mesh: %s\n", + atomic_read(&bat_priv->bonding_enabled) == 1 ? + "enabled" : "disabled", + bonding_enabled_tmp == 1 ? "enabled" : "disabled", + net_dev->name); + + atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp); + return count; +} + static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -182,12 +231,14 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr, static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR, show_aggr_ogms, store_aggr_ogms); +static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, show_orig_interval, store_orig_interval); static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, + &bat_attr_bonding, &bat_attr_vis_mode, &bat_attr_orig_interval, NULL, @@ -203,6 +254,7 @@ int sysfs_add_meshif(struct net_device *dev) /* FIXME: should be done in the general mesh setup routine as soon as we have it */ atomic_set(&bat_priv->aggregation_enabled, 1); + atomic_set(&bat_priv->bonding_enabled, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->orig_interval, 1000); bat_priv->primary_if = NULL; diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 6939b8d4ec80..f393cc0d744e 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -109,7 +109,7 @@ static void set_primary_if(struct bat_priv *bat_priv, set_main_if_addr(batman_if->net_dev->dev_addr); batman_packet = (struct batman_packet *)(batman_if->packet_buff); - batman_packet->flags = 0; + batman_packet->flags = PRIMARIES_FIRST_HOP; batman_packet->ttl = TTL; /*** diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 145ac5131bf8..fe5ee51357b5 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -59,6 +59,11 @@ #define VIS_INTERVAL 5000 /* 5 seconds */ +/* how much worse secondary interfaces may be to + * to be considered as bonding candidates */ + +#define BONDING_TQ_THRESHOLD 50 + #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or * change the size of * forw_packet->direct_link_flags */ diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 1f6cbe8f8f0b..195c1ee0198a 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -226,6 +226,8 @@ static bool purge_orig_neighbors(struct orig_node *orig_node, static bool purge_orig_node(struct orig_node *orig_node) { + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); struct neigh_node *best_neigh_node; if (time_after(jiffies, @@ -237,10 +239,14 @@ static bool purge_orig_node(struct orig_node *orig_node) orig_node->orig, (orig_node->last_valid / HZ)); return true; } else { - if (purge_orig_neighbors(orig_node, &best_neigh_node)) + if (purge_orig_neighbors(orig_node, &best_neigh_node)) { update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len); + /* update bonding candidates, we could have lost + * some candidates. */ + update_bonding_candidates(bat_priv, orig_node); + } } return false; diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index f0387babfa69..d0d35eabb03f 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h @@ -31,6 +31,7 @@ #define COMPAT_VERSION 11 #define DIRECTLINK 0x40 #define VIS_SERVER 0x20 +#define PRIMARIES_FIRST_HOP 0x10 /* ICMP message types */ #define ECHO_REPLY 0 diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 9dbfabeb9704..6a2c2d18d3f5 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -395,11 +395,132 @@ static char count_real_packets(struct ethhdr *ethhdr, return is_duplicate; } +/* copy primary address for bonding */ +static void mark_bonding_address(struct bat_priv *bat_priv, + struct orig_node *orig_node, + struct orig_node *orig_neigh_node, + struct batman_packet *batman_packet) + +{ + /* don't care if bonding is not enabled */ + if (!atomic_read(&bat_priv->bonding_enabled)) { + orig_node->bond.candidates = 0; + return; + } + + if (batman_packet->flags & PRIMARIES_FIRST_HOP) + memcpy(orig_neigh_node->primary_addr, + orig_node->orig, ETH_ALEN); + + return; +} + +/* mark possible bond.candidates in the neighbor list */ +void update_bonding_candidates(struct bat_priv *bat_priv, + struct orig_node *orig_node) +{ + int candidates; + int interference_candidate; + int best_tq; + struct neigh_node *tmp_neigh_node, *tmp_neigh_node2; + struct neigh_node *first_candidate, *last_candidate; + + /* don't care if bonding is not enabled */ + if (!atomic_read(&bat_priv->bonding_enabled)) { + orig_node->bond.candidates = 0; + return; + } + + /* update the candidates for this originator */ + if (!orig_node->router) { + orig_node->bond.candidates = 0; + return; + } + + best_tq = orig_node->router->tq_avg; + + /* update bond.candidates */ + + candidates = 0; + + /* mark other nodes which also received "PRIMARIES FIRST HOP" packets + * as "bonding partner" */ + + /* first, zero the list */ + list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { + tmp_neigh_node->next_bond_candidate = NULL; + } + + first_candidate = NULL; + last_candidate = NULL; + list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { + + /* only consider if it has the same primary address ... */ + if (memcmp(orig_node->orig, + tmp_neigh_node->orig_node->primary_addr, + ETH_ALEN) != 0) + continue; + + /* ... and is good enough to be considered */ + if (tmp_neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) + continue; + + /* check if we have another candidate with the same + * mac address or interface. If we do, we won't + * select this candidate because of possible interference. */ + + interference_candidate = 0; + list_for_each_entry(tmp_neigh_node2, + &orig_node->neigh_list, list) { + + if (tmp_neigh_node2 == tmp_neigh_node) + continue; + + /* we only care if the other candidate is even + * considered as candidate. */ + if (tmp_neigh_node2->next_bond_candidate == NULL) + continue; + + + if ((tmp_neigh_node->if_incoming == + tmp_neigh_node2->if_incoming) + || (memcmp(tmp_neigh_node->addr, + tmp_neigh_node2->addr, ETH_ALEN) == 0)) { + + interference_candidate = 1; + break; + } + } + /* don't care further if it is an interference candidate */ + if (interference_candidate) + continue; + + if (first_candidate == NULL) { + first_candidate = tmp_neigh_node; + tmp_neigh_node->next_bond_candidate = first_candidate; + } else + tmp_neigh_node->next_bond_candidate = last_candidate; + + last_candidate = tmp_neigh_node; + + candidates++; + } + + if (candidates > 0) { + first_candidate->next_bond_candidate = last_candidate; + orig_node->bond.selected = first_candidate; + } + + orig_node->bond.candidates = candidates; +} + void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming) { + /* FIXME: each orig_node->batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); struct batman_if *batman_if; struct orig_node *orig_neigh_node, *orig_node; char has_directlink_flag; @@ -577,6 +698,10 @@ void receive_bat_packet(struct ethhdr *ethhdr, update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate); + mark_bonding_address(bat_priv, orig_node, + orig_neigh_node, batman_packet); + update_bonding_candidates(bat_priv, orig_node); + /* is single hop (direct) neighbor */ if (is_single_hop_neigh) { @@ -859,16 +984,75 @@ int recv_icmp_packet(struct sk_buff *skb) return ret; } +/* find a suitable router for this originator, and use + * bonding if possible. */ +struct neigh_node *find_router(struct orig_node *orig_node) +{ + /* FIXME: each orig_node->batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); + struct orig_node *primary_orig_node; + struct orig_node *router_orig; + struct neigh_node *router; + static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; + + if (!orig_node) + return NULL; + + if (!orig_node->router) + return NULL; + + /* don't care if bonding is not enabled */ + if (!atomic_read(&bat_priv->bonding_enabled)) + return orig_node->router; + + router_orig = orig_node->router->orig_node; + + /* if we have something in the primary_addr, we can search + * for a potential bonding candidate. */ + if (memcmp(router_orig->primary_addr, zero_mac, ETH_ALEN) == 0) + return orig_node->router; + + /* find the orig_node which has the primary interface. might + * even be the same as our router_orig in many cases */ + + if (memcmp(router_orig->primary_addr, + router_orig->orig, ETH_ALEN) == 0) { + primary_orig_node = router_orig; + } else { + primary_orig_node = hash_find(orig_hash, + router_orig->primary_addr); + if (!primary_orig_node) + return orig_node->router; + } + + /* with less than 2 candidates, we can't do any + * bonding and prefer the original router. */ + + if (primary_orig_node->bond.candidates < 2) + return orig_node->router; + + router = primary_orig_node->bond.selected; + + /* sanity check - this should never happen. */ + if (!router) + return orig_node->router; + + /* select the next bonding partner ... */ + primary_orig_node->bond.selected = router->next_bond_candidate; + + return router; +} + int recv_unicast_packet(struct sk_buff *skb) { struct unicast_packet *unicast_packet; struct orig_node *orig_node; + struct neigh_node *router; struct ethhdr *ethhdr; struct batman_if *batman_if; struct sk_buff *skb_old; uint8_t dstaddr[ETH_ALEN]; int hdr_size = sizeof(struct unicast_packet); - int ret; unsigned long flags; /* drop packet if it has not necessary minimum size */ @@ -906,42 +1090,44 @@ int recv_unicast_packet(struct sk_buff *skb) return NET_RX_DROP; } - ret = NET_RX_DROP; /* get routing information */ spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, unicast_packet->dest)); - if ((orig_node != NULL) && - (orig_node->router != NULL)) { + router = find_router(orig_node); - /* don't lock while sending the packets ... we therefore - * copy the required data before sending */ - batman_if = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + if (!router) { spin_unlock_irqrestore(&orig_hash_lock, flags); + return NET_RX_DROP; + } - /* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - unicast_packet = (struct unicast_packet *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } - /* decrement ttl */ - unicast_packet->ttl--; + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ - /* route it */ - send_skb_packet(skb, batman_if, dstaddr); - ret = NET_RX_SUCCESS; + batman_if = router->if_incoming; + memcpy(dstaddr, router->addr, ETH_ALEN); - } else - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&orig_hash_lock, flags); - return ret; + /* create a copy of the skb, if needed, to modify it. */ + if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { + skb_old = skb; + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + unicast_packet = (struct unicast_packet *) skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb); + kfree_skb(skb_old); + } + + /* decrement ttl */ + unicast_packet->ttl--; + + /* route it */ + send_skb_packet(skb, batman_if, dstaddr); + + return NET_RX_SUCCESS; } int recv_bcast_packet(struct sk_buff *skb) diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index c6850d26779c..0e33d227cf19 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -35,3 +35,6 @@ int recv_bcast_packet(struct sk_buff *skb); int recv_vis_packet(struct sk_buff *skb); int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if); +struct neigh_node *find_router(struct orig_node *orig_node); +void update_bonding_candidates(struct bat_priv *bat_priv, + struct orig_node *orig_node); diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index f2653dd37c07..e61a62c6cb9a 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -287,7 +287,7 @@ void schedule_own_packet(struct batman_if *batman_if) htonl((uint32_t)atomic_read(&batman_if->seqno)); if (vis_server == VIS_TYPE_SERVER_SYNC) - batman_packet->flags = VIS_SERVER; + batman_packet->flags |= VIS_SERVER; else batman_packet->flags &= ~VIS_SERVER; @@ -349,6 +349,8 @@ void schedule_forward_packet(struct orig_node *orig_node, batman_packet->seqno = htonl(batman_packet->seqno); + /* switch of primaries first hop flag when forwarding */ + batman_packet->flags &= ~PRIMARIES_FIRST_HOP; if (directlink) batman_packet->flags |= DIRECTLINK; else diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index ce789a755739..37fd56565ca5 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -22,6 +22,7 @@ #include "main.h" #include "soft-interface.h" #include "hard-interface.h" +#include "routing.h" #include "send.h" #include "translation-table.h" #include "types.h" @@ -129,6 +130,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) struct unicast_packet *unicast_packet; struct bcast_packet *bcast_packet; struct orig_node *orig_node; + struct neigh_node *router; struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct bat_priv *priv = netdev_priv(dev); struct batman_if *batman_if; @@ -186,38 +188,36 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) if (!orig_node) orig_node = transtable_search(ethhdr->h_dest); - if ((orig_node) && - (orig_node->router)) { - struct neigh_node *router = orig_node->router; + router = find_router(orig_node); - if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) - goto unlock; + if (!router) + goto unlock; + + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + + batman_if = router->if_incoming; + memcpy(dstaddr, router->addr, ETH_ALEN); - unicast_packet = (struct unicast_packet *)skb->data; + spin_unlock_irqrestore(&orig_hash_lock, flags); - unicast_packet->version = COMPAT_VERSION; - /* batman packet type: unicast */ - unicast_packet->packet_type = BAT_UNICAST; - /* set unicast ttl */ - unicast_packet->ttl = TTL; - /* copy the destination for faster routing */ - memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); + if (batman_if->if_status != IF_ACTIVE) + goto dropped; - /* net_dev won't be available when not active */ - if (router->if_incoming->if_status != IF_ACTIVE) - goto unlock; + if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) + goto dropped; - /* don't lock while sending the packets ... we therefore - * copy the required data before sending */ + unicast_packet = (struct unicast_packet *)skb->data; - batman_if = router->if_incoming; - memcpy(dstaddr, router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + unicast_packet->version = COMPAT_VERSION; + /* batman packet type: unicast */ + unicast_packet->packet_type = BAT_UNICAST; + /* set unicast ttl */ + unicast_packet->ttl = TTL; + /* copy the destination for faster routing */ + memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); - send_skb_packet(skb, batman_if, dstaddr); - } else { - goto unlock; - } + send_skb_packet(skb, batman_if, dstaddr); } priv->stats.tx_packets++; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index d0af4893686a..84c3f43c4ac9 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -52,6 +52,7 @@ struct batman_if { /** * orig_node - structure for orig_list maintaining nodes of mesh + * @primary_addr: hosts primary interface address * @last_valid: when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset * @batman_seqno_reset: time when the batman seqno window was reset @@ -59,9 +60,13 @@ struct batman_if { * @last_real_seqno: last and best known squence number * @last_ttl: ttl of last received packet * @last_bcast_seqno: last broadcast sequence number received by this host + * + * @candidates: how many candidates are available + * @selected: next bonding candidate */ struct orig_node { uint8_t orig[ETH_ALEN]; + uint8_t primary_addr[ETH_ALEN]; struct neigh_node *router; TYPE_OF_WORD *bcast_own; uint8_t *bcast_own_sum; @@ -78,6 +83,10 @@ struct orig_node { TYPE_OF_WORD bcast_bits[NUM_WORDS]; uint32_t last_bcast_seqno; struct list_head neigh_list; + struct { + uint8_t candidates; + struct neigh_node *selected; + } bond; }; /** @@ -92,6 +101,7 @@ struct neigh_node { uint8_t tq_index; uint8_t tq_avg; uint8_t last_ttl; + struct neigh_node *next_bond_candidate; unsigned long last_valid; TYPE_OF_WORD real_bits[NUM_WORDS]; struct orig_node *orig_node; @@ -101,6 +111,7 @@ struct neigh_node { struct bat_priv { struct net_device_stats stats; atomic_t aggregation_enabled; + atomic_t bonding_enabled; atomic_t vis_mode; atomic_t orig_interval; char num_ifaces; -- cgit v1.2.3 From 11f79decfd4e33e29694075a859f529e6d4321ad Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 22 Jun 2010 01:25:53 +0200 Subject: Staging: batman-adv: bonding and interface alternating This patch adds interface alternating to the new bonding feature. By default, we now try to avoid forwarding packets on the receiving interface, instead choosing alternative interfaces. This feature works only on nodes which have multiple interfaces connected to the mesh. This approach should reduce problems of the half-duplex nature of WiFi Hardware and thus increase performance. Signed-off-by: Simon Wunderlich Acked-by: Marek Lindner [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/hard-interface.c | 2 +- drivers/staging/batman-adv/routing.c | 72 +++++++++++++++++++---------- drivers/staging/batman-adv/routing.h | 5 +- drivers/staging/batman-adv/soft-interface.c | 2 +- 4 files changed, 52 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index f393cc0d744e..5f8213786eaf 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -512,7 +512,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, /* unicast packet */ case BAT_UNICAST: - ret = recv_unicast_packet(skb); + ret = recv_unicast_packet(skb, batman_if); break; /* broadcast packet */ diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 6a2c2d18d3f5..048795e319a8 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -402,12 +402,6 @@ static void mark_bonding_address(struct bat_priv *bat_priv, struct batman_packet *batman_packet) { - /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) { - orig_node->bond.candidates = 0; - return; - } - if (batman_packet->flags & PRIMARIES_FIRST_HOP) memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); @@ -425,12 +419,6 @@ void update_bonding_candidates(struct bat_priv *bat_priv, struct neigh_node *tmp_neigh_node, *tmp_neigh_node2; struct neigh_node *first_candidate, *last_candidate; - /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) { - orig_node->bond.candidates = 0; - return; - } - /* update the candidates for this originator */ if (!orig_node->router) { orig_node->bond.candidates = 0; @@ -986,14 +974,16 @@ int recv_icmp_packet(struct sk_buff *skb) /* find a suitable router for this originator, and use * bonding if possible. */ -struct neigh_node *find_router(struct orig_node *orig_node) +struct neigh_node *find_router(struct orig_node *orig_node, + struct batman_if *recv_if) { /* FIXME: each orig_node->batman_if will be attached to a softif */ struct bat_priv *bat_priv = netdev_priv(soft_device); struct orig_node *primary_orig_node; struct orig_node *router_orig; - struct neigh_node *router; + struct neigh_node *router, *first_candidate, *best_router; static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; + int bonding_enabled; if (!orig_node) return NULL; @@ -1001,9 +991,12 @@ struct neigh_node *find_router(struct orig_node *orig_node) if (!orig_node->router) return NULL; - /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) - return orig_node->router; + /* without bonding, the first node should + * always choose the default router. */ + + bonding_enabled = atomic_read(&bat_priv->bonding_enabled); + if (!bonding_enabled && (recv_if == NULL)) + return orig_node->router; router_orig = orig_node->router->orig_node; @@ -1031,19 +1024,48 @@ struct neigh_node *find_router(struct orig_node *orig_node) if (primary_orig_node->bond.candidates < 2) return orig_node->router; - router = primary_orig_node->bond.selected; - /* sanity check - this should never happen. */ - if (!router) - return orig_node->router; + /* all nodes between should choose a candidate which + * is is not on the interface where the packet came + * in. */ + first_candidate = primary_orig_node->bond.selected; + router = first_candidate; + + if (bonding_enabled) { + /* in the bonding case, send the packets in a round + * robin fashion over the remaining interfaces. */ + do { + /* recv_if == NULL on the first node. */ + if (router->if_incoming != recv_if) + break; + + router = router->next_bond_candidate; + } while (router != first_candidate); + + primary_orig_node->bond.selected = router->next_bond_candidate; - /* select the next bonding partner ... */ - primary_orig_node->bond.selected = router->next_bond_candidate; + } else { + /* if bonding is disabled, use the best of the + * remaining candidates which are not using + * this interface. */ + best_router = first_candidate; + + do { + /* recv_if == NULL on the first node. */ + if ((router->if_incoming != recv_if) && + (router->tq_avg > best_router->tq_avg)) + best_router = router; + + router = router->next_bond_candidate; + } while (router != first_candidate); + + router = best_router; + } return router; } -int recv_unicast_packet(struct sk_buff *skb) +int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) { struct unicast_packet *unicast_packet; struct orig_node *orig_node; @@ -1095,7 +1117,7 @@ int recv_unicast_packet(struct sk_buff *skb) orig_node = ((struct orig_node *) hash_find(orig_hash, unicast_packet->dest)); - router = find_router(orig_node); + router = find_router(orig_node, recv_if); if (!router) { spin_unlock_irqrestore(&orig_hash_lock, flags); diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 0e33d227cf19..43387a2a3324 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -30,11 +30,12 @@ void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len); int recv_icmp_packet(struct sk_buff *skb); -int recv_unicast_packet(struct sk_buff *skb); +int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb); int recv_vis_packet(struct sk_buff *skb); int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if); -struct neigh_node *find_router(struct orig_node *orig_node); +struct neigh_node *find_router(struct orig_node *orig_node, + struct batman_if *recv_if); void update_bonding_candidates(struct bat_priv *bat_priv, struct orig_node *orig_node); diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 37fd56565ca5..ef7860d53a5c 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -188,7 +188,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) if (!orig_node) orig_node = transtable_search(ethhdr->h_dest); - router = find_router(orig_node); + router = find_router(orig_node, NULL); if (!router) goto unlock; -- cgit v1.2.3 From e4cb3720bfcf8b57b4c5a2adbbb6b5967af53432 Mon Sep 17 00:00:00 2001 From: Daniel Seither Date: Tue, 22 Jun 2010 01:25:54 +0200 Subject: Staging: batman-adv: record route for ICMP messages The standard layer 3 ping utility can use the record route (RR) option of IP to collect route data for sent ping messages (ping -R). This patch introduces comparable functionality for batman-adv ICMP messages. The patch adds a second batman ICMP packet format (icmp_packet_rr) such that up to 17 MAC addresses can be recorded (sufficient for up to 8 hops per direction). When no RR is wanted, the old icmp_packet without the RR overhead can be sent. Signed-off-by: Daniel Seither Signed-off-by: Marek Lindner [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/icmp_socket.c | 45 +++++++++++++++++++------------- drivers/staging/batman-adv/icmp_socket.h | 3 ++- drivers/staging/batman-adv/packet.h | 17 ++++++++++++ drivers/staging/batman-adv/routing.c | 43 +++++++++++++++++++----------- drivers/staging/batman-adv/types.h | 3 ++- 5 files changed, 76 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index d4411cbe350c..08a5f7b7b11b 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -32,7 +32,8 @@ static struct socket_client *socket_client_hash[256]; static void bat_socket_add_packet(struct socket_client *socket_client, - struct icmp_packet *icmp_packet); + struct icmp_packet_rr *icmp_packet, + size_t icmp_len); void bat_socket_init(void) { @@ -110,6 +111,7 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, struct socket_client *socket_client = (struct socket_client *)file->private_data; struct socket_packet *socket_packet; + size_t packet_len; int error; unsigned long flags; @@ -138,14 +140,15 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, spin_unlock_irqrestore(&socket_client->lock, flags); error = __copy_to_user(buf, &socket_packet->icmp_packet, - sizeof(struct icmp_packet)); + socket_packet->icmp_len); + packet_len = socket_packet->icmp_len; kfree(socket_packet); if (error) return -EFAULT; - return sizeof(struct icmp_packet); + return packet_len; } static ssize_t bat_socket_write(struct file *file, const char __user *buff, @@ -153,9 +156,10 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, { struct socket_client *socket_client = (struct socket_client *)file->private_data; - struct icmp_packet icmp_packet; + struct icmp_packet_rr icmp_packet; struct orig_node *orig_node; struct batman_if *batman_if; + size_t packet_len = sizeof(struct icmp_packet); uint8_t dstaddr[ETH_ALEN]; unsigned long flags; @@ -166,10 +170,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, return -EINVAL; } - if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) + if (len >= sizeof(struct icmp_packet_rr)) + packet_len = sizeof(struct icmp_packet_rr); + + if (!access_ok(VERIFY_READ, buff, packet_len)) return -EFAULT; - if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) + if (__copy_from_user(&icmp_packet, buff, packet_len)) return -EFAULT; if (icmp_packet.packet_type != BAT_ICMP) { @@ -191,7 +198,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (icmp_packet.version != COMPAT_VERSION) { icmp_packet.msg_type = PARAMETER_PROBLEM; icmp_packet.ttl = COMPAT_VERSION; - bat_socket_add_packet(socket_client, &icmp_packet); + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); goto out; } @@ -218,13 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (batman_if->if_status != IF_ACTIVE) goto dst_unreach; - memcpy(icmp_packet.orig, - batman_if->net_dev->dev_addr, - ETH_ALEN); + memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); + + if (packet_len == sizeof(struct icmp_packet_rr)) + memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); send_raw_packet((unsigned char *)&icmp_packet, - sizeof(struct icmp_packet), - batman_if, dstaddr); + packet_len, batman_if, dstaddr); goto out; @@ -232,7 +239,7 @@ unlock: spin_unlock_irqrestore(&orig_hash_lock, flags); dst_unreach: icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_socket_add_packet(socket_client, &icmp_packet); + bat_socket_add_packet(socket_client, &icmp_packet, packet_len); out: return len; } @@ -278,7 +285,8 @@ err: } static void bat_socket_add_packet(struct socket_client *socket_client, - struct icmp_packet *icmp_packet) + struct icmp_packet_rr *icmp_packet, + size_t icmp_len) { struct socket_packet *socket_packet; unsigned long flags; @@ -289,8 +297,8 @@ static void bat_socket_add_packet(struct socket_client *socket_client, return; INIT_LIST_HEAD(&socket_packet->list); - memcpy(&socket_packet->icmp_packet, icmp_packet, - sizeof(struct icmp_packet)); + memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len); + socket_packet->icmp_len = icmp_len; spin_lock_irqsave(&socket_client->lock, flags); @@ -319,10 +327,11 @@ static void bat_socket_add_packet(struct socket_client *socket_client, wake_up(&socket_client->queue_wait); } -void bat_socket_receive_packet(struct icmp_packet *icmp_packet) +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len) { struct socket_client *hash = socket_client_hash[icmp_packet->uid]; if (hash) - bat_socket_add_packet(hash, icmp_packet); + bat_socket_add_packet(hash, icmp_packet, icmp_len); } diff --git a/drivers/staging/batman-adv/icmp_socket.h b/drivers/staging/batman-adv/icmp_socket.h index 5ad73daa08ca..2dc954ac91ba 100644 --- a/drivers/staging/batman-adv/icmp_socket.h +++ b/drivers/staging/batman-adv/icmp_socket.h @@ -25,4 +25,5 @@ void bat_socket_init(void); int bat_socket_setup(struct bat_priv *bat_priv); -void bat_socket_receive_packet(struct icmp_packet *icmp_packet); +void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, + size_t icmp_len); diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index d0d35eabb03f..8a044186c20f 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h @@ -69,6 +69,23 @@ struct icmp_packet { uint8_t uid; } __attribute__((packed)); +#define BAT_RR_LEN 16 + +/* icmp_packet_rr must start with all fields from imcp_packet + as this is assumed by code that handles ICMP packets */ +struct icmp_packet_rr { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t msg_type; /* see ICMP message types above */ + uint8_t ttl; + uint8_t dst[6]; + uint8_t orig[6]; + uint16_t seqno; + uint8_t uid; + uint8_t rr_cur; + uint8_t rr[BAT_RR_LEN][ETH_ALEN]; +} __attribute__((packed)); + struct unicast_packet { uint8_t packet_type; uint8_t version; /* batman version field */ diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 048795e319a8..acd8f745ebc0 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -765,10 +765,10 @@ int recv_bat_packet(struct sk_buff *skb, return NET_RX_SUCCESS; } -static int recv_my_icmp_packet(struct sk_buff *skb) +static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) { struct orig_node *orig_node; - struct icmp_packet *icmp_packet; + struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct sk_buff *skb_old; struct batman_if *batman_if; @@ -776,12 +776,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb) unsigned long flags; uint8_t dstaddr[ETH_ALEN]; - icmp_packet = (struct icmp_packet *)skb->data; + icmp_packet = (struct icmp_packet_rr *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { - bat_socket_receive_packet(icmp_packet); + bat_socket_receive_packet(icmp_packet, icmp_len); return NET_RX_DROP; } @@ -803,13 +803,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb) /* create a copy of the skb, if needed, to modify it. */ skb_old = NULL; - if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + if (!skb_clone_writable(skb, icmp_len)) { skb_old = skb; skb = skb_copy(skb, GFP_ATOMIC); if (!skb) return NET_RX_DROP; - - icmp_packet = (struct icmp_packet *)skb->data; + icmp_packet = (struct icmp_packet_rr *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb); kfree_skb(skb_old); } @@ -828,7 +827,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb) return ret; } -static int recv_icmp_ttl_exceeded(struct sk_buff *skb) +static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) { struct orig_node *orig_node; struct icmp_packet *icmp_packet; @@ -867,7 +866,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb) spin_unlock_irqrestore(&orig_hash_lock, flags); /* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + if (!skb_clone_writable(skb, icmp_len)) { skb_old = skb; skb = skb_copy(skb, GFP_ATOMIC); if (!skb) @@ -894,7 +893,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb) int recv_icmp_packet(struct sk_buff *skb) { - struct icmp_packet *icmp_packet; + struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct orig_node *orig_node; struct sk_buff *skb_old; @@ -904,6 +903,12 @@ int recv_icmp_packet(struct sk_buff *skb) unsigned long flags; uint8_t dstaddr[ETH_ALEN]; + /** + * we truncate all incoming icmp packets if they don't match our size + */ + if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr)) + hdr_size = sizeof(struct icmp_packet_rr); + /* drop packet if it has not necessary minimum size */ if (skb_headlen(skb) < hdr_size) return NET_RX_DROP; @@ -922,15 +927,23 @@ int recv_icmp_packet(struct sk_buff *skb) if (!is_my_mac(ethhdr->h_dest)) return NET_RX_DROP; - icmp_packet = (struct icmp_packet *)skb->data; + icmp_packet = (struct icmp_packet_rr *)skb->data; + + /* add record route information if not full */ + if ((hdr_size == sizeof(struct icmp_packet_rr)) && + (icmp_packet->rr_cur < BAT_RR_LEN)) { + memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), + ethhdr->h_dest, ETH_ALEN); + icmp_packet->rr_cur++; + } /* packet for me */ if (is_my_mac(icmp_packet->dst)) - return recv_my_icmp_packet(skb); + return recv_my_icmp_packet(skb, hdr_size); /* TTL exceeded */ if (icmp_packet->ttl < 2) - return recv_icmp_ttl_exceeded(skb); + return recv_icmp_ttl_exceeded(skb, hdr_size); ret = NET_RX_DROP; @@ -949,12 +962,12 @@ int recv_icmp_packet(struct sk_buff *skb) spin_unlock_irqrestore(&orig_hash_lock, flags); /* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + if (!skb_clone_writable(skb, hdr_size)) { skb_old = skb; skb = skb_copy(skb, GFP_ATOMIC); if (!skb) return NET_RX_DROP; - icmp_packet = (struct icmp_packet *)skb->data; + icmp_packet = (struct icmp_packet_rr *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb); kfree_skb(skb_old); } diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 84c3f43c4ac9..e1fc4605772f 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -130,7 +130,8 @@ struct socket_client { struct socket_packet { struct list_head list; - struct icmp_packet icmp_packet; + size_t icmp_len; + struct icmp_packet_rr icmp_packet; }; struct hna_local_entry { -- cgit v1.2.3 From acf82e050150490e7a2d795594b2c6cb54243bfd Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Thu, 17 Jun 2010 13:10:33 -0400 Subject: Staging: xgifb: use %lx instead of %x in printk format This fixes compiler warning format '%x' expects type 'unsigned int', but argument 2 has type 'long unsigned int' Signed-off-by: Bill Pemberton Cc: Arnaud Patard Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 68bc1d839ad6..4d8dadd17d93 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -3510,7 +3510,8 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) XGIfb_registered = 1; - printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO); + printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n", + XGIFB_GET_INFO); /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n", XGIfb_accel ? "enabled" : "disabled", -- cgit v1.2.3 From 23aada9cc34759352e9a82c1a157d0e1ba3712bc Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Thu, 17 Jun 2010 13:10:34 -0400 Subject: Staging: xgifb: remove use of LINUX_VERSION_CODE Remove ifdefs that check LINUX_VERSION_CODE as this is not needed in the staging tree. Signed-off-by: Bill Pemberton Cc: Arnaud Patard Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_accel.c | 212 ------------------------------------ drivers/staging/xgifb/XGI_accel.h | 14 +-- drivers/staging/xgifb/XGI_main.h | 113 +------------------ drivers/staging/xgifb/XGI_main_26.c | 29 +---- drivers/staging/xgifb/vb_ext.c | 5 - drivers/staging/xgifb/vb_setmode.c | 5 - 6 files changed, 3 insertions(+), 375 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c index 86ec3421942f..24f454d93772 100644 --- a/drivers/staging/xgifb/XGI_accel.c +++ b/drivers/staging/xgifb/XGI_accel.c @@ -37,27 +37,12 @@ #include #include -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include -#else -#include