devi82365.c 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/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. #define MAP(x,o) (Rmap + (x)*0x8 + o)
  90. typedef struct I82365 I82365;
  91. /* a controller */
  92. enum
  93. {
  94. Ti82365,
  95. Tpd6710,
  96. Tpd6720,
  97. Tvg46x,
  98. };
  99. struct I82365
  100. {
  101. int type;
  102. int dev;
  103. int nslot;
  104. int xreg; /* index register address */
  105. int dreg; /* data register address */
  106. int irq;
  107. };
  108. static I82365 *controller[4];
  109. static int ncontroller;
  110. static PCMslot *slot;
  111. static PCMslot *lastslot;
  112. static nslot;
  113. static void i82365intr(Ureg*, void*);
  114. static int pcmio(int, ISAConf*);
  115. static long pcmread(int, int, void*, long, vlong);
  116. static long pcmwrite(int, int, void*, long, vlong);
  117. static void i82365dump(PCMslot*);
  118. /*
  119. * reading and writing card registers
  120. */
  121. static uchar
  122. rdreg(PCMslot *pp, int index)
  123. {
  124. outb(((I82365*)pp->cp)->xreg, pp->base + index);
  125. return inb(((I82365*)pp->cp)->dreg);
  126. }
  127. static void
  128. wrreg(PCMslot *pp, int index, uchar val)
  129. {
  130. outb(((I82365*)pp->cp)->xreg, pp->base + index);
  131. outb(((I82365*)pp->cp)->dreg, val);
  132. }
  133. /*
  134. * get info about card
  135. */
  136. static void
  137. slotinfo(PCMslot *pp)
  138. {
  139. uchar isr;
  140. isr = rdreg(pp, Ris);
  141. pp->occupied = (isr & (3<<2)) == (3<<2);
  142. pp->powered = isr & (1<<6);
  143. pp->battery = (isr & 3) == 3;
  144. pp->wrprot = isr & (1<<4);
  145. pp->busy = isr & (1<<5);
  146. pp->msec = TK2MS(MACHP(0)->ticks);
  147. }
  148. static int
  149. vcode(int volt)
  150. {
  151. switch(volt){
  152. case 5:
  153. return 1;
  154. case 12:
  155. return 2;
  156. default:
  157. return 0;
  158. }
  159. }
  160. /*
  161. * enable the slot card
  162. */
  163. static void
  164. slotena(PCMslot *pp)
  165. {
  166. if(pp->enabled)
  167. return;
  168. /* power up and unreset, wait's are empirical (???) */
  169. wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
  170. delay(300);
  171. wrreg(pp, Rigc, 0);
  172. delay(100);
  173. wrreg(pp, Rigc, Fnotreset);
  174. delay(500);
  175. /* get configuration */
  176. slotinfo(pp);
  177. if(pp->occupied){
  178. pcmcisread(pp);
  179. pp->enabled = 1;
  180. } else
  181. wrreg(pp, Rpc, Fautopower);
  182. }
  183. /*
  184. * disable the slot card
  185. */
  186. static void
  187. slotdis(PCMslot *pp)
  188. {
  189. wrreg(pp, Rpc, 0); /* turn off card power */
  190. wrreg(pp, Rwe, 0); /* no windows */
  191. pp->enabled = 0;
  192. }
  193. /*
  194. * status change interrupt
  195. */
  196. static void
  197. i82365intr(Ureg *, void *)
  198. {
  199. uchar csc, was;
  200. PCMslot *pp;
  201. if(slot == 0)
  202. return;
  203. for(pp = slot; pp < lastslot; pp++){
  204. csc = rdreg(pp, Rcsc);
  205. was = pp->occupied;
  206. slotinfo(pp);
  207. if(csc & (1<<3) && was != pp->occupied){
  208. if(!pp->occupied)
  209. slotdis(pp);
  210. }
  211. }
  212. }
  213. enum
  214. {
  215. Mshift= 12,
  216. Mgran= (1<<Mshift), /* granularity of maps */
  217. Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
  218. };
  219. /*
  220. * get a map for pc card region, return corrected len
  221. */
  222. PCMmap*
  223. pcmmap(int slotno, ulong offset, int len, int attr)
  224. {
  225. PCMslot *pp;
  226. uchar we, bit;
  227. PCMmap *m, *nm;
  228. int i;
  229. ulong e;
  230. pp = slot + slotno;
  231. lock(&pp->mlock);
  232. /* convert offset to granularity */
  233. if(len <= 0)
  234. len = 1;
  235. e = ROUND(offset+len, Mgran);
  236. offset &= Mmask;
  237. len = e - offset;
  238. /* look for a map that covers the right area */
  239. we = rdreg(pp, Rwe);
  240. bit = 1;
  241. nm = 0;
  242. for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
  243. if((we & bit))
  244. if(m->attr == attr)
  245. if(offset >= m->ca && e <= m->cea){
  246. m->ref++;
  247. unlock(&pp->mlock);
  248. return m;
  249. }
  250. bit <<= 1;
  251. if(nm == 0 && m->ref == 0)
  252. nm = m;
  253. }
  254. m = nm;
  255. if(m == 0){
  256. unlock(&pp->mlock);
  257. return 0;
  258. }
  259. /* if isa space isn't big enough, free it and get more */
  260. if(m->len < len){
  261. if(m->isa){
  262. umbfree(m->isa, m->len);
  263. m->len = 0;
  264. }
  265. m->isa = PADDR(umbmalloc(0, len, Mgran));
  266. if(m->isa == 0){
  267. print("pcmmap: out of isa space\n");
  268. unlock(&pp->mlock);
  269. return 0;
  270. }
  271. m->len = len;
  272. }
  273. /* set up new map */
  274. m->ca = offset;
  275. m->cea = m->ca + m->len;
  276. m->attr = attr;
  277. i = m-pp->mmap;
  278. bit = 1<<i;
  279. wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
  280. wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
  281. wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
  282. wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
  283. wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
  284. offset -= m->isa;
  285. offset &= (1<<25)-1;
  286. offset >>= Mshift;
  287. wrreg(pp, MAP(i, Mofflo), offset);
  288. wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
  289. wrreg(pp, Rwe, we | bit); /* enable map */
  290. m->ref = 1;
  291. unlock(&pp->mlock);
  292. return m;
  293. }
  294. void
  295. pcmunmap(int slotno, PCMmap* m)
  296. {
  297. PCMslot *pp;
  298. pp = slot + slotno;
  299. lock(&pp->mlock);
  300. m->ref--;
  301. unlock(&pp->mlock);
  302. }
  303. static void
  304. increfp(PCMslot *pp)
  305. {
  306. lock(pp);
  307. if(pp->ref++ == 0)
  308. slotena(pp);
  309. unlock(pp);
  310. }
  311. static void
  312. decrefp(PCMslot *pp)
  313. {
  314. lock(pp);
  315. if(pp->ref-- == 1)
  316. slotdis(pp);
  317. unlock(pp);
  318. }
  319. /*
  320. * look for a card whose version contains 'idstr'
  321. */
  322. static int
  323. pcmcia_pcmspecial(char *idstr, ISAConf *isa)
  324. {
  325. PCMslot *pp;
  326. extern char *strstr(char*, char*);
  327. int enabled;
  328. for(pp = slot; pp < lastslot; pp++){
  329. if(pp->special)
  330. continue; /* already taken */
  331. /*
  332. * make sure we don't power on cards when we already know what's
  333. * in them. We'll reread every two minutes if necessary
  334. */
  335. enabled = 0;
  336. if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){
  337. increfp(pp);
  338. enabled++;
  339. }
  340. if(pp->occupied) {
  341. if(strstr(pp->verstr, idstr)){
  342. if (!enabled){
  343. enabled = 1;
  344. increfp(pp);
  345. }
  346. if(isa == 0 || pcmio(pp->slotno, isa) == 0){
  347. pp->special = 1;
  348. return pp->slotno;
  349. }
  350. }
  351. } else
  352. pp->special = 1;
  353. if (enabled)
  354. decrefp(pp);
  355. }
  356. return -1;
  357. }
  358. static void
  359. pcmcia_pcmspecialclose(int slotno)
  360. {
  361. PCMslot *pp;
  362. if(slotno >= nslot)
  363. panic("pcmspecialclose");
  364. pp = slot + slotno;
  365. pp->special = 0;
  366. decrefp(pp);
  367. }
  368. enum
  369. {
  370. Qdir,
  371. Qmem,
  372. Qattr,
  373. Qctl,
  374. Nents = 3,
  375. };
  376. #define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
  377. #define TYPE(c) ((ulong)(c->qid.path&0xff))
  378. #define QID(s,t) (((s)<<8)|(t))
  379. static int
  380. pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
  381. {
  382. int slotno;
  383. Qid qid;
  384. long len;
  385. PCMslot *pp;
  386. if(i == DEVDOTDOT){
  387. mkqid(&qid, Qdir, 0, QTDIR);
  388. devdir(c, qid, "#y", 0, eve, 0555, dp);
  389. return 1;
  390. }
  391. if(i >= Nents*nslot)
  392. return -1;
  393. slotno = i/Nents;
  394. pp = slot + slotno;
  395. len = 0;
  396. switch(i%Nents){
  397. case 0:
  398. qid.path = QID(slotno, Qmem);
  399. snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
  400. len = pp->memlen;
  401. break;
  402. case 1:
  403. qid.path = QID(slotno, Qattr);
  404. snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
  405. len = pp->memlen;
  406. break;
  407. case 2:
  408. qid.path = QID(slotno, Qctl);
  409. snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
  410. break;
  411. }
  412. qid.vers = 0;
  413. qid.type = QTFILE;
  414. devdir(c, qid, up->genbuf, len, eve, 0660, dp);
  415. return 1;
  416. }
  417. static char *chipname[] =
  418. {
  419. [Ti82365] "Intel 82365SL",
  420. [Tpd6710] "Cirrus Logic CL-PD6710",
  421. [Tpd6720] "Cirrus Logic CL-PD6720",
  422. [Tvg46x] "Vadem VG-46x",
  423. };
  424. static I82365*
  425. i82365probe(int x, int d, int dev)
  426. {
  427. uchar c, id;
  428. I82365 *cp;
  429. ISAConf isa;
  430. int i, nslot;
  431. outb(x, Rid + (dev<<7));
  432. id = inb(d);
  433. if((id & 0xf0) != 0x80)
  434. return 0; /* not a memory & I/O card */
  435. if((id & 0x0f) == 0x00)
  436. return 0; /* no revision number, not possible */
  437. cp = xalloc(sizeof(I82365));
  438. cp->xreg = x;
  439. cp->dreg = d;
  440. cp->dev = dev;
  441. cp->type = Ti82365;
  442. cp->nslot = 2;
  443. switch(id){
  444. case 0x82:
  445. case 0x83:
  446. case 0x84:
  447. /* could be a cirrus */
  448. outb(x, Rchipinfo + (dev<<7));
  449. outb(d, 0);
  450. c = inb(d);
  451. if((c & 0xc0) != 0xc0)
  452. break;
  453. c = inb(d);
  454. if((c & 0xc0) != 0x00)
  455. break;
  456. if(c & 0x20){
  457. cp->type = Tpd6720;
  458. } else {
  459. cp->type = Tpd6710;
  460. cp->nslot = 1;
  461. }
  462. /* low power mode */
  463. outb(x, Rmisc2 + (dev<<7));
  464. c = inb(d);
  465. outb(d, c & ~Flowpow);
  466. break;
  467. }
  468. /* if it's not a Cirrus, it could be a Vadem... */
  469. if(cp->type == Ti82365){
  470. /* unlock the Vadem extended regs */
  471. outb(x, 0x0E + (dev<<7));
  472. outb(x, 0x37 + (dev<<7));
  473. /* make the id register show the Vadem id */
  474. outb(x, 0x3A + (dev<<7));
  475. c = inb(d);
  476. outb(d, c|0xC0);
  477. outb(x, Rid + (dev<<7));
  478. c = inb(d);
  479. if(c & 0x08)
  480. cp->type = Tvg46x;
  481. /* go back to Intel compatible id */
  482. outb(x, 0x3A + (dev<<7));
  483. c = inb(d);
  484. outb(d, c & ~0xC0);
  485. }
  486. memset(&isa, 0, sizeof(ISAConf));
  487. if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
  488. cp->irq = isa.irq;
  489. else
  490. cp->irq = IrqPCMCIA;
  491. for(i = 0; i < isa.nopt; i++){
  492. if(cistrncmp(isa.opt[i], "nslot=", 6))
  493. continue;
  494. nslot = strtol(&isa.opt[i][6], nil, 0);
  495. if(nslot > 0 && nslot <= 2)
  496. cp->nslot = nslot;
  497. }
  498. controller[ncontroller++] = cp;
  499. return cp;
  500. }
  501. static void
  502. i82365dump(PCMslot *pp)
  503. {
  504. int i;
  505. for(i = 0; i < 0x40; i++){
  506. if((i&0x0F) == 0)
  507. print("\n%2.2uX: ", i);
  508. print("%2.2uX ", rdreg(pp, i));
  509. if(((i+1) & 0x0F) == 0x08)
  510. print(" - ");
  511. }
  512. print("\n");
  513. }
  514. /*
  515. * set up for slot cards
  516. */
  517. void
  518. devi82365link(void)
  519. {
  520. static int already;
  521. int i, j;
  522. I82365 *cp;
  523. PCMslot *pp;
  524. char buf[32], *p;
  525. if(already)
  526. return;
  527. already = 1;
  528. if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
  529. return;
  530. if(_pcmspecial)
  531. return;
  532. /* look for controllers if the ports aren't already taken */
  533. if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
  534. i82365probe(0x3E0, 0x3E1, 0);
  535. i82365probe(0x3E0, 0x3E1, 1);
  536. if(ncontroller == 0)
  537. iofree(0x3E0);
  538. }
  539. if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
  540. i = ncontroller;
  541. i82365probe(0x3E2, 0x3E3, 0);
  542. i82365probe(0x3E2, 0x3E3, 1);
  543. if(ncontroller == i)
  544. iofree(0x3E2);
  545. }
  546. if(ncontroller == 0)
  547. return;
  548. _pcmspecial = pcmcia_pcmspecial;
  549. _pcmspecialclose = pcmcia_pcmspecialclose;
  550. for(i = 0; i < ncontroller; i++)
  551. nslot += controller[i]->nslot;
  552. slot = xalloc(nslot * sizeof(PCMslot));
  553. lastslot = slot;
  554. for(i = 0; i < ncontroller; i++){
  555. cp = controller[i];
  556. print("#y%d: %d slot %s: port 0x%uX irq %d\n",
  557. i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
  558. for(j = 0; j < cp->nslot; j++){
  559. pp = lastslot++;
  560. pp->slotno = pp - slot;
  561. pp->memlen = 64*MB;
  562. pp->base = (cp->dev<<7) | (j<<6);
  563. pp->cp = cp;
  564. pp->msec = ~0;
  565. pp->verstr[0] = 0;
  566. slotdis(pp);
  567. /* interrupt on status change */
  568. wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
  569. rdreg(pp, Rcsc);
  570. }
  571. /* for card management interrupts */
  572. snprint(buf, sizeof buf, "i82365.%d", i);
  573. intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf);
  574. }
  575. }
  576. static Chan*
  577. i82365attach(char *spec)
  578. {
  579. return devattach('y', spec);
  580. }
  581. static Walkqid*
  582. i82365walk(Chan *c, Chan *nc, char **name, int nname)
  583. {
  584. return devwalk(c, nc, name, nname, 0, 0, pcmgen);
  585. }
  586. static int
  587. i82365stat(Chan *c, uchar *db, int n)
  588. {
  589. return devstat(c, db, n, 0, 0, pcmgen);
  590. }
  591. static Chan*
  592. i82365open(Chan *c, int omode)
  593. {
  594. if(c->qid.type & QTDIR){
  595. if(omode != OREAD)
  596. error(Eperm);
  597. } else
  598. increfp(slot + SLOTNO(c));
  599. c->mode = openmode(omode);
  600. c->flag |= COPEN;
  601. c->offset = 0;
  602. return c;
  603. }
  604. static void
  605. i82365close(Chan *c)
  606. {
  607. if(c->flag & COPEN)
  608. if((c->qid.type & QTDIR) == 0)
  609. decrefp(slot+SLOTNO(c));
  610. }
  611. /* a memmove using only bytes */
  612. static void
  613. memmoveb(uchar *to, uchar *from, int n)
  614. {
  615. while(n-- > 0)
  616. *to++ = *from++;
  617. }
  618. /* a memmove using only shorts & bytes */
  619. static void
  620. memmoves(uchar *to, uchar *from, int n)
  621. {
  622. ushort *t, *f;
  623. if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
  624. while(n-- > 0)
  625. *to++ = *from++;
  626. } else {
  627. n = n/2;
  628. t = (ushort*)to;
  629. f = (ushort*)from;
  630. while(n-- > 0)
  631. *t++ = *f++;
  632. }
  633. }
  634. static long
  635. pcmread(int slotno, int attr, void *a, long n, vlong off)
  636. {
  637. int i, len;
  638. PCMmap *m;
  639. uchar *ac;
  640. PCMslot *pp;
  641. ulong offset = off;
  642. pp = slot + slotno;
  643. if(pp->memlen < offset)
  644. return 0;
  645. if(pp->memlen < offset + n)
  646. n = pp->memlen - offset;
  647. m = 0;
  648. if(waserror()){
  649. if(m)
  650. pcmunmap(pp->slotno, m);
  651. nexterror();
  652. }
  653. ac = a;
  654. for(len = n; len > 0; len -= i){
  655. m = pcmmap(pp->slotno, offset, 0, attr);
  656. if(m == 0)
  657. error("cannot map PCMCIA card");
  658. if(offset + len > m->cea)
  659. i = m->cea - offset;
  660. else
  661. i = len;
  662. memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
  663. pcmunmap(pp->slotno, m);
  664. offset += i;
  665. ac += i;
  666. }
  667. poperror();
  668. return n;
  669. }
  670. static long
  671. i82365read(Chan *c, void *a, long n, vlong off)
  672. {
  673. char *p, *buf, *e;
  674. PCMslot *pp;
  675. ulong offset = off;
  676. switch(TYPE(c)){
  677. case Qdir:
  678. return devdirread(c, a, n, 0, 0, pcmgen);
  679. case Qmem:
  680. case Qattr:
  681. return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
  682. case Qctl:
  683. buf = p = malloc(READSTR);
  684. if(p == nil)
  685. error(Enomem);
  686. e = p + READSTR;
  687. pp = slot + SLOTNO(c);
  688. buf[0] = 0;
  689. if(pp->occupied){
  690. p = seprint(p, e, "occupied\n");
  691. if(pp->verstr[0])
  692. p = seprint(p, e, "version %s\n", pp->verstr);
  693. }
  694. if(pp->enabled)
  695. p = seprint(p, e, "enabled\n");
  696. if(pp->powered)
  697. p = seprint(p, e, "powered\n");
  698. if(pp->configed)
  699. p = seprint(p, e, "configed\n");
  700. if(pp->wrprot)
  701. p = seprint(p, e, "write protected\n");
  702. if(pp->busy)
  703. p = seprint(p, e, "busy\n");
  704. seprint(p, e, "battery lvl %d\n", pp->battery);
  705. n = readstr(offset, a, n, buf);
  706. free(buf);
  707. return n;
  708. }
  709. error(Ebadarg);
  710. return -1; /* not reached */
  711. }
  712. static long
  713. pcmwrite(int dev, int attr, void *a, long n, vlong off)
  714. {
  715. int i, len;
  716. PCMmap *m;
  717. uchar *ac;
  718. PCMslot *pp;
  719. ulong offset = off;
  720. pp = slot + dev;
  721. if(pp->memlen < offset)
  722. return 0;
  723. if(pp->memlen < offset + n)
  724. n = pp->memlen - offset;
  725. m = 0;
  726. if(waserror()){
  727. if(m)
  728. pcmunmap(pp->slotno, m);
  729. nexterror();
  730. }
  731. ac = a;
  732. for(len = n; len > 0; len -= i){
  733. m = pcmmap(pp->slotno, offset, 0, attr);
  734. if(m == 0)
  735. error("cannot map PCMCIA card");
  736. if(offset + len > m->cea)
  737. i = m->cea - offset;
  738. else
  739. i = len;
  740. memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
  741. pcmunmap(pp->slotno, m);
  742. offset += i;
  743. ac += i;
  744. }
  745. poperror();
  746. return n;
  747. }
  748. static long
  749. i82365write(Chan *c, void *a, long n, vlong off)
  750. {
  751. PCMslot *pp;
  752. char buf[32];
  753. switch(TYPE(c)){
  754. case Qctl:
  755. if(n >= sizeof(buf))
  756. n = sizeof(buf) - 1;
  757. strncpy(buf, a, n);
  758. buf[n] = 0;
  759. pp = slot + SLOTNO(c);
  760. if(!pp->occupied)
  761. error(Eio);
  762. /* set vpp on card */
  763. if(strncmp(buf, "vpp", 3) == 0)
  764. wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena);
  765. return n;
  766. case Qmem:
  767. case Qattr:
  768. pp = slot + SLOTNO(c);
  769. if(pp->occupied == 0 || pp->enabled == 0)
  770. error(Eio);
  771. n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
  772. if(n < 0)
  773. error(Eio);
  774. return n;
  775. }
  776. error(Ebadarg);
  777. return -1; /* not reached */
  778. }
  779. Dev i82365devtab = {
  780. 'y',
  781. "i82365",
  782. devreset,
  783. devinit,
  784. devshutdown,
  785. i82365attach,
  786. i82365walk,
  787. i82365stat,
  788. i82365open,
  789. devcreate,
  790. i82365close,
  791. i82365read,
  792. devbread,
  793. i82365write,
  794. devbwrite,
  795. devremove,
  796. devwstat,
  797. };
  798. /*
  799. * configure the PCMslot for IO. We assume very heavily that we can read
  800. * configuration info from the CIS. If not, we won't set up correctly.
  801. */
  802. static int
  803. pcmio(int slotno, ISAConf *isa)
  804. {
  805. uchar we, x, *p;
  806. PCMslot *pp;
  807. PCMconftab *ct, *et, *t;
  808. PCMmap *m;
  809. int i, index, irq;
  810. char *cp;
  811. irq = isa->irq;
  812. if(irq == 2)
  813. irq = 9;
  814. if(slotno > nslot)
  815. return -1;
  816. pp = slot + slotno;
  817. if(!pp->occupied)
  818. return -1;
  819. et = &pp->ctab[pp->nctab];
  820. ct = 0;
  821. for(i = 0; i < isa->nopt; i++){
  822. if(strncmp(isa->opt[i], "index=", 6))
  823. continue;
  824. index = strtol(&isa->opt[i][6], &cp, 0);
  825. if(cp == &isa->opt[i][6] || index >= pp->nctab)
  826. return -1;
  827. ct = &pp->ctab[index];
  828. }
  829. if(ct == 0){
  830. /* assume default is right */
  831. if(pp->def)
  832. ct = pp->def;
  833. else
  834. ct = pp->ctab;
  835. /* try for best match */
  836. if(ct->nio == 0
  837. || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
  838. for(t = pp->ctab; t < et; t++)
  839. if(t->nio
  840. && t->io[0].start == isa->port
  841. && ((1<<irq) & t->irqs)){
  842. ct = t;
  843. break;
  844. }
  845. }
  846. if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
  847. for(t = pp->ctab; t < et; t++)
  848. if(t->nio && ((1<<irq) & t->irqs)){
  849. ct = t;
  850. break;
  851. }
  852. }
  853. if(ct->nio == 0){
  854. for(t = pp->ctab; t < et; t++)
  855. if(t->nio){
  856. ct = t;
  857. break;
  858. }
  859. }
  860. }
  861. if(ct == et || ct->nio == 0)
  862. return -1;
  863. if(isa->port == 0 && ct->io[0].start == 0)
  864. return -1;
  865. /* route interrupts */
  866. isa->irq = irq;
  867. wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
  868. /* set power and enable device */
  869. x = vcode(ct->vpp1);
  870. wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
  871. /* 16-bit data path */
  872. if(ct->bit16)
  873. x = Ftiming|Fiocs16|Fwidth16;
  874. else
  875. x = Ftiming;
  876. if(ct->nio == 2 && ct->io[1].start)
  877. x |= x<<4;
  878. wrreg(pp, Rio, x);
  879. /*
  880. * enable io port map 0
  881. * the 'top' register value includes the last valid address
  882. */
  883. if(isa->port == 0)
  884. isa->port = ct->io[0].start;
  885. we = rdreg(pp, Rwe);
  886. wrreg(pp, Riobtm0lo, isa->port);
  887. wrreg(pp, Riobtm0hi, isa->port>>8);
  888. i = isa->port+ct->io[0].len-1;
  889. wrreg(pp, Riotop0lo, i);
  890. wrreg(pp, Riotop0hi, i>>8);
  891. we |= 1<<6;
  892. if(ct->nio >= 2 && ct->io[1].start){
  893. wrreg(pp, Riobtm1lo, ct->io[1].start);
  894. wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
  895. i = ct->io[1].start+ct->io[1].len-1;
  896. wrreg(pp, Riotop1lo, i);
  897. wrreg(pp, Riotop1hi, i>>8);
  898. we |= 1<<7;
  899. }
  900. wrreg(pp, Rwe, we);
  901. /* only touch Rconfig if it is present */
  902. m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
  903. p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
  904. if(pp->cfg[0].cpresent & (1<<Rconfig)){
  905. /* Reset adapter */
  906. /* set configuration and interrupt type.
  907. * if level is possible on the card, use it.
  908. */
  909. x = ct->index;
  910. if(ct->irqtype & 0x20)
  911. x |= Clevel;
  912. /* enable the device, enable address decode and
  913. * irq enable.
  914. */
  915. x |= Cfunc|Cdecode|Cirq;
  916. p[0] = x;
  917. //delay(5);
  918. microdelay(40);
  919. }
  920. if(pp->cfg[0].cpresent & (1<<Riobase0)){
  921. /* set up the iobase 0 */
  922. p[Riobase0 << 1] = isa->port;
  923. p[Riobase1 << 1] = isa->port >> 8;
  924. }
  925. if(pp->cfg[0].cpresent & (1<<Riosize))
  926. p[Riosize << 1] = ct->io[0].len;
  927. pcmunmap(slotno, m);
  928. return 0;
  929. }