summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-03-30 18:09:34 +0200
committerLuca Barbieri <luca@luca-barbieri.com>2010-03-30 18:09:34 +0200
commit6cdc400120a1ae03c7f0236b58d2eae8a1e12561 (patch)
treee1e35b4c5dbaa8aeca16749c094352029cfeaa9a
parent78a2fd9454f8188a7c58e3e0e662f5ee045c1951 (diff)
.
-rw-r--r--nvlib.h131
-rw-r--r--ramfc.cpp2
2 files changed, 88 insertions, 45 deletions
diff --git a/nvlib.h b/nvlib.h
index a54fd55..719e28b 100644
--- a/nvlib.h
+++ b/nvlib.h
@@ -359,7 +359,7 @@ struct nv_device : public nv_region
//search_shift = (reg >> 24) + 4;
}
- nv_ramht(std::shared_ptr<nv_ramin> ramin, int channel, uint32_t offset)
+ nv_ramht(std::shared_ptr<nv_ramin> ramin, uint32_t offset, int channel = -1)
: nv_region(ramin->dev), ramin(ramin), channel(channel)
{
assert(dev->card_type >= NV_50);
@@ -760,6 +760,34 @@ struct nv_device : public nv_region
ptr = ramfc->ptr + dev->fifoctx_size * channel;
size = dev->fifoctx_size;
}
+
+ std::shared_ptr<nv_ramht> ramht() const
+ {
+ if(dev->dev_ramht)
+ return dev->dev_ramht;
+ else
+ // TODO: is the high part the logarithm of the size?
+ return std::shared_ptr<nv_ramht>(new nv_ramht(dev->ramin, (rd32(0x80) & 0xffffff) << 4));
+ }
+
+ std::shared_ptr<nv_grctx> grctx() const
+ {
+ if(dev->card_type >= NV_40) {
+ unsigned offset;
+ if(dev->card_type >= NV_50) {
+ if(dev->chipset < 0x60)
+ offset = offset_in(*dev->ramin) + 0x200;
+ else
+ offset = rd32(0x98) << 12;
+ } else {
+ assert(dev->fifoctx_grctx >= 0);
+ offset = rd32(56) << 4;
+ }
+ return std::shared_ptr<nv_grctx>(new nv_grctx(dev, offset));
+ }
+ else
+ return std::shared_ptr<nv_grctx>();
+ }
};
struct nv_hwchannel
@@ -773,35 +801,31 @@ struct nv_device : public nv_region
std::shared_ptr<nv_ramht> ramht;
nv_hwchannel(nv_device* dev, unsigned channel, std::shared_ptr<nv_fifoctx> fifoctx = std::shared_ptr<nv_fifoctx>())
- : dev(dev), channel(channel), fifoctx(fifoctx)
+ : dev(dev)
{
- assert(channel < dev->channels);
- user = dev->users->user[channel];
+ update(channel, fifoctx);
+ }
- if(!this->fifoctx)
- this->fifoctx = dev->fifoctx(channel);
+ void update(int p_channel = -1, std::shared_ptr<nv_fifoctx> p_fifoctx = std::shared_ptr<nv_fifoctx>())
+ {
+ if(p_channel >= 0)
+ channel = p_channel;
- // TODO: move this out?
- if(dev->card_type >= NV_20) {
- unsigned offset;
- if(dev->card_type >= NV_50) {
- if(dev->chipset < 0x60)
- offset = fifoctx->offset_in(*dev->ramin) + 0x200;
- else
- offset = fifoctx->rd32(0x98) << 12;
- } else if(dev->card_type == NV_40) {
- assert(dev->fifoctx_grctx >= 0);
- offset = fifoctx->rd32(56) << 4;
- } else
- offset = dev->grctx_table->rd32(channel * 4) << 4;
- grctx.reset(new nv_grctx(dev, offset));
- }
+ assert(channel < dev->channels);
+
+ user = dev->users->user[channel];
- if(dev->card_type < NV_50)
- ramht = dev->dev_ramht;
+ if(p_fifoctx)
+ fifoctx = p_fifoctx;
else
- // TODO: is the high part the logarithm of the size?
- ramht.reset(new nv_ramht(dev->ramin, channel, (fifoctx->rd32(0x80) & 0xffffff) << 4));
+ fifoctx = dev->fifoctx(channel);
+
+ grctx = fifoctx->grctx();
+ if(!grctx)
+ grctx = dev->grctx(channel);
+ ramht = fifoctx->ramht();
+ if(ramht != dev->dev_ramht)
+ ramht->channel = channel;
}
bool enabled() const
@@ -997,24 +1021,11 @@ struct nv_device : public nv_region
else
fifoctx_fifo = 0x48;
- ramin.reset(new nv_ramin(this));
- users.reset(new nv_users(this));
- if(card_type < NV_50) {
- ramfc.reset(new nv_ramfc(ramin));
- dev_ramht.reset(new nv_ramht(ramin));
- ramro.reset(new nv_ramro(ramin));
- ramhts = 1;
- }
- else
- ramhts = dev->channels;
-
if(dev->card_type == NV_40)
fifoctx_grctx = 56;
else
fifoctx_grctx = -1;
- if(card_type == NV_20 || card_type == NV_30)
- grctx_table.reset(new nv20_grctx_table(ramin));
init_grctx_info();
grctx_grclasses = -1;
@@ -1025,6 +1036,29 @@ struct nv_device : public nv_region
}
else if(card_type == NV_30)
grctx_grclasses = 0x40;
+
+ if(card_type < NV_50)
+ ramhts = 1;
+ else
+ ramhts = channels;
+
+ users.reset(new nv_users(this));
+
+ update();
+ }
+
+ void update()
+ {
+ ramin.reset(new nv_ramin(this));
+
+ if(card_type < NV_50) {
+ ramfc.reset(new nv_ramfc(ramin));
+ dev_ramht.reset(new nv_ramht(ramin));
+ ramro.reset(new nv_ramro(ramin));
+ }
+
+ if(card_type == NV_20 || card_type == NV_30)
+ grctx_table.reset(new nv20_grctx_table(ramin));
}
static nv_device* open_default()
@@ -1050,15 +1084,12 @@ struct nv_device : public nv_region
std::shared_ptr<nv_ramht> ramht(unsigned channel) const
{
- assert(channel < ramhts);
if(dev_ramht)
return dev_ramht;
else {
- std::shared_ptr<nv_hwchannel> hwchan = hwchannel(channel);
- if(!hwchan)
- return std::shared_ptr<nv_ramht>();
-
- return hwchan->ramht;
+ std::shared_ptr<nv_ramht> ramht = fifoctx(channel)->ramht();
+ ramht->channel = channel;
+ return ramht;
}
}
@@ -1079,6 +1110,18 @@ struct nv_device : public nv_region
}
}
+ std::shared_ptr<nv_grctx> grctx(unsigned channel) const
+ {
+ if(card_type < NV_40) {
+ if(card_type >= NV_20) {
+ unsigned offset = dev->grctx_table->rd32(channel * 4) << 4;
+ return std::shared_ptr<nv_grctx>(new nv_grctx(dev, offset));
+ } else
+ return std::shared_ptr<nv_grctx>();
+ }
+ else
+ return fifoctx(channel)->grctx();
+ }
private:
void init_grctx_info() {
if(card_type == NV_50)
diff --git a/ramfc.cpp b/ramfc.cpp
index 4008d0a..af4717f 100644
--- a/ramfc.cpp
+++ b/ramfc.cpp
@@ -13,7 +13,7 @@ int main(int argc, char** argv)
continue;
if(chans)
cout << '\n';
- cout << "Channel " << dec << i << " at " << hex08 << hwchan->fifoctx->offset_in(*hwchan->ramin);
+ cout << "Channel " << dec << i << " at " << hex08 << hwchan->fifoctx->offset_in(*dev->ramin);
for(unsigned j = 0; j < dev->fifoctx_size; j += 4) {
if(!(j & 15))
cout << endl;