isadma.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /* $OpenBSD: isadma.c,v 1.34 2015/03/14 03:38:47 jsg Exp $ */
  2. /* $NetBSD: isadma.c,v 1.32 1997/09/05 01:48:33 thorpej Exp $ */
  3. /*-
  4. * Copyright (c) 1997 The NetBSD Foundation, Inc.
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to The NetBSD Foundation
  8. * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
  9. * NASA Ames Research Center.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  24. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. * POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. /*
  33. * Device driver for the ISA on-board DMA controller.
  34. */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/device.h>
  38. #include <uvm/uvm_extern.h>
  39. #include <machine/bus.h>
  40. #include <dev/isa/isavar.h>
  41. #include <dev/isa/isadmavar.h>
  42. #include <dev/isa/isadmareg.h>
  43. #ifdef __ISADMA_COMPAT
  44. /* XXX ugly, but will go away soon... */
  45. struct device *isa_dev;
  46. bus_dmamap_t isadma_dmam[8];
  47. #endif
  48. /* Used by isa_malloc() */
  49. #include <sys/malloc.h>
  50. struct isa_mem {
  51. struct device *isadev;
  52. int chan;
  53. bus_size_t size;
  54. bus_addr_t addr;
  55. caddr_t kva;
  56. struct isa_mem *next;
  57. } *isa_mem_head = 0;
  58. /*
  59. * High byte of DMA address is stored in this DMAPG register for
  60. * the Nth DMA channel.
  61. */
  62. static int dmapageport[2][4] = {
  63. {0x7, 0x3, 0x1, 0x2},
  64. {0xf, 0xb, 0x9, 0xa}
  65. };
  66. static u_int8_t dmamode[4] = {
  67. DMA37MD_READ | DMA37MD_SINGLE,
  68. DMA37MD_WRITE | DMA37MD_SINGLE,
  69. DMA37MD_READ | DMA37MD_SINGLE | DMA37MD_LOOP,
  70. DMA37MD_WRITE | DMA37MD_SINGLE | DMA37MD_LOOP
  71. };
  72. int isadmamatch(struct device *, void *, void *);
  73. void isadmaattach(struct device *, struct device *, void *);
  74. struct cfattach isadma_ca = {
  75. sizeof(struct device), isadmamatch, isadmaattach
  76. };
  77. struct cfdriver isadma_cd = {
  78. NULL, "isadma", DV_DULL, 1
  79. };
  80. int
  81. isadmamatch(parent, match, aux)
  82. struct device *parent;
  83. void *match, *aux;
  84. {
  85. struct isa_attach_args *ia = aux;
  86. /* Sure we exist */
  87. ia->ia_iosize = 0;
  88. return (1);
  89. }
  90. void
  91. isadmaattach(parent, self, aux)
  92. struct device *parent, *self;
  93. void *aux;
  94. {
  95. #ifdef __ISADMA_COMPAT
  96. int i, sz;
  97. struct isa_softc *sc = (struct isa_softc *)parent;
  98. /* XXX ugly, but will go away soon... */
  99. isa_dev = parent;
  100. for (i = 0; i < 8; i++) {
  101. sz = (i & 4) ? 1 << 17 : 1 << 16;
  102. if ((bus_dmamap_create(sc->sc_dmat, sz, 1, sz, sz,
  103. BUS_DMA_24BIT|BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
  104. &isadma_dmam[i])) != 0)
  105. panic("isadmaattach: can not create DMA map");
  106. }
  107. #endif
  108. /* XXX I'd like to map the DMA ports here, see isa.c why not... */
  109. printf("\n");
  110. }
  111. static inline void isa_dmaunmask(struct isa_softc *, int);
  112. static inline void isa_dmamask(struct isa_softc *, int);
  113. static inline void
  114. isa_dmaunmask(sc, chan)
  115. struct isa_softc *sc;
  116. int chan;
  117. {
  118. int ochan = chan & 3;
  119. /* set dma channel mode, and set dma channel mode */
  120. if ((chan & 4) == 0)
  121. bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  122. DMA1_SMSK, ochan | DMA37SM_CLEAR);
  123. else
  124. bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  125. DMA2_SMSK, ochan | DMA37SM_CLEAR);
  126. }
  127. static inline void
  128. isa_dmamask(sc, chan)
  129. struct isa_softc *sc;
  130. int chan;
  131. {
  132. int ochan = chan & 3;
  133. /* set dma channel mode, and set dma channel mode */
  134. if ((chan & 4) == 0) {
  135. bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  136. DMA1_SMSK, ochan | DMA37SM_SET);
  137. bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  138. DMA1_FFC, 0);
  139. } else {
  140. bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  141. DMA2_SMSK, ochan | DMA37SM_SET);
  142. bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  143. DMA2_FFC, 0);
  144. }
  145. }
  146. /*
  147. * isa_dmacascade(): program 8237 DMA controller channel to accept
  148. * external dma control by a board.
  149. */
  150. void
  151. isa_dmacascade(isadev, chan)
  152. struct device *isadev;
  153. int chan;
  154. {
  155. struct isa_softc *sc = (struct isa_softc *)isadev;
  156. int ochan = chan & 3;
  157. if (chan < 0 || chan > 7) {
  158. printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  159. goto lose;
  160. }
  161. if (ISA_DRQ_ISFREE(sc, chan) == 0) {
  162. printf("%s: DRQ %d is not free\n", sc->sc_dev.dv_xname, chan);
  163. goto lose;
  164. }
  165. ISA_DRQ_ALLOC(sc, chan);
  166. /* set dma channel mode, and set dma channel mode */
  167. if ((chan & 4) == 0)
  168. bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
  169. DMA1_MODE, ochan | DMA37MD_CASCADE);
  170. else
  171. bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
  172. DMA2_MODE, ochan | DMA37MD_CASCADE);
  173. isa_dmaunmask(sc, chan);
  174. return;
  175. lose:
  176. panic("isa_dmacascade");
  177. }
  178. int
  179. isa_dmamap_create(isadev, chan, size, flags)
  180. struct device *isadev;
  181. int chan;
  182. bus_size_t size;
  183. int flags;
  184. {
  185. struct isa_softc *sc = (struct isa_softc *)isadev;
  186. bus_size_t maxsize;
  187. if (chan < 0 || chan > 7) {
  188. printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  189. goto lose;
  190. }
  191. if (chan & 4)
  192. maxsize = (1 << 17);
  193. else
  194. maxsize = (1 << 16);
  195. if (size > maxsize)
  196. return (EINVAL);
  197. if (ISA_DRQ_ISFREE(sc, chan) == 0) {
  198. printf("%s: drq %d is not free\n", sc->sc_dev.dv_xname, chan);
  199. goto lose;
  200. }
  201. ISA_DRQ_ALLOC(sc, chan);
  202. return (bus_dmamap_create(sc->sc_dmat, size, 1, size, maxsize,
  203. flags, &sc->sc_dmamaps[chan]));
  204. lose:
  205. panic("isa_dmamap_create");
  206. }
  207. void
  208. isa_dmamap_destroy(isadev, chan)
  209. struct device *isadev;
  210. int chan;
  211. {
  212. struct isa_softc *sc = (struct isa_softc *)isadev;
  213. if (chan < 0 || chan > 7) {
  214. printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  215. goto lose;
  216. }
  217. if (ISA_DRQ_ISFREE(sc, chan)) {
  218. printf("%s: drq %d is already free\n",
  219. sc->sc_dev.dv_xname, chan);
  220. goto lose;
  221. }
  222. ISA_DRQ_FREE(sc, chan);
  223. bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamaps[chan]);
  224. return;
  225. lose:
  226. panic("isa_dmamap_destroy");
  227. }
  228. /*
  229. * isa_dmastart(): program 8237 DMA controller channel and set it
  230. * in motion.
  231. */
  232. int
  233. isa_dmastart(isadev, chan, addr, nbytes, p, flags, busdmaflags)
  234. struct device *isadev;
  235. int chan;
  236. void *addr;
  237. bus_size_t nbytes;
  238. struct proc *p;
  239. int flags;
  240. int busdmaflags;
  241. {
  242. struct isa_softc *sc = (struct isa_softc *)isadev;
  243. bus_dmamap_t dmam;
  244. bus_addr_t dmaaddr;
  245. int waport;
  246. int ochan = chan & 3;
  247. int error;
  248. #ifdef __ISADMA_COMPAT
  249. int compat = busdmaflags & BUS_DMA_BUS1;
  250. busdmaflags &= ~BUS_DMA_BUS1;
  251. #endif /* __ISADMA_COMPAT */
  252. if (chan < 0 || chan > 7) {
  253. printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
  254. goto lose;
  255. }
  256. #ifdef ISADMA_DEBUG
  257. printf("isa_dmastart: drq %d, addr %p, nbytes 0x%lx, p %p, "
  258. "flags 0x%x, dmaflags 0x%x\n",
  259. chan, addr, nbytes, p, flags, busdmaflags);
  260. #endif
  261. if (chan & 4) {
  262. if (nbytes > (1 << 17) || nbytes & 1 || (u_long)addr & 1) {
  263. printf("%s: drq %d, nbytes 0x%lx, addr %p\n",
  264. sc->sc_dev.dv_xname, chan, nbytes, addr);
  265. goto lose;
  266. }
  267. } else {
  268. if (nbytes > (1 << 16)) {
  269. printf("%s: drq %d, nbytes 0x%lx\n",
  270. sc->sc_dev.dv_xname, chan, nbytes);
  271. goto lose;
  272. }
  273. }
  274. dmam = sc->sc_dmamaps[chan];
  275. if (dmam == NULL) {
  276. #ifdef __ISADMA_COMPAT
  277. if (compat)
  278. dmam = sc->sc_dmamaps[chan] = isadma_dmam[chan];
  279. else
  280. #endif /* __ISADMA_COMPAT */
  281. panic("isa_dmastart: no DMA map for chan %d", chan);
  282. }
  283. error = bus_dmamap_load(sc->sc_dmat, dmam, addr, nbytes, p,
  284. busdmaflags);
  285. if (error)
  286. return (error);
  287. #ifdef ISADMA_DEBUG
  288. __asm(".globl isa_dmastart_afterload ; isa_dmastart_afterload:");
  289. #endif
  290. if (flags & DMAMODE_READ) {
  291. bus_dmamap_sync(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  292. BUS_DMASYNC_PREREAD);
  293. sc->sc_dmareads |= (1 << chan);
  294. } else {
  295. bus_dmamap_sync(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  296. BUS_DMASYNC_PREWRITE);
  297. sc->sc_dmareads &= ~(1 << chan);
  298. }
  299. dmaaddr = dmam->dm_segs[0].ds_addr;
  300. #ifdef ISADMA_DEBUG
  301. printf(" dmaaddr 0x%lx\n", dmaaddr);
  302. __asm(".globl isa_dmastart_aftersync ; isa_dmastart_aftersync:");
  303. #endif
  304. sc->sc_dmalength[chan] = nbytes;
  305. isa_dmamask(sc, chan);
  306. sc->sc_dmafinished &= ~(1 << chan);
  307. if ((chan & 4) == 0) {
  308. /* set dma channel mode */
  309. bus_space_write_1(sc->sc_iot, sc->sc_dma1h, DMA1_MODE,
  310. ochan | dmamode[flags]);
  311. /* send start address */
  312. waport = DMA1_CHN(ochan);
  313. bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
  314. dmapageport[0][ochan], (dmaaddr >> 16) & 0xff);
  315. bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
  316. dmaaddr & 0xff);
  317. bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
  318. (dmaaddr >> 8) & 0xff);
  319. /* send count */
  320. bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
  321. (--nbytes) & 0xff);
  322. bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
  323. (nbytes >> 8) & 0xff);
  324. } else {
  325. /* set dma channel mode */
  326. bus_space_write_1(sc->sc_iot, sc->sc_dma2h, DMA2_MODE,
  327. ochan | dmamode[flags]);
  328. /* send start address */
  329. waport = DMA2_CHN(ochan);
  330. bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
  331. dmapageport[1][ochan], (dmaaddr >> 16) & 0xff);
  332. dmaaddr >>= 1;
  333. bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
  334. dmaaddr & 0xff);
  335. bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
  336. (dmaaddr >> 8) & 0xff);
  337. /* send count */
  338. nbytes >>= 1;
  339. bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
  340. (--nbytes) & 0xff);
  341. bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
  342. (nbytes >> 8) & 0xff);
  343. }
  344. isa_dmaunmask(sc, chan);
  345. return (0);
  346. lose:
  347. panic("isa_dmastart");
  348. }
  349. void
  350. isa_dmaabort(isadev, chan)
  351. struct device *isadev;
  352. int chan;
  353. {
  354. struct isa_softc *sc = (struct isa_softc *)isadev;
  355. if (chan < 0 || chan > 7) {
  356. panic("isa_dmaabort: %s: bogus drq %d", sc->sc_dev.dv_xname,
  357. chan);
  358. }
  359. isa_dmamask(sc, chan);
  360. bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamaps[chan]);
  361. sc->sc_dmareads &= ~(1 << chan);
  362. }
  363. bus_size_t
  364. isa_dmacount(isadev, chan)
  365. struct device *isadev;
  366. int chan;
  367. {
  368. struct isa_softc *sc = (struct isa_softc *)isadev;
  369. int waport;
  370. bus_size_t nbytes;
  371. int ochan = chan & 3;
  372. if (chan < 0 || chan > 7) {
  373. panic("isa_dmacount: %s: bogus drq %d", sc->sc_dev.dv_xname,
  374. chan);
  375. }
  376. isa_dmamask(sc, chan);
  377. /*
  378. * We have to shift the byte count by 1. If we're in auto-initialize
  379. * mode, the count may have wrapped around to the initial value. We
  380. * can't use the TC bit to check for this case, so instead we compare
  381. * against the original byte count.
  382. * If we're not in auto-initialize mode, then the count will wrap to
  383. * -1, so we also handle that case.
  384. */
  385. if ((chan & 4) == 0) {
  386. waport = DMA1_CHN(ochan);
  387. nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
  388. waport + 1) + 1;
  389. nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
  390. waport + 1) << 8;
  391. nbytes &= 0xffff;
  392. } else {
  393. waport = DMA2_CHN(ochan);
  394. nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
  395. waport + 2) + 1;
  396. nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
  397. waport + 2) << 8;
  398. nbytes <<= 1;
  399. nbytes &= 0x1ffff;
  400. }
  401. if (nbytes == sc->sc_dmalength[chan])
  402. nbytes = 0;
  403. isa_dmaunmask(sc, chan);
  404. return (nbytes);
  405. }
  406. int
  407. isa_dmafinished(isadev, chan)
  408. struct device *isadev;
  409. int chan;
  410. {
  411. struct isa_softc *sc = (struct isa_softc *)isadev;
  412. if (chan < 0 || chan > 7) {
  413. panic("isa_dmafinished: %s: bogus drq %d", sc->sc_dev.dv_xname,
  414. chan);
  415. }
  416. /* check that the terminal count was reached */
  417. if ((chan & 4) == 0)
  418. sc->sc_dmafinished |= bus_space_read_1(sc->sc_iot,
  419. sc->sc_dma1h, DMA1_SR) & 0x0f;
  420. else
  421. sc->sc_dmafinished |= (bus_space_read_1(sc->sc_iot,
  422. sc->sc_dma2h, DMA2_SR) & 0x0f) << 4;
  423. return ((sc->sc_dmafinished & (1 << chan)) != 0);
  424. }
  425. void
  426. isa_dmadone(isadev, chan)
  427. struct device *isadev;
  428. int chan;
  429. {
  430. struct isa_softc *sc = (struct isa_softc *)isadev;
  431. bus_dmamap_t dmam;
  432. if (chan < 0 || chan > 7) {
  433. panic("isa_dmadone: %s: bogus drq %d", sc->sc_dev.dv_xname,
  434. chan);
  435. }
  436. dmam = sc->sc_dmamaps[chan];
  437. isa_dmamask(sc, chan);
  438. if (isa_dmafinished(isadev, chan) == 0)
  439. printf("%s: isa_dmadone: channel %d not finished\n",
  440. sc->sc_dev.dv_xname, chan);
  441. bus_dmamap_sync(sc->sc_dmat, dmam, 0, dmam->dm_mapsize,
  442. (sc->sc_dmareads & (1 << chan)) ? BUS_DMASYNC_POSTREAD :
  443. BUS_DMASYNC_POSTWRITE);
  444. bus_dmamap_unload(sc->sc_dmat, dmam);
  445. sc->sc_dmareads &= ~(1 << chan);
  446. }
  447. int
  448. isa_dmamem_alloc(isadev, chan, size, addrp, flags)
  449. struct device *isadev;
  450. int chan;
  451. bus_size_t size;
  452. bus_addr_t *addrp;
  453. int flags;
  454. {
  455. struct isa_softc *sc = (struct isa_softc *)isadev;
  456. bus_dma_segment_t seg;
  457. int error, boundary, rsegs;
  458. if (chan < 0 || chan > 7) {
  459. panic("isa_dmamem_alloc: %s: bogus drq %d",
  460. sc->sc_dev.dv_xname, chan);
  461. }
  462. boundary = (chan & 4) ? (1 << 17) : (1 << 16);
  463. size = round_page(size);
  464. error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, boundary,
  465. &seg, 1, &rsegs, flags);
  466. if (error)
  467. return (error);
  468. *addrp = seg.ds_addr;
  469. return (0);
  470. }
  471. void
  472. isa_dmamem_free(isadev, chan, addr, size)
  473. struct device *isadev;
  474. int chan;
  475. bus_addr_t addr;
  476. bus_size_t size;
  477. {
  478. struct isa_softc *sc = (struct isa_softc *)isadev;
  479. bus_dma_segment_t seg;
  480. if (chan < 0 || chan > 7) {
  481. panic("isa_dmamem_free: %s: bogus drq %d",
  482. sc->sc_dev.dv_xname, chan);
  483. }
  484. seg.ds_addr = addr;
  485. seg.ds_len = size;
  486. bus_dmamem_free(sc->sc_dmat, &seg, 1);
  487. }
  488. int
  489. isa_dmamem_map(isadev, chan, addr, size, kvap, flags)
  490. struct device *isadev;
  491. int chan;
  492. bus_addr_t addr;
  493. bus_size_t size;
  494. caddr_t *kvap;
  495. int flags;
  496. {
  497. struct isa_softc *sc = (struct isa_softc *)isadev;
  498. bus_dma_segment_t seg;
  499. if (chan < 0 || chan > 7) {
  500. panic("isa_dmamem_map: %s: bogus drq %d", sc->sc_dev.dv_xname,
  501. chan);
  502. }
  503. seg.ds_addr = addr;
  504. seg.ds_len = size;
  505. return (bus_dmamem_map(sc->sc_dmat, &seg, 1, size, kvap, flags));
  506. }
  507. void
  508. isa_dmamem_unmap(isadev, chan, kva, size)
  509. struct device *isadev;
  510. int chan;
  511. caddr_t kva;
  512. size_t size;
  513. {
  514. struct isa_softc *sc = (struct isa_softc *)isadev;
  515. if (chan < 0 || chan > 7) {
  516. panic("isa_dmamem_unmap: %s: bogus drq %d",
  517. sc->sc_dev.dv_xname, chan);
  518. }
  519. bus_dmamem_unmap(sc->sc_dmat, kva, size);
  520. }
  521. int
  522. isa_dmamem_mmap(isadev, chan, addr, size, off, prot, flags)
  523. struct device *isadev;
  524. int chan;
  525. bus_addr_t addr;
  526. bus_size_t size;
  527. int off, prot, flags;
  528. {
  529. struct isa_softc *sc = (struct isa_softc *)isadev;
  530. bus_dma_segment_t seg;
  531. if (chan < 0 || chan > 7) {
  532. panic("isa_dmamem_mmap: %s: bogus drq %d", sc->sc_dev.dv_xname,
  533. chan);
  534. }
  535. if (off < 0)
  536. return (-1);
  537. seg.ds_addr = addr;
  538. seg.ds_len = size;
  539. return (bus_dmamem_mmap(sc->sc_dmat, &seg, 1, off, prot, flags));
  540. }
  541. int
  542. isa_drq_isfree(isadev, chan)
  543. struct device *isadev;
  544. int chan;
  545. {
  546. struct isa_softc *sc = (struct isa_softc *)isadev;
  547. if (chan < 0 || chan > 7) {
  548. panic("isa_drq_isfree: %s: bogus drq %d", sc->sc_dev.dv_xname,
  549. chan);
  550. }
  551. return ISA_DRQ_ISFREE(sc, chan);
  552. }
  553. void *
  554. isa_malloc(isadev, chan, size, pool, flags)
  555. struct device *isadev;
  556. int chan;
  557. size_t size;
  558. int pool;
  559. int flags;
  560. {
  561. bus_addr_t addr;
  562. caddr_t kva;
  563. int bflags;
  564. struct isa_mem *m;
  565. bflags = flags & M_NOWAIT ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
  566. if (isa_dmamem_alloc(isadev, chan, size, &addr, bflags))
  567. return 0;
  568. if (isa_dmamem_map(isadev, chan, addr, size, &kva, bflags)) {
  569. isa_dmamem_free(isadev, chan, addr, size);
  570. return 0;
  571. }
  572. m = malloc(sizeof(*m), pool, flags);
  573. if (m == 0) {
  574. isa_dmamem_unmap(isadev, chan, kva, size);
  575. isa_dmamem_free(isadev, chan, addr, size);
  576. return 0;
  577. }
  578. m->isadev = isadev;
  579. m->chan = chan;
  580. m->size = size;
  581. m->addr = addr;
  582. m->kva = kva;
  583. m->next = isa_mem_head;
  584. isa_mem_head = m;
  585. return (void *)kva;
  586. }
  587. void
  588. isa_free(addr, pool)
  589. void *addr;
  590. int pool;
  591. {
  592. struct isa_mem **mp, *m;
  593. caddr_t kva = (caddr_t)addr;
  594. for(mp = &isa_mem_head; *mp && (*mp)->kva != kva; mp = &(*mp)->next)
  595. ;
  596. m = *mp;
  597. if (!m) {
  598. printf("isa_free: freeing unallocated memory\n");
  599. return;
  600. }
  601. *mp = m->next;
  602. isa_dmamem_unmap(m->isadev, m->chan, kva, m->size);
  603. isa_dmamem_free(m->isadev, m->chan, m->addr, m->size);
  604. free(m, pool, 0);
  605. }
  606. paddr_t
  607. isa_mappage(mem, off, prot)
  608. void *mem;
  609. off_t off;
  610. int prot;
  611. {
  612. struct isa_mem *m;
  613. for(m = isa_mem_head; m && m->kva != (caddr_t)mem; m = m->next)
  614. ;
  615. if (!m) {
  616. printf("isa_mappage: mapping unallocated memory\n");
  617. return -1;
  618. }
  619. return (isa_dmamem_mmap(m->isadev, m->chan, m->addr, m->size, off,
  620. prot, BUS_DMA_WAITOK));
  621. }