Make sure all USB drivers allocate buffer memory

through the USB API and/or busdma.

The following assumptions have been made:
umass - buffers passed from CAM/SCSI layer are OK
network - mbufs are OK.

Some other nits while at it.

MFC after:	1 week
Suggested by:	imp
This commit is contained in:
Hans Petter Selasky 2012-12-20 18:38:02 +00:00
parent a6d2f40ec8
commit c180b3986d
8 changed files with 203 additions and 236 deletions

View File

@ -74,7 +74,7 @@ SYSCTL_INT(_hw_usb_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
/* Define some limits */
#ifndef USTORAGE_FS_BULK_SIZE
#define USTORAGE_FS_BULK_SIZE (1UL << 17) /* bytes */
#define USTORAGE_FS_BULK_SIZE (1U << 17) /* bytes */
#endif
#ifndef USTORAGE_FS_MAX_LUN
@ -85,8 +85,6 @@ SYSCTL_INT(_hw_usb_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
#define USTORAGE_QDATA_MAX 40 /* bytes */
#endif
#define sc_cmd_data sc_cbw.CBWCDB
/*
* The SCSI ID string must be exactly 28 characters long
* exluding the terminating zero.
@ -176,8 +174,9 @@ struct ustorage_fs_lun {
struct ustorage_fs_softc {
ustorage_fs_bbb_cbw_t sc_cbw; /* Command Wrapper Block */
ustorage_fs_bbb_csw_t sc_csw; /* Command Status Block */
ustorage_fs_bbb_cbw_t *sc_cbw; /* Command Wrapper Block */
ustorage_fs_bbb_csw_t *sc_csw; /* Command Status Block */
void *sc_dma_ptr; /* Main data buffer */
struct mtx sc_mtx;
@ -275,7 +274,6 @@ static struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
.flags = {.ext_buffer = 1,},
.callback = &ustorage_fs_t_bbb_command_callback,
.usb_mode = USB_MODE_DEVICE,
},
@ -295,7 +293,7 @@ static struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = USTORAGE_FS_BULK_SIZE,
.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
.flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
.callback = &ustorage_fs_t_bbb_data_read_callback,
.usb_mode = USB_MODE_DEVICE,
},
@ -315,7 +313,7 @@ static struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(ustorage_fs_bbb_csw_t),
.flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
.flags = {.short_xfer_ok = 1},
.callback = &ustorage_fs_t_bbb_status_callback,
.usb_mode = USB_MODE_DEVICE,
},
@ -409,6 +407,14 @@ ustorage_fs_attach(device_t dev)
"transfers, %s\n", usbd_errstr(err));
goto detach;
}
sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
USTORAGE_FS_T_BBB_COMMAND], 0);
sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
USTORAGE_FS_T_BBB_STATUS], 0);
sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
USTORAGE_FS_T_BBB_DATA_READ], 0);
/* start Mass Storage State Machine */
mtx_lock(&sc->sc_mtx);
@ -518,44 +524,44 @@ ustorage_fs_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
tag = UGETDW(sc->sc_cbw.dCBWSignature);
tag = UGETDW(sc->sc_cbw->dCBWSignature);
if (tag != CBWSIGNATURE) {
/* do nothing */
DPRINTF("invalid signature 0x%08x\n", tag);
break;
}
tag = UGETDW(sc->sc_cbw.dCBWTag);
tag = UGETDW(sc->sc_cbw->dCBWTag);
/* echo back tag */
USETDW(sc->sc_csw.dCSWTag, tag);
USETDW(sc->sc_csw->dCSWTag, tag);
/* reset status */
sc->sc_csw.bCSWStatus = 0;
sc->sc_csw->bCSWStatus = 0;
/* reset data offset, data length and data remainder */
sc->sc_transfer.offset = 0;
sc->sc_transfer.data_rem =
UGETDW(sc->sc_cbw.dCBWDataTransferLength);
UGETDW(sc->sc_cbw->dCBWDataTransferLength);
/* reset data flags */
sc->sc_transfer.data_short = 0;
/* extract LUN */
sc->sc_transfer.lun = sc->sc_cbw.bCBWLUN;
sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
if (sc->sc_transfer.data_rem == 0) {
sc->sc_transfer.cbw_dir = DIR_NONE;
} else {
if (sc->sc_cbw.bCBWFlags & CBWFLAGS_IN) {
if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
sc->sc_transfer.cbw_dir = DIR_WRITE;
} else {
sc->sc_transfer.cbw_dir = DIR_READ;
}
}
sc->sc_transfer.cmd_len = sc->sc_cbw.bCDBLength;
if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw.CBWCDB)) ||
sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
(sc->sc_transfer.cmd_len == 0)) {
/* just halt - this is invalid */
DPRINTF("invalid command length %d bytes\n",
@ -597,9 +603,6 @@ tr_setup:
usbd_xfer_set_stall(xfer);
DPRINTF("stall pipe\n");
}
usbd_xfer_set_frame_data(xfer, 0, &sc->sc_cbw,
sizeof(sc->sc_cbw));
usbd_transfer_submit(xfer);
break;
@ -616,9 +619,9 @@ tr_setup:
goto tr_setup;
}
if (err) {
if (sc->sc_csw.bCSWStatus == 0) {
if (sc->sc_csw->bCSWStatus == 0) {
/* set some default error code */
sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
}
if (sc->sc_transfer.cbw_dir == DIR_READ) {
/* dump all data */
@ -699,6 +702,9 @@ ustorage_fs_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
/* XXX copy data from DMA buffer */
memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.offset += actlen;
@ -721,8 +727,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
}
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
usbd_transfer_submit(xfer);
break;
@ -778,8 +783,10 @@ tr_setup:
usbd_xfer_set_stall(xfer);
}
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
/* XXX copy data to DMA buffer */
memcpy(sc->sc_dma_ptr, sc->sc_transfer.data_ptr, max_bulk);
usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
usbd_transfer_submit(xfer);
break;
@ -813,16 +820,13 @@ ustorage_fs_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
tr_setup:
USETDW(sc->sc_csw.dCSWSignature, CSWSIGNATURE);
USETDW(sc->sc_csw.dCSWDataResidue, sc->sc_transfer.data_rem);
USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
if (sc->sc_transfer.data_error) {
sc->sc_transfer.data_error = 0;
usbd_xfer_set_stall(xfer);
}
usbd_xfer_set_frame_data(xfer, 0, &sc->sc_csw,
sizeof(sc->sc_csw));
usbd_transfer_submit(xfer);
break;
@ -934,17 +938,17 @@ ustorage_fs_verify(struct ustorage_fs_softc *sc)
/*
* Get the starting Logical Block Address
*/
lba = get_be32(&sc->sc_cmd_data[2]);
lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the cache)
* but we don't implement it.
*/
if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
vlen = get_be16(&sc->sc_cmd_data[7]);
vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
if (vlen == 0) {
goto done;
}
@ -1092,8 +1096,8 @@ ustorage_fs_read_capacity(struct ustorage_fs_softc *sc)
{
uint8_t *buf = sc->sc_transfer.data_ptr;
struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
uint8_t pmi = sc->sc_cmd_data[8];
uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
uint8_t pmi = sc->sc_cbw->CBWCDB[8];
/* Check the PMI and LBA fields */
if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
@ -1126,7 +1130,7 @@ ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
uint8_t *buf0;
uint16_t len;
uint16_t limit;
uint8_t mscmnd = sc->sc_cmd_data[0];
uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
uint8_t pc;
uint8_t page_code;
uint8_t changeable_values;
@ -1134,13 +1138,13 @@ ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
buf0 = buf;
if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
/* Mask away DBD */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
pc = sc->sc_cmd_data[2] >> 6;
page_code = sc->sc_cmd_data[2] & 0x3f;
pc = sc->sc_cbw->CBWCDB[2] >> 6;
page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
if (pc == 3) {
currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return (1);
@ -1237,9 +1241,9 @@ ustorage_fs_start_stop(struct ustorage_fs_softc *sc)
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
immed = sc->sc_cmd_data[1] & 0x01;
loej = sc->sc_cmd_data[4] & 0x02;
start = sc->sc_cmd_data[4] & 0x01;
immed = sc->sc_cbw->CBWCDB[1] & 0x01;
loej = sc->sc_cbw->CBWCDB[4] & 0x02;
start = sc->sc_cbw->CBWCDB[4] & 0x01;
if (immed || loej || start) {
/* compile fix */
@ -1264,8 +1268,8 @@ ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc)
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
prevent = sc->sc_cmd_data[4] & 0x01;
if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
/* Mask away Prevent */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
@ -1369,18 +1373,18 @@ ustorage_fs_read(struct ustorage_fs_softc *sc)
* Get the starting Logical Block Address and check that it's not
* too big
*/
if (sc->sc_cmd_data[0] == SC_READ_6) {
lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
get_be16(&sc->sc_cmd_data[2]);
if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
get_be16(&sc->sc_cbw->CBWCDB[2]);
} else {
lba = get_be32(&sc->sc_cmd_data[2]);
lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
* cache) and FUA (Force Unit Access = don't read from the
* cache), but we don't implement them.
*/
if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
@ -1427,11 +1431,11 @@ ustorage_fs_write(struct ustorage_fs_softc *sc)
* Get the starting Logical Block Address and check that it's not
* too big.
*/
if (sc->sc_cmd_data[0] == SC_WRITE_6)
lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
get_be16(&sc->sc_cmd_data[2]);
if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
get_be16(&sc->sc_cbw->CBWCDB[2]);
else {
lba = get_be32(&sc->sc_cmd_data[2]);
lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
@ -1439,11 +1443,11 @@ ustorage_fs_write(struct ustorage_fs_softc *sc)
* medium). We don't implement DPO; we implement FUA by
* performing synchronous output.
*/
if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
if (sc->sc_cmd_data[1] & 0x08) {
if (sc->sc_cbw->CBWCDB[1] & 0x08) {
/* FUA */
/* XXX set SYNC flag here */
}
@ -1483,7 +1487,7 @@ ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask)
* there must be something wrong about this SCSI
* command
*/
sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
return (1);
}
/* compute the minimum length */
@ -1519,18 +1523,18 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
uint16_t mask, uint8_t needs_medium)
{
struct ustorage_fs_lun *currlun;
uint8_t lun = (sc->sc_cmd_data[1] >> 5);
uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
uint8_t i;
/* Verify the length of the command itself */
if (min_cmd_size > sc->sc_transfer.cmd_len) {
DPRINTF("%u > %u\n",
min_cmd_size, sc->sc_transfer.cmd_len);
sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
return (1);
}
/* Mask away the LUN */
sc->sc_cmd_data[1] &= 0x1f;
sc->sc_cbw->CBWCDB[1] &= 0x1f;
/* Check if LUN is correct */
if (lun != sc->sc_transfer.lun) {
@ -1540,7 +1544,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
if (sc->sc_transfer.lun <= sc->sc_last_lun) {
sc->sc_transfer.currlun = currlun =
sc->sc_lun + sc->sc_transfer.lun;
if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
currlun->sense_data = SS_NO_SENSE;
currlun->sense_data_info = 0;
currlun->info_valid = 0;
@ -1551,8 +1555,8 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* else must fail!
*/
if ((currlun->unit_attention_data != SS_NO_SENSE) &&
(sc->sc_cmd_data[0] != SC_INQUIRY) &&
(sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
(sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
(sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
currlun->sense_data = currlun->unit_attention_data;
currlun->unit_attention_data = SS_NO_SENSE;
return (1);
@ -1564,8 +1568,8 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not.
*/
if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
(sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
(sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
return (1);
}
}
@ -1575,7 +1579,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* non-zero.
*/
for (i = 0; i != min_cmd_size; i++) {
if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
if (currlun) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
}
@ -1613,12 +1617,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
sc->sc_transfer.data_ptr = sc->sc_qdata;
DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
switch (sc->sc_cmd_data[0]) {
switch (sc->sc_cbw->CBWCDB[0]) {
case SC_INQUIRY:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@ -1633,7 +1637,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SELECT_6:
sc->sc_transfer.cmd_dir = DIR_READ;
error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@ -1649,7 +1653,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SELECT_10:
sc->sc_transfer.cmd_dir = DIR_READ;
error = ustorage_fs_min_len(sc,
get_be16(&sc->sc_cmd_data[7]), -1U);
get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@ -1664,7 +1668,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SENSE_6:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@ -1680,7 +1684,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SENSE_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
get_be16(&sc->sc_cmd_data[7]), -1U);
get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@ -1708,7 +1712,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
case SC_READ_6:
i = sc->sc_cmd_data[4];
i = sc->sc_cbw->CBWCDB[4];
sc->sc_transfer.cmd_dir = DIR_WRITE;
temp = ((i == 0) ? 256UL : i);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
@ -1726,7 +1730,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
temp = get_be16(&sc->sc_cmd_data[7]);
temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
@ -1742,10 +1746,10 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_12:
sc->sc_transfer.cmd_dir = DIR_WRITE;
temp = get_be32(&sc->sc_cmd_data[6]);
temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
if (temp >= (1UL << (32 - 9))) {
/* numerical overflow */
sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
error = 1;
break;
}
@ -1776,7 +1780,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_FORMAT_CAPACITIES:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
get_be16(&sc->sc_cmd_data[7]), -1U);
get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@ -1791,7 +1795,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_REQUEST_SENSE:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@ -1860,7 +1864,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
case SC_WRITE_6:
i = sc->sc_cmd_data[4];
i = sc->sc_cbw->CBWCDB[4];
sc->sc_transfer.cmd_dir = DIR_READ;
temp = ((i == 0) ? 256UL : i);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
@ -1878,7 +1882,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_WRITE_10:
sc->sc_transfer.cmd_dir = DIR_READ;
temp = get_be16(&sc->sc_cmd_data[7]);
temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
@ -1894,10 +1898,10 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_WRITE_12:
sc->sc_transfer.cmd_dir = DIR_READ;
temp = get_be32(&sc->sc_cmd_data[6]);
temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
if (temp > (mask9 >> 9)) {
/* numerical overflow */
sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
error = 1;
break;
}

View File

@ -139,8 +139,8 @@ struct bbb_csw {
struct bbb_transfer {
struct mtx mtx;
struct cv cv;
struct bbb_cbw cbw;
struct bbb_csw csw;
struct bbb_cbw *cbw;
struct bbb_csw *csw;
struct usb_xfer *xfer[ST_MAX];
@ -158,7 +158,7 @@ struct bbb_transfer {
uint8_t status_try;
int error;
uint8_t buffer[SCSI_MAX_LEN] __aligned(4);
uint8_t *buffer;
};
static usb_callback_t bbb_command_callback;
@ -184,7 +184,6 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(struct bbb_cbw),
.flags = {.ext_buffer = 1,},
.callback = &bbb_command_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@ -193,8 +192,8 @@ static const struct usb_config bbb_config[ST_MAX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = BULK_SIZE,
.flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
.bufsize = MAX(SCSI_MAX_LEN, BULK_SIZE),
.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_data_read_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@ -232,7 +231,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(struct bbb_csw),
.flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
.flags = {.short_xfer_ok = 1,},
.callback = &bbb_status_callback,
.timeout = 1 * USB_MS_HZ, /* 1 second */
},
@ -241,7 +240,6 @@ static const struct usb_config bbb_config[ST_MAX] = {
static void
bbb_done(struct bbb_transfer *sc, int error)
{
sc->error = error;
sc->state = ST_COMMAND;
sc->status_try = 1;
@ -290,18 +288,17 @@ bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
sc->status_try = 0;
tag = UGETDW(sc->cbw.dCBWTag) + 1;
USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
USETDW(sc->cbw.dCBWTag, tag);
USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
sc->cbw.bCBWLUN = sc->lun;
sc->cbw.bCDBLength = sc->cmd_len;
if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) {
sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB);
tag = UGETDW(sc->cbw->dCBWTag) + 1;
USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
USETDW(sc->cbw->dCBWTag, tag);
USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
sc->cbw->bCBWLUN = sc->lun;
sc->cbw->bCDBLength = sc->cmd_len;
if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
DPRINTFN(0, "Truncating long command\n");
}
usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw));
usbd_transfer_submit(xfer);
break;
@ -430,9 +427,9 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
/* very simple status check */
if (actlen < (int)sizeof(sc->csw)) {
if (actlen < (int)sizeof(struct bbb_csw)) {
bbb_done(sc, USB_ERR_SHORT_XFER);
} else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
} else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
bbb_done(sc, 0); /* success */
} else {
bbb_done(sc, ERR_CSW_FAILED); /* error */
@ -440,7 +437,6 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
break;
case USB_ST_SETUP:
usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw));
usbd_transfer_submit(xfer);
break;
@ -478,9 +474,9 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
sc->data_timeout = (data_timeout + USB_MS_HZ);
sc->actlen = 0;
sc->cmd_len = cmd_len;
memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
mtx_lock(&sc->mtx);
usbd_transfer_start(sc->xfer[sc->state]);
@ -554,6 +550,14 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index)
bbb_detach(sc);
return (NULL);
}
/* store pointer to DMA buffers */
sc->buffer = usbd_xfer_get_frame_buffer(
sc->xfer[ST_DATA_RD], 0);
sc->cbw = usbd_xfer_get_frame_buffer(
sc->xfer[ST_COMMAND], 0);
sc->csw = usbd_xfer_get_frame_buffer(
sc->xfer[ST_STATUS], 0);
return (sc);
}

View File

@ -217,9 +217,8 @@ static const struct usb_config uath_usbconfig[UATH_N_XFERS] = {
.type = UE_BULK,
.endpoint = 0x1,
.direction = UE_DIR_OUT,
.bufsize = UATH_MAX_CMDSZ,
.bufsize = UATH_MAX_CMDSZ * UATH_CMD_LIST_COUNT,
.flags = {
.ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@ -242,9 +241,8 @@ static const struct usb_config uath_usbconfig[UATH_N_XFERS] = {
.type = UE_BULK,
.endpoint = 0x2,
.direction = UE_DIR_OUT,
.bufsize = UATH_MAX_TXBUFSZ,
.bufsize = UATH_MAX_TXBUFSZ * UATH_TX_DATA_LIST_COUNT,
.flags = {
.ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1
},
@ -258,10 +256,8 @@ static struct ieee80211vap *uath_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void uath_vap_delete(struct ieee80211vap *);
static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
int, int);
static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
int);
static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd []);
static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd []);
static int uath_host_available(struct uath_softc *);
static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
static int uath_get_devcap(struct uath_softc *);
@ -365,8 +361,7 @@ uath_attach(device_t dev)
/*
* Allocate xfers for firmware commands.
*/
error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
UATH_MAX_CMDSZ);
error = uath_alloc_cmd_list(sc, sc->sc_cmd);
if (error != 0) {
device_printf(sc->sc_dev,
"could not allocate Tx command list\n");
@ -381,6 +376,11 @@ uath_attach(device_t dev)
goto fail1;
}
sc->sc_cmd_dma_buf =
usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_INTR_TX], 0);
sc->sc_tx_dma_buf =
usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0);
/*
* We're now ready to send+receive firmware commands.
*/
@ -493,7 +493,7 @@ uath_attach(device_t dev)
fail4: if_free(ifp);
fail3: UATH_UNLOCK(sc);
fail2: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
fail1: uath_free_cmd_list(sc, sc->sc_cmd);
fail:
return (error);
}
@ -524,7 +524,7 @@ uath_detach(device_t dev)
UATH_LOCK(sc);
uath_free_rx_data_list(sc);
uath_free_tx_data_list(sc);
uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
uath_free_cmd_list(sc, sc->sc_cmd);
UATH_UNLOCK(sc);
if_free(ifp);
@ -533,45 +533,35 @@ uath_detach(device_t dev)
}
static void
uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
{
int i;
for (i = 0; i < ncmd; i++)
if (cmds[i].buf != NULL)
free(cmds[i].buf, M_USBDEV);
for (i = 0; i != UATH_CMD_LIST_COUNT; i++)
cmds[i].buf = NULL;
}
static int
uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
int ncmd, int maxsz)
uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
{
int i, error;
int i;
STAILQ_INIT(&sc->sc_cmd_active);
STAILQ_INIT(&sc->sc_cmd_pending);
STAILQ_INIT(&sc->sc_cmd_waiting);
STAILQ_INIT(&sc->sc_cmd_inactive);
for (i = 0; i < ncmd; i++) {
for (i = 0; i != UATH_CMD_LIST_COUNT; i++) {
struct uath_cmd *cmd = &cmds[i];
cmd->sc = sc; /* backpointer for callbacks */
cmd->msgid = i;
cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
if (cmd->buf == NULL) {
device_printf(sc->sc_dev,
"could not allocate xfer buffer\n");
error = ENOMEM;
goto fail;
}
cmd->buf = ((uint8_t *)sc->sc_cmd_dma_buf) +
(i * UATH_MAX_CMDSZ);
STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
UATH_STAT_INC(sc, st_cmd_inactive);
}
return (0);
fail: uath_free_cmd_list(sc, cmds, ncmd);
return (error);
}
static int
@ -942,10 +932,7 @@ uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata,
dp->buf = NULL;
}
} else {
if (dp->buf != NULL) {
free(dp->buf, M_USBDEV);
dp->buf = NULL;
}
dp->buf = NULL;
}
#ifdef UATH_DEBUG
if (dp->ni != NULL)
@ -956,7 +943,7 @@ uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata,
static int
uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
int ndata, int maxsz, int fillmbuf)
int ndata, int maxsz, void *dma_buf)
{
int i, error;
@ -964,7 +951,7 @@ uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
struct uath_data *dp = &data[i];
dp->sc = sc;
if (fillmbuf) {
if (dma_buf == NULL) {
/* XXX check maxsz */
dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (dp->m == NULL) {
@ -976,20 +963,14 @@ uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
dp->buf = mtod(dp->m, uint8_t *);
} else {
dp->m = NULL;
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
if (dp->buf == NULL) {
device_printf(sc->sc_dev,
"could not allocate buffer\n");
error = ENOMEM;
goto fail;
}
dp->buf = ((uint8_t *)dma_buf) + (i * maxsz);
}
dp->ni = NULL;
}
return (0);
fail: uath_free_data_list(sc, data, ndata, fillmbuf);
fail: uath_free_data_list(sc, data, ndata, 1 /* free mbufs */);
return (error);
}
@ -1001,7 +982,7 @@ uath_alloc_rx_data_list(struct uath_softc *sc)
/* XXX is it enough to store the RX packet with MCLBYTES bytes? */
error = uath_alloc_data_list(sc,
sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
1 /* setup mbufs */);
NULL /* setup mbufs */);
if (error != 0)
return (error);
@ -1024,7 +1005,7 @@ uath_alloc_tx_data_list(struct uath_softc *sc)
error = uath_alloc_data_list(sc,
sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
0 /* no mbufs */);
sc->sc_tx_dma_buf);
if (error != 0)
return (error);
@ -2741,8 +2722,7 @@ setup:
UATH_STAT_DEC(sc, st_rx_inactive);
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
UATH_STAT_INC(sc, st_rx_active);
usbd_xfer_set_frame_data(xfer, 0, data->buf,
usbd_xfer_max_len(xfer));
usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
usbd_transfer_submit(xfer);
/*
@ -2890,7 +2870,7 @@ static device_method_t uath_methods[] = {
DEVMETHOD(device_probe, uath_match),
DEVMETHOD(device_attach, uath_attach),
DEVMETHOD(device_detach, uath_detach),
{ 0, 0 }
DEVMETHOD_END
};
static driver_t uath_driver = {
.name = "uath",

View File

@ -186,6 +186,8 @@ struct uath_softc {
struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
void *sc_cmd_dma_buf;
void *sc_tx_dma_buf;
struct mtx sc_mtx;
uint32_t sc_debug;

View File

@ -201,9 +201,8 @@ static const struct usb_config upgt_config[UPGT_N_XFERS] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = MCLBYTES,
.bufsize = MCLBYTES * UPGT_TX_MAXCOUNT,
.flags = {
.ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1
},
@ -214,9 +213,8 @@ static const struct usb_config upgt_config[UPGT_N_XFERS] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = MCLBYTES,
.bufsize = MCLBYTES * UPGT_RX_MAXCOUNT,
.flags = {
.ext_buffer = 1,
.pipe_bof = 1,
.short_xfer_ok = 1
},
@ -277,6 +275,11 @@ upgt_attach(device_t dev)
goto fail3;
}
sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer(
sc->sc_xfer[UPGT_BULK_RX], 0);
sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(
sc->sc_xfer[UPGT_BULK_TX], 0);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
@ -1952,13 +1955,7 @@ upgt_alloc_tx(struct upgt_softc *sc)
for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_tx_data[i];
data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
if (data->buf == NULL) {
device_printf(sc->sc_dev,
"could not allocate TX buffer\n");
return (ENOMEM);
}
data->buf = ((uint8_t *)sc->sc_tx_dma_buf) + (i * MCLBYTES);
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
UPGT_STAT_INC(sc, st_tx_inactive);
}
@ -1976,13 +1973,7 @@ upgt_alloc_rx(struct upgt_softc *sc)
for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_rx_data[i];
data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
if (data->buf == NULL) {
device_printf(sc->sc_dev,
"could not allocate RX buffer\n");
return (ENOMEM);
}
data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES);
STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
}
@ -2004,8 +1995,10 @@ upgt_detach(device_t dev)
callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
ieee80211_ifdetach(ic);
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
upgt_free_rx(sc);
upgt_free_tx(sc);
@ -2023,7 +2016,7 @@ upgt_free_rx(struct upgt_softc *sc)
for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_rx_data[i];
free(data->buf, M_USBDEV);
data->buf = NULL;
data->ni = NULL;
}
}
@ -2036,7 +2029,7 @@ upgt_free_tx(struct upgt_softc *sc)
for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_tx_data[i];
free(data->buf, M_USBDEV);
data->buf = NULL;
data->ni = NULL;
}
}
@ -2278,8 +2271,7 @@ setup:
return;
STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
usbd_xfer_set_frame_data(xfer, 0, data->buf,
usbd_xfer_max_len(xfer));
usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
usbd_transfer_submit(xfer);
/*
@ -2382,8 +2374,7 @@ static device_method_t upgt_methods[] = {
DEVMETHOD(device_probe, upgt_match),
DEVMETHOD(device_attach, upgt_attach),
DEVMETHOD(device_detach, upgt_detach),
{ 0, 0 }
DEVMETHOD_END
};
static driver_t upgt_driver = {

View File

@ -422,6 +422,8 @@ struct upgt_softc {
device_t sc_dev;
struct ifnet *sc_ifp;
struct usb_device *sc_udev;
void *sc_rx_dma_buf;
void *sc_tx_dma_buf;
struct mtx sc_mtx;
struct upgt_stat sc_stat;
int sc_flags;

View File

@ -532,9 +532,8 @@ static const struct usb_config urtw_8187b_usbconfig[URTW_8187B_N_XFERS] = {
.type = UE_BULK,
.endpoint = 0x89,
.direction = UE_DIR_IN,
.bufsize = MCLBYTES,
.bufsize = sizeof(uint64_t),
.flags = {
.ext_buffer = 1,
.pipe_bof = 1,
.short_xfer_ok = 1
},
@ -544,9 +543,8 @@ static const struct usb_config urtw_8187b_usbconfig[URTW_8187B_N_XFERS] = {
.type = UE_BULK,
.endpoint = URTW_8187B_TXPIPE_BE,
.direction = UE_DIR_OUT,
.bufsize = URTW_TX_MAXSIZE,
.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
.flags = {
.ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@ -624,9 +622,8 @@ static const struct usb_config urtw_8187l_usbconfig[URTW_8187L_N_XFERS] = {
.type = UE_BULK,
.endpoint = 0x2,
.direction = UE_DIR_OUT,
.bufsize = URTW_TX_MAXSIZE,
.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
.flags = {
.ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@ -827,6 +824,16 @@ urtw_attach(device_t dev)
goto fail0;
}
if (sc->sc_flags & URTW_RTL8187B) {
sc->sc_tx_dma_buf =
usbd_xfer_get_frame_buffer(sc->sc_xfer[
URTW_8187B_BULK_TX_BE], 0);
} else {
sc->sc_tx_dma_buf =
usbd_xfer_get_frame_buffer(sc->sc_xfer[
URTW_8187L_BULK_TX_LOW], 0);
}
URTW_LOCK(sc);
urtw_read32_m(sc, URTW_RX, &data);
@ -937,9 +944,10 @@ urtw_detach(device_t dev)
usb_callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
ieee80211_ifdetach(ic);
usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
ieee80211_ifdetach(ic);
urtw_free_tx_data_list(sc);
urtw_free_rx_data_list(sc);
@ -980,10 +988,7 @@ urtw_free_data_list(struct urtw_softc *sc, struct urtw_data data[], int ndata,
dp->buf = NULL;
}
} else {
if (dp->buf != NULL) {
free(dp->buf, M_USBDEV);
dp->buf = NULL;
}
dp->buf = NULL;
}
if (dp->ni != NULL) {
ieee80211_free_node(dp->ni);
@ -1449,7 +1454,7 @@ urtw_start(struct ifnet *ifp)
static int
urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
int ndata, int maxsz, int fillmbuf)
int ndata, int maxsz, void *dma_buf)
{
int i, error;
@ -1457,7 +1462,7 @@ urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
struct urtw_data *dp = &data[i];
dp->sc = sc;
if (fillmbuf) {
if (dma_buf == NULL) {
dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (dp->m == NULL) {
device_printf(sc->sc_dev,
@ -1468,24 +1473,15 @@ urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
dp->buf = mtod(dp->m, uint8_t *);
} else {
dp->m = NULL;
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
if (dp->buf == NULL) {
device_printf(sc->sc_dev,
"could not allocate buffer\n");
error = ENOMEM;
goto fail;
}
if (((unsigned long)dp->buf) % 4)
device_printf(sc->sc_dev,
"warn: unaligned buffer %p\n", dp->buf);
dp->buf = ((uint8_t *)dma_buf) +
(i * maxsz);
}
dp->ni = NULL;
}
return (0);
return 0;
fail: urtw_free_data_list(sc, data, ndata, fillmbuf);
return error;
fail: urtw_free_data_list(sc, data, ndata, 1);
return (error);
}
static int
@ -1494,7 +1490,8 @@ urtw_alloc_rx_data_list(struct urtw_softc *sc)
int error, i;
error = urtw_alloc_data_list(sc,
sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */);
sc->sc_rx, URTW_RX_DATA_LIST_COUNT,
MCLBYTES, NULL /* mbufs */);
if (error != 0)
return (error);
@ -1514,7 +1511,7 @@ urtw_alloc_tx_data_list(struct urtw_softc *sc)
error = urtw_alloc_data_list(sc,
sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
0 /* no mbufs */);
sc->sc_tx_dma_buf /* no mbufs */);
if (error != 0)
return (error);
@ -2709,42 +2706,28 @@ fail:
return (error);
}
/* XXX why we should allocalte memory buffer instead of using memory stack? */
static usb_error_t
urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
uint16_t *data)
{
uint8_t *buf;
uint8_t buf[2];
uint16_t data16;
struct usb_device_request *req;
struct usb_device_request req;
usb_error_t error = 0;
data16 = *data;
req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (req == NULL) {
device_printf(sc->sc_dev, "could not allocate a memory\n");
goto fail0;
}
buf = (uint8_t *)malloc(2, M_80211_VAP, M_NOWAIT | M_ZERO);
if (req == NULL) {
device_printf(sc->sc_dev, "could not allocate a memory\n");
goto fail1;
}
req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
req->bRequest = URTW_8187_SETREGS_REQ;
USETW(req->wValue, addr);
USETW(req->wIndex, index);
USETW(req->wLength, sizeof(uint16_t));
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = URTW_8187_SETREGS_REQ;
USETW(req.wValue, addr);
USETW(req.wIndex, index);
USETW(req.wLength, sizeof(uint16_t));
buf[0] = (data16 & 0x00ff);
buf[1] = (data16 & 0xff00) >> 8;
error = urtw_do_request(sc, req, buf);
error = urtw_do_request(sc, &req, buf);
free(buf, M_80211_VAP);
fail1: free(req, M_80211_VAP);
fail0: return (error);
return (error);
}
static usb_error_t
@ -4133,6 +4116,7 @@ urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
URTW_ASSERT_LOCKED(sc);
@ -4142,8 +4126,7 @@ urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
/* FALLTHROUGH */
case USB_ST_SETUP:
setup:
usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus,
sizeof(int64_t));
memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t));
usbd_transfer_submit(xfer);
break;
default:
@ -4431,7 +4414,7 @@ static device_method_t urtw_methods[] = {
DEVMETHOD(device_probe, urtw_match),
DEVMETHOD(device_attach, urtw_attach),
DEVMETHOD(device_detach, urtw_detach),
{ 0, 0 }
DEVMETHOD_END
};
static driver_t urtw_driver = {
.name = "urtw",

View File

@ -97,6 +97,7 @@ struct urtw_softc {
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
void *sc_tx_dma_buf;
int sc_debug;
int sc_if_flags;