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:
simokawa 2003-10-02 04:06:56 +00:00
parent 0093875b35
commit 0c1b10fee8
13 changed files with 805 additions and 658 deletions

View File

@ -141,12 +141,10 @@ fw_noderesolve_nodeid(struct firewire_comm *fc, int dst)
s = splfw(); s = splfw();
STAILQ_FOREACH(fwdev, &fc->devices, link) STAILQ_FOREACH(fwdev, &fc->devices, link)
if (fwdev->dst == dst) if (fwdev->dst == dst && fwdev->status != FWDEVINVAL)
break; break;
splx(s); splx(s);
if(fwdev == NULL) return NULL;
if(fwdev->status == FWDEVINVAL) return NULL;
return fwdev; return fwdev;
} }
@ -184,15 +182,11 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
struct tcode_info *info; struct tcode_info *info;
if(xfer == NULL) return EINVAL; if(xfer == NULL) return EINVAL;
if(xfer->send.len > MAXREC(fc->maxrec)){
printf("send.len > maxrec\n");
return EINVAL;
}
if(xfer->act.hand == NULL){ if(xfer->act.hand == NULL){
printf("act.hand == NULL\n"); printf("act.hand == NULL\n");
return EINVAL; return EINVAL;
} }
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
tcode = fp->mode.common.tcode & 0xf; tcode = fp->mode.common.tcode & 0xf;
info = &fc->tcode[tcode]; info = &fc->tcode[tcode];
@ -205,16 +199,21 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
else else
xferq = fc->ats; xferq = fc->ats;
len = info->hdr_len; 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) if (info->flag & FWTI_BLOCK_STR)
len += fp->mode.stream.len; len = fp->mode.stream.len;
else if (info->flag & FWTI_BLOCK_ASY) else if (info->flag & FWTI_BLOCK_ASY)
len += fp->mode.rresb.len; len = fp->mode.rresb.len;
if( len > xfer->send.len ){ else
printf("len(%d) > send.len(%d) (tcode=%d)\n", len = 0;
len, xfer->send.len, tcode); if (len != xfer->send.pay_len){
printf("len(%d) != send.pay_len(%d) (tcode=%d)\n",
len, xfer->send.pay_len, tcode);
return EINVAL; return EINVAL;
} }
xfer->send.len = len;
if(xferq->start == NULL){ if(xferq->start == NULL){
printf("xferq->start == NULL\n"); printf("xferq->start == NULL\n");
@ -226,7 +225,7 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
return EINVAL; return EINVAL;
} }
microtime(&xfer->tv);
if (info->flag & FWTI_TLABEL) { if (info->flag & FWTI_TLABEL) {
if((tl = fw_get_tlabel(fc, xfer)) == -1 ) if((tl = fw_get_tlabel(fc, xfer)) == -1 )
return EIO; return EIO;
@ -314,8 +313,8 @@ firewire_xfer_timeout(struct firewire_comm *fc)
struct timeval split_timeout; struct timeval split_timeout;
int i, s; int i, s;
split_timeout.tv_sec = 6; split_timeout.tv_sec = 0;
split_timeout.tv_usec = 0; split_timeout.tv_usec = 200 * 1000; /* 200 msec */
microtime(&tv); microtime(&tv);
timevalsub(&tv, &split_timeout); timevalsub(&tv, &split_timeout);
@ -329,7 +328,7 @@ firewire_xfer_timeout(struct firewire_comm *fc)
break; break;
device_printf(fc->bdev, device_printf(fc->bdev,
"split transaction timeout dst=0x%x tl=0x%x state=%d\n", "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; xfer->resp = ETIMEDOUT;
STAILQ_REMOVE_HEAD(&fc->tlabels[i], link); STAILQ_REMOVE_HEAD(&fc->tlabels[i], link);
fw_xfer_done(xfer); fw_xfer_done(xfer);
@ -346,7 +345,7 @@ firewire_watchdog(void *arg)
fc = (struct firewire_comm *)arg; fc = (struct firewire_comm *)arg;
firewire_xfer_timeout(fc); firewire_xfer_timeout(fc);
fc->timeout(fc); fc->timeout(fc);
callout_reset(&fc->timeout_callout, hz, callout_reset(&fc->timeout_callout, hz / 10,
(void *)firewire_watchdog, (void *)fc); (void *)firewire_watchdog, (void *)fc);
} }
@ -776,22 +775,22 @@ void fw_init(struct firewire_comm *fc)
#endif #endif
} }
#define BIND_CMP(addr, fwb) (((addr) < (fwb)->start)?-1:\
((fwb)->end < (addr))?1:0)
/* /*
* To lookup binded process from IEEE1394 address. * To lookup binded process from IEEE1394 address.
*/ */
struct fw_bind * 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; struct fw_bind *tfw;
for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ;
tfw = STAILQ_NEXT(tfw, fclist)){ addr = ((u_int64_t)dest_hi << 32) | dest_lo;
if (tfw->act_type != FWACT_NULL && STAILQ_FOREACH(tfw, &fc->binds, fclist)
tfw->start_hi == dest_hi && if (tfw->act_type != FWACT_NULL && BIND_CMP(addr, tfw) == 0)
tfw->start_lo <= dest_lo &&
(tfw->start_lo + tfw->addrlen) > dest_lo){
return(tfw); return(tfw);
}
}
return(NULL); return(NULL);
} }
@ -801,45 +800,34 @@ fw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo)
int int
fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
{ {
struct fw_bind *tfw, *tfw2 = NULL; struct fw_bind *tfw, *prev = NULL;
int err = 0;
tfw = STAILQ_FIRST(&fc->binds); if (fwb->start > fwb->end) {
if(tfw == NULL){ 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); STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
goto out; goto out;
} }
if((tfw->start_hi > fwb->start_hi) || if (prev->end < fwb->start) {
(tfw->start_hi == fwb->start_hi && STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist);
(tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){
STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
goto out; goto out;
} }
for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){
if((tfw->start_hi < fwb->start_hi) || printf("%s: bind failed\n", __FUNCTION__);
(tfw->start_hi == fwb->start_hi && return (EBUSY);
(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);
}
out: out:
if (!err && fwb->act_type == FWACT_CH) if (fwb->act_type == FWACT_CH)
STAILQ_INSERT_HEAD(&fc->ir[fwb->sub]->binds, fwb, chlist); 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 int
fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
{ {
int s; #if 0
struct fw_xfer *xfer, *next; struct fw_xfer *xfer, *next;
#endif
struct fw_bind *tfw;
int s;
s = splfw(); s = splfw();
/* shall we check the existance? */ STAILQ_FOREACH(tfw, &fc->binds, fclist)
STAILQ_REMOVE(&fc->binds, fwb, fw_bind, 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? */ /* shall we do this? */
for (xfer = STAILQ_FIRST(&fwb->xferlist); xfer != NULL; xfer = next) { for (xfer = STAILQ_FIRST(&fwb->xferlist); xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link); next = STAILQ_NEXT(xfer, link);
fw_xfer_free(xfer); fw_xfer_free(xfer);
} }
STAILQ_INIT(&fwb->xferlist); STAILQ_INIT(&fwb->xferlist);
#endif
splx(s); splx(s);
return 0; 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; for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL;
tl = STAILQ_NEXT(tl, link)){ tl = STAILQ_NEXT(tl, link)){
if(tl->xfer->dst == node){ if(tl->xfer->send.hdr.mode.hdr.dst == node){
xfer = tl->xfer; xfer = tl->xfer;
splx(s); splx(s);
if (firewire_debug > 2) if (firewire_debug > 2)
@ -925,7 +926,6 @@ fw_xfer_alloc(struct malloc_type *type)
if (xfer == NULL) if (xfer == NULL)
return xfer; return xfer;
microtime(&xfer->tv);
xfer->malloc = type; xfer->malloc = type;
return xfer; return xfer;
@ -937,22 +937,22 @@ fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len)
struct fw_xfer *xfer; struct fw_xfer *xfer;
xfer = fw_xfer_alloc(type); xfer = fw_xfer_alloc(type);
xfer->send.len = send_len; xfer->send.pay_len = send_len;
xfer->recv.len = recv_len; xfer->recv.pay_len = recv_len;
if (xfer == NULL) if (xfer == NULL)
return(NULL); return(NULL);
if (send_len) { if (send_len > 0) {
xfer->send.buf = malloc(send_len, type, M_NOWAIT | M_ZERO); xfer->send.payload = malloc(send_len, type, M_NOWAIT | M_ZERO);
if (xfer->send.buf == NULL) { if (xfer->send.payload == NULL) {
fw_xfer_free(xfer); fw_xfer_free(xfer);
return(NULL); return(NULL);
} }
} }
if (recv_len) { if (recv_len > 0) {
xfer->recv.buf = malloc(recv_len, type, M_NOWAIT); xfer->recv.payload = malloc(recv_len, type, M_NOWAIT);
if (xfer->recv.buf == NULL) { if (xfer->recv.payload == NULL) {
if (xfer->send.buf != NULL) if (xfer->send.payload != NULL)
free(xfer->send.buf, type); free(xfer->send.payload, type);
fw_xfer_free(xfer); fw_xfer_free(xfer);
return(NULL); return(NULL);
} }
@ -1015,20 +1015,34 @@ fw_xfer_unload(struct fw_xfer* xfer)
* To free IEEE1394 XFER structure. * To free IEEE1394 XFER structure.
*/ */
void void
fw_xfer_free( struct fw_xfer* xfer) fw_xfer_free_buf( struct fw_xfer* xfer)
{ {
if(xfer == NULL ) return; if (xfer == NULL) {
fw_xfer_unload(xfer); printf("%s: xfer == NULL\n", __FUNCTION__);
if(xfer->send.buf != NULL){ return;
free(xfer->send.buf, xfer->malloc);
} }
if(xfer->recv.buf != NULL){ fw_xfer_unload(xfer);
free(xfer->recv.buf, xfer->malloc); 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); 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) fw_asy_callback_free(struct fw_xfer *xfer)
{ {
#if 0 #if 0
@ -1049,14 +1063,14 @@ fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
fc->status = FWBUSPHYCONF; fc->status = FWBUSPHYCONF;
xfer = fw_xfer_alloc_buf(M_FWXFER, 12, 0); xfer = fw_xfer_alloc(M_FWXFER);
if (xfer == NULL) if (xfer == NULL)
return; return;
xfer->fc = fc; xfer->fc = fc;
xfer->retry_req = fw_asybusy; xfer->retry_req = fw_asybusy;
xfer->act.hand = fw_asy_callback_free; xfer->act.hand = fw_asy_callback_free;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.ld[1] = 0; fp->mode.ld[1] = 0;
if (root_node >= 0) if (root_node >= 0)
fp->mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; 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); fw_bus_explore_callback);
if(xfer == NULL) goto done; if(xfer == NULL) goto done;
#else #else
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 16); xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){ if(xfer == NULL){
goto done; goto done;
} }
xfer->spd = 0; xfer->send.spd = 0;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.rreqq.dest_hi = 0xffff; fp->mode.rreqq.dest_hi = 0xffff;
fp->mode.rreqq.tlrt = 0; fp->mode.rreqq.tlrt = 0;
fp->mode.rreqq.tcode = FWTCODE_RREQQ; fp->mode.rreqq.tcode = FWTCODE_RREQQ;
fp->mode.rreqq.pri = 0; fp->mode.rreqq.pri = 0;
fp->mode.rreqq.src = 0; fp->mode.rreqq.src = 0;
xfer->dst = FWLOCALBUS | fc->ongonode; fp->mode.rreqq.dst = FWLOCALBUS | fc->ongonode;
fp->mode.rreqq.dst = xfer->dst;
fp->mode.rreqq.dest_lo = addr; fp->mode.rreqq.dest_lo = addr;
xfer->act.hand = fw_bus_explore_callback; 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; struct fw_pkt *fp;
int err; int err;
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 16); xfer = fw_xfer_alloc(M_FWXFER);
if (xfer == NULL) if (xfer == NULL)
return NULL; return NULL;
xfer->spd = spd; /* XXX:min(spd, fc->spd) */ xfer->send.spd = spd; /* XXX:min(spd, fc->spd) */
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.rreqq.dest_hi = addr_hi & 0xffff; fp->mode.rreqq.dest_hi = addr_hi & 0xffff;
if(tl & FWP_TL_VALID){ if(tl & FWP_TL_VALID){
fp->mode.rreqq.tlrt = (tl & 0x3f) << 2; 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.tcode = FWTCODE_RREQQ;
fp->mode.rreqq.pri = 0; fp->mode.rreqq.pri = 0;
fp->mode.rreqq.src = 0; fp->mode.rreqq.src = 0;
xfer->dst = addr_hi >> 16; fp->mode.rreqq.dst = addr_hi >> 16;
fp->mode.rreqq.dst = xfer->dst;
fp->mode.rreqq.dest_lo = addr_lo; fp->mode.rreqq.dest_lo = addr_lo;
xfer->act.hand = hand; xfer->act.hand = hand;
@ -1442,19 +1454,8 @@ fw_bus_explore_callback(struct fw_xfer *xfer)
goto errnode; goto errnode;
} }
if(xfer->send.buf == NULL){ sfp = &xfer->send.hdr;
printf("node%d: send.buf=NULL addr=0x%x\n", rfp = &xfer->recv.hdr;
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;
#if 0 #if 0
{ {
u_int32_t *qld; u_int32_t *qld;
@ -1650,7 +1651,9 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
label = (label + 1) & 0x3f; label = (label + 1) & 0x3f;
for(tmptl = STAILQ_FIRST(&fc->tlabels[label]); for(tmptl = STAILQ_FIRST(&fc->tlabels[label]);
tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){ 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) { if(tmptl == NULL) {
tl = malloc(sizeof(struct tlabel),M_FW,M_NOWAIT); 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); splx(s);
if (firewire_debug > 1) if (firewire_debug > 1)
printf("fw_get_tlabel: dst=%d tl=%d\n", printf("fw_get_tlabel: dst=%d tl=%d\n",
xfer->dst, label); xfer->send.hdr.mode.hdr.dst, label);
return(label); return(label);
} }
} }
@ -1674,39 +1677,67 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
} }
static void static void
fw_rcv_copy(struct fw_xfer *xfer, struct iovec *vec, int nvec) fw_rcv_copy(struct fw_rcv_buf *rb)
{ {
char *p; struct fw_pkt *pkt;
int res, i, len; u_char *p;
struct tcode_info *tinfo;
u_int res, i, len, plen;
p = xfer->recv.buf; rb->xfer->recv.spd -= rb->spd;
res = xfer->recv.len;
for (i = 0; i < nvec; i++, vec++) { pkt = (struct fw_pkt *)rb->vec->iov_base;
len = vec->iov_len; 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) { if (res < len) {
printf("rcv buffer(%d) is %d bytes short.\n", printf("rcv buffer(%d) is %d bytes short.\n",
xfer->recv.len, len - res); rb->xfer->recv.pay_len, len - res);
len = res; len = res;
} }
bcopy(vec->iov_base, p, len); bcopy(rb->vec->iov_base, p, len);
p += len; p += len;
res -= len; res -= len;
if (res <= 0) plen -= len;
if (res == 0 || plen == 0)
break; break;
} }
xfer->recv.len -= res; rb->xfer->recv.pay_len -= res;
} }
/* /*
* Generic packet receving process. * Generic packet receving process.
*/ */
void 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_pkt *fp, *resfp;
struct fw_xfer *xfer;
struct fw_bind *bind; struct fw_bind *bind;
struct firewire_softc *sc;
int tcode, s; int tcode, s;
int i, len, oldstate; int i, len, oldstate;
#if 0 #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"); if((i % 16) != 15) printf("\n");
} }
#endif #endif
fp = (struct fw_pkt *)vec[0].iov_base; fp = (struct fw_pkt *)rb->vec[0].iov_base;
tcode = fp->mode.common.tcode; 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) { switch (tcode) {
case FWTCODE_WRES: case FWTCODE_WRES:
case FWTCODE_RRESQ: case FWTCODE_RRESQ:
case FWTCODE_RRESB: case FWTCODE_RRESB:
case FWTCODE_LRES: 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); fp->mode.hdr.tlrt >> 2);
if(xfer == NULL) { if(rb->xfer == NULL) {
printf("fw_rcv: unknown response " printf("fw_rcv: unknown response "
"tcode=%d src=0x%x tl=0x%x rt=%d data=0x%x\n", "tcode=%d src=0x%x tl=0x%x rt=%d data=0x%x\n",
tcode, 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); fp->mode.rresq.data);
#if 1 #if 1
printf("try ad-hoc work around!!\n"); 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); (fp->mode.hdr.tlrt >> 2)^3);
if (xfer == NULL) { if (rb->xfer == NULL) {
printf("no use...\n"); printf("no use...\n");
goto err; 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; goto err;
#endif #endif
} }
fw_rcv_copy(xfer, vec, nvec); fw_rcv_copy(rb);
xfer->resp = 0; 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 */ /* make sure the packet is drained in AT queue */
oldstate = xfer->state; oldstate = rb->xfer->state;
xfer->state = FWXF_RCVD; rb->xfer->state = FWXF_RCVD;
switch (oldstate) { switch (oldstate) {
case FWXF_SENT: case FWXF_SENT:
fw_xfer_done(xfer); fw_xfer_done(rb->xfer);
break; break;
case FWXF_START: case FWXF_START:
#if 0 #if 0
if (firewire_debug) if (firewire_debug)
printf("not sent yet tl=%x\n", xfer->tl); printf("not sent yet tl=%x\n", rb->xfer->tl);
#endif #endif
break; break;
default: default:
printf("unexpected state %d\n", xfer->state); printf("unexpected state %d\n", rb->xfer->state);
} }
return; return;
case FWTCODE_WREQQ: 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_RREQQ:
case FWTCODE_RREQB: case FWTCODE_RREQB:
case FWTCODE_LREQ: 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); fp->mode.rreqq.dest_lo);
if(bind == NULL){ if(bind == NULL){
#if __FreeBSD_version >= 500000 #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 #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 #endif
fp->mode.wreqq.dest_hi, fp->mode.wreqq.dest_hi,
fp->mode.wreqq.dest_lo, fp->mode.wreqq.dest_lo,
tcode, tcode,
fp->mode.hdr.src, fp->mode.hdr.src,
ntohl(fp->mode.wreqq.data)); ntohl(fp->mode.wreqq.data));
if (fc->status == FWBUSRESET) { if (rb->fc->status == FWBUSRESET) {
printf("fw_rcv: cannot respond(bus reset)!\n"); printf("fw_rcv: cannot respond(bus reset)!\n");
goto err; goto err;
} }
xfer = fw_xfer_alloc_buf(M_FWXFER, 16, 0); rb->xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){ if(rb->xfer == NULL){
return; return;
} }
xfer->spd = spd; rb->xfer->send.spd = rb->spd;
resfp = (struct fw_pkt *)xfer->send.buf; rb->xfer->send.pay_len = 0;
resfp = &rb->xfer->send.hdr;
switch (tcode) { switch (tcode) {
case FWTCODE_WREQQ: case FWTCODE_WREQQ:
case FWTCODE_WREQB: case FWTCODE_WREQB:
resfp->mode.hdr.tcode = FWTCODE_WRES; resfp->mode.hdr.tcode = FWTCODE_WRES;
xfer->send.len = 12;
break; break;
case FWTCODE_RREQQ: case FWTCODE_RREQQ:
resfp->mode.hdr.tcode = FWTCODE_RRESQ; resfp->mode.hdr.tcode = FWTCODE_RRESQ;
xfer->send.len = 16;
break; break;
case FWTCODE_RREQB: case FWTCODE_RREQB:
resfp->mode.hdr.tcode = FWTCODE_RRESB; resfp->mode.hdr.tcode = FWTCODE_RRESB;
xfer->send.len = 16;
break; break;
case FWTCODE_LREQ: case FWTCODE_LREQ:
resfp->mode.hdr.tcode = FWTCODE_LRES; resfp->mode.hdr.tcode = FWTCODE_LRES;
xfer->send.len = 16;
break; break;
} }
resfp->mode.hdr.dst = fp->mode.hdr.src; resfp->mode.hdr.dst = fp->mode.hdr.src;
resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt; resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt;
resfp->mode.hdr.pri = fp->mode.hdr.pri; 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.extcode = 0;
resfp->mode.rresb.len = 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; rb->xfer->act.hand = fw_xfer_free;
if(fw_asyreq(fc, -1, xfer)){ if(fw_asyreq(rb->fc, -1, rb->xfer)){
fw_xfer_free( xfer); fw_xfer_free(rb->xfer);
return; return;
} }
goto err; goto err;
} }
len = 0; len = 0;
for (i = 0; i < nvec; i ++) for (i = 0; i < rb->nvec; i ++)
len += vec[i].iov_len; len += rb->vec[i].iov_len;
switch(bind->act_type){ switch(bind->act_type){
case FWACT_XFER: case FWACT_XFER:
/* splfw()?? */ /* splfw()?? */
xfer = STAILQ_FIRST(&bind->xferlist); rb->xfer = STAILQ_FIRST(&bind->xferlist);
if (xfer == NULL) { if (rb->xfer == NULL) {
printf("Discard a packet for this bind.\n"); printf("Discard a packet for this bind.\n");
goto err; goto err;
} }
STAILQ_REMOVE_HEAD(&bind->xferlist, link); STAILQ_REMOVE_HEAD(&bind->xferlist, link);
fw_rcv_copy(xfer, vec, nvec); fw_rcv_copy(rb);
xfer->spd = spd; if (rb->fc->status != FWBUSRESET)
if (fc->status != FWBUSRESET) rb->xfer->act.hand(rb->xfer);
xfer->act.hand(xfer);
else else
STAILQ_INSERT_TAIL(&fc->pending, xfer, link); STAILQ_INSERT_TAIL(&rb->fc->pending,
rb->xfer, link);
return; return;
break; break;
case FWACT_CH: case FWACT_CH:
if(fc->ir[bind->sub]->queued >= if(rb->fc->ir[bind->sub]->queued >=
fc->ir[bind->sub]->maxq){ rb->fc->ir[bind->sub]->maxq){
device_printf(fc->bdev, device_printf(rb->fc->bdev,
"Discard a packet %x %d\n", "Discard a packet %x %d\n",
bind->sub, bind->sub,
fc->ir[bind->sub]->queued); rb->fc->ir[bind->sub]->queued);
goto err; goto err;
} }
xfer = STAILQ_FIRST(&bind->xferlist); rb->xfer = STAILQ_FIRST(&bind->xferlist);
if (xfer == NULL) { if (rb->xfer == NULL) {
printf("Discard packet for this bind\n"); printf("Discard packet for this bind\n");
goto err; goto err;
} }
STAILQ_REMOVE_HEAD(&bind->xferlist, link); STAILQ_REMOVE_HEAD(&bind->xferlist, link);
fw_rcv_copy(xfer, vec, nvec); fw_rcv_copy(rb);
xfer->spd = spd;
s = splfw(); s = splfw();
fc->ir[bind->sub]->queued++; rb->fc->ir[bind->sub]->queued++;
STAILQ_INSERT_TAIL(&fc->ir[bind->sub]->q, xfer, link); STAILQ_INSERT_TAIL(&rb->fc->ir[bind->sub]->q,
rb->xfer, link);
splx(s); splx(s);
wakeup((caddr_t)fc->ir[bind->sub]); wakeup((caddr_t)rb->fc->ir[bind->sub]);
return; return;
break; break;
@ -1895,11 +1915,12 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
break; break;
} }
break; break;
#if 0 /* shouldn't happen ?? or for GASP */
case FWTCODE_STREAM: case FWTCODE_STREAM:
{ {
struct fw_xferq *xferq; struct fw_xferq *xferq;
xferq = fc->ir[sub]; xferq = rb->fc->ir[sub];
#if 0 #if 0
printf("stream rcv dma %d len %d off %d spd %d\n", printf("stream rcv dma %d len %d off %d spd %d\n",
sub, len, off, spd); 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 /* XXX get xfer from xfer queue, we don't need copy for
per packet mode */ 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); vec[0].iov_len);
if(xfer == NULL) goto err; if (rb->xfer == NULL) goto err;
fw_rcv_copy(xfer, vec, nvec); fw_rcv_copy(rb)
xfer->spd = spd;
s = splfw(); s = splfw();
xferq->queued++; xferq->queued++;
STAILQ_INSERT_TAIL(&xferq->q, xfer, link); STAILQ_INSERT_TAIL(&xferq->q, rb->xfer, link);
splx(s); splx(s);
sc = device_get_softc(fc->bdev); sc = device_get_softc(rb->fc->bdev);
#if __FreeBSD_version >= 500000 #if __FreeBSD_version >= 500000
if (SEL_WAITING(&xferq->rsel)) if (SEL_WAITING(&xferq->rsel))
#else #else
@ -1936,6 +1956,7 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
return; return;
break; break;
} }
#endif
default: default:
printf("fw_rcv: unknow tcode %d\n", tcode); printf("fw_rcv: unknow tcode %d\n", tcode);
break; break;
@ -1950,7 +1971,6 @@ fw_rcv(struct firewire_comm *fc, struct iovec *vec, int nvec, u_int sub, u_int s
static void static void
fw_try_bmr_callback(struct fw_xfer *xfer) fw_try_bmr_callback(struct fw_xfer *xfer)
{ {
struct fw_pkt *rfp;
struct firewire_comm *fc; struct firewire_comm *fc;
int bmr; int bmr;
@ -1959,26 +1979,23 @@ fw_try_bmr_callback(struct fw_xfer *xfer)
fc = xfer->fc; fc = xfer->fc;
if (xfer->resp != 0) if (xfer->resp != 0)
goto error; goto error;
if (xfer->send.buf == NULL) if (xfer->recv.payload == NULL)
goto error; goto error;
if (xfer->recv.buf == NULL) if (xfer->recv.hdr.mode.lres.rtcode != FWRCODE_COMPLETE)
goto error;
rfp = (struct fw_pkt *)xfer->recv.buf;
if (rfp->mode.lres.rtcode != FWRCODE_COMPLETE)
goto error; goto error;
bmr = ntohl(rfp->mode.lres.payload[0]); bmr = ntohl(xfer->recv.payload[0]);
if (bmr == 0x3f) if (bmr == 0x3f)
bmr = fc->nodeid; bmr = fc->nodeid;
CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f); CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f);
fw_xfer_free(xfer); fw_xfer_free_buf(xfer);
fw_bmr(fc); fw_bmr(fc);
return; return;
error: error:
device_printf(fc->bdev, "bus manager election failed\n"); 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; struct fw_pkt *fp;
int err = 0; int err = 0;
xfer = fw_xfer_alloc_buf(M_FWXFER, 24, 20); xfer = fw_xfer_alloc_buf(M_FWXFER, 8, 4);
if(xfer == NULL){ if(xfer == NULL){
return; return;
} }
xfer->spd = 0; xfer->send.spd = 0;
fc->status = FWBUSMGRELECT; fc->status = FWBUSMGRELECT;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.lreq.dest_hi = 0xffff; fp->mode.lreq.dest_hi = 0xffff;
fp->mode.lreq.tlrt = 0; fp->mode.lreq.tlrt = 0;
fp->mode.lreq.tcode = FWTCODE_LREQ; fp->mode.lreq.tcode = FWTCODE_LREQ;
fp->mode.lreq.pri = 0; fp->mode.lreq.pri = 0;
fp->mode.lreq.src = 0; fp->mode.lreq.src = 0;
fp->mode.lreq.len = 8; fp->mode.lreq.len = 8;
fp->mode.lreq.extcode = FW_LREQ_CMPSWAP; fp->mode.lreq.extcode = EXTCODE_CMP_SWAP;
xfer->dst = FWLOCALBUS | fc->irm; fp->mode.lreq.dst = FWLOCALBUS | fc->irm;
fp->mode.lreq.dst = xfer->dst;
fp->mode.lreq.dest_lo = 0xf0000000 | BUS_MGR_ID; fp->mode.lreq.dest_lo = 0xf0000000 | BUS_MGR_ID;
fp->mode.lreq.payload[0] = htonl(0x3f); xfer->send.payload[0] = htonl(0x3f);
fp->mode.lreq.payload[1] = htonl(fc->nodeid); xfer->send.payload[1] = htonl(fc->nodeid);
xfer->act.hand = fw_try_bmr_callback; xfer->act.hand = fw_try_bmr_callback;
err = fw_asyreq(fc, -1, xfer); err = fw_asyreq(fc, -1, xfer);
if(err){ if(err){
fw_xfer_free( xfer); fw_xfer_free_buf(xfer);
return; return;
} }
return; return;
@ -2124,6 +2140,7 @@ fw_bmr(struct firewire_comm *fc)
struct fw_device fwdev; struct fw_device fwdev;
union fw_self_id *self_id; union fw_self_id *self_id;
int cmstr; int cmstr;
u_int32_t quad;
/* Check to see if the current root node is cycle master capable */ /* Check to see if the current root node is cycle master capable */
self_id = &fc->topology_map->self_id[fc->max_node]; 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.maxrec = 8; /* 512 */
fwdev.status = FWDEVINIT; fwdev.status = FWDEVINIT;
/* Set cmstr bit on the cycle master */ /* Set cmstr bit on the cycle master */
quad = htonl(1 << 8);
fwmem_write_quad(&fwdev, NULL, 0/*spd*/, fwmem_write_quad(&fwdev, NULL, 0/*spd*/,
0xffff, 0xf0000000 | STATE_SET, htonl(1 << 8), 0xffff, 0xf0000000 | STATE_SET, &quad, fw_asy_callback_free);
fw_asy_callback_free);
return 0; return 0;
} }

