static int nvd0_disp_base_init(struct nouveau_object *object) { struct nv50_disp_priv *priv = (void *)object->engine; struct nv50_disp_base *base = (void *)object; int ret, i; u32 tmp; ret = nouveau_parent_init(&base->base); if (ret) return ret; /* The below segments of code copying values from one register to * another appear to inform EVO of the display capabilities or * something similar. */ /* ... CRTC caps */ for (i = 0; i < priv->head.nr; i++) { tmp = nv_rd32(priv, 0x616104 + (i * 0x800)); nv_wr32(priv, 0x6101b4 + (i * 0x800), tmp); tmp = nv_rd32(priv, 0x616108 + (i * 0x800)); nv_wr32(priv, 0x6101b8 + (i * 0x800), tmp); tmp = nv_rd32(priv, 0x61610c + (i * 0x800)); nv_wr32(priv, 0x6101bc + (i * 0x800), tmp); } /* ... DAC caps */ for (i = 0; i < priv->dac.nr; i++) { tmp = nv_rd32(priv, 0x61a000 + (i * 0x800)); nv_wr32(priv, 0x6101c0 + (i * 0x800), tmp); } /* ... SOR caps */ for (i = 0; i < priv->sor.nr; i++) { tmp = nv_rd32(priv, 0x61c000 + (i * 0x800)); nv_wr32(priv, 0x6301c4 + (i * 0x800), tmp); } /* steal display away from vbios, or something like that */ if (nv_rd32(priv, 0x6100ac) & 0x00000100) { nv_wr32(priv, 0x6100ac, 0x00000100); nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000); if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) { nv_error(priv, "timeout acquiring display\n"); return -EBUSY; } } /* point at display engine memory area (hash table, objects) */ nv_wr32(priv, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9); /* enable supervisor interrupts, disable everything else */ nv_wr32(priv, 0x610090, 0x00000000); nv_wr32(priv, 0x6100a0, 0x00000000); nv_wr32(priv, 0x6100b0, 0x00000307); return 0; }
u32 nv50_display_active_crtcs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; u32 mask = 0; int i; if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) { for (i = 0; i < 2; i++) mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); } else { for (i = 0; i < 4; i++) mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); } for (i = 0; i < 3; i++) mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); return mask & 3; }
static u32 read_pll_1(struct nouveau_device *device, u32 reg) { u32 ctrl = nv_rd32(device, reg + 0x00); int P = (ctrl & 0x00070000) >> 16; int N = (ctrl & 0x0000ff00) >> 8; int M = (ctrl & 0x000000ff) >> 0; u32 ref = 27000, clk = 0; if (ctrl & 0x80000000) clk = ref * N / M; return clk >> P; }
static void gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) { nv_mask(priv, 0x137250, 0x3f, 0); nv_mask(priv, 0x000200, 0x20, 0); usleep_range(20, 30); nv_mask(priv, 0x000200, 0x20, 0x20); nv_wr32(priv, 0x12004c, 0x4); nv_wr32(priv, 0x122204, 0x2); nv_rd32(priv, 0x122204); }
int nvc0_vram_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; uint32_t ctrlr_num, ctrlr_amt; dev_priv->vram = kzalloc (sizeof *dev_priv->vram, GFP_KERNEL); if (!dev_priv->vram) { NV_ERROR(dev, "VRAM: out ot memory\n"); return -ENOMEM; } dev_priv->vram->alloc = nvc0_vram_alloc; dev_priv->vram->free = pscnv_vram_free; dev_priv->vram->takedown = pscnv_vram_takedown; ctrlr_num = nv_rd32(dev, NVC0_MEM_CTRLR_COUNT); ctrlr_amt = nv_rd32(dev, NVC0_MEM_CTRLR_RAM_AMOUNT); dev_priv->vram_size = ctrlr_num * (ctrlr_amt << 20); if (!dev_priv->vram_size) { NV_ERROR(dev, "No VRAM detected, aborting.\n"); return -ENODEV; } NV_INFO(dev, "VRAM: size 0x%llx, %d controllers\n", dev_priv->vram_size, ctrlr_num); ret = pscnv_mm_init(dev, 0x40000, dev_priv->vram_size - 0x20000, 0x1000, 0x20000, 0x1000, &dev_priv->vram_mm); if (ret) { kfree(dev_priv->vram); return ret; } return 0; }
static void gk104_pwr_pgob(struct nouveau_pwr *ppwr, bool enable) { nv_mask(ppwr, 0x000200, 0x00001000, 0x00000000); nv_rd32(ppwr, 0x000200); nv_mask(ppwr, 0x000200, 0x08000000, 0x08000000); msleep(50); nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000002); nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001); nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000); nv_mask(ppwr, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000); msleep(50); nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000000); nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001); nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000); nv_mask(ppwr, 0x000200, 0x08000000, 0x00000000); nv_mask(ppwr, 0x000200, 0x00001000, 0x00001000); nv_rd32(ppwr, 0x000200); }
static int nv10_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; u32 cfg0 = nv_rd32(pfb, 0x100200); int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; if (cfg0 & 0x00000001) ram->type = NV_MEM_TYPE_DDR1; else ram->type = NV_MEM_TYPE_SDRAM; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; return 0; }
static void nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) { struct dcb_output outp; u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); if (conf != ~0) { u32 addr, data; if (outp.type == DCB_OUTPUT_DP) { u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); switch ((sync & 0x000003c0) >> 6) { case 6: pclk = pclk * 30 / 8; break; case 5: pclk = pclk * 24 / 8; break; case 2: default: pclk = pclk * 18 / 8; break; } nouveau_dp_train(&priv->base, priv->sor.dp, &outp, head, pclk); }
static u32 read_pll_2(struct nouveau_device *device, u32 reg) { u32 ctrl = nv_rd32(device, reg + 0x00); u32 coef = nv_rd32(device, reg + 0x04); int N2 = (coef & 0xff000000) >> 24; int M2 = (coef & 0x00ff0000) >> 16; int N1 = (coef & 0x0000ff00) >> 8; int M1 = (coef & 0x000000ff) >> 0; int P = (ctrl & 0x00070000) >> 16; u32 ref = 27000, clk = 0; if ((ctrl & 0x80000000) && M1) { clk = ref * N1 / M1; if ((ctrl & 0x40000100) == 0x40000000) { if (M2) clk = clk * N2 / M2; else clk = 0; } } return clk >> P; }
static u64 nv98_devinit_disable(struct nouveau_devinit *devinit) { struct nv50_devinit_priv *priv = (void *)devinit; u32 r001540 = nv_rd32(priv, 0x001540); u32 r00154c = nv_rd32(priv, 0x00154c); u64 disable = 0ULL; if (!(r001540 & 0x40000000)) { disable |= (1ULL << NVDEV_ENGINE_VP); disable |= (1ULL << NVDEV_ENGINE_BSP); disable |= (1ULL << NVDEV_ENGINE_PPP); } if (!(r00154c & 0x00000004)) disable |= (1ULL << NVDEV_ENGINE_DISP); if (!(r00154c & 0x00000020)) disable |= (1ULL << NVDEV_ENGINE_BSP); if (!(r00154c & 0x00000040)) disable |= (1ULL << NVDEV_ENGINE_CRYPT); return disable; }
void gf100_ltc_intr(struct nvkm_subdev *subdev) { struct nvkm_ltc_priv *priv = (void *)subdev; u32 mask; mask = nv_rd32(priv, 0x00017c); while (mask) { u32 lts, ltc = __ffs(mask); for (lts = 0; lts < priv->lts_nr; lts++) gf100_ltc_lts_intr(priv, ltc, lts); mask &= ~(1 << ltc); } }
int nv40_temp_get(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; int offset = sensor->offset_mult / sensor->offset_div; int core_temp; if (dev_priv->chipset >= 0x50) { core_temp = nv_rd32(dev, 0x20008); } else { core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; /* Setup the sensor if the temperature is 0 */ if (core_temp == 0) core_temp = nv40_sensor_setup(dev); } core_temp = core_temp * sensor->slope_mult / sensor->slope_div; core_temp = core_temp + offset + sensor->offset_constant; return core_temp; }
static void nv41_vm_flush(struct nouveau_vm *vm) { struct nv04_vm_priv *priv = (void *)vm->vmm; mutex_lock(&nv_subdev(priv)->mutex); nv_wr32(priv, 0x100810, 0x00000022); if (!nv_wait(priv, 0x100810, 0x00000020, 0x00000020)) { nv_warn(priv, "flush timeout, 0x%08x\n", nv_rd32(priv, 0x100810)); } nv_wr32(priv, 0x100810, 0x00000000); mutex_unlock(&nv_subdev(priv)->mutex); }
static void nv50_sor_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); uint32_t val; int or = nv_encoder->or; NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); /* wait for it to be done */ if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); } val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); if (mode == DRM_MODE_DPMS_ON) val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; else val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or), NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); } if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON) nv50_sor_dp_link_train(encoder); }
irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = arg; struct nouveau_device *device = nouveau_dev(dev); struct nouveau_mc *pmc = nouveau_mc(device); u32 stat; stat = nv_rd32(device, 0x000100); if (stat == 0 || stat == ~0) return IRQ_NONE; nv_subdev(pmc)->intr(nv_subdev(pmc)); return IRQ_HANDLED; }
static int nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nvc0_ltcg_priv *priv; struct nouveau_fb *pfb = nouveau_fb(parent); u32 parts, mask; int ret, i; ret = nouveau_ltcg_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; parts = nv_rd32(priv, 0x022438); mask = nv_rd32(priv, 0x022554); for (i = 0; i < parts; i++) { if (!(mask & (1 << i))) priv->part_nr++; } priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ ret = nvc0_ltcg_init_tag_ram(pfb, priv); if (ret) return ret; priv->base.tags_alloc = nvc0_ltcg_tags_alloc; priv->base.tags_free = nvc0_ltcg_tags_free; priv->base.tags_clear = nvc0_ltcg_tags_clear; nv_subdev(priv)->intr = nvc0_ltcg_intr; return 0; }
static void gf100_ltc_lts_intr(struct nvkm_ltc_priv *priv, int ltc, int lts) { u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400); u32 intr = nv_rd32(priv, base + 0x020); u32 stat = intr & 0x0000ffff; if (stat) { nv_info(priv, "LTC%d_LTS%d:", ltc, lts); nvkm_bitfield_print(gf100_ltc_lts_intr_name, stat); pr_cont("\n"); } nv_wr32(priv, base + 0x020, intr); }
static void nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) { u32 ustat = nv_rd32(priv, 0x409c18); if (ustat & 0x00000001) nv_error(priv, "CTXCTRL ucode error\n"); if (ustat & 0x00080000) nv_error(priv, "CTXCTRL watchdog timeout\n"); if (ustat & ~0x00080001) nv_error(priv, "CTXCTRL 0x%08x\n", ustat); nvc0_graph_ctxctl_debug(priv); nv_wr32(priv, 0x409c20, ustat); }
void nv94_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) { u32 temp = nv_rd32(i2c, 0x00e068), i; for (i = 0; i < 8; i++) { if (mask & (1 << i)) { if (!(data & (1 << i))) { temp &= ~(type << (i * 4)); continue; } temp |= type << (i * 4); } } nv_wr32(i2c, 0x00e068, temp); }
static int nv50_disp_mast_init(struct nouveau_object *object) { struct nv50_disp_priv *priv = (void *)object->engine; struct nv50_disp_dmac *mast = (void *)object; int ret; ret = nv50_disp_chan_init(&mast->base); if (ret) return ret; /* enable error reporting */ nv_mask(priv, 0x610028, 0x00010001, 0x00010001); /* attempt to unstick channel from some unknown state */ if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000) nv_mask(priv, 0x610200, 0x00800000, 0x00800000); if ((nv_rd32(priv, 0x610200) & 0x003f0000) == 0x00030000) nv_mask(priv, 0x610200, 0x00600000, 0x00600000); /* initialise channel for dma command submission */ nv_wr32(priv, 0x610204, mast->push); nv_wr32(priv, 0x610208, 0x00010000); nv_wr32(priv, 0x61020c, 0x00000000); nv_mask(priv, 0x610200, 0x00000010, 0x00000010); nv_wr32(priv, 0x640000, 0x00000000); nv_wr32(priv, 0x610200, 0x01000013); /* wait for it to go inactive */ if (!nv_wait(priv, 0x610200, 0x80000000, 0x00000000)) { nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610200)); return -EBUSY; } return 0; }
int nv44_mc_init(struct nouveau_object *object) { struct nv04_mc_priv *priv = (void *)object; u32 tmp = nv_rd32(priv, 0x10020c); nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ nv_wr32(priv, 0x001700, tmp); nv_wr32(priv, 0x001704, 0); nv_wr32(priv, 0x001708, 0); nv_wr32(priv, 0x00170c, tmp); return nouveau_mc_init(&priv->base); }
static void nvc0_mfb_isr(struct drm_device *dev) { u32 units = nv_rd32(dev, 0x00017c); while (units) { u32 subp, unit = ffs(units) - 1; for (subp = 0; subp < 2; subp++) nvc0_mfb_subp_isr(dev, unit, subp); units &= ~(1 << unit); } /* we do something horribly wrong and upset PMFB a lot, so mask off * interrupts from it after the first one until it's fixed */ nv_mask(dev, 0x000640, 0x02000000, 0x00000000); }
void nv50_cursor_fini(struct nouveau_crtc *nv_crtc) { struct drm_device *dev = nv_crtc->base.dev; int idx = nv_crtc->index; NV_DEBUG_KMS(dev, "\n"); nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); } }
static void gk20a_ibus_intr(struct nvkm_subdev *subdev) { struct gk20a_ibus_priv *priv = (void *)subdev; u32 status0 = nv_rd32(priv, 0x120058); if (status0 & 0x7) { nv_debug(priv, "resetting priv ring\n"); gk20a_ibus_init_priv_ring(priv); } /* Acknowledge interrupt */ nv_mask(priv, 0x12004c, 0x2, 0x2); if (!nv_wait(subdev, 0x12004c, 0x3f, 0x00)) nv_warn(priv, "timeout waiting for ringmaster ack\n"); }
bool nv_lockvgac(void *obj, bool lock) { struct nouveau_device *dev = nv_device(obj); bool locked = !nv_rdvgac(obj, 0, 0x1f); u8 data = lock ? 0x99 : 0x57; if (dev->card_type < NV_50) nv_wrvgac(obj, 0, 0x1f, data); else nv_wrvgac(obj, 0, 0x3f, data); if (dev->chipset == 0x11) { if (!(nv_rd32(obj, 0x001084) & 0x10000000)) nv_wrvgac(obj, 1, 0x1f, data); } return locked; }
static int nv50_disp_pioc_fini(struct nouveau_object *object, bool suspend) { struct nv50_disp_priv *priv = (void *)object->engine; struct nv50_disp_pioc *pioc = (void *)object; int chid = pioc->base.chid; nv_mask(priv, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000); if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00000000)) { nv_error(pioc, "timeout: 0x%08x\n", nv_rd32(priv, 0x610200 + (chid * 0x10))); if (suspend) return -EBUSY; } return nv50_disp_chan_fini(&pioc->base, suspend); }
static int gf100_ltc_init(struct nvkm_object *object) { struct nvkm_ltc_priv *priv = (void *)object; u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001); int ret; ret = nvkm_ltc_init(priv); if (ret) return ret; nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ nv_wr32(priv, 0x17e8d8, priv->ltc_nr); nv_wr32(priv, 0x17e8d4, priv->tag_base); nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); return 0; }
static void legacy_perf_init(struct drm_device *dev) { struct nouveau_device *device = nouveau_dev(dev); struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; struct nouveau_pm *pm = nouveau_pm(dev); char *perf, *entry, *bmp = &bios->data[bios->offset]; int headerlen, use_straps; if (bmp[5] < 0x5 || bmp[6] < 0x14) { NV_DEBUG(drm, "BMP version too old for perf\n"); return; } perf = ROMPTR(dev, bmp[0x73]); if (!perf) { NV_DEBUG(drm, "No memclock table pointer found.\n"); return; } switch (perf[0]) { case 0x12: case 0x14: case 0x18: use_straps = 0; headerlen = 1; break; case 0x01: use_straps = perf[1] & 1; headerlen = (use_straps ? 8 : 2); break; default: NV_WARN(drm, "Unknown memclock table version %x.\n", perf[0]); return; } entry = perf + headerlen; if (use_straps) entry += (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; sprintf(pm->perflvl[0].name, "performance_level_0"); pm->perflvl[0].memory = ROM16(entry[0]) * 20; pm->nr_perflvl = 1; }
void nouveau_agp_reset(struct nouveau_drm *drm) { #if __OS_HAS_AGP struct nouveau_device *device = nv_device(drm->device); struct drm_device *dev = drm->dev; u32 save[2]; int ret; if (!nouveau_agp_enabled(drm)) return; /* First of all, disable fast writes, otherwise if it's * already enabled in the AGP bridge and we disable the card's * AGP controller we might be locking ourselves out of it. */ if ((nv_rd32(device, NV04_PBUS_PCI_NV_19) | dev->agp->mode) & PCI_AGP_COMMAND_FW) { struct drm_agp_info info; struct drm_agp_mode mode; ret = drm_agp_info(dev, &info); if (ret) return; mode.mode = get_agp_mode(drm, &info); mode.mode &= ~PCI_AGP_COMMAND_FW; ret = drm_agp_enable(dev, mode); if (ret) return; } /* clear busmaster bit, and disable AGP */ save[0] = nv_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000); nv_wr32(device, NV04_PBUS_PCI_NV_19, 0); /* reset PGRAPH, PFIFO and PTIMER */ save[1] = nv_mask(device, 0x000200, 0x00011100, 0x00000000); nv_mask(device, 0x000200, 0x00011100, save[1]); /* and restore bustmaster bit (gives effect of resetting AGP) */ nv_wr32(device, NV04_PBUS_PCI_NV_1, save[0]); #endif }
u8 * nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvbios *bios = &dev_priv->vbios; u8 strap, hdr, cnt; u8 *rammap; strap = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; if (bios->ram_restrict_tbl_ptr) strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; rammap = nouveau_perf_rammap(dev, freq, ver, &hdr, &cnt, len); if (rammap && strap < cnt) return rammap + hdr + (strap * *len); return NULL; }