Leaked source code of windows server 2003
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.

1546 lines
47 KiB

  1. /*--------------------------------------------------------------------------
  2. | port.c - common port code
  3. Change History:
  4. 4-27-98 - adjust for scanrate addition.
  5. 3-23-98 - add in broadcast for boxes if not found(had put in V1.12) but
  6. the changes did not make it into source-safe. kpb.
  7. 3-20-98 - Change scheme to track remote tx-buffer level, all changes
  8. ifdef'ed by NEW_Q in port.h, turned off for now. - kpb.
  9. 3-16-98 - VS recovery fix, reset flags in port_resync_all() to force update.
  10. If RAS lost box, it would continue to see active connections, then on
  11. recovery, DSR,CD,CTS input signals would not be updated immediately.
  12. 11-05-97 - Add Backup Server feature. DCS
  13. 6-17-97 - start using index field assigned to box to id rx-messages.
  14. 6-17-97 - change link-integrity check code.
  15. |--------------------------------------------------------------------------*/
  16. #include "precomp.h"
  17. int check_ack_code(PortMan *pm, BYTE *pkt);
  18. int send_code(PortMan *pm);
  19. int send_go(PortMan *pm);
  20. int port_handle_outpkt(PortMan *pm, BYTE **buf, int *tx_used, int *port_set);
  21. BYTE *port_setup_outpkt(PortMan *pm, int *tx_used);
  22. void port_query_reply(PortMan *pm, BYTE *pkt);
  23. void port_load_pkt(PortMan *pm, BYTE *pkt);
  24. ULONG port_event_proc(PVOID context, int message_id, ULONG message_data);
  25. int port_resync_all(PortMan *pm);
  26. int port_connect_reply(Hdlc *hd);
  27. int port_connect_ask(Hdlc *hd);
  28. int port_packet(PortMan *pm, BYTE *buf);
  29. #define DISABLE()
  30. #define ENABLE()
  31. #define TraceErr3(s, p1, p2, p3) GTrace3(D_Error, sz_modid, s, p1, p2, p3)
  32. #define TraceErr2(s, p1, p2) GTrace2(D_Error, sz_modid, s, p1, p2)
  33. #define TraceErr1(s, p1) GTrace1(D_Error, sz_modid, s, p1)
  34. #define Trace2(s, p1, p2) GTrace2(D_Port, sz_modid, s, p1, p2)
  35. #define Trace1(s, p1) GTrace1(D_Port, sz_modid, s, p1)
  36. #define TraceStr(s) GTrace(D_Port, sz_modid, s)
  37. #define TraceErr(s) GTrace(D_Error, sz_modid_err, s)
  38. #define TraceAssert(l,s)
  39. static char *sz_modid = {"Port"};
  40. static char *sz_modid_err = {"Error,Port"};
  41. // following for trace or dump messages, make public for other mods as well.
  42. char *port_state_str[] = {"Init", "InitOwn", "SendCode", "Connect", "Active", "."};
  43. #ifdef NEW_Q
  44. /*--------------------------------------------------------------------------
  45. PortGetTxCntRemote -
  46. |--------------------------------------------------------------------------*/
  47. WORD PortGetTxCntRemote(SerPort *p)
  48. {
  49. WORD Get, Put;
  50. Get = p->nGetRemote;
  51. Put = p->nPutRemote;
  52. if (Put >= Get)
  53. return (Put - Get);
  54. else
  55. return (Put + (~Get) + 1);
  56. }
  57. #endif
  58. /*--------------------------------------------------------------------------
  59. PortFlushTx -
  60. |--------------------------------------------------------------------------*/
  61. void PortFlushTx(SerPort *p)
  62. {
  63. if (!q_empty(&p->QOut)) // flush local side
  64. {
  65. q_put_flush(&p->QOut);
  66. }
  67. pFlushOutput(p); // flush remote
  68. }
  69. /*--------------------------------------------------------------------------
  70. PortFlushRx -
  71. |--------------------------------------------------------------------------*/
  72. void PortFlushRx(SerPort *p)
  73. {
  74. if (!q_empty(&p->QIn)) // flush local side
  75. {
  76. #ifdef NEW_Q
  77. p->nGetLocal += q_count(&p->QIn);
  78. #endif
  79. q_get_flush(&p->QIn);
  80. p->Status |= S_UPDATE_ROOM;
  81. }
  82. pFlushInput(p); // flush remote
  83. }
  84. /*--------------------------------------------------------------------------
  85. port_resync_all - total-resync, this routine is called to reset port
  86. users, to inform them of a re-sync operation and adjust operation
  87. accordingly.
  88. If our case, since remote q is critical to maintain between both sides,
  89. we clear out all buffer data and start with all empty buffers.
  90. |--------------------------------------------------------------------------*/
  91. int port_resync_all(PortMan *pm)
  92. {
  93. int i;
  94. SerPort *Port;
  95. TraceStr( "ReSync");
  96. for (i=0; i<pm->num_ports; i++)
  97. {
  98. Port = pm->sp[i];
  99. if (Port != NULL)
  100. {
  101. Port->QOut.QSize = OUT_BUF_SIZE;
  102. Port->QOut.QGet = 0;
  103. Port->QOut.QPut = 0;
  104. #ifdef NEW_Q
  105. Port->nPutRemote = 0;
  106. Port->nGetRemote = 0;
  107. Port->nGetLocal = 0;
  108. #else
  109. Port->QInRemote.QSize= OUT_BUF_SIZE; // for now assume same sizes
  110. Port->QInRemote.QGet = 0;
  111. Port->QInRemote.QPut = 0;
  112. #endif
  113. //Port->LanIndex = i;
  114. Port->QIn.QSize = IN_BUF_SIZE;
  115. Port->QIn.QGet = 0;
  116. Port->QIn.QPut = 0;
  117. Port->change_flags |= (CHG_BAUDRATE | CHG_SP_CHARS);
  118. Port->old_baudrate = 0; // force baud rate update
  119. Port->old_control_settings = ~Port->control_settings; // force update
  120. Port->old_mcr_value = ~Port->mcr_value; // force update
  121. // reset this
  122. memset(&Port->last_sp_chars, 0, sizeof(Port->last_sp_chars));
  123. Port->msr_value = 0; // back to initial state.
  124. }
  125. }
  126. return 0;
  127. }
  128. /*--------------------------------------------------------------------------
  129. Callback routine that hdlc(l2) protocol calls on events.
  130. We are upper layer(3).
  131. |--------------------------------------------------------------------------*/
  132. ULONG port_event_proc(PVOID context, int message_id, ULONG message_data)
  133. {
  134. TraceStr("L3Event");
  135. switch(message_id)
  136. {
  137. case EV_L2_CHECK_LINK: // hdlc wants us to check link
  138. TraceStr("Chk Link");
  139. // request that the portman do a link message check
  140. ((PortMan *) context)->Status |= S_CHECK_LINK;
  141. break;
  142. case EV_L2_ADMIN_REPLY: // got a query-id reply ADMIN packet
  143. TraceStr("ID PKT");
  144. port_query_reply((PortMan *) context, (BYTE *) message_data);
  145. break;
  146. case EV_L2_BOOT_REPLY: // got a boot loader ADMIN packet
  147. TraceStr("LOAD PKT");
  148. port_load_pkt((PortMan *) context, (BYTE *) message_data);
  149. break;
  150. case EV_L2_RESYNC:
  151. // this happens on RK_CONNECT reply
  152. port_resync_all((PortMan *) context);
  153. break;
  154. case EV_L2_RELOAD:
  155. // this only happens when alive timer times out,
  156. // (hdlc-level detects a bad connection),
  157. // so lets assume box needs to be brought up from ground zero.
  158. port_resync_all((PortMan *) context);
  159. ((PortMan *) context)->state = ST_INIT;
  160. ((PortMan *) context)->load_timer = 0;
  161. ++((PortMan *) context)->reload_errors;
  162. TraceErr("Reload device");
  163. break;
  164. case EV_L2_RX_PACKET:
  165. port_packet((PortMan *) context, ((BYTE *) message_data) );
  166. break;
  167. }
  168. return 0;
  169. }
  170. /*--------------------------------------------------------------------------
  171. port_set_new_mac_addr -
  172. |--------------------------------------------------------------------------*/
  173. int port_set_new_mac_addr(PortMan *pm, BYTE *box_addr)
  174. {
  175. // Hdlc *hd;
  176. // int i;
  177. // copy over the new mac-address
  178. memcpy(pm->hd->dest_addr, box_addr, 6);
  179. // force a complete update of the box
  180. pm->reload_errors = 0;
  181. pm->state = 0;
  182. pm->Status |= S_NEED_CODE_UPDATE;
  183. pm->Status |= S_SERVER; // yes we are server(not box)
  184. port_resync_all(pm);
  185. return 0;
  186. }
  187. /*--------------------------------------------------------------------------
  188. portman_init - init the Box(PortMAn) struct, and the associated hdlc hd object.
  189. At this point the Nic object is already open.
  190. |--------------------------------------------------------------------------*/
  191. int portman_init(Hdlc *hd,
  192. PortMan *pm,
  193. int num_ports,
  194. int unique_id,
  195. int backup_server,
  196. int backup_timer,
  197. BYTE *box_addr)
  198. {
  199. int i, stat;
  200. MyKdPrint(D_Init, ("portman_init\n"))
  201. TraceStr( "PortInit");
  202. stat = 0;
  203. // allocate serial-port structures.
  204. for (i=0; i<num_ports; i++)
  205. {
  206. if (pm->sp[i] == NULL)
  207. {
  208. pm->sp[i] = (SerPort *)our_locked_alloc(sizeof(SerPort), "Dsp");
  209. port_init(pm->sp[i]); // let port create and init some stuff
  210. }
  211. }
  212. pm->num_ports = num_ports;
  213. pm->backup_server = backup_server;
  214. pm->backup_timer = backup_timer;
  215. pm->unique_id = unique_id;
  216. pm->load_timer = 0;
  217. // default to the first nic card slot, port state handling and nic
  218. // packet reception handling dynamically figures this out.
  219. // we should probably set it to null, but I'm afraid of this right now
  220. #ifdef BREAK_NIC_STUFF
  221. pm->nic =NULL;
  222. #else
  223. pm->nic = &Driver.nics[0];
  224. #endif
  225. pm->nic_index = 0;
  226. pm->hd = hd;
  227. pm->reload_errors = 0;
  228. pm->state = 0;
  229. pm->state_timer = 0;
  230. pm->Status |= S_NEED_CODE_UPDATE;
  231. pm->Status |= S_SERVER; // yes we are server(not box)
  232. pm->hd = hd;
  233. stat = hdlc_open(pm->hd, box_addr);
  234. hd->context = pm; // put our handle here, so hdlc sends this along
  235. // with any upper_layer messages
  236. if (stat)
  237. {
  238. if (Driver.VerboseLog)
  239. Eprintf("Hdlc open fail:%d",stat);
  240. TraceStr("Err-Hdlc Open!");
  241. return 3;
  242. }
  243. // set HDLC's callback RX-proc to point to our routine
  244. hd->upper_layer_proc = port_event_proc;
  245. port_resync_all(pm);
  246. return 0;
  247. }
  248. /*--------------------------------------------------------------------------
  249. portman_close - close down the port manager.
  250. |--------------------------------------------------------------------------*/
  251. int portman_close(PortMan *pm)
  252. {
  253. int i;
  254. pm->state = 0;
  255. // deallocate any Port things
  256. for (i=0; i<pm->num_ports; i++)
  257. {
  258. if (pm->sp[i] != NULL)
  259. {
  260. port_close(pm->sp[i]);
  261. our_free(pm->sp[i], "Dsp");
  262. pm->sp[i] = NULL;
  263. }
  264. }
  265. return 0;
  266. }
  267. /*--------------------------------------------------------------------------
  268. port_init - init a SerPort thing.
  269. |--------------------------------------------------------------------------*/
  270. int port_init(SerPort *sp)
  271. {
  272. TraceStr("SPort_Init");
  273. if (sp->QOut.QBase == NULL)
  274. {
  275. sp->QOut.QBase = our_locked_alloc(OUT_BUF_SIZE+2,"pmQO");
  276. if (sp->QOut.QBase == NULL)
  277. {
  278. return 1;
  279. }
  280. }
  281. if (sp->QIn.QBase == NULL)
  282. {
  283. sp->QIn.QBase = our_locked_alloc(IN_BUF_SIZE+2, "pmQI");
  284. if (sp->QIn.QBase == NULL)
  285. {
  286. return 2;
  287. }
  288. }
  289. sp->Status |= S_OPENED;
  290. sp->mcr_value = 0;
  291. //sp->mcr_value = MCR_RTS_SET_ON | MCR_DTR_SET_ON;
  292. sp->old_mcr_value = sp->mcr_value;
  293. sp->sp_chars.tx_xon = 0x11;
  294. sp->sp_chars.tx_xoff = 0x13;
  295. sp->sp_chars.rx_xon = 0x11;
  296. sp->sp_chars.rx_xoff = 0x13;
  297. sp->last_sp_chars = sp->sp_chars; // copy struct to old
  298. sp->change_flags = 0;
  299. }
  300. /*--------------------------------------------------------------------------
  301. port_close -
  302. |--------------------------------------------------------------------------*/
  303. int port_close(SerPort *sp)
  304. {
  305. int i;
  306. if (sp == NULL)
  307. return 0;
  308. if (sp->QIn.QBase != NULL)
  309. {
  310. our_free(sp->QIn.QBase,"pmQI");
  311. sp->QIn.QBase = NULL;
  312. }
  313. if (sp->QOut.QBase != NULL)
  314. {
  315. our_free(sp->QOut.QBase,"pmQO");
  316. sp->QOut.QBase = NULL;
  317. }
  318. return 0;
  319. }
  320. /*--------------------------------------------------------------------------
  321. port_packet - got an incoming packet, do something with it.
  322. |--------------------------------------------------------------------------*/
  323. int port_packet(PortMan *pm, BYTE *buf)
  324. {
  325. SerPort *Port;
  326. int port_num;
  327. int done, len;
  328. int QInRoom;
  329. TraceStr( "GotPkt");
  330. Port = pm->sp[0]; // default to point to first port
  331. //----- process all the sub-packets in the lan-packet, process
  332. // until we hit a zero header field, or some header we don't know
  333. // about(default: case).
  334. done = 0;
  335. if (*(buf) == 0)
  336. {
  337. // bugbug: this is a problem, we get a bunch of these during
  338. // normal operation, for now just show in debug version, as
  339. // they are a nuciance in peer error tracing.
  340. #if DBG
  341. TraceErr("Empty pkt!");
  342. #endif
  343. }
  344. while (!done)
  345. {
  346. switch(*buf++)
  347. {
  348. case RK_CONNECT_CHECK: // check link
  349. TraceStr( "Rk_Conn_Chk_reply");
  350. // do nothing on the server, on box send back a iframe reply
  351. break;
  352. case RK_CONNECT_REPLY: // reply from our request to bring up connection
  353. TraceStr( "Rk_reply");
  354. if (pm->Status & S_SERVER)
  355. {
  356. if (pm->state == ST_CONNECT) // should happen at this time
  357. {
  358. pm->state = ST_ACTIVE; // fire up a connection
  359. }
  360. else // got it when not expecting it.
  361. {
  362. TraceStr("Err-Recover!");
  363. // client recovering, need resyc.
  364. port_resync_all(pm);
  365. }
  366. }
  367. break;
  368. case RK_CONNECT_ASK: // packet from server
  369. TraceStr( "Rk_Ask");
  370. // should not see this on server
  371. break;
  372. case RK_PORT_SET: // set the port num to work with
  373. TraceStr( "Rk_Port");
  374. if (*buf >= pm->num_ports)
  375. {
  376. TraceErr( "PortI!");
  377. port_num = *buf++;
  378. break;
  379. }
  380. port_num = *buf++;
  381. Port = pm->sp[port_num];
  382. break;
  383. #ifdef COMMENT_OUT // not on server
  384. case RK_BAUD_SET: // set the baud rate
  385. Port->baudrate = *((DWORD *)(buf)); // Remotes QIn.QGet value
  386. buf += 4;
  387. //sSetBaudRate(ChP, Port->baudrate, 1);
  388. break;
  389. case RK_CONTROL_SET: // set the baud rate
  390. w1 = *((WORD *)(buf)); // control settings
  391. buf += 2;
  392. control_set(port_num, w1);
  393. break;
  394. case RK_MCR_SET: // modem control reg pkt
  395. w1 = *((WORD *)(buf)); // control settings
  396. buf += 2;
  397. mcr_set(port_num, w1);
  398. break;
  399. #endif
  400. case RK_MSR_SET: // modem status reg pkt
  401. Port->msr_value = *((WORD *)(buf));
  402. Trace1("Rk_MSR:%xH", Port->msr_value);
  403. buf += 2;
  404. break;
  405. case RK_ACTION_ACK: // modem status reg pkt
  406. // NT does not use this one, novell driver does to
  407. // help dump all data in transit during a flush.
  408. //Port->action_resp = *((WORD *)(buf));
  409. Trace1("Rk_Act_Ack:%xH", *((WORD *)(buf)));
  410. buf += 2;
  411. break;
  412. case RK_ESR_SET: // error status reg pkt
  413. Port->esr_reg = *((WORD *)(buf));
  414. Trace1("Rk_ESR:%xH", Port->esr_reg);
  415. buf += 2;
  416. break;
  417. case RK_QIN_STATUS: // qin status report
  418. TraceStr( "Rk_QStat");
  419. #ifdef NEW_Q
  420. Port->nGetRemote = *((WORD *)(buf)); // track remote output buffer space
  421. #else
  422. Port->QInRemote.QGet = *((short *)(buf)); // Remotes QIn.QGet value
  423. #endif
  424. buf += 2;
  425. break;
  426. case RK_DATA_BLK: // data block to put in buffer queue
  427. TraceStr( "Rk_Data");
  428. #ifdef NEW_Q
  429. //old(does not belong here!):Port->Status |= S_UPDATE_ROOM;
  430. #else
  431. Port->Status |= S_UPDATE_ROOM;
  432. #endif
  433. len = *((WORD *)(buf));
  434. buf += 2;
  435. QInRoom = q_room(&Port->QIn);
  436. TraceAssert((QInRoom < Port->QIn.QSize), "Err1B!!!");
  437. TraceAssert((QInRoom >= 0), "Err1B!!!");
  438. if (len > QInRoom) // Overflow
  439. {
  440. TraceErr("Err-Port Overflow!");
  441. len = 0;
  442. }
  443. q_put(&Port->QIn, buf, len);
  444. buf += len;
  445. break;
  446. default:
  447. done = 1;
  448. if (*(buf-1) != 0)
  449. {
  450. TraceErr("Bad Sub pkt hdr!");
  451. GTrace1(D_Error,sz_modid," HDR:%xH",*(buf-1));
  452. }
  453. break;
  454. } // case per sub-packet
  455. } // while not done with sub-packets
  456. return 0;
  457. }
  458. /*--------------------------------------------------------------------------
  459. port_poll - check to see if we need to send any packets over. If we have
  460. new data in or need to send status packets over.
  461. |--------------------------------------------------------------------------*/
  462. int port_poll(PortMan *pm)
  463. {
  464. #define MAX_TX_SPACE 1460
  465. int i, tx_used;
  466. SerPort *Port;
  467. unsigned char *buf;
  468. int ToMove, ThisMove;
  469. int QOutCount;
  470. int QLanRoom;
  471. #ifdef NEW_Q
  472. WORD tmp_word;
  473. #endif
  474. int port_set; // flag it as not setup.
  475. // this logic is in isr.c service routine now
  476. // if (pm->state != ST_ACTIVE)
  477. // {
  478. // port_state_handler(pm);
  479. // return 0;
  480. // }
  481. tx_used = MAX_TX_SPACE+1000; // indicate no pkt allocated
  482. #if DBG
  483. if (pm == NULL)
  484. {
  485. MyKdPrint(D_Error, ("!!!!!pm null\n"))
  486. return 0;
  487. }
  488. #endif
  489. // handle box things, send out a query to check-connection if
  490. // hdlc saw inactivity.
  491. if (pm->Status & S_CHECK_LINK)
  492. {
  493. if (tx_used > (MAX_TX_SPACE-50)) // if our tx-pkt is near full or null
  494. {
  495. buf = port_setup_outpkt(pm, &tx_used);
  496. if (buf == NULL)
  497. return 0; // no more output packet space available, so all done
  498. buf[tx_used++] = RK_CONNECT_CHECK;
  499. // at this point we queued our iframe to query other side(to ensure
  500. // link-integrity.
  501. pm->Status &= ~S_CHECK_LINK; // reset our request to send this
  502. TraceStr("Check sent");
  503. }
  504. }
  505. for (i=0; i<pm->num_ports; i++)
  506. {
  507. Port = pm->sp[pm->last_round_robin];
  508. //----- see if flag set to tell other side how much room in Port Rx buf
  509. if (Port->Status & S_UPDATE_ROOM)
  510. {
  511. TraceStr("Update needed");
  512. if (tx_used > (MAX_TX_SPACE-50)) // if our tx-pkt is near full or null
  513. {
  514. buf = port_setup_outpkt(pm, &tx_used);
  515. if (buf == NULL)
  516. return 0; // no more output packet space available, so all done
  517. port_set = 0xff; // flag it as not setup.
  518. }
  519. if (port_set != pm->last_round_robin) // our port index not setup
  520. {
  521. buf[tx_used++] = RK_PORT_SET;
  522. buf[tx_used++] = (BYTE) pm->last_round_robin;
  523. port_set = pm->last_round_robin;
  524. }
  525. // take away status reminder flag
  526. Port->Status &= ~S_UPDATE_ROOM;
  527. // form the sub-packet in our output packet buffer
  528. buf[tx_used++] = RK_QIN_STATUS;
  529. // report our actual QGet index to other side.
  530. #ifdef NEW_Q
  531. *((WORD *)(&buf[tx_used])) = Port->nGetLocal;
  532. #else
  533. *((short *)(&buf[tx_used])) = Port->QIn.QGet;
  534. #endif
  535. tx_used += 2;
  536. }
  537. //----- do action items
  538. if (Port->action_reg != 0)
  539. {
  540. if (port_handle_outpkt(pm, &buf, &tx_used, &port_set) != 0) // no pkt space avail
  541. return 0; // no more output packet space available, so all done
  542. TraceStr("act pkt");
  543. buf[tx_used++] = RK_ACTION_SET;
  544. *((WORD *)(&buf[tx_used])) = Port->action_reg;
  545. Port->action_reg = 0; // its a one-shot deal, so we reset this now
  546. tx_used += 2;
  547. }
  548. //----- do updates for control settings, mcr, etc
  549. if (Port->old_control_settings != Port->control_settings)
  550. {
  551. if (port_handle_outpkt(pm, &buf, &tx_used, &port_set) != 0) // no pkt space avail
  552. return 0; // no more output packet space available, so all done
  553. Port->old_control_settings = Port->control_settings;
  554. TraceStr("ctr chg");
  555. buf[tx_used++] = RK_CONTROL_SET;
  556. *((WORD *)(&buf[tx_used])) = Port->control_settings;
  557. tx_used += 2;
  558. }
  559. //----- do updates for mcr
  560. if (Port->old_mcr_value != Port->mcr_value)
  561. {
  562. if (port_handle_outpkt(pm, &buf, &tx_used, &port_set) != 0) // no pkt space avail
  563. return 0; // no more output packet space available, so all done
  564. TraceStr("mcr chg");
  565. Port->old_mcr_value = Port->mcr_value;
  566. buf[tx_used++] = RK_MCR_SET;
  567. *((WORD *)(&buf[tx_used])) = Port->mcr_value;
  568. tx_used += 2;
  569. }
  570. //----- do updates for special chars, etc
  571. if (Port->change_flags)
  572. {
  573. if (Port->change_flags & CHG_BAUDRATE)
  574. {
  575. //----- do updates for baud rate settings
  576. if (Port->old_baudrate != Port->baudrate)
  577. {
  578. if (port_handle_outpkt(pm, &buf, &tx_used, &port_set) != 0) // no pkt space avail
  579. return 0; // no more output packet space available, so all done
  580. Port->old_baudrate = Port->baudrate;
  581. Trace1("baud:%lu", Port->baudrate);
  582. buf[tx_used++] = RK_BAUD_SET;
  583. *((DWORD *)(&buf[tx_used])) = Port->baudrate;
  584. tx_used += 4;
  585. }
  586. }
  587. if (Port->change_flags & CHG_SP_CHARS)
  588. {
  589. if (memcmp(&Port->last_sp_chars, &Port->sp_chars, 6) != 0) // compare structs for chg
  590. {
  591. Port->last_sp_chars = Port->sp_chars; // remember last set values
  592. if (port_handle_outpkt(pm, &buf, &tx_used, &port_set) != 0) // no pkt space avail
  593. return 0; // no more output packet space available, so all done
  594. TraceStr("sp_chars");
  595. buf[tx_used++] = RK_SPECIAL_CHAR_SET;
  596. Trace1(" rx_xon:%x", Port->sp_chars.rx_xon);
  597. Trace1(" rx_xoff:%x", Port->sp_chars.rx_xoff);
  598. Trace1(" tx_xon:%x", Port->sp_chars.tx_xon);
  599. Trace1(" tx_xoff:%x", Port->sp_chars.tx_xoff);
  600. Trace1(" error:%x", Port->sp_chars.error);
  601. Trace1(" event:%x", Port->sp_chars.event);
  602. buf[tx_used++] = Port->sp_chars.rx_xon;
  603. buf[tx_used++] = Port->sp_chars.rx_xoff;
  604. buf[tx_used++] = Port->sp_chars.tx_xon;
  605. buf[tx_used++] = Port->sp_chars.tx_xoff;
  606. buf[tx_used++] = Port->sp_chars.error;
  607. buf[tx_used++] = Port->sp_chars.event;
  608. }
  609. }
  610. Port->change_flags = 0; // reset all
  611. }
  612. //----- send any outgoing data if other side has room.
  613. QOutCount = q_count(&Port->QOut);
  614. #ifdef NEW_Q
  615. // calculate our remote tx-buffer space based on WORD modulo arithmetic
  616. tmp_word = PortGetTxCntRemote(Port);
  617. // right now this var is equal to how much tx-data is in remote buffer.
  618. if (tmp_word < REMOTE_IN_BUF_SIZE)
  619. QLanRoom = REMOTE_IN_BUF_SIZE - tmp_word;
  620. else QLanRoom = 0;
  621. // now it is how much room we have in the remote tx-buffer.
  622. #else
  623. QLanRoom = q_room(&Port->QInRemote); // other sides port queue room
  624. #endif
  625. if ((QOutCount > 0) && (QLanRoom > 50)) // have data, other side has room
  626. {
  627. TraceStr("Data to Send");
  628. if (QOutCount > QLanRoom) // more data than room
  629. ToMove = QLanRoom; // limit
  630. else ToMove = QOutCount;
  631. do
  632. {
  633. if (tx_used > (MAX_TX_SPACE-50)) // if our tx-pkt is near full or null
  634. {
  635. buf = port_setup_outpkt(pm, &tx_used); // allocate a new one
  636. if (buf == NULL)
  637. return 0; // no more output packet space available, so all done
  638. port_set = 0xff; // flag it as not setup.
  639. }
  640. if (port_set != pm->last_round_robin) // our port index not setup
  641. {
  642. buf[tx_used++] = RK_PORT_SET;
  643. buf[tx_used++] = (BYTE) pm->last_round_robin;
  644. port_set = pm->last_round_robin;
  645. }
  646. // make sure we have emough room for data, limit if we don't
  647. if (ToMove > ((MAX_TX_SPACE-1) - tx_used) )
  648. {
  649. ThisMove = (MAX_TX_SPACE-1) - tx_used;
  650. ToMove -= ThisMove;
  651. }
  652. else
  653. {
  654. ThisMove = ToMove;
  655. ToMove = 0;
  656. }
  657. buf[tx_used++] = RK_DATA_BLK; // set header sub-type
  658. *((WORD *)(&buf[tx_used])) = ThisMove; // set header data size
  659. tx_used += 2;
  660. q_get(&Port->QOut, &buf[tx_used], ThisMove);
  661. tx_used += ThisMove;
  662. // keep our own copy of remote qin indexes
  663. #ifdef NEW_Q
  664. // bump our tx-buffer count based on WORD modulo arithmetic
  665. Port->nPutRemote += ((WORD)ThisMove);
  666. #else
  667. q_putted(&Port->QInRemote, ((short)ThisMove));
  668. #endif
  669. } while (ToMove > 0); // keep using packets if more to send
  670. } // if data sent
  671. ++pm->last_round_robin;
  672. if (pm->last_round_robin >= pm->num_ports)
  673. pm->last_round_robin = 0;
  674. }
  675. if (tx_used < (MAX_TX_SPACE+1000)) // then we allocated a packet prior
  676. { // and need to send it
  677. if (hdlc_send_outpkt(pm->hd, tx_used, pm->hd->dest_addr)) // send it out!
  678. {
  679. TraceErr("Err-hdlc_send1");
  680. }
  681. }
  682. //TraceStr( "EndPoll");
  683. return 0;
  684. }
  685. /*--------------------------------------------------------------------------
  686. port_state_handler - handle states other than normal data flowage.
  687. Called at scanrate(1-20ms) times per second from service routine.
  688. |--------------------------------------------------------------------------*/
  689. void port_state_handler(PortMan *pm)
  690. {
  691. int inic;
  692. if (pm->old_state != pm->state)
  693. {
  694. pm->old_state = pm->state;
  695. pm->state_timer = 0;
  696. }
  697. pm->timer_base += ((WORD) Driver.Tick100usBase); // 100us base units(typical:100)
  698. if (pm->timer_base < 98) // less than 9.8ms
  699. {
  700. // we want to run roughly 100 ticks per second
  701. return;
  702. }
  703. pm->timer_base = 0;
  704. switch(pm->state)
  705. {
  706. case ST_INIT:
  707. // if we are server, then wait for query back.
  708. //pm->state_timer = 0;
  709. //break;
  710. if (pm->Status & S_SERVER)
  711. {
  712. if (pm->state_timer == 600) // 6 seconds
  713. {
  714. pm->ownership_timer = 0;
  715. TraceStr( "Send Query");
  716. // find box out on network, use ADMIN pkt
  717. // do the query on all nic-segments
  718. for (inic=0; inic<VS1000_MAX_NICS; inic++)
  719. {
  720. if (Driver.nics[inic].Open) // if nic-card open for use
  721. {
  722. // send a passive query(don't try to assume ownership
  723. if (admin_send_query_id(&Driver.nics[inic], pm->hd->dest_addr,
  724. 0, 0) != 0)
  725. {
  726. TraceErr( "Err1E");
  727. }
  728. }
  729. }
  730. }
  731. else if (pm->state_timer == 1800) // 18 seconds
  732. {
  733. // try a broadcast to cut through switches.
  734. TraceStr( "Send Br.Query");
  735. // find box out on network, use ADMIN pkt
  736. // do the query on all nic-segments
  737. for (inic=0; inic<VS1000_MAX_NICS; inic++)
  738. {
  739. if (Driver.nics[inic].Open) // if nic-card open for use
  740. {
  741. // send a passive query(don't try to assume ownership
  742. if (admin_send_query_id(&Driver.nics[inic], broadcast_addr,
  743. 0, 0) != 0)
  744. {
  745. TraceErr( "Err1E");
  746. }
  747. }
  748. }
  749. }
  750. else if (pm->state_timer > 2400) // 24 sec, give up start over
  751. pm->state_timer = 0;
  752. }
  753. break;
  754. case ST_GET_OWNERSHIP:
  755. // if we are server, then wait for query back.
  756. if (pm->Status & S_SERVER)
  757. {
  758. // Increment when in ST_GET_OWNERSHIP state for backup server.
  759. ++pm->load_timer;
  760. if (pm->state_timer == 10) // 100ms
  761. {
  762. TraceStr( "Send Query Owner");
  763. // find box out on network, use ADMIN pkt
  764. // do the query on all nic-segments
  765. for (inic=0; inic<VS1000_MAX_NICS; inic++)
  766. {
  767. if (Driver.nics[inic].Open) // if nic-card open for use
  768. {
  769. // BUGFIX(8-26-98), this was only sending it out on
  770. // the nic card assigned to pm.
  771. //)if (admin_send_query_id(pm->nic, pm->hd->dest_addr,
  772. if (admin_send_query_id(&Driver.nics[inic], pm->hd->dest_addr,
  773. 1, (BYTE) pm->unique_id) != 0)
  774. {
  775. TraceErr( "Err1G");
  776. }
  777. }
  778. }
  779. }
  780. else if (pm->state_timer > 600) // 6 seconds
  781. {
  782. // SAFE GUARD ADDED DUE to SCREWED UP OWNERSHIP STATE MACHINE
  783. // kpb, 8-25-98, make sure we don't spend forever in this state.
  784. pm->ownership_timer += 6;
  785. if (pm->ownership_timer > (60 * 15)) // 15 minutes
  786. {
  787. pm->state = ST_INIT;
  788. pm->load_timer = 0;
  789. }
  790. pm->state_timer = 0;
  791. }
  792. // 8-26-98
  793. // NOTICE, we are not reseting state to INIT after a while,
  794. // this is a problem!
  795. }
  796. break;
  797. case ST_SENDCODE: // download main driver code to box
  798. if (pm->state_timer == 0)
  799. {
  800. ++pm->total_loads;
  801. pm->code_cnt = 0; // start upload
  802. send_code(pm);
  803. }
  804. else if (pm->state_timer == 1000) // 10 seconds since init
  805. {
  806. TraceErr("Upload Retry");
  807. ++pm->total_loads;
  808. pm->code_cnt = 0; // start upload
  809. send_code(pm);
  810. }
  811. else if (pm->state_timer == 2000) // 20 seconds since init
  812. {
  813. TraceErr("Upload Retry");
  814. ++pm->total_loads;
  815. pm->code_cnt = 0; // start upload
  816. send_code(pm);
  817. }
  818. else if (pm->state_timer == 3000) // fail it out, start over with init
  819. {
  820. TraceErr("Upload Fail");
  821. pm->state = ST_INIT;
  822. pm->load_timer = 0;
  823. }
  824. else if (pm->code_state == 1) // signal port poll code to send next chunk
  825. {
  826. TraceStr("Upload, next chk.");
  827. if (pm->code_cnt < Driver.MicroCodeSize)
  828. {
  829. if (send_code(pm) == 0) // success
  830. pm->code_state = 0;
  831. }
  832. else // all done
  833. {
  834. TraceStr("Code Upload Done.");
  835. if (send_go(pm) == 0)
  836. {
  837. ++pm->good_loads;
  838. pm->code_cnt = 0;
  839. pm->state = ST_GET_OWNERSHIP;
  840. }
  841. }
  842. }
  843. break;
  844. case ST_CONNECT:
  845. if (pm->state_timer == 0)
  846. port_connect_ask(pm->hd);
  847. else if (pm->state_timer == 1000) // 10 seconds
  848. port_connect_ask(pm->hd);
  849. else if (pm->state_timer == 2000) // 20 seconds
  850. {
  851. pm->state = ST_INIT; // fall back
  852. pm->load_timer = 0;
  853. }
  854. break;
  855. default:
  856. TraceErr("Err-PState!");
  857. pm->state = ST_INIT;
  858. pm->load_timer = 0;
  859. break;
  860. }
  861. ++pm->state_timer;
  862. }
  863. /*--------------------------------------------------------------------------
  864. port_handle_outpkt - check if we have at least 50 bytes in outpkt, if
  865. not get a new one. If no new one avail, return non-zero.
  866. |--------------------------------------------------------------------------*/
  867. int port_handle_outpkt(PortMan *pm, BYTE **buf, int *tx_used, int *port_set)
  868. {
  869. if (*tx_used > (MAX_TX_SPACE-50)) // if our tx-pkt is near full or null
  870. {
  871. *buf = port_setup_outpkt(pm, tx_used);
  872. if (*buf == NULL)
  873. return 1; // no more output packet space available, so all done
  874. *port_set = 0xff;
  875. }
  876. if (*port_set != pm->last_round_robin)
  877. {
  878. // since we have a new pkt, we need to
  879. (*buf)[(*tx_used)++] = RK_PORT_SET;
  880. (*buf)[(*tx_used)++] = (BYTE) pm->last_round_robin;
  881. *port_set = pm->last_round_robin;
  882. }
  883. return 0; // current pkt has plenty of room(at least 50 bytes)
  884. }
  885. /*--------------------------------------------------------------------------
  886. port_setup_outpkt - setup an outgoing packet if one is available, if previously
  887. filled one out then we ship it off out the nic card.
  888. |--------------------------------------------------------------------------*/
  889. BYTE *port_setup_outpkt(PortMan *pm, int *tx_used)
  890. {
  891. BYTE *buf;
  892. if (*tx_used != (MAX_TX_SPACE+1000)) // then we allocated a packet prior
  893. { // and need to send it
  894. if (hdlc_send_outpkt(pm->hd, *tx_used, pm->hd->dest_addr)) // send it out!
  895. {
  896. TraceErr("send err");
  897. }
  898. }
  899. if (hdlc_get_outpkt(pm->hd, &buf) == 0) // no error, got a output packet
  900. {
  901. TraceStr("NPkt2");
  902. *tx_used = 0; // have a new empty output packet allocated
  903. return buf; // all done
  904. }
  905. else
  906. {
  907. TraceStr("NPktDone2");
  908. *tx_used = MAX_TX_SPACE+1000; // indicate no pkt allocated
  909. return NULL; // all done
  910. }
  911. }
  912. /*--------------------------------------------------------------------------
  913. port_load_pkt - got a admin boot load packet: ACK back from code download pkt.
  914. |--------------------------------------------------------------------------*/
  915. void port_load_pkt(PortMan *pm, BYTE *pkt)
  916. {
  917. if (pm->state != ST_SENDCODE) // not expected at this time, lets reset it.
  918. {
  919. TraceErr("BootLoad not at SENDCODE!");
  920. Tprintf("state=%d", pm->state);
  921. // other details????
  922. pm->state = ST_INIT;
  923. pm->load_timer = 0;
  924. //pm->hd->state = ST_HDLC_INIT;
  925. return;
  926. }
  927. if (Driver.MicroCodeSize == 0)
  928. {
  929. TraceErr("Bad MC");
  930. return;
  931. }
  932. if (check_ack_code(pm,pkt) != 0)
  933. {
  934. TraceErr("Bad Ack");
  935. return;
  936. }
  937. TraceStr("Good Ack!");
  938. // send more data
  939. if (pm->code_cnt < Driver.MicroCodeSize)
  940. pm->code_cnt += 1000;
  941. pm->code_state = 1; // signal port poll code to send next chunk
  942. }
  943. #if NEW_QUERY_HANDLER
  944. /*--------------------------------------------------------------------------
  945. port_query_reply - got a ADMIN query reply back, server sends out
  946. query-id request on init and when setup is entered, box sends back
  947. id(which tells us if code is loaded.) A query reply is ignored in
  948. states other that ST_INIT and ST_GET_OWNERSHIP
  949. |--------------------------------------------------------------------------*/
  950. void port_query_reply(PortMan *pm, BYTE *pkt)
  951. {
  952. int unit_available = 0;
  953. int unit_needs_code = 0;
  954. int unit_needs_reset = 0;
  955. if (!mac_match(pkt, pm->hd->dest_addr))
  956. {
  957. TraceErr("Reply MAC bad!");
  958. return;
  959. }
  960. // ignore if not ST_INIT or ST_GET_OWNERSHIP
  961. if ((pm->state != ST_INIT) && (pm->state != ST_GET_OWNERSHIP))
  962. {
  963. return;
  964. }
  965. if (pkt[7] >= VS1000_MAX_NICS) // if invalid nic-index
  966. {
  967. TraceErr("Nic Index Reply!");
  968. return;
  969. }
  970. // when we get the query packet, we stash the nic-card index
  971. // into part of the receive buffer that is unused(pkt[7]).
  972. // see if this matches what our port-manager nic_index is,
  973. // if not, then we switched nic cards and need to update some
  974. // things.
  975. if (pm->nic_index != (int)(pkt[7])) // changed nic cards
  976. {
  977. TraceErr("Nic Changed!");
  978. pm->nic_index = (int)(pkt[7]); // set nic_index
  979. pm->nic = &Driver.nics[pm->nic_index]; // changed nic cards
  980. pm->hd->nic = pm->nic; // update the hdlc nic ptr
  981. }
  982. #define Q_DRIVER_RUNNING 1
  983. #define Q_NOT_OWNER 2
  984. #define Q_ABANDONED 4
  985. // we are NOT owner(2H), and main app-driver running(1H), be careful
  986. if ((pkt[6] & Q_DRIVER_RUNNING) && (pkt[6] & Q_NOT_OWNER))
  987. {
  988. // if not owner timeout, (4H=ABANDONED) then leave alone!
  989. // some other server is actively using it.
  990. if ((pkt[6] & Q_ABANDONED) == 0)
  991. {
  992. Trace1("ReplyID, Not Ours. [%x]", pkt[6]);
  993. pm->load_timer = 0;
  994. pm->state = ST_INIT;
  995. pm->load_timer = 0;
  996. return;
  997. }
  998. // else its abandoned, so we can take ownership.
  999. unit_available = 1;
  1000. unit_needs_reset = 1;
  1001. }
  1002. else
  1003. {
  1004. // we are owner or main-driver not running yet
  1005. unit_available = 1;
  1006. }
  1007. if ((pkt[6] & Q_DRIVER_RUNNING) == 0)
  1008. {
  1009. unit_needs_code = 1;
  1010. }
  1011. if (pm->Status & S_NEED_CODE_UPDATE)
  1012. {
  1013. unit_needs_reset = 1;
  1014. unit_needs_code = 1;
  1015. }
  1016. // ok to take ownership(no owner)
  1017. TraceStr("ReplyID, Unit Available");
  1018. if (pm->state == ST_INIT)
  1019. {
  1020. if ((pm->backup_server == 0) ||
  1021. (pm->load_timer >= (pm->backup_timer*6000)) )
  1022. {
  1023. if (pm->backup_server == 0)
  1024. { TraceStr("Pri. make owner"); }
  1025. else
  1026. { TraceStr("2nd. make owner"); }
  1027. pm->state = ST_GET_OWNERSHIP;
  1028. // this will cause the state machine to issue a query trying to
  1029. // obtain ownership
  1030. unit_needs_reset = 1;
  1031. }
  1032. else
  1033. {
  1034. if (pm->load_timer >= (pm->backup_timer*6000))
  1035. {
  1036. TraceStr("2nd, make owner");
  1037. pm->state = ST_GET_OWNERSHIP;
  1038. // this will cause the state machine to issue a query trying to
  1039. // obtain ownership
  1040. }
  1041. }
  1042. }
  1043. else if (pm->state == ST_GET_OWNERSHIP)
  1044. {
  1045. TraceStr("ReplyID in GET_OWNERSHIP");
  1046. // Is this the primary server or has the backup timer expired?
  1047. if ((pm->backup_server == 0) && (pm->load_timer >= (pm->backup_timer*6000))
  1048. {
  1049. // we are NOT owner(2H), and main app-driver running(1H), be careful
  1050. if ((pkt[6] & 3) == 3)
  1051. {
  1052. if (pkt[6] & 4) // Owner has timed out - force reload
  1053. {
  1054. // force a reset of box on driver-load(this bit is set in
  1055. // port_init) so we load up some fresh microcode.
  1056. admin_send_reset(pm->nic, pm->hd->dest_addr);
  1057. TraceStr("Abandoned, ReSet");
  1058. }
  1059. }
  1060. else if ((pkt[6] & 1) == 0) // code is not downloaded, so download it.
  1061. {
  1062. // Make sure that we are the owner?
  1063. if (pkt[6] & 2) // 2h=not owner bit
  1064. {
  1065. TraceStr("GET_OWNERSHIP: No App - Not Owner!");
  1066. pm->state = ST_INIT;
  1067. pm->load_timer = 0;
  1068. return;
  1069. }
  1070. TraceStr("GET_OWNERSHIP: Download");
  1071. pm->Status &= ~S_NEED_CODE_UPDATE;
  1072. pm->state = ST_SENDCODE;
  1073. }
  1074. else // code is downloaded - we are the owner
  1075. {
  1076. if (pm->Status & S_NEED_CODE_UPDATE)
  1077. {
  1078. // force a reset of box on driver-load(this bit is set in
  1079. // port_init) and set S_NEED_CODE_UPDATE so we load up some
  1080. // fresh microcode.
  1081. admin_send_reset(pm->nic, pm->hd->dest_addr);
  1082. TraceStr("ReplyID, ReLoad");
  1083. pm->Status &= ~S_NEED_CODE_UPDATE;
  1084. }
  1085. else
  1086. {
  1087. TraceStr("ReplyID, GoToConnect");
  1088. port_resync_all(pm);
  1089. //pm->state = ST_ACTIVE;
  1090. pm->state = ST_CONNECT;
  1091. }
  1092. }
  1093. }
  1094. }
  1095. }
  1096. #else
  1097. /*--------------------------------------------------------------------------
  1098. port_query_reply - got a ADMIN query reply back, server sends out
  1099. query-id request on init and when setup is entered, box sends back
  1100. id(which tells us if code is loaded.) A query reply is ignored in
  1101. states other that ST_INIT and ST_GET_OWNERSHIP
  1102. |--------------------------------------------------------------------------*/
  1103. void port_query_reply(PortMan *pm, BYTE *pkt)
  1104. {
  1105. if (!mac_match(pkt, pm->hd->dest_addr))
  1106. {
  1107. TraceErr("Reply MAC bad!");
  1108. return;
  1109. }
  1110. // ignore if not ST_INIT or ST_GET_OWNERSHIP
  1111. if ((pm->state != ST_INIT) && (pm->state != ST_GET_OWNERSHIP))
  1112. {
  1113. return;
  1114. }
  1115. if (pkt[7] >= VS1000_MAX_NICS) // if invalid nic-index
  1116. {
  1117. TraceErr("Nic Index Reply!");
  1118. return;
  1119. }
  1120. // when we get the query packet, we stash the nic-card index
  1121. // into part of the receive buffer that is unused(pkt[7]).
  1122. // see if this matches what our port-manager nic_index is,
  1123. // if not, then we switched nic cards and need to update some
  1124. // things.
  1125. if (pm->nic_index != (int)(pkt[7])) // changed nic cards
  1126. {
  1127. TraceErr("Nic Changed!");
  1128. pm->nic_index = (int)(pkt[7]); // set nic_index
  1129. pm->nic = &Driver.nics[pm->nic_index]; // changed nic cards
  1130. pm->hd->nic = pm->nic; // update the hdlc nic ptr
  1131. }
  1132. // we are NOT owner(2H), and main app-driver running(1H), be careful
  1133. if ((pkt[6] & 3) == 3)
  1134. {
  1135. // if not owner timeout, (4H=ABANDONED) then leave alone!
  1136. // some other server is actively using it.
  1137. if ((pkt[6] & 4) == 0)
  1138. {
  1139. Trace1("ReplyID, Not Ours. [%x]", pkt[6]);
  1140. pm->load_timer = 0;
  1141. pm->state = ST_INIT;
  1142. return;
  1143. }
  1144. }
  1145. if (pm->state == ST_INIT)
  1146. {
  1147. // ok to take ownership(no owner)
  1148. pm->state = ST_GET_OWNERSHIP;
  1149. if(pm->backup_server == 0)
  1150. {
  1151. Trace1("ReplyID, Primary Server - Unit Available [%x]", pkt[6]);
  1152. }
  1153. else
  1154. {
  1155. Trace1("ReplyID, Backup Server - Unit Available [%x]", pkt[6]);
  1156. }
  1157. }
  1158. else if (pm->state == ST_GET_OWNERSHIP)
  1159. {
  1160. Trace1("ReplyID, GET_OWNERSHIP [%x]", pkt[6]);
  1161. // Is this the primary server or has the backup timer expired?
  1162. if((pm->backup_server == 0) ||
  1163. (pm->load_timer >= (pm->backup_timer*6000)))
  1164. {
  1165. // we are NOT owner(2H), and main app-driver running(1H), be careful
  1166. if ((pkt[6] & 3) == 3)
  1167. {
  1168. if (pkt[6] & 4) // Owner has timed out - force reload
  1169. {
  1170. // force a reset of box on driver-load(this bit is set in
  1171. // port_init) so we load up some fresh microcode.
  1172. admin_send_reset(pm->nic, pm->hd->dest_addr);
  1173. TraceStr("ReplyID, ReLoad");
  1174. }
  1175. else
  1176. {
  1177. TraceStr("GET_OWNERSHIP: App Running - Not Owner!");
  1178. pm->state = ST_INIT;
  1179. pm->load_timer = 0;
  1180. return;
  1181. }
  1182. }
  1183. else if ((pkt[6] & 1) == 0) // code is not downloaded, so download it.
  1184. {
  1185. // Make sure that we are the owner?
  1186. if (pkt[6] & 2) // 2h=not owner bit
  1187. {
  1188. TraceStr("GET_OWNERSHIP: No App - Not Owner!");
  1189. pm->state = ST_INIT;
  1190. pm->load_timer = 0;
  1191. return;
  1192. }
  1193. TraceStr("GET_OWNERSHIP: Download");
  1194. pm->Status &= ~S_NEED_CODE_UPDATE;
  1195. pm->state = ST_SENDCODE;
  1196. }
  1197. else // code is downloaded - we are the owner
  1198. {
  1199. if (pm->Status & S_NEED_CODE_UPDATE)
  1200. {
  1201. // force a reset of box on driver-load(this bit is set in
  1202. // port_init) and set S_NEED_CODE_UPDATE so we load up some
  1203. // fresh microcode.
  1204. admin_send_reset(pm->nic, pm->hd->dest_addr);
  1205. TraceStr("ReplyID, ReLoad");
  1206. pm->Status &= ~S_NEED_CODE_UPDATE;
  1207. }
  1208. else
  1209. {
  1210. TraceStr("ReplyID, GoToConnect");
  1211. port_resync_all(pm);
  1212. //pm->state = ST_ACTIVE;
  1213. pm->state = ST_CONNECT;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. }
  1219. #endif
  1220. /*--------------------------------------------------------------------------
  1221. | port_connect_reply - Reply to server connection request, we return our
  1222. MAC address, and do a re-sync operation.
  1223. |--------------------------------------------------------------------------*/
  1224. int port_connect_reply(Hdlc *hd)
  1225. {
  1226. BYTE rkt_header[8];
  1227. TraceStr( "Connect Reply");
  1228. rkt_header[0] = RK_CONNECT_REPLY;
  1229. memcpy(&rkt_header[1], hd->nic->address,6);
  1230. hdlc_send_control(hd, rkt_header, 7,
  1231. NULL, 0, // ptr to data to send
  1232. hd->dest_addr); // MAC address to send to
  1233. hdlc_resync(hd);
  1234. return 0;
  1235. }
  1236. /*--------------------------------------------------------------------------
  1237. | port_connect_ask - Ask box to initiate a connection. We send out our
  1238. MAC address, and do a resync.
  1239. |--------------------------------------------------------------------------*/
  1240. int port_connect_ask(Hdlc *hd)
  1241. {
  1242. BYTE rkt_header[8];
  1243. TraceStr( "Connect Ask");
  1244. rkt_header[0] = RK_CONNECT_ASK;
  1245. memcpy(&rkt_header[1], hd->nic->address,6);
  1246. hdlc_send_control(hd, rkt_header, 7,
  1247. NULL, 0, // ptr to data to send
  1248. hd->dest_addr); // MAC address to send to
  1249. hdlc_resync(hd);
  1250. return 0;
  1251. }
  1252. /*------------------------------------------------------------------
  1253. PortSetBaudRate - Set the desired baud rate. Return non-zero on error.
  1254. |-------------------------------------------------------------------*/
  1255. int PortSetBaudRate(SerPort *p,
  1256. ULONG desired_baud,
  1257. USHORT SetHardware,
  1258. DWORD clock_freq,
  1259. DWORD clk_prescaler)
  1260. {
  1261. ULONG diff;
  1262. ULONG act_baud;
  1263. ULONG percent_error;
  1264. ULONG div;
  1265. ULONG base_clock_rate;
  1266. base_clock_rate = ((clock_freq/16) / ((clk_prescaler & 0xf)+1));
  1267. // calculate the divisor for our hardware register.
  1268. // this is really just div = clk/desired_baud -1. but we do some
  1269. // work to minimize round-off error.
  1270. if (desired_baud <= 0) desired_baud = 1; // guard against div 0
  1271. div = ((base_clock_rate+(desired_baud>>1)) / desired_baud) - 1;
  1272. if (div > 8191) // overflow hardware divide register
  1273. div = 8191;
  1274. // this is really just (clk) / (div+1) but we do some
  1275. // work to minimize round-off error.
  1276. act_baud = (base_clock_rate+((div+1)>>1)) / (div+1);
  1277. if (desired_baud > act_baud)
  1278. diff = desired_baud - act_baud;
  1279. else
  1280. diff = act_baud - desired_baud;
  1281. percent_error = (diff * 100) / desired_baud;
  1282. if (percent_error > 5)
  1283. return (int) percent_error;
  1284. if (SetHardware)
  1285. {
  1286. p->change_flags |= CHG_BAUDRATE;
  1287. //---- OLD p->out_flags |= SC_BAUDRATE_CHANGE; // tells what needs changing to remote
  1288. p->baudrate = desired_baud;
  1289. }
  1290. return 0;
  1291. }
  1292. /*---------------------------------------------------------------------------
  1293. | check_ack_code - upload code, given ack packet, check for good status.
  1294. |---------------------------------------------------------------------------*/
  1295. int check_ack_code(PortMan *pm, BYTE *pkt)
  1296. {
  1297. int stat;
  1298. int snd;
  1299. TraceStr("CodeChk");
  1300. stat = eth_device_reply(UPLOAD_COMMAND,
  1301. 0x00010000L + pm->code_cnt,
  1302. &snd,
  1303. NULL,
  1304. pkt);
  1305. return stat;
  1306. }
  1307. /*---------------------------------------------------------------------------
  1308. | send_go - send boot loader command to start execution of uploaded driver
  1309. at 1000:0 in memory.
  1310. |---------------------------------------------------------------------------*/
  1311. int send_go(PortMan *pm)
  1312. {
  1313. int stat;
  1314. BYTE *buf;
  1315. WORD io[4];
  1316. BYTE *tx_base;
  1317. TraceStr("GoSend");
  1318. hdlc_get_ctl_outpkt(pm->hd, &buf);
  1319. if (buf == NULL)
  1320. return 1;
  1321. tx_base = buf - 20; // backup to start of pkt
  1322. io[0] = 0x1000; // segment to go at
  1323. io[1] = 0; // offset to go at
  1324. // send more code, loading at 10000H location in mem.
  1325. // first just transfer data to an outgoing packet buffer
  1326. stat = ioctl_device(IOCTL_COMMAND,
  1327. (BYTE *) io,
  1328. buf,
  1329. 12, // 12 = go command
  1330. 4); // num bytes of data
  1331. // setup header
  1332. tx_base[14] = ASYNC_PRODUCT_HEADER_ID; // comtrol packet type = driver management, any product.
  1333. tx_base[15] = 0; // conc. index field
  1334. tx_base[16] = 1; // admin
  1335. *((WORD *)&tx_base[17]) = 40;
  1336. tx_base[19] = 1; // ADMIN packet type, 1=boot-loader, 3=id-reply
  1337. // send it.
  1338. stat = hdlc_send_raw(pm->hd, 60, NULL);
  1339. return 0;
  1340. }
  1341. /*---------------------------------------------------------------------------
  1342. | send_code - upload code.
  1343. |---------------------------------------------------------------------------*/
  1344. int send_code(PortMan *pm)
  1345. {
  1346. int stat;
  1347. BYTE *buf;
  1348. BYTE *tx_base;
  1349. long snd;
  1350. TraceStr("CodeSend");
  1351. // send more data
  1352. if (pm->code_cnt < Driver.MicroCodeSize)
  1353. {
  1354. if ((Driver.MicroCodeSize - pm->code_cnt) > 1000)
  1355. snd = 1000;
  1356. else
  1357. snd = Driver.MicroCodeSize - pm->code_cnt;
  1358. hdlc_get_ctl_outpkt(pm->hd, &buf);
  1359. if (buf == NULL)
  1360. {
  1361. TraceErr("CodeSend Err1A");
  1362. return 1;
  1363. }
  1364. tx_base = buf - 20; // backup to start of pkt
  1365. // send more code, loading at 10000H location in mem.
  1366. // first just transfer data to an outgoing packet buffer
  1367. stat = ioctl_device(UPLOAD_COMMAND,
  1368. &Driver.MicroCodeImage[pm->code_cnt],
  1369. buf,
  1370. 0x00010000L + pm->code_cnt, // offset into memory
  1371. snd);
  1372. // setup header
  1373. tx_base[14] = ASYNC_PRODUCT_HEADER_ID; // comtrol packet type = driver management, any product.
  1374. tx_base[15] = 0; // conc. index field
  1375. tx_base[16] = 1; // admin
  1376. *((WORD *)&tx_base[17]) = snd+20;
  1377. tx_base[19] = 1; // ADMIN packet type, 1=boot-loader, 3=id-reply
  1378. // send it.
  1379. stat = hdlc_send_raw(pm->hd, snd+40, NULL);
  1380. }
  1381. return 0;
  1382. }