View File

@ -190,12 +190,6 @@ struct fw_pkt {
BIT16x2(src, dest_hi); BIT16x2(src, dest_hi);
u_int32_t dest_lo; u_int32_t dest_lo;
BIT16x2(len, extcode); 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]; u_int32_t payload[0];
} lreq; } lreq;
struct { struct {
@ -215,6 +209,33 @@ struct fw_pkt {
} mode; } 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 { struct fw_eui64 {
u_int32_t hi, lo; u_int32_t hi, lo;
}; };

View File

@ -224,7 +224,8 @@ struct tlabel{
}; };
struct fw_bind{ 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_HEAD(, fw_xfer) xferlist;
STAILQ_ENTRY(fw_bind) fclist; STAILQ_ENTRY(fw_bind) fclist;
STAILQ_ENTRY(fw_bind) chlist; STAILQ_ENTRY(fw_bind) chlist;
@ -240,9 +241,6 @@ struct fw_xfer{
struct firewire_comm *fc; struct firewire_comm *fc;
struct fw_xferq *q; struct fw_xferq *q;
struct timeval tv; struct timeval tv;
/* XXX should be removed */
u_int32_t dst; /* XXX for if_fwe */
u_int8_t spd;
int8_t resp; int8_t resp;
#define FWXF_INIT 0 #define FWXF_INIT 0
#define FWXF_INQ 1 #define FWXF_INQ 1
@ -259,16 +257,28 @@ struct fw_xfer{
void (*hand) __P((struct fw_xfer *)); void (*hand) __P((struct fw_xfer *));
} act; } act;
struct { struct {
int len; struct fw_pkt hdr;
caddr_t buf; u_int32_t *payload;
u_int16_t pay_len;
u_int8_t spd;
} send, recv; } send, recv;
struct mbuf *mbuf; struct mbuf *mbuf;
STAILQ_ENTRY(fw_xfer) link; STAILQ_ENTRY(fw_xfer) link;
struct malloc_type *malloc; 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_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_unload __P(( struct fw_xfer*));
void fw_xfer_free_buf __P(( struct fw_xfer*));
void fw_xfer_free __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 __P((struct malloc_type *));
struct fw_xfer *fw_xfer_alloc_buf __P((struct malloc_type *, int, int)); 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_timeout __P((void *));
void fw_xfer_done __P((struct fw_xfer *)); void fw_xfer_done __P((struct fw_xfer *));
void fw_asy_callback __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_nodeid __P((struct firewire_comm *, int));
struct fw_device *fw_noderesolve_eui64 __P((struct firewire_comm *, struct fw_eui64 *)); 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 *)); void fw_drain_txq __P((struct firewire_comm *));
int fwdev_makedev __P((struct firewire_softc *)); int fwdev_makedev __P((struct firewire_softc *));
int fwdev_destroydev __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) #define CALLOUT_INIT(x) callout_init(x)
#endif #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_FW);
MALLOC_DECLARE(M_FWXFER); MALLOC_DECLARE(M_FWXFER);

