From owner-freebsd-firewire@FreeBSD.ORG Thu May 22 17:34:09 2008 Return-Path: Delivered-To: freebsd-firewire@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6A16C1065672 for ; Thu, 22 May 2008 17:34:09 +0000 (UTC) (envelope-from sbruno@miralink.com) Received: from plato.miralink.com (mail.miralink.com [70.103.185.20]) by mx1.freebsd.org (Postfix) with ESMTP id E8D8A8FC12 for ; Thu, 22 May 2008 17:34:08 +0000 (UTC) (envelope-from sbruno@miralink.com) Received: from localhost (localhost.localdomain [127.0.0.1]) by plato.miralink.com (Postfix) with ESMTP id AF39F1A92DB; Thu, 22 May 2008 10:23:46 -0700 (PDT) X-Virus-Scanned: amavisd-new at X-Spam-Flag: NO X-Spam-Score: -4.399 X-Spam-Level: X-Spam-Status: No, score=-4.399 tagged_above=-10 required=6.6 tests=[ALL_TRUSTED=-1.8, BAYES_00=-2.599] Received: from plato.miralink.com ([127.0.0.1]) by localhost (plato.miralink.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1ejUHGWpqN5d; Thu, 22 May 2008 10:23:39 -0700 (PDT) Received: from iago.office.miralink.com (iago.office.miralink.com [10.0.0.40]) by plato.miralink.com (Postfix) with ESMTP id BD46B1A92D9; Thu, 22 May 2008 10:23:39 -0700 (PDT) Message-ID: <4835AC29.4030802@miralink.com> Date: Thu, 22 May 2008 10:23:53 -0700 From: Sean Bruno User-Agent: Thunderbird 2.0.0.14 (X11/20080501) MIME-Version: 1.0 To: freebsd-firewire@FreeBSD.org Content-Type: multipart/mixed; boundary="------------040806030102050805070300" Cc: simokawa@ieee.org Subject: Current sbp_targ diff X-BeenThere: freebsd-firewire@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Firewire support in FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 May 2008 17:34:09 -0000 This is a multi-part message in MIME format. --------------040806030102050805070300 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit I've been quiet lately but I had some time at BSDCAN to cleanup some of my firewire sbp_targ diffs and would like to get them out for review. 1. I've added a new XPORT_FW type to sys/cam/cam_ccb.h for firewire. I have added a couple of patches from RELENG_7 to my tree, but they can be ignored: Index: cam/cam_ccb.h =================================================================== --- cam/cam_ccb.h (.../FreeBSD_RELENG_6_13APR07/src/sys) (revision 5436) +++ cam/cam_ccb.h (.../miralink.FreeBSD.6/src/sys) (revision 5436) @@ -226,14 +223,15 @@ XPORT_SSA, /* Serial Storage Architecture */ XPORT_USB, /* Universal Serial Bus */ XPORT_PPB, /* Parallel Port Bus */ - XPORT_ATA /* AT Attachment */ + XPORT_ATA, /* AT Attachment */ + XPORT_SAS, /* Serial Attached SCSI */ + XPORT_FW /* FireWire 1394a/b */ } cam_xport; 2. I've added a new file to sbp_targ(fwcsr.c) that currently only handles the Busy Timeout register, but will undoubtably handle more in the future: Index: modules/firewire/firewire/Makefile =================================================================== --- modules/firewire/firewire/Makefile (.../FreeBSD_RELENG_6_13APR07/src/sys) (revision 5436) +++ modules/firewire/firewire/Makefile (.../miralink.FreeBSD.6/src/sys) (revision 5436) @@ -9,7 +9,8 @@ firewire.c firewire.h firewire_phy.h firewirereg.h \ fwohci.c fwohci_pci.c fwohcireg.h fwohcivar.h \ iec13213.h iec68113.h \ - fwcrom.c fwdev.c fwmem.c fwmem.h fwdma.c fwdma.h + fwcrom.c fwdev.c fwmem.c fwmem.h fwdma.c fwdma.h \ + fwcsr.c fwcsr.h .include Index: conf/files =================================================================== --- conf/files (.../FreeBSD_RELENG_6_13APR07/src/sys) (revision 5436) +++ conf/files (.../miralink.FreeBSD.6/src/sys) (revision 5436) @@ -617,6 +617,7 @@ dev/fe/if_fe_pccard.c optional fe pccard dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire +dev/firewire/fwcsr.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire 3. Finally, the code. I'm attaching a diff, however it's pretty intrusive so I'm also placing a tar ball of the code on my web server at: http://www.consultcsg.com/firewire_sbp-targ.tgz so you can review the entirety of the code at your leisure. I am still working on the code at this time and will be generating even more intrusive patches to support SBP-2 and possibly SBP-3 soon-ish. -- Sean Bruno MiraLink Corporation 6015 NE 80th Ave, Ste 100 Portland, OR 97218 Phone 503-621-5143 Fax 503-621-5199 --------------040806030102050805070300 Content-Type: text/x-patch; name="firewire.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="firewire.diff" Index: fwcsr.c =================================================================== --- fwcsr.c (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ fwcsr.c (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -1,85 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -void -fwcsr_busy_timeout_init(struct fw_bind *busy_timeout, - struct firewire_dev_comm *fd, - void *dev_softc, - struct malloc_type *dev_type, - uint32_t send_len, - uint32_t recv_len, - uint32_t max_lun) -{ - busy_timeout->start = 0xfffff0000000 | BUSY_TIMEOUT; - busy_timeout->end = 0xfffff0000000 | BUSY_TIMEOUT; - - STAILQ_INIT(&busy_timeout->xferlist); - fw_xferlist_add(&busy_timeout->xferlist, dev_type, - /*send*/ send_len, /*recv*/ recv_len, - max_lun, - fd->fc, dev_softc, fwcsr_busy_timeout_handler); - fw_bindadd(fd->fc, busy_timeout); -} - -void -fwcsr_busy_timeout_stop(struct fw_bind *busy_timeout, - struct firewire_dev_comm *fd) -{ - fw_xferlist_remove(&busy_timeout->xferlist); - fw_bindremove(fd->fc, busy_timeout); -} - -void -fwcsr_busy_timeout_handler(struct fw_xfer *xfer) -{ - struct fw_pkt *fp, *sfp; - struct fw_device *fwdev; - uint32_t lo = 0; - int s, rtcode; - struct firewire_softc *sc; - - s = splfw(); - sc = (struct firewire_softc *)xfer->sc; - fp = &xfer->recv.hdr; - fwdev = fw_noderesolve_nodeid(sc->fc, fp->mode.wreqb.src & 0x3f); - if (fwdev == NULL) { - printf("%s: cannot resolve nodeid=%d\n", - __func__, fp->mode.wreqb.src & 0x3f); - rtcode = RESP_TYPE_ERROR; /* XXX */ - } else { - printf("%s: BUSY_TIMEOUT Recieved\n", __func__); - rtcode = 0; - } - if (rtcode != 0) - printf("%s: rtcode = %d lo == 0x%x\n", __func__, rtcode, lo); - - sfp = &xfer->send.hdr; - xfer->send.spd = FWSPD_S400; -#if 0 - xfer->hand = fw_busy_timeout_resp_callback; -#endif - sfp->mode.wres.dst = fp->mode.wreqb.src; - sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt; - sfp->mode.wres.tcode = FWTCODE_WRES; - sfp->mode.wres.rtcode = rtcode; - sfp->mode.wres.pri = 0; - - fw_asyreq(xfer->fc, -1, xfer); - splx(s); -} - Index: fwcsr.h =================================================================== --- fwcsr.h (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ fwcsr.h (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -1,5 +0,0 @@ -void fwcsr_busy_timeout_handler(struct fw_xfer *); -void fwcsr_busy_timeout_init(struct fw_bind *, struct firewire_dev_comm *, - void *, struct malloc_type *, uint32_t, - uint32_t, uint32_t); -void fwcsr_busy_timeout_stop(struct fw_bind *, struct firewire_dev_comm *); Index: sbp_targ.c =================================================================== --- sbp_targ.c (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ sbp_targ.c (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -53,7 +53,6 @@ #include #include #include -#include #include #include @@ -62,7 +61,6 @@ #include #include #include -#include #define SBP_TARG_RECV_LEN 8 #define MAX_INITIATORS 8 @@ -75,10 +73,9 @@ * BASE 0xffff f001 0000 management port * BASE 0xffff f001 0020 command port for login id 0 * BASE 0xffff f001 0040 command port for login id 1 - * BASE 0xffff f001 (0x20 * [login_id + 1]) for login_id * */ -#define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 0000 */ +#define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 000 */ #define SBP_TARG_BIND_HI 0xffff #define SBP_TARG_BIND_LO(l) (0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1)) #define SBP_TARG_BIND_START (((u_int64_t)SBP_TARG_BIND_HI << 32) | \ @@ -91,16 +88,12 @@ #define FETCH_CMD 1 #define FETCH_POINTER 2 -#define F_LINK_ACTIVE (1 << 0) /* The F/W link is active */ -#define F_ATIO_STARVED (1 << 1) /* We are out of ATIO's */ -#define F_LOGIN (1 << 2) /* This initiator has logged in */ -#define F_HOLD (1 << 3) /* Hold on to this login */ -#define F_FREEZED (1 << 4) /* Frozen login, usually a bus reset occured */ -#define F_RECYCLE_LOGIN (1 << 5) /* This login is to be reused due */ - /* to login before SBP_TARG_HOLD_TIMEOUT */ +#define F_LINK_ACTIVE (1 << 0) +#define F_ATIO_STARVED (1 << 1) +#define F_LOGIN (1 << 2) +#define F_HOLD (1 << 3) +#define F_FREEZED (1 << 4) -#define SBP_TARG_HOLD_TIMEOUT 1 - MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode"); static int debug = 0; @@ -141,7 +134,6 @@ struct cam_sim *sim; struct cam_path *path; struct fw_bind fwb; - struct fw_bind busy_timeout; int ndevs; int flags; struct crom_chunk unit; @@ -176,10 +168,6 @@ struct morb4 { #if BYTE_ORDER == BIG_ENDIAN - uint16_t reserved; - uint16_t off_hi; - uint32_t off_lo; - uint64_t reserved2; uint32_t n:1, rq_fmt:2, :9, @@ -191,26 +179,9 @@ :9, rq_fmt:2, n:1; - uint64_t reserved2; - uint32_t off_lo; - uint16_t off_hi; - uint16_t reserved; #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; @@ -233,24 +204,10 @@ struct corb4 orb4; STAILQ_ENTRY(orb_info) link; uint32_t orb[8]; - 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; + uint32_t *page_table; struct sbp_status status; }; -struct agent_state { - uint32_t fetch_agent_state; -#define AGENT_STATE_RESET 0 -#define AGENT_STATE_ACTIVE 1 -#define AGENT_STATE_SUSPENDED 2 -#define AGENT_STATE_DEAD 3 - uint32_t bus_reset_command_reset_init_vals; - uint32_t read_vals; - uint32_t write_effects; -}; - static char *orb_fun_name[] = { ORB_FUN_NAMES }; @@ -258,8 +215,6 @@ 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_send_agent_state(struct fw_xfer *); static void sbp_targ_identify(driver_t *driver, device_t parent) @@ -287,22 +242,18 @@ struct orb_info *orbi, *next; if (login == NULL) { + printf("%s: login = NULL\n", __func__); return; } 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 @@ -312,25 +263,12 @@ login = (struct sbp_targ_login *)arg; - /* if the login has been deallocated - * prior to the login timeout, login - * should be NULL, and we should do - * nothing - */ - if (login != NULL ) { - if (login->flags & F_HOLD) { - if (debug) - printf("%s: login(%p), " - "login_id=%d expired\n", - __func__, login, login->id); - sbp_targ_dealloc_login(login); - } else if (debug) { - printf("%s: login(%p), " - "login_id=%d not hold\n", - __func__, login, login->id); - } - } else if (debug) - printf("%s: woke up and this login was NULL\n", __func__); + if (login->flags & F_HOLD) { + printf("%s: login_id=%d expired\n", __func__, login->id); + sbp_targ_dealloc_login(login); + } else { + printf("%s: login_id=%d not hold\n", __func__, login->id); + } } static void @@ -353,8 +291,9 @@ if ((sc->flags & F_FREEZED) == 0) { sc->flags |= F_FREEZED; xpt_freeze_simq(sc->sim, /*count*/1); - } else if (debug) + } else { printf("%s: already freezed\n", __func__); + } bzero(unit, sizeof(struct crom_chunk)); @@ -371,8 +310,6 @@ lstate = sc->lstate[i]; if (lstate == NULL) continue; - if (debug) - printf("%s: lstate not null\n", __func__); crom_add_entry(unit, CSRKEY_FIRM_VER, 1); crom_add_entry(unit, CROM_LUN, i); crom_add_entry(unit, CSRKEY_MODEL, 1); @@ -382,25 +319,13 @@ /* Process for reconnection hold time */ for (i = 0; i < MAX_LOGINS; i ++) { login = sc->logins[i]; - if (login == NULL) { + if (login == NULL) continue; - } if (login->flags & F_LOGIN) { - if (debug) - printf("%s: setting sbp_targ_hold_expire " - "for this login(%p)\n", - __func__, login); login->flags |= F_HOLD; - login->flags &= ~F_LOGIN; callout_reset(&login->hold_callout, hz * login->hold_sec, sbp_targ_hold_expire, (void *)login); - } else if (debug) { - /* Do nothing, allow sbp_Targ_hold_expire */ - /* to delete the login */ - printf("%s login->flags = %0x, " - "not F_LOGIN\n", - __func__, login->flags); } } } @@ -426,29 +351,20 @@ 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 (debug) - printf("%s: lstate for lun is invalid," - " target(%d), lun(%d)\n", - __func__, - ccb->ccb_h.target_id, lun); + if (notfound_failure != 0 && *lstate == NULL) 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); } @@ -485,20 +401,11 @@ printf("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; - } else { - if (debug) { - printf("%s: malloc'd lstate %p\n", - __func__, lstate); - } - } - if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) { + } + if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) sc->black_hole = lstate; - if (debug) - printf("Blackhole set due to target id == %d\n", - ccb->ccb_h.target_id); - } else + 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, @@ -507,7 +414,6 @@ 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; @@ -527,7 +433,6 @@ 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; @@ -543,7 +448,6 @@ } if (ccb->ccb_h.status != CAM_REQ_CMP) { - printf("status != CAM_REQ_CMP\n"); return; } @@ -561,15 +465,9 @@ sc->black_hole = NULL; else sc->lstate[ccb->ccb_h.target_lun] = NULL; - if (debug) - printf("%s: free lstate %p\n", __func__, lstate); - if (lstate != NULL) { - free(lstate, M_SBP_TARG); - lstate = NULL; - } else if (debug) - printf("%s: lstate was null\n", __func__); + free(lstate, M_SBP_TARG); + /* bus reset */ - sc->fd.fc->ibr(sc->fd.fc); } } @@ -617,17 +515,10 @@ printf("%s: no such login\n", __func__); return (NULL); } - STAILQ_FOREACH(orbi, &login->orbs, link) { + STAILQ_FOREACH(orbi, &login->orbs, link) if (orbi->orb_lo == tag_id) goto found; - if ( orbi->state == ORBI_STATUS_ABORTED) - printf("%s: orb aborted in flight tag_id=0x%08x\n", - __func__, tag_id); - else { - panic("%s: orb not found tag_id=0x%08x, state(%0x)\n", - __func__, tag_id, orbi->state); - } - } + printf("%s: orb not found tag_id=0x%08x\n", __func__, tag_id); return (NULL); found: return (orbi); @@ -639,8 +530,7 @@ struct orb_info *norbi; for (; orbi != NULL; orbi = norbi) { - printf("%s: status=%d ccb=%p\n", - __func__, orbi->state, orbi->ccb); + printf("%s: status=%d\n", __func__, orbi->state); norbi = STAILQ_NEXT(orbi, link); if (orbi->state != ORBI_STATUS_ABORTED) { if (orbi->ccb != NULL) { @@ -650,12 +540,7 @@ } if (orbi->state <= ORBI_STATUS_ATIO) { sbp_targ_remove_orb_info(orbi->login, orbi); - if (debug) { - printf("%s: free orbi %p\n", - __func__, orbi); - } free(orbi, M_SBP_TARG); - orbi = NULL; } else orbi->state = ORBI_STATUS_ABORTED; } @@ -667,23 +552,12 @@ { 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); } @@ -692,14 +566,14 @@ uint32_t fifo_hi, uint32_t fifo_lo, int dequeue) { struct fw_xfer *xfer; + if (dequeue) sbp_targ_remove_orb_info(orbi->login, orbi); xfer = fwmem_write_block(orbi->fwdev, (void *)orbi, - /*spd*/FWSPD_S400, fifo_hi, fifo_lo, - sizeof(uint32_t) * (orbi->status.len + 1), - (char *)&orbi->status, - sbp_targ_free_orbi); + /*spd*/2, fifo_hi, fifo_lo, + sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status, + sbp_targ_free_orbi); if (xfer == NULL) { /* XXX */ @@ -707,10 +581,6 @@ } } -/* - * Generate the appropriate CAM status for the - * target. - */ static void sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb) { @@ -724,7 +594,6 @@ 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) @@ -732,22 +601,15 @@ 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: - if (debug) - printf("%s: STATUS SCSI_STATUS_CMD_TERMINATED\n", - __func__); -process_scsi_status: { struct sbp_cmd_status *sbp_cmd_status; struct scsi_sense_data *sense; + 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; @@ -784,7 +646,6 @@ bcopy(&sense->sense_key_spec[0], &sbp_cmd_status->s_keydep[0], 3); - ccb->ccb_h.status |= CAM_SENT_SENSE; break; } default: @@ -795,17 +656,10 @@ sbp_targ_status_FIFO(orbi, orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); + if (orbi->page_table != NULL) + free(orbi->page_table, M_SBP_TARG); } -/* - * 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) { @@ -814,9 +668,10 @@ orbi = (struct orb_info *)xfer->sc; - if (debug) + if (debug > 1) printf("%s: resp=%d refcount=%d\n", __func__, xfer->resp, orbi->refcount); + if (xfer->resp != 0) { printf("%s: xfer->resp = %d\n", __func__, xfer->resp); orbi->status.resp = SBP_TRANS_FAIL; @@ -825,7 +680,7 @@ sbp_targ_abort(STAILQ_NEXT(orbi, link)); } - orbi->refcount--; + orbi->refcount --; ccb = orbi->ccb; if (orbi->refcount == 0) { @@ -833,31 +688,13 @@ if (debug) printf("%s: orbi aborted\n", __func__); sbp_targ_remove_orb_info(orbi->login, orbi); - if (orbi->page_table != NULL) { - if (debug) - printf("%s: free orbi->page_table %p\n", - __func__, orbi->page_table); + if (orbi->page_table != NULL) 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; - } 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); - } + } else if (orbi->status.resp == 0) { + if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) sbp_targ_send_status(orbi, ccb); - } else { - if (debug) { - printf("%s: CAM_SEND_STATUS !set %0x\n", - __func__, ccb->ccb_h.flags); - } - ccb->ccb_h.status = CAM_REQ_CMP; - } + ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } else { orbi->status.len = 1; @@ -923,13 +760,6 @@ 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, @@ -948,24 +778,17 @@ /* XXX assume dst_lo + off doesn't overflow */ len = MIN(size, 2048 /* XXX */); size -= len; - orbi->refcount++; - if (ccb_dir == CAM_DIR_OUT) { - if (debug) - printf("%s: CAM_DIR_OUT --> read block in?\n", - __func__); + orbi->refcount ++; + if (ccb_dir == CAM_DIR_OUT) xfer = fwmem_read_block(orbi->fwdev, - (void *)orbi, /*spd*/FWSPD_S400, + (void *)orbi, /*spd*/2, dst_hi, dst_lo + off, len, ptr + off, hand); - } else { - if (debug) - printf("%s: CAM_DIR_IN --> write block out?\n", - __func__); + else xfer = fwmem_write_block(orbi->fwdev, - (void *)orbi, /*spd*/FWSPD_S400, + (void *)orbi, /*spd*/2, dst_hi, dst_lo + off, len, ptr + off, hand); - } if (xfer == NULL) { printf("%s: xfer == NULL", __func__); /* XXX what should we do?? */ @@ -979,24 +802,18 @@ sbp_targ_pt_done(struct fw_xfer *xfer) { struct orb_info *orbi; - struct unrestricted_page_table_fmt *pt; - uint32_t i; + union ccb *ccb; + u_int i, offset, res, len; + uint32_t t1, t2, *p; 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); - orbi->page_table = NULL; free(orbi, M_SBP_TARG); - orbi = NULL; fw_xfer_free(xfer); return; } @@ -1010,166 +827,58 @@ sbp_targ_status_FIFO(orbi, orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); - 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; fw_xfer_free(xfer); return; } - 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); + 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; } - - sbp_targ_xfer_pt(orbi); - - orbi->refcount--; + 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; - /* - * 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); - + 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) 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; } @@ -1192,8 +901,7 @@ struct orb_info *orbi; if (debug) - printf("%s: XPT_CONT_TARGET_IO(0x%08x)\n", - __func__, ccb->csio.tag_id); + printf("%s: XPT_CONT_TARGET_IO\n", __func__); if (status != CAM_REQ_CMP) { ccb->ccb_h.status = status; @@ -1212,12 +920,7 @@ if (debug) printf("%s: ctio aborted\n", __func__); sbp_targ_remove_orb_info(orbi->login, orbi); - if (debug) - printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); - orbi = NULL; - ccb->ccb_h.status = CAM_REQ_ABORTED; - xpt_done(ccb); break; } orbi->state = ORBI_STATUS_CTIO; @@ -1249,30 +952,23 @@ break; } - if (ccb_dir != CAM_DIR_NONE) { + /* 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) 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) { - if (debug) - printf("%s: CAM_SEND_STATUS set %0x\n", - __func__, ccb->ccb_h.flags); + if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) sbp_targ_send_status(orbi, ccb); - } else { - if (debug) - printf("%s: CAM_SEND_STATUS !set %0x\n", - __func__, ccb->ccb_h.flags); - ccb->ccb_h.status = CAM_REQ_CMP; - } + ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } break; @@ -1327,9 +1023,7 @@ cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; - cpi->transport = XPORT_FW; - cpi->hba_misc = PIM_NOINITIATOR - | PIM_NOBUSRESET; + cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE; cpi->hba_eng_cnt = 0; cpi->max_target = 7; /* XXX */ cpi->max_lun = MAX_LUN - 1; @@ -1367,39 +1061,10 @@ xpt_done(ccb); break; } - 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; - } default: - printf("%s: unknown function 0x%x\n", + printf("%s: unknown function %d\n", __func__, ccb->ccb_h.func_code); - ccb->ccb_h.status = CAM_PROVIDE_FAIL; + ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; } @@ -1450,17 +1115,10 @@ } fp = &xfer->recv.hdr; - atio = orbi->atio; - if (orbi->state == ORBI_STATUS_ABORTED) { printf("%s: aborted\n", __func__); sbp_targ_remove_orb_info(orbi->login, orbi); - if (debug) - printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); - orbi = NULL; - atio->ccb_h.status = CAM_REQ_ABORTED; - xpt_done((union ccb*)atio); goto done0; } orbi->state = ORBI_STATUS_ATIO; @@ -1476,21 +1134,21 @@ printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt); } + atio = orbi->atio; atio->ccb_h.target_id = 0; /* XXX */ atio->ccb_h.target_lun = orbi->login->lstate->lun; atio->sense_len = 0; - atio->tag_action = MSG_SIMPLE_TASK; + atio->tag_action = 1; /* XXX */ atio->tag_id = orbi->orb_lo; atio->init_id = orbi->login->id; atio->ccb_h.flags = CAM_TAG_ACTION_VALID; - bytes = (u_char *)&orb[5]; + bytes = (char *)&orb[5]; if (debug) - printf("%s: %p %02x %02x %02x %02x %02x" - " %02x %02x %02x %02x %02x\n", - __func__, (void *)atio, - bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], - bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]); + printf("%s: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + __func__, + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], + bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]); switch (bytes[0] >> 5) { case 0: atio->cdb_len = 6; @@ -1549,25 +1207,8 @@ lstate = sc->lstate[lun]; STAILQ_FOREACH(login, &lstate->logins, link) - if (login->fwdev == fwdev) { - /* - * We are receiving a login from - * an initiator that left and didn't - * logout properly. We need to kill - * the callout before returning the - * login struct to the caller. - * For 7.X and higher, this is not safe - * and will need to be protected by - * a lock. - * For 6.X we are safe as we hold Giant - * and the callout must aquire Giant. - */ - if (!(callout_stop(&login->hold_callout)) && (debug)) - printf("%s:callout in progress for login(%p)\n", - __func__, login); - login->flags |= F_RECYCLE_LOGIN; + if (login->fwdev == fwdev) return (login); - } for (i = 0; i < MAX_LOGINS; i ++) if (sc->logins[i] == NULL) @@ -1583,8 +1224,6 @@ if (login == NULL) { printf("%s: malloc failed\n", __func__); return (NULL); - } else if (debug) { - printf("%s: malloc'd login %p\n", __func__, login); } login->id = i; @@ -1592,9 +1231,7 @@ login->lstate = lstate; login->last_hi = 0xffff; login->last_lo = 0xffffffff; - login->hold_sec = SBP_TARG_HOLD_TIMEOUT; - login->flags |= F_LOGIN ; - login->flags &= ~F_RECYCLE_LOGIN ; + login->hold_sec = 1; STAILQ_INIT(&login->orbs); CALLOUT_INIT(&login->hold_callout); sc->logins[i] = login; @@ -1609,7 +1246,7 @@ struct fw_pkt *fp; uint32_t *orb; struct morb4 *orb4; - struct orb_info *orbi, *aborted_orb = NULL; + struct orb_info *orbi; int i; orbi = (struct orb_info *)xfer->sc; @@ -1633,7 +1270,7 @@ for (i = 0; i < 8; i ++) { orb[i] = ntohl(orb[i]); } - orb4 = (struct morb4 *)&orb; + orb4 = (struct morb4 *)&orb[4]; if (debug) printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]); @@ -1650,10 +1287,11 @@ lun = orb4->id; lstate = orbi->sc->lstate[lun]; - if (lun >= MAX_LUN || lstate == NULL - || (exclusive - && STAILQ_FIRST(&lstate->logins) != NULL - && STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)) { + if (lun >= MAX_LUN || lstate == NULL || + (exclusive && + STAILQ_FIRST(&lstate->logins) != NULL && + STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev) + ) { /* error */ orbi->status.dead = 1; orbi->status.status = STATUS_ACCESS_DENY; @@ -1672,8 +1310,6 @@ break; } - printf("%s: New login(%p), login id=%d\n", - __func__, login, login->id); login->fifo_hi = orb[6]; login->fifo_lo = orb[7]; login->loginres.len = htons(sizeof(uint32_t) * 4); @@ -1682,30 +1318,10 @@ login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id)); login->loginres.recon_hold = htons(login->hold_sec); - 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); - /* - * If this is a new initiator and a login - * was recycled, then it is already in the - * login STAILQ, don't re-insert it. - */ - if (login->flags & F_RECYCLE_LOGIN) { - if (debug) - printf("%s: login(%p) already in STAILQ," - " flags(%0x) no reinsertion needed\n", - __func__, login, login->flags); - /* - * Clear RECYCLE flag - */ - login->flags &= ~F_RECYCLE_LOGIN; - } else { - if (debug) - printf("%s: login(%p) not in STAILQ," - " inserting\n", __func__, login); - STAILQ_INSERT_TAIL(&lstate->logins, login, link); - } - + fwmem_write_block(orbi->fwdev, NULL, /*spd*/2, orb[2], orb[3], + sizeof(struct sbp_login_res), (void *)&login->loginres, + fw_asy_callback_free); + STAILQ_INSERT_TAIL(&lstate->logins, login, link); /* XXX return status after loginres is successfully written */ break; } @@ -1714,7 +1330,6 @@ if (login != NULL && login->fwdev == orbi->fwdev) { login->flags &= ~F_HOLD; callout_stop(&login->hold_callout); - login->flags |= F_LOGIN; printf("%s: reconnected id=%d\n", __func__, login->id); } else { @@ -1732,44 +1347,6 @@ } sbp_targ_dealloc_login(login); break; - case ORB_FUN_ATA: /* TODO */ - /* - * Find the orb to be aborted. - * If we haven't fetched, just drop it on the floor. - * If we have already fetched, - * process normally and don't worry about it. - */ - printf("%s: Abort Task recieved\n", __func__); - login = orbi->sc->logins[orb4->id]; - STAILQ_FOREACH(aborted_orb, &login->orbs, link) { - if (aborted_orb->orb_lo == (orb4->off_lo >> 2)) - sbp_targ_abort(aborted_orb); - else { - panic("%s: orb not found" - " aborted_orb->orb_lo=0x%08x," - " orb4->off_lo(%0x)\n", - __func__, aborted_orb->orb_lo, - (orb4->off_lo >> 2)); - } - } - break; - case ORB_FUN_ATS: /* TODO */ - printf("%s: Abort Task Set recieved for orb\n",__func__ ); - login = orbi->sc->logins[orb4->id]; - STAILQ_FOREACH(aborted_orb, &login->orbs, link) { - if (aborted_orb != NULL) { - printf("%s: aborting orb\n", __func__); - sbp_targ_abort(aborted_orb); - } - } - printf("%s: all orb aborted\n", __func__); - break; - case ORB_FUN_LUR: /* TODO */ - printf("%s: Logical Unit Reset recieved for orb\n",__func__); - break; - case ORB_FUN_RST: /* TODO */ - printf("%s: Target Reset recieved for orb\n", __func__); - break; default: printf("%s: %s not implemented yet\n", __func__, orb_fun_name[orb4->fun]); @@ -1802,10 +1379,7 @@ sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev, (uint16_t)orb0, orb1, orbi->login, FETCH_CMD); done: - if (debug) - printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); - orbi = NULL; fw_xfer_free(xfer); return; } @@ -1818,14 +1392,11 @@ struct orb_info *orbi; if (debug) - printf("%s: fetch orb mode %d, %04x:%08x\n", - __func__, mode, orb_hi, orb_lo); + printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo); orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO); if (orbi == NULL) { printf("%s: malloc failed\n", __func__); return; - } else if (debug) { - printf("%s: malloc'd orbi %p\n", __func__, orbi); } orbi->sc = sc; orbi->fwdev = fwdev; @@ -1834,20 +1405,14 @@ 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: - if (debug) - printf("%s: FETCH_MGM for orbi %p\n", __func__, orbi); - fwmem_read_block(fwdev, (void *)orbi, - /*spd*/FWSPD_S400, orb_hi, orb_lo, - sizeof(uint32_t) * 8, &orbi->orb[0], + fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + sizeof(uint32_t) * 8, &orbi->orb[0], sbp_targ_mgm_handler); break; case FETCH_CMD: - if (debug) - printf("%s: FETCH_CMD for orbi %p\n", __func__, orbi); orbi->state = ORBI_STATUS_FETCH; login->last_hi = orb_hi; login->last_lo = orb_lo; @@ -1866,22 +1431,17 @@ break; } SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle); - fwmem_read_block(fwdev, (void *)orbi, - /*spd*/FWSPD_S400, orb_hi, orb_lo, - sizeof(uint32_t) * 8, &orbi->orb[0], - sbp_targ_cmd_handler); + fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + sizeof(uint32_t) * 8, &orbi->orb[0], + sbp_targ_cmd_handler); STAILQ_INSERT_TAIL(&login->orbs, orbi, link); break; case FETCH_POINTER: - if (debug) - printf("%s: FETCH_POINTER for orbi %p\n", - __func__, orbi); orbi->state = ORBI_STATUS_POINTER; login->flags |= F_LINK_ACTIVE; - fwmem_read_block(fwdev, (void *)orbi, - /*spd*/FWSPD_S400, orb_hi, orb_lo, - sizeof(uint32_t) * 2, &orbi->orb[0], - sbp_targ_pointer_handler); + fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo, + sizeof(uint32_t) * 2, &orbi->orb[0], + sbp_targ_pointer_handler); break; default: printf("%s: invalid mode %d\n", __func__, mode); @@ -1911,13 +1471,11 @@ { struct sbp_targ_login *login; struct sbp_targ_softc *sc; - struct orb_info *unsolicited_orbi; int rtcode = 0; if (login_id < 0 || login_id >= MAX_LOGINS) return(RESP_ADDRESS_ERROR); - printf("%s: made it here\n",__func__); sc = (struct sbp_targ_softc *)xfer->sc; login = sc->logins[login_id]; if (login == NULL) @@ -1931,7 +1489,7 @@ switch (reg) { case 0x08: /* ORB_POINTER */ if (debug) - printf("%s: ORB_POINTER (%d)\n", __func__, login_id); + printf("%s: ORB_POINTER\n", __func__); if ((login->flags & F_LINK_ACTIVE) != 0) { if (debug) printf("link active (ORB_POINTER)\n"); @@ -1944,14 +1502,14 @@ break; case 0x04: /* AGENT_RESET */ if (debug) - printf("%s: AGENT RESET (%d)\n", __func__, login_id); + printf("%s: AGENT RESET\n", __func__); login->last_hi = 0xffff; login->last_lo = 0xffffffff; sbp_targ_abort(STAILQ_FIRST(&login->orbs)); break; case 0x10: /* DOORBELL */ if (debug) - printf("%s: DOORBELL (%d)\n", __func__, login_id); + printf("%s: DOORBELL\n", __func__); if (login->last_hi == 0xffff && login->last_lo == 0xffffffff) { printf("%s: no previous pointer(DOORBELL)\n", @@ -1968,58 +1526,19 @@ login, FETCH_POINTER); break; case 0x00: /* AGENT_STATE */ - printf("%s: AGENT_STATE (%d)\n", __func__, login_id); - sbp_targ_send_agent_state(xfer); + printf("%s: AGENT_STATE (ignore)\n", __func__); break; case 0x14: /* UNSOLICITED_STATE_ENABLE */ - printf("%s: UNSOLICITED_STATE_ENABLE (%d)\n", - __func__, login_id); - unsolicited_orbi = malloc(sizeof(struct orb_info), - M_SBP_TARG, - M_NOWAIT | M_ZERO); - unsolicited_orbi->fwdev = login->fwdev; - unsolicited_orbi->status.src = SRC_UNSOL; - unsolicited_orbi->status.resp = SBP_REQ_CMP; - sbp_targ_status_FIFO(unsolicited_orbi, - login->fifo_hi, - login->fifo_lo, - /*No dequeue*/0); + printf("%s: UNSOLICITED_STATE_ENABLE (ignore)\n", __func__); break; default: - printf("%s: invalid register %d(%d)\n", - __func__, reg, login_id); + printf("%s: invalid register %d\n", __func__, reg); rtcode = RESP_ADDRESS_ERROR; } return (rtcode); } -static void -sbp_targ_send_agent_state(struct fw_xfer *xfer) -{ - struct agent_state *current_state; - struct fw_pkt *rfp; /* response to request --> from target */ - - xfer->send.payload = malloc(sizeof(struct agent_state), - M_SBP_TARG, - M_NOWAIT | M_ZERO); - xfer->send.pay_len = ntohs(sizeof(struct agent_state)); - xfer->send.spd = FWSPD_S400; - - current_state = (struct agent_state *)xfer->send.payload; - current_state->fetch_agent_state = AGENT_STATE_ACTIVE; - - rfp = &xfer->recv.hdr; - rfp->mode.rresb.tcode = FWTCODE_RRESB; - rfp->mode.rresb.rtcode = 0; - rfp->mode.rresb.extcode = 0; - xfer->send.hdr.mode.hdr.dst = ntohs(rfp->mode.hdr.src); - xfer->hand = fw_xfer_free_buf; - rfp->mode.hdr.pri = 0; - fw_asyreq(xfer->fc, -1, xfer); - -} - static int sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev) { @@ -2048,7 +1567,7 @@ { struct fw_pkt *fp, *sfp; struct fw_device *fwdev; - uint32_t lo = 0; + uint32_t lo; int s, rtcode; struct sbp_targ_softc *sc; @@ -2060,22 +1579,22 @@ printf("%s: cannot resolve nodeid=%d\n", __func__, fp->mode.wreqb.src & 0x3f); rtcode = RESP_TYPE_ERROR; /* XXX */ - } else { - lo = fp->mode.wreqb.dest_lo; - if (lo == SBP_TARG_BIND_LO(-1)) - rtcode = sbp_targ_mgm(xfer, fwdev); - else if (lo >= SBP_TARG_BIND_LO(0)) - rtcode = sbp_targ_cmd(xfer, fwdev, - SBP_TARG_LOGIN_ID(lo), - lo % 0x20); - else - rtcode = RESP_ADDRESS_ERROR; + goto done; } + lo = fp->mode.wreqb.dest_lo; + if (lo == SBP_TARG_BIND_LO(-1)) + rtcode = sbp_targ_mgm(xfer, fwdev); + else if (lo >= SBP_TARG_BIND_LO(0)) + rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo), + lo % 0x20); + else + rtcode = RESP_ADDRESS_ERROR; +done: if (rtcode != 0) - printf("%s: rtcode = %d lo == 0x%x\n", __func__, rtcode, lo); + printf("%s: rtcode = %d\n", __func__, rtcode); sfp = &xfer->send.hdr; - xfer->send.spd = FWSPD_S400; + xfer->send.spd = 2; /* XXX */ xfer->hand = sbp_targ_resp_callback; sfp->mode.wres.dst = fp->mode.wreqb.src; sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt; @@ -2096,8 +1615,6 @@ sc = (struct sbp_targ_softc *) device_get_softc(dev); bzero((void *)sc, sizeof(struct sbp_targ_softc)); - - sc->fd.fc = device_get_ivars(dev); sc->fd.dev = dev; sc->fd.post_explore = (void *) sbp_targ_post_explore; @@ -2133,23 +1650,6 @@ /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */, sc->fd.fc, (void *)sc, sbp_targ_recv); fw_bindadd(sc->fd.fc, &sc->fwb); - /* - * setup CSR for BUSY_TIMEOUT from - * initiator(0x210) - */ - fwcsr_busy_timeout_init(&sc->busy_timeout, &sc->fd, sc, - M_SBP_TARG, 0, - SBP_TARG_RECV_LEN, - MAX_LUN); -#if 0 - sc->busy_timeout.start = 0xfffff0000000 | BUSY_TIMEOUT; - sc->busy_timeout.end = 0xfffff0000000 | BUSY_TIMEOUT; - STAILQ_INIT(&sc->busy_timeout.xferlist); - fw_xferlist_add(&sc->busy_timeout.xferlist, M_SBP_TARG, - /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */, - sc->fd.fc, (void *)sc, sbp_targ_busy_timeout); - fw_bindadd(sc->fd.fc, &sc->busy_timeout); -#endif return 0; fail: @@ -2175,30 +1675,17 @@ lstate = sc->lstate[i]; if (lstate != NULL) { xpt_free_path(lstate->path); - if (debug) { - printf("%s: lstate free %p\n", - __func__, lstate); - } free(lstate, M_SBP_TARG); - lstate = NULL; } } if (sc->black_hole != NULL) { xpt_free_path(sc->black_hole->path); - if (debug) { - printf("%s: free blackhole? %p\n", - __func__, sc->black_hole); - } free(sc->black_hole, M_SBP_TARG); - sc->black_hole = NULL; } fw_bindremove(sc->fd.fc, &sc->fwb); fw_xferlist_remove(&sc->fwb.xferlist); - fw_bindremove(sc->fd.fc, &sc->busy_timeout); - fwcsr_busy_timeout_stop(&sc->busy_timeout, &sc->fd); - return 0; } Index: firewire.c =================================================================== --- firewire.c (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ firewire.c (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -285,7 +285,7 @@ return; } #endif - microuptime(&xfer->tv); + microtime(&xfer->tv); s = splfw(); xfer->state = FWXF_INQ; STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link); @@ -315,51 +315,40 @@ { struct fw_xfer *xfer; struct timeval tv; - struct timeval now; struct timeval split_timeout; int i, s; split_timeout.tv_sec = 0; split_timeout.tv_usec = 200 * 1000; /* 200 msec */ - microuptime(&tv); - if (timevalcmp(&split_timeout, &tv, >)) { - /* we haven't been awake long enough, come back later */ - } else { - now.tv_sec = tv.tv_sec; - now.tv_usec = tv.tv_usec; - timevalsub(&tv, &split_timeout); + microtime(&tv); + timevalsub(&tv, &split_timeout); - s = splfw(); - for (i = 0; i < 0x40; i ++) { - while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { - if (timevalcmp(&xfer->tv, &tv, >)) - /* the rests are newer than this */ - break; - if (xfer->state == FWXF_START) - /* not sent yet */ - break; - device_printf(fc->bdev, - "split transaction timeout dst=0x%x tl=0x%x state=%d\n" - "xfer->tv(%ld,%ld) tv(%ld,%ld), now(%ld,%ld)\n", - xfer->send.hdr.mode.hdr.dst, i, xfer->state, - xfer->tv.tv_sec, xfer->tv.tv_usec, - tv.tv_sec, tv.tv_usec, - now.tv_sec, now.tv_usec); - xfer->resp = ETIMEDOUT; - fw_xfer_done(xfer); - } + s = splfw(); + for (i = 0; i < 0x40; i ++) { + while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { + if (timevalcmp(&xfer->tv, &tv, >)) + /* the rests are newer than this */ + break; + if (xfer->state == FWXF_START) + /* not sent yet */ + break; + device_printf(fc->bdev, + "split transaction timeout dst=0x%x tl=0x%x state=%d\n", + xfer->send.hdr.mode.hdr.dst, i, xfer->state); + xfer->resp = ETIMEDOUT; + fw_xfer_done(xfer); } - splx(s); } + splx(s); } -#define WATCHDOG_HZ 10 +#define WATCHDOC_HZ 10 static void firewire_watchdog(void *arg) { struct firewire_comm *fc; - static int watchdog_clock = 0; + static int watchdoc_clock = 0; fc = (struct firewire_comm *)arg; @@ -368,13 +357,13 @@ * We encounter a timeout easily. To avoid this, * ignore clock interrupt for a while. */ - if (watchdog_clock > WATCHDOG_HZ * 15) { + if (watchdoc_clock > WATCHDOC_HZ * 15) { firewire_xfer_timeout(fc); fc->timeout(fc); } else - watchdog_clock ++; + watchdoc_clock ++; - callout_reset(&fc->timeout_callout, hz / WATCHDOG_HZ, + callout_reset(&fc->timeout_callout, hz / WATCHDOC_HZ, (void *)firewire_watchdog, (void *)fc); } @@ -638,7 +627,7 @@ crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project"); crom_add_entry(root, CSRKEY_HW, __DragonFly_cc_version); #else - crom_add_simple_text(src, root, &buf->vendor, "Miralink"); + crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project"); crom_add_entry(root, CSRKEY_HW, __FreeBSD_version); #endif crom_add_simple_text(src, root, &buf->hw, hostname); Index: sbp.c =================================================================== --- sbp.c (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ sbp.c (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -2523,24 +2523,15 @@ 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_SPI; /* 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; SBP_DEBUG(1) printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", device_get_nameunit(sbp->fd.dev), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); END_DEBUG + /* Enable disconnect and tagged queuing */ + cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; + cts->flags = CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB; + cts->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; Index: sbp.h =================================================================== --- sbp.h (.../miralink.FreeBSD.6/src/sys/dev/firewire) (revision 5436) +++ sbp.h (.../FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire) (revision 5436) @@ -103,18 +103,12 @@ uint32_t orb_lo; uint32_t data[6]; }; -/* - * Values for src - * From sbp-2 5.3 - */ +/* src */ #define SRC_NEXT_EXISTS 0 #define SRC_NO_NEXT 1 #define SRC_UNSOL 2 -/* - * Values for resp. - * From sbp-2 5.3 - */ +/* resp */ #define SBP_REQ_CMP 0 /* request complete */ #define SBP_TRANS_FAIL 1 /* transport failure */ #define SBP_ILLE_REQ 2 /* illegal request */ --------------040806030102050805070300--