I have been using sbp_targ with our own custom backend target for about a month now and have generated the following patch that is required to make the target work and process data correctly. Issue 1. Correct CTIO processing when multiple CTIO's are required for a single ATIO. This was handled by creating a unrestricted page table structure and indexing through the page_table with easier to read variables. Split out the processing of the page table into a seperate function(sbp_targ_xfer_pt) for ease of invocation. Issue 2. Change the tag_action for every ATIO to be "MSG_SIMPLE_TASK", this was causing crashes in my backend target when it was set to "1" Issue 3. Change default handler in sbp_targ_action1() to CAM_PROVIDE_FAIL Issue 4. Add new transport type of "XPORT_FW" so that my backend target can detect the differences between firewire and other XPORT types. Issue 5. Move atio assignment so that it is not mis-accessed by the error handlers. Issue 6. Implement code for "CAM_NEW_TRAN_CODE" (That's what I use). Issue 7. Remove the number "2" in assignment of firewire speed. Use define FWSPD_S400 in it's place. This is a precursor to detecting the SIM's bus speed capabilities and using that for this value. Issue 8. A lot of debugging code added, along with some comments. They really helped me out and should be incorporated in some form or fashion into the code for the "next person". TODO items Issue 9. Possible race condition around orbi->refcount Issue 10. Implement compatibility with sbp so they can coexist Issue 11. Implement detection of bus speed so firewire 800 cards can be used Fix: Issues 1-8 are resolved with the patch attached to this PR. Issues 9-11 are under construction. :) Partial credit for these fixes should go to Justin Gibbs. Patch attached with submission follows: How-To-Repeat: Try to use sbp_targ with a backend target.
Responsible Changed From-To: freebsd-bugs->simokawa I'll take care of this PR.
Looks like I've run into a new item for my TODO list. Item 12: firewire_xfer_timeout() finding timed out transactions. Timeout too small at 200 msec? Sean
Ah, now windows is exploding all over the place. Looks like I need to implement all of the task management functions: ORB_FUN_ATA <--- Abort task ORB_FUN_ATS <--- Abort task set ORB_FUN_LUR <--- Logical unit reset ORB_FUN_RST <--- Target reset So add this to the todo list as item 13
Responsible Changed From-To: simokawa->sbruno I'm a committer now, I'll take care of this one.
Author: sbruno Date: Wed Jan 25 23:33:50 2012 New Revision: 230558 URL: http://svn.freebsd.org/changeset/base/230558 Log: Update sbp_targ such that it can actually handle multiple CTIO's during operation PR: kern/119575 Modified: head/sys/dev/firewire/sbp_targ.c Modified: head/sys/dev/firewire/sbp_targ.c ============================================================================== --- head/sys/dev/firewire/sbp_targ.c Wed Jan 25 22:39:22 2012 (r230557) +++ head/sys/dev/firewire/sbp_targ.c Wed Jan 25 23:33:50 2012 (r230558) @@ -62,6 +62,7 @@ #include <cam/cam_debug.h> #include <cam/cam_periph.h> #include <cam/scsi/scsi_all.h> +#include <cam/scsi/scsi_message.h> #define SBP_TARG_RECV_LEN 8 #define MAX_INITIATORS 8 @@ -186,6 +187,21 @@ struct morb4 { #endif }; + +/* + * Urestricted page table format + * states that the segment length + * and high base addr are in the first + * 32 bits and the base low is in + * the second + */ +struct unrestricted_page_table_fmt { + uint16_t segment_len; + uint16_t segment_base_high; + uint32_t segment_base_low; +}; + + struct orb_info { struct sbp_targ_softc *sc; struct fw_device *fwdev; @@ -208,7 +224,10 @@ struct orb_info { struct corb4 orb4; STAILQ_ENTRY(orb_info) link; uint32_t orb[8]; - uint32_t *page_table; + struct unrestricted_page_table_fmt *page_table; + struct unrestricted_page_table_fmt *cur_pte; + struct unrestricted_page_table_fmt *last_pte; + uint32_t last_block_read; struct sbp_status status; }; @@ -219,6 +238,7 @@ static char *orb_fun_name[] = { static void sbp_targ_recv(struct fw_xfer *); static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *, uint16_t, uint32_t, struct sbp_targ_login *, int); +static void sbp_targ_xfer_pt(struct orb_info *); static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *); static void @@ -252,13 +272,19 @@ sbp_targ_dealloc_login(struct sbp_targ_l } for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) { next = STAILQ_NEXT(orbi, link); + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); + orbi = NULL; } callout_stop(&login->hold_callout); STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link); login->lstate->sc->logins[login->id] = NULL; + if (debug) + printf("%s: free login %p\n", __func__, login); free((void *)login, M_SBP_TARG); + login = NULL; } static void @@ -361,20 +387,26 @@ sbp_targ_find_devs(struct sbp_targ_softc if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) { *lstate = sc->black_hole; + if (debug) + printf("setting black hole for this target id(%d)\n", ccb->ccb_h.target_id); return (CAM_REQ_CMP); } - if (ccb->ccb_h.target_id != 0) - return (CAM_TID_INVALID); - lun = ccb->ccb_h.target_lun; if (lun >= MAX_LUN) return (CAM_LUN_INVALID); *lstate = sc->lstate[lun]; - if (notfound_failure != 0 && *lstate == NULL) + if (notfound_failure != 0 && *lstate == NULL) { + if (debug) + printf("%s: lstate for lun is invalid, target(%d), lun(%d)\n", + __func__, ccb->ccb_h.target_id, lun); return (CAM_PATH_INVALID); + } else + if (debug) + printf("%s: setting lstate for tgt(%d) lun(%d)\n", + __func__,ccb->ccb_h.target_id, lun); return (CAM_REQ_CMP); } @@ -411,11 +443,18 @@ sbp_targ_en_lun(struct sbp_targ_softc *s printf("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; - } - if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) + } else { + if (debug) + printf("%s: malloc'd lstate %p\n",__func__, lstate); + } + if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) { sc->black_hole = lstate; - else + if (debug) + printf("Blackhole set due to target id == %d\n", + ccb->ccb_h.target_id); + } else sc->lstate[ccb->ccb_h.target_lun] = lstate; + memset(lstate, 0, sizeof(*lstate)); lstate->sc = sc; status = xpt_create_path(&lstate->path, /*periph*/NULL, @@ -424,6 +463,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s xpt_path_lun_id(ccb->ccb_h.path)); if (status != CAM_REQ_CMP) { free(lstate, M_SBP_TARG); + lstate = NULL; xpt_print_path(ccb->ccb_h.path); printf("Couldn't allocate path\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; @@ -443,6 +483,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s if (lstate == NULL) { ccb->ccb_h.status = CAM_LUN_INVALID; + printf("Invalid lstate for this target\n"); return; } ccb->ccb_h.status = CAM_REQ_CMP; @@ -458,6 +499,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s } if (ccb->ccb_h.status != CAM_REQ_CMP) { + printf("status != CAM_REQ_CMP\n"); return; } @@ -475,7 +517,10 @@ sbp_targ_en_lun(struct sbp_targ_softc *s sc->black_hole = NULL; else sc->lstate[ccb->ccb_h.target_lun] = NULL; + if (debug) + printf("%s: free lstate %p\n", __func__, lstate); free(lstate, M_SBP_TARG); + lstate = NULL; /* bus reset */ sc->fd.fc->ibr(sc->fd.fc); @@ -538,7 +583,7 @@ sbp_targ_get_orb_info(struct sbp_targ_ls if (orbi->orb_lo == tag_id) goto found; printf("%s: orb not found tag_id=0x%08x init_id=%d\n", - __func__, tag_id, init_id); + __func__, tag_id, init_id); return (NULL); found: return (orbi); @@ -559,12 +604,13 @@ sbp_targ_abort(struct sbp_targ_softc *sc xpt_done(orbi->ccb); orbi->ccb = NULL; } -#if 0 if (orbi->state <= ORBI_STATUS_ATIO) { sbp_targ_remove_orb_info_locked(orbi->login, orbi); + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); + orbi = NULL; } else -#endif orbi->state = ORBI_STATUS_ABORTED; } } @@ -576,12 +622,21 @@ sbp_targ_free_orbi(struct fw_xfer *xfer) { struct orb_info *orbi; - orbi = (struct orb_info *)xfer->sc; if (xfer->resp != 0) { /* XXX */ printf("%s: xfer->resp = %d\n", __func__, xfer->resp); } + orbi = (struct orb_info *)xfer->sc; + if ( orbi->page_table != NULL ) { + if (debug) + printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table); + free(orbi->page_table, M_SBP_TARG); + orbi->page_table = NULL; + } + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); + orbi = NULL; fw_xfer_free(xfer); } @@ -595,7 +650,7 @@ sbp_targ_status_FIFO(struct orb_info *or sbp_targ_remove_orb_info(orbi->login, orbi); xfer = fwmem_write_block(orbi->fwdev, (void *)orbi, - /*spd*/2, fifo_hi, fifo_lo, + /*spd*/FWSPD_S400, fifo_hi, fifo_lo, sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status, sbp_targ_free_orbi); @@ -605,6 +660,10 @@ sbp_targ_status_FIFO(struct orb_info *or } } +/* + * Generate the appropriate CAM status for the + * target. + */ static void sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb) { @@ -621,6 +680,8 @@ sbp_targ_send_status(struct orb_info *or sbp_status->status = 0; /* XXX */ sbp_status->dead = 0; /* XXX */ + ccb->ccb_h.status= CAM_REQ_CMP; + switch (ccb->csio.scsi_status) { case SCSI_STATUS_OK: if (debug) @@ -628,8 +689,15 @@ sbp_targ_send_status(struct orb_info *or sbp_status->len = 1; break; case SCSI_STATUS_CHECK_COND: + if (debug) + printf("%s: STATUS SCSI_STATUS_CHECK_COND\n", __func__); + goto process_scsi_status; case SCSI_STATUS_BUSY: + if (debug) + printf("%s: STATUS SCSI_STATUS_BUSY\n", __func__); + goto process_scsi_status; case SCSI_STATUS_CMD_TERMINATED: +process_scsi_status: { struct sbp_cmd_status *sbp_cmd_status; struct scsi_sense_data *sense; @@ -640,9 +708,6 @@ sbp_targ_send_status(struct orb_info *or int64_t sinfo; int sense_len; - if (debug) - printf("%s: STATUS %d\n", __func__, - ccb->csio.scsi_status); sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0]; sbp_cmd_status->status = ccb->csio.scsi_status; sense = &ccb->csio.sense_data; @@ -734,6 +799,7 @@ sbp_targ_send_status(struct orb_info *or if (scsi_get_sks(sense, sense_len, sks) == 0) { bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks)); sbp_status->len = 5; + ccb->ccb_h.status |= CAM_SENT_SENSE; } break; @@ -743,13 +809,20 @@ sbp_targ_send_status(struct orb_info *or sbp_status->status); } - if (orbi->page_table != NULL) - free(orbi->page_table, M_SBP_TARG); sbp_targ_status_FIFO(orbi, orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); } +/* + * Invoked as a callback handler from fwmem_read/write_block + * + * Process read/write of initiator address space + * completion and pass status onto the backend target. + * If this is a partial read/write for a CCB then + * we decrement the orbi's refcount to indicate + * the status of the read/write is complete + */ static void sbp_targ_cam_done(struct fw_xfer *xfer) { @@ -758,7 +831,7 @@ sbp_targ_cam_done(struct fw_xfer *xfer) orbi = (struct orb_info *)xfer->sc; - if (debug > 1) + if (debug) printf("%s: resp=%d refcount=%d\n", __func__, xfer->resp, orbi->refcount); @@ -779,13 +852,26 @@ sbp_targ_cam_done(struct fw_xfer *xfer) if (debug) printf("%s: orbi aborted\n", __func__); sbp_targ_remove_orb_info(orbi->login, orbi); - if (orbi->page_table != NULL) + if (orbi->page_table != NULL) { + if (debug) + printf("%s: free orbi->page_table %p\n", + __func__, orbi->page_table); free(orbi->page_table, M_SBP_TARG); + } + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); - } else if (orbi->status.resp == 0) { - if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) + orbi = NULL; + } else if (orbi->status.resp == ORBI_STATUS_NONE) { + if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { + if (debug) + printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags); sbp_targ_send_status(orbi, ccb); - ccb->ccb_h.status = CAM_REQ_CMP; + } else { + if (debug) + printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags); + ccb->ccb_h.status = CAM_REQ_CMP; + } SBP_LOCK(orbi->sc); xpt_done(ccb); SBP_UNLOCK(orbi->sc); @@ -855,6 +941,13 @@ sbp_targ_abort_ccb(struct sbp_targ_softc return (CAM_PATH_INVALID); } +/* + * directly execute a read or write to the initiator + * address space and set hand(sbp_targ_cam_done) to + * process the completion from the SIM to the target. + * set orbi->refcount to inidicate that a read/write + * is inflight to/from the initiator. + */ static void sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset, uint16_t dst_hi, uint32_t dst_lo, u_int size, @@ -874,16 +967,21 @@ sbp_targ_xfer_buf(struct orb_info *orbi, len = MIN(size, 2048 /* XXX */); size -= len; orbi->refcount ++; - if (ccb_dir == CAM_DIR_OUT) + if (ccb_dir == CAM_DIR_OUT) { + if (debug) + printf("%s: CAM_DIR_OUT --> read block in?\n",__func__); xfer = fwmem_read_block(orbi->fwdev, - (void *)orbi, /*spd*/2, + (void *)orbi, /*spd*/FWSPD_S400, dst_hi, dst_lo + off, len, ptr + off, hand); - else + } else { + if (debug) + printf("%s: CAM_DIR_IN --> write block out?\n",__func__); xfer = fwmem_write_block(orbi->fwdev, - (void *)orbi, /*spd*/2, + (void *)orbi, /*spd*/FWSPD_S400, dst_hi, dst_lo + off, len, ptr + off, hand); + } if (xfer == NULL) { printf("%s: xfer == NULL", __func__); /* XXX what should we do?? */ @@ -897,18 +995,22 @@ static void sbp_targ_pt_done(struct fw_xfer *xfer) { struct orb_info *orbi; - union ccb *ccb; - u_int i, offset, res, len; - uint32_t t1, t2, *p; + struct unrestricted_page_table_fmt *pt; + uint32_t i; orbi = (struct orb_info *)xfer->sc; - ccb = orbi->ccb; + if (orbi->state == ORBI_STATUS_ABORTED) { if (debug) printf("%s: orbi aborted\n", __func__); sbp_targ_remove_orb_info(orbi->login, orbi); + if (debug) { + printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table); + printf("%s: free orbi %p\n", __func__, orbi); + } free(orbi->page_table, M_SBP_TARG); free(orbi, M_SBP_TARG); + orbi = NULL; fw_xfer_free(xfer); return; } @@ -920,60 +1022,158 @@ sbp_targ_pt_done(struct fw_xfer *xfer) orbi->status.len = 1; sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link)); + if (debug) + printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table); + sbp_targ_status_FIFO(orbi, orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); free(orbi->page_table, M_SBP_TARG); + orbi->page_table = NULL; fw_xfer_free(xfer); return; } - res = ccb->csio.dxfer_len; - offset = 0; - if (debug) - printf("%s: dxfer_len=%d\n", __func__, res); - orbi->refcount ++; - for (p = orbi->page_table, i = orbi->orb4.data_size; i > 0; i --) { - t1 = ntohl(*p++); - t2 = ntohl(*p++); - if (debug > 1) - printf("page_table: %04x:%08x %d\n", - t1 & 0xffff, t2, t1>>16); - len = MIN(t1 >> 16, res); - res -= len; - sbp_targ_xfer_buf(orbi, offset, t1 & 0xffff, t2, len, - sbp_targ_cam_done); - offset += len; - if (res == 0) - break; + orbi->refcount++; +/* + * Set endianess here so we don't have + * to deal with is later + */ + for (i = 0, pt = orbi->page_table; i < orbi->orb4.data_size; i++, pt++) { + pt->segment_len = ntohs(pt->segment_len); + if (debug) + printf("%s:segment_len = %u\n", __func__,pt->segment_len); + pt->segment_base_high = ntohs(pt->segment_base_high); + pt->segment_base_low = ntohl(pt->segment_base_low); } - orbi->refcount --; + + sbp_targ_xfer_pt(orbi); + + orbi->refcount--; if (orbi->refcount == 0) printf("%s: refcount == 0\n", __func__); - if (res !=0) - /* XXX handle res != 0 case */ - printf("%s: page table is too small(%d)\n", __func__, res); fw_xfer_free(xfer); return; } +static void sbp_targ_xfer_pt(struct orb_info *orbi) +{ + union ccb *ccb; + uint32_t res, offset, len; + + ccb = orbi->ccb; + if (debug) + printf("%s: dxfer_len=%d\n", __func__, ccb->csio.dxfer_len); + res = ccb->csio.dxfer_len; + /* + * If the page table required multiple CTIO's to + * complete, then cur_pte is non NULL + * and we need to start from the last position + * If this is the first pass over a page table + * then we just start at the beginning of the page + * table. + * + * Parse the unrestricted page table and figure out where we need + * to shove the data from this read request. + */ + for (offset = 0, len = 0; (res != 0) && (orbi->cur_pte < orbi->last_pte); offset += len) { + len = MIN(orbi->cur_pte->segment_len, res); + res -= len; + if (debug) + printf("%s:page_table: %04x:%08x segment_len(%u) res(%u) len(%u)\n", + __func__, orbi->cur_pte->segment_base_high, + orbi->cur_pte->segment_base_low, + orbi->cur_pte->segment_len, + res, len); + sbp_targ_xfer_buf(orbi, offset, + orbi->cur_pte->segment_base_high, + orbi->cur_pte->segment_base_low, + len, sbp_targ_cam_done); + /* + * If we have only written partially to + * this page table, then we need to save + * our position for the next CTIO. If we + * have completed the page table, then we + * are safe to move on to the next entry. + */ + if (len == orbi->cur_pte->segment_len) { + orbi->cur_pte++; + } else { + uint32_t saved_base_low; + + /* Handle transfers that cross a 4GB boundary. */ + saved_base_low = orbi->cur_pte->segment_base_low; + orbi->cur_pte->segment_base_low += len; + if (orbi->cur_pte->segment_base_low < saved_base_low) + orbi->cur_pte->segment_base_high++; + + orbi->cur_pte->segment_len -= len; + } + } + if (debug) { + printf("%s: base_low(%08x) page_table_off(%p) last_block(%u)\n", + __func__, orbi->cur_pte->segment_base_low, + orbi->cur_pte, orbi->last_block_read); + } + if (res != 0) + printf("Warning - short pt encountered. " + "Could not transfer all data.\n"); + return; +} + +/* + * Create page table in local memory + * and transfer it from the initiator + * in order to know where we are supposed + * to put the data. + */ + static void sbp_targ_fetch_pt(struct orb_info *orbi) { struct fw_xfer *xfer; - if (debug) - printf("%s: page_table_size=%d\n", - __func__, orbi->orb4.data_size); - orbi->page_table = malloc(orbi->orb4.data_size*8, M_SBP_TARG, M_NOWAIT); - if (orbi->page_table == NULL) - goto error; - xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/2, - orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*8, - (void *)orbi->page_table, sbp_targ_pt_done); - if (xfer != NULL) + /* + * Pull in page table from initiator + * and setup for data from our + * backend device. + */ + if (orbi->page_table == NULL) { + orbi->page_table = malloc(orbi->orb4.data_size* + sizeof(struct unrestricted_page_table_fmt), + M_SBP_TARG, M_NOWAIT|M_ZERO); + if (orbi->page_table == NULL) + goto error; + orbi->cur_pte = orbi->page_table; + orbi->last_pte = orbi->page_table + orbi->orb4.data_size; + orbi->last_block_read = orbi->orb4.data_size; + if (debug && orbi->page_table != NULL) + printf("%s: malloc'd orbi->page_table(%p), orb4.data_size(%u)\n", + __func__, orbi->page_table, orbi->orb4.data_size); + + xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/FWSPD_S400, + orbi->data_hi, orbi->data_lo, orbi->orb4.data_size* + sizeof(struct unrestricted_page_table_fmt), + (void *)orbi->page_table, sbp_targ_pt_done); + + if (xfer != NULL) + return; + } else { + /* + * This is a CTIO for a page table we have + * already malloc'd, so just directly invoke + * the xfer function on the orbi. + */ + sbp_targ_xfer_pt(orbi); return; + } error: orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + if (debug) + printf("%s: free orbi->page_table %p due to xfer == NULL\n", __func__, orbi->page_table); + if (orbi->page_table != NULL) { + free(orbi->page_table, M_SBP_TARG); + orbi->page_table = NULL; + } xpt_done(orbi->ccb); return; } @@ -1016,6 +1216,8 @@ sbp_targ_action1(struct cam_sim *sim, un if (debug) printf("%s: ctio aborted\n", __func__); sbp_targ_remove_orb_info_locked(orbi->login, orbi); + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); ccb->ccb_h.status = CAM_REQ_ABORTED; xpt_done(ccb); @@ -1051,17 +1253,16 @@ sbp_targ_action1(struct cam_sim *sim, un } /* Sanity check */ - if (ccb_dir != CAM_DIR_NONE && - orbi->orb4.data_size != ccb->csio.dxfer_len) - printf("%s: data_size(%d) != dxfer_len(%d)\n", - __func__, orbi->orb4.data_size, - ccb->csio.dxfer_len); - - if (ccb_dir != CAM_DIR_NONE) + if (ccb_dir != CAM_DIR_NONE) { sbp_targ_xfer_buf(orbi, 0, orbi->data_hi, orbi->data_lo, MIN(orbi->orb4.data_size, ccb->csio.dxfer_len), sbp_targ_cam_done); + if ( orbi->orb4.data_size > ccb->csio.dxfer_len ) { + orbi->data_lo += ccb->csio.dxfer_len; + orbi->orb4.data_size -= ccb->csio.dxfer_len; + } + } if (ccb_dir == CAM_DIR_NONE) { if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { @@ -1125,7 +1326,8 @@ sbp_targ_action1(struct cam_sim *sim, un cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; - cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE; + cpi->transport = XPORT_SPI; /* FIXME add XPORT_FW type to cam */ + cpi->hba_misc = PIM_NOBUSRESET | PIM_NOBUSRESET; cpi->hba_eng_cnt = 0; cpi->max_target = 7; /* XXX */ cpi->max_lun = MAX_LUN - 1; @@ -1163,10 +1365,42 @@ sbp_targ_action1(struct cam_sim *sim, un xpt_done(ccb); break; } +#ifdef CAM_NEW_TRAN_CODE + case XPT_SET_TRAN_SETTINGS: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + case XPT_GET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; + + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_FW; /* should have a FireWire */ + cts->transport_version = 2; + spi->valid = CTS_SPI_VALID_DISC; + spi->flags = CTS_SPI_FLAGS_DISC_ENB; + scsi->valid = CTS_SCSI_VALID_TQ; + scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; +#if 0 + printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:\n", + device_get_nameunit(sc->fd.dev), + ccb->ccb_h.target_id, ccb->ccb_h.target_lun); +#endif + cts->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } +#endif + default: - printf("%s: unknown function %d\n", + printf("%s: unknown function 0x%x\n", __func__, ccb->ccb_h.func_code); - ccb->ccb_h.status = CAM_REQ_INVALID; + ccb->ccb_h.status = CAM_PROVIDE_FAIL; xpt_done(ccb); break; } @@ -1245,7 +1479,7 @@ sbp_targ_cmd_handler(struct fw_xfer *xfe atio->ccb_h.target_id = 0; /* XXX */ atio->ccb_h.target_lun = orbi->login->lstate->lun; atio->sense_len = 0; - atio->tag_action = 1; /* XXX */ + atio->tag_action = MSG_SIMPLE_TASK; atio->tag_id = orbi->orb_lo; atio->init_id = orbi->login->id; @@ -1429,7 +1663,7 @@ sbp_targ_mgm_handler(struct fw_xfer *xfe login->loginres.recon_hold = htons(login->hold_sec); STAILQ_INSERT_TAIL(&lstate->logins, login, link); - fwmem_write_block(orbi->fwdev, NULL, /*spd*/2, orb[2], orb[3], + fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3], sizeof(struct sbp_login_res), (void *)&login->loginres, fw_asy_callback_free); /* XXX return status after loginres is successfully written */ @@ -1515,10 +1749,11 @@ sbp_targ_fetch_orb(struct sbp_targ_softc orbi->orb_lo = orb_lo; orbi->status.orb_hi = htons(orb_hi); orbi->status.orb_lo = htonl(orb_lo); + orbi->page_table = NULL; switch (mode) { case FETCH_MGM: - fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo, sizeof(uint32_t) * 8, &orbi->orb[0], sbp_targ_mgm_handler); break; @@ -1545,14 +1780,14 @@ sbp_targ_fetch_orb(struct sbp_targ_softc SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle); STAILQ_INSERT_TAIL(&login->orbs, orbi, link); SBP_UNLOCK(sc); - fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo, sizeof(uint32_t) * 8, &orbi->orb[0], sbp_targ_cmd_handler); break; case FETCH_POINTER: orbi->state = ORBI_STATUS_POINTER; login->flags |= F_LINK_ACTIVE; - fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo, sizeof(uint32_t) * 2, &orbi->orb[0], sbp_targ_pointer_handler); break; @@ -1709,7 +1944,7 @@ done: if (rtcode != 0) printf("%s: rtcode = %d\n", __func__, rtcode); sfp = &xfer->send.hdr; - xfer->send.spd = 2; /* XXX */ + xfer->send.spd = FWSPD_S400; xfer->hand = sbp_targ_resp_callback; sfp->mode.wres.dst = fp->mode.wreqb.src; sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: open->patched
State Changed From-To: patched->closed Patches applied quite some time ago