MFp4: Change struct fw_xfer to reduce memory copy in fwmem_*() functions.
And many changes. * all - Major change of struct fw_xfer. o {send,recv}.buf is splitted into hdr and payload. o Remove unnecessary fields. o spd is moved under send and recv. - Remove unnecessary 'volatile' keyword. - Add definition of rtcode and extcode. * firewire.c - Ignore FWDEVINVAL devices in fw_noderesolve_nodeid(). - Check the existance of the bind before call STAILQ_REMOVE(). - Fix bug in the fw_bindadd(). - Change element of struct fw_bind for simplicity. - Check rtcode of response packet. - Reduce split transaction timeout to 200 msec. (100msec is the default value in the spec.) - Set watchdog timer cycle to 10 Hz. - Set xfer->tv just before calling fw_get_tlabel(). * fwohci.c - Simplifies fwohci_get_plen(). * sbp.c - Fix byte order of multibyte scsi_status informations. - Split sbp.c and sbp.h. - Unit number is not necessary for FIFO¤ address. - Reduce LOGIN_DELAY and SCAN_DELAY to 1 sec. - Add some constants defineded in SBP-2 spec. * fwmem.c - Introduce fwmem_strategy() and reduce memory copy.
This commit is contained in:
parent
c142b0fcfe
commit
c4778b5d1c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120660
@ -141,12 +141,10 @@ fw_noderesolve_nodeid(struct firewire_comm *fc, int dst)
|
||||
|
||||
s = splfw();
|
||||
STAILQ_FOREACH(fwdev, &fc->devices, link)
|
||||
if (fwdev->dst == dst)
|
||||
if (fwdev->dst == dst && fwdev->status != FWDEVINVAL)
|
||||
break;
|
||||
splx(s);
|
||||
|
||||
if(fwdev == NULL) return NULL;
|
||||
if(fwdev->status == FWDEVINVAL) return NULL;
|
||||
return fwdev;
|
||||
}
|
||||
|
||||
@ -184,15 +182,11 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
|
||||
struct tcode_info *info;
|
||||
|
||||
if(xfer == NULL) return EINVAL;
|
||||
if(xfer->send.len > MAXREC(fc->maxrec)){
|
||||
printf("send.len > maxrec\n");
|
||||
return EINVAL;
|
||||
}
|
||||
if(xfer->act.hand == NULL){
|
||||
printf("act.hand == NULL\n");
|
||||
return EINVAL;
|
||||
}
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
|
||||
tcode = fp->mode.common.tcode & 0xf;
|
||||
info = &fc->tcode[tcode];
|
||||
@ -205,16 +199,21 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
|
||||
else
|
||||
xferq = fc->ats;
|
||||
len = info->hdr_len;
|
||||
if (xfer->send.pay_len > MAXREC(fc->maxrec)) {
|
||||
printf("send.pay_len > maxrec\n");
|
||||
return EINVAL;
|
||||
}
|
||||
if (info->flag & FWTI_BLOCK_STR)
|
||||
len += fp->mode.stream.len;
|
||||
len = fp->mode.stream.len;
|
||||
else if (info->flag & FWTI_BLOCK_ASY)
|
||||
len += fp->mode.rresb.len;
|
||||
if( len > xfer->send.len ){
|
||||
printf("len(%d) > send.len(%d) (tcode=%d)\n",
|
||||
len, xfer->send.len, tcode);
|
||||
len = fp->mode.rresb.len;
|
||||
else
|
||||
len = 0;
|
||||
if (len != xfer->send.pay_len){
|
||||
printf("len(%d) != send.pay_len(%d) (tcode=%d)\n",
|
||||
len, xfer->send.pay_len, tcode);
|
||||
return EINVAL;
|
||||
}
|
||||
xfer->send.len = len;
|
||||
|
||||
if(xferq->start == NULL){
|
||||
printf("xferq->start == NULL\n");
|
||||
@ -226,7 +225,7 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
|
||||
microtime(&xfer->tv);
|
||||
if (info->flag & FWTI_TLABEL) {
|
||||
if((tl = fw_get_tlabel(fc, xfer)) == -1 )
|
||||
return EIO;
|
||||
@ -314,8 +313,8 @@ firewire_xfer_timeout(struct firewire_comm *fc)
|
||||
struct timeval split_timeout;
|
||||
int i, s;
|
||||
|
||||
split_timeout.tv_sec = 6;
|
||||
split_timeout.tv_usec = 0;
|
||||
split_timeout.tv_sec = 0;
|
||||
split_timeout.tv_usec = 200 * 1000; /* 200 msec */
|
||||
|
||||
microtime(&tv);
|
||||
timevalsub(&tv, &split_timeout);
|
||||
@ -329,7 +328,7 @@ firewire_xfer_timeout(struct firewire_comm *fc)
|
||||
break;
|
||||
device_printf(fc->bdev,
|
||||
"split transaction timeout dst=0x%x tl=0x%x state=%d\n",
|
||||
xfer->dst, i, xfer->state);
|
||||
xfer->send.hdr.mode.hdr.dst, i, xfer->state);
|
||||
xfer->resp = ETIMEDOUT;
|
||||
STAILQ_REMOVE_HEAD(&fc->tlabels[i], link);
|
||||
fw_xfer_done(xfer);
|
||||
@ -346,7 +345,7 @@ firewire_watchdog(void *arg)
|
||||
fc = (struct firewire_comm *)arg;
|
||||
firewire_xfer_timeout(fc);
|
||||
fc->timeout(fc);
|
||||
callout_reset(&fc->timeout_callout, hz,
|
||||
callout_reset(&fc->timeout_callout, hz / 10,
|
||||
(void *)firewire_watchdog, (void *)fc);
|
||||
}
|
||||
|
||||
@ -776,22 +775,22 @@ void fw_init(struct firewire_comm *fc)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define BIND_CMP(addr, fwb) (((addr) < (fwb)->start)?-1:\
|
||||
((fwb)->end < (addr))?1:0)
|
||||
|
||||
/*
|
||||
* To lookup binded process from IEEE1394 address.
|
||||
*/
|
||||
struct fw_bind *
|
||||
fw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo)
|
||||
fw_bindlookup(struct firewire_comm *fc, u_int16_t dest_hi, u_int32_t dest_lo)
|
||||
{
|
||||
u_int64_t addr;
|
||||
struct fw_bind *tfw;
|
||||
for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ;
|
||||
tfw = STAILQ_NEXT(tfw, fclist)){
|
||||
if (tfw->act_type != FWACT_NULL &&
|
||||
tfw->start_hi == dest_hi &&
|
||||
tfw->start_lo <= dest_lo &&
|
||||
(tfw->start_lo + tfw->addrlen) > dest_lo){
|
||||
|
||||
addr = ((u_int64_t)dest_hi << 32) | dest_lo;
|
||||
STAILQ_FOREACH(tfw, &fc->binds, fclist)
|
||||
if (tfw->act_type != FWACT_NULL && BIND_CMP(addr, tfw) == 0)
|
||||
return(tfw);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -801,45 +800,34 @@ fw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo)
|
||||
int
|
||||
fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
|
||||
{
|
||||
struct fw_bind *tfw, *tfw2 = NULL;
|
||||
int err = 0;
|
||||
tfw = STAILQ_FIRST(&fc->binds);
|
||||
if(tfw == NULL){
|
||||
struct fw_bind *tfw, *prev = NULL;
|
||||
|
||||
if (fwb->start > fwb->end) {
|
||||
printf("%s: invalid range\n", __FUNCTION__);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
STAILQ_FOREACH(tfw, &fc->binds, fclist) {
|
||||
if (fwb->end < tfw->start)
|
||||
break;
|
||||
prev = tfw;
|
||||
}
|
||||
if (prev == NULL) {
|
||||
STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
|
||||
goto out;
|
||||
}
|
||||
if((tfw->start_hi > fwb->start_hi) ||
|
||||
(tfw->start_hi == fwb->start_hi &&
|
||||
(tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){
|
||||
STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
|
||||
if (prev->end < fwb->start) {
|
||||
STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist);
|
||||
goto out;
|
||||
}
|
||||
for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){
|
||||
if((tfw->start_hi < fwb->start_hi) ||
|
||||
(tfw->start_hi == fwb->start_hi &&
|
||||
(tfw->start_lo + tfw->addrlen) < fwb->start_lo)){
|
||||
tfw2 = STAILQ_NEXT(tfw, fclist);
|
||||
if(tfw2 == NULL)
|
||||
break;
|
||||
if((tfw2->start_hi > fwb->start_hi) ||
|
||||
(tfw2->start_hi == fwb->start_hi &&
|
||||
tfw2->start_lo > (fwb->start_lo + fwb->addrlen))){
|
||||
break;
|
||||
}else{
|
||||
err = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(tfw != NULL){
|
||||
STAILQ_INSERT_AFTER(&fc->binds, tfw, fwb, fclist);
|
||||
}else{
|
||||
STAILQ_INSERT_TAIL(&fc->binds, fwb, fclist);
|
||||
}
|
||||
|
||||
printf("%s: bind failed\n", __FUNCTION__);
|
||||
return (EBUSY);
|
||||
|
||||
out:
|
||||
if (!err && fwb->act_type == FWACT_CH)
|
||||
if (fwb->act_type == FWACT_CH)
|
||||
STAILQ_INSERT_HEAD(&fc->ir[fwb->sub]->binds, fwb, chlist);
|
||||
return err;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -848,18 +836,31 @@ fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
|
||||
int
|
||||
fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
|
||||
{
|
||||
int s;
|
||||
#if 0
|
||||
struct fw_xfer *xfer, *next;
|
||||
#endif
|
||||
struct fw_bind *tfw;
|
||||
int s;
|
||||
|
||||
s = splfw();
|
||||
/* shall we check the existance? */
|
||||
STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
|
||||
STAILQ_FOREACH(tfw, &fc->binds, fclist)
|
||||
if (tfw == fwb) {
|
||||
STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
|
||||
goto found;
|
||||
}
|
||||
|
||||
printf("%s: no such bind\n", __FUNCTION__);
|
||||
splx(s);
|
||||
return (1);
|
||||
found:
|
||||
#if 0
|
||||
/* shall we do this? */
|
||||
for (xfer = STAILQ_FIRST(&fwb->xferlist); xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free(xfer);
|
||||
}
|
||||
STAILQ_INIT(&fwb->xferlist);
|
||||
#endif
|
||||
|
||||
splx(s);
|
||||
return 0;
|
||||
@ -899,7 +900,7 @@ fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel)
|
||||
|
||||
for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL;
|
||||
tl = STAILQ_NEXT(tl, link)){
|
||||
if(tl->xfer->dst == node){
|
||||
if(tl->xfer->send.hdr.mode.hdr.dst == node){
|
||||
xfer = tl->xfer;
|
||||
splx(s);
|
||||
if (firewire_debug > 2)
|
||||
@ -925,7 +926,6 @@ fw_xfer_alloc(struct malloc_type *type)
|
||||
if (xfer == NULL)
|
||||
return xfer;
|
||||
|
||||
microtime(&xfer->tv);
|
||||
xfer->malloc = type;
|
||||
|
||||
return xfer;
|
||||
@ -937,22 +937,22 @@ fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len)
|
||||
struct fw_xfer *xfer;
|
||||
|
||||
xfer = fw_xfer_alloc(type);
|
||||
xfer->send.len = send_len;
|
||||
xfer->recv.len = recv_len;
|
||||
xfer->send.pay_len = send_len;
|
||||
xfer->recv.pay_len = recv_len;
|
||||
if (xfer == NULL)
|
||||
return(NULL);
|
||||
if (send_len) {
|
||||
xfer->send.buf = malloc(send_len, type, M_NOWAIT | M_ZERO);
|
||||
if (xfer->send.buf == NULL) {
|
||||
if (send_len > 0) {
|
||||
xfer->send.payload = malloc(send_len, type, M_NOWAIT | M_ZERO);
|
||||
if (xfer->send.payload == NULL) {
|
||||
fw_xfer_free(xfer);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
if (recv_len) {
|
||||
xfer->recv.buf = malloc(recv_len, type, M_NOWAIT);
|
||||
if (xfer->recv.buf == NULL) {
|
||||
if (xfer->send.buf != NULL)
|
||||
free(xfer->send.buf, type);
|
||||
if (recv_len > 0) {
|
||||
xfer->recv.payload = malloc(recv_len, type, M_NOWAIT);
|
||||
if (xfer->recv.payload == NULL) {
|
||||
if (xfer->send.payload != NULL)
|
||||
free(xfer->send.payload, type);
|
||||
fw_xfer_free(xfer);
|
||||
return(NULL);
|
||||
}
|
||||
@ -1015,20 +1015,34 @@ fw_xfer_unload(struct fw_xfer* xfer)
|
||||
* To free IEEE1394 XFER structure.
|
||||
*/
|
||||
void
|
||||
fw_xfer_free( struct fw_xfer* xfer)
|
||||
fw_xfer_free_buf( struct fw_xfer* xfer)
|
||||
{
|
||||
if(xfer == NULL ) return;
|
||||
fw_xfer_unload(xfer);
|
||||
if(xfer->send.buf != NULL){
|
||||
free(xfer->send.buf, xfer->malloc);
|
||||
if (xfer == NULL) {
|
||||
printf("%s: xfer == NULL\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if(xfer->recv.buf != NULL){
|
||||
free(xfer->recv.buf, xfer->malloc);
|
||||
fw_xfer_unload(xfer);
|
||||
if(xfer->send.payload != NULL){
|
||||
free(xfer->send.payload, xfer->malloc);
|
||||
}
|
||||
if(xfer->recv.payload != NULL){
|
||||
free(xfer->recv.payload, xfer->malloc);
|
||||
}
|
||||
free(xfer, xfer->malloc);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
fw_xfer_free( struct fw_xfer* xfer)
|
||||
{
|
||||
if (xfer == NULL) {
|
||||
printf("%s: xfer == NULL\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
fw_xfer_unload(xfer);
|
||||
free(xfer, xfer->malloc);
|
||||
}
|
||||
|
||||
void
|
||||
fw_asy_callback_free(struct fw_xfer *xfer)
|
||||
{
|
||||
#if 0
|
||||
@ -1049,14 +1063,14 @@ fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
|
||||
|
||||
fc->status = FWBUSPHYCONF;
|
||||
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 12, 0);
|
||||
xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if (xfer == NULL)
|
||||
return;
|
||||
xfer->fc = fc;
|
||||
xfer->retry_req = fw_asybusy;
|
||||
xfer->act.hand = fw_asy_callback_free;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.ld[1] = 0;
|
||||
if (root_node >= 0)
|
||||
fp->mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23;
|
||||
@ -1337,19 +1351,18 @@ fw_bus_explore(struct firewire_comm *fc )
|
||||
fw_bus_explore_callback);
|
||||
if(xfer == NULL) goto done;
|
||||
#else
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 16);
|
||||
xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if(xfer == NULL){
|
||||
goto done;
|
||||
}
|
||||
xfer->spd = 0;
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
xfer->send.spd = 0;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.rreqq.dest_hi = 0xffff;
|
||||
fp->mode.rreqq.tlrt = 0;
|
||||
fp->mode.rreqq.tcode = FWTCODE_RREQQ;
|
||||
fp->mode.rreqq.pri = 0;
|
||||
fp->mode.rreqq.src = 0;
|
||||
xfer->dst = FWLOCALBUS | fc->ongonode;
|
||||
fp->mode.rreqq.dst = xfer->dst;
|
||||
fp->mode.rreqq.dst = FWLOCALBUS | fc->ongonode;
|
||||
fp->mode.rreqq.dest_lo = addr;
|
||||
xfer->act.hand = fw_bus_explore_callback;
|
||||
|
||||
@ -1383,12 +1396,12 @@ asyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt,
|
||||
struct fw_pkt *fp;
|
||||
int err;
|
||||
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 16);
|
||||
xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if (xfer == NULL)
|
||||
return NULL;
|
||||
|
||||
xfer->spd = spd; /* XXX:min(spd, fc->spd) */
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
xfer->send.spd = spd; /* XXX:min(spd, fc->spd) */
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.rreqq.dest_hi = addr_hi & 0xffff;
|
||||
if(tl & FWP_TL_VALID){
|
||||
fp->mode.rreqq.tlrt = (tl & 0x3f) << 2;
|
||||
@ -1399,8 +1412,7 @@ asyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt,
|
||||
fp->mode.rreqq.tcode = FWTCODE_RREQQ;
|
||||
fp->mode.rreqq.pri = 0;
|
||||
fp->mode.rreqq.src = 0;
|
||||
xfer->dst = addr_hi >> 16;
|
||||
fp->mode.rreqq.dst = xfer->dst;
|
||||
fp->mode.rreqq.dst = addr_hi >> 16;
|
||||
fp->mode.rreqq.dest_lo = addr_lo;
|
||||
xfer->act.hand = hand;
|
||||
|
||||
@ -1442,19 +1454,8 @@ fw_bus_explore_callback(struct fw_xfer *xfer)
|
||||
goto errnode;
|
||||
}
|
||||
|
||||
if(xfer->send.buf == NULL){
|
||||
printf("node%d: send.buf=NULL addr=0x%x\n",
|
||||
fc->ongonode, fc->ongoaddr);
|
||||
goto errnode;
|
||||
}
|
||||
sfp = (struct fw_pkt *)xfer->send.buf;
|
||||
|
||||
if(xfer->recv.buf == NULL){
|
||||
printf("node%d: recv.buf=NULL addr=0x%x\n",
|
||||
fc->ongonode, fc->ongoaddr);
|
||||
goto errnode;
|
||||
}
|
||||
rfp = (struct fw_pkt *)xfer->recv.buf;
|
||||
sfp = &xfer->send.hdr;
|
||||
rfp = &xfer->recv.hdr;
|
||||
#if 0
|
||||
{
|
||||
u_int32_t *qld;
|
||||
@ -1650,7 +1651,9 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
|
||||
label = (label + 1) & 0x3f;
|
||||
for(tmptl = STAILQ_FIRST(&fc->tlabels[label]);
|
||||
tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){
|
||||
if(tmptl->xfer->dst == xfer->dst) break;
|
||||
if (tmptl->xfer->send.hdr.mode.hdr.dst ==
|
||||
xfer->send.hdr.mode.hdr.dst)
|
||||
break;
|
||||
}
|
||||
if(tmptl == NULL) {
|
||||
tl = malloc(sizeof(struct tlabel),M_FW,M_NOWAIT);
|
||||
@ -1663,7 +1666,7 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
|
||||
splx(s);
|
||||
if (firewire_debug > 1)
|
||||
printf("fw_get_tlabel: dst=%d tl=%d\n",
|
||||
xfer->dst, label);
|
||||
xfer->send.hdr.mode.hdr.dst, label);
|
||||
return(label);
|
||||
}
|
||||
}
|
||||
@ -1674,39 +1677,67 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
|
||||
}
|
||||
|
||||
static void
|
||||
fw_rcv_copy(struct fw_xfer *xfer, struct iovec *vec, int nvec)
|
||||
fw_rcv_copy(struct fw_rcv_buf *rb)
|
||||
{
|
||||
char *p;
|
||||
int res, i, len;
|
||||
struct fw_pkt *pkt;
|
||||
u_char *p;
|
||||
struct tcode_info *tinfo;
|
||||
u_int res, i, len, plen;
|
||||
|
||||
p = xfer->recv.buf;
|
||||
res = xfer->recv.len;
|
||||
for (i = 0; i < nvec; i++, vec++) {
|
||||
len = vec->iov_len;
|
||||
rb->xfer->recv.spd -= rb->spd;
|
||||
|
||||
pkt = (struct fw_pkt *)rb->vec->iov_base;
|
||||
tinfo = &rb->fc->tcode[pkt->mode.hdr.tcode];
|
||||
|
||||
/* Copy header */
|
||||
p = (u_char *)&rb->xfer->recv.hdr;
|
||||
bcopy(rb->vec->iov_base, p, tinfo->hdr_len);
|
||||
(u_char *)rb->vec->iov_base += tinfo->hdr_len;
|
||||
rb->vec->iov_len -= tinfo->hdr_len;
|
||||
|
||||
/* Copy payload */
|
||||
p = (u_char *)rb->xfer->recv.payload;
|
||||
res = rb->xfer->recv.pay_len;
|
||||
|
||||
/* special handling for RRESQ */
|
||||
if (pkt->mode.hdr.tcode == FWTCODE_RRESQ &&
|
||||
p != NULL && res >= sizeof(u_int32_t)) {
|
||||
*(u_int32_t *)p = pkt->mode.rresq.data;
|
||||
rb->xfer->recv.pay_len = sizeof(u_int32_t);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tinfo->flag & FWTI_BLOCK_ASY) == 0)
|
||||
return;
|
||||
|
||||
plen = pkt->mode.rresb.len;
|
||||
|
||||
for (i = 0; i < rb->nvec; i++, rb->vec++) {
|
||||
len = MIN(rb->vec->iov_len, plen);
|
||||
if (res < len) {
|
||||
printf("rcv buffer(%d) is %d bytes short.\n",
|
||||
xfer->recv.len, len - res);
|
||||
rb->xfer->recv.pay_len, len - res);
|
||||
len = res;
|
||||
}
|
||||
bcopy(vec->iov_base, p, len);
|
||||
bcopy(rb->vec->iov_base, p, len);
|
||||
p += len;
|
||||
res -= len;
|
||||
if (res <= 0)
|
||||
plen -= len;
|
||||
if (res == 0 || plen == 0)
|
||||
break;
|
||||
}
|
||||
xfer->recv.len -= res;
|
||||
rb->xfer->recv.pay_len -= res;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic packet receving process.
|
||||
*/
|
||||
void
|
||||
fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int spd)
|
||||
fw_rcv(struct fw_rcv_buf *rb)
|
||||
{
|
||||
struct fw_pkt *fp, *resfp;
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_bind *bind;
|
||||
struct firewire_softc *sc;
|
||||
int tcode, s;
|
||||
int i, len, oldstate;
|
||||
#if 0
|
||||
@ -1722,27 +1753,16 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
if((i % 16) != 15) printf("\n");
|
||||
}
|
||||
#endif
|
||||
fp = (struct fw_pkt *)vec[0].iov_base;
|
||||
fp = (struct fw_pkt *)rb->vec[0].iov_base;
|
||||
tcode = fp->mode.common.tcode;
|
||||
#if 0 /* XXX this check is not valid for RRESQ and WREQQ */
|
||||
if (vec[0].iov_len < fc->tcode[tcode].hdr_len) {
|
||||
#if __FreeBSD_version >= 500000
|
||||
printf("fw_rcv: iov_len(%zu) is less than"
|
||||
#else
|
||||
printf("fw_rcv: iov_len(%u) is less than"
|
||||
#endif
|
||||
" hdr_len(%d:tcode=%d)\n", vec[0].iov_len,
|
||||
fc->tcode[tcode].hdr_len, tcode);
|
||||
}
|
||||
#endif
|
||||
switch (tcode) {
|
||||
case FWTCODE_WRES:
|
||||
case FWTCODE_RRESQ:
|
||||
case FWTCODE_RRESB:
|
||||
case FWTCODE_LRES:
|
||||
xfer = fw_tl2xfer(fc, fp->mode.hdr.src,
|
||||
rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src,
|
||||
fp->mode.hdr.tlrt >> 2);
|
||||
if(xfer == NULL) {
|
||||
if(rb->xfer == NULL) {
|
||||
printf("fw_rcv: unknown response "
|
||||
"tcode=%d src=0x%x tl=0x%x rt=%d data=0x%x\n",
|
||||
tcode,
|
||||
@ -1752,9 +1772,9 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
fp->mode.rresq.data);
|
||||
#if 1
|
||||
printf("try ad-hoc work around!!\n");
|
||||
xfer = fw_tl2xfer(fc, fp->mode.hdr.src,
|
||||
rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src,
|
||||
(fp->mode.hdr.tlrt >> 2)^3);
|
||||
if (xfer == NULL) {
|
||||
if (rb->xfer == NULL) {
|
||||
printf("no use...\n");
|
||||
goto err;
|
||||
}
|
||||
@ -1762,23 +1782,26 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
goto err;
|
||||
#endif
|
||||
}
|
||||
fw_rcv_copy(xfer, vec, nvec);
|
||||
xfer->resp = 0;
|
||||
fw_rcv_copy(rb);
|
||||
if (rb->xfer->recv.hdr.mode.wres.rtcode != RESP_CMP)
|
||||
rb->xfer->resp = EIO;
|
||||
else
|
||||
rb->xfer->resp = 0;
|
||||
/* make sure the packet is drained in AT queue */
|
||||
oldstate = xfer->state;
|
||||
xfer->state = FWXF_RCVD;
|
||||
oldstate = rb->xfer->state;
|
||||
rb->xfer->state = FWXF_RCVD;
|
||||
switch (oldstate) {
|
||||
case FWXF_SENT:
|
||||
fw_xfer_done(xfer);
|
||||
fw_xfer_done(rb->xfer);
|
||||
break;
|
||||
case FWXF_START:
|
||||
#if 0
|
||||
if (firewire_debug)
|
||||
printf("not sent yet tl=%x\n", xfer->tl);
|
||||
printf("not sent yet tl=%x\n", rb->xfer->tl);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("unexpected state %d\n", xfer->state);
|
||||
printf("unexpected state %d\n", rb->xfer->state);
|
||||
}
|
||||
return;
|
||||
case FWTCODE_WREQQ:
|
||||
@ -1786,107 +1809,104 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
case FWTCODE_RREQQ:
|
||||
case FWTCODE_RREQB:
|
||||
case FWTCODE_LREQ:
|
||||
bind = fw_bindlookup(fc, fp->mode.rreqq.dest_hi,
|
||||
bind = fw_bindlookup(rb->fc, fp->mode.rreqq.dest_hi,
|
||||
fp->mode.rreqq.dest_lo);
|
||||
if(bind == NULL){
|
||||
#if __FreeBSD_version >= 500000
|
||||
printf("Unknown service addr 0x%08x:0x%08x tcode=%x src=0x%x data=%x\n",
|
||||
printf("Unknown service addr 0x%04x:0x%08x tcode=%x src=0x%x data=%x\n",
|
||||
#else
|
||||
printf("Unknown service addr 0x%08x:0x%08x tcode=%x src=0x%x data=%lx\n",
|
||||
printf("Unknown service addr 0x%04x:0x%08x tcode=%x src=0x%x data=%lx\n",
|
||||
#endif
|
||||
fp->mode.wreqq.dest_hi,
|
||||
fp->mode.wreqq.dest_lo,
|
||||
tcode,
|
||||
fp->mode.hdr.src,
|
||||
ntohl(fp->mode.wreqq.data));
|
||||
if (fc->status == FWBUSRESET) {
|
||||
if (rb->fc->status == FWBUSRESET) {
|
||||
printf("fw_rcv: cannot respond(bus reset)!\n");
|
||||
goto err;
|
||||
}
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 0);
|
||||
if(xfer == NULL){
|
||||
rb->xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if(rb->xfer == NULL){
|
||||
return;
|
||||
}
|
||||
xfer->spd = spd;
|
||||
resfp = (struct fw_pkt *)xfer->send.buf;
|
||||
rb->xfer->send.spd = rb->spd;
|
||||
rb->xfer->send.pay_len = 0;
|
||||
resfp = &rb->xfer->send.hdr;
|
||||
switch (tcode) {
|
||||
case FWTCODE_WREQQ:
|
||||
case FWTCODE_WREQB:
|
||||
resfp->mode.hdr.tcode = FWTCODE_WRES;
|
||||
xfer->send.len = 12;
|
||||
break;
|
||||
case FWTCODE_RREQQ:
|
||||
resfp->mode.hdr.tcode = FWTCODE_RRESQ;
|
||||
xfer->send.len = 16;
|
||||
break;
|
||||
case FWTCODE_RREQB:
|
||||
resfp->mode.hdr.tcode = FWTCODE_RRESB;
|
||||
xfer->send.len = 16;
|
||||
break;
|
||||
case FWTCODE_LREQ:
|
||||
resfp->mode.hdr.tcode = FWTCODE_LRES;
|
||||
xfer->send.len = 16;
|
||||
break;
|
||||
}
|
||||
resfp->mode.hdr.dst = fp->mode.hdr.src;
|
||||
resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt;
|
||||
resfp->mode.hdr.pri = fp->mode.hdr.pri;
|
||||
resfp->mode.rresb.rtcode = 7;
|
||||
resfp->mode.rresb.rtcode = RESP_ADDRESS_ERROR;
|
||||
resfp->mode.rresb.extcode = 0;
|
||||
resfp->mode.rresb.len = 0;
|
||||
/*
|
||||
xfer->act.hand = fw_asy_callback;
|
||||
rb->xfer->act.hand = fw_asy_callback;
|
||||
*/
|
||||
xfer->act.hand = fw_xfer_free;
|
||||
if(fw_asyreq(fc, -1, xfer)){
|
||||
fw_xfer_free( xfer);
|
||||
rb->xfer->act.hand = fw_xfer_free;
|
||||
if(fw_asyreq(rb->fc, -1, rb->xfer)){
|
||||
fw_xfer_free(rb->xfer);
|
||||
return;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
len = 0;
|
||||
for (i = 0; i < nvec; i ++)
|
||||
len += vec[i].iov_len;
|
||||
for (i = 0; i < rb->nvec; i ++)
|
||||
len += rb->vec[i].iov_len;
|
||||
switch(bind->act_type){
|
||||
case FWACT_XFER:
|
||||
/* splfw()?? */
|
||||
xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (xfer == NULL) {
|
||||
rb->xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (rb->xfer == NULL) {
|
||||
printf("Discard a packet for this bind.\n");
|
||||
goto err;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&bind->xferlist, link);
|
||||
fw_rcv_copy(xfer, vec, nvec);
|
||||
xfer->spd = spd;
|
||||
if (fc->status != FWBUSRESET)
|
||||
xfer->act.hand(xfer);
|
||||
fw_rcv_copy(rb);
|
||||
if (rb->fc->status != FWBUSRESET)
|
||||
rb->xfer->act.hand(rb->xfer);
|
||||
else
|
||||
STAILQ_INSERT_TAIL(&fc->pending, xfer, link);
|
||||
STAILQ_INSERT_TAIL(&rb->fc->pending,
|
||||
rb->xfer, link);
|
||||
return;
|
||||
break;
|
||||
case FWACT_CH:
|
||||
if(fc->ir[bind->sub]->queued >=
|
||||
fc->ir[bind->sub]->maxq){
|
||||
device_printf(fc->bdev,
|
||||
if(rb->fc->ir[bind->sub]->queued >=
|
||||
rb->fc->ir[bind->sub]->maxq){
|
||||
device_printf(rb->fc->bdev,
|
||||
"Discard a packet %x %d\n",
|
||||
bind->sub,
|
||||
fc->ir[bind->sub]->queued);
|
||||
rb->fc->ir[bind->sub]->queued);
|
||||
goto err;
|
||||
}
|
||||
xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (xfer == NULL) {
|
||||
rb->xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (rb->xfer == NULL) {
|
||||
printf("Discard packet for this bind\n");
|
||||
goto err;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&bind->xferlist, link);
|
||||
fw_rcv_copy(xfer, vec, nvec);
|
||||
xfer->spd = spd;
|
||||
fw_rcv_copy(rb);
|
||||
s = splfw();
|
||||
fc->ir[bind->sub]->queued++;
|
||||
STAILQ_INSERT_TAIL(&fc->ir[bind->sub]->q, xfer, link);
|
||||
rb->fc->ir[bind->sub]->queued++;
|
||||
STAILQ_INSERT_TAIL(&rb->fc->ir[bind->sub]->q,
|
||||
rb->xfer, link);
|
||||
splx(s);
|
||||
|
||||
wakeup((caddr_t)fc->ir[bind->sub]);
|
||||
wakeup((caddr_t)rb->fc->ir[bind->sub]);
|
||||
|
||||
return;
|
||||
break;
|
||||
@ -1895,11 +1915,12 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#if 0 /* shouldn't happen ?? or for GASP */
|
||||
case FWTCODE_STREAM:
|
||||
{
|
||||
struct fw_xferq *xferq;
|
||||
|
||||
xferq = fc->ir[sub];
|
||||
xferq = rb->fc->ir[sub];
|
||||
#if 0
|
||||
printf("stream rcv dma %d len %d off %d spd %d\n",
|
||||
sub, len, off, spd);
|
||||
@ -1910,16 +1931,15 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
}
|
||||
/* XXX get xfer from xfer queue, we don't need copy for
|
||||
per packet mode */
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 0, /* XXX */
|
||||
rb->xfer = fw_xfer_alloc_buf(M_FWXFER, 0, /* XXX */
|
||||
vec[0].iov_len);
|
||||
if(xfer == NULL) goto err;
|
||||
fw_rcv_copy(xfer, vec, nvec);
|
||||
xfer->spd = spd;
|
||||
if (rb->xfer == NULL) goto err;
|
||||
fw_rcv_copy(rb)
|
||||
s = splfw();
|
||||
xferq->queued++;
|
||||
STAILQ_INSERT_TAIL(&xferq->q, xfer, link);
|
||||
STAILQ_INSERT_TAIL(&xferq->q, rb->xfer, link);
|
||||
splx(s);
|
||||
sc = device_get_softc(fc->bdev);
|
||||
sc = device_get_softc(rb->fc->bdev);
|
||||
#if __FreeBSD_version >= 500000
|
||||
if (SEL_WAITING(&xferq->rsel))
|
||||
#else
|
||||
@ -1936,6 +1956,7 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
return;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
printf("fw_rcv: unknow tcode %d\n", tcode);
|
||||
break;
|
||||
@ -1950,7 +1971,6 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
|
||||
static void
|
||||
fw_try_bmr_callback(struct fw_xfer *xfer)
|
||||
{
|
||||
struct fw_pkt *rfp;
|
||||
struct firewire_comm *fc;
|
||||
int bmr;
|
||||
|
||||
@ -1959,26 +1979,23 @@ fw_try_bmr_callback(struct fw_xfer *xfer)
|
||||
fc = xfer->fc;
|
||||
if (xfer->resp != 0)
|
||||
goto error;
|
||||
if (xfer->send.buf == NULL)
|
||||
if (xfer->recv.payload == NULL)
|
||||
goto error;
|
||||
if (xfer->recv.buf == NULL)
|
||||
goto error;
|
||||
rfp = (struct fw_pkt *)xfer->recv.buf;
|
||||
if (rfp->mode.lres.rtcode != FWRCODE_COMPLETE)
|
||||
if (xfer->recv.hdr.mode.lres.rtcode != FWRCODE_COMPLETE)
|
||||
goto error;
|
||||
|
||||
bmr = ntohl(rfp->mode.lres.payload[0]);
|
||||
bmr = ntohl(xfer->recv.payload[0]);
|
||||
if (bmr == 0x3f)
|
||||
bmr = fc->nodeid;
|
||||
|
||||
CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f);
|
||||
fw_xfer_free(xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
fw_bmr(fc);
|
||||
return;
|
||||
|
||||
error:
|
||||
device_printf(fc->bdev, "bus manager election failed\n");
|
||||
fw_xfer_free(xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
|
||||
|
||||
@ -1993,31 +2010,30 @@ fw_try_bmr(void *arg)
|
||||
struct fw_pkt *fp;
|
||||
int err = 0;
|
||||
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 24, 20);
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, 8, 4);
|
||||
if(xfer == NULL){
|
||||
return;
|
||||
}
|
||||
xfer->spd = 0;
|
||||
xfer->send.spd = 0;
|
||||
fc->status = FWBUSMGRELECT;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.lreq.dest_hi = 0xffff;
|
||||
fp->mode.lreq.tlrt = 0;
|
||||
fp->mode.lreq.tcode = FWTCODE_LREQ;
|
||||
fp->mode.lreq.pri = 0;
|
||||
fp->mode.lreq.src = 0;
|
||||
fp->mode.lreq.len = 8;
|
||||
fp->mode.lreq.extcode = FW_LREQ_CMPSWAP;
|
||||
xfer->dst = FWLOCALBUS | fc->irm;
|
||||
fp->mode.lreq.dst = xfer->dst;
|
||||
fp->mode.lreq.extcode = EXTCODE_CMP_SWAP;
|
||||
fp->mode.lreq.dst = FWLOCALBUS | fc->irm;
|
||||
fp->mode.lreq.dest_lo = 0xf0000000 | BUS_MGR_ID;
|
||||
fp->mode.lreq.payload[0] = htonl(0x3f);
|
||||
fp->mode.lreq.payload[1] = htonl(fc->nodeid);
|
||||
xfer->send.payload[0] = htonl(0x3f);
|
||||
xfer->send.payload[1] = htonl(fc->nodeid);
|
||||
xfer->act.hand = fw_try_bmr_callback;
|
||||
|
||||
err = fw_asyreq(fc, -1, xfer);
|
||||
if(err){
|
||||
fw_xfer_free( xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
@ -2124,6 +2140,7 @@ fw_bmr(struct firewire_comm *fc)
|
||||
struct fw_device fwdev;
|
||||
union fw_self_id *self_id;
|
||||
int cmstr;
|
||||
u_int32_t quad;
|
||||
|
||||
/* Check to see if the current root node is cycle master capable */
|
||||
self_id = &fc->topology_map->self_id[fc->max_node];
|
||||
@ -2163,9 +2180,9 @@ fw_bmr(struct firewire_comm *fc)
|
||||
fwdev.maxrec = 8; /* 512 */
|
||||
fwdev.status = FWDEVINIT;
|
||||
/* Set cmstr bit on the cycle master */
|
||||
quad = htonl(1 << 8);
|
||||
fwmem_write_quad(&fwdev, NULL, 0/*spd*/,
|
||||
0xffff, 0xf0000000 | STATE_SET, htonl(1 << 8),
|
||||
fw_asy_callback_free);
|
||||
0xffff, 0xf0000000 | STATE_SET, &quad, fw_asy_callback_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -190,12 +190,6 @@ struct fw_pkt {
|
||||
BIT16x2(src, dest_hi);
|
||||
u_int32_t dest_lo;
|
||||
BIT16x2(len, extcode);
|
||||
#define FW_LREQ_MSKSWAP 1
|
||||
#define FW_LREQ_CMPSWAP 2
|
||||
#define FW_LREQ_FTADD 3
|
||||
#define FW_LREQ_LTADD 4
|
||||
#define FW_LREQ_BDADD 5
|
||||
#define FW_LREQ_WRADD 6
|
||||
u_int32_t payload[0];
|
||||
} lreq;
|
||||
struct {
|
||||
@ -215,6 +209,33 @@ struct fw_pkt {
|
||||
} mode;
|
||||
};
|
||||
|
||||
/*
|
||||
* Response code (rtcode)
|
||||
*/
|
||||
/* The node has successfully completed the command. */
|
||||
#define RESP_CMP 0
|
||||
/* A resource conflict was detected. The request may be retried. */
|
||||
#define RESP_CONFLICT_ERROR 4
|
||||
/* Hardware error, data is unavailable. */
|
||||
#define RESP_DATA_ERROR 5
|
||||
/* A field in the request packet header was set to an unsupported or incorrect
|
||||
* value, or an invalid transaction was attempted (e.g., a write to a read-only
|
||||
* address). */
|
||||
#define RESP_TYPE_ERROR 6
|
||||
/* The destination offset field in the request was set to an address not
|
||||
* accessible in the destination node. */
|
||||
#define RESP_ADDRESS_ERROR 7
|
||||
|
||||
/*
|
||||
* Extended transaction code (extcode)
|
||||
*/
|
||||
#define EXTCODE_MASK_SWAP 1
|
||||
#define EXTCODE_CMP_SWAP 2
|
||||
#define EXTCODE_FETCH_ADD 3
|
||||
#define EXTCODE_LITTLE_ADD 4
|
||||
#define EXTCODE_BOUNDED_ADD 5
|
||||
#define EXTCODE_WRAP_ADD 6
|
||||
|
||||
struct fw_eui64 {
|
||||
u_int32_t hi, lo;
|
||||
};
|
||||
|
@ -224,7 +224,8 @@ struct tlabel{
|
||||
};
|
||||
|
||||
struct fw_bind{
|
||||
u_int32_t start_hi, start_lo, addrlen;
|
||||
u_int64_t start;
|
||||
u_int64_t end;
|
||||
STAILQ_HEAD(, fw_xfer) xferlist;
|
||||
STAILQ_ENTRY(fw_bind) fclist;
|
||||
STAILQ_ENTRY(fw_bind) chlist;
|
||||
@ -240,9 +241,6 @@ struct fw_xfer{
|
||||
struct firewire_comm *fc;
|
||||
struct fw_xferq *q;
|
||||
struct timeval tv;
|
||||
/* XXX should be removed */
|
||||
u_int32_t dst; /* XXX for if_fwe */
|
||||
u_int8_t spd;
|
||||
int8_t resp;
|
||||
#define FWXF_INIT 0
|
||||
#define FWXF_INQ 1
|
||||
@ -259,16 +257,28 @@ struct fw_xfer{
|
||||
void (*hand) __P((struct fw_xfer *));
|
||||
} act;
|
||||
struct {
|
||||
int len;
|
||||
caddr_t buf;
|
||||
struct fw_pkt hdr;
|
||||
u_int32_t *payload;
|
||||
u_int16_t pay_len;
|
||||
u_int8_t spd;
|
||||
} send, recv;
|
||||
struct mbuf *mbuf;
|
||||
STAILQ_ENTRY(fw_xfer) link;
|
||||
struct malloc_type *malloc;
|
||||
};
|
||||
|
||||
struct fw_rcv_buf {
|
||||
struct firewire_comm *fc;
|
||||
struct fw_xfer *xfer;
|
||||
struct iovec *vec;
|
||||
u_int nvec;
|
||||
u_int8_t spd;
|
||||
};
|
||||
|
||||
void fw_sidrcv __P((struct firewire_comm *, u_int32_t *, u_int));
|
||||
void fw_rcv __P((struct firewire_comm *, struct iovec *, int, u_int, u_int));
|
||||
void fw_rcv __P((struct fw_rcv_buf *));
|
||||
void fw_xfer_unload __P(( struct fw_xfer*));
|
||||
void fw_xfer_free_buf __P(( struct fw_xfer*));
|
||||
void fw_xfer_free __P(( struct fw_xfer*));
|
||||
struct fw_xfer *fw_xfer_alloc __P((struct malloc_type *));
|
||||
struct fw_xfer *fw_xfer_alloc_buf __P((struct malloc_type *, int, int));
|
||||
@ -284,9 +294,10 @@ u_int16_t fw_crc16 __P((u_int32_t *, u_int32_t));
|
||||
void fw_xfer_timeout __P((void *));
|
||||
void fw_xfer_done __P((struct fw_xfer *));
|
||||
void fw_asy_callback __P((struct fw_xfer *));
|
||||
void fw_asy_callback_free __P((struct fw_xfer *));
|
||||
struct fw_device *fw_noderesolve_nodeid __P((struct firewire_comm *, int));
|
||||
struct fw_device *fw_noderesolve_eui64 __P((struct firewire_comm *, struct fw_eui64 *));
|
||||
struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int32_t, u_int32_t));
|
||||
struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int16_t, u_int32_t));
|
||||
void fw_drain_txq __P((struct firewire_comm *));
|
||||
int fwdev_makedev __P((struct firewire_softc *));
|
||||
int fwdev_destroydev __P((struct firewire_softc *));
|
||||
@ -303,5 +314,23 @@ extern devclass_t firewire_devclass;
|
||||
#define CALLOUT_INIT(x) callout_init(x)
|
||||
#endif
|
||||
|
||||
#if __FreeBSD_version < 500000
|
||||
/* compatibility shim for 4.X */
|
||||
#define bio buf
|
||||
#define bio_bcount b_bcount
|
||||
#define bio_cmd b_flags
|
||||
#define bio_count b_count
|
||||
#define bio_data b_data
|
||||
#define bio_dev b_dev
|
||||
#define bio_error b_error
|
||||
#define bio_flags b_flags
|
||||
#define bio_offset b_offset
|
||||
#define bio_resid b_resid
|
||||
#define BIO_ERROR B_ERROR
|
||||
#define BIO_READ B_READ
|
||||
#define BIO_WRITE B_WRITE
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
MALLOC_DECLARE(M_FW);
|
||||
MALLOC_DECLARE(M_FWXFER);
|
||||
|
@ -424,6 +424,7 @@ crom_add_chunk(struct crom_src *src, struct crom_chunk *parent,
|
||||
return(index);
|
||||
}
|
||||
|
||||
#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext))
|
||||
int
|
||||
crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
|
||||
struct crom_chunk *chunk, char *buf)
|
||||
@ -431,9 +432,9 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
|
||||
struct csrtext *tl;
|
||||
u_int32_t *p;
|
||||
int len, i;
|
||||
char t[MAX_TEXT];
|
||||
|
||||
len = strlen(buf);
|
||||
#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext))
|
||||
if (len > MAX_TEXT) {
|
||||
#if __FreeBSD_version < 500000
|
||||
printf("text(%d) trancated to %d.\n", len, MAX_TEXT);
|
||||
@ -448,7 +449,9 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
|
||||
tl->spec_id = 0;
|
||||
tl->spec_type = 0;
|
||||
tl->lang_id = 0;
|
||||
p = (u_int32_t *) buf;
|
||||
bzero(&t[0], roundup2(len, sizeof(u_int32_t)));
|
||||
bcopy(buf, &t[0], len);
|
||||
p = (u_int32_t *)&t[0];
|
||||
for (i = 0; i < howmany(len, sizeof(u_int32_t)); i ++)
|
||||
tl->text[i] = ntohl(*p++);
|
||||
return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF));
|
||||
|
@ -39,6 +39,11 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mbuf.h>
|
||||
#if __FreeBSD_version < 500000
|
||||
#include <sys/buf.h>
|
||||
#else
|
||||
#include <sys/bio.h>
|
||||
#endif
|
||||
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -67,6 +72,7 @@ static d_poll_t fw_poll;
|
||||
static d_read_t fw_read; /* for Isochronous packet */
|
||||
static d_write_t fw_write;
|
||||
static d_mmap_t fw_mmap;
|
||||
static d_strategy_t fw_strategy;
|
||||
|
||||
struct cdevsw firewire_cdevsw =
|
||||
{
|
||||
@ -78,12 +84,13 @@ struct cdevsw firewire_cdevsw =
|
||||
.d_ioctl = fw_ioctl,
|
||||
.d_poll = fw_poll,
|
||||
.d_mmap = fw_mmap,
|
||||
.d_strategy = fw_strategy,
|
||||
.d_name = "fw",
|
||||
.d_maj = CDEV_MAJOR,
|
||||
.d_flags = D_MEM
|
||||
#else
|
||||
fw_open, fw_close, fw_read, fw_write, fw_ioctl,
|
||||
fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR,
|
||||
fw_poll, fw_mmap, fw_strategy, "fw", CDEV_MAJOR,
|
||||
nodump, nopsize, D_MEM, -1
|
||||
#endif
|
||||
};
|
||||
@ -270,7 +277,7 @@ fw_read (dev_t dev, struct uio *uio, int ioflag)
|
||||
struct fw_pkt *fp;
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
return fwmem_read(dev, uio, ioflag);
|
||||
return physio(dev, uio, ioflag);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
|
||||
@ -303,16 +310,19 @@ fw_read (dev_t dev, struct uio *uio, int ioflag)
|
||||
err = EIO;
|
||||
return err;
|
||||
} else if(xfer != NULL) {
|
||||
#if 0 /* XXX broken */
|
||||
/* per packet mode or FWACT_CH bind?*/
|
||||
s = splfw();
|
||||
ir->queued --;
|
||||
STAILQ_REMOVE_HEAD(&ir->q, link);
|
||||
splx(s);
|
||||
fp = (struct fw_pkt *)xfer->recv.buf;
|
||||
if(sc->fc->irx_post != NULL)
|
||||
fp = &xfer->recv.hdr;
|
||||
if (sc->fc->irx_post != NULL)
|
||||
sc->fc->irx_post(sc->fc, fp->mode.ld);
|
||||
err = uiomove(xfer->recv.buf, xfer->recv.len, uio);
|
||||
err = uiomove((void *)fp, 1 /* XXX header size */, uio);
|
||||
/* XXX copy payload too */
|
||||
/* XXX we should recycle this xfer */
|
||||
#endif
|
||||
fw_xfer_free( xfer);
|
||||
} else if(ir->stproc != NULL) {
|
||||
/* iso bulkxfer */
|
||||
@ -354,7 +364,7 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
struct fw_xferq *it;
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
return fwmem_write(dev, uio, ioflag);
|
||||
return physio(dev, uio, ioflag);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
fc = sc->fc;
|
||||
@ -520,8 +530,11 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
}
|
||||
break;
|
||||
case FW_ASYREQ:
|
||||
{
|
||||
struct tcode_info *tinfo;
|
||||
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len,
|
||||
PAGE_SIZE /* XXX */);
|
||||
PAGE_SIZE/*XXX*/);
|
||||
if(xfer == NULL){
|
||||
err = ENOMEM;
|
||||
return err;
|
||||
@ -529,7 +542,6 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
fp = &asyreq->pkt;
|
||||
switch (asyreq->req.type) {
|
||||
case FWASREQNODE:
|
||||
xfer->dst = fp->mode.hdr.dst;
|
||||
break;
|
||||
case FWASREQEUI:
|
||||
fwdev = fw_noderesolve_eui64(sc->fc,
|
||||
@ -540,8 +552,7 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
err = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
xfer->dst = FWLOCALBUS | fwdev->dst;
|
||||
fp->mode.hdr.dst = xfer->dst;
|
||||
fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst;
|
||||
break;
|
||||
case FWASRESTL:
|
||||
/* XXX what's this? */
|
||||
@ -550,26 +561,41 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
/* nothing to do */
|
||||
break;
|
||||
}
|
||||
xfer->spd = asyreq->req.sped;
|
||||
bcopy(fp, xfer->send.buf, xfer->send.len);
|
||||
xfer->send.spd = asyreq->req.sped;
|
||||
tinfo = &sc->fc->tcode[fp->mode.hdr.tcode];
|
||||
bcopy(fp, (void *)&xfer->send.hdr, tinfo->hdr_len);
|
||||
if ((tinfo->flag & FWTI_BLOCK_ASY) != 0)
|
||||
bcopy((char *)fp + tinfo->hdr_len,
|
||||
(void *)&xfer->send.payload,
|
||||
asyreq->req.len - tinfo->hdr_len);
|
||||
xfer->act.hand = fw_asy_callback;
|
||||
err = fw_asyreq(sc->fc, -1, xfer);
|
||||
if(err){
|
||||
fw_xfer_free( xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
return err;
|
||||
}
|
||||
err = tsleep(xfer, FWPRI, "asyreq", hz);
|
||||
if(err == 0){
|
||||
if(asyreq->req.len >= xfer->recv.len){
|
||||
asyreq->req.len = xfer->recv.len;
|
||||
if (err == 0) {
|
||||
if (xfer->resp != 0) {
|
||||
err = EIO;
|
||||
goto error;
|
||||
}
|
||||
tinfo = &sc->fc->tcode[xfer->recv.hdr.mode.hdr.tcode];
|
||||
if (asyreq->req.len >= xfer->recv.pay_len +
|
||||
tinfo->hdr_len) {
|
||||
asyreq->req.len = xfer->recv.pay_len;
|
||||
}else{
|
||||
err = EINVAL;
|
||||
}
|
||||
bcopy(xfer->recv.buf, fp, asyreq->req.len);
|
||||
bcopy(&xfer->recv.hdr, fp, tinfo->hdr_len);
|
||||
bcopy(xfer->recv.payload,
|
||||
(char *)fp + tinfo->hdr_len,
|
||||
asyreq->req.len - tinfo->hdr_len);
|
||||
}
|
||||
error:
|
||||
fw_xfer_free( xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
break;
|
||||
}
|
||||
case FW_IBUSRST:
|
||||
sc->fc->ibr(sc->fc);
|
||||
break;
|
||||
@ -598,13 +624,14 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
err = ENOMEM;
|
||||
break;
|
||||
}
|
||||
fwb->start_hi = bindreq->start.hi;
|
||||
fwb->start_lo = bindreq->start.lo;
|
||||
fwb->addrlen = bindreq->len;
|
||||
fwb->start = ((u_int64_t)bindreq->start.hi << 32) |
|
||||
bindreq->start.lo;
|
||||
fwb->end = fwb->start + bindreq->len;
|
||||
/* XXX */
|
||||
fwb->sub = ir->dmach;
|
||||
fwb->act_type = FWACT_CH;
|
||||
|
||||
/* XXX alloc buf */
|
||||
xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if(xfer == NULL){
|
||||
err = ENOMEM;
|
||||
@ -736,6 +763,23 @@ fw_mmap (dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
fw_strategy(struct bio *bp)
|
||||
{
|
||||
dev_t dev;
|
||||
|
||||
dev = bp->bio_dev;
|
||||
if (DEV_FWMEM(dev)) {
|
||||
fwmem_strategy(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
bp->bio_error = EOPNOTSUPP;
|
||||
bp->bio_flags |= BIO_ERROR;
|
||||
bp->bio_resid = bp->bio_bcount;
|
||||
biodone(bp);
|
||||
}
|
||||
|
||||
int
|
||||
fwdev_makedev(struct firewire_softc *sc)
|
||||
{
|
||||
|
@ -44,6 +44,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/sysctl.h>
|
||||
#if __FreeBSD_version < 500000
|
||||
#include <sys/buf.h>
|
||||
#else
|
||||
#include <sys/bio.h>
|
||||
#endif
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
@ -70,6 +75,8 @@ SYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0,
|
||||
SYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0,
|
||||
"Fwmem driver debug flag");
|
||||
|
||||
#define MAXLEN (512 << fwmem_speed)
|
||||
|
||||
static struct fw_xfer *
|
||||
fwmem_xfer_req(
|
||||
struct fw_device *fwdev,
|
||||
@ -81,19 +88,21 @@ fwmem_xfer_req(
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
|
||||
xfer = fw_xfer_alloc_buf(M_FWXFER, slen, rlen);
|
||||
xfer = fw_xfer_alloc(M_FWXFER);
|
||||
if (xfer == NULL)
|
||||
return NULL;
|
||||
|
||||
xfer->fc = fwdev->fc;
|
||||
xfer->dst = FWLOCALBUS | fwdev->dst;
|
||||
xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst;
|
||||
if (spd < 0)
|
||||
xfer->spd = fwdev->speed;
|
||||
xfer->send.spd = fwdev->speed;
|
||||
else
|
||||
xfer->spd = min(spd, fwdev->speed);
|
||||
xfer->send.spd = min(spd, fwdev->speed);
|
||||
xfer->act.hand = hand;
|
||||
xfer->retry_req = fw_asybusy;
|
||||
xfer->sc = sc;
|
||||
xfer->send.pay_len = slen;
|
||||
xfer->recv.pay_len = rlen;
|
||||
|
||||
return xfer;
|
||||
}
|
||||
@ -105,21 +114,25 @@ fwmem_read_quad(
|
||||
u_int8_t spd,
|
||||
u_int16_t dst_hi,
|
||||
u_int32_t dst_lo,
|
||||
void *data,
|
||||
void (*hand)(struct fw_xfer *))
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt *fp;
|
||||
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, 12, 16, hand);
|
||||
if (xfer == NULL)
|
||||
xfer = fwmem_xfer_req(fwdev, (void *)sc, spd, 0, 4, hand);
|
||||
if (xfer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.rreqq.tcode = FWTCODE_RREQQ;
|
||||
fp->mode.rreqq.dst = xfer->dst;
|
||||
fp->mode.rreqq.dest_hi = dst_hi;
|
||||
fp->mode.rreqq.dest_lo = dst_lo;
|
||||
|
||||
xfer->send.payload = NULL;
|
||||
xfer->recv.payload = (u_int32_t *)data;
|
||||
|
||||
if (fwmem_debug)
|
||||
printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst,
|
||||
dst_hi, dst_lo);
|
||||
@ -138,27 +151,27 @@ fwmem_write_quad(
|
||||
u_int8_t spd,
|
||||
u_int16_t dst_hi,
|
||||
u_int32_t dst_lo,
|
||||
u_int32_t data,
|
||||
void *data,
|
||||
void (*hand)(struct fw_xfer *))
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt *fp;
|
||||
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, 16, 12, hand);
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, 0, 0, hand);
|
||||
if (xfer == NULL)
|
||||
return NULL;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqq.tcode = FWTCODE_WREQQ;
|
||||
fp->mode.wreqq.dst = xfer->dst;
|
||||
fp->mode.wreqq.dest_hi = dst_hi;
|
||||
fp->mode.wreqq.dest_lo = dst_lo;
|
||||
fp->mode.wreqq.data = *(u_int32_t *)data;
|
||||
|
||||
fp->mode.wreqq.data = data;
|
||||
xfer->send.payload = xfer->recv.payload = NULL;
|
||||
|
||||
if (fwmem_debug)
|
||||
printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst,
|
||||
dst_hi, dst_lo, data);
|
||||
dst_hi, dst_lo, *(u_int32_t *)data);
|
||||
|
||||
if (fw_asyreq(xfer->fc, -1, xfer) == 0)
|
||||
return xfer;
|
||||
@ -175,21 +188,25 @@ fwmem_read_block(
|
||||
u_int16_t dst_hi,
|
||||
u_int32_t dst_lo,
|
||||
int len,
|
||||
void *data,
|
||||
void (*hand)(struct fw_xfer *))
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt *fp;
|
||||
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, 16, roundup2(16+len,4), hand);
|
||||
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, 0, roundup2(len, 4), hand);
|
||||
if (xfer == NULL)
|
||||
return NULL;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.rreqb.tcode = FWTCODE_RREQB;
|
||||
fp->mode.rreqb.dst = xfer->dst;
|
||||
fp->mode.rreqb.dest_hi = dst_hi;
|
||||
fp->mode.rreqb.dest_lo = dst_lo;
|
||||
fp->mode.rreqb.len = len;
|
||||
fp->mode.rreqb.extcode = 0;
|
||||
|
||||
xfer->send.payload = NULL;
|
||||
xfer->recv.payload = data;
|
||||
|
||||
if (fwmem_debug)
|
||||
printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst,
|
||||
@ -209,23 +226,25 @@ fwmem_write_block(
|
||||
u_int16_t dst_hi,
|
||||
u_int32_t dst_lo,
|
||||
int len,
|
||||
char *data,
|
||||
void *data,
|
||||
void (*hand)(struct fw_xfer *))
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt *fp;
|
||||
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, roundup(16+len, 4), 12, hand);
|
||||
xfer = fwmem_xfer_req(fwdev, sc, spd, len, 0, hand);
|
||||
if (xfer == NULL)
|
||||
return NULL;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqb.tcode = FWTCODE_WREQB;
|
||||
fp->mode.wreqb.dst = xfer->dst;
|
||||
fp->mode.wreqb.dest_hi = dst_hi;
|
||||
fp->mode.wreqb.dest_lo = dst_lo;
|
||||
fp->mode.wreqb.len = len;
|
||||
bcopy(data, &fp->mode.wreqb.payload[0], len);
|
||||
fp->mode.wreqb.extcode = 0;
|
||||
|
||||
xfer->send.payload = data;
|
||||
xfer->recv.payload = NULL;
|
||||
|
||||
if (fwmem_debug)
|
||||
printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst,
|
||||
@ -252,6 +271,7 @@ fwmem_open (dev_t dev, int flags, int fmt, fw_proc *td)
|
||||
return ENOMEM;
|
||||
bcopy(&fwmem_eui64, eui, sizeof(struct fw_eui64));
|
||||
dev->si_drv1 = (void *)eui;
|
||||
dev->si_iosize_max = DFLTPHYS;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -265,145 +285,90 @@ fwmem_close (dev_t dev, int flags, int fmt, fw_proc *td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define MAXLEN 2048
|
||||
#define USE_QUAD 0
|
||||
int
|
||||
fwmem_read (dev_t dev, struct uio *uio, int ioflag)
|
||||
|
||||
static void
|
||||
fwmem_biodone(struct fw_xfer *xfer)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct fw_device *fwdev;
|
||||
struct fw_xfer *xfer;
|
||||
int err = 0;
|
||||
int unit = DEV2UNIT(dev);
|
||||
u_int16_t dst_hi;
|
||||
u_int32_t dst_lo;
|
||||
off_t offset;
|
||||
int len, s;
|
||||
struct bio *bp;
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
fwdev = fw_noderesolve_eui64(sc->fc, (struct fw_eui64 *)dev->si_drv1);
|
||||
if (fwdev == NULL) {
|
||||
if (fwmem_debug)
|
||||
printf("fwmem: no such device ID:%08x%08x\n",
|
||||
fwmem_eui64.hi, fwmem_eui64.lo);
|
||||
return EINVAL;
|
||||
bp = (struct bio *)xfer->sc;
|
||||
bp->bio_error = xfer->resp;
|
||||
|
||||
if (bp->bio_error != 0) {
|
||||
printf("%s: err=%d\n", __FUNCTION__, bp->bio_error);
|
||||
bp->bio_flags |= BIO_ERROR;
|
||||
bp->bio_resid = bp->bio_bcount;
|
||||
}
|
||||
|
||||
while(uio->uio_resid > 0 && !err) {
|
||||
offset = uio->uio_offset;
|
||||
dst_hi = (offset >> 32) & 0xffff;
|
||||
dst_lo = offset & 0xffffffff;
|
||||
len = uio->uio_resid;
|
||||
if (len == 4 && (dst_lo & 3) == 0) {
|
||||
s = splfw();
|
||||
xfer = fwmem_read_quad(fwdev, NULL, fwmem_speed,
|
||||
dst_hi, dst_lo, fw_asy_callback);
|
||||
if (xfer == NULL) {
|
||||
err = EINVAL;
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
err = tsleep((caddr_t)xfer, FWPRI, "fwmrq", 0);
|
||||
splx(s);
|
||||
if (xfer->recv.buf == NULL)
|
||||
err = EIO;
|
||||
else if (xfer->resp != 0)
|
||||
err = xfer->resp;
|
||||
else if (err == 0)
|
||||
err = uiomove(xfer->recv.buf + 4*3, 4, uio);
|
||||
} else {
|
||||
if (len > MAXLEN)
|
||||
len = MAXLEN;
|
||||
s = splfw();
|
||||
xfer = fwmem_read_block(fwdev, NULL, fwmem_speed,
|
||||
dst_hi, dst_lo, len, fw_asy_callback);
|
||||
if (xfer == NULL) {
|
||||
err = EINVAL;
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
err = tsleep((caddr_t)xfer, FWPRI, "fwmrb", 0);
|
||||
splx(s);
|
||||
if (xfer->recv.buf == NULL)
|
||||
err = EIO;
|
||||
else if (xfer->resp != 0)
|
||||
err = xfer->resp;
|
||||
else if (err == 0)
|
||||
err = uiomove(xfer->recv.buf + 4*4, len, uio);
|
||||
}
|
||||
fw_xfer_free(xfer);
|
||||
}
|
||||
return err;
|
||||
fw_xfer_free(xfer);
|
||||
biodone(bp);
|
||||
}
|
||||
int
|
||||
fwmem_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
|
||||
void
|
||||
fwmem_strategy(struct bio *bp)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct fw_device *fwdev;
|
||||
struct fw_xfer *xfer;
|
||||
int err = 0;
|
||||
int unit = DEV2UNIT(dev);
|
||||
u_int16_t dst_hi;
|
||||
u_int32_t dst_lo, quad;
|
||||
char *data;
|
||||
off_t offset;
|
||||
int len, s;
|
||||
dev_t dev;
|
||||
int unit, err=0, s, iolen;
|
||||
|
||||
KASSERT(BUF_REFCNT(bp) > 0, ("fwmem_strategy: bp %p not busy %d", bp, BUF_REFCNT(bp)));
|
||||
dev = bp->bio_dev;
|
||||
/* XXX check request length */
|
||||
|
||||
unit = DEV2UNIT(dev);
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
|
||||
s = splfw();
|
||||
fwdev = fw_noderesolve_eui64(sc->fc, (struct fw_eui64 *)dev->si_drv1);
|
||||
if (fwdev == NULL) {
|
||||
if (fwmem_debug)
|
||||
printf("fwmem: no such device ID:%08x%08x\n",
|
||||
fwmem_eui64.hi, fwmem_eui64.lo);
|
||||
return EINVAL;
|
||||
err = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
data = malloc(MAXLEN, M_FW, M_WAITOK);
|
||||
if (data == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
while(uio->uio_resid > 0 && !err) {
|
||||
offset = uio->uio_offset;
|
||||
dst_hi = (offset >> 32) & 0xffff;
|
||||
dst_lo = offset & 0xffffffff;
|
||||
len = uio->uio_resid;
|
||||
if (len == 4 && (dst_lo & 3) == 0) {
|
||||
err = uiomove((char *)&quad, sizeof(quad), uio);
|
||||
s = splfw();
|
||||
xfer = fwmem_write_quad(fwdev, NULL, fwmem_speed,
|
||||
dst_hi, dst_lo, quad, fw_asy_callback);
|
||||
if (xfer == NULL) {
|
||||
err = EINVAL;
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
err = tsleep((caddr_t)xfer, FWPRI, "fwmwq", 0);
|
||||
splx(s);
|
||||
if (xfer->resp != 0)
|
||||
err = xfer->resp;
|
||||
} else {
|
||||
if (len > MAXLEN)
|
||||
len = MAXLEN;
|
||||
err = uiomove(data, len, uio);
|
||||
if (err)
|
||||
break;
|
||||
s = splfw();
|
||||
xfer = fwmem_write_block(fwdev, NULL, fwmem_speed,
|
||||
dst_hi, dst_lo, len, data, fw_asy_callback);
|
||||
if (xfer == NULL) {
|
||||
err = EINVAL;
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
err = tsleep((caddr_t)xfer, FWPRI, "fwmwb", 0);
|
||||
splx(s);
|
||||
if (xfer->resp != 0)
|
||||
err = xfer->resp;
|
||||
}
|
||||
fw_xfer_free(xfer);
|
||||
iolen = MIN(bp->bio_bcount, MAXLEN);
|
||||
if ((bp->bio_cmd & BIO_READ) == BIO_READ) {
|
||||
if (iolen == 4 && (bp->bio_offset & 3) == 0)
|
||||
xfer = fwmem_read_quad(fwdev,
|
||||
(void *) bp, fwmem_speed,
|
||||
bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
|
||||
bp->bio_data, fwmem_biodone);
|
||||
else
|
||||
xfer = fwmem_read_block(fwdev,
|
||||
(void *) bp, fwmem_speed,
|
||||
bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
|
||||
iolen, bp->bio_data, fwmem_biodone);
|
||||
} else {
|
||||
if (iolen == 4 && (bp->bio_offset & 3) == 0)
|
||||
xfer = fwmem_write_quad(fwdev,
|
||||
(void *)bp, fwmem_speed,
|
||||
bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
|
||||
bp->bio_data, fwmem_biodone);
|
||||
else
|
||||
xfer = fwmem_write_block(fwdev,
|
||||
(void *)bp, fwmem_speed,
|
||||
bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
|
||||
iolen, bp->bio_data, fwmem_biodone);
|
||||
}
|
||||
if (xfer == NULL) {
|
||||
err = EIO;
|
||||
goto error;
|
||||
}
|
||||
/* XXX */
|
||||
bp->bio_resid = bp->bio_bcount - iolen;
|
||||
error:
|
||||
splx(s);
|
||||
if (err != 0) {
|
||||
printf("%s: err=%d\n", __FUNCTION__, err);
|
||||
bp->bio_error = err;
|
||||
bp->bio_flags |= BIO_ERROR;
|
||||
bp->bio_resid = bp->bio_bcount;
|
||||
biodone(bp);
|
||||
}
|
||||
free(data, M_FW);
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -35,13 +35,13 @@
|
||||
*/
|
||||
|
||||
struct fw_xfer *fwmem_read_quad(struct fw_device *, caddr_t, u_int8_t,
|
||||
u_int16_t, u_int32_t, void (*)(struct fw_xfer *));
|
||||
u_int16_t, u_int32_t, void *, void (*)(struct fw_xfer *));
|
||||
struct fw_xfer *fwmem_write_quad(struct fw_device *, caddr_t, u_int8_t,
|
||||
u_int16_t, u_int32_t, u_int32_t, void (*)(struct fw_xfer *));
|
||||
u_int16_t, u_int32_t, void *, void (*)(struct fw_xfer *));
|
||||
struct fw_xfer *fwmem_read_block(struct fw_device *, caddr_t, u_int8_t,
|
||||
u_int16_t, u_int32_t, int, void (*)(struct fw_xfer *));
|
||||
u_int16_t, u_int32_t, int, void *, void (*)(struct fw_xfer *));
|
||||
struct fw_xfer *fwmem_write_block(struct fw_device *, caddr_t, u_int8_t,
|
||||
u_int16_t, u_int32_t, int, char *, void (*)(struct fw_xfer *));
|
||||
u_int16_t, u_int32_t, int, void *, void (*)(struct fw_xfer *));
|
||||
|
||||
d_open_t fwmem_open;
|
||||
d_close_t fwmem_close;
|
||||
@ -50,3 +50,4 @@ d_read_t fwmem_read;
|
||||
d_write_t fwmem_write;
|
||||
d_poll_t fwmem_poll;
|
||||
d_mmap_t fwmem_mmap;
|
||||
d_strategy_t fwmem_strategy;
|
||||
|
@ -138,7 +138,7 @@ static void fwohci_set_intr __P((struct firewire_comm *, int));
|
||||
static int fwohci_add_rx_buf __P((struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *));
|
||||
static int fwohci_add_tx_buf __P((struct fwohci_dbch *, struct fwohcidb_tr *, int));
|
||||
static void dump_db __P((struct fwohci_softc *, u_int32_t));
|
||||
static void print_db __P((struct fwohcidb_tr *, volatile struct fwohcidb *, u_int32_t , u_int32_t));
|
||||
static void print_db __P((struct fwohcidb_tr *, struct fwohcidb *, u_int32_t , u_int32_t));
|
||||
static void dump_dma __P((struct fwohci_softc *, u_int32_t));
|
||||
static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
|
||||
static void fwohci_rbuf_update __P((struct fwohci_softc *, int));
|
||||
@ -799,7 +799,7 @@ static void
|
||||
fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
{
|
||||
struct fwohcidb_tr *db_tr;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
bus_dma_segment_t *s;
|
||||
int i;
|
||||
|
||||
@ -831,15 +831,15 @@ static void
|
||||
fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
{
|
||||
int i, s;
|
||||
int tcode, hdr_len, pl_off, pl_len;
|
||||
int tcode, hdr_len, pl_off;
|
||||
int fsegment = -1;
|
||||
u_int32_t off;
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt *fp;
|
||||
volatile struct fwohci_txpkthdr *ohcifp;
|
||||
struct fwohci_txpkthdr *ohcifp;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
volatile struct fwohcidb *db;
|
||||
volatile u_int32_t *ld;
|
||||
struct fwohcidb *db;
|
||||
u_int32_t *ld;
|
||||
struct tcode_info *info;
|
||||
static int maxdesc=0;
|
||||
|
||||
@ -868,10 +868,10 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
db_tr->xfer = xfer;
|
||||
xfer->state = FWXF_START;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
tcode = fp->mode.common.tcode;
|
||||
|
||||
ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
|
||||
ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
|
||||
info = &tinfo[tcode];
|
||||
hdr_len = pl_off = info->hdr_len;
|
||||
|
||||
@ -880,7 +880,7 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
for( i = 0 ; i < pl_off ; i+= 4)
|
||||
ld[i/4] = fp->mode.ld[i/4];
|
||||
|
||||
ohcifp->mode.common.spd = xfer->spd & 0x7;
|
||||
ohcifp->mode.common.spd = xfer->send.spd & 0x7;
|
||||
if (tcode == FWTCODE_STREAM ){
|
||||
hdr_len = 8;
|
||||
ohcifp->mode.stream.len = fp->mode.stream.len;
|
||||
@ -915,16 +915,12 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
again:
|
||||
db_tr->dbcnt = 2;
|
||||
db = &db_tr->db[db_tr->dbcnt];
|
||||
pl_len = xfer->send.len - pl_off;
|
||||
if (pl_len > 0) {
|
||||
if (xfer->send.pay_len > 0) {
|
||||
int err;
|
||||
/* handle payload */
|
||||
if (xfer->mbuf == NULL) {
|
||||
caddr_t pl_addr;
|
||||
|
||||
pl_addr = xfer->send.buf + pl_off;
|
||||
err = bus_dmamap_load(dbch->dmat, db_tr->dma_map,
|
||||
pl_addr, pl_len,
|
||||
&xfer->send.payload[0], xfer->send.pay_len,
|
||||
fwohci_execute_db, db_tr,
|
||||
/*flags*/0);
|
||||
} else {
|
||||
@ -1030,7 +1026,7 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
{
|
||||
int s, ch, err = 0;
|
||||
struct fwohcidb_tr *tr;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
struct fw_xfer *xfer;
|
||||
u_int32_t off;
|
||||
u_int stat, status;
|
||||
@ -1123,14 +1119,14 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
if (xfer->retry_req != NULL)
|
||||
xfer->retry_req(xfer);
|
||||
else {
|
||||
xfer->recv.len = 0;
|
||||
xfer->recv.pay_len = 0;
|
||||
fw_xfer_done(xfer);
|
||||
}
|
||||
} else if (stat != FWOHCIEV_ACKPEND) {
|
||||
if (stat != FWOHCIEV_ACKCOMPL)
|
||||
xfer->state = FWXF_SENTERR;
|
||||
xfer->resp = err;
|
||||
xfer->recv.len = 0;
|
||||
xfer->recv.pay_len = 0;
|
||||
fw_xfer_done(xfer);
|
||||
}
|
||||
}
|
||||
@ -1319,7 +1315,7 @@ fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
int idb, z, i, dmach = 0, ldesc;
|
||||
u_int32_t off = NULL;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
|
||||
if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
|
||||
err = EINVAL;
|
||||
@ -1378,7 +1374,7 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
int idb, z, i, dmach = 0, ldesc;
|
||||
u_int32_t off = NULL;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
|
||||
z = dbch->ndesc;
|
||||
if(&sc->arrq == dbch){
|
||||
@ -1509,7 +1505,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
s = splfw();
|
||||
prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
|
||||
while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
|
||||
fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
@ -1636,7 +1632,7 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach)
|
||||
s = splfw();
|
||||
prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
|
||||
while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
|
||||
#if 1 /* XXX for if_fwe */
|
||||
if (chunk->mbuf != NULL) {
|
||||
@ -2104,7 +2100,7 @@ static void
|
||||
fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
|
||||
{
|
||||
struct firewire_comm *fc = &sc->fc;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
struct fw_bulkxfer *chunk;
|
||||
struct fw_xferq *it;
|
||||
u_int32_t stat, count;
|
||||
@ -2150,7 +2146,7 @@ static void
|
||||
fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
|
||||
{
|
||||
struct firewire_comm *fc = &sc->fc;
|
||||
volatile struct fwohcidb_tr *db_tr;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
struct fw_bulkxfer *chunk;
|
||||
struct fw_xferq *ir;
|
||||
u_int32_t stat;
|
||||
@ -2255,7 +2251,7 @@ dump_db(struct fwohci_softc *sc, u_int32_t ch)
|
||||
{
|
||||
struct fwohci_dbch *dbch;
|
||||
struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
|
||||
volatile struct fwohcidb *curr = NULL, *prev, *next = NULL;
|
||||
struct fwohcidb *curr = NULL, *prev, *next = NULL;
|
||||
int idb, jdb;
|
||||
u_int32_t cmd, off;
|
||||
if(ch == 0){
|
||||
@ -2329,7 +2325,7 @@ dump_db(struct fwohci_softc *sc, u_int32_t ch)
|
||||
}
|
||||
|
||||
void
|
||||
print_db(struct fwohcidb_tr *db_tr, volatile struct fwohcidb *db,
|
||||
print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
|
||||
u_int32_t ch, u_int32_t max)
|
||||
{
|
||||
fwohcireg_t stat;
|
||||
@ -2446,9 +2442,9 @@ fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
|
||||
{
|
||||
struct fwohcidb_tr *db_tr, *fdb_tr;
|
||||
struct fwohci_dbch *dbch;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
struct fw_pkt *fp;
|
||||
volatile struct fwohci_txpkthdr *ohcifp;
|
||||
struct fwohci_txpkthdr *ohcifp;
|
||||
unsigned short chtag;
|
||||
int idb;
|
||||
|
||||
@ -2463,7 +2459,7 @@ device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_
|
||||
for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) {
|
||||
db = db_tr->db;
|
||||
fp = (struct fw_pkt *)db_tr->buf;
|
||||
ohcifp = (volatile struct fwohci_txpkthdr *) db[1].db.immed;
|
||||
ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
|
||||
ohcifp->mode.ld[0] = fp->mode.ld[0];
|
||||
ohcifp->mode.common.spd = 0 & 0x7;
|
||||
ohcifp->mode.stream.len = fp->mode.stream.len;
|
||||
@ -2511,7 +2507,7 @@ static int
|
||||
fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
|
||||
int poffset)
|
||||
{
|
||||
volatile struct fwohcidb *db = db_tr->db;
|
||||
struct fwohcidb *db = db_tr->db;
|
||||
struct fw_xferq *it;
|
||||
int err = 0;
|
||||
|
||||
@ -2526,8 +2522,7 @@ fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
|
||||
FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
|
||||
OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
|
||||
FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
|
||||
bzero((void *)(uintptr_t)(volatile void *)
|
||||
&db[1].db.immed[0], sizeof(db[1].db.immed));
|
||||
bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
|
||||
FWOHCI_DMA_WRITE(db[2].db.desc.addr,
|
||||
fwdma_bus_addr(it->buf, poffset) + sizeof(u_int32_t));
|
||||
|
||||
@ -2544,7 +2539,7 @@ int
|
||||
fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
|
||||
int poffset, struct fwdma_alloc *dummy_dma)
|
||||
{
|
||||
volatile struct fwohcidb *db = db_tr->db;
|
||||
struct fwohcidb *db = db_tr->db;
|
||||
struct fw_xferq *ir;
|
||||
int i, ldesc;
|
||||
bus_addr_t dbuf[2];
|
||||
@ -2595,7 +2590,7 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len)
|
||||
{
|
||||
struct fw_pkt *fp0;
|
||||
u_int32_t ld0;
|
||||
int slen;
|
||||
int slen, hlen;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
int i;
|
||||
#endif
|
||||
@ -2605,6 +2600,7 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len)
|
||||
printf("ld0: x%08x\n", ld0);
|
||||
#endif
|
||||
fp0 = (struct fw_pkt *)&ld0;
|
||||
/* determine length to swap */
|
||||
switch (fp0->mode.common.tcode) {
|
||||
case FWTCODE_RREQQ:
|
||||
case FWTCODE_WRES:
|
||||
@ -2624,75 +2620,47 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len)
|
||||
printf("Unknown tcode %d\n", fp0->mode.common.tcode);
|
||||
return(0);
|
||||
}
|
||||
if (slen > len) {
|
||||
hlen = tinfo[fp0->mode.common.tcode].hdr_len;
|
||||
if (hlen > len) {
|
||||
if (firewire_debug)
|
||||
printf("splitted header\n");
|
||||
return(-slen);
|
||||
return(-hlen);
|
||||
}
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
for(i = 0; i < slen/4; i ++)
|
||||
fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
|
||||
#endif
|
||||
return(slen);
|
||||
return(hlen);
|
||||
}
|
||||
|
||||
#define PLEN(x) roundup2(x, sizeof(u_int32_t))
|
||||
static int
|
||||
fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
|
||||
{
|
||||
struct tcode_info *info;
|
||||
int r;
|
||||
|
||||
switch(fp->mode.common.tcode){
|
||||
case FWTCODE_RREQQ:
|
||||
r = sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_WRES:
|
||||
r = sizeof(fp->mode.wres) + sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_WREQQ:
|
||||
r = sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_RREQB:
|
||||
r = sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_RRESQ:
|
||||
r = sizeof(fp->mode.rresq) + sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_WREQB:
|
||||
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
|
||||
+ sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_LREQ:
|
||||
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
|
||||
+ sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_RRESB:
|
||||
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
|
||||
+ sizeof(u_int32_t);
|
||||
break;
|
||||
case FWTCODE_LRES:
|
||||
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
|
||||
+ sizeof(u_int32_t);
|
||||
break;
|
||||
case FWOHCITCODE_PHY:
|
||||
r = 16;
|
||||
break;
|
||||
default:
|
||||
info = &tinfo[fp->mode.common.tcode];
|
||||
r = info->hdr_len + sizeof(u_int32_t);
|
||||
if ((info->flag & FWTI_BLOCK_ASY) != 0)
|
||||
r += roundup2(fp->mode.wreqb.len, sizeof(u_int32_t));
|
||||
|
||||
if (r == sizeof(u_int32_t))
|
||||
/* XXX */
|
||||
device_printf(sc->fc.dev, "Unknown tcode %d\n",
|
||||
fp->mode.common.tcode);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (r > dbch->xferq.psize) {
|
||||
device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
|
||||
/* panic ? */
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_arcv_free_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr)
|
||||
{
|
||||
volatile struct fwohcidb *db = &db_tr->db[0];
|
||||
struct fwohcidb *db = &db_tr->db[0];
|
||||
|
||||
FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
|
||||
FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
|
||||
@ -2812,7 +2780,8 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
|
||||
if (plen < 0) {
|
||||
/* minimum header size + trailer
|
||||
= sizeof(fw_pkt) so this shouldn't happens */
|
||||
printf("plen is negative! offset=%d\n", offset);
|
||||
printf("plen(%d) is negative! offset=%d\n",
|
||||
plen, offset);
|
||||
goto out;
|
||||
}
|
||||
if (plen > 0) {
|
||||
@ -2842,7 +2811,8 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
|
||||
stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
|
||||
#endif
|
||||
#if 0
|
||||
printf("plen: %d, stat %x\n", plen ,stat);
|
||||
printf("plen: %d, stat %x\n",
|
||||
plen ,stat);
|
||||
#endif
|
||||
spd = (stat >> 5) & 0x3;
|
||||
stat &= 0x1f;
|
||||
@ -2853,11 +2823,19 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
|
||||
#endif
|
||||
/* fall through */
|
||||
case FWOHCIEV_ACKCOMPL:
|
||||
{
|
||||
struct fw_rcv_buf rb;
|
||||
|
||||
if ((vec[nvec-1].iov_len -=
|
||||
sizeof(struct fwohci_trailer)) == 0)
|
||||
nvec--;
|
||||
fw_rcv(&sc->fc, vec, nvec, 0, spd);
|
||||
break;
|
||||
rb.fc = &sc->fc;
|
||||
rb.vec = vec;
|
||||
rb.nvec = nvec;
|
||||
rb.spd = spd;
|
||||
fw_rcv(&rb);
|
||||
break;
|
||||
}
|
||||
case FWOHCIEV_BUSRST:
|
||||
if (sc->fc.status != FWBUSRESET)
|
||||
printf("got BUSRST packet!?\n");
|
||||
|
@ -76,7 +76,7 @@
|
||||
#define OHCI_MAX_DMA_CH (0x4 + OHCI_DMA_ITCH + OHCI_DMA_IRCH)
|
||||
|
||||
|
||||
typedef volatile u_int32_t fwohcireg_t;
|
||||
typedef u_int32_t fwohcireg_t;
|
||||
|
||||
/* for PCI */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
@ -94,12 +94,12 @@ typedef volatile u_int32_t fwohcireg_t;
|
||||
struct fwohcidb {
|
||||
union {
|
||||
struct {
|
||||
volatile u_int32_t cmd;
|
||||
volatile u_int32_t addr;
|
||||
volatile u_int32_t depend;
|
||||
volatile u_int32_t res;
|
||||
u_int32_t cmd;
|
||||
u_int32_t addr;
|
||||
u_int32_t depend;
|
||||
u_int32_t res;
|
||||
} desc;
|
||||
volatile u_int32_t immed[4];
|
||||
u_int32_t immed[4];
|
||||
} db;
|
||||
#define OHCI_STATUS_SHIFT 16
|
||||
#define OHCI_COUNT_MASK 0xffff
|
||||
@ -317,7 +317,7 @@ struct ohci_registers {
|
||||
struct fwohcidb_tr{
|
||||
STAILQ_ENTRY(fwohcidb_tr) link;
|
||||
struct fw_xfer *xfer;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fwohcidb *db;
|
||||
bus_dmamap_t dma_map;
|
||||
caddr_t buf;
|
||||
bus_addr_t bus_addr;
|
||||
|
@ -350,7 +350,7 @@ fwe_init(void *arg)
|
||||
xfer = fw_xfer_alloc(M_FWE);
|
||||
if (xfer == NULL)
|
||||
break;
|
||||
xfer->spd = tx_speed;
|
||||
xfer->send.spd = tx_speed;
|
||||
xfer->fc = fwe->fd.fc;
|
||||
xfer->retry_req = fw_asybusy;
|
||||
xfer->sc = (caddr_t)fwe;
|
||||
@ -447,7 +447,6 @@ fwe_output_callback(struct fw_xfer *xfer)
|
||||
ifp->if_oerrors ++;
|
||||
|
||||
m_freem(xfer->mbuf);
|
||||
xfer->send.buf = NULL;
|
||||
fw_xfer_unload(xfer);
|
||||
|
||||
s = splimp();
|
||||
@ -529,12 +528,11 @@ fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp)
|
||||
|
||||
/* keep ip packet alignment for alpha */
|
||||
M_PREPEND(m, ETHER_ALIGN, M_DONTWAIT);
|
||||
fp = (struct fw_pkt *)&xfer->dst; /* XXX */
|
||||
xfer->dst = *((int32_t *)&fwe->pkt_hdr);
|
||||
fp = &xfer->send.hdr;
|
||||
*(u_int32_t *)&xfer->send.hdr = *(int32_t *)&fwe->pkt_hdr;
|
||||
fp->mode.stream.len = m->m_pkthdr.len;
|
||||
xfer->send.buf = (caddr_t) fp;
|
||||
xfer->mbuf = m;
|
||||
xfer->send.len = m->m_pkthdr.len + HDR_LEN;
|
||||
xfer->send.pay_len = m->m_pkthdr.len;
|
||||
|
||||
if (fw_asyreq(fwe->fd.fc, -1, xfer) != 0) {
|
||||
/* error */
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include <dev/firewire/firewirereg.h>
|
||||
#include <dev/firewire/fwdma.h>
|
||||
#include <dev/firewire/iec13213.h>
|
||||
#include <dev/firewire/sbp.h>
|
||||
|
||||
#define ccb_sdev_ptr spriv_ptr0
|
||||
#define ccb_sbp_ptr spriv_ptr1
|
||||
@ -77,10 +78,6 @@
|
||||
#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb))
|
||||
#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS)
|
||||
|
||||
#define SBP_INITIATOR 7
|
||||
|
||||
#define LOGIN_DELAY 2
|
||||
|
||||
/*
|
||||
* STATUS FIFO addressing
|
||||
* bit
|
||||
@ -88,67 +85,25 @@
|
||||
* 0- 1( 2): 0 (alingment)
|
||||
* 2- 7( 6): target
|
||||
* 8-15( 8): lun
|
||||
* 16-23( 8): unit
|
||||
* 24-31( 8): reserved
|
||||
* 16-31( 8): reserved
|
||||
* 32-47(16): SBP_BIND_HI
|
||||
* 48-64(16): bus_id, node_id
|
||||
*/
|
||||
#define SBP_BIND_HI 0x1
|
||||
#define SBP_DEV2ADDR(u, t, l) \
|
||||
((((u) & 0xff) << 16) | (((l) & 0xff) << 8) | (((t) & 0x3f) << 2))
|
||||
#define SBP_DEV2ADDR(t, l) \
|
||||
(((u_int64_t)SBP_BIND_HI << 32) \
|
||||
| (((l) & 0xff) << 8) \
|
||||
| (((t) & 0x3f) << 2))
|
||||
#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f)
|
||||
#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff)
|
||||
#define SBP_INITIATOR 7
|
||||
|
||||
#define ORB_NOTIFY (1 << 31)
|
||||
#define ORB_FMT_STD (0 << 29)
|
||||
#define ORB_FMT_VED (2 << 29)
|
||||
#define ORB_FMT_NOP (3 << 29)
|
||||
#define ORB_FMT_MSK (3 << 29)
|
||||
#define ORB_EXV (1 << 28)
|
||||
/* */
|
||||
#define ORB_CMD_IN (1 << 27)
|
||||
/* */
|
||||
#define ORB_CMD_SPD(x) ((x) << 24)
|
||||
#define ORB_CMD_MAXP(x) ((x) << 20)
|
||||
#define ORB_RCN_TMO(x) ((x) << 20)
|
||||
#define ORB_CMD_PTBL (1 << 19)
|
||||
#define ORB_CMD_PSZ(x) ((x) << 16)
|
||||
|
||||
#define ORB_FUN_LGI (0 << 16)
|
||||
#define ORB_FUN_QLG (1 << 16)
|
||||
#define ORB_FUN_RCN (3 << 16)
|
||||
#define ORB_FUN_LGO (7 << 16)
|
||||
#define ORB_FUN_ATA (0xb << 16)
|
||||
#define ORB_FUN_ATS (0xc << 16)
|
||||
#define ORB_FUN_LUR (0xe << 16)
|
||||
#define ORB_FUN_RST (0xf << 16)
|
||||
#define ORB_FUN_MSK (0xf << 16)
|
||||
#define ORB_FUN_RUNQUEUE 0xffff
|
||||
#define LOGIN_DELAY 1
|
||||
|
||||
static char *orb_fun_name[] = {
|
||||
/* 0 */ "LOGIN",
|
||||
/* 1 */ "QUERY LOGINS",
|
||||
/* 2 */ "Reserved",
|
||||
/* 3 */ "RECONNECT",
|
||||
/* 4 */ "SET PASSWORD",
|
||||
/* 5 */ "Reserved",
|
||||
/* 6 */ "Reserved",
|
||||
/* 7 */ "LOGOUT",
|
||||
/* 8 */ "Reserved",
|
||||
/* 9 */ "Reserved",
|
||||
/* A */ "Reserved",
|
||||
/* B */ "ABORT TASK",
|
||||
/* C */ "ABORT TASK SET",
|
||||
/* D */ "Reserved",
|
||||
/* E */ "LOGICAL UNIT RESET",
|
||||
/* F */ "TARGET RESET"
|
||||
ORB_FUN_NAMES
|
||||
};
|
||||
|
||||
#define ORB_RES_CMPL 0
|
||||
#define ORB_RES_FAIL 1
|
||||
#define ORB_RES_ILLE 2
|
||||
#define ORB_RES_VEND 3
|
||||
|
||||
static int debug = 0;
|
||||
static int auto_login = 1;
|
||||
static int max_speed = 2;
|
||||
@ -163,14 +118,8 @@ SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RW, &auto_login, 0,
|
||||
SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0,
|
||||
"SBP transfer max speed");
|
||||
|
||||
#define SBP_DEBUG(x) if (debug > x) {
|
||||
#define END_DEBUG }
|
||||
|
||||
#define NEED_RESPONSE 0
|
||||
|
||||
struct ind_ptr {
|
||||
u_int32_t hi,lo;
|
||||
};
|
||||
#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE)
|
||||
#ifdef __sparc64__ /* iommu */
|
||||
#define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX)
|
||||
@ -181,9 +130,9 @@ struct sbp_ocb {
|
||||
STAILQ_ENTRY(sbp_ocb) ocb;
|
||||
union ccb *ccb;
|
||||
bus_addr_t bus_addr;
|
||||
volatile u_int32_t orb[8];
|
||||
u_int32_t orb[8];
|
||||
#define IND_PTR_OFFSET (8*sizeof(u_int32_t))
|
||||
volatile struct ind_ptr ind_ptr[SBP_IND_MAX];
|
||||
struct ind_ptr ind_ptr[SBP_IND_MAX];
|
||||
struct sbp_dev *sdev;
|
||||
int flags; /* XXX should be removed */
|
||||
bus_dmamap_t dmamap;
|
||||
@ -193,63 +142,6 @@ struct sbp_ocb {
|
||||
#define OCB_ACT_CMD 1
|
||||
#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo))
|
||||
|
||||
#define SBP_RECV_LEN (16 + 32) /* header + payload */
|
||||
|
||||
struct sbp_login_res{
|
||||
u_int16_t len;
|
||||
u_int16_t id;
|
||||
u_int16_t res0;
|
||||
u_int16_t cmd_hi;
|
||||
u_int32_t cmd_lo;
|
||||
u_int16_t res1;
|
||||
u_int16_t recon_hold;
|
||||
};
|
||||
struct sbp_status{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int8_t src:2,
|
||||
resp:2,
|
||||
dead:1,
|
||||
len:3;
|
||||
#else
|
||||
u_int8_t len:3,
|
||||
dead:1,
|
||||
resp:2,
|
||||
src:2;
|
||||
#endif
|
||||
u_int8_t status;
|
||||
u_int16_t orb_hi;
|
||||
u_int32_t orb_lo;
|
||||
u_int32_t data[6];
|
||||
};
|
||||
struct sbp_cmd_status{
|
||||
#define SBP_SFMT_CURR 0
|
||||
#define SBP_SFMT_DEFER 1
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int8_t sfmt:2,
|
||||
status:6;
|
||||
u_int8_t valid:1,
|
||||
mark:1,
|
||||
eom:1,
|
||||
ill_len:1,
|
||||
s_key:4;
|
||||
#else
|
||||
u_int8_t status:6,
|
||||
sfmt:2;
|
||||
u_int8_t s_key:4,
|
||||
ill_len:1,
|
||||
eom:1,
|
||||
mark:1,
|
||||
valid:1;
|
||||
#endif
|
||||
u_int8_t s_code;
|
||||
u_int8_t s_qlfr;
|
||||
u_int32_t info;
|
||||
u_int32_t cdb;
|
||||
u_int8_t fru;
|
||||
u_int8_t s_keydep[3];
|
||||
u_int32_t vend[2];
|
||||
};
|
||||
|
||||
struct sbp_dev{
|
||||
#define SBP_DEV_RESET 0 /* accept login */
|
||||
#define SBP_DEV_LOGIN 1 /* to login */
|
||||
@ -289,7 +181,7 @@ struct sbp_target {
|
||||
struct sbp_ocb *mgm_ocb_cur;
|
||||
STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue;
|
||||
struct callout mgm_ocb_timeout;
|
||||
#define SCAN_DELAY 2
|
||||
#define SCAN_DELAY 1
|
||||
struct callout scan_callout;
|
||||
STAILQ_HEAD(, fw_xfer) xferlist;
|
||||
int n_xfer;
|
||||
@ -406,7 +298,7 @@ END_DEBUG
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
device_set_desc(dev, "SBP2/SCSI over firewire");
|
||||
device_set_desc(dev, "SBP-2/SCSI over FireWire");
|
||||
|
||||
if (bootverbose)
|
||||
debug = bootverbose;
|
||||
@ -879,7 +771,7 @@ END_DEBUG
|
||||
|
||||
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
|
||||
xfer->act.hand = sbp_reset_start_callback;
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqq.dest_hi = 0xffff;
|
||||
fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
|
||||
fp->mode.wreqq.data = htonl(0xf);
|
||||
@ -1057,7 +949,7 @@ sbp_agent_reset_callback(struct fw_xfer *xfer)
|
||||
sdev = (struct sbp_dev *)xfer->sc;
|
||||
SBP_DEBUG(1)
|
||||
sbp_show_sdev_info(sdev, 2);
|
||||
printf("sbp_cmd_callback\n");
|
||||
printf("%s\n", __FUNCTION__);
|
||||
END_DEBUG
|
||||
if (xfer->resp != 0) {
|
||||
sbp_show_sdev_info(sdev, 2);
|
||||
@ -1088,7 +980,7 @@ END_DEBUG
|
||||
xfer->act.hand = sbp_agent_reset_callback;
|
||||
else
|
||||
xfer->act.hand = sbp_do_attach;
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqq.data = htonl(0xf);
|
||||
fw_asyreq(xfer->fc, -1, xfer);
|
||||
sbp_abort_all_ocbs(sdev, CAM_BDR_SENT);
|
||||
@ -1120,7 +1012,7 @@ END_DEBUG
|
||||
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
|
||||
|
||||
xfer->act.hand = sbp_busy_timeout_callback;
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqq.dest_hi = 0xffff;
|
||||
fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT;
|
||||
fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf);
|
||||
@ -1142,12 +1034,12 @@ END_DEBUG
|
||||
return;
|
||||
xfer->act.hand = sbp_cmd_callback;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqb.len = 8;
|
||||
fp->mode.wreqb.extcode = 0;
|
||||
fp->mode.wreqb.payload[0] =
|
||||
xfer->send.payload[0] =
|
||||
htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16));
|
||||
fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
|
||||
xfer->send.payload[1] = htonl(ocb->bus_addr);
|
||||
|
||||
if(fw_asyreq(xfer->fc, -1, xfer) != 0){
|
||||
sbp_xfer_free(xfer);
|
||||
@ -1194,7 +1086,7 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
|
||||
splx(s);
|
||||
return(NULL);
|
||||
}
|
||||
xfer = fw_xfer_alloc_buf(M_SBP, 24, 12);
|
||||
xfer = fw_xfer_alloc_buf(M_SBP, 8, 0);
|
||||
if(xfer == NULL){
|
||||
printf("sbp: fw_xfer_alloc_buf failed\n");
|
||||
splx(s);
|
||||
@ -1211,26 +1103,26 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
|
||||
|
||||
microtime(&xfer->tv);
|
||||
|
||||
if (tcode == FWTCODE_WREQQ)
|
||||
xfer->send.len = 16;
|
||||
else
|
||||
xfer->send.len = 24;
|
||||
xfer->recv.len = 12;
|
||||
|
||||
if (new) {
|
||||
xfer->spd = min(sdev->target->fwdev->speed, max_speed);
|
||||
xfer->recv.pay_len = 0;
|
||||
xfer->send.spd = min(sdev->target->fwdev->speed, max_speed);
|
||||
xfer->fc = sdev->target->sbp->fd.fc;
|
||||
xfer->retry_req = fw_asybusy;
|
||||
}
|
||||
|
||||
if (tcode == FWTCODE_WREQB)
|
||||
xfer->send.pay_len = 8;
|
||||
else
|
||||
xfer->send.pay_len = 0;
|
||||
|
||||
xfer->sc = (caddr_t)sdev;
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqq.dest_hi = sdev->login->cmd_hi;
|
||||
fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset;
|
||||
fp->mode.wreqq.tlrt = 0;
|
||||
fp->mode.wreqq.tcode = tcode;
|
||||
fp->mode.wreqq.pri = 0;
|
||||
xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst;
|
||||
fp->mode.wreqq.dst = xfer->dst;
|
||||
fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst;
|
||||
|
||||
return xfer;
|
||||
|
||||
@ -1265,12 +1157,9 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb)
|
||||
ocb->flags = OCB_ACT_MGM;
|
||||
ocb->sdev = sdev;
|
||||
|
||||
bzero((void *)(uintptr_t)(volatile void *)ocb->orb, sizeof(ocb->orb));
|
||||
bzero((void *)ocb->orb, sizeof(ocb->orb));
|
||||
ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI);
|
||||
ocb->orb[7] = htonl(SBP_DEV2ADDR(
|
||||
device_get_unit(target->sbp->fd.dev),
|
||||
target->target_id,
|
||||
sdev->lun_id));
|
||||
ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id));
|
||||
|
||||
SBP_DEBUG(0)
|
||||
sbp_show_sdev_info(sdev, 2);
|
||||
@ -1278,6 +1167,7 @@ SBP_DEBUG(0)
|
||||
END_DEBUG
|
||||
switch (func) {
|
||||
case ORB_FUN_LGI:
|
||||
ocb->orb[0] = ocb->orb[1] = 0; /* password */
|
||||
ocb->orb[2] = htonl(nid << 16);
|
||||
ocb->orb[3] = htonl(sdev->dma.bus_addr);
|
||||
ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id);
|
||||
@ -1315,13 +1205,17 @@ END_DEBUG
|
||||
}
|
||||
xfer->act.hand = sbp_mgm_callback;
|
||||
|
||||
fp = (struct fw_pkt *)xfer->send.buf;
|
||||
fp = &xfer->send.hdr;
|
||||
fp->mode.wreqb.dest_hi = sdev->target->mgm_hi;
|
||||
fp->mode.wreqb.dest_lo = sdev->target->mgm_lo;
|
||||
fp->mode.wreqb.len = 8;
|
||||
fp->mode.wreqb.extcode = 0;
|
||||
fp->mode.wreqb.payload[0] = htonl(nid << 16);
|
||||
fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
|
||||
xfer->send.payload[0] = htonl(nid << 16);
|
||||
xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff);
|
||||
SBP_DEBUG(0)
|
||||
sbp_show_sdev_info(sdev, 2);
|
||||
printf("mgm orb: %08x\n", (u_int32_t)ocb->bus_addr);
|
||||
END_DEBUG
|
||||
|
||||
fw_asyreq(xfer->fc, -1, xfer);
|
||||
}
|
||||
@ -1509,23 +1403,21 @@ printf("sbp %x %d %d %08x %08x %08x %08x\n",
|
||||
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
|
||||
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11]));
|
||||
*/
|
||||
|
||||
sbp = (struct sbp_softc *)xfer->sc;
|
||||
if(xfer->resp != 0){
|
||||
if (xfer->resp != 0){
|
||||
printf("sbp_recv: xfer->resp != 0\n");
|
||||
goto done0;
|
||||
}
|
||||
if(xfer->recv.buf == NULL){
|
||||
printf("sbp_recv: xfer->recv.buf == NULL\n");
|
||||
if (xfer->recv.payload == NULL){
|
||||
printf("sbp_recv: xfer->recv.payload == NULL\n");
|
||||
goto done0;
|
||||
}
|
||||
sbp = (struct sbp_softc *)xfer->sc;
|
||||
rfp = (struct fw_pkt *)xfer->recv.buf;
|
||||
rfp = &xfer->recv.hdr;
|
||||
if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){
|
||||
printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode);
|
||||
goto done0;
|
||||
}
|
||||
sbp_status = (struct sbp_status *)rfp->mode.wreqb.payload;
|
||||
sbp_status = (struct sbp_status *)xfer->recv.payload;
|
||||
addr = rfp->mode.wreqb.dest_lo;
|
||||
SBP_DEBUG(2)
|
||||
printf("received address 0x%x\n", addr);
|
||||
@ -1748,6 +1640,7 @@ printf("len %d\n", sbp_status->len);
|
||||
sbp_agent_reset(sdev);
|
||||
|
||||
done0:
|
||||
xfer->recv.pay_len = SBP_RECV_LEN;
|
||||
/* The received packet is usually small enough to be stored within
|
||||
* the buffer. In that case, the controller return ack_complete and
|
||||
* no respose is necessary.
|
||||
@ -1772,7 +1665,6 @@ printf("len %d\n", sbp_status->len);
|
||||
fw_asyreq(xfer->fc, -1, xfer);
|
||||
#else
|
||||
/* recycle */
|
||||
xfer->recv.len = SBP_RECV_LEN;
|
||||
STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
|
||||
#endif
|
||||
|
||||
@ -1856,23 +1748,20 @@ END_DEBUG
|
||||
goto fail;
|
||||
|
||||
if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_bus_deregister(cam_sim_path(sbp->sim));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sbp->fwb.start_hi = SBP_BIND_HI;
|
||||
sbp->fwb.start_lo = SBP_DEV2ADDR(device_get_unit(sbp->fd.dev), 0, 0);
|
||||
/* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */
|
||||
sbp->fwb.addrlen = 0xffff;
|
||||
sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0);
|
||||
sbp->fwb.end = sbp->fwb.start + 0xffff;
|
||||
sbp->fwb.act_type = FWACT_XFER;
|
||||
/* pre-allocate xfer */
|
||||
STAILQ_INIT(&sbp->fwb.xferlist);
|
||||
for (i = 0; i < SBP_NUM_OCB/2; i ++) {
|
||||
xfer = fw_xfer_alloc_buf(M_SBP,
|
||||
#if NEED_RESPONSE
|
||||
/* send */12,
|
||||
#else
|
||||
/* send */0,
|
||||
#endif
|
||||
/* recv */SBP_RECV_LEN);
|
||||
xfer->act.hand = sbp_recv;
|
||||
#if NEED_RESPONSE
|
||||
@ -1949,8 +1838,10 @@ END_DEBUG
|
||||
|
||||
for (i = 0; i < SBP_NUM_TARGETS; i ++)
|
||||
sbp_cam_detach_target(&sbp->targets[i]);
|
||||
xpt_async(AC_LOST_DEVICE, sbp->path, NULL);
|
||||
xpt_free_path(sbp->path);
|
||||
xpt_bus_deregister(cam_sim_path(sbp->sim));
|
||||
cam_sim_free(sbp->sim, /*free_devq*/ TRUE),
|
||||
|
||||
sbp_logout_all(sbp);
|
||||
|
||||
@ -1974,7 +1865,7 @@ END_DEBUG
|
||||
for (xfer = STAILQ_FIRST(&target->xferlist);
|
||||
xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free(xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
free(target->luns, M_SBP);
|
||||
}
|
||||
@ -1982,7 +1873,7 @@ END_DEBUG
|
||||
for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist);
|
||||
xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free(xfer);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
STAILQ_INIT(&sbp->fwb.xferlist);
|
||||
fw_bindremove(fc, &sbp->fwb);
|
||||
@ -2259,9 +2150,7 @@ END_DEBUG
|
||||
cdb = (void *)csio->cdb_io.cdb_ptr;
|
||||
else
|
||||
cdb = (void *)&csio->cdb_io.cdb_bytes;
|
||||
bcopy(cdb,
|
||||
(void *)(uintptr_t)(volatile void *)&ocb->orb[5],
|
||||
csio->cdb_len);
|
||||
bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len);
|
||||
/*
|
||||
printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3]));
|
||||
printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7]));
|
||||
|
202
sys/dev/firewire/sbp.h
Normal file
202
sys/dev/firewire/sbp.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Hidetosh Shimokawa
|
||||
* Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetosh Shimokawa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the acknowledgement as bellow:
|
||||
*
|
||||
* This product includes software developed by K. Kobayashi and H. Shimokawa
|
||||
*
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
|
||||
#define ORB_NOTIFY (1 << 31)
|
||||
#define ORB_FMT_STD (0 << 29)
|
||||
#define ORB_FMT_VED (2 << 29)
|
||||
#define ORB_FMT_NOP (3 << 29)
|
||||
#define ORB_FMT_MSK (3 << 29)
|
||||
#define ORB_EXV (1 << 28)
|
||||
/* */
|
||||
#define ORB_CMD_IN (1 << 27)
|
||||
/* */
|
||||
#define ORB_CMD_SPD(x) ((x) << 24)
|
||||
#define ORB_CMD_MAXP(x) ((x) << 20)
|
||||
#define ORB_RCN_TMO(x) ((x) << 20)
|
||||
#define ORB_CMD_PTBL (1 << 19)
|
||||
#define ORB_CMD_PSZ(x) ((x) << 16)
|
||||
|
||||
#define ORB_FUN_LGI (0 << 16)
|
||||
#define ORB_FUN_QLG (1 << 16)
|
||||
#define ORB_FUN_RCN (3 << 16)
|
||||
#define ORB_FUN_LGO (7 << 16)
|
||||
#define ORB_FUN_ATA (0xb << 16)
|
||||
#define ORB_FUN_ATS (0xc << 16)
|
||||
#define ORB_FUN_LUR (0xe << 16)
|
||||
#define ORB_FUN_RST (0xf << 16)
|
||||
#define ORB_FUN_MSK (0xf << 16)
|
||||
#define ORB_FUN_RUNQUEUE 0xffff
|
||||
|
||||
#define ORB_RES_CMPL 0
|
||||
#define ORB_RES_FAIL 1
|
||||
#define ORB_RES_ILLE 2
|
||||
#define ORB_RES_VEND 3
|
||||
|
||||
#define SBP_DEBUG(x) if (debug > x) {
|
||||
#define END_DEBUG }
|
||||
|
||||
struct ind_ptr {
|
||||
u_int32_t hi,lo;
|
||||
};
|
||||
|
||||
|
||||
#define SBP_RECV_LEN 32
|
||||
|
||||
struct sbp_login_res{
|
||||
u_int16_t len;
|
||||
u_int16_t id;
|
||||
u_int16_t res0;
|
||||
u_int16_t cmd_hi;
|
||||
u_int32_t cmd_lo;
|
||||
u_int16_t res1;
|
||||
u_int16_t recon_hold;
|
||||
};
|
||||
|
||||
struct sbp_status{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int8_t src:2,
|
||||
resp:2,
|
||||
dead:1,
|
||||
len:3;
|
||||
#else
|
||||
u_int8_t len:3,
|
||||
dead:1,
|
||||
resp:2,
|
||||
src:2;
|
||||
#endif
|
||||
u_int8_t status;
|
||||
u_int16_t orb_hi;
|
||||
u_int32_t orb_lo;
|
||||
u_int32_t data[6];
|
||||
};
|
||||
/* src */
|
||||
#define SRC_NEXT_EXISTS 0
|
||||
#define SRC_NO_NEXT 1
|
||||
#define SRC_UNSOL 2
|
||||
|
||||
/* resp */
|
||||
#define SBP_REQ_CMP 0 /* request complete */
|
||||
#define SBP_TRANS_FAIL 1 /* transport failure */
|
||||
#define SBP_ILLE_REQ 2 /* illegal request */
|
||||
#define SBP_VEND_DEP 3 /* vendor dependent */
|
||||
|
||||
/* status (resp == 0) */
|
||||
/* 0: No additional Information to report */
|
||||
/* 1: Request Type not supported */
|
||||
/* 2: Speed not supported */
|
||||
/* 3: Page size not supported */
|
||||
/* 4: Access denied */
|
||||
#define STATUS_ACCESS_DENY 4
|
||||
/* 5: Logical unit not supported */
|
||||
/* 6: Maximum payload too small */
|
||||
/* 7: Reserved for future standardization */
|
||||
/* 8: Resource unavailabe */
|
||||
/* 9: Function Rejected */
|
||||
/* 10: Login ID not recognized */
|
||||
/* 11: Dummy ORB completed */
|
||||
/* 12: Request aborted */
|
||||
/* 255: Unspecified error */
|
||||
|
||||
/* status (resp == 1) */
|
||||
/* Referenced object */
|
||||
#define OBJ_ORB (0 << 6) /* 0: ORB */
|
||||
#define OBJ_DATA (1 << 6) /* 1: Data buffer */
|
||||
#define OBJ_PT (2 << 6) /* 2: Page table */
|
||||
#define OBJ_UNSPEC (3 << 6) /* 3: Unable to specify */
|
||||
/* Serial bus error */
|
||||
/* 0: Missing acknowledge */
|
||||
/* 1: Reserved; not to be used */
|
||||
/* 2: Time-out error */
|
||||
#define SBE_TIMEOUT 2
|
||||
/* 3: Reserved; not to be used */
|
||||
/* 4: Busy retry limit exceeded: ack_busy_X */
|
||||
/* 5: Busy retry limit exceeded: ack_busy_A */
|
||||
/* 6: Busy retry limit exceeded: ack_busy_B */
|
||||
/* 7-A: Reserved for future standardization */
|
||||
/* B: Tardy retry limit exceeded */
|
||||
/* C: Confilict error */
|
||||
/* D: Data error */
|
||||
/* E: Type error */
|
||||
/* F: Address error */
|
||||
|
||||
|
||||
struct sbp_cmd_status{
|
||||
#define SBP_SFMT_CURR 0
|
||||
#define SBP_SFMT_DEFER 1
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int8_t sfmt:2,
|
||||
status:6;
|
||||
u_int8_t valid:1,
|
||||
mark:1,
|
||||
eom:1,
|
||||
ill_len:1,
|
||||
s_key:4;
|
||||
#else
|
||||
u_int8_t status:6,
|
||||
sfmt:2;
|
||||
u_int8_t s_key:4,
|
||||
ill_len:1,
|
||||
eom:1,
|
||||
mark:1,
|
||||
valid:1;
|
||||
#endif
|
||||
u_int8_t s_code;
|
||||
u_int8_t s_qlfr;
|
||||
u_int32_t info;
|
||||
u_int32_t cdb;
|
||||
u_int8_t fru;
|
||||
u_int8_t s_keydep[3];
|
||||
u_int32_t vend[2];
|
||||
};
|
||||
|
||||
#define ORB_FUN_NAMES \
|
||||
/* 0 */ "LOGIN", \
|
||||
/* 1 */ "QUERY LOGINS", \
|
||||
/* 2 */ "Reserved", \
|
||||
/* 3 */ "RECONNECT", \
|
||||
/* 4 */ "SET PASSWORD", \
|
||||
/* 5 */ "Reserved", \
|
||||
/* 6 */ "Reserved", \
|
||||
/* 7 */ "LOGOUT", \
|
||||
/* 8 */ "Reserved", \
|
||||
/* 9 */ "Reserved", \
|
||||
/* A */ "Reserved", \
|
||||
/* B */ "ABORT TASK", \
|
||||
/* C */ "ABORT TASK SET", \
|
||||
/* D */ "Reserved", \
|
||||
/* E */ "LOGICAL UNIT RESET", \
|
||||
/* F */ "TARGET RESET"
|
@ -7,7 +7,7 @@
|
||||
KMOD = sbp
|
||||
SRCS = bus_if.h device_if.h \
|
||||
opt_cam.h opt_scsi.h \
|
||||
sbp.c \
|
||||
sbp.c sbp.h \
|
||||
firewire.h firewirereg.h \
|
||||
iec13213.h
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user