View File

@ -424,6 +424,7 @@ crom_add_chunk(struct crom_src *src, struct crom_chunk *parent,
return(index); return(index);
} }
#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext))
int int
crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
struct crom_chunk *chunk, char *buf) 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; struct csrtext *tl;
u_int32_t *p; u_int32_t *p;
int len, i; int len, i;
char t[MAX_TEXT];
len = strlen(buf); len = strlen(buf);
#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext))
if (len > MAX_TEXT) { if (len > MAX_TEXT) {
#if __FreeBSD_version < 500000 #if __FreeBSD_version < 500000
printf("text(%d) trancated to %d.\n", len, MAX_TEXT); 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_id = 0;
tl->spec_type = 0; tl->spec_type = 0;
tl->lang_id = 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 ++) for (i = 0; i < howmany(len, sizeof(u_int32_t)); i ++)
tl->text[i] = ntohl(*p++); tl->text[i] = ntohl(*p++);
return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF)); return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF));

View File

@ -39,6 +39,11 @@
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mbuf.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/kernel.h>
#include <sys/malloc.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_read_t fw_read; /* for Isochronous packet */
static d_write_t fw_write; static d_write_t fw_write;
static d_mmap_t fw_mmap; static d_mmap_t fw_mmap;
static d_strategy_t fw_strategy;
struct cdevsw firewire_cdevsw = struct cdevsw firewire_cdevsw =
{ {
@ -78,12 +84,13 @@ struct cdevsw firewire_cdevsw =
.d_ioctl = fw_ioctl, .d_ioctl = fw_ioctl,
.d_poll = fw_poll, .d_poll = fw_poll,
.d_mmap = fw_mmap, .d_mmap = fw_mmap,
.d_strategy = fw_strategy,
.d_name = "fw", .d_name = "fw",
.d_maj = CDEV_MAJOR, .d_maj = CDEV_MAJOR,
.d_flags = D_MEM .d_flags = D_MEM
#else #else
fw_open, fw_close, fw_read, fw_write, fw_ioctl, 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 nodump, nopsize, D_MEM, -1
#endif #endif
}; };
@ -270,7 +277,7 @@ fw_read (dev_t dev, struct uio *uio, int ioflag)
struct fw_pkt *fp; struct fw_pkt *fp;
if (DEV_FWMEM(dev)) if (DEV_FWMEM(dev))
return fwmem_read(dev, uio, ioflag); return physio(dev, uio, ioflag);
sc = devclass_get_softc(firewire_devclass, unit); sc = devclass_get_softc(firewire_devclass, unit);
@ -303,16 +310,19 @@ fw_read (dev_t dev, struct uio *uio, int ioflag)
err = EIO; err = EIO;
return err; return err;
} else if(xfer != NULL) { } else if(xfer != NULL) {
#if 0 /* XXX broken */
/* per packet mode or FWACT_CH bind?*/ /* per packet mode or FWACT_CH bind?*/
s = splfw(); s = splfw();
ir->queued --; ir->queued --;
STAILQ_REMOVE_HEAD(&ir->q, link); STAILQ_REMOVE_HEAD(&ir->q, link);
splx(s); splx(s);
fp = (struct fw_pkt *)xfer->recv.buf; fp = &xfer->recv.hdr;
if(sc->fc->irx_post != NULL) if (sc->fc->irx_post != NULL)
sc->fc->irx_post(sc->fc, fp->mode.ld); 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 */ /* XXX we should recycle this xfer */
#endif
fw_xfer_free( xfer); fw_xfer_free( xfer);
} else if(ir->stproc != NULL) { } else if(ir->stproc != NULL) {
/* iso bulkxfer */ /* iso bulkxfer */
@ -354,7 +364,7 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
struct fw_xferq *it; struct fw_xferq *it;
if (DEV_FWMEM(dev)) if (DEV_FWMEM(dev))
return fwmem_write(dev, uio, ioflag); return physio(dev, uio, ioflag);
sc = devclass_get_softc(firewire_devclass, unit); sc = devclass_get_softc(firewire_devclass, unit);
fc = sc->fc; fc = sc->fc;
@ -520,8 +530,11 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
} }
break; break;
case FW_ASYREQ: case FW_ASYREQ:
{
struct tcode_info *tinfo;
xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len, xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len,
PAGE_SIZE /* XXX */); PAGE_SIZE/*XXX*/);
if(xfer == NULL){ if(xfer == NULL){
err = ENOMEM; err = ENOMEM;
return err; 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; fp = &asyreq->pkt;
switch (asyreq->req.type) { switch (asyreq->req.type) {
case FWASREQNODE: case FWASREQNODE:
xfer->dst = fp->mode.hdr.dst;
break; break;
case FWASREQEUI: case FWASREQEUI:
fwdev = fw_noderesolve_eui64(sc->fc, 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; err = EINVAL;
goto error; goto error;
} }
xfer->dst = FWLOCALBUS | fwdev->dst; fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst;
fp->mode.hdr.dst = xfer->dst;
break; break;
case FWASRESTL: case FWASRESTL:
/* XXX what's this? */ /* 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 */ /* nothing to do */
break; break;
} }
xfer->spd = asyreq->req.sped; xfer->send.spd = asyreq->req.sped;
bcopy(fp, xfer->send.buf, xfer->send.len); 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; xfer->act.hand = fw_asy_callback;
err = fw_asyreq(sc->fc, -1, xfer); err = fw_asyreq(sc->fc, -1, xfer);
if(err){ if(err){
fw_xfer_free( xfer); fw_xfer_free_buf(xfer);
return err; return err;
} }
err = tsleep(xfer, FWPRI, "asyreq", hz); err = tsleep(xfer, FWPRI, "asyreq", hz);
if(err == 0){ if (err == 0) {
if(asyreq->req.len >= xfer->recv.len){ if (xfer->resp != 0) {
asyreq->req.len = xfer->recv.len; 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{ }else{
err = EINVAL; 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: error:
fw_xfer_free( xfer); fw_xfer_free_buf(xfer);
break; break;
}
case FW_IBUSRST: case FW_IBUSRST:
sc->fc->ibr(sc->fc); sc->fc->ibr(sc->fc);
break; break;
@ -598,13 +624,14 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
err = ENOMEM; err = ENOMEM;
break; break;
} }
fwb->start_hi = bindreq->start.hi; fwb->start = ((u_int64_t)bindreq->start.hi << 32) |
fwb->start_lo = bindreq->start.lo; bindreq->start.lo;
fwb->addrlen = bindreq->len; fwb->end = fwb->start + bindreq->len;
/* XXX */ /* XXX */
fwb->sub = ir->dmach; fwb->sub = ir->dmach;
fwb->act_type = FWACT_CH; fwb->act_type = FWACT_CH;
/* XXX alloc buf */
xfer = fw_xfer_alloc(M_FWXFER); xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){ if(xfer == NULL){
err = ENOMEM; err = ENOMEM;
@ -736,6 +763,23 @@ fw_mmap (dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto)
return EINVAL; 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 int
fwdev_makedev(struct firewire_softc *sc) fwdev_makedev(struct firewire_softc *sc)
{ {

View File

@ -44,6 +44,11 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/conf.h> #include <sys/conf.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#if __FreeBSD_version < 500000
#include <sys/buf.h>
#else
#include <sys/bio.h>
#endif
#include <sys/bus.h> #include <sys/bus.h>
#include <machine/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, SYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0,
"Fwmem driver debug flag"); "Fwmem driver debug flag");
#define MAXLEN (512 << fwmem_speed)
static struct fw_xfer * static struct fw_xfer *
fwmem_xfer_req( fwmem_xfer_req(
struct fw_device *fwdev, struct fw_device *fwdev,
@ -81,19 +88,21 @@ fwmem_xfer_req(
{ {
struct fw_xfer *xfer; struct fw_xfer *xfer;
xfer = fw_xfer_alloc_buf(M_FWXFER, slen, rlen); xfer = fw_xfer_alloc(M_FWXFER);
if (xfer == NULL) if (xfer == NULL)
return NULL; return NULL;
xfer->fc = fwdev->fc; xfer->fc = fwdev->fc;
xfer->dst = FWLOCALBUS | fwdev->dst; xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst;
if (spd < 0) if (spd < 0)
xfer->spd = fwdev->speed; xfer->send.spd = fwdev->speed;
else else
xfer->spd = min(spd, fwdev->speed); xfer->send.spd = min(spd, fwdev->speed);
xfer->act.hand = hand; xfer->act.hand = hand;
xfer->retry_req = fw_asybusy; xfer->retry_req = fw_asybusy;
xfer->sc = sc; xfer->sc = sc;
xfer->send.pay_len = slen;
xfer->recv.pay_len = rlen;
return xfer; return xfer;
} }
@ -105,21 +114,25 @@ fwmem_read_quad(
u_int8_t spd, u_int8_t spd,
u_int16_t dst_hi, u_int16_t dst_hi,
u_int32_t dst_lo, u_int32_t dst_lo,
void *data,
void (*hand)(struct fw_xfer *)) void (*hand)(struct fw_xfer *))
{ {
struct fw_xfer *xfer; struct fw_xfer *xfer;
struct fw_pkt *fp; struct fw_pkt *fp;
xfer = fwmem_xfer_req(fwdev, sc, spd, 12, 16, hand); xfer = fwmem_xfer_req(fwdev, (void *)sc, spd, 0, 4, hand);
if (xfer == NULL) if (xfer == NULL) {
return NULL; return NULL;
}
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.rreqq.tcode = FWTCODE_RREQQ; fp->mode.rreqq.tcode = FWTCODE_RREQQ;
fp->mode.rreqq.dst = xfer->dst;
fp->mode.rreqq.dest_hi = dst_hi; fp->mode.rreqq.dest_hi = dst_hi;
fp->mode.rreqq.dest_lo = dst_lo; fp->mode.rreqq.dest_lo = dst_lo;
xfer->send.payload = NULL;
xfer->recv.payload = (u_int32_t *)data;
if (fwmem_debug) if (fwmem_debug)
printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst, printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst,
dst_hi, dst_lo); dst_hi, dst_lo);
@ -138,27 +151,27 @@ fwmem_write_quad(
u_int8_t spd, u_int8_t spd,
u_int16_t dst_hi, u_int16_t dst_hi,
u_int32_t dst_lo, u_int32_t dst_lo,
u_int32_t data, void *data,
void (*hand)(struct fw_xfer *)) void (*hand)(struct fw_xfer *))
{ {
struct fw_xfer *xfer; struct fw_xfer *xfer;
struct fw_pkt *fp; 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) if (xfer == NULL)
return NULL; return NULL;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.wreqq.tcode = FWTCODE_WREQQ; fp->mode.wreqq.tcode = FWTCODE_WREQQ;
fp->mode.wreqq.dst = xfer->dst;
fp->mode.wreqq.dest_hi = dst_hi; fp->mode.wreqq.dest_hi = dst_hi;
fp->mode.wreqq.dest_lo = dst_lo; 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) if (fwmem_debug)
printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst, 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) if (fw_asyreq(xfer->fc, -1, xfer) == 0)
return xfer; return xfer;
@ -175,21 +188,25 @@ fwmem_read_block(
u_int16_t dst_hi, u_int16_t dst_hi,
u_int32_t dst_lo, u_int32_t dst_lo,
int len, int len,
void *data,
void (*hand)(struct fw_xfer *)) void (*hand)(struct fw_xfer *))
{ {
struct fw_xfer *xfer; struct fw_xfer *xfer;
struct fw_pkt *fp; 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) if (xfer == NULL)
return NULL; return NULL;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.rreqb.tcode = FWTCODE_RREQB; fp->mode.rreqb.tcode = FWTCODE_RREQB;
fp->mode.rreqb.dst = xfer->dst;
fp->mode.rreqb.dest_hi = dst_hi; fp->mode.rreqb.dest_hi = dst_hi;
fp->mode.rreqb.dest_lo = dst_lo; fp->mode.rreqb.dest_lo = dst_lo;
fp->mode.rreqb.len = len; fp->mode.rreqb.len = len;
fp->mode.rreqb.extcode = 0;
xfer->send.payload = NULL;
xfer->recv.payload = data;
if (fwmem_debug) if (fwmem_debug)
printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst, printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst,
@ -209,23 +226,25 @@ fwmem_write_block(
u_int16_t dst_hi, u_int16_t dst_hi,
u_int32_t dst_lo, u_int32_t dst_lo,
int len, int len,
char *data, void *data,
void (*hand)(struct fw_xfer *)) void (*hand)(struct fw_xfer *))
{ {
struct fw_xfer *xfer; struct fw_xfer *xfer;
struct fw_pkt *fp; 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) if (xfer == NULL)
return NULL; return NULL;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.wreqb.tcode = FWTCODE_WREQB; fp->mode.wreqb.tcode = FWTCODE_WREQB;
fp->mode.wreqb.dst = xfer->dst;
fp->mode.wreqb.dest_hi = dst_hi; fp->mode.wreqb.dest_hi = dst_hi;
fp->mode.wreqb.dest_lo = dst_lo; fp->mode.wreqb.dest_lo = dst_lo;
fp->mode.wreqb.len = len; 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) if (fwmem_debug)
printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst, 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; return ENOMEM;
bcopy(&fwmem_eui64, eui, sizeof(struct fw_eui64)); bcopy(&fwmem_eui64, eui, sizeof(struct fw_eui64));
dev->si_drv1 = (void *)eui; dev->si_drv1 = (void *)eui;
dev->si_iosize_max = DFLTPHYS;
return (0); return (0);
} }
@ -265,145 +285,90 @@ fwmem_close (dev_t dev, int flags, int fmt, fw_proc *td)
return (0); return (0);
} }
#define MAXLEN 2048
#define USE_QUAD 0 static void
int fwmem_biodone(struct fw_xfer *xfer)
fwmem_read (dev_t dev, struct uio *uio, int ioflag)
{ {
struct firewire_softc *sc; struct bio *bp;
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;
sc = devclass_get_softc(firewire_devclass, unit); bp = (struct bio *)xfer->sc;
fwdev = fw_noderesolve_eui64(sc->fc, (struct fw_eui64 *)dev->si_drv1); bp->bio_error = xfer->resp;
if (fwdev == NULL) {
if (fwmem_debug) if (bp->bio_error != 0) {
printf("fwmem: no such device ID:%08x%08x\n", printf("%s: err=%d\n", __FUNCTION__, bp->bio_error);
fwmem_eui64.hi, fwmem_eui64.lo); bp->bio_flags |= BIO_ERROR;
return EINVAL; bp->bio_resid = bp->bio_bcount;
} }
while(uio->uio_resid > 0 && !err) { fw_xfer_free(xfer);
offset = uio->uio_offset; biodone(bp);
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;
} }
int
fwmem_write (dev_t dev, struct uio *uio, int ioflag) void
fwmem_strategy(struct bio *bp)
{ {
struct firewire_softc *sc; struct firewire_softc *sc;
struct fw_device *fwdev; struct fw_device *fwdev;
struct fw_xfer *xfer; struct fw_xfer *xfer;
int err = 0; dev_t dev;
int unit = DEV2UNIT(dev); int unit, err=0, s, iolen;
u_int16_t dst_hi;
u_int32_t dst_lo, quad;
char *data;
off_t offset;
int len, s;
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); sc = devclass_get_softc(firewire_devclass, unit);
s = splfw();
fwdev = fw_noderesolve_eui64(sc->fc, (struct fw_eui64 *)dev->si_drv1); fwdev = fw_noderesolve_eui64(sc->fc, (struct fw_eui64 *)dev->si_drv1);
if (fwdev == NULL) { if (fwdev == NULL) {
if (fwmem_debug) if (fwmem_debug)
printf("fwmem: no such device ID:%08x%08x\n", printf("fwmem: no such device ID:%08x%08x\n",
fwmem_eui64.hi, fwmem_eui64.lo); fwmem_eui64.hi, fwmem_eui64.lo);
return EINVAL; err = EINVAL;
goto error;
} }
data = malloc(MAXLEN, M_FW, M_WAITOK); iolen = MIN(bp->bio_bcount, MAXLEN);
if (data == NULL) if ((bp->bio_cmd & BIO_READ) == BIO_READ) {
return ENOMEM; if (iolen == 4 && (bp->bio_offset & 3) == 0)
xfer = fwmem_read_quad(fwdev,
while(uio->uio_resid > 0 && !err) { (void *) bp, fwmem_speed,
offset = uio->uio_offset; bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
dst_hi = (offset >> 32) & 0xffff; bp->bio_data, fwmem_biodone);
dst_lo = offset & 0xffffffff; else
len = uio->uio_resid; xfer = fwmem_read_block(fwdev,
if (len == 4 && (dst_lo & 3) == 0) { (void *) bp, fwmem_speed,
err = uiomove((char *)&quad, sizeof(quad), uio); bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
s = splfw(); iolen, bp->bio_data, fwmem_biodone);
xfer = fwmem_write_quad(fwdev, NULL, fwmem_speed, } else {
dst_hi, dst_lo, quad, fw_asy_callback); if (iolen == 4 && (bp->bio_offset & 3) == 0)
if (xfer == NULL) { xfer = fwmem_write_quad(fwdev,
err = EINVAL; (void *)bp, fwmem_speed,
splx(s); bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
break; bp->bio_data, fwmem_biodone);
} else
err = tsleep((caddr_t)xfer, FWPRI, "fwmwq", 0); xfer = fwmem_write_block(fwdev,
splx(s); (void *)bp, fwmem_speed,
if (xfer->resp != 0) bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
err = xfer->resp; iolen, bp->bio_data, fwmem_biodone);
} else { }
if (len > MAXLEN) if (xfer == NULL) {
len = MAXLEN; err = EIO;
err = uiomove(data, len, uio); goto error;
if (err) }
break; /* XXX */
s = splfw(); bp->bio_resid = bp->bio_bcount - iolen;
xfer = fwmem_write_block(fwdev, NULL, fwmem_speed, error:
dst_hi, dst_lo, len, data, fw_asy_callback); splx(s);
if (xfer == NULL) { if (err != 0) {
err = EINVAL; printf("%s: err=%d\n", __FUNCTION__, err);
splx(s); bp->bio_error = err;
break; bp->bio_flags |= BIO_ERROR;
} bp->bio_resid = bp->bio_bcount;
err = tsleep((caddr_t)xfer, FWPRI, "fwmwb", 0); biodone(bp);
splx(s);
if (xfer->resp != 0)
err = xfer->resp;
}
fw_xfer_free(xfer);
} }
free(data, M_FW);
return err;
} }
int int

