drvfbi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /******************************************************************************
  3. *
  4. * (C)Copyright 1998,1999 SysKonnect,
  5. * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
  6. *
  7. * See the file "skfddi.c" for further information.
  8. *
  9. * The information in this file is provided "AS IS" without warranty.
  10. *
  11. ******************************************************************************/
  12. /*
  13. * FBI board dependent Driver for SMT and LLC
  14. */
  15. #include "h/types.h"
  16. #include "h/fddi.h"
  17. #include "h/smc.h"
  18. #include "h/supern_2.h"
  19. #include "h/skfbiinc.h"
  20. #include <linux/bitrev.h>
  21. #include <linux/pci.h>
  22. /*
  23. * PCM active state
  24. */
  25. #define PC8_ACTIVE 8
  26. #define LED_Y_ON 0x11 /* Used for ring up/down indication */
  27. #define LED_Y_OFF 0x10
  28. #define MS2BCLK(x) ((x)*12500L)
  29. /*
  30. * valid configuration values are:
  31. */
  32. /*
  33. * xPOS_ID:xxxx
  34. * | \ /
  35. * | \/
  36. * | --------------------- the patched POS_ID of the Adapter
  37. * | xxxx = (Vendor ID low byte,
  38. * | Vendor ID high byte,
  39. * | Device ID low byte,
  40. * | Device ID high byte)
  41. * +------------------------------ the patched oem_id must be
  42. * 'S' for SK or 'I' for IBM
  43. * this is a short id for the driver.
  44. */
  45. #ifndef MULT_OEM
  46. #ifndef OEM_CONCEPT
  47. const u_char oem_id[] = "xPOS_ID:xxxx" ;
  48. #else /* OEM_CONCEPT */
  49. const u_char oem_id[] = OEM_ID ;
  50. #endif /* OEM_CONCEPT */
  51. #define ID_BYTE0 8
  52. #define OEMID(smc,i) oem_id[ID_BYTE0 + i]
  53. #else /* MULT_OEM */
  54. const struct s_oem_ids oem_ids[] = {
  55. #include "oemids.h"
  56. {0}
  57. };
  58. #define OEMID(smc,i) smc->hw.oem_id->oi_id[i]
  59. #endif /* MULT_OEM */
  60. /* Prototypes of external functions */
  61. #ifdef AIX
  62. extern int AIX_vpdReadByte() ;
  63. #endif
  64. /* Prototype of a local function. */
  65. static void smt_stop_watchdog(struct s_smc *smc);
  66. /*
  67. * FDDI card reset
  68. */
  69. static void card_start(struct s_smc *smc)
  70. {
  71. int i ;
  72. #ifdef PCI
  73. u_char rev_id ;
  74. u_short word;
  75. #endif
  76. smt_stop_watchdog(smc) ;
  77. #ifdef PCI
  78. /*
  79. * make sure no transfer activity is pending
  80. */
  81. outpw(FM_A(FM_MDREG1),FM_MINIT) ;
  82. outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
  83. hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
  84. /*
  85. * now reset everything
  86. */
  87. outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
  88. i = (int) inp(ADDR(B0_CTRL)) ; /* do dummy read */
  89. SK_UNUSED(i) ; /* Make LINT happy. */
  90. outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
  91. /*
  92. * Reset all bits in the PCI STATUS register
  93. */
  94. outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ; /* enable for writes */
  95. word = inpw(PCI_C(PCI_STATUS)) ;
  96. outpw(PCI_C(PCI_STATUS), word | PCI_STATUS_ERROR_BITS);
  97. outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ; /* disable writes */
  98. /*
  99. * Release the reset of all the State machines
  100. * Release Master_Reset
  101. * Release HPI_SM_Reset
  102. */
  103. outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
  104. /*
  105. * determine the adapter type
  106. * Note: Do it here, because some drivers may call card_start() once
  107. * at very first before any other initialization functions is
  108. * executed.
  109. */
  110. rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
  111. if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
  112. smc->hw.hw_is_64bit = TRUE ;
  113. } else {
  114. smc->hw.hw_is_64bit = FALSE ;
  115. }
  116. /*
  117. * Watermark initialization
  118. */
  119. if (!smc->hw.hw_is_64bit) {
  120. outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
  121. outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
  122. outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
  123. }
  124. outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* clear the reset chips */
  125. outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
  126. /* init the timer value for the watch dog 2,5 minutes */
  127. outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
  128. /* initialize the ISR mask */
  129. smc->hw.is_imask = ISR_MASK ;
  130. smc->hw.hw_state = STOPPED ;
  131. #endif
  132. GET_PAGE(0) ; /* necessary for BOOT */
  133. }
  134. void card_stop(struct s_smc *smc)
  135. {
  136. smt_stop_watchdog(smc) ;
  137. smc->hw.mac_ring_is_up = 0 ; /* ring down */
  138. #ifdef PCI
  139. /*
  140. * make sure no transfer activity is pending
  141. */
  142. outpw(FM_A(FM_MDREG1),FM_MINIT) ;
  143. outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
  144. hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
  145. /*
  146. * now reset everything
  147. */
  148. outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
  149. outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* reset for all chips */
  150. outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
  151. smc->hw.hw_state = STOPPED ;
  152. #endif
  153. }
  154. /*--------------------------- ISR handling ----------------------------------*/
  155. void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
  156. {
  157. int restart_tx = 0 ;
  158. again:
  159. /*
  160. * parity error: note encoding error is not possible in tag mode
  161. */
  162. if (stl & (FM_SPCEPDS | /* parity err. syn.q.*/
  163. FM_SPCEPDA0 | /* parity err. a.q.0 */
  164. FM_SPCEPDA1)) { /* parity err. a.q.1 */
  165. SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
  166. }
  167. /*
  168. * buffer underrun: can only occur if a tx threshold is specified
  169. */
  170. if (stl & (FM_STBURS | /* tx buffer underrun syn.q.*/
  171. FM_STBURA0 | /* tx buffer underrun a.q.0 */
  172. FM_STBURA1)) { /* tx buffer underrun a.q.2 */
  173. SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
  174. }
  175. if ( (stu & (FM_SXMTABT | /* transmit abort */
  176. FM_STXABRS | /* syn. tx abort */
  177. FM_STXABRA0)) || /* asyn. tx abort */
  178. (stl & (FM_SQLCKS | /* lock for syn. q. */
  179. FM_SQLCKA0)) ) { /* lock for asyn. q. */
  180. formac_tx_restart(smc) ; /* init tx */
  181. restart_tx = 1 ;
  182. stu = inpw(FM_A(FM_ST1U)) ;
  183. stl = inpw(FM_A(FM_ST1L)) ;
  184. stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
  185. if (stu || stl)
  186. goto again ;
  187. }
  188. if (stu & (FM_STEFRMA0 | /* end of asyn tx */
  189. FM_STEFRMS)) { /* end of sync tx */
  190. restart_tx = 1 ;
  191. }
  192. if (restart_tx)
  193. llc_restart_tx(smc) ;
  194. }
  195. /*
  196. * interrupt source= plc1
  197. * this function is called in nwfbisr.asm
  198. */
  199. void plc1_irq(struct s_smc *smc)
  200. {
  201. u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
  202. plc_irq(smc,PB,st) ;
  203. }
  204. /*
  205. * interrupt source= plc2
  206. * this function is called in nwfbisr.asm
  207. */
  208. void plc2_irq(struct s_smc *smc)
  209. {
  210. u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
  211. plc_irq(smc,PA,st) ;
  212. }
  213. /*
  214. * interrupt source= timer
  215. */
  216. void timer_irq(struct s_smc *smc)
  217. {
  218. hwt_restart(smc);
  219. smc->hw.t_stop = smc->hw.t_start;
  220. smt_timer_done(smc) ;
  221. }
  222. /*
  223. * return S-port (PA or PB)
  224. */
  225. int pcm_get_s_port(struct s_smc *smc)
  226. {
  227. SK_UNUSED(smc) ;
  228. return PS;
  229. }
  230. /*
  231. * Station Label = "FDDI-XYZ" where
  232. *
  233. * X = connector type
  234. * Y = PMD type
  235. * Z = port type
  236. */
  237. #define STATION_LABEL_CONNECTOR_OFFSET 5
  238. #define STATION_LABEL_PMD_OFFSET 6
  239. #define STATION_LABEL_PORT_OFFSET 7
  240. void read_address(struct s_smc *smc, u_char *mac_addr)
  241. {
  242. char ConnectorType ;
  243. char PmdType ;
  244. int i ;
  245. #ifdef PCI
  246. for (i = 0; i < 6; i++) { /* read mac address from board */
  247. smc->hw.fddi_phys_addr.a[i] =
  248. bitrev8(inp(ADDR(B2_MAC_0+i)));
  249. }
  250. #endif
  251. ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
  252. PmdType = inp(ADDR(B2_PMD_TYP)) ;
  253. smc->y[PA].pmd_type[PMD_SK_CONN] =
  254. smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
  255. smc->y[PA].pmd_type[PMD_SK_PMD ] =
  256. smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
  257. if (mac_addr) {
  258. for (i = 0; i < 6 ;i++) {
  259. smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
  260. smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
  261. }
  262. return ;
  263. }
  264. smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
  265. for (i = 0; i < 6 ;i++) {
  266. smc->hw.fddi_canon_addr.a[i] =
  267. bitrev8(smc->hw.fddi_phys_addr.a[i]);
  268. }
  269. }
  270. /*
  271. * FDDI card soft reset
  272. */
  273. void init_board(struct s_smc *smc, u_char *mac_addr)
  274. {
  275. card_start(smc) ;
  276. read_address(smc,mac_addr) ;
  277. if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
  278. smc->s.sas = SMT_SAS ; /* Single att. station */
  279. else
  280. smc->s.sas = SMT_DAS ; /* Dual att. station */
  281. if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
  282. smc->mib.fddiSMTBypassPresent = 0 ;
  283. /* without opt. bypass */
  284. else
  285. smc->mib.fddiSMTBypassPresent = 1 ;
  286. /* with opt. bypass */
  287. }
  288. /*
  289. * insert or deinsert optical bypass (called by ECM)
  290. */
  291. void sm_pm_bypass_req(struct s_smc *smc, int mode)
  292. {
  293. DB_ECMN(1, "ECM : sm_pm_bypass_req(%s)",
  294. mode == BP_INSERT ? "BP_INSERT" : "BP_DEINSERT");
  295. if (smc->s.sas != SMT_DAS)
  296. return ;
  297. #ifdef PCI
  298. switch(mode) {
  299. case BP_INSERT :
  300. outp(ADDR(B0_DAS),DAS_BYP_INS) ; /* insert station */
  301. break ;
  302. case BP_DEINSERT :
  303. outp(ADDR(B0_DAS),DAS_BYP_RMV) ; /* bypass station */
  304. break ;
  305. }
  306. #endif
  307. }
  308. /*
  309. * check if bypass connected
  310. */
  311. int sm_pm_bypass_present(struct s_smc *smc)
  312. {
  313. return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
  314. }
  315. void plc_clear_irq(struct s_smc *smc, int p)
  316. {
  317. SK_UNUSED(p) ;
  318. SK_UNUSED(smc) ;
  319. }
  320. /*
  321. * led_indication called by rmt_indication() and
  322. * pcm_state_change()
  323. *
  324. * Input:
  325. * smc: SMT context
  326. * led_event:
  327. * 0 Only switch green LEDs according to their respective PCM state
  328. * LED_Y_OFF just switch yellow LED off
  329. * LED_Y_ON just switch yello LED on
  330. */
  331. static void led_indication(struct s_smc *smc, int led_event)
  332. {
  333. /* use smc->hw.mac_ring_is_up == TRUE
  334. * as indication for Ring Operational
  335. */
  336. u_short led_state ;
  337. struct s_phy *phy ;
  338. struct fddi_mib_p *mib_a ;
  339. struct fddi_mib_p *mib_b ;
  340. phy = &smc->y[PA] ;
  341. mib_a = phy->mib ;
  342. phy = &smc->y[PB] ;
  343. mib_b = phy->mib ;
  344. #ifdef PCI
  345. led_state = 0 ;
  346. /* Ring up = yellow led OFF*/
  347. if (led_event == LED_Y_ON) {
  348. led_state |= LED_MY_ON ;
  349. }
  350. else if (led_event == LED_Y_OFF) {
  351. led_state |= LED_MY_OFF ;
  352. }
  353. else { /* PCM state changed */
  354. /* Link at Port A/S = green led A ON */
  355. if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {
  356. led_state |= LED_GA_ON ;
  357. }
  358. else {
  359. led_state |= LED_GA_OFF ;
  360. }
  361. /* Link at Port B = green led B ON */
  362. if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
  363. led_state |= LED_GB_ON ;
  364. }
  365. else {
  366. led_state |= LED_GB_OFF ;
  367. }
  368. }
  369. outp(ADDR(B0_LED), led_state) ;
  370. #endif /* PCI */
  371. }
  372. void pcm_state_change(struct s_smc *smc, int plc, int p_state)
  373. {
  374. /*
  375. * the current implementation of pcm_state_change() in the driver
  376. * parts must be renamed to drv_pcm_state_change() which will be called
  377. * now after led_indication.
  378. */
  379. DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
  380. led_indication(smc,0) ;
  381. }
  382. void rmt_indication(struct s_smc *smc, int i)
  383. {
  384. /* Call a driver special function if defined */
  385. DRV_RMT_INDICATION(smc,i) ;
  386. led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
  387. }
  388. /*
  389. * llc_recover_tx called by init_tx (fplus.c)
  390. */
  391. void llc_recover_tx(struct s_smc *smc)
  392. {
  393. #ifdef LOAD_GEN
  394. extern int load_gen_flag ;
  395. load_gen_flag = 0 ;
  396. #endif
  397. #ifndef SYNC
  398. smc->hw.n_a_send= 0 ;
  399. #else
  400. SK_UNUSED(smc) ;
  401. #endif
  402. }
  403. #ifdef MULT_OEM
  404. static int is_equal_num(char comp1[], char comp2[], int num)
  405. {
  406. int i ;
  407. for (i = 0 ; i < num ; i++) {
  408. if (comp1[i] != comp2[i])
  409. return 0;
  410. }
  411. return 1;
  412. } /* is_equal_num */
  413. /*
  414. * set the OEM ID defaults, and test the contents of the OEM data base
  415. * The default OEM is the first ACTIVE entry in the OEM data base
  416. *
  417. * returns: 0 success
  418. * 1 error in data base
  419. * 2 data base empty
  420. * 3 no active entry
  421. */
  422. int set_oi_id_def(struct s_smc *smc)
  423. {
  424. int sel_id ;
  425. int i ;
  426. int act_entries ;
  427. i = 0 ;
  428. sel_id = -1 ;
  429. act_entries = FALSE ;
  430. smc->hw.oem_id = 0 ;
  431. smc->hw.oem_min_status = OI_STAT_ACTIVE ;
  432. /* check OEM data base */
  433. while (oem_ids[i].oi_status) {
  434. switch (oem_ids[i].oi_status) {
  435. case OI_STAT_ACTIVE:
  436. act_entries = TRUE ; /* we have active IDs */
  437. if (sel_id == -1)
  438. sel_id = i ; /* save the first active ID */
  439. case OI_STAT_VALID:
  440. case OI_STAT_PRESENT:
  441. i++ ;
  442. break ; /* entry ok */
  443. default:
  444. return 1; /* invalid oi_status */
  445. }
  446. }
  447. if (i == 0)
  448. return 2;
  449. if (!act_entries)
  450. return 3;
  451. /* ok, we have a valid OEM data base with an active entry */
  452. smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[sel_id] ;
  453. return 0;
  454. }
  455. #endif /* MULT_OEM */
  456. void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
  457. {
  458. int i ;
  459. for (i = 0 ; i < 6 ; i++)
  460. bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
  461. }
  462. void smt_start_watchdog(struct s_smc *smc)
  463. {
  464. SK_UNUSED(smc) ; /* Make LINT happy. */
  465. #ifndef DEBUG
  466. #ifdef PCI
  467. if (smc->hw.wdog_used) {
  468. outpw(ADDR(B2_WDOG_CRTL),TIM_START) ; /* Start timer. */
  469. }
  470. #endif
  471. #endif /* DEBUG */
  472. }
  473. static void smt_stop_watchdog(struct s_smc *smc)
  474. {
  475. SK_UNUSED(smc) ; /* Make LINT happy. */
  476. #ifndef DEBUG
  477. #ifdef PCI
  478. if (smc->hw.wdog_used) {
  479. outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ; /* Stop timer. */
  480. }
  481. #endif
  482. #endif /* DEBUG */
  483. }
  484. #ifdef PCI
  485. void mac_do_pci_fix(struct s_smc *smc)
  486. {
  487. SK_UNUSED(smc) ;
  488. }
  489. #endif /* PCI */