From c4778b5d1c8715bc45e1c54b783cc7c719104db0 Mon Sep 17 00:00:00 2001 From: Hidetoshi Shimokawa Date: Thu, 2 Oct 2003 04:06:56 +0000 Subject: [PATCH] MFp4: Change struct fw_xfer to reduce memory copy in fwmem_*() functions. And many changes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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. --- sys/dev/firewire/firewire.c | 439 ++++++++++++++++-------------- sys/dev/firewire/firewire.h | 33 ++- sys/dev/firewire/firewirereg.h | 45 ++- sys/dev/firewire/fwcrom.c | 7 +- sys/dev/firewire/fwdev.c | 86 ++++-- sys/dev/firewire/fwmem.c | 251 ++++++++--------- sys/dev/firewire/fwmem.h | 9 +- sys/dev/firewire/fwohci.c | 140 ++++------ sys/dev/firewire/fwohcireg.h | 14 +- sys/dev/firewire/if_fwe.c | 10 +- sys/dev/firewire/sbp.c | 225 ++++----------- sys/dev/firewire/sbp.h | 202 ++++++++++++++ sys/modules/firewire/sbp/Makefile | 2 +- 13 files changed, 805 insertions(+), 658 deletions(-) create mode 100644 sys/dev/firewire/sbp.h diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c index 2775b0f84ed9..1fe238961cfa 100644 --- a/sys/dev/firewire/firewire.c +++ b/sys/dev/firewire/firewire.c @@ -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 @@ out: 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 @@ dorequest: 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 @@ err: 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; } diff --git a/sys/dev/firewire/firewire.h b/sys/dev/firewire/firewire.h index ca9cbac245c7..0063f47baf83 100644 --- a/sys/dev/firewire/firewire.h +++ b/sys/dev/firewire/firewire.h @@ -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; }; diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h index e90f0c07f526..0f97574f542e 100644 --- a/sys/dev/firewire/firewirereg.h +++ b/sys/dev/firewire/firewirereg.h @@ -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); diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c index ce7dfd3d1c28..15dd818e2728 100644 --- a/sys/dev/firewire/fwcrom.c +++ b/sys/dev/firewire/fwcrom.c @@ -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)); diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c index 545f1cd18666..29af3b2a57c2 100644 --- a/sys/dev/firewire/fwdev.c +++ b/sys/dev/firewire/fwdev.c @@ -39,6 +39,11 @@ #include #include #include +#if __FreeBSD_version < 500000 +#include +#else +#include +#endif #include #include @@ -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 @@ readloop: 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 @@ error: 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) { diff --git a/sys/dev/firewire/fwmem.c b/sys/dev/firewire/fwmem.c index daaf68a34a0d..35915cc8cc8c 100644 --- a/sys/dev/firewire/fwmem.c +++ b/sys/dev/firewire/fwmem.c @@ -44,6 +44,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#if __FreeBSD_version < 500000 +#include +#else +#include +#endif #include #include @@ -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 diff --git a/sys/dev/firewire/fwmem.h b/sys/dev/firewire/fwmem.h index 0567f81e9a65..f9442bb9123b 100644 --- a/sys/dev/firewire/fwmem.h +++ b/sys/dev/firewire/fwmem.h @@ -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; diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index 3b71c47c54f6..20d72c9e0464 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -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 @@ txloop: 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 @@ txloop: 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 @@ txloop: 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 @@ outdb: } 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"); diff --git a/sys/dev/firewire/fwohcireg.h b/sys/dev/firewire/fwohcireg.h index 9b1e703e1717..5295cd53fed0 100644 --- a/sys/dev/firewire/fwohcireg.h +++ b/sys/dev/firewire/fwohcireg.h @@ -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; diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c index 3eddef71ac4a..b076497098e8 100644 --- a/sys/dev/firewire/if_fwe.c +++ b/sys/dev/firewire/if_fwe.c @@ -350,7 +350,7 @@ found: 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 */ diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index 1c8b377f0f82..53c0241844cc 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -66,6 +66,7 @@ #include #include #include +#include #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 @@ start: } 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 @@ done: 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 @@ done0: 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])); diff --git a/sys/dev/firewire/sbp.h b/sys/dev/firewire/sbp.h new file mode 100644 index 000000000000..0949049cfac3 --- /dev/null +++ b/sys/dev/firewire/sbp.h @@ -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" diff --git a/sys/modules/firewire/sbp/Makefile b/sys/modules/firewire/sbp/Makefile index e114dbb4dbac..7acf1a39fb32 100644 --- a/sys/modules/firewire/sbp/Makefile +++ b/sys/modules/firewire/sbp/Makefile @@ -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