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

View File

@ -190,12 +190,6 @@ struct fw_pkt {
BIT16x2(src, dest_hi);
u_int32_t dest_lo;
BIT16x2(len, extcode);
#define FW_LREQ_MSKSWAP 1
#define FW_LREQ_CMPSWAP 2
#define FW_LREQ_FTADD 3
#define FW_LREQ_LTADD 4
#define FW_LREQ_BDADD 5
#define FW_LREQ_WRADD 6
u_int32_t payload[0];
} lreq;
struct {
@ -215,6 +209,33 @@ struct fw_pkt {
} mode;
};
/*
* Response code (rtcode)
*/
/* The node has successfully completed the command. */
#define RESP_CMP 0
/* A resource conflict was detected. The request may be retried. */
#define RESP_CONFLICT_ERROR 4
/* Hardware error, data is unavailable. */
#define RESP_DATA_ERROR 5
/* A field in the request packet header was set to an unsupported or incorrect
* value, or an invalid transaction was attempted (e.g., a write to a read-only
* address). */
#define RESP_TYPE_ERROR 6
/* The destination offset field in the request was set to an address not
* accessible in the destination node. */
#define RESP_ADDRESS_ERROR 7
/*
* Extended transaction code (extcode)
*/
#define EXTCODE_MASK_SWAP 1
#define EXTCODE_CMP_SWAP 2
#define EXTCODE_FETCH_ADD 3
#define EXTCODE_LITTLE_ADD 4
#define EXTCODE_BOUNDED_ADD 5
#define EXTCODE_WRAP_ADD 6
struct fw_eui64 {
u_int32_t hi, lo;
};

View File

@ -224,7 +224,8 @@ struct tlabel{
};
struct fw_bind{
u_int32_t start_hi, start_lo, addrlen;
u_int64_t start;
u_int64_t end;
STAILQ_HEAD(, fw_xfer) xferlist;
STAILQ_ENTRY(fw_bind) fclist;
STAILQ_ENTRY(fw_bind) chlist;
@ -240,9 +241,6 @@ struct fw_xfer{
struct firewire_comm *fc;
struct fw_xferq *q;
struct timeval tv;
/* XXX should be removed */
u_int32_t dst; /* XXX for if_fwe */
u_int8_t spd;
int8_t resp;
#define FWXF_INIT 0
#define FWXF_INQ 1
@ -259,16 +257,28 @@ struct fw_xfer{
void (*hand) __P((struct fw_xfer *));
} act;
struct {
int len;
caddr_t buf;
struct fw_pkt hdr;
u_int32_t *payload;
u_int16_t pay_len;
u_int8_t spd;
} send, recv;
struct mbuf *mbuf;
STAILQ_ENTRY(fw_xfer) link;
struct malloc_type *malloc;
};
struct fw_rcv_buf {
struct firewire_comm *fc;
struct fw_xfer *xfer;
struct iovec *vec;
u_int nvec;
u_int8_t spd;
};
void fw_sidrcv __P((struct firewire_comm *, u_int32_t *, u_int));
void fw_rcv __P((struct firewire_comm *, struct iovec *, int, u_int, u_int));
void fw_rcv __P((struct fw_rcv_buf *));
void fw_xfer_unload __P(( struct fw_xfer*));
void fw_xfer_free_buf __P(( struct fw_xfer*));
void fw_xfer_free __P(( struct fw_xfer*));
struct fw_xfer *fw_xfer_alloc __P((struct malloc_type *));
struct fw_xfer *fw_xfer_alloc_buf __P((struct malloc_type *, int, int));
@ -284,9 +294,10 @@ u_int16_t fw_crc16 __P((u_int32_t *, u_int32_t));
void fw_xfer_timeout __P((void *));
void fw_xfer_done __P((struct fw_xfer *));
void fw_asy_callback __P((struct fw_xfer *));
void fw_asy_callback_free __P((struct fw_xfer *));
struct fw_device *fw_noderesolve_nodeid __P((struct firewire_comm *, int));
struct fw_device *fw_noderesolve_eui64 __P((struct firewire_comm *, struct fw_eui64 *));
struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int32_t, u_int32_t));
struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int16_t, u_int32_t));
void fw_drain_txq __P((struct firewire_comm *));
int fwdev_makedev __P((struct firewire_softc *));
int fwdev_destroydev __P((struct firewire_softc *));
@ -303,5 +314,23 @@ extern devclass_t firewire_devclass;
#define CALLOUT_INIT(x) callout_init(x)
#endif
#if __FreeBSD_version < 500000
/* compatibility shim for 4.X */
#define bio buf
#define bio_bcount b_bcount
#define bio_cmd b_flags
#define bio_count b_count
#define bio_data b_data
#define bio_dev b_dev
#define bio_error b_error
#define bio_flags b_flags
#define bio_offset b_offset
#define bio_resid b_resid
#define BIO_ERROR B_ERROR
#define BIO_READ B_READ
#define BIO_WRITE B_WRITE
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
MALLOC_DECLARE(M_FW);
MALLOC_DECLARE(M_FWXFER);

