Home | History | Annotate | Line # | Download | only in dev
ldc.c revision 1.7
      1 /*	$NetBSD: ldc.c,v 1.7 2021/04/05 12:19:22 palle Exp $	*/
      2 /*	$OpenBSD: ldc.c,v 1.12 2015/03/21 18:02:58 kettenis Exp $	*/
      3 /*
      4  * Copyright (c) 2009 Mark Kettenis
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/kmem.h>
     20 #include <sys/malloc.h>
     21 #include <sys/param.h>
     22 #include <sys/systm.h>
     23 
     24 #include <sys/bus.h>
     25 #include <machine/hypervisor.h>
     26 
     27 #include <uvm/uvm_extern.h>
     28 
     29 #include <sparc64/dev/ldcvar.h>
     30 
     31 #ifdef LDC_DEBUG
     32 #define DPRINTF(x)	printf x
     33 #else
     34 #define DPRINTF(x)
     35 #endif
     36 
     37 void	ldc_rx_ctrl_vers(struct ldc_conn *, struct ldc_pkt *);
     38 void	ldc_rx_ctrl_rtr(struct ldc_conn *, struct ldc_pkt *);
     39 void	ldc_rx_ctrl_rts(struct ldc_conn *, struct ldc_pkt *);
     40 void	ldc_rx_ctrl_rdx(struct ldc_conn *, struct ldc_pkt *);
     41 
     42 void	ldc_send_ack(struct ldc_conn *);
     43 void	ldc_send_rtr(struct ldc_conn *);
     44 void	ldc_send_rts(struct ldc_conn *);
     45 void	ldc_send_rdx(struct ldc_conn *);
     46 
     47 void
     48 ldc_rx_ctrl(struct ldc_conn *lc, struct ldc_pkt *lp)
     49 {
     50 	switch (lp->ctrl) {
     51 	case LDC_VERS:
     52 		ldc_rx_ctrl_vers(lc, lp);
     53 		break;
     54 
     55 	case LDC_RTS:
     56 		ldc_rx_ctrl_rts(lc, lp);
     57 		break;
     58 
     59 	case LDC_RTR:
     60 		ldc_rx_ctrl_rtr(lc, lp);
     61 		break;
     62 
     63 	case LDC_RDX:
     64 		ldc_rx_ctrl_rdx(lc, lp);
     65 		break;
     66 
     67 	default:
     68 		DPRINTF(("CTRL/0x%02x/0x%02x\n", lp->stype, lp->ctrl));
     69 		ldc_reset(lc);
     70 		break;
     71 	}
     72 }
     73 
     74 void
     75 ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp)
     76 {
     77 	switch (lp->stype) {
     78 	case LDC_INFO:
     79 		DPRINTF(("CTRL/INFO/VERS major %d minor %d\n", lp->major, lp->minor));
     80 		if (lp->major == LDC_VERSION_MAJOR &&
     81 		    lp->minor == LDC_VERSION_MINOR)
     82 			ldc_send_ack(lc);
     83 		else {
     84 			/* XXX do nothing for now. */
     85 			DPRINTF(("CTRL/INFO/VERS unsupported major/minor\n"));
     86 		}
     87 		break;
     88 
     89 	case LDC_ACK:
     90 		DPRINTF(("CTRL/ACK/VERS\n"));
     91 		if (lc->lc_state != LDC_SND_VERS) {
     92 			DPRINTF(("Spurious CTRL/ACK/VERS: state %d major %d minor %d (ignored)\n",
     93 					 lc->lc_state, lp->major, lp->minor));
     94 		}
     95 		else {
     96 			ldc_send_rts(lc);
     97 		}
     98 		break;
     99 
    100 	case LDC_NACK:
    101 		DPRINTF(("CTRL/NACK/VERS\n"));
    102 		ldc_reset(lc);
    103 		break;
    104 
    105 	default:
    106 		DPRINTF(("CTRL/0x%02x/VERS\n", lp->stype));
    107 		ldc_reset(lc);
    108 		break;
    109 	}
    110 }
    111 
    112 void
    113 ldc_rx_ctrl_rts(struct ldc_conn *lc, struct ldc_pkt *lp)
    114 {
    115 	switch (lp->stype) {
    116 	case LDC_INFO:
    117 		if (lc->lc_state != LDC_RCV_VERS) {
    118 			DPRINTF(("Spurious CTRL/INFO/RTS: state %d\n",
    119 			    lc->lc_state));
    120 			ldc_reset(lc);
    121 			return;
    122 		}
    123 		DPRINTF(("CTRL/INFO/RTS\n"));
    124 		ldc_send_rtr(lc);
    125 		break;
    126 
    127 	case LDC_ACK:
    128 		DPRINTF(("CTRL/ACK/RTS\n"));
    129 		ldc_reset(lc);
    130 		break;
    131 
    132 	case LDC_NACK:
    133 		DPRINTF(("CTRL/NACK/RTS\n"));
    134 		ldc_reset(lc);
    135 		break;
    136 
    137 	default:
    138 		DPRINTF(("CTRL/0x%02x/RTS\n", lp->stype));
    139 		ldc_reset(lc);
    140 		break;
    141 	}
    142 }
    143 
    144 void
    145 ldc_rx_ctrl_rtr(struct ldc_conn *lc, struct ldc_pkt *lp)
    146 {
    147 	switch (lp->stype) {
    148 	case LDC_INFO:
    149 		if (lc->lc_state != LDC_SND_RTS) {
    150 			DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n",
    151 			    lc->lc_state));
    152 			ldc_reset(lc);
    153 			return;
    154 		}
    155 		DPRINTF(("CTRL/INFO/RTR\n"));
    156 		ldc_send_rdx(lc);
    157 		lc->lc_start(lc);
    158 		break;
    159 
    160 	case LDC_ACK:
    161 		DPRINTF(("CTRL/ACK/RTR\n"));
    162 		ldc_reset(lc);
    163 		break;
    164 
    165 	case LDC_NACK:
    166 		DPRINTF(("CTRL/NACK/RTR\n"));
    167 		ldc_reset(lc);
    168 		break;
    169 
    170 	default:
    171 		DPRINTF(("CTRL/0x%02x/RTR\n", lp->stype));
    172 		ldc_reset(lc);
    173 		break;
    174 	}
    175 }
    176 
    177 void
    178 ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp)
    179 {
    180 	switch (lp->stype) {
    181 	case LDC_INFO:
    182 		if (lc->lc_state != LDC_SND_RTR) {
    183 			DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n",
    184 			    lc->lc_state));
    185 			ldc_reset(lc);
    186 			return;
    187 		}
    188 		DPRINTF(("CTRL/INFO/RDX\n"));
    189 		lc->lc_start(lc);
    190 		break;
    191 
    192 	case LDC_ACK:
    193 		DPRINTF(("CTRL/ACK/RDX\n"));
    194 		ldc_reset(lc);
    195 		break;
    196 
    197 	case LDC_NACK:
    198 		DPRINTF(("CTRL/NACK/RDX\n"));
    199 		ldc_reset(lc);
    200 		break;
    201 
    202 	default:
    203 		DPRINTF(("CTRL/0x%02x/RDX\n", lp->stype));
    204 		ldc_reset(lc);
    205 		break;
    206 	}
    207 }
    208 
    209 void
    210 ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
    211 {
    212 	size_t len;
    213 
    214 	if (lp->stype != LDC_INFO) {
    215 		DPRINTF(("DATA/0x%02x\n", lp->stype));
    216 		ldc_reset(lc);
    217 		return;
    218 	}
    219 
    220 	if (lc->lc_state != LDC_SND_RTR &&
    221 	    lc->lc_state != LDC_SND_RDX) {
    222 		DPRINTF(("Spurious DATA/INFO: state %d\n", lc->lc_state));
    223 		ldc_reset(lc);
    224 		return;
    225 	}
    226 
    227 	if (lp->env & LDC_FRAG_START) {
    228 		lc->lc_len = (lp->env & LDC_LEN_MASK) + 8;
    229 		KASSERT(lc->lc_len <= sizeof(lc->lc_msg));
    230 		memcpy((uint8_t *)lc->lc_msg, lp, lc->lc_len);
    231 	} else {
    232 		len = (lp->env & LDC_LEN_MASK);
    233 		if (lc->lc_len + len > sizeof(lc->lc_msg)) {
    234 			DPRINTF(("Buffer overrun\n"));
    235 			ldc_reset(lc);
    236 			return;
    237 		}
    238 		memcpy(((uint8_t *)lc->lc_msg) + lc->lc_len, &lp->major, len);
    239 		lc->lc_len += len;
    240 	}
    241 
    242 	if (lp->env & LDC_FRAG_STOP)
    243 		lc->lc_rx_data(lc, (struct ldc_pkt *)lc->lc_msg);
    244 }
    245 
    246 void
    247 ldc_send_vers(struct ldc_conn *lc)
    248 {
    249 	struct ldc_pkt *lp;
    250 	uint64_t tx_head, tx_tail, tx_state;
    251 	int err;
    252 
    253 	mutex_enter(&lc->lc_txq->lq_mtx);
    254 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    255 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    256 		mutex_exit(&lc->lc_txq->lq_mtx);
    257 		return;
    258 	}
    259 
    260 	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    261 	bzero(lp, sizeof(struct ldc_pkt));
    262 	lp->type = LDC_CTRL;
    263 	lp->stype = LDC_INFO;
    264 	lp->ctrl = LDC_VERS;
    265 	lp->major = 1;
    266 	lp->minor = 0;
    267 	DPRINTF(("ldc_send_vers() major %d minor %d\n", lp->major, lp->minor));
    268 
    269 	tx_tail += sizeof(*lp);
    270 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    271 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    272 	if (err != H_EOK) {
    273 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    274 		mutex_exit(&lc->lc_txq->lq_mtx);
    275 		return;
    276 	}
    277 
    278 	lc->lc_state = LDC_SND_VERS;
    279 	DPRINTF(("ldc_send_vers() setting lc->lc_state to %d\n", lc->lc_state));
    280 	mutex_exit(&lc->lc_txq->lq_mtx);
    281 }
    282 
    283 void
    284 ldc_send_ack(struct ldc_conn *lc)
    285 {
    286 	struct ldc_pkt *lp;
    287 	uint64_t tx_head, tx_tail, tx_state;
    288 	int err;
    289 
    290 	mutex_enter(&lc->lc_txq->lq_mtx);
    291 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    292 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    293 		mutex_exit(&lc->lc_txq->lq_mtx);
    294 		return;
    295 	}
    296 
    297 	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    298 	bzero(lp, sizeof(struct ldc_pkt));
    299 	lp->type = LDC_CTRL;
    300 	lp->stype = LDC_ACK;
    301 	lp->ctrl = LDC_VERS;
    302 	lp->major = 1;
    303 	lp->minor = 0;
    304 
    305 	tx_tail += sizeof(*lp);
    306 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    307 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    308 	if (err != H_EOK) {
    309 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    310 		mutex_exit(&lc->lc_txq->lq_mtx);
    311 		return;
    312 	}
    313 
    314 	lc->lc_state = LDC_RCV_VERS;
    315 	DPRINTF(("ldc_send_ack() setting lc->lc_state to %d\n", lc->lc_state));
    316 	mutex_exit(&lc->lc_txq->lq_mtx);
    317 }
    318 
    319 void
    320 ldc_send_rts(struct ldc_conn *lc)
    321 {
    322 	struct ldc_pkt *lp;
    323 	uint64_t tx_head, tx_tail, tx_state;
    324 	int err;
    325 
    326 	mutex_enter(&lc->lc_txq->lq_mtx);
    327 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    328 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    329 		mutex_exit(&lc->lc_txq->lq_mtx);
    330 		return;
    331 	}
    332 
    333 	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    334 	bzero(lp, sizeof(struct ldc_pkt));
    335 	lp->type = LDC_CTRL;
    336 	lp->stype = LDC_INFO;
    337 	lp->ctrl = LDC_RTS;
    338 	lp->env = LDC_MODE_UNRELIABLE;
    339 	lp->seqid = lc->lc_tx_seqid++;
    340 
    341 	tx_tail += sizeof(*lp);
    342 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    343 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    344 	if (err != H_EOK) {
    345 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    346 		mutex_exit(&lc->lc_txq->lq_mtx);
    347 		return;
    348 	}
    349 
    350 	lc->lc_state = LDC_SND_RTS;
    351 	DPRINTF(("ldc_send_rts() setting lc->lc_state to %d\n", lc->lc_state));
    352 	mutex_exit(&lc->lc_txq->lq_mtx);
    353 }
    354 
    355 void
    356 ldc_send_rtr(struct ldc_conn *lc)
    357 {
    358 	struct ldc_pkt *lp;
    359 	uint64_t tx_head, tx_tail, tx_state;
    360 	int err;
    361 
    362 	mutex_enter(&lc->lc_txq->lq_mtx);
    363 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    364 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    365 		mutex_exit(&lc->lc_txq->lq_mtx);
    366 		return;
    367 	}
    368 
    369 	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    370 	bzero(lp, sizeof(struct ldc_pkt));
    371 	lp->type = LDC_CTRL;
    372 	lp->stype = LDC_INFO;
    373 	lp->ctrl = LDC_RTR;
    374 	lp->env = LDC_MODE_UNRELIABLE;
    375 	lp->seqid = lc->lc_tx_seqid++;
    376 
    377 	tx_tail += sizeof(*lp);
    378 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    379 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    380 	if (err != H_EOK) {
    381 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    382 		mutex_exit(&lc->lc_txq->lq_mtx);
    383 		return;
    384 	}
    385 
    386 	lc->lc_state = LDC_SND_RTR;
    387 	DPRINTF(("ldc_send_rtr() setting lc->lc_state to %d\n", lc->lc_state));
    388 	mutex_exit(&lc->lc_txq->lq_mtx);
    389 }
    390 
    391 void
    392 ldc_send_rdx(struct ldc_conn *lc)
    393 {
    394 	struct ldc_pkt *lp;
    395 	uint64_t tx_head, tx_tail, tx_state;
    396 	int err;
    397 
    398 	mutex_enter(&lc->lc_txq->lq_mtx);
    399 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    400 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    401 		mutex_exit(&lc->lc_txq->lq_mtx);
    402 		return;
    403 	}
    404 
    405 	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    406 	bzero(lp, sizeof(struct ldc_pkt));
    407 	lp->type = LDC_CTRL;
    408 	lp->stype = LDC_INFO;
    409 	lp->ctrl = LDC_RDX;
    410 	lp->env = LDC_MODE_UNRELIABLE;
    411 	lp->seqid = lc->lc_tx_seqid++;
    412 
    413 	tx_tail += sizeof(*lp);
    414 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    415 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    416 	if (err != H_EOK) {
    417 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    418 		mutex_exit(&lc->lc_txq->lq_mtx);
    419 		return;
    420 	}
    421 
    422 	lc->lc_state = LDC_SND_RDX;
    423 	DPRINTF(("ldc_send_rdx() setting lc->lc_state to %d\n", lc->lc_state));
    424 	mutex_exit(&lc->lc_txq->lq_mtx);
    425 }
    426 
    427 int
    428 ldc_send_unreliable(struct ldc_conn *lc, void *msg, size_t len)
    429 {
    430 	struct ldc_pkt *lp;
    431 	uint64_t tx_head, tx_tail, tx_state;
    432 	uint64_t tx_avail;
    433 	uint8_t *p = msg;
    434 	int err;
    435 
    436 	mutex_enter(&lc->lc_txq->lq_mtx);
    437 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    438 	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
    439 		mutex_exit(&lc->lc_txq->lq_mtx);
    440 		return (EIO);
    441 	}
    442 
    443 	tx_avail = (tx_head - tx_tail) / sizeof(*lp) +
    444 	    lc->lc_txq->lq_nentries - 1;
    445 	tx_avail %= lc->lc_txq->lq_nentries;
    446 	if (len > tx_avail * LDC_PKT_PAYLOAD) {
    447 		mutex_exit(&lc->lc_txq->lq_mtx);
    448 		return (EWOULDBLOCK);
    449 	}
    450 
    451 	while (len > 0) {
    452 		lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
    453 		bzero(lp, sizeof(struct ldc_pkt));
    454 		lp->type = LDC_DATA;
    455 		lp->stype = LDC_INFO;
    456 		lp->env = uimin(len, LDC_PKT_PAYLOAD);
    457 		if (p == msg)
    458 			lp->env |= LDC_FRAG_START;
    459 		if (len <= LDC_PKT_PAYLOAD)
    460 			lp->env |= LDC_FRAG_STOP;
    461 		lp->seqid = lc->lc_tx_seqid++;
    462 		bcopy(p, &lp->major, uimin(len, LDC_PKT_PAYLOAD));
    463 
    464 		tx_tail += sizeof(*lp);
    465 		tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
    466 		err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
    467 		if (err != H_EOK) {
    468 			printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
    469 			mutex_exit(&lc->lc_txq->lq_mtx);
    470 			return (EIO);
    471 		}
    472 		p += uimin(len, LDC_PKT_PAYLOAD);
    473 		len -= uimin(len, LDC_PKT_PAYLOAD);
    474 	}
    475 
    476 	mutex_exit(&lc->lc_txq->lq_mtx);
    477 	return (0);
    478 }
    479 
    480 void
    481 ldc_reset(struct ldc_conn *lc)
    482 {
    483 	int err;
    484 	vaddr_t va;
    485 	paddr_t pa;
    486 
    487 	DPRINTF(("Resetting connection\n"));
    488 
    489 	mutex_enter(&lc->lc_txq->lq_mtx);
    490 
    491 #if OPENBSD_BUSDMA
    492 	err = hv_ldc_tx_qconf(lc->lc_id,
    493 	    lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries);
    494 #else
    495         va = lc->lc_txq->lq_va;
    496 	pa = 0;
    497 	if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
    498 	  panic("pmap_extract failed %lx\n", va);
    499 	err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_txq->lq_nentries);
    500 #endif
    501 	if (err != H_EOK)
    502 		printf("%s: hv_ldc_tx_qconf %d\n", __func__, err);
    503 
    504 #if OPENBSD_BUSDMA
    505 	err = hv_ldc_rx_qconf(lc->lc_id,
    506 	    lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries);
    507 #else
    508         va = lc->lc_rxq->lq_va;
    509 	pa = 0;
    510 	if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
    511 	  panic("pmap_extract failed %lx\n", va);
    512 	err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_rxq->lq_nentries);
    513 #endif
    514 	if (err != H_EOK)
    515 		printf("%s: hv_ldc_rx_qconf %d\n", __func__, err);
    516 
    517 	lc->lc_tx_seqid = 0;
    518 	lc->lc_state = 0;
    519 	lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN;
    520 	mutex_exit(&lc->lc_txq->lq_mtx);
    521 
    522 	lc->lc_reset(lc);
    523 }
    524 #if OPENBSD_BUSDMA
    525 struct ldc_queue *
    526 ldc_queue_alloc(bus_dma_tag_t t, int nentries)
    527 #else
    528 struct ldc_queue *
    529 ldc_queue_alloc(int nentries)
    530 #endif
    531 {
    532 	struct ldc_queue *lq;
    533 	bus_size_t size;
    534 	vaddr_t va = 0;
    535 #if OPENBSD_BUSDMA
    536 	int nsegs;
    537 #endif
    538 
    539 	lq = kmem_zalloc(sizeof(struct ldc_queue), KM_SLEEP);
    540 
    541 	mutex_init(&lq->lq_mtx, MUTEX_DEFAULT, IPL_TTY);
    542 
    543 	size = roundup(nentries * sizeof(struct ldc_pkt), PAGE_SIZE);
    544 #if OPENBSD_BUSDMA
    545 	if (bus_dmamap_create(t, size, 1, size, 0,
    546 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lq->lq_map) != 0)
    547 		return (NULL);
    548 
    549 	if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lq->lq_seg, 1,
    550 	    &nsegs, BUS_DMA_NOWAIT) != 0)
    551 		goto destroy;
    552 
    553 	if (bus_dmamem_map(t, &lq->lq_seg, 1, size, (void *)&va,
    554 	    BUS_DMA_NOWAIT) != 0)
    555 		goto free;
    556 
    557 	 if (bus_dmamap_load(t, lq->lq_map, (void*)va, size, NULL,
    558 	    BUS_DMA_NOWAIT) != 0)
    559 		goto unmap;
    560 #else
    561 	va = (vaddr_t)kmem_zalloc(size, KM_SLEEP);
    562 #endif
    563 	lq->lq_va = (vaddr_t)va;
    564 	lq->lq_nentries = nentries;
    565 	return (lq);
    566 #if OPENBSD_BUSDMA
    567 unmap:
    568 	bus_dmamem_unmap(t, (void*)va, size);
    569 free:
    570 	bus_dmamem_free(t, &lq->lq_seg, 1);
    571 destroy:
    572 	bus_dmamap_destroy(t, lq->lq_map);
    573 #endif
    574 	return (NULL);
    575 }
    576 
    577 void
    578 #if OPENBSD_BUSDMA
    579 ldc_queue_free(bus_dma_tag_t t, struct ldc_queue *lq)
    580 #else
    581 ldc_queue_free(struct ldc_queue *lq)
    582 #endif
    583 {
    584 	bus_size_t size;
    585 
    586 	size = roundup(lq->lq_nentries * sizeof(struct ldc_pkt), PAGE_SIZE);
    587 
    588 #if OPENBSD_BUSDMA
    589 	bus_dmamap_unload(t, lq->lq_map);
    590 	bus_dmamem_unmap(t, &lq->lq_va, size);
    591 	bus_dmamem_free(t, &lq->lq_seg, 1);
    592 	bus_dmamap_destroy(t, lq->lq_map);
    593 #else
    594 	kmem_free((void *)lq->lq_va, size);
    595 #endif
    596 	kmem_free(lq, size);
    597 }
    598 
    599 #if OPENBSD_BUSDMA
    600 struct ldc_map *
    601 ldc_map_alloc(bus_dma_tag_t t, int nentries)
    602 #else
    603 struct ldc_map *
    604 ldc_map_alloc(int nentries)
    605 #endif
    606 {
    607 	struct ldc_map *lm;
    608 	bus_size_t size;
    609 	vaddr_t va = 0;
    610 
    611 #if OPENBSD_BUSDMA
    612 	int nsegs;
    613 #endif
    614 	lm = kmem_zalloc(sizeof(struct ldc_map), KM_SLEEP);
    615 	size = roundup(nentries * sizeof(struct ldc_map_slot), PAGE_SIZE);
    616 
    617 #if OPENBSD_BUSDMA
    618 	if (bus_dmamap_create(t, size, 1, size, 0,
    619 			      BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lm->lm_map) != 0) {
    620 		DPRINTF(("ldc_map_alloc() - bus_dmamap_create() failed\n"));
    621 		return (NULL);
    622 	}
    623 
    624 	if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lm->lm_seg, 1,
    625 			     &nsegs, BUS_DMA_NOWAIT) != 0) {
    626 		DPRINTF(("ldc_map_alloc() - bus_dmamem_alloc() failed\n"));
    627 		goto destroy;
    628 	}
    629 
    630 	if (bus_dmamem_map(t, &lm->lm_seg, 1, size, (void *)&va,
    631 			   BUS_DMA_NOWAIT) != 0) {
    632 		DPRINTF(("ldc_map_alloc() - bus_dmamem_map() failed\n"));
    633 		goto free;
    634 	}
    635 	if (bus_dmamap_load(t, lm->lm_map, (void*)va, size, NULL,
    636 			    BUS_DMA_NOWAIT) != 0) {
    637 		DPRINTF(("ldc_map_alloc() - bus_dmamap_load() failed\n"));
    638 		goto unmap;
    639 	}
    640 #else
    641 	va = (vaddr_t)kmem_zalloc(size, KM_SLEEP);
    642 #endif
    643 	lm->lm_slot = (struct ldc_map_slot *)va;
    644 	lm->lm_nentries = nentries;
    645 	bzero(lm->lm_slot, nentries * sizeof(struct ldc_map_slot));
    646 	return (lm);
    647 
    648 #if OPENBSD_BUSDMA
    649 unmap:
    650 	bus_dmamem_unmap(t, (void*)va, size);
    651 free:
    652 	bus_dmamem_free(t, &lm->lm_seg, 1);
    653 destroy:
    654 	bus_dmamap_destroy(t, lm->lm_map);
    655 #endif
    656 	return (NULL);
    657 }
    658 
    659 #if OPENBSD_BUSDMA
    660 void
    661 ldc_map_free(bus_dma_tag_t t, struct ldc_map *lm)
    662 #else
    663 void
    664 ldc_map_free(struct ldc_map *lm)
    665 #endif
    666 {
    667 	bus_size_t size;
    668 
    669 	size = lm->lm_nentries * sizeof(struct ldc_map_slot);
    670 	size = roundup(size, PAGE_SIZE);
    671 
    672 #if OPENBSD_BUSDMA
    673 	bus_dmamap_unload(t, lm->lm_map);
    674 	bus_dmamem_unmap(t, lm->lm_slot, size);
    675 	bus_dmamem_free(t, &lm->lm_seg, 1);
    676 	bus_dmamap_destroy(t, lm->lm_map);
    677 #else
    678 	kmem_free(lm->lm_slot, size);
    679 #endif
    680 	kmem_free(lm, size);
    681 }
    682