quirks.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  This file contains quirk handling code for ISAPnP devices
  3.  *  Some devices do not report all their resources, and need to have extra
  4.  *  resources added. This is most easily accomplished at initialisation time
  5.  *  when building up the resource structure for the first time.
  6.  *
  7.  *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
  8.  *
  9.  *  Heavily based on PCI quirks handling which is
  10.  *
  11.  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  12.  */
  13. #include <linux/types.h>
  14. #include <linux/kernel.h>
  15. #include <linux/pci.h>
  16. #include <linux/init.h>
  17. #include <linux/isapnp.h>
  18. #include <linux/string.h>
  19. #if 0
  20. #define ISAPNP_DEBUG
  21. #endif
  22. static void __init quirk_awe32_resources(struct pci_dev *dev)
  23. {
  24. struct isapnp_port *port, *port2, *port3;
  25. struct isapnp_resources *res = dev->sysdata;
  26. /*
  27.  * Unfortunately the isapnp_add_port_resource is too tightly bound
  28.  * into the PnP discovery sequence, and cannot be used. Link in the
  29.  * two extra ports (at offset 0x400 and 0x800 from the one given) by
  30.  * hand.
  31.  */
  32. for ( ; res ; res = res->alt ) {
  33. port2 = isapnp_alloc(sizeof(struct isapnp_port));
  34. port3 = isapnp_alloc(sizeof(struct isapnp_port));
  35. if (!port2 || !port3)
  36. return;
  37. port = res->port;
  38. memcpy(port2, port, sizeof(struct isapnp_port));
  39. memcpy(port3, port, sizeof(struct isapnp_port));
  40. port->next = port2;
  41. port2->next = port3;
  42. port2->min += 0x400;
  43. port2->max += 0x400;
  44. port3->min += 0x800;
  45. port3->max += 0x800;
  46. }
  47. printk(KERN_INFO "isapnp: AWE32 quirk - adding two portsn");
  48. }
  49. static void __init quirk_cmi8330_resources(struct pci_dev *dev)
  50. {
  51. struct isapnp_resources *res = dev->sysdata;
  52. for ( ; res ; res = res->alt ) {
  53. struct isapnp_irq *irq;
  54. struct isapnp_dma *dma;
  55. for( irq = res->irq; irq; irq = irq->next ) // Valid irqs are 5, 7, 10
  56. irq->map = 0x04A0; // 0000 0100 1010 0000
  57. for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3
  58. if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT )
  59. dma->map = 0x000A;
  60. }
  61. printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dman");
  62. }
  63. static void __init quirk_sb16audio_resources(struct pci_dev *dev)
  64. {
  65. struct isapnp_port *port;
  66. struct isapnp_resources *res = dev->sysdata;
  67. int    changed = 0;
  68. /* 
  69.  * The default range on the mpu port for these devices is 0x388-0x388.
  70.  * Here we increase that range so that two such cards can be
  71.  * auto-configured.
  72.  */
  73. for( ; res ; res = res->alt ) {
  74. port = res->port;
  75. if(!port)
  76. continue;
  77. port = port->next;
  78. if(!port)
  79. continue;
  80. port = port->next;
  81. if(!port)
  82. continue;
  83. if(port->min != port->max)
  84. continue;
  85. port->max += 0x70;
  86. changed = 1;
  87. }
  88. if(changed)
  89. printk(KERN_INFO "isapnp: SB audio device quirk - increasing port rangen");
  90. return;
  91. }
  92. /*
  93.  *  ISAPnP Quirks
  94.  *  Cards or devices that need some tweaking due to broken hardware
  95.  */
  96. static struct isapnp_fixup isapnp_fixups[] __initdata = {
  97. /* Soundblaster awe io port quirk */
  98. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
  99. quirk_awe32_resources },
  100. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022),
  101. quirk_awe32_resources },
  102. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
  103. quirk_awe32_resources },
  104. /* CMI 8330 interrupt and dma fix */
  105. { ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001),
  106. quirk_cmi8330_resources },
  107. /* Soundblaster audio device io port range quirk */
  108. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0001),
  109. quirk_sb16audio_resources },
  110. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0031),
  111. quirk_sb16audio_resources },
  112. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0041),
  113. quirk_sb16audio_resources },
  114. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
  115. quirk_sb16audio_resources },
  116. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
  117. quirk_sb16audio_resources },
  118. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
  119. quirk_sb16audio_resources },
  120. { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
  121. quirk_sb16audio_resources },
  122. { 0 }
  123. };
  124. void isapnp_fixup_device(struct pci_dev *dev)
  125. {
  126. int i = 0;
  127. while (isapnp_fixups[i].vendor != 0) {
  128. if ((isapnp_fixups[i].vendor == dev->vendor) &&
  129.     (isapnp_fixups[i].device == dev->device)) {
  130. #ifdef ISAPNP_DEBUG
  131. printk(KERN_DEBUG "isapnp: Calling quirk for %02x:%02xn",
  132.        dev->bus->number, dev->devfn);
  133. #endif
  134. isapnp_fixups[i].quirk_function(dev);
  135. }
  136. i++;
  137. }
  138. }