View File

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

View File

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

View File

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

View File

@ -35,13 +35,13 @@
*/
struct fw_xfer *fwmem_read_quad(struct fw_device *, caddr_t, u_int8_t,
u_int16_t, u_int32_t, void (*)(struct fw_xfer *));
u_int16_t, u_int32_t, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_write_quad(struct fw_device *, caddr_t, u_int8_t,
u_int16_t, u_int32_t, u_int32_t, void (*)(struct fw_xfer *));
u_int16_t, u_int32_t, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_read_block(struct fw_device *, caddr_t, u_int8_t,
u_int16_t, u_int32_t, int, void (*)(struct fw_xfer *));
u_int16_t, u_int32_t, int, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_write_block(struct fw_device *, caddr_t, u_int8_t,
u_int16_t, u_int32_t, int, char *, void (*)(struct fw_xfer *));
u_int16_t, u_int32_t, int, void *, void (*)(struct fw_xfer *));
d_open_t fwmem_open;
d_close_t fwmem_close;
@ -50,3 +50,4 @@ d_read_t fwmem_read;
d_write_t fwmem_write;
d_poll_t fwmem_poll;
d_mmap_t fwmem_mmap;
d_strategy_t fwmem_strategy;

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

View File

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

View File

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

View File

@ -66,6 +66,7 @@
#include <dev/firewire/firewirereg.h>
#include <dev/firewire/fwdma.h>
#include <dev/firewire/iec13213.h>
#include <dev/firewire/sbp.h>
#define ccb_sdev_ptr spriv_ptr0
#define ccb_sbp_ptr spriv_ptr1
@ -77,10 +78,6 @@
#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb))
#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS)
#define SBP_INITIATOR 7
#define LOGIN_DELAY 2
/*
* STATUS FIFO addressing
* bit
@ -88,67 +85,25 @@
* 0- 1( 2): 0 (alingment)
* 2- 7( 6): target
* 8-15( 8): lun
* 16-23( 8): unit
* 24-31( 8): reserved
* 16-31( 8): reserved
* 32-47(16): SBP_BIND_HI
* 48-64(16): bus_id, node_id
*/
#define SBP_BIND_HI 0x1
#define SBP_DEV2ADDR(u, t, l) \
((((u) & 0xff) << 16) | (((l) & 0xff) << 8) | (((t) & 0x3f) << 2))
#define SBP_DEV2ADDR(t, l) \
(((u_int64_t)SBP_BIND_HI << 32) \
| (((l) & 0xff) << 8) \
| (((t) & 0x3f) << 2))
#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f)
#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff)
#define SBP_INITIATOR 7
#define ORB_NOTIFY (1 << 31)
#define ORB_FMT_STD (0 << 29)
#define ORB_FMT_VED (2 << 29)
#define ORB_FMT_NOP (3 << 29)
#define ORB_FMT_MSK (3 << 29)
#define ORB_EXV (1 << 28)
/* */
#define ORB_CMD_IN (1 << 27)
/* */
#define ORB_CMD_SPD(x) ((x) << 24)
#define ORB_CMD_MAXP(x) ((x) << 20)
#define ORB_RCN_TMO(x) ((x) << 20)
#define ORB_CMD_PTBL (1 << 19)
#define ORB_CMD_PSZ(x) ((x) << 16)
#define ORB_FUN_LGI (0 << 16)
#define ORB_FUN_QLG (1 << 16)
#define ORB_FUN_RCN (3 << 16)
#define ORB_FUN_LGO (7 << 16)
#define ORB_FUN_ATA (0xb << 16)
#define ORB_FUN_ATS (0xc << 16)
#define ORB_FUN_LUR (0xe << 16)
#define ORB_FUN_RST (0xf << 16)
#define ORB_FUN_MSK (0xf << 16)
#define ORB_FUN_RUNQUEUE 0xffff
#define LOGIN_DELAY 1
static char *orb_fun_name[] = {
/* 0 */ "LOGIN",
/* 1 */ "QUERY LOGINS",
/* 2 */ "Reserved",
/* 3 */ "RECONNECT",
/* 4 */ "SET PASSWORD",
/* 5 */ "Reserved",
/* 6 */ "Reserved",
/* 7 */ "LOGOUT",
/* 8 */ "Reserved",
/* 9 */ "Reserved",
/* A */ "Reserved",
/* B */ "ABORT TASK",
/* C */ "ABORT TASK SET",
/* D */ "Reserved",
/* E */ "LOGICAL UNIT RESET",
/* F */ "TARGET RESET"
ORB_FUN_NAMES
};
#define ORB_RES_CMPL 0
#define ORB_RES_FAIL 1
#define ORB_RES_ILLE 2
#define ORB_RES_VEND 3
static int debug = 0;
static int auto_login = 1;
static int max_speed = 2;
@ -163,14 +118,8 @@ SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RW, &auto_login, 0,
SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0,
"SBP transfer max speed");
#define SBP_DEBUG(x) if (debug > x) {
#define END_DEBUG }
#define NEED_RESPONSE 0
struct ind_ptr {
u_int32_t hi,lo;
};
#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE)
#ifdef __sparc64__ /* iommu */
#define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX)
@ -181,9 +130,9 @@ struct sbp_ocb {
STAILQ_ENTRY(sbp_ocb) ocb;
union ccb *ccb;
bus_addr_t bus_addr;
volatile u_int32_t orb[8];
u_int32_t orb[8];
#define IND_PTR_OFFSET (8*sizeof(u_int32_t))
volatile struct ind_ptr ind_ptr[SBP_IND_MAX];
struct ind_ptr ind_ptr[SBP_IND_MAX];
struct sbp_dev *sdev;
int flags; /* XXX should be removed */
bus_dmamap_t dmamap;
@ -193,63 +142,6 @@ struct sbp_ocb {
#define OCB_ACT_CMD 1
#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo))
#define SBP_RECV_LEN (16 + 32) /* header + payload */
struct sbp_login_res{
u_int16_t len;
u_int16_t id;
u_int16_t res0;
u_int16_t cmd_hi;
u_int32_t cmd_lo;
u_int16_t res1;
u_int16_t recon_hold;
};
struct sbp_status{
#if BYTE_ORDER == BIG_ENDIAN
u_int8_t src:2,
resp:2,
dead:1,
len:3;
#else
u_int8_t len:3,
dead:1,
resp:2,
src:2;
#endif
u_int8_t status;
u_int16_t orb_hi;
u_int32_t orb_lo;
u_int32_t data[6];
};
struct sbp_cmd_status{
#define SBP_SFMT_CURR 0
#define SBP_SFMT_DEFER 1
#if BYTE_ORDER == BIG_ENDIAN
u_int8_t sfmt:2,
status:6;
u_int8_t valid:1,
mark:1,
eom:1,
ill_len:1,
s_key:4;
#else
u_int8_t status:6,
sfmt:2;
u_int8_t s_key:4,
ill_len:1,
eom:1,
mark:1,
valid:1;
#endif
u_int8_t s_code;
u_int8_t s_qlfr;
u_int32_t info;
u_int32_t cdb;
u_int8_t fru;
u_int8_t s_keydep[3];
u_int32_t vend[2];
};
struct sbp_dev{
#define SBP_DEV_RESET 0 /* accept login */
#define SBP_DEV_LOGIN 1 /* to login */
@ -289,7 +181,7 @@ struct sbp_target {
struct sbp_ocb *mgm_ocb_cur;
STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue;
struct callout mgm_ocb_timeout;
#define SCAN_DELAY 2
#define SCAN_DELAY 1
struct callout scan_callout;
STAILQ_HEAD(, fw_xfer) xferlist;
int n_xfer;
@ -406,7 +298,7 @@ END_DEBUG
return(ENXIO);
}
device_set_desc(dev, "SBP2/SCSI over firewire");
device_set_desc(dev, "SBP-2/SCSI over FireWire");
if (bootverbose)
debug = bootverbose;
@ -879,7 +771,7 @@ END_DEBUG
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
xfer->act.hand = sbp_reset_start_callback;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqq.dest_hi = 0xffff;
fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
fp->mode.wreqq.data = htonl(0xf);
@ -1057,7 +949,7 @@ sbp_agent_reset_callback(struct fw_xfer *xfer)
sdev = (struct sbp_dev *)xfer->sc;
SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_cmd_callback\n");
printf("%s\n", __FUNCTION__);
END_DEBUG
if (xfer->resp != 0) {
sbp_show_sdev_info(sdev, 2);
@ -1088,7 +980,7 @@ END_DEBUG
xfer->act.hand = sbp_agent_reset_callback;
else
xfer->act.hand = sbp_do_attach;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqq.data = htonl(0xf);
fw_asyreq(xfer->fc, -1, xfer);
sbp_abort_all_ocbs(sdev, CAM_BDR_SENT);
@ -1120,7 +1012,7 @@ END_DEBUG
xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
xfer->act.hand = sbp_busy_timeout_callback;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqq.dest_hi = 0xffff;
fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT;
fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf);
@ -1142,12 +1034,12 @@ END_DEBUG
return;
xfer->act.hand = sbp_cmd_callback;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqb.len = 8;
fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] =
xfer->send.payload[0] =
htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16));
fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
xfer->send.payload[1] = htonl(ocb->bus_addr);
if(fw_asyreq(xfer->fc, -1, xfer) != 0){
sbp_xfer_free(xfer);
@ -1194,7 +1086,7 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
splx(s);
return(NULL);
}
xfer = fw_xfer_alloc_buf(M_SBP, 24, 12);
xfer = fw_xfer_alloc_buf(M_SBP, 8, 0);
if(xfer == NULL){
printf("sbp: fw_xfer_alloc_buf failed\n");
splx(s);
@ -1211,26 +1103,26 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
microtime(&xfer->tv);
if (tcode == FWTCODE_WREQQ)
xfer->send.len = 16;
else
xfer->send.len = 24;
xfer->recv.len = 12;
if (new) {
xfer->spd = min(sdev->target->fwdev->speed, max_speed);
xfer->recv.pay_len = 0;
xfer->send.spd = min(sdev->target->fwdev->speed, max_speed);
xfer->fc = sdev->target->sbp->fd.fc;
xfer->retry_req = fw_asybusy;
}
if (tcode == FWTCODE_WREQB)
xfer->send.pay_len = 8;
else
xfer->send.pay_len = 0;
xfer->sc = (caddr_t)sdev;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqq.dest_hi = sdev->login->cmd_hi;
fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset;
fp->mode.wreqq.tlrt = 0;
fp->mode.wreqq.tcode = tcode;
fp->mode.wreqq.pri = 0;
xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst;
fp->mode.wreqq.dst = xfer->dst;
fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst;
return xfer;
@ -1265,12 +1157,9 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb)
ocb->flags = OCB_ACT_MGM;
ocb->sdev = sdev;
bzero((void *)(uintptr_t)(volatile void *)ocb->orb, sizeof(ocb->orb));
bzero((void *)ocb->orb, sizeof(ocb->orb));
ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI);
ocb->orb[7] = htonl(SBP_DEV2ADDR(
device_get_unit(target->sbp->fd.dev),
target->target_id,
sdev->lun_id));
ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id));
SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
@ -1278,6 +1167,7 @@ SBP_DEBUG(0)
END_DEBUG
switch (func) {
case ORB_FUN_LGI:
ocb->orb[0] = ocb->orb[1] = 0; /* password */
ocb->orb[2] = htonl(nid << 16);
ocb->orb[3] = htonl(sdev->dma.bus_addr);
ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id);
@ -1315,13 +1205,17 @@ END_DEBUG
}
xfer->act.hand = sbp_mgm_callback;
fp = (struct fw_pkt *)xfer->send.buf;
fp = &xfer->send.hdr;
fp->mode.wreqb.dest_hi = sdev->target->mgm_hi;
fp->mode.wreqb.dest_lo = sdev->target->mgm_lo;
fp->mode.wreqb.len = 8;
fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] = htonl(nid << 16);
fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
xfer->send.payload[0] = htonl(nid << 16);
xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff);
SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("mgm orb: %08x\n", (u_int32_t)ocb->bus_addr);
END_DEBUG
fw_asyreq(xfer->fc, -1, xfer);
}
@ -1509,23 +1403,21 @@ printf("sbp %x %d %d %08x %08x %08x %08x\n",
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11]));
*/
sbp = (struct sbp_softc *)xfer->sc;
if(xfer->resp != 0){
if (xfer->resp != 0){
printf("sbp_recv: xfer->resp != 0\n");
goto done0;
}
if(xfer->recv.buf == NULL){
printf("sbp_recv: xfer->recv.buf == NULL\n");
if (xfer->recv.payload == NULL){
printf("sbp_recv: xfer->recv.payload == NULL\n");
goto done0;
}
sbp = (struct sbp_softc *)xfer->sc;
rfp = (struct fw_pkt *)xfer->recv.buf;
rfp = &xfer->recv.hdr;
if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){
printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode);
goto done0;
}
sbp_status = (struct sbp_status *)rfp->mode.wreqb.payload;
sbp_status = (struct sbp_status *)xfer->recv.payload;
addr = rfp->mode.wreqb.dest_lo;
SBP_DEBUG(2)
printf("received address 0x%x\n", addr);
@ -1748,6 +1640,7 @@ printf("len %d\n", sbp_status->len);
sbp_agent_reset(sdev);
done0:
xfer->recv.pay_len = SBP_RECV_LEN;
/* The received packet is usually small enough to be stored within
* the buffer. In that case, the controller return ack_complete and
* no respose is necessary.
@ -1772,7 +1665,6 @@ printf("len %d\n", sbp_status->len);
fw_asyreq(xfer->fc, -1, xfer);
#else
/* recycle */
xfer->recv.len = SBP_RECV_LEN;
STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
#endif
@ -1856,23 +1748,20 @@ END_DEBUG
goto fail;
if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path(sbp->sim));
goto fail;
}
sbp->fwb.start_hi = SBP_BIND_HI;
sbp->fwb.start_lo = SBP_DEV2ADDR(device_get_unit(sbp->fd.dev), 0, 0);
/* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */
sbp->fwb.addrlen = 0xffff;
sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0);
sbp->fwb.end = sbp->fwb.start + 0xffff;
sbp->fwb.act_type = FWACT_XFER;
/* pre-allocate xfer */
STAILQ_INIT(&sbp->fwb.xferlist);
for (i = 0; i < SBP_NUM_OCB/2; i ++) {
xfer = fw_xfer_alloc_buf(M_SBP,
#if NEED_RESPONSE
/* send */12,
#else
/* send */0,
#endif
/* recv */SBP_RECV_LEN);
xfer->act.hand = sbp_recv;
#if NEED_RESPONSE
@ -1949,8 +1838,10 @@ END_DEBUG
for (i = 0; i < SBP_NUM_TARGETS; i ++)
sbp_cam_detach_target(&sbp->targets[i]);
xpt_async(AC_LOST_DEVICE, sbp->path, NULL);
xpt_free_path(sbp->path);
xpt_bus_deregister(cam_sim_path(sbp->sim));
cam_sim_free(sbp->sim, /*free_devq*/ TRUE),
sbp_logout_all(sbp);
@ -1974,7 +1865,7 @@ END_DEBUG
for (xfer = STAILQ_FIRST(&target->xferlist);
xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link);
fw_xfer_free(xfer);
fw_xfer_free_buf(xfer);
}
free(target->luns, M_SBP);
}
@ -1982,7 +1873,7 @@ END_DEBUG
for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist);
xfer != NULL; xfer = next) {
next = STAILQ_NEXT(xfer, link);
fw_xfer_free(xfer);
fw_xfer_free_buf(xfer);
}
STAILQ_INIT(&sbp->fwb.xferlist);
fw_bindremove(fc, &sbp->fwb);
@ -2259,9 +2150,7 @@ END_DEBUG
cdb = (void *)csio->cdb_io.cdb_ptr;
else
cdb = (void *)&csio->cdb_io.cdb_bytes;
bcopy(cdb,
(void *)(uintptr_t)(volatile void *)&ocb->orb[5],
csio->cdb_len);
bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len);
/*
printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3]));
printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7]));

202
sys/dev/firewire/sbp.h Normal file
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
SRCS = bus_if.h device_if.h \
opt_cam.h opt_scsi.h \
sbp.c \
sbp.c sbp.h \
firewire.h firewirereg.h \
iec13213.h