devi82365.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "error.h"
  7. #include "io.h"
  8. /*
  9. * Intel 82365SL PCIC controller and compatibles.
  10. */
  11. enum
  12. {
  13. /*
  14. * registers indices
  15. */
  16. Rid= 0x0, /* identification and revision */
  17. Ris= 0x1, /* interface status */
  18. Rpc= 0x2, /* power control */
  19. Foutena= (1<<7), /* output enable */
  20. Fautopower= (1<<5), /* automatic power switching */
  21. Fcardena= (1<<4), /* PC card enable */
  22. Rigc= 0x3, /* interrupt and general control */
  23. Fiocard= (1<<5), /* I/O card (vs memory) */
  24. Fnotreset= (1<<6), /* reset if not set */
  25. FSMIena= (1<<4), /* enable change interrupt on SMI */
  26. Rcsc= 0x4, /* card status change */
  27. Rcscic= 0x5, /* card status change interrupt config */
  28. Fchangeena= (1<<3), /* card changed */
  29. Fbwarnena= (1<<1), /* card battery warning */
  30. Fbdeadena= (1<<0), /* card battery dead */
  31. Rwe= 0x6, /* address window enable */
  32. Fmem16= (1<<5), /* use A23-A12 to decode address */
  33. Rio= 0x7, /* I/O control */
  34. Fwidth16= (1<<0), /* 16 bit data width */
  35. Fiocs16= (1<<1), /* IOCS16 determines data width */
  36. Fzerows= (1<<2), /* zero wait state */
  37. Ftiming= (1<<3), /* timing register to use */
  38. Riobtm0lo= 0x8, /* I/O address 0 start low byte */
  39. Riobtm0hi= 0x9, /* I/O address 0 start high byte */
  40. Riotop0lo= 0xa, /* I/O address 0 stop low byte */
  41. Riotop0hi= 0xb, /* I/O address 0 stop high byte */
  42. Riobtm1lo= 0xc, /* I/O address 1 start low byte */
  43. Riobtm1hi= 0xd, /* I/O address 1 start high byte */
  44. Riotop1lo= 0xe, /* I/O address 1 stop low byte */
  45. Riotop1hi= 0xf, /* I/O address 1 stop high byte */
  46. Rmap= 0x10, /* map 0 */
  47. /*
  48. * CL-PD67xx extension registers
  49. */
  50. Rmisc1= 0x16, /* misc control 1 */
  51. F5Vdetect= (1<<0),
  52. Fvcc3V= (1<<1),
  53. Fpmint= (1<<2),
  54. Fpsirq= (1<<3),
  55. Fspeaker= (1<<4),
  56. Finpack= (1<<7),
  57. Rfifo= 0x17, /* fifo control */
  58. Fflush= (1<<7), /* flush fifo */
  59. Rmisc2= 0x1E, /* misc control 2 */
  60. Flowpow= (1<<1), /* low power mode */
  61. Rchipinfo= 0x1F, /* chip information */
  62. Ratactl= 0x26, /* ATA control */
  63. /*
  64. * offsets into the system memory address maps
  65. */
  66. Mbtmlo= 0x0, /* System mem addr mapping start low byte */
  67. Mbtmhi= 0x1, /* System mem addr mapping start high byte */
  68. F16bit= (1<<7), /* 16-bit wide data path */
  69. Mtoplo= 0x2, /* System mem addr mapping stop low byte */
  70. Mtophi= 0x3, /* System mem addr mapping stop high byte */
  71. Ftimer1= (1<<6), /* timer set 1 */
  72. Mofflo= 0x4, /* Card memory offset address low byte */
  73. Moffhi= 0x5, /* Card memory offset address high byte */
  74. Fregactive= (1<<6), /* attribute memory */
  75. /*
  76. * configuration registers - they start at an offset in attribute
  77. * memory found in the CIS.
  78. */
  79. Rconfig= 0,
  80. Creset= (1<<7), /* reset device */
  81. Clevel= (1<<6), /* level sensitive interrupt line */
  82. Cirq= (1<<2), /* IRQ enable */
  83. Cdecode= (1<<1), /* address decode */
  84. Cfunc= (1<<0), /* function enable */
  85. Riobase0= 5,
  86. Riobase1= 6,
  87. Riosize= 9,
  88. };
  89. static int pcmcia_pcmspecial(char *, ISAConf *);
  90. static void pcmcia_pcmspecialclose(int);
  91. #define MAP(x,o) (Rmap + (x)*0x8 + o)
  92. typedef struct I82365 I82365;
  93. /* a controller */
  94. enum
  95. {
  96. Ti82365,
  97. Tpd6710,
  98. Tpd6720,
  99. Tvg46x,
  100. };
  101. struct I82365
  102. {
  103. int type;
  104. int dev;
  105. int nslot;
  106. int xreg; /* index register address */
  107. int dreg; /* data register address */
  108. int irq;
  109. };
  110. static I82365 *controller[4];
  111. static int ncontroller;
  112. static PCMslot *slot;
  113. static PCMslot *lastslot;
  114. static nslot;
  115. static void i82365intr(Ureg*, void*);
  116. static void i82365reset(void);
  117. static int pcmio(int, ISAConf*);
  118. static void i82365dump(PCMslot*);
  119. void
  120. devi82365link(void)
  121. {
  122. static int already;
  123. char *p;
  124. if(already)
  125. return;
  126. already = 1;
  127. if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
  128. return;
  129. if (_pcmspecial)
  130. return;
  131. _pcmspecial = pcmcia_pcmspecial;
  132. _pcmspecialclose = pcmcia_pcmspecialclose;
  133. }
  134. /*
  135. * reading and writing card registers
  136. */
  137. static uchar
  138. rdreg(PCMslot *pp, int index)
  139. {
  140. outb(((I82365*)pp->cp)->xreg, pp->base + index);
  141. return inb(((I82365*)pp->cp)->dreg);
  142. }
  143. static void
  144. wrreg(PCMslot *pp, int index, uchar val)
  145. {
  146. outb(((I82365*)pp->cp)->xreg, pp->base + index);
  147. outb(((I82365*)pp->cp)->dreg, val);
  148. }
  149. /*
  150. * get info about card
  151. */
  152. static void
  153. slotinfo(PCMslot *pp)
  154. {
  155. uchar isr;
  156. isr = rdreg(pp, Ris);
  157. pp->occupied = (isr & (3<<2)) == (3<<2);
  158. pp->powered = isr & (1<<6);
  159. pp->battery = (isr & 3) == 3;
  160. pp->wrprot = isr & (1<<4);
  161. pp->busy = isr & (1<<5);
  162. //pp->msec = TK2MS(MACHP(0)->ticks);
  163. }
  164. static int
  165. vcode(int volt)
  166. {
  167. switch(volt){
  168. case 5:
  169. return 1;
  170. case 12:
  171. return 2;
  172. default:
  173. return 0;
  174. }
  175. }
  176. /*
  177. * enable the slot card
  178. */
  179. static void
  180. slotena(PCMslot *pp)
  181. {
  182. if(pp->enabled)
  183. return;
  184. /* power up and unreset, wait's are empirical (???) */
  185. wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
  186. delay(300);
  187. wrreg(pp, Rigc, 0);
  188. delay(100);
  189. wrreg(pp, Rigc, Fnotreset);
  190. delay(500);
  191. /* get configuration */
  192. slotinfo(pp);
  193. if(pp->occupied){
  194. pcmcisread(pp);
  195. pp->enabled = 1;
  196. } else
  197. wrreg(pp, Rpc, Fautopower);
  198. }
  199. /*
  200. * disable the slot card
  201. */
  202. static void
  203. slotdis(PCMslot *pp)
  204. {
  205. wrreg(pp, Rpc, 0); /* turn off card power */
  206. wrreg(pp, Rwe, 0); /* no windows */
  207. pp->enabled = 0;
  208. }
  209. /*
  210. * status change interrupt
  211. */
  212. static void
  213. i82365intr(Ureg *, void *)
  214. {
  215. uchar csc, was;
  216. PCMslot *pp;
  217. if(slot == 0)
  218. return;
  219. for(pp = slot; pp < lastslot; pp++){
  220. csc = rdreg(pp, Rcsc);
  221. was = pp->occupied;
  222. slotinfo(pp);
  223. if(csc & (1<<3) && was != pp->occupied){
  224. if(!pp->occupied)
  225. slotdis(pp);
  226. }
  227. }
  228. }
  229. enum
  230. {
  231. Mshift= 12,
  232. Mgran= (1<<Mshift), /* granularity of maps */
  233. Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
  234. };
  235. /*
  236. * get a map for pc card region, return corrected len
  237. */
  238. PCMmap*
  239. pcmmap(int slotno, ulong offset, int len, int attr)
  240. {
  241. PCMslot *pp;
  242. uchar we, bit;
  243. PCMmap *m, *nm;
  244. int i;
  245. ulong e;
  246. pp = slot + slotno;
  247. lock(&pp->mlock);
  248. /* convert offset to granularity */
  249. if(len <= 0)
  250. len = 1;
  251. e = ROUND(offset+len, Mgran);
  252. offset &= Mmask;
  253. len = e - offset;
  254. /* look for a map that covers the right area */
  255. we = rdreg(pp, Rwe);
  256. bit = 1;
  257. nm = 0;
  258. for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
  259. if((we & bit))
  260. if(m->attr == attr)
  261. if(offset >= m->ca && e <= m->cea){
  262. m->ref++;
  263. unlock(&pp->mlock);
  264. return m;
  265. }
  266. bit <<= 1;
  267. if(nm == 0 && m->ref == 0)
  268. nm = m;
  269. }
  270. m = nm;
  271. if(m == 0){
  272. unlock(&pp->mlock);
  273. return 0;
  274. }
  275. /* if isa space isn't big enough, free it and get more */
  276. if(m->len < len){
  277. if(m->isa){
  278. umbfree(m->isa, m->len);
  279. m->len = 0;
  280. }
  281. m->isa = PADDR(umbmalloc(0, len, Mgran));
  282. if(m->isa == 0){
  283. print("pcmmap %d: out of isa space\n", len);
  284. unlock(&pp->mlock);
  285. return 0;
  286. }
  287. m->len = len;
  288. }
  289. /* set up new map */
  290. m->ca = offset;
  291. m->cea = m->ca + m->len;
  292. m->attr = attr;
  293. i = m-pp->mmap;
  294. bit = 1<<i;
  295. wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
  296. wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
  297. wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
  298. wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
  299. wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
  300. offset -= m->isa;
  301. offset &= (1<<25)-1;
  302. offset >>= Mshift;
  303. wrreg(pp, MAP(i, Mofflo), offset);
  304. wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
  305. wrreg(pp, Rwe, we | bit); /* enable map */
  306. m->ref = 1;
  307. unlock(&pp->mlock);
  308. return m;
  309. }
  310. void
  311. pcmunmap(int slotno, PCMmap* m)
  312. {
  313. PCMslot *pp;
  314. pp = slot + slotno;
  315. lock(&pp->mlock);
  316. m->ref--;
  317. unlock(&pp->mlock);
  318. }
  319. static void
  320. increfp(PCMslot *pp)
  321. {
  322. lock(pp);
  323. if(pp->ref++ == 0)
  324. slotena(pp);
  325. unlock(pp);
  326. }
  327. static void
  328. decrefp(PCMslot *pp)
  329. {
  330. lock(pp);
  331. if(pp->ref-- == 1)
  332. slotdis(pp);
  333. unlock(pp);
  334. }
  335. /*
  336. * look for a card whose version contains 'idstr'
  337. */
  338. static int
  339. pcmcia_pcmspecial(char *idstr, ISAConf *isa)
  340. {
  341. PCMslot *pp;
  342. extern char *strstr(char*, char*);
  343. int enabled;
  344. i82365reset();
  345. for(pp = slot; pp < lastslot; pp++){
  346. if(pp->special)
  347. continue; /* already taken */
  348. enabled = 0;
  349. /* make sure we don't power on cards when we already know what's
  350. * in them. We'll reread every two minutes if necessary
  351. */
  352. if (pp->verstr[0] == '\0') {
  353. increfp(pp);
  354. enabled++;
  355. }
  356. if(pp->occupied) {
  357. if(strstr(pp->verstr, idstr)){
  358. if (!enabled){
  359. enabled = 1;
  360. increfp(pp);
  361. }
  362. if(isa == 0 || pcmio(pp->slotno, isa) == 0){
  363. pp->special = 1;
  364. return pp->slotno;
  365. }
  366. }
  367. } else
  368. pp->special = 1;
  369. if (enabled)
  370. decrefp(pp);
  371. }
  372. return -1;
  373. }
  374. static void
  375. pcmcia_pcmspecialclose(int slotno)
  376. {
  377. PCMslot *pp;
  378. print("pcmspecialclose called\n");
  379. if(slotno >= nslot)
  380. panic("pcmspecialclose");
  381. pp = slot + slotno;
  382. pp->special = 0;
  383. decrefp(pp);
  384. }
  385. static char *chipname[] =
  386. {
  387. [Ti82365] "Intel 82365SL",
  388. [Tpd6710] "Cirrus Logic PD6710",
  389. [Tpd6720] "Cirrus Logic PD6720",
  390. [Tvg46x] "Vadem VG-46x",
  391. };
  392. static I82365*
  393. i82365probe(int x, int d, int dev)
  394. {
  395. uchar c, id;
  396. I82365 *cp;
  397. ISAConf isa;
  398. int i, nslot;
  399. outb(x, Rid + (dev<<7));
  400. id = inb(d);
  401. if((id & 0xf0) != 0x80)
  402. return 0; /* not a memory & I/O card */
  403. if((id & 0x0f) == 0x00)
  404. return 0; /* no revision number, not possible */
  405. cp = xalloc(sizeof(I82365));
  406. cp->xreg = x;
  407. cp->dreg = d;
  408. cp->dev = dev;
  409. cp->type = Ti82365;
  410. cp->nslot = 2;
  411. switch(id){
  412. case 0x82:
  413. case 0x83:
  414. case 0x84:
  415. /* could be a cirrus */
  416. outb(x, Rchipinfo + (dev<<7));
  417. outb(d, 0);
  418. c = inb(d);
  419. if((c & 0xc0) != 0xc0)
  420. break;
  421. c = inb(d);
  422. if((c & 0xc0) != 0x00)
  423. break;
  424. if(c & 0x20){
  425. cp->type = Tpd6720;
  426. } else {
  427. cp->type = Tpd6710;
  428. cp->nslot = 1;
  429. }
  430. /* low power mode */
  431. outb(x, Rmisc2 + (dev<<7));
  432. c = inb(d);
  433. outb(d, c & ~Flowpow);
  434. break;
  435. }
  436. /* if it's not a Cirrus, it could be a Vadem... */
  437. if(cp->type == Ti82365){
  438. /* unlock the Vadem extended regs */
  439. outb(x, 0x0E + (dev<<7));
  440. outb(x, 0x37 + (dev<<7));
  441. /* make the id register show the Vadem id */
  442. outb(x, 0x3A + (dev<<7));
  443. c = inb(d);
  444. outb(d, c|0xC0);
  445. outb(x, Rid + (dev<<7));
  446. c = inb(d);
  447. if(c & 0x08)
  448. cp->type = Tvg46x;
  449. /* go back to Intel compatible id */
  450. outb(x, 0x3A + (dev<<7));
  451. c = inb(d);
  452. outb(d, c & ~0xC0);
  453. }
  454. memset(&isa, 0, sizeof(ISAConf));
  455. if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
  456. cp->irq = isa.irq;
  457. else
  458. cp->irq = VectorPCMCIA - VectorPIC;
  459. for(i = 0; i < isa.nopt; i++){
  460. if(cistrncmp(isa.opt[i], "nslot=", 6))
  461. continue;
  462. nslot = strtol(&isa.opt[i][6], nil, 0);
  463. if(nslot > 0 && nslot <= 2)
  464. cp->nslot = nslot;
  465. }
  466. controller[ncontroller++] = cp;
  467. return cp;
  468. }
  469. static void
  470. i82365dump(PCMslot *pp)
  471. {
  472. int i;
  473. for(i = 0; i < 0x40; i++){
  474. if((i&0x0F) == 0)
  475. print("\n%2.2uX: ", i);
  476. if(((i+1) & 0x0F) == 0x08)
  477. print(" - ");
  478. print("%2.2uX ", rdreg(pp, i));
  479. }
  480. print("\n");
  481. }
  482. /*
  483. * set up for slot cards
  484. */
  485. static void
  486. i82365reset(void)
  487. {
  488. static int already;
  489. int i, j;
  490. I82365 *cp;
  491. PCMslot *pp;
  492. if(already)
  493. return;
  494. already = 1;
  495. /* look for controllers */
  496. i82365probe(0x3E0, 0x3E1, 0);
  497. i82365probe(0x3E0, 0x3E1, 1);
  498. i82365probe(0x3E2, 0x3E3, 0);
  499. i82365probe(0x3E2, 0x3E3, 1);
  500. for(i = 0; i < ncontroller; i++)
  501. nslot += controller[i]->nslot;
  502. slot = xalloc(nslot * sizeof(PCMslot));
  503. lastslot = slot;
  504. for(i = 0; i < ncontroller; i++){
  505. cp = controller[i];
  506. print("#y%d: %d slot %s: port 0x%uX irq %d\n",
  507. i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
  508. for(j = 0; j < cp->nslot; j++){
  509. pp = lastslot++;
  510. pp->slotno = pp - slot;
  511. pp->memlen = 64*MB;
  512. pp->base = (cp->dev<<7) | (j<<6);
  513. pp->cp = cp;
  514. pp->msec = ~0;
  515. pp->verstr[0] = 0;
  516. slotdis(pp);
  517. /* interrupt on status change */
  518. wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
  519. rdreg(pp, Rcsc);
  520. }
  521. /* for card management interrupts */
  522. setvec(cp->irq+VectorPIC, i82365intr, 0);
  523. }
  524. }
  525. /*
  526. * configure the PCMslot for IO. We assume very heavily that we can read
  527. * configuration info from the CIS. If not, we won't set up correctly.
  528. */
  529. static int
  530. pcmio(int slotno, ISAConf *isa)
  531. {
  532. uchar we, x, *p;
  533. PCMslot *pp;
  534. PCMconftab *ct, *et, *t;
  535. PCMmap *m;
  536. int i, index, irq;
  537. char *cp;
  538. irq = isa->irq;
  539. if(irq == 2)
  540. irq = 9;
  541. if(slotno > nslot)
  542. return -1;
  543. pp = slot + slotno;
  544. if(!pp->occupied)
  545. return -1;
  546. et = &pp->ctab[pp->nctab];
  547. ct = 0;
  548. for(i = 0; i < isa->nopt; i++){
  549. if(strncmp(isa->opt[i], "index=", 6))
  550. continue;
  551. index = strtol(&isa->opt[i][6], &cp, 0);
  552. if(cp == &isa->opt[i][6] || index >= pp->nctab)
  553. return -1;
  554. ct = &pp->ctab[index];
  555. }
  556. if(ct == 0){
  557. /* assume default is right */
  558. if(pp->def)
  559. ct = pp->def;
  560. else
  561. ct = pp->ctab;
  562. /* try for best match */
  563. if(ct->nio == 0
  564. || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
  565. for(t = pp->ctab; t < et; t++)
  566. if(t->nio
  567. && t->io[0].start == isa->port
  568. && ((1<<irq) & t->irqs)){
  569. ct = t;
  570. break;
  571. }
  572. }
  573. if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
  574. for(t = pp->ctab; t < et; t++)
  575. if(t->nio && ((1<<irq) & t->irqs)){
  576. ct = t;
  577. break;
  578. }
  579. }
  580. if(ct->nio == 0){
  581. for(t = pp->ctab; t < et; t++)
  582. if(t->nio){
  583. ct = t;
  584. break;
  585. }
  586. }
  587. }
  588. if(ct == et || ct->nio == 0)
  589. return -1;
  590. if(isa->port == 0 && ct->io[0].start == 0)
  591. return -1;
  592. /* route interrupts */
  593. isa->irq = irq;
  594. wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
  595. /* set power and enable device */
  596. x = vcode(ct->vpp1);
  597. wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
  598. /* 16-bit data path */
  599. if(ct->bit16)
  600. x = Ftiming|Fiocs16|Fwidth16;
  601. else
  602. x = Ftiming;
  603. if(ct->nio == 2 && ct->io[1].start)
  604. x |= x<<4;
  605. wrreg(pp, Rio, x);
  606. /*
  607. * enable io port map 0
  608. * the 'top' register value includes the last valid address
  609. */
  610. if(isa->port == 0)
  611. isa->port = ct->io[0].start;
  612. we = rdreg(pp, Rwe);
  613. wrreg(pp, Riobtm0lo, isa->port);
  614. wrreg(pp, Riobtm0hi, isa->port>>8);
  615. i = isa->port+ct->io[0].len-1;
  616. wrreg(pp, Riotop0lo, i);
  617. wrreg(pp, Riotop0hi, i>>8);
  618. we |= 1<<6;
  619. if(ct->nio >= 2 && ct->io[1].start){
  620. wrreg(pp, Riobtm1lo, ct->io[1].start);
  621. wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
  622. i = ct->io[1].start+ct->io[1].len-1;
  623. wrreg(pp, Riotop1lo, i);
  624. wrreg(pp, Riotop1hi, i>>8);
  625. we |= 1<<7;
  626. }
  627. wrreg(pp, Rwe, we);
  628. /* only touch Rconfig if it is present */
  629. m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
  630. p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
  631. if(pp->cfg[0].cpresent & (1<<Rconfig)){
  632. /* Reset adapter */
  633. /* set configuration and interrupt type.
  634. * if level is possible on the card, use it.
  635. */
  636. x = ct->index;
  637. if(ct->irqtype & 0x20)
  638. x |= Clevel;
  639. /* enable the device, enable address decode and
  640. * irq enable.
  641. */
  642. x |= Cfunc|Cdecode|Cirq;
  643. p[0] = x;
  644. //delay(5);
  645. microdelay(40);
  646. }
  647. if(pp->cfg[0].cpresent & (1<<Riobase0)){
  648. /* set up the iobase 0 */
  649. p[Riobase0 << 1] = isa->port;
  650. p[Riobase1 << 1] = isa->port >> 8;
  651. }
  652. if(pp->cfg[0].cpresent & (1<<Riosize))
  653. p[Riosize << 1] = ct->io[0].len;
  654. pcmunmap(slotno, m);
  655. return 0;
  656. }