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