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.

pxe.c 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /** @file
  2. *
  3. *
  4. *
  5. */
  6. /*
  7. * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of the
  12. * License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include "dev.h"
  24. #include "pxe.h"
  25. struct net_device *pxe_netdev = NULL;
  26. #if 0
  27. /* Global pointer to currently installed PXE stack */
  28. pxe_stack_t *pxe_stack = NULL;
  29. /* Various startup/shutdown routines. The startup/shutdown call
  30. * sequence is incredibly badly defined in the Intel PXE spec, for
  31. * example:
  32. *
  33. * PXENV_UNDI_INITIALIZE says that the parameters used to initialize
  34. * the adaptor should be those supplied to the most recent
  35. * PXENV_UNDI_STARTUP call. PXENV_UNDI_STARTUP takes no parameters.
  36. *
  37. * PXENV_UNDI_CLEANUP says that the rest of the API will not be
  38. * available after making this call. Figure 3-3 ("Early UNDI API
  39. * usage") shows a call to PXENV_UNDI_CLEANUP being followed by a
  40. * call to the supposedly now unavailable PXENV_STOP_UNDI.
  41. *
  42. * PXENV_UNLOAD_BASE_STACK talks about freeing up the memory
  43. * occupied by the PXE stack. Figure 4-3 ("PXE IPL") shows a call
  44. * to PXENV_STOP_UNDI being made after the call to
  45. * PXENV_UNLOAD_BASE_STACK, by which time the entire PXE stack
  46. * should have been freed (and, potentially, zeroed).
  47. *
  48. * Nothing, anywhere, seems to mention who's responsible for freeing
  49. * up the base memory allocated for the stack segment. It's not
  50. * even clear whether or not this is expected to be in free base
  51. * memory rather than claimed base memory.
  52. *
  53. * Consequently, we adopt a rather defensive strategy, designed to
  54. * work with any conceivable sequence of initialisation or shutdown
  55. * calls. We have only two things that we care about:
  56. *
  57. * 1. Have we hooked INT 1A and INT 15,E820(etc.)?
  58. * 2. Is the NIC initialised?
  59. *
  60. * The NIC should never be initialised without the vectors being
  61. * hooked, similarly the vectors should never be unhooked with the NIC
  62. * still initialised. We do, however, want to be able to have the
  63. * vectors hooked with the NIC shutdown. We therefore have three
  64. * possible states:
  65. *
  66. * 1. Ready to unload: interrupts unhooked, NIC shutdown.
  67. * 2. Midway: interrupts hooked, NIC shutdown.
  68. * 3. Fully ready: interrupts hooked, NIC initialised.
  69. *
  70. * We provide the three states CAN_UNLOAD, MIDWAY and READY to define
  71. * these, and the call pxe_ensure_state() to ensure that the stack is
  72. * in the specified state. All our PXE API call implementations
  73. * should use this call to ensure that the state is as required for
  74. * that PXE API call. This enables us to cope with whatever the
  75. * end-user's interpretation of the PXE spec may be. It even allows
  76. * for someone calling e.g. PXENV_START_UNDI followed by
  77. * PXENV_UDP_WRITE, without bothering with any of the intervening
  78. * calls.
  79. *
  80. * pxe_ensure_state() returns 1 for success, 0 for failure. In the
  81. * event of failure (which can arise from e.g. asking for state READY
  82. * when we don't know where our NIC is), the error code
  83. * PXENV_STATUS_UNDI_INVALID_STATE should be returned to the user.
  84. * The macros ENSURE_XXX() can be used to achieve this without lots of
  85. * duplicated code.
  86. */
  87. /* pxe_[un]hook_stack are architecture-specific and provided in
  88. * pxe_callbacks.c
  89. */
  90. int pxe_initialise_nic ( void ) {
  91. if ( pxe_stack->state >= READY ) return 1;
  92. #warning "device probing mechanism has completely changed"
  93. #if 0
  94. /* Check if NIC is initialised. dev.disable is set to 0
  95. * when disable() is called, so we use this.
  96. */
  97. if ( dev.disable ) {
  98. /* NIC may have been initialised independently
  99. * (e.g. when we set up the stack prior to calling the
  100. * NBP).
  101. */
  102. pxe_stack->state = READY;
  103. return 1;
  104. }
  105. /* If we already have a NIC defined, reuse that one with
  106. * PROBE_AWAKE. If one was specifed via PXENV_START_UNDI, try
  107. * that one first. Otherwise, set PROBE_FIRST.
  108. */
  109. if ( dev.state.pci.dev.use_specified == 1 ) {
  110. dev.how_probe = PROBE_NEXT;
  111. DBG ( " initialising NIC specified via START_UNDI" );
  112. } else if ( dev.state.pci.dev.driver ) {
  113. DBG ( " reinitialising NIC" );
  114. dev.how_probe = PROBE_AWAKE;
  115. } else {
  116. DBG ( " probing for any NIC" );
  117. dev.how_probe = PROBE_FIRST;
  118. }
  119. /* Call probe routine to bring up the NIC */
  120. if ( eth_probe ( &dev ) != PROBE_WORKED ) {
  121. DBG ( " failed" );
  122. return 0;
  123. }
  124. #endif
  125. pxe_stack->state = READY;
  126. return 1;
  127. }
  128. int pxe_shutdown_nic ( void ) {
  129. if ( pxe_stack->state <= MIDWAY ) return 1;
  130. eth_irq ( DISABLE );
  131. disable ( &dev );
  132. pxe_stack->state = MIDWAY;
  133. return 1;
  134. }
  135. int ensure_pxe_state ( pxe_stack_state_t wanted ) {
  136. int success = 1;
  137. if ( ! pxe_stack ) return 0;
  138. if ( wanted >= MIDWAY )
  139. success = success & hook_pxe_stack();
  140. if ( wanted > MIDWAY ) {
  141. success = success & pxe_initialise_nic();
  142. } else {
  143. success = success & pxe_shutdown_nic();
  144. }
  145. if ( wanted < MIDWAY )
  146. success = success & unhook_pxe_stack();
  147. return success;
  148. }
  149. #endif