@@ -65,195 +65,232 @@ static bool nv_cksum(const uint8_t *data, unsigned int length)
65
65
}
66
66
67
67
static int
68
- score_vbios (struct drm_device * dev , const uint8_t * data , const bool writeable )
68
+ score_vbios (struct nvbios * bios , const bool writeable )
69
69
{
70
- if (!( data [0 ] == 0x55 && data [1 ] == 0xAA ) ) {
71
- NV_TRACEWARN (dev , "... BIOS signature not found\n" );
70
+ if (!bios -> data || bios -> data [0 ] != 0x55 || bios -> data [1 ] != 0xAA ) {
71
+ NV_TRACEWARN (bios -> dev , "... BIOS signature not found\n" );
72
72
return 0 ;
73
73
}
74
74
75
- if (nv_cksum (data , data [2 ] * 512 )) {
76
- NV_TRACEWARN (dev , "... BIOS checksum invalid\n" );
75
+ if (nv_cksum (bios -> data , bios -> data [2 ] * 512 )) {
76
+ NV_TRACEWARN (bios -> dev , "... BIOS checksum invalid\n" );
77
77
/* if a ro image is somewhat bad, it's probably all rubbish */
78
78
return writeable ? 2 : 1 ;
79
- } else
80
- NV_TRACE (dev , "... appears to be valid\n" );
79
+ }
81
80
81
+ NV_TRACE (bios -> dev , "... appears to be valid\n" );
82
82
return 3 ;
83
83
}
84
84
85
- static void load_vbios_prom (struct drm_device * dev , uint8_t * data )
85
+ static void
86
+ bios_shadow_prom (struct nvbios * bios )
86
87
{
88
+ struct drm_device * dev = bios -> dev ;
87
89
struct drm_nouveau_private * dev_priv = dev -> dev_private ;
88
- uint32_t pci_nv_20 , save_pci_nv_20 ;
89
- int pcir_ptr ;
90
+ u32 pcireg , access ;
91
+ u16 pcir ;
90
92
int i ;
91
93
94
+ /* enable access to rom */
92
95
if (dev_priv -> card_type >= NV_50 )
93
- pci_nv_20 = 0x88050 ;
96
+ pcireg = 0x088050 ;
94
97
else
95
- pci_nv_20 = NV_PBUS_PCI_NV_20 ;
98
+ pcireg = NV_PBUS_PCI_NV_20 ;
99
+ access = nv_mask (dev , pcireg , 0x00000001 , 0x00000000 );
96
100
97
- /* enable ROM access */
98
- save_pci_nv_20 = nvReadMC (dev , pci_nv_20 );
99
- nvWriteMC (dev , pci_nv_20 ,
100
- save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED );
101
+ /* bail if no rom signature, with a workaround for a PROM reading
102
+ * issue on some chipsets. the first read after a period of
103
+ * inactivity returns the wrong result, so retry the first header
104
+ * byte a few times before giving up as a workaround
105
+ */
106
+ i = 16 ;
107
+ do {
108
+ if (nv_rd08 (dev , NV_PROM_OFFSET + 0 ) == 0x55 )
109
+ break ;
110
+ } while (i -- );
101
111
102
- /* bail if no rom signature */
103
- if (nv_rd08 (dev , NV_PROM_OFFSET ) != 0x55 ||
104
- nv_rd08 (dev , NV_PROM_OFFSET + 1 ) != 0xaa )
112
+ if (!i || nv_rd08 (dev , NV_PROM_OFFSET + 1 ) != 0xaa )
105
113
goto out ;
106
114
107
115
/* additional check (see note below) - read PCI record header */
108
- pcir_ptr = nv_rd08 (dev , NV_PROM_OFFSET + 0x18 ) |
109
- nv_rd08 (dev , NV_PROM_OFFSET + 0x19 ) << 8 ;
110
- if (nv_rd08 (dev , NV_PROM_OFFSET + pcir_ptr ) != 'P' ||
111
- nv_rd08 (dev , NV_PROM_OFFSET + pcir_ptr + 1 ) != 'C' ||
112
- nv_rd08 (dev , NV_PROM_OFFSET + pcir_ptr + 2 ) != 'I' ||
113
- nv_rd08 (dev , NV_PROM_OFFSET + pcir_ptr + 3 ) != 'R' )
116
+ pcir = nv_rd08 (dev , NV_PROM_OFFSET + 0x18 ) |
117
+ nv_rd08 (dev , NV_PROM_OFFSET + 0x19 ) << 8 ;
118
+ if (nv_rd08 (dev , NV_PROM_OFFSET + pcir + 0 ) != 'P' ||
119
+ nv_rd08 (dev , NV_PROM_OFFSET + pcir + 1 ) != 'C' ||
120
+ nv_rd08 (dev , NV_PROM_OFFSET + pcir + 2 ) != 'I' ||
121
+ nv_rd08 (dev , NV_PROM_OFFSET + pcir + 3 ) != 'R' )
114
122
goto out ;
115
123
116
- /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a
117
- * a good read may be obtained by waiting or re-reading (cargocult: 5x)
118
- * each byte. we'll hope pramin has something usable instead
119
- */
120
- for (i = 0 ; i < NV_PROM_SIZE ; i ++ )
121
- data [i ] = nv_rd08 (dev , NV_PROM_OFFSET + i );
124
+ /* read entire bios image to system memory */
125
+ bios -> length = nv_rd08 (dev , NV_PROM_OFFSET + 2 ) * 512 ;
126
+ bios -> data = kmalloc (bios -> length , GFP_KERNEL );
127
+ if (bios -> data ) {
128
+ for (i = 0 ; i < bios -> length ; i ++ )
129
+ bios -> data [i ] = nv_rd08 (dev , NV_PROM_OFFSET + i );
130
+ }
122
131
123
132
out :
124
- /* disable ROM access */
125
- nvWriteMC (dev , pci_nv_20 ,
126
- save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED );
133
+ /* disable access to rom */
134
+ nv_wr32 (dev , pcireg , access );
127
135
}
128
136
129
- static void load_vbios_pramin (struct drm_device * dev , uint8_t * data )
137
+ static void
138
+ bios_shadow_pramin (struct nvbios * bios )
130
139
{
140
+ struct drm_device * dev = bios -> dev ;
131
141
struct drm_nouveau_private * dev_priv = dev -> dev_private ;
132
- uint32_t old_bar0_pramin = 0 ;
142
+ u32 bar0 = 0 ;
133
143
int i ;
134
144
135
145
if (dev_priv -> card_type >= NV_50 ) {
136
146
u64 addr = (u64 )(nv_rd32 (dev , 0x619f04 ) & 0xffffff00 ) << 8 ;
137
147
if (!addr ) {
138
- addr = (u64 )nv_rd32 (dev , 0x1700 ) << 16 ;
148
+ addr = (u64 )nv_rd32 (dev , 0x001700 ) << 16 ;
139
149
addr += 0xf0000 ;
140
150
}
141
151
142
- old_bar0_pramin = nv_rd32 (dev , 0x1700 );
143
- nv_wr32 (dev , 0x1700 , addr >> 16 );
152
+ bar0 = nv_mask (dev , 0x001700 , 0xffffffff , addr >> 16 );
144
153
}
145
154
146
155
/* bail if no rom signature */
147
- if (nv_rd08 (dev , NV_PRAMIN_OFFSET ) != 0x55 ||
156
+ if (nv_rd08 (dev , NV_PRAMIN_OFFSET + 0 ) != 0x55 ||
148
157
nv_rd08 (dev , NV_PRAMIN_OFFSET + 1 ) != 0xaa )
149
158
goto out ;
150
159
151
- for (i = 0 ; i < NV_PROM_SIZE ; i ++ )
152
- data [i ] = nv_rd08 (dev , NV_PRAMIN_OFFSET + i );
160
+ bios -> length = nv_rd08 (dev , NV_PRAMIN_OFFSET + 2 ) * 512 ;
161
+ bios -> data = kmalloc (bios -> length , GFP_KERNEL );
162
+ if (bios -> data ) {
163
+ for (i = 0 ; i < bios -> length ; i ++ )
164
+ bios -> data [i ] = nv_rd08 (dev , NV_PRAMIN_OFFSET + i );
165
+ }
153
166
154
167
out :
155
168
if (dev_priv -> card_type >= NV_50 )
156
- nv_wr32 (dev , 0x1700 , old_bar0_pramin );
169
+ nv_wr32 (dev , 0x001700 , bar0 );
157
170
}
158
171
159
- static void load_vbios_pci (struct drm_device * dev , uint8_t * data )
172
+ static void
173
+ bios_shadow_pci (struct nvbios * bios )
174
+ {
175
+ struct pci_dev * pdev = bios -> dev -> pdev ;
176
+ size_t length ;
177
+
178
+ if (!pci_enable_rom (pdev )) {
179
+ void __iomem * rom = pci_map_rom (pdev , & length );
180
+ if (rom ) {
181
+ bios -> data = kmalloc (length , GFP_KERNEL );
182
+ if (bios -> data ) {
183
+ memcpy_fromio (bios -> data , rom , length );
184
+ bios -> length = length ;
185
+ }
186
+ pci_unmap_rom (pdev , rom );
187
+ }
188
+
189
+ pci_disable_rom (pdev );
190
+ }
191
+ }
192
+
193
+ static void
194
+ bios_shadow_acpi (struct nvbios * bios )
160
195
{
161
- void __iomem * rom = NULL ;
162
- size_t rom_len ;
163
- int ret ;
196
+ struct pci_dev * pdev = bios -> dev -> pdev ;
197
+ int ptr , len , ret ;
198
+ u8 data [ 3 ] ;
164
199
165
- ret = pci_enable_rom (dev -> pdev );
166
- if (ret )
200
+ if (!nouveau_acpi_rom_supported (pdev ))
167
201
return ;
168
202
169
- rom = pci_map_rom (dev -> pdev , & rom_len );
170
- if (!rom )
171
- goto out ;
172
- memcpy_fromio (data , rom , rom_len );
173
- pci_unmap_rom (dev -> pdev , rom );
203
+ ret = nouveau_acpi_get_bios_chunk (data , 0 , sizeof (data ));
204
+ if (ret != sizeof (data ))
205
+ return ;
174
206
175
- out :
176
- pci_disable_rom (dev -> pdev );
177
- }
207
+ bios -> length = min (data [2 ] * 512 , 65536 );
208
+ bios -> data = kmalloc (bios -> length , GFP_KERNEL );
209
+ if (!bios -> data )
210
+ return ;
178
211
179
- static void load_vbios_acpi (struct drm_device * dev , uint8_t * data )
180
- {
181
- int i ;
182
- int ret ;
183
- int size = 64 * 1024 ;
212
+ len = bios -> length ;
213
+ ptr = 0 ;
214
+ while (len ) {
215
+ int size = (len > ROM_BIOS_PAGE ) ? ROM_BIOS_PAGE : len ;
184
216
185
- if (!nouveau_acpi_rom_supported (dev -> pdev ))
186
- return ;
217
+ ret = nouveau_acpi_get_bios_chunk (bios -> data , ptr , size );
218
+ if (ret != size ) {
219
+ kfree (bios -> data );
220
+ bios -> data = NULL ;
221
+ return ;
222
+ }
187
223
188
- for (i = 0 ; i < (size / ROM_BIOS_PAGE ); i ++ ) {
189
- ret = nouveau_acpi_get_bios_chunk (data ,
190
- (i * ROM_BIOS_PAGE ),
191
- ROM_BIOS_PAGE );
192
- if (ret <= 0 )
193
- break ;
224
+ len -= size ;
225
+ ptr += size ;
194
226
}
195
- return ;
196
227
}
197
228
198
229
struct methods {
199
230
const char desc [8 ];
200
- void (* loadbios )(struct drm_device * , uint8_t * );
231
+ void (* shadow )(struct nvbios * );
201
232
const bool rw ;
233
+ int score ;
234
+ u32 size ;
235
+ u8 * data ;
202
236
};
203
237
204
- static struct methods shadow_methods [] = {
205
- { "PRAMIN" , load_vbios_pramin , true },
206
- { "PROM" , load_vbios_prom , false },
207
- { "ACPI" , load_vbios_acpi , true },
208
- { "PCIROM " , load_vbios_pci , true },
209
- };
210
- #define NUM_SHADOW_METHODS ARRAY_SIZE(shadow_methods)
211
-
212
- static bool NVShadowVBIOS ( struct drm_device * dev , uint8_t * data )
213
- {
214
- struct methods * methods = shadow_methods ;
215
- int testscore = 3 ;
216
- int scores [ NUM_SHADOW_METHODS ], i ;
238
+ static bool
239
+ bios_shadow ( struct drm_device * dev )
240
+ {
241
+ struct methods shadow_methods [] = {
242
+ { "PRAMIN " , bios_shadow_pramin , true, 0 , 0 , NULL },
243
+ { "PROM" , bios_shadow_prom , false, 0 , 0 , NULL },
244
+ { "ACPI" , bios_shadow_acpi , true, 0 , 0 , NULL },
245
+ { "PCIROM" , bios_shadow_pci , true, 0 , 0 , NULL },
246
+ {}
247
+ };
248
+ struct drm_nouveau_private * dev_priv = dev -> dev_private ;
249
+ struct nvbios * bios = & dev_priv -> vbios ;
250
+ struct methods * mthd , * best ;
217
251
218
252
if (nouveau_vbios ) {
219
- for (i = 0 ; i < NUM_SHADOW_METHODS ; i ++ )
220
- if (!strcasecmp (nouveau_vbios , methods [i ].desc ))
221
- break ;
222
-
223
- if (i < NUM_SHADOW_METHODS ) {
224
- NV_INFO (dev , "Attempting to use BIOS image from %s\n" ,
225
- methods [i ].desc );
253
+ mthd = shadow_methods ;
254
+ do {
255
+ if (strcasecmp (nouveau_vbios , mthd -> desc ))
256
+ continue ;
257
+ NV_INFO (dev , "VBIOS source: %s\n" , mthd -> desc );
226
258
227
- methods [i ].loadbios (dev , data );
228
- if (score_vbios (dev , data , methods [i ].rw ))
259
+ mthd -> shadow (bios );
260
+ mthd -> score = score_vbios (bios , mthd -> rw );
261
+ if (mthd -> score )
229
262
return true;
230
- }
263
+ } while (( ++ mthd ) -> shadow );
231
264
232
265
NV_ERROR (dev , "VBIOS source \'%s\' invalid\n" , nouveau_vbios );
233
266
}
234
267
235
- for (i = 0 ; i < NUM_SHADOW_METHODS ; i ++ ) {
236
- NV_TRACE (dev , "Attempting to load BIOS image from %s\n" ,
237
- methods [i ].desc );
238
- data [0 ] = data [1 ] = 0 ; /* avoid reuse of previous image */
239
- methods [i ].loadbios (dev , data );
240
- scores [i ] = score_vbios (dev , data , methods [i ].rw );
241
- if (scores [i ] == testscore )
242
- return true;
243
- }
244
-
245
- while (-- testscore > 0 ) {
246
- for (i = 0 ; i < NUM_SHADOW_METHODS ; i ++ ) {
247
- if (scores [i ] == testscore ) {
248
- NV_TRACE (dev , "Using BIOS image from %s\n" ,
249
- methods [i ].desc );
250
- methods [i ].loadbios (dev , data );
251
- return true;
252
- }
268
+ mthd = shadow_methods ;
269
+ do {
270
+ NV_TRACE (dev , "Checking %s for VBIOS\n" , mthd -> desc );
271
+ mthd -> shadow (bios );
272
+ mthd -> score = score_vbios (bios , mthd -> rw );
273
+ mthd -> size = bios -> length ;
274
+ mthd -> data = bios -> data ;
275
+ } while (mthd -> score != 3 && (++ mthd )-> shadow );
276
+
277
+ mthd = shadow_methods ;
278
+ best = mthd ;
279
+ do {
280
+ if (mthd -> score > best -> score ) {
281
+ kfree (best -> data );
282
+ best = mthd ;
253
283
}
284
+ } while ((++ mthd )-> shadow );
285
+
286
+ if (best -> score ) {
287
+ NV_TRACE (dev , "Using VBIOS from %s\n" , best -> desc );
288
+ bios -> length = best -> size ;
289
+ bios -> data = best -> data ;
290
+ return true;
254
291
}
255
292
256
- NV_ERROR (dev , "No valid BIOS image found\n" );
293
+ NV_ERROR (dev , "No valid VBIOS image found\n" );
257
294
return false;
258
295
}
259
296
@@ -6334,11 +6371,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
6334
6371
spin_lock_init (& bios -> lock );
6335
6372
bios -> dev = dev ;
6336
6373
6337
- if (!NVShadowVBIOS (dev , bios -> data ))
6338
- return false;
6339
-
6340
- bios -> length = NV_PROM_SIZE ;
6341
- return true;
6374
+ return bios_shadow (dev );
6342
6375
}
6343
6376
6344
6377
static int nouveau_parse_vbios_struct (struct drm_device * dev )
@@ -6498,6 +6531,10 @@ nouveau_bios_init(struct drm_device *dev)
6498
6531
void
6499
6532
nouveau_bios_takedown (struct drm_device * dev )
6500
6533
{
6534
+ struct drm_nouveau_private * dev_priv = dev -> dev_private ;
6535
+
6501
6536
nouveau_mxm_fini (dev );
6502
6537
nouveau_i2c_fini (dev );
6538
+
6539
+ kfree (dev_priv -> vbios .data );
6503
6540
}
0 commit comments