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.

isapnp.c 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #ifdef CONFIG_ISA
  2. /**************************************************************************
  3. *
  4. * isapnp.c -- Etherboot isapnp support for the 3Com 3c515
  5. * Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. * Portions of this code:
  22. * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
  23. *
  24. *
  25. * REVISION HISTORY:
  26. * ================
  27. * Version 0.1 April 26, 2002 TJL
  28. * Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
  29. * Version 0.3 Sept 23, 2003 timlegge Change delay to currticks
  30. *
  31. *
  32. * Indent Options: indent -kr -i8
  33. ***************************************************************************/
  34. /* to get some global routines like printf */
  35. #include "etherboot.h"
  36. #include "timer.h"
  37. #include "isapnp.h"
  38. static int pnp_card_csn = 0;
  39. void isapnp_wait(unsigned int nticks)
  40. {
  41. unsigned int to = currticks() + nticks;
  42. while (currticks() < to)
  43. /* Wait */ ;
  44. }
  45. /* The following code is the ISA PNP logic required to activate the 3c515 */
  46. /* PNP Defines */
  47. #define IDENT_LEN 9
  48. #define NUM_CARDS 128
  49. /* PNP declares */
  50. static unsigned char serial_identifier[NUM_CARDS + 1][IDENT_LEN];
  51. static unsigned char isapnp_checksum_value;
  52. static char initdata[INIT_LENGTH] = INITDATA;
  53. int read_port = 0;
  54. /* PNP Prototypes */
  55. static int Isolate(void);
  56. static int do_isapnp_isolate(void);
  57. static int isapnp_build_device_list(void);
  58. static int isapnp_isolate_rdp_select(void);
  59. static int isapnp_next_rdp(void);
  60. static void isapnp_peek(unsigned char *data, int bytes);
  61. static void send_key(void);
  62. static unsigned char isapnp_checksum(unsigned char *data);
  63. int Config(int csn);
  64. void config_pnp_device(void)
  65. {
  66. /* PNP Configuration */
  67. printf("Probing/Configuring ISAPNP devices\n");
  68. if (!read_port) {
  69. Isolate();
  70. if (pnp_card_csn)
  71. Config(pnp_card_csn);
  72. }
  73. }
  74. /* Isolate all the PNP Boards on the ISA BUS */
  75. static int Isolate(void)
  76. {
  77. int cards = 0;
  78. if (read_port < 0x203 || read_port > 0x3ff) {
  79. cards = do_isapnp_isolate();
  80. if (cards < 0 || (read_port < 0x203 || read_port > 0x3ff)) {
  81. printf("No Plug & Play device found\n");
  82. return 0;
  83. }
  84. }
  85. isapnp_build_device_list();
  86. #ifdef EDEBUG
  87. printf("%d Plug & Play device found\n", cards);
  88. #endif
  89. return 0;
  90. }
  91. static int do_isapnp_isolate(void)
  92. {
  93. unsigned char checksum = 0x6a;
  94. unsigned char chksum = 0x00;
  95. unsigned char bit = 0x00;
  96. unsigned char c1, c2;
  97. int csn = 0;
  98. int i;
  99. int iteration = 1;
  100. read_port = 0x213;
  101. if (isapnp_isolate_rdp_select() < 0)
  102. return -1;
  103. while (1) {
  104. for (i = 1; i <= 64; i++) {
  105. c1 = READ_DATA;
  106. isapnp_wait(1);
  107. c2 = READ_DATA;
  108. isapnp_wait(1);
  109. if (c1 == 0x55) {
  110. if (c2 == 0xAA) {
  111. bit = 0x01;
  112. }
  113. }
  114. checksum =
  115. ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
  116. << 7) | (checksum >> 1);
  117. bit = 0x00;
  118. }
  119. #ifdef EDEBUG
  120. printf("Calc checksum %d", checksum);
  121. #endif
  122. for (i = 65; i <= 72; i++) {
  123. c1 = READ_DATA;
  124. udelay(250);
  125. c2 = READ_DATA;
  126. udelay(250);
  127. if (c1 == 0x55) {
  128. if (c2 == 0xAA)
  129. chksum |= (1 << (i - 65));
  130. }
  131. }
  132. #ifdef EDEBUG
  133. printf("Actual checksum %d", chksum);
  134. #endif
  135. if (checksum != 0x00 && checksum == chksum) {
  136. csn++;
  137. serial_identifier[csn][iteration] >>= 1;
  138. serial_identifier[csn][iteration] |= bit;
  139. CARDSELECTNUMBER;
  140. #ifdef EDEBUG
  141. printf("Writing csn: %d", csn);
  142. #endif
  143. WRITE_DATA(csn);
  144. udelay(250);
  145. iteration++;
  146. /* Force all cards without a CSN into Isolation state */
  147. Wake(0);
  148. SetRdPort(read_port);
  149. udelay(1000);
  150. SERIALISOLATION;
  151. udelay(1000);
  152. goto __next;
  153. }
  154. if (iteration == 1) {
  155. read_port += READ_ADDR_STEP;
  156. if (isapnp_isolate_rdp_select() < 0)
  157. return -1;
  158. } else if (iteration > 1) {
  159. break;
  160. }
  161. __next:
  162. checksum = 0x6a;
  163. chksum = 0x00;
  164. bit = 0x00;
  165. }
  166. return csn;
  167. }
  168. /*
  169. * Build device list for all present ISA PnP devices.
  170. */
  171. static int isapnp_build_device_list(void)
  172. {
  173. int csn, device, vendor, serial;
  174. unsigned char header[9], checksum;
  175. for (csn = 1; csn <= 10; csn++) {
  176. Wake(csn);
  177. isapnp_peek(header, 9);
  178. checksum = isapnp_checksum(header);
  179. #ifdef EDEBUG
  180. printf
  181. ("vendor: 0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX\n",
  182. header[0], header[1], header[2], header[3], header[4],
  183. header[5], header[6], header[7], header[8]);
  184. printf("checksum = 0xhX\n", checksum);
  185. #endif
  186. /* Don't be strict on the checksum, here !
  187. e.g. 'SCM SwapBox Plug and Play' has header[8]==0 (should be: b7) */
  188. if (header[8] == 0);
  189. else if (checksum == 0x00 || checksum != header[8]) /* not valid CSN */
  190. continue;
  191. vendor = (header[1] << 8) | header[0];
  192. device = (header[3] << 8) | header[2];
  193. serial =
  194. (header[7] << 24) | (header[6] << 16) | (header[5] <<
  195. 8) |
  196. header[4];
  197. if (vendor == 0x6D50)
  198. if (device == 0x5150) {
  199. printf
  200. ("\nFound 3Com 3c515 PNP Card!\n Vendor ID: 0x%hX, Device ID: 0x%hX, Serial Num: 0x%hX\n",
  201. vendor, device, serial);
  202. pnp_card_csn = csn;
  203. }
  204. isapnp_checksum_value = 0x00;
  205. }
  206. return 0;
  207. }
  208. int Config(int csn)
  209. {
  210. #define TIMEOUT_PNP 100
  211. unsigned char id[IDENT_LEN];
  212. int i, x;
  213. Wake(csn);
  214. udelay(1000);
  215. for (i = 0; i < IDENT_LEN; i++) {
  216. for (x = 1; x < TIMEOUT_PNP; x++) {
  217. if (STATUS & 1)
  218. break;
  219. udelay(1000);
  220. }
  221. id[i] = RESOURCEDATA;
  222. #ifdef EDEBUG
  223. printf(" 0x%hX ", id[i]);
  224. #endif
  225. }
  226. #ifdef EDEBUG
  227. printf("Got The status bit\n");
  228. #endif
  229. /*Set Logical Device Register active */
  230. LOGICALDEVICENUMBER;
  231. /* Specify the first logical device */
  232. WRITE_DATA(0);
  233. /* Apparently just activating the card is enough
  234. for Etherboot to detect it. Why bother with the
  235. following code. Left in place in case it is
  236. later required */
  237. /*==========================================*/
  238. /* set DMA */
  239. /* ADDRESS(0x74 + 0);
  240. WRITE_DATA(7); */
  241. /*Set IRQ */
  242. /* udelay(1000);
  243. ADDRESS(0x70 + (0 << 1));
  244. WRITE_DATA(9);
  245. udelay(1000); */
  246. /*=============================================*/
  247. /*Activate */
  248. ACTIVATE;
  249. WRITE_DATA(1);
  250. udelay(250);
  251. /* Ask for access to the Wait for Key command - ConfigControl register */
  252. CONFIGCONTROL;
  253. /* Write the Wait for Key Command to the ConfigControl Register */
  254. WRITE_DATA(CONFIG_WAIT_FOR_KEY);
  255. /* As per doc. Two Write cycles of 0x00 required befor the Initialization key is sent */
  256. ADDRESS(0);
  257. ADDRESS(0);
  258. return 1;
  259. }
  260. static void send_key(void)
  261. {
  262. int i;
  263. /* Ask for access to the Wait for Key command - ConfigControl register */
  264. CONFIGCONTROL;
  265. /* Write the Wait for Key Command to the ConfigControl Register */
  266. WRITE_DATA(CONFIG_WAIT_FOR_KEY);
  267. /* As per doc. Two Write cycles of 0x00 required befor the Initialization key is sent */
  268. ADDRESS(0);
  269. ADDRESS(0);
  270. /* 32 writes of the initiation key to the card */
  271. for (i = 0; i < INIT_LENGTH; i++)
  272. ADDRESS(initdata[i]);
  273. }
  274. static void isapnp_peek(unsigned char *data, int bytes)
  275. {
  276. int i, j;
  277. unsigned char d = 0;
  278. for (i = 1; i <= bytes; i++) {
  279. for (j = 0; j < 20; j++) {
  280. d = STATUS;
  281. if (d & 1)
  282. break;
  283. udelay(100);
  284. }
  285. if (!(d & 1)) {
  286. if (data != NULL)
  287. *data++ = 0xff;
  288. continue;
  289. }
  290. d = RESOURCEDATA; /* PRESDI */
  291. isapnp_checksum_value += d;
  292. if (data != NULL)
  293. *data++ = d;
  294. }
  295. }
  296. /*
  297. * Compute ISA PnP checksum for first eight bytes.
  298. */
  299. static unsigned char isapnp_checksum(unsigned char *data)
  300. {
  301. int i, j;
  302. unsigned char checksum = 0x6a, bit, b;
  303. for (i = 0; i < 8; i++) {
  304. b = data[i];
  305. for (j = 0; j < 8; j++) {
  306. bit = 0;
  307. if (b & (1 << j))
  308. bit = 1;
  309. checksum =
  310. ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
  311. << 7) | (checksum >> 1);
  312. }
  313. }
  314. return checksum;
  315. }
  316. static int isapnp_next_rdp(void)
  317. {
  318. int rdp = read_port;
  319. while (rdp <= 0x3ff) {
  320. /*
  321. * We cannot use NE2000 probe spaces for ISAPnP or we
  322. * will lock up machines.
  323. */
  324. if ((rdp < 0x280 || rdp > 0x380)) {
  325. read_port = rdp;
  326. return 0;
  327. }
  328. rdp += READ_ADDR_STEP;
  329. }
  330. return -1;
  331. }
  332. static int isapnp_isolate_rdp_select(void)
  333. {
  334. send_key();
  335. /* Control: reset CSN and conditionally everything else too */
  336. CONFIGCONTROL;
  337. WRITE_DATA((CONFIG_RESET_CSN | CONFIG_WAIT_FOR_KEY));
  338. mdelay(2);
  339. send_key();
  340. Wake(0);
  341. if (isapnp_next_rdp() < 0) {
  342. /* Ask for access to the Wait for Key command - ConfigControl register */
  343. CONFIGCONTROL;
  344. /* Write the Wait for Key Command to the ConfigControl Register */
  345. WRITE_DATA(CONFIG_WAIT_FOR_KEY);
  346. return -1;
  347. }
  348. SetRdPort(read_port);
  349. udelay(1000);
  350. SERIALISOLATION;
  351. udelay(1000);
  352. return 0;
  353. }
  354. #endif /* CONFIG_ISA */