View File

@ -35,13 +35,13 @@
*/ */
struct fw_xfer *fwmem_read_quad(struct fw_device *, caddr_t, u_int8_t, 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, 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, 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, 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_open_t fwmem_open;
d_close_t fwmem_close; d_close_t fwmem_close;
@ -50,3 +50,4 @@ d_read_t fwmem_read;
d_write_t fwmem_write; d_write_t fwmem_write;
d_poll_t fwmem_poll; d_poll_t fwmem_poll;
d_mmap_t fwmem_mmap; d_mmap_t fwmem_mmap;
d_strategy_t fwmem_strategy;

View File

@ -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_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 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 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 void dump_dma __P((struct fwohci_softc *, u_int32_t));
static u_int32_t fwohci_cyctimer __P((struct firewire_comm *)); static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
static void fwohci_rbuf_update __P((struct fwohci_softc *, int)); 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) fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{ {
struct fwohcidb_tr *db_tr; struct fwohcidb_tr *db_tr;
volatile struct fwohcidb *db; struct fwohcidb *db;
bus_dma_segment_t *s; bus_dma_segment_t *s;
int i; int i;
@ -831,15 +831,15 @@ static void
fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
{ {
int i, s; int i, s;
int tcode, hdr_len, pl_off, pl_len; int tcode, hdr_len, pl_off;
int fsegment = -1; int fsegment = -1;
u_int32_t off; u_int32_t off;
struct fw_xfer *xfer; struct fw_xfer *xfer;
struct fw_pkt *fp; struct fw_pkt *fp;
volatile struct fwohci_txpkthdr *ohcifp; struct fwohci_txpkthdr *ohcifp;
struct fwohcidb_tr *db_tr; struct fwohcidb_tr *db_tr;
volatile struct fwohcidb *db; struct fwohcidb *db;
volatile u_int32_t *ld; u_int32_t *ld;
struct tcode_info *info; struct tcode_info *info;
static int maxdesc=0; static int maxdesc=0;
@ -868,10 +868,10 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
db_tr->xfer = xfer; db_tr->xfer = xfer;
xfer->state = FWXF_START; xfer->state = FWXF_START;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
tcode = fp->mode.common.tcode; 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]; info = &tinfo[tcode];
hdr_len = pl_off = info->hdr_len; 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) for( i = 0 ; i < pl_off ; i+= 4)
ld[i/4] = fp->mode.ld[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 ){ if (tcode == FWTCODE_STREAM ){
hdr_len = 8; hdr_len = 8;
ohcifp->mode.stream.len = fp->mode.stream.len; ohcifp->mode.stream.len = fp->mode.stream.len;
@ -915,16 +915,12 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
again: again:
db_tr->dbcnt = 2; db_tr->dbcnt = 2;
db = &db_tr->db[db_tr->dbcnt]; db = &db_tr->db[db_tr->dbcnt];
pl_len = xfer->send.len - pl_off; if (xfer->send.pay_len > 0) {
if (pl_len > 0) {
int err; int err;
/* handle payload */ /* handle payload */
if (xfer->mbuf == NULL) { 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, 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, fwohci_execute_db, db_tr,
/*flags*/0); /*flags*/0);
} else { } else {
@ -1030,7 +1026,7 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
{ {
int s, ch, err = 0; int s, ch, err = 0;
struct fwohcidb_tr *tr; struct fwohcidb_tr *tr;
volatile struct fwohcidb *db; struct fwohcidb *db;
struct fw_xfer *xfer; struct fw_xfer *xfer;
u_int32_t off; u_int32_t off;
u_int stat, status; u_int stat, status;
@ -1123,14 +1119,14 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
if (xfer->retry_req != NULL) if (xfer->retry_req != NULL)
xfer->retry_req(xfer); xfer->retry_req(xfer);
else { else {
xfer->recv.len = 0; xfer->recv.pay_len = 0;
fw_xfer_done(xfer); fw_xfer_done(xfer);
} }
} else if (stat != FWOHCIEV_ACKPEND) { } else if (stat != FWOHCIEV_ACKPEND) {
if (stat != FWOHCIEV_ACKCOMPL) if (stat != FWOHCIEV_ACKCOMPL)
xfer->state = FWXF_SENTERR; xfer->state = FWXF_SENTERR;
xfer->resp = err; xfer->resp = err;
xfer->recv.len = 0; xfer->recv.pay_len = 0;
fw_xfer_done(xfer); 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; int idb, z, i, dmach = 0, ldesc;
u_int32_t off = NULL; u_int32_t off = NULL;
struct fwohcidb_tr *db_tr; struct fwohcidb_tr *db_tr;
volatile struct fwohcidb *db; struct fwohcidb *db;
if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
err = EINVAL; err = EINVAL;
@ -1378,7 +1374,7 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
int idb, z, i, dmach = 0, ldesc; int idb, z, i, dmach = 0, ldesc;
u_int32_t off = NULL; u_int32_t off = NULL;
struct fwohcidb_tr *db_tr; struct fwohcidb_tr *db_tr;
volatile struct fwohcidb *db; struct fwohcidb *db;
z = dbch->ndesc; z = dbch->ndesc;
if(&sc->arrq == dbch){ if(&sc->arrq == dbch){
@ -1509,7 +1505,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
s = splfw(); s = splfw();
prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link); prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) { while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
volatile struct fwohcidb *db; struct fwohcidb *db;
fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket, fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
BUS_DMASYNC_PREWRITE); BUS_DMASYNC_PREWRITE);
@ -1636,7 +1632,7 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach)
s = splfw(); s = splfw();
prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link); prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) { while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
volatile struct fwohcidb *db; struct fwohcidb *db;
#if 1 /* XXX for if_fwe */ #if 1 /* XXX for if_fwe */
if (chunk->mbuf != NULL) { if (chunk->mbuf != NULL) {
@ -2104,7 +2100,7 @@ static void
fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
{ {
struct firewire_comm *fc = &sc->fc; struct firewire_comm *fc = &sc->fc;
volatile struct fwohcidb *db; struct fwohcidb *db;
struct fw_bulkxfer *chunk; struct fw_bulkxfer *chunk;
struct fw_xferq *it; struct fw_xferq *it;
u_int32_t stat, count; u_int32_t stat, count;
@ -2150,7 +2146,7 @@ static void
fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
{ {
struct firewire_comm *fc = &sc->fc; struct firewire_comm *fc = &sc->fc;
volatile struct fwohcidb_tr *db_tr; struct fwohcidb_tr *db_tr;
struct fw_bulkxfer *chunk; struct fw_bulkxfer *chunk;
struct fw_xferq *ir; struct fw_xferq *ir;
u_int32_t stat; u_int32_t stat;
@ -2255,7 +2251,7 @@ dump_db(struct fwohci_softc *sc, u_int32_t ch)
{ {
struct fwohci_dbch *dbch; struct fwohci_dbch *dbch;
struct fwohcidb_tr *cp = NULL, *pp, *np = NULL; 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; int idb, jdb;
u_int32_t cmd, off; u_int32_t cmd, off;
if(ch == 0){ if(ch == 0){
@ -2329,7 +2325,7 @@ dump_db(struct fwohci_softc *sc, u_int32_t ch)
} }
void 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) u_int32_t ch, u_int32_t max)
{ {
fwohcireg_t stat; 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 fwohcidb_tr *db_tr, *fdb_tr;
struct fwohci_dbch *dbch; struct fwohci_dbch *dbch;
volatile struct fwohcidb *db; struct fwohcidb *db;
struct fw_pkt *fp; struct fw_pkt *fp;
volatile struct fwohci_txpkthdr *ohcifp; struct fwohci_txpkthdr *ohcifp;
unsigned short chtag; unsigned short chtag;
int idb; 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 ++) { for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) {
db = db_tr->db; db = db_tr->db;
fp = (struct fw_pkt *)db_tr->buf; 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.ld[0] = fp->mode.ld[0];
ohcifp->mode.common.spd = 0 & 0x7; ohcifp->mode.common.spd = 0 & 0x7;
ohcifp->mode.stream.len = fp->mode.stream.len; 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, fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
int poffset) int poffset)
{ {
volatile struct fwohcidb *db = db_tr->db; struct fwohcidb *db = db_tr->db;
struct fw_xferq *it; struct fw_xferq *it;
int err = 0; 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, FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
bzero((void *)(uintptr_t)(volatile void *) bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
&db[1].db.immed[0], sizeof(db[1].db.immed));
FWOHCI_DMA_WRITE(db[2].db.desc.addr, FWOHCI_DMA_WRITE(db[2].db.desc.addr,
fwdma_bus_addr(it->buf, poffset) + sizeof(u_int32_t)); 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, fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
int poffset, struct fwdma_alloc *dummy_dma) int poffset, struct fwdma_alloc *dummy_dma)
{ {
volatile struct fwohcidb *db = db_tr->db; struct fwohcidb *db = db_tr->db;
struct fw_xferq *ir; struct fw_xferq *ir;
int i, ldesc; int i, ldesc;
bus_addr_t dbuf[2]; bus_addr_t dbuf[2];
@ -2595,7 +2590,7 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len)
{ {
struct fw_pkt *fp0; struct fw_pkt *fp0;
u_int32_t ld0; u_int32_t ld0;
int slen; int slen, hlen;
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
int i; int i;
#endif #endif
@ -2605,6 +2600,7 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len)
printf("ld0: x%08x\n", ld0); printf("ld0: x%08x\n", ld0);
#endif #endif
fp0 = (struct fw_pkt *)&ld0; fp0 = (struct fw_pkt *)&ld0;
/* determine length to swap */
switch (fp0->mode.common.tcode) { switch (fp0->mode.common.tcode) {
case FWTCODE_RREQQ: case FWTCODE_RREQQ:
case FWTCODE_WRES: 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); printf("Unknown tcode %d\n", fp0->mode.common.tcode);
return(0); return(0);
} }
if (slen > len) { hlen = tinfo[fp0->mode.common.tcode].hdr_len;
if (hlen > len) {
if (firewire_debug) if (firewire_debug)
printf("splitted header\n"); printf("splitted header\n");
return(-slen); return(-hlen);
} }
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
for(i = 0; i < slen/4; i ++) for(i = 0; i < slen/4; i ++)
fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
#endif #endif
return(slen); return(hlen);
} }
#define PLEN(x) roundup2(x, sizeof(u_int32_t))
static int static int
fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp) fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
{ {
struct tcode_info *info;
int r; int r;
switch(fp->mode.common.tcode){ info = &tinfo[fp->mode.common.tcode];
case FWTCODE_RREQQ: r = info->hdr_len + sizeof(u_int32_t);
r = sizeof(fp->mode.rreqq) + sizeof(u_int32_t); if ((info->flag & FWTI_BLOCK_ASY) != 0)
break; r += roundup2(fp->mode.wreqb.len, sizeof(u_int32_t));
case FWTCODE_WRES:
r = sizeof(fp->mode.wres) + sizeof(u_int32_t); if (r == sizeof(u_int32_t))
break; /* XXX */
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:
device_printf(sc->fc.dev, "Unknown tcode %d\n", device_printf(sc->fc.dev, "Unknown tcode %d\n",
fp->mode.common.tcode); fp->mode.common.tcode);
r = 0;
}
if (r > dbch->xferq.psize) { if (r > dbch->xferq.psize) {
device_printf(sc->fc.dev, "Invalid packet length %d\n", r); device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
/* panic ? */ /* panic ? */
} }
return r; return r;
} }
static void static void
fwohci_arcv_free_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr) 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_CLEAR(db->db.desc.depend, 0xf);
FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); 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) { if (plen < 0) {
/* minimum header size + trailer /* minimum header size + trailer
= sizeof(fw_pkt) so this shouldn't happens */ = 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; goto out;
} }
if (plen > 0) { 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; stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
#endif #endif
#if 0 #if 0
printf("plen: %d, stat %x\n", plen ,stat); printf("plen: %d, stat %x\n",
plen ,stat);
#endif #endif
spd = (stat >> 5) & 0x3; spd = (stat >> 5) & 0x3;
stat &= 0x1f; stat &= 0x1f;
@ -2853,11 +2823,19 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
#endif #endif
/* fall through */ /* fall through */
case FWOHCIEV_ACKCOMPL: case FWOHCIEV_ACKCOMPL:
{
struct fw_rcv_buf rb;
if ((vec[nvec-1].iov_len -= if ((vec[nvec-1].iov_len -=
sizeof(struct fwohci_trailer)) == 0) sizeof(struct fwohci_trailer)) == 0)
nvec--; nvec--;
fw_rcv(&sc->fc, vec, nvec, 0, spd); rb.fc = &sc->fc;
break; rb.vec = vec;
rb.nvec = nvec;
rb.spd = spd;
fw_rcv(&rb);
break;
}
case FWOHCIEV_BUSRST: case FWOHCIEV_BUSRST:
if (sc->fc.status != FWBUSRESET) if (sc->fc.status != FWBUSRESET)
printf("got BUSRST packet!?\n"); printf("got BUSRST packet!?\n");

View File

@ -76,7 +76,7 @@
#define OHCI_MAX_DMA_CH (0x4 + OHCI_DMA_ITCH + OHCI_DMA_IRCH) #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 */ /* for PCI */
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
@ -94,12 +94,12 @@ typedef volatile u_int32_t fwohcireg_t;
struct fwohcidb { struct fwohcidb {
union { union {
struct { struct {
volatile u_int32_t cmd; u_int32_t cmd;
volatile u_int32_t addr; u_int32_t addr;
volatile u_int32_t depend; u_int32_t depend;
volatile u_int32_t res; u_int32_t res;
} desc; } desc;
volatile u_int32_t immed[4]; u_int32_t immed[4];
} db; } db;
#define OHCI_STATUS_SHIFT 16 #define OHCI_STATUS_SHIFT 16
#define OHCI_COUNT_MASK 0xffff #define OHCI_COUNT_MASK 0xffff
@ -317,7 +317,7 @@ struct ohci_registers {
struct fwohcidb_tr{ struct fwohcidb_tr{
STAILQ_ENTRY(fwohcidb_tr) link; STAILQ_ENTRY(fwohcidb_tr) link;
struct fw_xfer *xfer; struct fw_xfer *xfer;
volatile struct fwohcidb *db; struct fwohcidb *db;
bus_dmamap_t dma_map; bus_dmamap_t dma_map;
caddr_t buf; caddr_t buf;
bus_addr_t bus_addr; bus_addr_t bus_addr;

View File

@ -350,7 +350,7 @@ fwe_init(void *arg)
xfer = fw_xfer_alloc(M_FWE); xfer = fw_xfer_alloc(M_FWE);
if (xfer == NULL) if (xfer == NULL)
break; break;
xfer->spd = tx_speed; xfer->send.spd = tx_speed;
xfer->fc = fwe->fd.fc; xfer->fc = fwe->fd.fc;
xfer->retry_req = fw_asybusy; xfer->retry_req = fw_asybusy;
xfer->sc = (caddr_t)fwe; xfer->sc = (caddr_t)fwe;
@ -447,7 +447,6 @@ fwe_output_callback(struct fw_xfer *xfer)
ifp->if_oerrors ++; ifp->if_oerrors ++;
m_freem(xfer->mbuf); m_freem(xfer->mbuf);
xfer->send.buf = NULL;
fw_xfer_unload(xfer); fw_xfer_unload(xfer);
s = splimp(); s = splimp();
@ -529,12 +528,11 @@ fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp)
/* keep ip packet alignment for alpha */ /* keep ip packet alignment for alpha */
M_PREPEND(m, ETHER_ALIGN, M_DONTWAIT); M_PREPEND(m, ETHER_ALIGN, M_DONTWAIT);
fp = (struct fw_pkt *)&xfer->dst; /* XXX */ fp = &xfer->send.hdr;
xfer->dst = *((int32_t *)&fwe->pkt_hdr); *(u_int32_t *)&xfer->send.hdr = *(int32_t *)&fwe->pkt_hdr;
fp->mode.stream.len = m->m_pkthdr.len; fp->mode.stream.len = m->m_pkthdr.len;
xfer->send.buf = (caddr_t) fp;
xfer->mbuf = m; 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) { if (fw_asyreq(fwe->fd.fc, -1, xfer) != 0) {
/* error */ /* error */

View File

@ -66,6 +66,7 @@
#include <dev/firewire/firewirereg.h> #include <dev/firewire/firewirereg.h>
#include <dev/firewire/fwdma.h> #include <dev/firewire/fwdma.h>
#include <dev/firewire/iec13213.h> #include <dev/firewire/iec13213.h>
#include <dev/firewire/sbp.h>
#define ccb_sdev_ptr spriv_ptr0 #define ccb_sdev_ptr spriv_ptr0
#define ccb_sbp_ptr spriv_ptr1 #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_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb))
#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) #define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS)
#define SBP_INITIATOR 7
#define LOGIN_DELAY 2
/* /*
* STATUS FIFO addressing * STATUS FIFO addressing
* bit * bit
@ -88,67 +85,25 @@
* 0- 1( 2): 0 (alingment) * 0- 1( 2): 0 (alingment)
* 2- 7( 6): target * 2- 7( 6): target
* 8-15( 8): lun * 8-15( 8): lun
* 16-23( 8): unit * 16-31( 8): reserved
* 24-31( 8): reserved
* 32-47(16): SBP_BIND_HI * 32-47(16): SBP_BIND_HI
* 48-64(16): bus_id, node_id * 48-64(16): bus_id, node_id
*/ */
#define SBP_BIND_HI 0x1 #define SBP_BIND_HI 0x1
#define SBP_DEV2ADDR(u, t, l) \ #define SBP_DEV2ADDR(t, l) \
((((u) & 0xff) << 16) | (((l) & 0xff) << 8) | (((t) & 0x3f) << 2)) (((u_int64_t)SBP_BIND_HI << 32) \
| (((l) & 0xff) << 8) \
| (((t) & 0x3f) << 2))
#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f) #define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f)
#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff) #define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff)
#define SBP_INITIATOR 7
#define ORB_NOTIFY (1 << 31) #define LOGIN_DELAY 1
#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
static char *orb_fun_name[] = { static char *orb_fun_name[] = {
/* 0 */ "LOGIN", ORB_FUN_NAMES
/* 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"
}; };
#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 debug = 0;
static int auto_login = 1; static int auto_login = 1;
static int max_speed = 2; 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, SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0,
"SBP transfer max speed"); "SBP transfer max speed");
#define SBP_DEBUG(x) if (debug > x) {
#define END_DEBUG }
#define NEED_RESPONSE 0 #define NEED_RESPONSE 0
struct ind_ptr {
u_int32_t hi,lo;
};
#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE) #define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE)
#ifdef __sparc64__ /* iommu */ #ifdef __sparc64__ /* iommu */
#define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX) #define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX)
@ -181,9 +130,9 @@ struct sbp_ocb {
STAILQ_ENTRY(sbp_ocb) ocb; STAILQ_ENTRY(sbp_ocb) ocb;
union ccb *ccb; union ccb *ccb;
bus_addr_t bus_addr; 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)) #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; struct sbp_dev *sdev;
int flags; /* XXX should be removed */ int flags; /* XXX should be removed */
bus_dmamap_t dmamap; bus_dmamap_t dmamap;
@ -193,63 +142,6 @@ struct sbp_ocb {
#define OCB_ACT_CMD 1 #define OCB_ACT_CMD 1
#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo)) #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{ struct sbp_dev{
#define SBP_DEV_RESET 0 /* accept login */ #define SBP_DEV_RESET 0 /* accept login */
#define SBP_DEV_LOGIN 1 /* to login */ #define SBP_DEV_LOGIN 1 /* to login */
@ -289,7 +181,7 @@ struct sbp_target {
struct sbp_ocb *mgm_ocb_cur; struct sbp_ocb *mgm_ocb_cur;
STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue;
struct callout mgm_ocb_timeout; struct callout mgm_ocb_timeout;
#define SCAN_DELAY 2 #define SCAN_DELAY 1
struct callout scan_callout; struct callout scan_callout;
STAILQ_HEAD(, fw_xfer) xferlist; STAILQ_HEAD(, fw_xfer) xferlist;
int n_xfer; int n_xfer;
@ -406,7 +298,7 @@ END_DEBUG
return(ENXIO); return(ENXIO);
} }
device_set_desc(dev, "SBP2/SCSI over firewire"); device_set_desc(dev, "SBP-2/SCSI over FireWire");
if (bootverbose) if (bootverbose)
debug = bootverbose; debug = bootverbose;
@ -879,7 +771,7 @@ END_DEBUG
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
xfer->act.hand = sbp_reset_start_callback; 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_hi = 0xffff;
fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
fp->mode.wreqq.data = htonl(0xf); fp->mode.wreqq.data = htonl(0xf);
@ -1057,7 +949,7 @@ sbp_agent_reset_callback(struct fw_xfer *xfer)
sdev = (struct sbp_dev *)xfer->sc; sdev = (struct sbp_dev *)xfer->sc;
SBP_DEBUG(1) SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2); sbp_show_sdev_info(sdev, 2);
printf("sbp_cmd_callback\n"); printf("%s\n", __FUNCTION__);
END_DEBUG END_DEBUG
if (xfer->resp != 0) { if (xfer->resp != 0) {
sbp_show_sdev_info(sdev, 2); sbp_show_sdev_info(sdev, 2);
@ -1088,7 +980,7 @@ END_DEBUG
xfer->act.hand = sbp_agent_reset_callback; xfer->act.hand = sbp_agent_reset_callback;
else else
xfer->act.hand = sbp_do_attach; xfer->act.hand = sbp_do_attach;
fp = (struct fw_pkt *)xfer->send.buf; fp = &xfer->send.hdr;
fp->mode.wreqq.data = htonl(0xf); fp->mode.wreqq.data = htonl(0xf);
fw_asyreq(xfer->fc, -1, xfer); fw_asyreq(xfer->fc, -1, xfer);
sbp_abort_all_ocbs(sdev, CAM_BDR_SENT); sbp_abort_all_ocbs(sdev, CAM_BDR_SENT);
@ -1120,7 +1012,7 @@ END_DEBUG
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
xfer->act.hand = sbp_busy_timeout_callback; 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_hi = 0xffff;
fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT;
fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf); fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf);
@ -1142,12 +1034,12 @@ END_DEBUG
return; return;
xfer->act.hand = sbp_cmd_callback; 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.len = 8;
fp->mode.wreqb.extcode = 0; fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] = xfer->send.payload[0] =
htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); 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){ if(fw_asyreq(xfer->fc, -1, xfer) != 0){
sbp_xfer_free(xfer); sbp_xfer_free(xfer);
@ -1194,7 +1086,7 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
splx(s); splx(s);
return(NULL); return(NULL);
} }
xfer = fw_xfer_alloc_buf(M_SBP, 24, 12); xfer = fw_xfer_alloc_buf(M_SBP, 8, 0);
if(xfer == NULL){ if(xfer == NULL){
printf("sbp: fw_xfer_alloc_buf failed\n"); printf("sbp: fw_xfer_alloc_buf failed\n");
splx(s); splx(s);
@ -1211,26 +1103,26 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
microtime(&xfer->tv); microtime(&xfer->tv);
if (tcode == FWTCODE_WREQQ)
xfer->send.len = 16;
else
xfer->send.len = 24;
xfer->recv.len = 12;
if (new) { 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->fc = sdev->target->sbp->fd.fc;
xfer->retry_req = fw_asybusy; 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; 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_hi = sdev->login->cmd_hi;
fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset; fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset;
fp->mode.wreqq.tlrt = 0; fp->mode.wreqq.tlrt = 0;
fp->mode.wreqq.tcode = tcode; fp->mode.wreqq.tcode = tcode;
fp->mode.wreqq.pri = 0; fp->mode.wreqq.pri = 0;
xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst; fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst;
fp->mode.wreqq.dst = xfer->dst;
return xfer; 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->flags = OCB_ACT_MGM;
ocb->sdev = sdev; 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[6] = htonl((nid << 16) | SBP_BIND_HI);
ocb->orb[7] = htonl(SBP_DEV2ADDR( ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id));
device_get_unit(target->sbp->fd.dev),
target->target_id,
sdev->lun_id));
SBP_DEBUG(0) SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2); sbp_show_sdev_info(sdev, 2);
@ -1278,6 +1167,7 @@ SBP_DEBUG(0)
END_DEBUG END_DEBUG
switch (func) { switch (func) {
case ORB_FUN_LGI: case ORB_FUN_LGI:
ocb->orb[0] = ocb->orb[1] = 0; /* password */
ocb->orb[2] = htonl(nid << 16); ocb->orb[2] = htonl(nid << 16);
ocb->orb[3] = htonl(sdev->dma.bus_addr); ocb->orb[3] = htonl(sdev->dma.bus_addr);
ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id); ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id);
@ -1315,13 +1205,17 @@ END_DEBUG
} }
xfer->act.hand = sbp_mgm_callback; 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_hi = sdev->target->mgm_hi;
fp->mode.wreqb.dest_lo = sdev->target->mgm_lo; fp->mode.wreqb.dest_lo = sdev->target->mgm_lo;
fp->mode.wreqb.len = 8; fp->mode.wreqb.len = 8;
fp->mode.wreqb.extcode = 0; fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] = htonl(nid << 16); xfer->send.payload[0] = htonl(nid << 16);
fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr); 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); 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[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])); 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; sbp = (struct sbp_softc *)xfer->sc;
if(xfer->resp != 0){ if (xfer->resp != 0){
printf("sbp_recv: xfer->resp != 0\n"); printf("sbp_recv: xfer->resp != 0\n");
goto done0; goto done0;
} }
if(xfer->recv.buf == NULL){ if (xfer->recv.payload == NULL){
printf("sbp_recv: xfer->recv.buf == NULL\n"); printf("sbp_recv: xfer->recv.payload == NULL\n");
goto done0; goto done0;
} }
sbp = (struct sbp_softc *)xfer->sc; rfp = &xfer->recv.hdr;
rfp = (struct fw_pkt *)xfer->recv.buf;
if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){ if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){
printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode);
goto done0; 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; addr = rfp->mode.wreqb.dest_lo;
SBP_DEBUG(2) SBP_DEBUG(2)
printf("received address 0x%x\n", addr); printf("received address 0x%x\n", addr);
@ -1748,6 +1640,7 @@ printf("len %d\n", sbp_status->len);
sbp_agent_reset(sdev); sbp_agent_reset(sdev);
done0: done0:
xfer->recv.pay_len = SBP_RECV_LEN;
/* The received packet is usually small enough to be stored within /* The received packet is usually small enough to be stored within
* the buffer. In that case, the controller return ack_complete and * the buffer. In that case, the controller return ack_complete and
* no respose is necessary. * no respose is necessary.
@ -1772,7 +1665,6 @@ printf("len %d\n", sbp_status->len);
fw_asyreq(xfer->fc, -1, xfer); fw_asyreq(xfer->fc, -1, xfer);
#else #else
/* recycle */ /* recycle */
xfer->recv.len = SBP_RECV_LEN;
STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
#endif #endif
@ -1856,23 +1748,20 @@ END_DEBUG
goto fail; goto fail;
if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim), 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; 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) */ /* 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; sbp->fwb.act_type = FWACT_XFER;
/* pre-allocate xfer */ /* pre-allocate xfer */
STAILQ_INIT(&sbp->fwb.xferlist); STAILQ_INIT(&sbp->fwb.xferlist);
for (i = 0; i < SBP_NUM_OCB/2; i ++) { for (i = 0; i < SBP_NUM_OCB/2; i ++) {
xfer = fw_xfer_alloc_buf(M_SBP, xfer = fw_xfer_alloc_buf(M_SBP,
#if NEED_RESPONSE
/* send */12,
#else
/* send */0, /* send */0,
#endif
/* recv */SBP_RECV_LEN); /* recv */SBP_RECV_LEN);
xfer->act.hand = sbp_recv; xfer->act.hand = sbp_recv;
#if NEED_RESPONSE #if NEED_RESPONSE
@ -1949,8 +1838,10 @@ END_DEBUG
for (i = 0; i < SBP_NUM_TARGETS; i ++) for (i = 0; i < SBP_NUM_TARGETS; i ++)
sbp_cam_detach_target(&sbp->targets[i]); sbp_cam_detach_target(&sbp->targets[i]);
xpt_async(AC_LOST_DEVICE, sbp->path, NULL);
xpt_free_path(sbp->path); xpt_free_path(sbp->path);
xpt_bus_deregister(cam_sim_path(sbp->sim)); xpt_bus_deregister(cam_sim_path(sbp->sim));
cam_sim_free(sbp->sim, /*free_devq*/ TRUE),
sbp_logout_all(sbp); sbp_logout_all(sbp);
@ -1974,7 +1865,7 @@ END_DEBUG
for (xfer = STAILQ_FIRST(&target->xferlist); for (xfer = STAILQ_FIRST(&target->xferlist);
xfer != NULL; xfer = next) { xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link); next = STAILQ_NEXT(xfer, link);
fw_xfer_free(xfer); fw_xfer_free_buf(xfer);
} }
free(target->luns, M_SBP); free(target->luns, M_SBP);
} }
@ -1982,7 +1873,7 @@ END_DEBUG
for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist); for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist);
xfer != NULL; xfer = next) { xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link); next = STAILQ_NEXT(xfer, link);
fw_xfer_free(xfer); fw_xfer_free_buf(xfer);
} }
STAILQ_INIT(&sbp->fwb.xferlist); STAILQ_INIT(&sbp->fwb.xferlist);
fw_bindremove(fc, &sbp->fwb); fw_bindremove(fc, &sbp->fwb);
@ -2259,9 +2150,7 @@ END_DEBUG
cdb = (void *)csio->cdb_io.cdb_ptr; cdb = (void *)csio->cdb_io.cdb_ptr;
else else
cdb = (void *)&csio->cdb_io.cdb_bytes; cdb = (void *)&csio->cdb_io.cdb_bytes;
bcopy(cdb, bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len);
(void *)(uintptr_t)(volatile 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[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])); 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
View 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"

View File

@ -7,7 +7,7 @@
KMOD = sbp KMOD = sbp
SRCS = bus_if.h device_if.h \ SRCS = bus_if.h device_if.h \
opt_cam.h opt_scsi.h \ opt_cam.h opt_scsi.h \
sbp.c \ sbp.c sbp.h \
firewire.h firewirereg.h \ firewire.h firewirereg.h \
iec13213.h iec13213.h