Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpqphp_nvram.c
Go to the documentation of this file.
1 /*
2  * Compaq Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
6  * Copyright (C) 2001 IBM Corp.
7  *
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18  * NON INFRINGEMENT. See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Send feedback to <[email protected]>
26  *
27  */
28 
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/types.h>
32 #include <linux/proc_fs.h>
33 #include <linux/slab.h>
34 #include <linux/workqueue.h>
35 #include <linux/pci.h>
36 #include <linux/pci_hotplug.h>
37 #include <linux/init.h>
38 #include <asm/uaccess.h>
39 #include "cpqphp.h"
40 #include "cpqphp_nvram.h"
41 
42 
43 #define ROM_INT15_PHY_ADDR 0x0FF859
44 #define READ_EV 0xD8A4
45 #define WRITE_EV 0xD8A5
46 
47 struct register_foo {
48  union {
49  unsigned long lword; /* eax */
50  unsigned short word; /* ax */
51 
52  struct {
53  unsigned char low; /* al */
54  unsigned char high; /* ah */
55  } byte;
56  } data;
57 
58  unsigned char opcode; /* see below */
59  unsigned long length; /* if the reg. is a pointer, how much data */
60 } __attribute__ ((packed));
61 
62 struct all_reg {
70 } __attribute__ ((packed));
71 
72 
73 struct ev_hrt_header {
77 };
78 
79 struct ev_hrt_ctrl {
82  u8 function;
88 };
89 
90 
91 static u8 evbuffer_init;
92 static u8 evbuffer_length;
93 static u8 evbuffer[1024];
94 
95 static void __iomem *compaq_int15_entry_point;
96 
97 /* lock for ordering int15_bios_call() */
98 static spinlock_t int15_lock;
99 
100 
101 /* This is a series of function that deals with
102  * setting & getting the hotplug resource table in some environment variable.
103  */
104 
105 /*
106  * We really shouldn't be doing this unless there is a _very_ good reason to!!!
107  * greg k-h
108  */
109 
110 
111 static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
112 {
113  u8 **tByte;
114 
115  if ((*used + 1) > *avail)
116  return(1);
117 
118  *((u8*)*p_buffer) = value;
119  tByte = (u8**)p_buffer;
120  (*tByte)++;
121  *used+=1;
122  return(0);
123 }
124 
125 
126 static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
127 {
128  if ((*used + 4) > *avail)
129  return(1);
130 
131  **p_buffer = value;
132  (*p_buffer)++;
133  *used+=4;
134  return(0);
135 }
136 
137 
138 /*
139  * check_for_compaq_ROM
140  *
141  * this routine verifies that the ROM OEM string is 'COMPAQ'
142  *
143  * returns 0 for non-Compaq ROM, 1 for Compaq ROM
144  */
145 static int check_for_compaq_ROM (void __iomem *rom_start)
146 {
147  u8 temp1, temp2, temp3, temp4, temp5, temp6;
148  int result = 0;
149 
150  temp1 = readb(rom_start + 0xffea + 0);
151  temp2 = readb(rom_start + 0xffea + 1);
152  temp3 = readb(rom_start + 0xffea + 2);
153  temp4 = readb(rom_start + 0xffea + 3);
154  temp5 = readb(rom_start + 0xffea + 4);
155  temp6 = readb(rom_start + 0xffea + 5);
156  if ((temp1 == 'C') &&
157  (temp2 == 'O') &&
158  (temp3 == 'M') &&
159  (temp4 == 'P') &&
160  (temp5 == 'A') &&
161  (temp6 == 'Q')) {
162  result = 1;
163  }
164  dbg ("%s - returned %d\n", __func__, result);
165  return result;
166 }
167 
168 
169 static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
170 {
171  unsigned long flags;
172  int op = operation;
173  int ret_val;
174 
175  if (!compaq_int15_entry_point)
176  return -ENODEV;
177 
178  spin_lock_irqsave(&int15_lock, flags);
179  __asm__ (
180  "xorl %%ebx,%%ebx\n" \
181  "xorl %%edx,%%edx\n" \
182  "pushf\n" \
183  "push %%cs\n" \
184  "cli\n" \
185  "call *%6\n"
186  : "=c" (*buf_size), "=a" (ret_val)
187  : "a" (op), "c" (*buf_size), "S" (ev_name),
188  "D" (buffer), "m" (compaq_int15_entry_point)
189  : "%ebx", "%edx");
190  spin_unlock_irqrestore(&int15_lock, flags);
191 
192  return((ret_val & 0xFF00) >> 8);
193 }
194 
195 
196 /*
197  * load_HRT
198  *
199  * Read the hot plug Resource Table from NVRAM
200  */
201 static int load_HRT (void __iomem *rom_start)
202 {
203  u32 available;
204  u32 temp_dword;
205  u8 temp_byte = 0xFF;
206  u32 rc;
207 
208  if (!check_for_compaq_ROM(rom_start)) {
209  return -ENODEV;
210  }
211 
212  available = 1024;
213 
214  /* Now load the EV */
215  temp_dword = available;
216 
217  rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
218 
219  evbuffer_length = temp_dword;
220 
221  /* We're maintaining the resource lists so write FF to invalidate old
222  * info
223  */
224  temp_dword = 1;
225 
226  rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
227 
228  return rc;
229 }
230 
231 
232 /*
233  * store_HRT
234  *
235  * Save the hot plug Resource Table in NVRAM
236  */
237 static u32 store_HRT (void __iomem *rom_start)
238 {
239  u32 *buffer;
240  u32 *pFill;
241  u32 usedbytes;
242  u32 available;
243  u32 temp_dword;
244  u32 rc;
245  u8 loop;
246  u8 numCtrl = 0;
247  struct controller *ctrl;
248  struct pci_resource *resNode;
249  struct ev_hrt_header *p_EV_header;
250  struct ev_hrt_ctrl *p_ev_ctrl;
251 
252  available = 1024;
253 
254  if (!check_for_compaq_ROM(rom_start)) {
255  return(1);
256  }
257 
258  buffer = (u32*) evbuffer;
259 
260  if (!buffer)
261  return(1);
262 
263  pFill = buffer;
264  usedbytes = 0;
265 
266  p_EV_header = (struct ev_hrt_header *) pFill;
267 
268  ctrl = cpqhp_ctrl_list;
269 
270  /* The revision of this structure */
271  rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
272  if (rc)
273  return(rc);
274 
275  /* The number of controllers */
276  rc = add_byte( &pFill, 1, &usedbytes, &available);
277  if (rc)
278  return(rc);
279 
280  while (ctrl) {
281  p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
282 
283  numCtrl++;
284 
285  /* The bus number */
286  rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
287  if (rc)
288  return(rc);
289 
290  /* The device Number */
291  rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
292  if (rc)
293  return(rc);
294 
295  /* The function Number */
296  rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
297  if (rc)
298  return(rc);
299 
300  /* Skip the number of available entries */
301  rc = add_dword( &pFill, 0, &usedbytes, &available);
302  if (rc)
303  return(rc);
304 
305  /* Figure out memory Available */
306 
307  resNode = ctrl->mem_head;
308 
309  loop = 0;
310 
311  while (resNode) {
312  loop ++;
313 
314  /* base */
315  rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
316  if (rc)
317  return(rc);
318 
319  /* length */
320  rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
321  if (rc)
322  return(rc);
323 
324  resNode = resNode->next;
325  }
326 
327  /* Fill in the number of entries */
328  p_ev_ctrl->mem_avail = loop;
329 
330  /* Figure out prefetchable memory Available */
331 
332  resNode = ctrl->p_mem_head;
333 
334  loop = 0;
335 
336  while (resNode) {
337  loop ++;
338 
339  /* base */
340  rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
341  if (rc)
342  return(rc);
343 
344  /* length */
345  rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
346  if (rc)
347  return(rc);
348 
349  resNode = resNode->next;
350  }
351 
352  /* Fill in the number of entries */
353  p_ev_ctrl->p_mem_avail = loop;
354 
355  /* Figure out IO Available */
356 
357  resNode = ctrl->io_head;
358 
359  loop = 0;
360 
361  while (resNode) {
362  loop ++;
363 
364  /* base */
365  rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
366  if (rc)
367  return(rc);
368 
369  /* length */
370  rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
371  if (rc)
372  return(rc);
373 
374  resNode = resNode->next;
375  }
376 
377  /* Fill in the number of entries */
378  p_ev_ctrl->io_avail = loop;
379 
380  /* Figure out bus Available */
381 
382  resNode = ctrl->bus_head;
383 
384  loop = 0;
385 
386  while (resNode) {
387  loop ++;
388 
389  /* base */
390  rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
391  if (rc)
392  return(rc);
393 
394  /* length */
395  rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
396  if (rc)
397  return(rc);
398 
399  resNode = resNode->next;
400  }
401 
402  /* Fill in the number of entries */
403  p_ev_ctrl->bus_avail = loop;
404 
405  ctrl = ctrl->next;
406  }
407 
408  p_EV_header->num_of_ctrl = numCtrl;
409 
410  /* Now store the EV */
411 
412  temp_dword = usedbytes;
413 
414  rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
415 
416  dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
417 
418  evbuffer_length = temp_dword;
419 
420  if (rc) {
422  return(1);
423  }
424 
425  return(0);
426 }
427 
428 
429 void compaq_nvram_init (void __iomem *rom_start)
430 {
431  if (rom_start) {
432  compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
433  }
434  dbg("int15 entry = %p\n", compaq_int15_entry_point);
435 
436  /* initialize our int15 lock */
437  spin_lock_init(&int15_lock);
438 }
439 
440 
441 int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
442 {
443  u8 bus, device, function;
444  u8 nummem, numpmem, numio, numbus;
445  u32 rc;
446  u8 *p_byte;
447  struct pci_resource *mem_node;
448  struct pci_resource *p_mem_node;
449  struct pci_resource *io_node;
450  struct pci_resource *bus_node;
451  struct ev_hrt_ctrl *p_ev_ctrl;
452  struct ev_hrt_header *p_EV_header;
453 
454  if (!evbuffer_init) {
455  /* Read the resource list information in from NVRAM */
456  if (load_HRT(rom_start))
457  memset (evbuffer, 0, 1024);
458 
459  evbuffer_init = 1;
460  }
461 
462  /* If we saved information in NVRAM, use it now */
463  p_EV_header = (struct ev_hrt_header *) evbuffer;
464 
465  /* The following code is for systems where version 1.0 of this
466  * driver has been loaded, but doesn't support the hardware.
467  * In that case, the driver would incorrectly store something
468  * in NVRAM.
469  */
470  if ((p_EV_header->Version == 2) ||
471  ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
472  p_byte = &(p_EV_header->next);
473 
474  p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
475 
476  p_byte += 3;
477 
478  if (p_byte > ((u8*)p_EV_header + evbuffer_length))
479  return 2;
480 
481  bus = p_ev_ctrl->bus;
482  device = p_ev_ctrl->device;
483  function = p_ev_ctrl->function;
484 
485  while ((bus != ctrl->bus) ||
486  (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
487  (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
488  nummem = p_ev_ctrl->mem_avail;
489  numpmem = p_ev_ctrl->p_mem_avail;
490  numio = p_ev_ctrl->io_avail;
491  numbus = p_ev_ctrl->bus_avail;
492 
493  p_byte += 4;
494 
495  if (p_byte > ((u8*)p_EV_header + evbuffer_length))
496  return 2;
497 
498  /* Skip forward to the next entry */
499  p_byte += (nummem + numpmem + numio + numbus) * 8;
500 
501  if (p_byte > ((u8*)p_EV_header + evbuffer_length))
502  return 2;
503 
504  p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
505 
506  p_byte += 3;
507 
508  if (p_byte > ((u8*)p_EV_header + evbuffer_length))
509  return 2;
510 
511  bus = p_ev_ctrl->bus;
512  device = p_ev_ctrl->device;
513  function = p_ev_ctrl->function;
514  }
515 
516  nummem = p_ev_ctrl->mem_avail;
517  numpmem = p_ev_ctrl->p_mem_avail;
518  numio = p_ev_ctrl->io_avail;
519  numbus = p_ev_ctrl->bus_avail;
520 
521  p_byte += 4;
522 
523  if (p_byte > ((u8*)p_EV_header + evbuffer_length))
524  return 2;
525 
526  while (nummem--) {
527  mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
528 
529  if (!mem_node)
530  break;
531 
532  mem_node->base = *(u32*)p_byte;
533  dbg("mem base = %8.8x\n",mem_node->base);
534  p_byte += 4;
535 
536  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
537  kfree(mem_node);
538  return 2;
539  }
540 
541  mem_node->length = *(u32*)p_byte;
542  dbg("mem length = %8.8x\n",mem_node->length);
543  p_byte += 4;
544 
545  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
546  kfree(mem_node);
547  return 2;
548  }
549 
550  mem_node->next = ctrl->mem_head;
551  ctrl->mem_head = mem_node;
552  }
553 
554  while (numpmem--) {
555  p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
556 
557  if (!p_mem_node)
558  break;
559 
560  p_mem_node->base = *(u32*)p_byte;
561  dbg("pre-mem base = %8.8x\n",p_mem_node->base);
562  p_byte += 4;
563 
564  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
565  kfree(p_mem_node);
566  return 2;
567  }
568 
569  p_mem_node->length = *(u32*)p_byte;
570  dbg("pre-mem length = %8.8x\n",p_mem_node->length);
571  p_byte += 4;
572 
573  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
574  kfree(p_mem_node);
575  return 2;
576  }
577 
578  p_mem_node->next = ctrl->p_mem_head;
579  ctrl->p_mem_head = p_mem_node;
580  }
581 
582  while (numio--) {
583  io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
584 
585  if (!io_node)
586  break;
587 
588  io_node->base = *(u32*)p_byte;
589  dbg("io base = %8.8x\n",io_node->base);
590  p_byte += 4;
591 
592  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
593  kfree(io_node);
594  return 2;
595  }
596 
597  io_node->length = *(u32*)p_byte;
598  dbg("io length = %8.8x\n",io_node->length);
599  p_byte += 4;
600 
601  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
602  kfree(io_node);
603  return 2;
604  }
605 
606  io_node->next = ctrl->io_head;
607  ctrl->io_head = io_node;
608  }
609 
610  while (numbus--) {
611  bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
612 
613  if (!bus_node)
614  break;
615 
616  bus_node->base = *(u32*)p_byte;
617  p_byte += 4;
618 
619  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
620  kfree(bus_node);
621  return 2;
622  }
623 
624  bus_node->length = *(u32*)p_byte;
625  p_byte += 4;
626 
627  if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
628  kfree(bus_node);
629  return 2;
630  }
631 
632  bus_node->next = ctrl->bus_head;
633  ctrl->bus_head = bus_node;
634  }
635 
636  /* If all of the following fail, we don't have any resources for
637  * hot plug add
638  */
639  rc = 1;
644 
645  if (rc)
646  return(rc);
647  } else {
648  if ((evbuffer[0] != 0) && (!ctrl->push_flag))
649  return 1;
650  }
651 
652  return 0;
653 }
654 
655 
656 int compaq_nvram_store (void __iomem *rom_start)
657 {
658  int rc = 1;
659 
660  if (rom_start == NULL)
661  return -ENODEV;
662 
663  if (evbuffer_init) {
664  rc = store_HRT(rom_start);
665  if (rc) {
667  }
668  }
669  return rc;
670 }
671