You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

isa.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <stdint.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <ipxe/io.h>
  7. #include <ipxe/isa.h>
  8. FILE_LICENCE ( GPL2_OR_LATER );
  9. /*
  10. * isa.c implements a "classical" port-scanning method of ISA device
  11. * detection. The driver must provide a list of probe addresses
  12. * (probe_addrs), together with a function (probe_addr) that can be
  13. * used to test for the physical presence of a device at any given
  14. * address.
  15. *
  16. * Note that this should probably be considered the "last resort" for
  17. * device probing. If the card supports ISAPnP or EISA, use that
  18. * instead. Some cards (e.g. the 3c509) implement a proprietary
  19. * ISAPnP-like mechanism.
  20. *
  21. * The ISA probe address list can be overridden by config.h; if the
  22. * user specifies ISA_PROBE_ADDRS then that list will be used first.
  23. * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
  24. * used).
  25. */
  26. /*
  27. * User-supplied probe address list
  28. *
  29. */
  30. static isa_probe_addr_t isa_extra_probe_addrs[] = {
  31. #ifdef ISA_PROBE_ADDRS
  32. ISA_PROBE_ADDRS
  33. #endif
  34. };
  35. #define ISA_EXTRA_PROBE_ADDR_COUNT \
  36. ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
  37. #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
  38. #ifdef ISA_PROBE_ONLY
  39. #define ISA_IOIDX_MAX( driver ) ( -1 )
  40. #else
  41. #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
  42. #endif
  43. #define ISA_IOADDR( driver, ioidx ) \
  44. ( ( (ioidx) >= 0 ) ? \
  45. (driver)->probe_addrs[(ioidx)] : \
  46. *( isa_extra_probe_addrs + (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ) )
  47. static void isabus_remove ( struct root_device *rootdev );
  48. /**
  49. * Probe an ISA device
  50. *
  51. * @v isa ISA device
  52. * @ret rc Return status code
  53. */
  54. static int isa_probe ( struct isa_device *isa ) {
  55. int rc;
  56. DBG ( "Trying ISA driver %s at I/O %04x\n",
  57. isa->driver->name, isa->ioaddr );
  58. if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
  59. DBG ( "...probe failed\n" );
  60. return rc;
  61. }
  62. DBG ( "...device found\n" );
  63. return 0;
  64. }
  65. /**
  66. * Remove an ISA device
  67. *
  68. * @v isa ISA device
  69. */
  70. static void isa_remove ( struct isa_device *isa ) {
  71. isa->driver->remove ( isa );
  72. DBG ( "Removed ISA%04x\n", isa->ioaddr );
  73. }
  74. /**
  75. * Probe ISA root bus
  76. *
  77. * @v rootdev ISA bus root device
  78. *
  79. * Scans the ISA bus for devices and registers all devices it can
  80. * find.
  81. */
  82. static int isabus_probe ( struct root_device *rootdev ) {
  83. struct isa_device *isa = NULL;
  84. struct isa_driver *driver;
  85. int ioidx;
  86. int rc;
  87. for_each_table_entry ( driver, ISA_DRIVERS ) {
  88. for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
  89. ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
  90. /* Allocate struct isa_device */
  91. if ( ! isa )
  92. isa = malloc ( sizeof ( *isa ) );
  93. if ( ! isa ) {
  94. rc = -ENOMEM;
  95. goto err;
  96. }
  97. memset ( isa, 0, sizeof ( *isa ) );
  98. isa->driver = driver;
  99. isa->ioaddr = ISA_IOADDR ( driver, ioidx );
  100. /* Add to device hierarchy */
  101. snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
  102. "ISA%04x", isa->ioaddr );
  103. isa->dev.driver_name = driver->name;
  104. isa->dev.desc.bus_type = BUS_TYPE_ISA;
  105. isa->dev.desc.vendor = driver->vendor_id;
  106. isa->dev.desc.device = driver->prod_id;
  107. isa->dev.parent = &rootdev->dev;
  108. list_add ( &isa->dev.siblings,
  109. &rootdev->dev.children );
  110. INIT_LIST_HEAD ( &isa->dev.children );
  111. /* Try probing at this I/O address */
  112. if ( isa_probe ( isa ) == 0 ) {
  113. /* isadev registered, we can drop our ref */
  114. isa = NULL;
  115. } else {
  116. /* Not registered; re-use struct */
  117. list_del ( &isa->dev.siblings );
  118. }
  119. }
  120. }
  121. free ( isa );
  122. return 0;
  123. err:
  124. free ( isa );
  125. isabus_remove ( rootdev );
  126. return rc;
  127. }
  128. /**
  129. * Remove ISA root bus
  130. *
  131. * @v rootdev ISA bus root device
  132. */
  133. static void isabus_remove ( struct root_device *rootdev ) {
  134. struct isa_device *isa;
  135. struct isa_device *tmp;
  136. list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
  137. dev.siblings ) {
  138. isa_remove ( isa );
  139. list_del ( &isa->dev.siblings );
  140. free ( isa );
  141. }
  142. }
  143. /** ISA bus root device driver */
  144. static struct root_driver isa_root_driver = {
  145. .probe = isabus_probe,
  146. .remove = isabus_remove,
  147. };
  148. /** ISA bus root device */
  149. struct root_device isa_root_device __root_device = {
  150. .dev = { .name = "ISA" },
  151. .driver = &isa_root_driver,
  152. };