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.

mca.c 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * MCA bus driver code
  3. *
  4. * Abstracted from 3c509.c.
  5. *
  6. */
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <errno.h>
  12. #include <io.h>
  13. #include <gpxe/mca.h>
  14. static struct mca_driver mca_drivers[0]
  15. __table_start ( struct mca_driver, mca_drivers );
  16. static struct mca_driver mca_drivers_end[0]
  17. __table_end ( struct mca_driver, mca_drivers );
  18. static void mcabus_remove ( struct root_device *rootdev );
  19. /**
  20. * Probe an MCA device
  21. *
  22. * @v mca MCA device
  23. * @ret rc Return status code
  24. *
  25. * Searches for a driver for the MCA device. If a driver is found,
  26. * its probe() routine is called.
  27. */
  28. static int mca_probe ( struct mca_device *mca ) {
  29. struct mca_driver *driver;
  30. struct mca_device_id *id;
  31. unsigned int i;
  32. int rc;
  33. DBG ( "Adding MCA slot %02x (ID %04x POS "
  34. "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)\n",
  35. mca->slot, MCA_ID ( mca ),
  36. mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3],
  37. mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] );
  38. for ( driver = mca_drivers; driver < mca_drivers_end; driver++ ){
  39. for ( i = 0 ; i < driver->id_count ; i++ ) {
  40. id = &driver->ids[i];
  41. if ( id->id != MCA_ID ( mca ) )
  42. continue;
  43. mca->driver = driver;
  44. mca->driver_name = id->name;
  45. DBG ( "...using driver %s\n", mca->driver_name );
  46. if ( ( rc = driver->probe ( mca, id ) ) != 0 ) {
  47. DBG ( "......probe failed\n" );
  48. continue;
  49. }
  50. return 0;
  51. }
  52. }
  53. DBG ( "...no driver found\n" );
  54. return -ENOTTY;
  55. }
  56. /**
  57. * Remove an MCA device
  58. *
  59. * @v mca MCA device
  60. */
  61. static void mca_remove ( struct mca_device *mca ) {
  62. mca->driver->remove ( mca );
  63. DBG ( "Removed MCA device %02x\n", mca->slot );
  64. }
  65. /**
  66. * Probe MCA root bus
  67. *
  68. * @v rootdev MCA bus root device
  69. *
  70. * Scans the MCA bus for devices and registers all devices it can
  71. * find.
  72. */
  73. static int mcabus_probe ( struct root_device *rootdev ) {
  74. struct mca_device *mca = NULL;
  75. unsigned int slot;
  76. int seen_non_ff;
  77. unsigned int i;
  78. int rc;
  79. for ( slot = 0 ; slot <= MCA_MAX_SLOT_NR ; slot++ ) {
  80. /* Allocate struct mca_device */
  81. if ( ! mca )
  82. mca = malloc ( sizeof ( *mca ) );
  83. if ( ! mca ) {
  84. rc = -ENOMEM;
  85. goto err;
  86. }
  87. memset ( mca, 0, sizeof ( *mca ) );
  88. mca->slot = slot;
  89. /* Make sure motherboard setup is off */
  90. outb_p ( 0xff, MCA_MOTHERBOARD_SETUP_REG );
  91. /* Select the slot */
  92. outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG );
  93. /* Read the POS registers */
  94. seen_non_ff = 0;
  95. for ( i = 0 ; i < ( sizeof ( mca->pos ) /
  96. sizeof ( mca->pos[0] ) ) ; i++ ) {
  97. mca->pos[i] = inb_p ( MCA_POS_REG ( i ) );
  98. if ( mca->pos[i] != 0xff )
  99. seen_non_ff = 1;
  100. }
  101. /* Kill all setup modes */
  102. outb_p ( 0, MCA_ADAPTER_SETUP_REG );
  103. /* If all POS registers are 0xff, this means there's no device
  104. * present
  105. */
  106. if ( ! seen_non_ff )
  107. continue;
  108. /* Add to device hierarchy */
  109. snprintf ( mca->dev.name, sizeof ( mca->dev.name ),
  110. "MCA%02x", slot );
  111. mca->dev.desc.bus_type = BUS_TYPE_MCA;
  112. mca->dev.desc.vendor = GENERIC_MCA_VENDOR;
  113. mca->dev.desc.device = MCA_ID ( mca );
  114. mca->dev.parent = &rootdev->dev;
  115. list_add ( &mca->dev.siblings, &rootdev->dev.children );
  116. INIT_LIST_HEAD ( &mca->dev.children );
  117. /* Look for a driver */
  118. if ( mca_probe ( mca ) == 0 ) {
  119. /* mcadev registered, we can drop our ref */
  120. mca = NULL;
  121. } else {
  122. /* Not registered; re-use struct */
  123. list_del ( &mca->dev.siblings );
  124. }
  125. }
  126. free ( mca );
  127. return 0;
  128. err:
  129. free ( mca );
  130. mcabus_remove ( rootdev );
  131. return rc;
  132. }
  133. /**
  134. * Remove MCA root bus
  135. *
  136. * @v rootdev MCA bus root device
  137. */
  138. static void mcabus_remove ( struct root_device *rootdev ) {
  139. struct mca_device *mca;
  140. struct mca_device *tmp;
  141. list_for_each_entry_safe ( mca, tmp, &rootdev->dev.children,
  142. dev.siblings ) {
  143. mca_remove ( mca );
  144. list_del ( &mca->dev.siblings );
  145. free ( mca );
  146. }
  147. }
  148. /** MCA bus root device driver */
  149. static struct root_driver mca_root_driver = {
  150. .probe = mcabus_probe,
  151. .remove = mcabus_remove,
  152. };
  153. /** MCA bus root device */
  154. struct root_device mca_root_device __root_device = {
  155. .dev = { .name = "MCA" },
  156. .driver = &mca_root_driver,
  157. };