diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/ata/ata_all.c /storage/p4/scottl-camlock/src/sys/cam/ata/ata_all.c --- /storage/FreeBSD/head/sys/cam/ata/ata_all.c 2009-09-28 01:21:58.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/ata/ata_all.c 2009-10-14 15:26:15.000000000 +0300 @@ -98,6 +98,11 @@ ata_28bit_cmd(struct ccb_ataio *ataio, u { bzero(&ataio->cmd, sizeof(ataio->cmd)); ataio->cmd.flags = 0; + if (cmd == ATA_READ_DMA || + cmd == ATA_READ_DMA_QUEUED || + cmd == ATA_WRITE_DMA || + cmd == ATA_WRITE_DMA_QUEUED) + ataio->cmd.flags |= CAM_ATAIO_DMA; ataio->cmd.command = cmd; ataio->cmd.features = features; ataio->cmd.lba_low = lba; @@ -113,6 +118,11 @@ ata_48bit_cmd(struct ccb_ataio *ataio, u { bzero(&ataio->cmd, sizeof(ataio->cmd)); ataio->cmd.flags = CAM_ATAIO_48BIT; + if (cmd == ATA_READ_DMA48 || + cmd == ATA_READ_DMA_QUEUED48 || + cmd == ATA_WRITE_DMA48 || + cmd == ATA_WRITE_DMA_QUEUED48) + ataio->cmd.flags |= CAM_ATAIO_DMA; ataio->cmd.command = cmd; ataio->cmd.features = features; ataio->cmd.lba_low = lba; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/ata/ata_all.h /storage/p4/scottl-camlock/src/sys/cam/ata/ata_all.h --- /storage/FreeBSD/head/sys/cam/ata/ata_all.h 2009-08-30 19:31:23.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/ata/ata_all.h 2009-10-14 15:26:15.000000000 +0300 @@ -41,6 +41,7 @@ struct ata_cmd { #define CAM_ATAIO_FPDMA 0x02 /* FPDMA command */ #define CAM_ATAIO_CONTROL 0x04 /* Control, not a command */ #define CAM_ATAIO_NEEDRESULT 0x08 /* Request requires result. */ +#define CAM_ATAIO_DMA 0x10 /* DMA command */ u_int8_t command; u_int8_t features; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/ata/ata_da.c /storage/p4/scottl-camlock/src/sys/cam/ata/ata_da.c --- /storage/FreeBSD/head/sys/cam/ata/ata_da.c 2009-10-21 17:20:55.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/ata/ata_da.c 2009-10-22 10:32:59.000000000 +0300 @@ -270,7 +270,7 @@ adaclose(struct disk *dp) /* We only sync the cache if the drive is capable of it. */ if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { - ccb = cam_periph_getccb(periph, /*priority*/1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); cam_fill_ataio(&ccb->ataio, 1, adadone, @@ -343,7 +343,7 @@ adastrategy(struct bio *bp) /* * Schedule ourselves for performing the work. */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); cam_periph_unlock(periph); return; @@ -377,7 +377,7 @@ adadump(void *arg, void *virtual, vm_off if (length > 0) { periph->flags |= CAM_PERIPH_POLLED; - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.ccb_h.ccb_state = ADA_CCB_DUMP; cam_fill_ataio(&ccb.ataio, 0, @@ -408,7 +408,7 @@ adadump(void *arg, void *virtual, vm_off } if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.ccb_h.ccb_state = ADA_CCB_DUMP; cam_fill_ataio(&ccb.ataio, @@ -563,7 +563,7 @@ adaasync(void *callback_arg, u_int32_t c */ softc->state = ADA_STATE_SET_MULTI; cam_periph_acquire(periph); - xpt_schedule(periph, 0); + xpt_schedule(periph, CAM_PRIORITY_DEV); break; } default: @@ -665,7 +665,7 @@ adaregister(struct cam_periph *periph, v /* Check if the SIM does not want queued commands */ bzero(&cpi, sizeof(cpi)); - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); if (cpi.ccb_h.status != CAM_REQ_CMP || @@ -743,7 +743,7 @@ adaregister(struct cam_periph *periph, v * the end of probe. */ cam_periph_acquire(periph); - xpt_schedule(periph, /*priority*/5); + xpt_schedule(periph, CAM_PRIORITY_DEV); /* * Schedule a periodic event to occasionally send an @@ -897,7 +897,7 @@ adastart(struct cam_periph *periph, unio if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } break; } @@ -1027,7 +1027,7 @@ adadone(struct cam_periph *periph, union xpt_release_ccb(done_ccb); if (bioq_first(&softc->bio_queue) != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, 1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } cam_periph_release_locked(periph); return; @@ -1127,6 +1127,9 @@ adashutdown(void * arg, int howto) TAILQ_FOREACH(periph, &adadriver.units, unit_links) { union ccb ccb; + /* If we paniced with lock held - not recurse here. */ + if (cam_periph_owned(periph)) + continue; cam_periph_lock(periph); softc = (struct ada_softc *)periph->softc; /* @@ -1139,7 +1142,7 @@ adashutdown(void * arg, int howto) continue; } - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.ccb_h.ccb_state = ADA_CCB_DUMP; cam_fill_ataio(&ccb.ataio, diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/ata/ata_pmp.c /storage/p4/scottl-camlock/src/sys/cam/ata/ata_pmp.c --- /storage/FreeBSD/head/sys/cam/ata/ata_pmp.c 1970-01-01 03:00:00.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/ata/ata_pmp.c 2009-10-16 22:05:30.000000000 +0300 @@ -0,0 +1,735 @@ +/*- + * Copyright (c) 2009 Alexander Motin + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + * 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. + */ + +#include +__FBSDID("$FreeBSD: src/sys/cam/ata/ata_da.c,v 1.1 2009/07/10 08:18:08 scottl Exp $"); + +#include + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* _KERNEL */ + +#ifndef _KERNEL +#include +#include +#endif /* _KERNEL */ + +#include +#include +#include +#include +#include + +#include + +#ifdef _KERNEL + +typedef enum { + PMP_STATE_NORMAL, + PMP_STATE_PORTS, + PMP_STATE_CONFIG, + PMP_STATE_RESET, + PMP_STATE_CONNECT, + PMP_STATE_CHECK, + PMP_STATE_CLEAR, + PMP_STATE_SCAN +} pmp_state; + +typedef enum { + PMP_FLAG_SCTX_INIT = 0x200 +} pmp_flags; + +typedef enum { + PMP_CCB_PROBE = 0x01, +} pmp_ccb_state; + +/* Offsets into our private area for storing information */ +#define ccb_state ppriv_field0 +#define ccb_bp ppriv_ptr1 + +struct pmp_softc { + SLIST_ENTRY(pmp_softc) links; + pmp_state state; + pmp_flags flags; + uint32_t pm_pid; + uint32_t pm_prv; + int pm_ports; + int pm_step; + int pm_try; + int found; + int frozen; + union ccb saved_ccb; + struct task sysctl_task; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; +}; + +static periph_init_t pmpinit; +static void pmpasync(void *callback_arg, u_int32_t code, + struct cam_path *path, void *arg); +static void pmpsysctlinit(void *context, int pending); +static periph_ctor_t pmpregister; +static periph_dtor_t pmpcleanup; +static periph_start_t pmpstart; +static periph_oninv_t pmponinvalidate; +static void pmpdone(struct cam_periph *periph, + union ccb *done_ccb); + +#ifndef PMP_DEFAULT_TIMEOUT +#define PMP_DEFAULT_TIMEOUT 30 /* Timeout in seconds */ +#endif + +#ifndef PMP_DEFAULT_RETRY +#define PMP_DEFAULT_RETRY 1 +#endif + +static int pmp_retry_count = PMP_DEFAULT_RETRY; +static int pmp_default_timeout = PMP_DEFAULT_TIMEOUT; + +SYSCTL_NODE(_kern_cam, OID_AUTO, pmp, CTLFLAG_RD, 0, + "CAM Direct Access Disk driver"); +SYSCTL_INT(_kern_cam_pmp, OID_AUTO, retry_count, CTLFLAG_RW, + &pmp_retry_count, 0, "Normal I/O retry count"); +TUNABLE_INT("kern.cam.pmp.retry_count", &pmp_retry_count); +SYSCTL_INT(_kern_cam_pmp, OID_AUTO, default_timeout, CTLFLAG_RW, + &pmp_default_timeout, 0, "Normal I/O timeout (in seconds)"); +TUNABLE_INT("kern.cam.pmp.default_timeout", &pmp_default_timeout); + +static struct periph_driver pmpdriver = +{ + pmpinit, "pmp", + TAILQ_HEAD_INITIALIZER(pmpdriver.units), /* generation */ 0 +}; + +PERIPHDRIVER_DECLARE(pmp, pmpdriver); + +MALLOC_DEFINE(M_ATPMP, "ata_pmp", "ata_pmp buffers"); + +static void +pmpinit(void) +{ + cam_status status; + + /* + * Install a global async callback. This callback will + * receive async callbacks like "new device found". + */ + status = xpt_register_async(AC_FOUND_DEVICE, pmpasync, NULL, NULL); + + if (status != CAM_REQ_CMP) { + printf("pmp: Failed to attach master async callback " + "due to status 0x%x!\n", status); + } +} + +static void +pmpfreeze(struct cam_periph *periph, int mask) +{ + struct pmp_softc *softc = (struct pmp_softc *)periph->softc; + struct cam_path *dpath; + int i; + + mask &= ~softc->frozen; + for (i = 0; i < 15; i++) { + if ((mask & (1 << i)) == 0) + continue; + if (xpt_create_path(&dpath, periph, + xpt_path_path_id(periph->path), + i, 0) == CAM_REQ_CMP) { +printf("PMP freeze: %d\n", i); + softc->frozen |= (1 << i); + cam_freeze_devq(dpath); + xpt_free_path(dpath); + } + } +} + +static void +pmprelease(struct cam_periph *periph, int mask) +{ + struct pmp_softc *softc = (struct pmp_softc *)periph->softc; + struct cam_path *dpath; + int i; + + mask &= softc->frozen; + for (i = 0; i < 15; i++) { + if ((mask & (1 << i)) == 0) + continue; + if (xpt_create_path(&dpath, periph, + xpt_path_path_id(periph->path), + i, 0) == CAM_REQ_CMP) { +printf("PMP release: %d\n", i); + softc->frozen &= ~(1 << i); + cam_release_devq(dpath, 0, 0, 0, FALSE); + xpt_free_path(dpath); + } + } +} + +static void +pmponinvalidate(struct cam_periph *periph) +{ + struct pmp_softc *softc; + struct cam_path *dpath; + int i; + + softc = (struct pmp_softc *)periph->softc; + + /* + * De-register any async callbacks. + */ + xpt_register_async(0, pmpasync, periph, periph->path); + + for (i = 0; i < 15; i++) { + if (xpt_create_path(&dpath, periph, + xpt_path_path_id(periph->path), + i, 0) == CAM_REQ_CMP) { + xpt_async(AC_LOST_DEVICE, dpath, NULL); + xpt_free_path(dpath); + } + } + xpt_print(periph->path, "lost device\n"); +} + +static void +pmpcleanup(struct cam_periph *periph) +{ + struct pmp_softc *softc; + + softc = (struct pmp_softc *)periph->softc; + + xpt_print(periph->path, "removing device entry\n"); + cam_periph_unlock(periph); + + /* + * If we can't free the sysctl tree, oh well... + */ + if ((softc->flags & PMP_FLAG_SCTX_INIT) != 0 + && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { + xpt_print(periph->path, "can't remove sysctl context\n"); + } + + free(softc, M_DEVBUF); + cam_periph_lock(periph); +} + +static void +pmpasync(void *callback_arg, u_int32_t code, + struct cam_path *path, void *arg) +{ + struct cam_periph *periph; + struct pmp_softc *softc; + + periph = (struct cam_periph *)callback_arg; + switch (code) { + case AC_FOUND_DEVICE: + { + struct ccb_getdev *cgd; + cam_status status; + + cgd = (struct ccb_getdev *)arg; + if (cgd == NULL) + break; + + if (cgd->protocol != PROTO_SATAPM) + break; + + /* + * Allocate a peripheral instance for + * this device and start the probe + * process. + */ + status = cam_periph_alloc(pmpregister, pmponinvalidate, + pmpcleanup, pmpstart, + "pmp", CAM_PERIPH_BIO, + cgd->ccb_h.path, pmpasync, + AC_FOUND_DEVICE, cgd); + + if (status != CAM_REQ_CMP + && status != CAM_REQ_INPROG) + printf("pmpasync: Unable to attach to new device " + "due to status 0x%x\n", status); + break; + } + case AC_SCSI_AEN: + case AC_SENT_BDR: + case AC_BUS_RESET: + softc = (struct pmp_softc *)periph->softc; + cam_periph_async(periph, code, path, arg); + if (softc->state != PMP_STATE_NORMAL) + break; + pmpfreeze(periph, softc->found); + if (code == AC_SENT_BDR || code == AC_BUS_RESET) + softc->found = 0; /* We have to reset everything. */ + softc->state = PMP_STATE_PORTS; + cam_periph_acquire(periph); + xpt_schedule(periph, CAM_PRIORITY_BUS); + break; + default: + cam_periph_async(periph, code, path, arg); + break; + } +} + +static void +pmpsysctlinit(void *context, int pending) +{ + struct cam_periph *periph; + struct pmp_softc *softc; + char tmpstr[80], tmpstr2[80]; + + periph = (struct cam_periph *)context; + if (cam_periph_acquire(periph) != CAM_REQ_CMP) + return; + + softc = (struct pmp_softc *)periph->softc; + snprintf(tmpstr, sizeof(tmpstr), "CAM PMP unit %d", periph->unit_number); + snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); + + sysctl_ctx_init(&softc->sysctl_ctx); + softc->flags |= PMP_FLAG_SCTX_INIT; + softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_kern_cam_pmp), OID_AUTO, tmpstr2, + CTLFLAG_RD, 0, tmpstr); + if (softc->sysctl_tree == NULL) { + printf("pmpsysctlinit: unable to allocate sysctl tree\n"); + cam_periph_release(periph); + return; + } + + cam_periph_release(periph); +} + +static cam_status +pmpregister(struct cam_periph *periph, void *arg) +{ + struct pmp_softc *softc; + struct ccb_pathinq cpi; + struct ccb_getdev *cgd; + + cgd = (struct ccb_getdev *)arg; + if (periph == NULL) { + printf("pmpregister: periph was NULL!!\n"); + return(CAM_REQ_CMP_ERR); + } + + if (cgd == NULL) { + printf("pmpregister: no getdev CCB, can't register device\n"); + return(CAM_REQ_CMP_ERR); + } + + softc = (struct pmp_softc *)malloc(sizeof(*softc), M_DEVBUF, + M_NOWAIT|M_ZERO); + + if (softc == NULL) { + printf("pmpregister: Unable to probe new device. " + "Unable to allocate softc\n"); + return(CAM_REQ_CMP_ERR); + } + periph->softc = softc; + + softc->state = PMP_STATE_PORTS; + softc->pm_pid = ((uint32_t *)&cgd->ident_data)[0]; + softc->pm_prv = ((uint32_t *)&cgd->ident_data)[1]; + + /* Check if the SIM does not want queued commands */ + bzero(&cpi, sizeof(cpi)); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); + cpi.ccb_h.func_code = XPT_PATH_INQ; + xpt_action((union ccb *)&cpi); + + TASK_INIT(&softc->sysctl_task, 0, pmpsysctlinit, periph); + + xpt_announce_periph(periph, NULL); + + /* + * Add async callbacks for bus reset and + * bus device reset calls. I don't bother + * checking if this fails as, in most cases, + * the system will function just fine without + * them and the only alternative would be to + * not attach the device on failure. + */ + xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | + AC_SCSI_AEN, pmpasync, periph, periph->path); + + /* + * Take an exclusive refcount on the periph while pmpstart is called + * to finish the probe. The reference will be dropped in pmpdone at + * the end of probe. + */ + (void)cam_periph_acquire(periph); + xpt_schedule(periph, CAM_PRIORITY_BUS); + + return(CAM_REQ_CMP); +} + +static void +pmpstart(struct cam_periph *periph, union ccb *start_ccb) +{ + struct ccb_ataio *ataio; + struct pmp_softc *softc; + + softc = (struct pmp_softc *)periph->softc; + ataio = &start_ccb->ataio; + + switch (softc->state) { + case PMP_STATE_PORTS: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_read_cmd(ataio, 2, 15); + break; + case PMP_STATE_CONFIG: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_write_cmd(ataio, 0x60, 15, 0xf); + break; + case PMP_STATE_RESET: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_write_cmd(ataio, 2, softc->pm_step, + (softc->found & (1 << softc->pm_step)) ? 0 : 1); +printf("PM RESET %d%s\n", softc->pm_step, + (softc->found & (1 << softc->pm_step)) ? " skipping" : ""); + break; + case PMP_STATE_CONNECT: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_write_cmd(ataio, 2, softc->pm_step, 0); + break; + case PMP_STATE_CHECK: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_read_cmd(ataio, 0, softc->pm_step); + break; + case PMP_STATE_CLEAR: + cam_fill_ataio(ataio, + pmp_retry_count, + pmpdone, + /*flags*/CAM_DIR_NONE, + 0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + pmp_default_timeout * 1000); + ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF); + break; + default: + break; + } + xpt_action(start_ccb); +} + +static void +pmpdone(struct cam_periph *periph, union ccb *done_ccb) +{ + struct pmp_softc *softc; + struct ccb_ataio *ataio; + union ccb *work_ccb; + struct cam_path *path, *dpath; + u_int32_t priority; + + softc = (struct pmp_softc *)periph->softc; + ataio = &done_ccb->ataio; + + CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("pmpdone\n")); + + path = done_ccb->ccb_h.path; + priority = done_ccb->ccb_h.pinfo.priority; + + switch (softc->state) { + case PMP_STATE_PORTS: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->pm_ports = (done_ccb->ataio.res.lba_high << 24) + + (done_ccb->ataio.res.lba_mid << 16) + + (done_ccb->ataio.res.lba_low << 8) + + done_ccb->ataio.res.sector_count; + /* This PM declares 6 ports, while only 5 of them are real. + * Port 5 is enclosure management bridge port, which has implementation + * problems, causing probe faults. Hide it for now. */ + if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6) + softc->pm_ports = 5; + /* This PM declares 7 ports, while only 5 of them are real. + * Port 5 is some fake "Config Disk" with 640 sectors size, + * port 6 is enclosure management bridge port. + * Both fake ports has implementation problems, causing + * probe faults. Hide them for now. */ + if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7) + softc->pm_ports = 5; + printf("PM ports: %d\n", softc->pm_ports); + softc->state = PMP_STATE_CONFIG; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_CONFIG: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->pm_step = 0; + softc->state = PMP_STATE_RESET; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_RESET: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->pm_step++; + if (softc->pm_step < softc->pm_ports) { + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else { + softc->pm_step = 0; + DELAY(5000); + printf("PM reset done\n"); + softc->state = PMP_STATE_CONNECT; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_CONNECT: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->pm_step++; + if (softc->pm_step < softc->pm_ports) { + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else { + softc->pm_step = 0; + softc->pm_try = 0; + printf("PM connect done\n"); + softc->state = PMP_STATE_CHECK; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_CHECK: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + int res = (done_ccb->ataio.res.lba_high << 24) + + (done_ccb->ataio.res.lba_mid << 16) + + (done_ccb->ataio.res.lba_low << 8) + + done_ccb->ataio.res.sector_count; + if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) { + printf("PM status: %d - %08x\n", softc->pm_step, res); + softc->found |= (1 << softc->pm_step); + softc->pm_step++; + } else { + if (softc->pm_try < 100) { + DELAY(10000); + softc->pm_try++; + } else { + printf("PM status: %d - %08x\n", softc->pm_step, res); + softc->found &= ~(1 << softc->pm_step); + if (xpt_create_path(&dpath, periph, + done_ccb->ccb_h.path_id, + softc->pm_step, 0) == CAM_REQ_CMP) { + xpt_async(AC_LOST_DEVICE, dpath, NULL); + xpt_free_path(dpath); + } + softc->pm_step++; + } + } + if (softc->pm_step < softc->pm_ports) { + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else { + softc->pm_step = 0; + softc->state = PMP_STATE_CLEAR; + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_CLEAR: + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + softc->pm_step++; + if (softc->pm_step < softc->pm_ports) { + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } else if (softc->found) { + softc->pm_step = 0; + softc->state = PMP_STATE_SCAN; + work_ccb = xpt_alloc_ccb_nowait(); + if (work_ccb != NULL) + goto do_scan; + xpt_release_ccb(done_ccb); + } + break; + } else if (cam_periph_error(done_ccb, 0, 0, + &softc->saved_ccb) == ERESTART) { + return; + } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + xpt_release_ccb(done_ccb); + break; + case PMP_STATE_SCAN: + work_ccb = done_ccb; + done_ccb = (union ccb*)work_ccb->ccb_h.ppriv_ptr0; + /* Free the current request path- we're done with it. */ + xpt_free_path(work_ccb->ccb_h.path); + softc->pm_step++; +do_scan: + while (softc->pm_step < softc->pm_ports && + (softc->found & (1 << softc->pm_step)) == 0) { + softc->pm_step++; + } + if (softc->pm_step >= softc->pm_ports) { + xpt_free_ccb(work_ccb); + xpt_release_ccb(done_ccb); + break; + } + if (xpt_create_path(&dpath, periph, + done_ccb->ccb_h.path_id, + softc->pm_step, 0) != CAM_REQ_CMP) { + printf("pmpdone: xpt_create_path failed" + ", bus scan halted\n"); + xpt_free_ccb(work_ccb); + xpt_release_ccb(done_ccb); + break; + } + xpt_setup_ccb(&work_ccb->ccb_h, dpath, + done_ccb->ccb_h.pinfo.priority); + work_ccb->ccb_h.func_code = XPT_SCAN_LUN; + work_ccb->ccb_h.cbfcnp = pmpdone; + work_ccb->ccb_h.ppriv_ptr0 = done_ccb; + work_ccb->crcn.flags = done_ccb->crcn.flags; + xpt_action(work_ccb); + pmprelease(periph, 1 << softc->pm_step); + return; + default: + break; + } + softc->state = PMP_STATE_NORMAL; + pmprelease(periph, -1); + cam_periph_release_locked(periph); +} + +#endif /* _KERNEL */ diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/ata/ata_xpt.c /storage/p4/scottl-camlock/src/sys/cam/ata/ata_xpt.c --- /storage/FreeBSD/head/sys/cam/ata/ata_xpt.c 2009-10-21 18:27:48.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/ata/ata_xpt.c 2009-10-22 10:32:59.000000000 +0300 @@ -96,11 +96,6 @@ typedef enum { PROBE_FULL_INQUIRY, PROBE_PM_PID, PROBE_PM_PRV, - PROBE_PM_PORTS, - PROBE_PM_RESET, - PROBE_PM_CONNECT, - PROBE_PM_CHECK, - PROBE_PM_CLEAR, PROBE_INVALID } probe_action; @@ -112,11 +107,6 @@ static char *probe_action_text[] = { "PROBE_FULL_INQUIRY", "PROBE_PM_PID", "PROBE_PM_PRV", - "PROBE_PM_PORTS", - "PROBE_PM_RESET", - "PROBE_PM_CONNECT", - "PROBE_PM_CHECK", - "PROBE_PM_CLEAR", "PROBE_INVALID" }; @@ -142,9 +132,6 @@ typedef struct { u_int8_t digest[16]; uint32_t pm_pid; uint32_t pm_prv; - int pm_ports; - int pm_step; - int pm_try; struct cam_periph *periph; } probe_softc; @@ -192,10 +179,12 @@ static void ata_dev_async(u_int32_t asy struct cam_ed *device, void *async_arg); static void ata_action(union ccb *start_ccb); +static void ata_done(union ccb *done_ccb); static struct xpt_xport ata_xport = { .alloc_device = ata_alloc_device, .action = ata_action, + .done = ata_done, .async = ata_dev_async, }; @@ -270,14 +259,13 @@ probeschedule(struct cam_periph *periph) softc = (probe_softc *)periph->softc; ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); - if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) + if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) || + periph->path->device->protocol == PROTO_SATAPM) PROBE_SET_ACTION(softc, PROBE_RESET); - else if (periph->path->device->protocol == PROTO_SATAPM) - PROBE_SET_ACTION(softc, PROBE_PM_PID); else PROBE_SET_ACTION(softc, PROBE_IDENTIFY); @@ -286,7 +274,7 @@ probeschedule(struct cam_periph *periph) else softc->flags &= ~PROBE_NO_ANNOUNCE; - xpt_schedule(periph, ccb->ccb_h.pinfo.priority); + xpt_schedule(periph, CAM_PRIORITY_HOST); } static void @@ -295,7 +283,6 @@ probestart(struct cam_periph *periph, un /* Probe the device that our peripheral driver points to */ struct ccb_ataio *ataio; struct ccb_scsiio *csio; - struct ccb_trans_settings cts; probe_softc *softc; CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); @@ -306,21 +293,11 @@ probestart(struct cam_periph *periph, un switch (softc->action) { case PROBE_RESET: - if (start_ccb->ccb_h.target_id == 15) { - /* Report SIM that we have no knowledge about PM presence. */ - bzero(&cts, sizeof(cts)); - xpt_setup_ccb(&cts.ccb_h, start_ccb->ccb_h.path, 1); - cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - cts.xport_specific.sata.pm_present = 0; - cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; - xpt_action((union ccb *)&cts); - } cam_fill_ataio(ataio, 0, probedone, /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, + 0, /*data_ptr*/NULL, /*dxfer_len*/0, (start_ccb->ccb_h.target_id == 15 ? 3 : 15) * 1000); @@ -351,7 +328,7 @@ probestart(struct cam_periph *periph, un 1, probedone, /*flags*/CAM_DIR_IN, - MSG_SIMPLE_Q_TAG, + 0, /*data_ptr*/(u_int8_t *)ident_buf, /*dxfer_len*/sizeof(struct ata_params), 30 * 1000); @@ -413,7 +390,7 @@ probestart(struct cam_periph *periph, un 1, probedone, /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, + 0, /*data_ptr*/NULL, /*dxfer_len*/0, 10 * 1000); @@ -424,74 +401,12 @@ probestart(struct cam_periph *periph, un 1, probedone, /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, + 0, /*data_ptr*/NULL, /*dxfer_len*/0, 10 * 1000); ata_pm_read_cmd(ataio, 1, 15); break; - case PROBE_PM_PORTS: - cam_fill_ataio(ataio, - 1, - probedone, - /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, - /*data_ptr*/NULL, - /*dxfer_len*/0, - 10 * 1000); - ata_pm_read_cmd(ataio, 2, 15); - break; - case PROBE_PM_RESET: - { - struct ata_params *ident_buf = - &periph->path->device->ident_data; - cam_fill_ataio(ataio, - 1, - probedone, - /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, - /*data_ptr*/NULL, - /*dxfer_len*/0, - 10 * 1000); - ata_pm_write_cmd(ataio, 2, softc->pm_step, - (ident_buf->cylinders & (1 << softc->pm_step)) ? 0 : 1); -printf("PM RESET %d %04x %d\n", softc->pm_step, ident_buf->cylinders, - (ident_buf->cylinders & (1 << softc->pm_step)) ? 0 : 1); - break; - } - case PROBE_PM_CONNECT: - cam_fill_ataio(ataio, - 1, - probedone, - /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, - /*data_ptr*/NULL, - /*dxfer_len*/0, - 10 * 1000); - ata_pm_write_cmd(ataio, 2, softc->pm_step, 0); - break; - case PROBE_PM_CHECK: - cam_fill_ataio(ataio, - 1, - probedone, - /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, - /*data_ptr*/NULL, - /*dxfer_len*/0, - 10 * 1000); - ata_pm_read_cmd(ataio, 0, softc->pm_step); - break; - case PROBE_PM_CLEAR: - cam_fill_ataio(ataio, - 1, - probedone, - /*flags*/CAM_DIR_NONE, - MSG_SIMPLE_Q_TAG, - /*data_ptr*/NULL, - /*dxfer_len*/0, - 10 * 1000); - ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF); - break; case PROBE_INVALID: CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO, ("probestart: invalid action state\n")); @@ -506,7 +421,7 @@ proberequestdefaultnegotiation(struct ca { struct ccb_trans_settings cts; - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_USER_SETTINGS; xpt_action((union ccb *)&cts); @@ -528,7 +443,7 @@ proberequestbackoff(struct cam_periph *p struct ccb_trans_settings_spi *spi; memset(&cts, 0, sizeof (cts)); - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; xpt_action((union ccb *)&cts); @@ -630,7 +545,7 @@ probedone(struct cam_periph *periph, uni probe_softc *softc; struct cam_path *path; u_int32_t priority; - int found = 0; + int found = 1; CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); @@ -655,7 +570,7 @@ probedone(struct cam_periph *periph, uni /* Report SIM that PM is present. */ bzero(&cts, sizeof(cts)); - xpt_setup_ccb(&cts.ccb_h, path, 1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; cts.xport_specific.sata.pm_present = 1; @@ -672,8 +587,7 @@ probedone(struct cam_periph *periph, uni xpt_print(path, "Unexpected signature 0x%04x\n", sign); } - xpt_release_ccb(done_ccb); - break; + goto device_fail; } xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); @@ -780,9 +694,8 @@ device_fail: * drivers that this device is no more. */ if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) - /* Send the async notification. */ xpt_async(AC_LOST_DEVICE, path, NULL); - + found = 0; xpt_release_ccb(done_ccb); break; } @@ -881,6 +794,7 @@ modedone: if (path->device->protocol == (done_ccb->ataio.res.lba_mid << 16) + (done_ccb->ataio.res.lba_low << 8) + done_ccb->ataio.res.sector_count; + ((uint32_t *)ident_buf)[0] = softc->pm_pid; printf("PM Product ID: %08x\n", softc->pm_pid); snprintf(ident_buf->model, sizeof(ident_buf->model), "Port Multiplier %08x", softc->pm_pid); @@ -903,164 +817,24 @@ modedone: if (path->device->protocol == (done_ccb->ataio.res.lba_mid << 16) + (done_ccb->ataio.res.lba_low << 8) + done_ccb->ataio.res.sector_count; + ((uint32_t *)ident_buf)[1] = softc->pm_prv; printf("PM Revision: %08x\n", softc->pm_prv); snprintf(ident_buf->revision, sizeof(ident_buf->revision), "%04x", softc->pm_prv); - PROBE_SET_ACTION(softc, PROBE_PM_PORTS); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else if (cam_periph_error(done_ccb, 0, 0, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - goto device_fail; - case PROBE_PM_PORTS: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - softc->pm_ports = (done_ccb->ataio.res.lba_high << 24) + - (done_ccb->ataio.res.lba_mid << 16) + - (done_ccb->ataio.res.lba_low << 8) + - done_ccb->ataio.res.sector_count; - /* This PM declares 6 ports, while only 5 of them are real. - * Port 5 is enclosure management bridge port, which has implementation - * problems, causing probe faults. Hide it for now. */ - if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6) - softc->pm_ports = 5; - /* This PM declares 7 ports, while only 5 of them are real. - * Port 5 is some fake "Config Disk" with 640 sectors size, - * port 6 is enclosure management bridge port. - * Both fake ports has implementation problems, causing - * probe faults. Hide them for now. */ - if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7) - softc->pm_ports = 5; - printf("PM ports: %d\n", softc->pm_ports); - ident_buf->config = softc->pm_ports; path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; - softc->pm_step = 0; - PROBE_SET_ACTION(softc, PROBE_PM_RESET); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else if (cam_periph_error(done_ccb, 0, 0, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - goto device_fail; - case PROBE_PM_RESET: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - softc->pm_step++; - if (softc->pm_step < softc->pm_ports) { - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else { - softc->pm_step = 0; - DELAY(5000); - printf("PM reset done\n"); - PROBE_SET_ACTION(softc, PROBE_PM_CONNECT); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - } else if (cam_periph_error(done_ccb, 0, 0, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - goto device_fail; - case PROBE_PM_CONNECT: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - softc->pm_step++; - if (softc->pm_step < softc->pm_ports) { - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else { - softc->pm_step = 0; - softc->pm_try = 0; - printf("PM connect done\n"); - PROBE_SET_ACTION(softc, PROBE_PM_CHECK); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - } else if (cam_periph_error(done_ccb, 0, 0, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - goto device_fail; - case PROBE_PM_CHECK: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - int res = (done_ccb->ataio.res.lba_high << 24) + - (done_ccb->ataio.res.lba_mid << 16) + - (done_ccb->ataio.res.lba_low << 8) + - done_ccb->ataio.res.sector_count; - if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) { - printf("PM status: %d - %08x\n", softc->pm_step, res); - ident_buf->cylinders |= (1 << softc->pm_step); - softc->pm_step++; - } else { - if (softc->pm_try < 100) { - DELAY(10000); - softc->pm_try++; - } else { - printf("PM status: %d - %08x\n", softc->pm_step, res); - ident_buf->cylinders &= ~(1 << softc->pm_step); - softc->pm_step++; - } - } - if (softc->pm_step < softc->pm_ports) { - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else { - softc->pm_step = 0; - PROBE_SET_ACTION(softc, PROBE_PM_CLEAR); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - } else if (cam_periph_error(done_ccb, 0, 0, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - goto device_fail; - case PROBE_PM_CLEAR: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - softc->pm_step++; - if (softc->pm_step < softc->pm_ports) { - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - found = ident_buf->cylinders | 0x8000; - if (path->device->flags & CAM_DEV_UNCONFIGURED) { + if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { path->device->flags &= ~CAM_DEV_UNCONFIGURED; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; xpt_action(done_ccb); xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); - xpt_release_ccb(done_ccb); + } else { + done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action(done_ccb); + xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, + done_ccb); } + xpt_release_ccb(done_ccb); break; } else if (cam_periph_error(done_ccb, 0, 0, &softc->saved_ccb) == ERESTART) { @@ -1192,11 +966,11 @@ ata_scan_bus(struct cam_periph *periph, scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; /* Free the current request path- we're done with it. */ xpt_free_path(work_ccb->ccb_h.path); - /* If there is PM... */ + /* If there is PMP... */ if (scan_info->counter == 15) { if (work_ccb->ccb_h.ppriv_field1 != 0) { - /* Save PM probe result. */ - scan_info->found = work_ccb->ccb_h.ppriv_field1; + /* everything else willbe probed by it */ + scan_info->found = 0x8000; } else { struct ccb_trans_settings cts; @@ -1225,6 +999,8 @@ take_next: break; } scan_next: + if ((scan_info->found & (1 << scan_info->counter)) == 0) + goto take_next; status = xpt_create_path(&path, xpt_periph, scan_info->request_ccb->ccb_h.path_id, scan_info->counter, 0); @@ -1240,11 +1016,6 @@ scan_next: xpt_done(request_ccb); break; } - if ((scan_info->found & (1 << scan_info->counter)) == 0) { - xpt_async(AC_LOST_DEVICE, path, NULL); - xpt_free_path(path); - goto take_next; - } xpt_setup_ccb(&work_ccb->ccb_h, path, scan_info->request_ccb->ccb_h.pinfo.priority); work_ccb->ccb_h.func_code = XPT_SCAN_LUN; @@ -1270,7 +1041,7 @@ ata_scan_lun(struct cam_periph *periph, CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n")); - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -1308,7 +1079,7 @@ ata_scan_lun(struct cam_periph *periph, free(new_path, M_CAMXPT); return; } - xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1); + xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL); request_ccb->ccb_h.cbfcnp = xptscandone; request_ccb->ccb_h.func_code = XPT_SCAN_LUN; request_ccb->crcn.flags = flags; @@ -1407,7 +1178,7 @@ ata_device_transport(struct cam_path *pa struct ata_params *ident_buf = NULL; /* Get transport information from the SIM */ - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -1427,7 +1198,7 @@ ata_device_transport(struct cam_path *pa ata_version(ident_buf->version_major) : cpi.transport_version; /* Tell the controller what we think */ - xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; cts.transport = path->device->transport; @@ -1474,6 +1245,36 @@ ata_action(union ccb *start_ccb) } static void +ata_done(union ccb *done_ccb) +{ + struct cam_path *path; + union ccb *work_ccb; + + switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + case CAM_UNCOR_PARITY: + work_ccb = xpt_alloc_ccb_nowait(); + if (work_ccb == NULL) + break; + if (xpt_create_path(&path, xpt_periph, done_ccb->ccb_h.path_id, + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_free_ccb(work_ccb); + break; + } + xpt_setup_ccb(&work_ccb->ccb_h, path, CAM_PRIORITY_NORMAL); + work_ccb->ccb_h.func_code = XPT_RESET_BUS; + work_ccb->ccb_h.cbfcnp = NULL; + CAM_DEBUG(path, CAM_DEBUG_SUBTRACE, ("Resetting Bus\n")); + xpt_action(work_ccb); + xpt_free_ccb(work_ccb); + break; + } + + /* Call default done handler. */ + xpt_done_default(done_ccb); +} + +static void scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, int async_update) { @@ -1555,7 +1356,7 @@ scsi_set_transfer_settings(struct ccb_tr inq_data = &device->inq_data; scsi = &cts->proto_specific.scsi; - xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -1576,7 +1377,7 @@ scsi_set_transfer_settings(struct ccb_tr * Perform sanity checking against what the * controller and device can do. */ - xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1); + xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cur_cts.type = cts->type; xpt_action((union ccb *)&cur_cts); @@ -1636,7 +1437,7 @@ scsi_set_transfer_settings(struct ccb_tr device->tag_delay_count = 0; xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path, - /*priority*/1); + CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; crs.openings @@ -1669,7 +1470,7 @@ scsi_toggle_tags(struct cam_path *path) && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { struct ccb_trans_settings cts; - xpt_setup_ccb(&cts.ccb_h, path, 1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.protocol = PROTO_SCSI; cts.protocol_version = PROTO_VERSION_UNSPECIFIED; cts.transport = XPORT_UNSPECIFIED; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam.h /storage/p4/scottl-camlock/src/sys/cam/cam.h --- /storage/FreeBSD/head/sys/cam/cam.h 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam.h 2009-10-14 15:26:16.000000000 +0300 @@ -66,6 +66,11 @@ struct cam_periph; */ typedef struct { u_int32_t priority; +#define CAM_PRIORITY_HOST 100 +#define CAM_PRIORITY_BUS 200 +#define CAM_PRIORITY_DEV 300 +#define CAM_PRIORITY_HIGH 400 +#define CAM_PRIORITY_NORMAL 500 #define CAM_PRIORITY_NONE (u_int32_t)-1 u_int32_t generation; int index; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_periph.c /storage/p4/scottl-camlock/src/sys/cam/cam_periph.c --- /storage/FreeBSD/head/sys/cam/cam_periph.c 2009-09-23 01:23:51.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_periph.c 2009-10-14 15:26:16.000000000 +0300 @@ -534,13 +534,13 @@ camperiphfree(struct cam_periph *periph) switch (periph->deferred_ac) { case AC_FOUND_DEVICE: ccb.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/ 1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); xpt_action(&ccb); arg = &ccb; break; case AC_PATH_REGISTERED: ccb.ccb_h.func_code = XPT_PATH_INQ; - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/ 1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); xpt_action(&ccb); arg = &ccb; break; @@ -831,10 +831,10 @@ cam_periph_ioctl(struct cam_periph *peri switch(cmd){ case CAMGETPASSTHRU: - ccb = cam_periph_getccb(periph, /* priority */ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, - /*priority*/1); + CAM_PRIORITY_NORMAL); ccb->ccb_h.func_code = XPT_GDEVLIST; /* @@ -939,7 +939,7 @@ cam_freeze_devq(struct cam_path *path) { struct ccb_hdr ccb_h; - xpt_setup_ccb(&ccb_h, path, /*priority*/1); + xpt_setup_ccb(&ccb_h, path, CAM_PRIORITY_NORMAL); ccb_h.func_code = XPT_NOOP; ccb_h.flags = CAM_DEV_QFREEZE; xpt_action((union ccb *)&ccb_h); @@ -952,8 +952,7 @@ cam_release_devq(struct cam_path *path, { struct ccb_relsim crs; - xpt_setup_ccb(&crs.ccb_h, path, - /*priority*/1); + xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; crs.release_flags = relsim_flags; @@ -1070,7 +1069,7 @@ camperiphdone(struct cam_periph *periph, * Grab the inquiry data for this device. */ xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, - /*priority*/ 1); + CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); err_action = scsi_error_action(&done_ccb->csio, @@ -1212,7 +1211,7 @@ cam_periph_bus_settle(struct cam_periph { struct ccb_getdevstats cgds; - xpt_setup_ccb(&cgds.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cgds.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cgds.ccb_h.func_code = XPT_GDEV_STATS; xpt_action((union ccb *)&cgds); cam_periph_freeze_after_event(periph, &cgds.last_reset, bus_settle); @@ -1280,7 +1279,7 @@ camperiphscsistatuserror(union ccb *ccb, */ xpt_setup_ccb(&cgds.ccb_h, ccb->ccb_h.path, - /*priority*/1); + CAM_PRIORITY_NORMAL); cgds.ccb_h.func_code = XPT_GDEV_STATS; xpt_action((union ccb *)&cgds); @@ -1403,7 +1402,7 @@ camperiphscsisenseerror(union ccb *ccb, /* * Grab the inquiry data for this device. */ - xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, /*priority*/ 1); + xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); @@ -1543,14 +1542,14 @@ camperiphscsisenseerror(union ccb *ccb, if ((err_action & SS_MASK) >= SS_START) { /* - * Drop the priority to 0 so that the recovery + * Drop the priority, so that the recovery * CCB is the first to execute. Freeze the queue * after this command is sent so that we can * restore the old csio and have it queued in * the proper order before we release normal * transactions to the device. */ - ccb->ccb_h.pinfo.priority = 0; + ccb->ccb_h.pinfo.priority = CAM_PRIORITY_DEV; ccb->ccb_h.flags |= CAM_DEV_QFREEZE; ccb->ccb_h.saved_ccb_ptr = save_ccb; error = ERESTART; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_periph.h /storage/p4/scottl-camlock/src/sys/cam/cam_periph.h --- /storage/FreeBSD/head/sys/cam/cam_periph.h 2009-06-23 19:31:32.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_periph.h 2009-10-14 15:26:16.000000000 +0300 @@ -177,17 +177,9 @@ void cam_periph_freeze_after_event(stru int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags, union ccb *save_ccb); -static __inline void -cam_periph_lock(struct cam_periph *periph) -{ - mtx_lock(periph->sim->mtx); -} - -static __inline void -cam_periph_unlock(struct cam_periph *periph) -{ - mtx_unlock(periph->sim->mtx); -} +#define cam_periph_lock(periph) mtx_lock((periph)->sim->mtx) +#define cam_periph_unlock(periph) mtx_unlock((periph)->sim->mtx) +#define cam_periph_owned(periph) mtx_owned((periph)->sim->mtx) #endif /* _KERNEL */ #endif /* _CAM_CAM_PERIPH_H */ diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_sim.h /storage/p4/scottl-camlock/src/sys/cam/cam_sim.h --- /storage/FreeBSD/head/sys/cam/cam_sim.h 2009-03-14 17:09:14.000000000 +0200 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_sim.h 2009-10-14 15:26:16.000000000 +0300 @@ -94,23 +94,13 @@ struct cam_sim { const char *sim_name; void *softc; struct mtx *mtx; - TAILQ_HEAD(, ccb_hdr) sim_doneq; + struct cam_devq *devq; /* Device Queue to use for this SIM */ TAILQ_ENTRY(cam_sim) links; u_int32_t path_id;/* The Boot device may set this to 0? */ u_int32_t unit_number; u_int32_t bus_id; int max_tagged_dev_openings; int max_dev_openings; - u_int32_t flags; -#define CAM_SIM_REL_TIMEOUT_PENDING 0x01 -#define CAM_SIM_MPSAFE 0x02 -#define CAM_SIM_ON_DONEQ 0x04 - struct callout callout; - struct cam_devq *devq; /* Device Queue to use for this SIM */ - int refcount; /* References to the SIM. */ - - /* "Pool" of inactive ccbs managed by xpt_get_ccb and xpt_release_ccb */ - SLIST_HEAD(,ccb_hdr) ccb_freeq; /* * Maximum size of ccb pool. Modified as devices are added/removed * or have their * opening counts changed. @@ -118,7 +108,15 @@ struct cam_sim { u_int max_ccbs; /* Current count of allocated ccbs */ u_int ccb_count; - + struct callout callout; + u_int32_t flags; +#define CAM_SIM_REL_TIMEOUT_PENDING 0x01 +#define CAM_SIM_MPSAFE 0x02 +#define CAM_SIM_ON_DONEQ 0x04 + int refcount; /* References to the SIM. */ + TAILQ_HEAD(, ccb_hdr) sim_doneq; /* Completed requests queue. */ + /* "Pool" of inactive ccbs managed by xpt_get_ccb and xpt_release_ccb */ + SLIST_HEAD(, ccb_hdr) ccb_freeq; }; #define CAM_SIM_LOCK(sim) mtx_lock((sim)->mtx); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_xpt.c /storage/p4/scottl-camlock/src/sys/cam/cam_xpt.c --- /storage/FreeBSD/head/sys/cam/cam_xpt.c 2009-10-21 18:57:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_xpt.c 2009-10-22 10:32:59.000000000 +0300 @@ -812,7 +812,7 @@ xpt_scanner_thread(void *dummy) else ccb->ccb_h.func_code = XPT_SCAN_LUN; ccb->ccb_h.cbfcnp = xptdone; - xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 1); + xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, CAM_PRIORITY_BUS); cam_periph_runccb(ccb, NULL, 0, 0, NULL); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -1059,7 +1059,7 @@ xpt_announce_periph(struct cam_periph *p printf("%s%d: Serial Number %.60s\n", periph->periph_name, periph->unit_number, path->device->serial_num); } - xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; xpt_action((union ccb*)&cts); @@ -1068,7 +1068,7 @@ xpt_announce_periph(struct cam_periph *p } /* Ask the SIM for its base transfer speed */ - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -2335,7 +2335,7 @@ xptsetasyncfunc(struct cam_ed *device, v device->target->bus->path_id, device->target->target_id, device->lun_id); - xpt_setup_ccb(&cgd.ccb_h, &path, /*priority*/1); + xpt_setup_ccb(&cgd.ccb_h, &path, CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); cur_entry->callback(cur_entry->callback_arg, @@ -2359,7 +2359,7 @@ xptsetasyncbusfunc(struct cam_eb *bus, v bus->sim->path_id, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); - xpt_setup_ccb(&cpi.ccb_h, &path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); cur_entry->callback(cur_entry->callback_arg, @@ -2989,6 +2989,13 @@ xpt_action_default(union ccb *start_ccb) } void +xpt_done_default(union ccb *done_ccb) +{ + /* Call the peripheral driver's callback */ + (*done_ccb->ccb_h.cbfcnp)(done_ccb->ccb_h.path->periph, done_ccb); +} + +void xpt_polled_action(union ccb *start_ccb) { u_int32_t timeout; @@ -3729,6 +3736,7 @@ xpt_release_ccb(union ccb *free_ccb) static struct xpt_xport xport_default = { .alloc_device = xpt_alloc_device_default, .action = xpt_action_default, + .done = xpt_done_default, .async = xpt_dev_async_default, }; @@ -3799,7 +3807,7 @@ xpt_bus_register(struct cam_sim *sim, de if (status != CAM_REQ_CMP) printf("xpt_compile_path returned %d\n", status); - xpt_setup_ccb(&cpi.ccb_h, &path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -4544,7 +4552,7 @@ xpt_start_tags(struct cam_path *path) newopenings = min(device->maxtags, sim->max_tagged_dev_openings); xpt_dev_ccbq_resize(path, newopenings); - xpt_setup_ccb(&crs.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; crs.openings @@ -4571,7 +4579,7 @@ xptconfigbuscountfunc(struct cam_eb *bus busses_to_config++; xpt_compile_path(&path, NULL, bus->path_id, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); - xpt_setup_ccb(&cpi.ccb_h, &path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); can_negotiate = cpi.hba_inquiry; @@ -4614,7 +4622,7 @@ xptconfigfunc(struct cam_eb *bus, void * xpt_finishconfig(xpt_periph, NULL); return(0); } - xpt_setup_ccb(&work_ccb->ccb_h, path, /*priority*/1); + xpt_setup_ccb(&work_ccb->ccb_h, path, CAM_PRIORITY_NORMAL); work_ccb->ccb_h.func_code = XPT_PATH_INQ; xpt_action(work_ccb); if (work_ccb->ccb_h.status != CAM_REQ_CMP) { @@ -4629,7 +4637,7 @@ xptconfigfunc(struct cam_eb *bus, void * can_negotiate &= (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE); if ((work_ccb->cpi.hba_misc & PIM_NOBUSRESET) == 0 && (can_negotiate != 0)) { - xpt_setup_ccb(&work_ccb->ccb_h, path, /*priority*/1); + xpt_setup_ccb(&work_ccb->ccb_h, path, CAM_PRIORITY_NORMAL); work_ccb->ccb_h.func_code = XPT_RESET_BUS; work_ccb->ccb_h.cbfcnp = NULL; CAM_DEBUG(path, CAM_DEBUG_SUBTRACE, @@ -4808,7 +4816,7 @@ xpt_register_async(int event, ac_callbac xptpath = 1; } - xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); + xpt_setup_ccb(&csa.ccb_h, path, CAM_PRIORITY_NORMAL); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = event; csa.callback = cbfunc; @@ -4999,8 +5007,8 @@ camisr_runqueue(void *V_queue) xpt_run_dev_sendq(ccb_h->path->bus); } - /* Call the peripheral driver's callback */ - (*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h); + /* Call the XPT's callback */ + (*(ccb_h->path->bus->xport->done))((union ccb *)ccb_h); } } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_xpt.h /storage/p4/scottl-camlock/src/sys/cam/cam_xpt.h --- /storage/FreeBSD/head/sys/cam/cam_xpt.h 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_xpt.h 2009-10-14 15:26:16.000000000 +0300 @@ -87,6 +87,7 @@ SLIST_HEAD(periph_list, cam_periph); void xpt_action(union ccb *new_ccb); void xpt_action_default(union ccb *new_ccb); +void xpt_done_default(union ccb *new_ccb); void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/cam_xpt_internal.h /storage/p4/scottl-camlock/src/sys/cam/cam_xpt_internal.h --- /storage/FreeBSD/head/sys/cam/cam_xpt_internal.h 2009-10-21 18:27:48.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/cam_xpt_internal.h 2009-10-22 10:32:59.000000000 +0300 @@ -41,6 +41,7 @@ typedef void (*xpt_release_device_func)( struct cam_et *target, struct cam_ed *device); typedef void (*xpt_action_func)(union ccb *start_ccb); +typedef void (*xpt_done_func)(union ccb *done_ccb); typedef void (*xpt_dev_async_func)(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, @@ -53,6 +54,7 @@ struct xpt_xport { xpt_alloc_device_func alloc_device; xpt_release_device_func reldev; xpt_action_func action; + xpt_done_func done; xpt_dev_async_func async; xpt_announce_periph_func announce; }; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_all.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_all.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_all.c 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_all.c 2009-10-14 15:26:16.000000000 +0300 @@ -3004,7 +3004,7 @@ scsi_command_string(struct cam_device *d */ xpt_setup_ccb(&cgd.ccb_h, csio->ccb_h.path, - /*priority*/ 1); + CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); @@ -3088,7 +3088,7 @@ scsi_sense_sbuf(struct cam_device *devic */ xpt_setup_ccb(&cgd.ccb_h, csio->ccb_h.path, - /*priority*/ 1); + CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_cd.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_cd.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_cd.c 2009-09-15 20:30:08.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_cd.c 2009-10-14 15:26:16.000000000 +0300 @@ -673,7 +673,7 @@ cdregister(struct cam_periph *periph, vo softc->quirks = CD_Q_NONE; /* Check if the SIM does not want 6 byte commands */ - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE)) @@ -965,9 +965,9 @@ cdregisterexit: (void)cam_periph_hold(periph, PRIBIO); if ((softc->flags & CD_FLAG_CHANGER) == 0) - xpt_schedule(periph, /*priority*/5); + xpt_schedule(periph, CAM_PRIORITY_DEV); else - cdschedule(periph, /*priority*/ 5); + cdschedule(periph, CAM_PRIORITY_DEV); return(CAM_REQ_CMP); } @@ -1105,7 +1105,7 @@ cdschedule(struct cam_periph *periph, in * We don't do anything with the priority here. * This is strictly a fifo queue. */ - softc->pinfo.priority = 1; + softc->pinfo.priority = CAM_PRIORITY_NORMAL; softc->pinfo.generation = ++softc->changer->devq.generation; camq_insert(&softc->changer->devq, (cam_pinfo *)softc); @@ -1206,7 +1206,7 @@ cdrunchangerqueue(void *arg) /* Just in case this device is waiting */ wakeup(&softc->changer); - xpt_schedule(softc->periph, /*priority*/ 1); + xpt_schedule(softc->periph, CAM_PRIORITY_NORMAL); /* * Get rid of any pending timeouts, and set a flag to schedule new @@ -1344,7 +1344,7 @@ cdgetccb(struct cam_periph *periph, u_in * If this changer isn't already queued, queue it up. */ if (softc->pinfo.index == CAM_UNQUEUED_INDEX) { - softc->pinfo.priority = 1; + softc->pinfo.priority = CAM_PRIORITY_NORMAL; softc->pinfo.generation = ++softc->changer->devq.generation; camq_insert(&softc->changer->devq, @@ -1421,9 +1421,9 @@ cdstrategy(struct bio *bp) * differently for changers. */ if ((softc->flags & CD_FLAG_CHANGER) == 0) - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); else - cdschedule(periph, /* priority */ 1); + cdschedule(periph, CAM_PRIORITY_NORMAL); cam_periph_unlock(periph); return; @@ -1493,7 +1493,7 @@ cdstart(struct cam_periph *periph, union } if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } break; } @@ -1668,7 +1668,7 @@ cddone(struct cam_periph *periph, union xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, - /* priority */ 1); + CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); @@ -2727,7 +2727,7 @@ cdprevent(struct cam_periph *periph, int return; } - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); scsi_prevent(&ccb->csio, /*retries*/ 1, @@ -2901,7 +2901,7 @@ cdsize(struct cam_periph *periph, u_int3 softc = (struct cd_softc *)periph->softc; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); /* XXX Should be M_WAITOK */ rcap_buf = malloc(sizeof(struct scsi_read_capacity_data), @@ -3153,7 +3153,7 @@ cdreadtoc(struct cam_periph *periph, u_i ntoc = len; error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3200,7 +3200,7 @@ cdreadsubchannel(struct cam_periph *peri error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3252,7 +3252,7 @@ cdgetmode(struct cam_periph *periph, str softc = (struct cd_softc *)periph->softc; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3351,7 +3351,7 @@ cdsetmode(struct cam_periph *periph, str softc = (struct cd_softc *)periph->softc; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3443,7 +3443,7 @@ cdplay(struct cam_periph *periph, u_int3 u_int8_t cdb_len; error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; /* * Use the smallest possible command to perform the operation. @@ -3500,7 +3500,7 @@ cdplaymsf(struct cam_periph *periph, u_i error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3546,7 +3546,7 @@ cdplaytracks(struct cam_periph *periph, error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3588,7 +3588,7 @@ cdpause(struct cam_periph *periph, u_int error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; @@ -3625,7 +3625,7 @@ cdstartunit(struct cam_periph *periph, i error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); scsi_start_stop(&ccb->csio, /* retries */ 1, @@ -3653,7 +3653,7 @@ cdstopunit(struct cam_periph *periph, u_ error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); scsi_start_stop(&ccb->csio, /* retries */ 1, @@ -3682,7 +3682,7 @@ cdsetspeed(struct cam_periph *periph, u_ int error; error = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; /* Preserve old behavior: units in multiples of CDROM speed */ @@ -3730,7 +3730,7 @@ cdreportkey(struct cam_periph *periph, s databuf = NULL; lba = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); switch (authinfo->format) { case DVD_REPORT_AGID: @@ -3887,7 +3887,7 @@ cdsendkey(struct cam_periph *periph, str error = 0; databuf = NULL; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); switch(authinfo->format) { case DVD_SEND_CHALLENGE: { @@ -3983,7 +3983,7 @@ cdreaddvdstructure(struct cam_periph *pe /* The address is reserved for many of the formats */ address = 0; - ccb = cdgetccb(periph, /* priority */ 1); + ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL); switch(dvdstruct->format) { case DVD_STRUCT_PHYSICAL: diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_ch.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_ch.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_ch.c 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_ch.c 2009-10-14 15:26:16.000000000 +0300 @@ -376,7 +376,7 @@ chregister(struct cam_periph *periph, vo * This first call can't block */ (void)cam_periph_hold(periph, PRIBIO); - xpt_schedule(periph, /*priority*/5); + xpt_schedule(periph, CAM_PRIORITY_DEV); return(CAM_REQ_CMP); } @@ -809,7 +809,7 @@ chmove(struct cam_periph *periph, struct fromelem = softc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit; toelem = softc->sc_firsts[cm->cm_totype] + cm->cm_tounit; - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_move_medium(&ccb->csio, /* retries */ 1, @@ -868,7 +868,7 @@ chexchange(struct cam_periph *periph, st dst1 = softc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit; dst2 = softc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit; - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_exchange_medium(&ccb->csio, /* retries */ 1, @@ -918,7 +918,7 @@ chposition(struct cam_periph *periph, st */ dst = softc->sc_firsts[cp->cp_type] + cp->cp_unit; - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_position_to_element(&ccb->csio, /* retries */ 1, @@ -1075,7 +1075,7 @@ chgetelemstatus(struct cam_periph *perip data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK); cam_periph_lock(periph); - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_read_element_status(&ccb->csio, /* retries */ 1, @@ -1201,7 +1201,7 @@ chielem(struct cam_periph *periph, error = 0; softc = (struct ch_softc *)periph->softc; - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_initialize_element_status(&ccb->csio, /* retries */ 1, @@ -1285,7 +1285,7 @@ chsetvoltag(struct cam_periph *periph, min(strlen(csvr->csvr_voltag.cv_volid), sizeof(ssvtp.vitf))); scsi_ulto2b(csvr->csvr_voltag.cv_serial, ssvtp.minvsn); - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_send_volume_tag(&ccb->csio, /* retries */ 1, @@ -1323,7 +1323,7 @@ chgetparams(struct cam_periph *periph) softc = (struct ch_softc *)periph->softc; - ccb = cam_periph_getccb(periph, /*priority*/ 1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); /* * The scsi_mode_sense_data structure is just a convenience diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_da.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_da.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_da.c 2009-09-15 20:30:08.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_da.c 2009-10-14 15:26:17.000000000 +0300 @@ -729,7 +729,7 @@ daclose(struct disk *dp) if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { union ccb *ccb; - ccb = cam_periph_getccb(periph, /*priority*/1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_synchronize_cache(&ccb->csio, /*retries*/1, @@ -821,12 +821,6 @@ dastrategy(struct bio *bp) #endif /* - * Mask interrupts so that the pack cannot be invalidated until - * after we are in the queue. Otherwise, we might not properly - * clean up one of the buffers. - */ - - /* * If the device has been made invalid, error out */ if ((softc->flags & DA_FLAG_PACK_INVALID)) { @@ -843,7 +837,7 @@ dastrategy(struct bio *bp) /* * Schedule ourselves for performing the work. */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); cam_periph_unlock(periph); return; @@ -873,7 +867,7 @@ dadump(void *arg, void *virtual, vm_offs if (length > 0) { periph->flags |= CAM_PERIPH_POLLED; - xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); csio.ccb_h.ccb_state = DA_CCB_DUMP; scsi_read_write(&csio, /*retries*/1, @@ -910,7 +904,7 @@ dadump(void *arg, void *virtual, vm_offs */ if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { - xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); csio.ccb_h.ccb_state = DA_CCB_DUMP; scsi_synchronize_cache(&csio, /*retries*/1, @@ -1207,7 +1201,7 @@ daregister(struct cam_periph *periph, vo /* Check if the SIM does not want 6 byte commands */ bzero(&cpi, sizeof(cpi)); - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE)) @@ -1288,7 +1282,7 @@ daregister(struct cam_periph *periph, vo * the end of probe. */ (void)cam_periph_hold(periph, PRIBIO); - xpt_schedule(periph, /*priority*/5); + xpt_schedule(periph, CAM_PRIORITY_DEV); /* * Schedule a periodic event to occasionally send an @@ -1394,7 +1388,7 @@ dastart(struct cam_periph *periph, union if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } break; } @@ -1504,8 +1498,10 @@ dadone(struct cam_periph *periph, union { struct da_softc *softc; struct ccb_scsiio *csio; + u_int32_t priority; softc = (struct da_softc *)periph->softc; + priority = done_ccb->ccb_h.pinfo.priority; csio = &done_ccb->csio; switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) { case DA_CCB_BUFFER_IO: @@ -1623,7 +1619,7 @@ dadone(struct cam_periph *periph, union softc->state = DA_STATE_PROBE2; free(rdcap, M_SCSIDA); xpt_release_ccb(done_ccb); - xpt_schedule(periph, /*priority*/5); + xpt_schedule(periph, priority); return; } } else { @@ -1691,7 +1687,7 @@ dadone(struct cam_periph *periph, union xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, - /* priority */ 1); + priority); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); @@ -1845,7 +1841,7 @@ daprevent(struct cam_periph *periph, int return; } - ccb = cam_periph_getccb(periph, /*priority*/1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_prevent(&ccb->csio, /*retries*/1, @@ -1895,7 +1891,7 @@ dagetcapacity(struct cam_periph *periph) if (rcap == NULL) return (ENOMEM); - ccb = cam_periph_getccb(periph, /*priority*/1); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); scsi_read_capacity(&ccb->csio, /*retries*/4, /*cbfncp*/dadone, @@ -1989,7 +1985,7 @@ dasetgeom(struct cam_periph *periph, uin * up with something that will make this a bootable * device. */ - xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccg.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccg.ccb_h.func_code = XPT_CALC_GEOMETRY; ccg.block_size = dp->secsize; ccg.volume_size = dp->sectors; @@ -2063,7 +2059,7 @@ dashutdown(void * arg, int howto) continue; } - xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.ccb_h.ccb_state = DA_CCB_DUMP; scsi_synchronize_cache(&ccb.csio, diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_low.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_low.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_low.c 2009-10-22 10:34:23.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_low.c 2009-10-22 10:32:59.000000000 +0300 @@ -979,7 +979,7 @@ scsi_low_rescan_bus_cam(slp) ccb = xpt_alloc_ccb(); bzero(ccb, sizeof(union ccb)); - xpt_setup_ccb(&ccb->ccb_h, path, 5); + xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_BUS); ccb->ccb_h.func_code = XPT_SCAN_BUS; ccb->ccb_h.cbfcnp = scsi_low_cam_rescan_callback; ccb->crcn.flags = CAM_FLAG_NONE; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_pt.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_pt.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_pt.c 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_pt.c 2009-10-14 15:26:17.000000000 +0300 @@ -224,7 +224,7 @@ ptstrategy(struct bio *bp) /* * Schedule ourselves for performing the work. */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); cam_periph_unlock(periph); return; @@ -464,7 +464,7 @@ ptstart(struct cam_periph *periph, union if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, /* XXX priority */1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } } } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_sa.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_sa.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_sa.c 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_sa.c 2009-10-14 15:26:17.000000000 +0300 @@ -786,7 +786,7 @@ sastrategy(struct bio *bp) /* * Schedule ourselves for performing the work. */ - xpt_schedule(periph, 1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); cam_periph_unlock(periph); return; @@ -1689,7 +1689,7 @@ again: if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ - xpt_schedule(periph, 1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } break; } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_sg.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_sg.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_sg.c 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_sg.c 2009-10-14 15:26:17.000000000 +0300 @@ -510,7 +510,7 @@ sgioctl(struct cdev *dev, u_long cmd, ca break; } - ccb = cam_periph_getccb(periph, /*priority*/5); + ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); csio = &ccb->csio; error = copyin(req.cmdp, &csio->cdb_io.cdb_bytes, @@ -729,7 +729,7 @@ sgwrite(struct cdev *dev, struct uio *ui cam_periph_lock(periph); sc = periph->softc; - xpt_setup_ccb(&ccb->ccb_h, periph->path, /*priority*/5); + xpt_setup_ccb(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL); cam_fill_csio(csio, /*retries*/1, sgdone, diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_targ_bh.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_targ_bh.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_targ_bh.c 2009-03-14 17:09:14.000000000 +0200 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_targ_bh.c 2009-10-14 15:26:18.000000000 +0300 @@ -240,7 +240,7 @@ targbhenlun(struct cam_periph *periph) if ((softc->flags & TARGBH_FLAG_LUN_ENABLED) != 0) return (CAM_REQ_CMP); - xpt_setup_ccb(&immed_ccb.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&immed_ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); immed_ccb.ccb_h.func_code = XPT_EN_LUN; /* Don't need support for any vendor specific commands */ @@ -280,7 +280,7 @@ targbhenlun(struct cam_periph *periph) break; } - xpt_setup_ccb(&atio->ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&atio->ccb_h, periph->path, CAM_PRIORITY_NORMAL); atio->ccb_h.func_code = XPT_ACCEPT_TARGET_IO; atio->ccb_h.cbfcnp = targbhdone; xpt_action((union ccb *)atio); @@ -318,7 +318,7 @@ targbhenlun(struct cam_periph *periph) break; } - xpt_setup_ccb(&inot->ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&inot->ccb_h, periph->path, CAM_PRIORITY_NORMAL); inot->ccb_h.func_code = XPT_IMMED_NOTIFY; inot->ccb_h.cbfcnp = targbhdone; xpt_action((union ccb *)inot); @@ -361,7 +361,7 @@ targbhdislun(struct cam_periph *periph) softc->accept_tio_list = ((struct targbh_cmd_desc*)atio->ccb_h.ccb_descr)->atio_link; - xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.cab.ccb_h.func_code = XPT_ABORT; ccb.cab.abort_ccb = (union ccb *)atio; xpt_action(&ccb); @@ -369,7 +369,7 @@ targbhdislun(struct cam_periph *periph) while ((ccb_h = SLIST_FIRST(&softc->immed_notify_slist)) != NULL) { SLIST_REMOVE_HEAD(&softc->immed_notify_slist, periph_links.sle); - xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.cab.ccb_h.func_code = XPT_ABORT; ccb.cab.abort_ccb = (union ccb *)ccb_h; xpt_action(&ccb); @@ -378,7 +378,7 @@ targbhdislun(struct cam_periph *periph) /* * Dissable this lun. */ - xpt_setup_ccb(&ccb.cel.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&ccb.cel.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccb.cel.ccb_h.func_code = XPT_EN_LUN; ccb.cel.enable = 0; xpt_action(&ccb); @@ -528,7 +528,7 @@ targbhstart(struct cam_periph *periph, u ccbh = TAILQ_FIRST(&softc->work_queue); } if (ccbh != NULL) - xpt_schedule(periph, /*priority*/1); + xpt_schedule(periph, CAM_PRIORITY_NORMAL); } static void @@ -647,7 +647,7 @@ targbhdone(struct cam_periph *periph, un } else { TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h, periph_links.tqe); - priority = 1; + priority = CAM_PRIORITY_NORMAL; } xpt_schedule(periph, priority); break; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_target.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_target.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_target.c 2009-09-23 01:14:50.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_target.c 2009-10-14 15:26:18.000000000 +0300 @@ -319,7 +319,7 @@ targioctl(struct cdev *dev, u_long cmd, else cdbg.flags = CAM_DEBUG_NONE; cam_periph_lock(softc->periph); - xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0); + xpt_setup_ccb(&cdbg.ccb_h, softc->path, CAM_PRIORITY_NORMAL); cdbg.ccb_h.func_code = XPT_DEBUG; cdbg.ccb_h.cbfcnp = targdone; @@ -410,7 +410,7 @@ targendislun(struct cam_path *path, int cam_status status; /* Tell the lun to begin answering selects */ - xpt_setup_ccb(&en_ccb.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&en_ccb.ccb_h, path, CAM_PRIORITY_NORMAL); en_ccb.ccb_h.func_code = XPT_EN_LUN; /* Don't need support for any vendor specific commands */ en_ccb.grp6_len = grp6_len; @@ -438,7 +438,7 @@ targenable(struct targ_softc *softc, str return (CAM_LUN_ALRDY_ENA); /* Make sure SIM supports target mode */ - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); status = cpi.ccb_h.status & CAM_STATUS_MASK; @@ -586,7 +586,7 @@ targwrite(struct cdev *dev, struct uio * break; } priority = fuword32(&user_ccb->ccb_h.pinfo.priority); - if (priority == -1) { + if (priority == CAM_PRIORITY_NONE) { error = EINVAL; break; } @@ -1100,7 +1100,7 @@ abort_all_pending(struct targ_softc *sof * Then abort all pending CCBs. * targdone() will return the aborted CCB via user_ccb_queue */ - xpt_setup_ccb(&cab.ccb_h, softc->path, /*priority*/0); + xpt_setup_ccb(&cab.ccb_h, softc->path, CAM_PRIORITY_NORMAL); cab.ccb_h.func_code = XPT_ABORT; cab.ccb_h.status = CAM_REQ_CMP_ERR; TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue, periph_links.tqe) { diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/cam/scsi/scsi_xpt.c /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c --- /storage/FreeBSD/head/sys/cam/scsi/scsi_xpt.c 2009-07-14 22:06:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c 2009-10-14 15:26:18.000000000 +0300 @@ -555,6 +555,7 @@ static void scsi_action(union ccb *star static struct xpt_xport scsi_xport = { .alloc_device = scsi_alloc_device, .action = scsi_action, + .done = xpt_done_default, .async = scsi_dev_async, }; @@ -629,7 +630,7 @@ probeschedule(struct cam_periph *periph) softc = (probe_softc *)periph->softc; ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -667,7 +668,7 @@ probeschedule(struct cam_periph *periph) else softc->flags &= ~PROBE_NO_ANNOUNCE; - xpt_schedule(periph, ccb->ccb_h.pinfo.priority); + xpt_schedule(periph, CAM_PRIORITY_HOST); } static void @@ -880,7 +881,7 @@ proberequestdefaultnegotiation(struct ca { struct ccb_trans_settings cts; - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_USER_SETTINGS; xpt_action((union ccb *)&cts); @@ -902,7 +903,7 @@ proberequestbackoff(struct cam_periph *p struct ccb_trans_settings_spi *spi; memset(&cts, 0, sizeof (cts)); - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; xpt_action((union ccb *)&cts); @@ -1748,7 +1749,7 @@ scsi_scan_lun(struct cam_periph *periph, CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -1798,7 +1799,7 @@ scsi_scan_lun(struct cam_periph *periph, free(new_path, M_CAMXPT); return; } - xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1); + xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL); request_ccb->ccb_h.cbfcnp = xptscandone; request_ccb->ccb_h.func_code = XPT_SCAN_LUN; request_ccb->crcn.flags = flags; @@ -1896,7 +1897,7 @@ scsi_devise_transport(struct cam_path *p struct scsi_inquiry_data *inq_buf; /* Get transport information from the SIM */ - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -1956,7 +1957,7 @@ scsi_devise_transport(struct cam_path *p */ /* Tell the controller what we think */ - xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; cts.transport = path->device->transport; @@ -2084,7 +2085,7 @@ scsi_set_transfer_settings(struct ccb_tr inq_data = &device->inq_data; scsi = &cts->proto_specific.scsi; - xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1); + xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -2105,7 +2106,7 @@ scsi_set_transfer_settings(struct ccb_tr * Perform sanity checking against what the * controller and device can do. */ - xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1); + xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL); cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cur_cts.type = cts->type; xpt_action((union ccb *)&cur_cts); @@ -2273,7 +2274,7 @@ scsi_set_transfer_settings(struct ccb_tr device->tag_delay_count = 0; xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path, - /*priority*/1); + CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; crs.openings @@ -2306,7 +2307,7 @@ scsi_toggle_tags(struct cam_path *path) && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { struct ccb_trans_settings cts; - xpt_setup_ccb(&cts.ccb_h, path, 1); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.protocol = PROTO_SCSI; cts.protocol_version = PROTO_VERSION_UNSPECIFIED; cts.transport = XPORT_UNSPECIFIED; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/conf/files /storage/p4/scottl-camlock/src/sys/conf/files --- /storage/FreeBSD/head/sys/conf/files 2009-10-21 15:29:25.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/conf/files 2009-10-22 10:32:59.000000000 +0300 @@ -117,6 +117,7 @@ cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/ata/ata_da.c optional da +cam/ata/ata_pmp.c optional da cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct | ncv | nsp | stg cam/scsi/scsi_low_pisa.c optional ct | ncv | nsp | stg diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/conf/options /storage/p4/scottl-camlock/src/sys/conf/options --- /storage/FreeBSD/head/sys/conf/options 2009-10-22 10:34:23.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/conf/options 2009-10-22 10:32:59.000000000 +0300 @@ -350,6 +350,7 @@ ISCSI_INITIATOR_DEBUG opt_iscsi_initiato # Options used in the 'ata' ATA/ATAPI driver ATA_STATIC_ID opt_ata.h ATA_NOPCI opt_ata.h +ATA_CAM opt_ata.h # Net stuff. ACCEPT_FILTER_DATA diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-all.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-all.c --- /storage/FreeBSD/head/sys/dev/ata/ata-all.c 2009-08-30 17:46:09.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-all.c 2009-10-14 15:27:03.000000000 +0300 @@ -50,6 +50,16 @@ __FBSDID("$FreeBSD: head/sys/dev/ata/ata #include #include +#ifdef ATA_CAM +#include +#include +#include +#include +#include +#include +#endif + +#ifndef ATA_CAM /* device structure */ static d_ioctl_t ata_ioctl; static struct cdevsw ata_cdevsw = { @@ -58,14 +68,21 @@ static struct cdevsw ata_cdevsw = { .d_ioctl = ata_ioctl, .d_name = "ata", }; +#endif /* prototypes */ +#ifndef ATA_CAM static void ata_boot_attach(void); static device_t ata_add_child(device_t, struct ata_device *, int); +#else +static void ataaction(struct cam_sim *sim, union ccb *ccb); +static void atapoll(struct cam_sim *sim); +#endif static void ata_conn_event(void *, int); static void bswap(int8_t *, int); static void btrim(int8_t *, int); static void bpack(int8_t *, int8_t *, int); +static void ata_interrupt_locked(void *data); /* global vars */ MALLOC_DEFINE(M_ATA, "ata_generic", "ATA driver generic layer"); @@ -115,6 +132,9 @@ ata_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); int error, rid; +#ifdef ATA_CAM + struct cam_devq *devq; +#endif /* check that we have a virgin channel to attach */ if (ch->r_irq) @@ -133,7 +153,9 @@ ata_attach(device_t dev) /* reset the controller HW, the channel and device(s) */ while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit) pause("ataatch", 1); +#ifndef ATA_CAM ATA_RESET(dev); +#endif ATA_LOCKING(dev, ATA_LF_UNLOCK); /* allocate DMA resources if DMA HW present*/ @@ -154,18 +176,61 @@ ata_attach(device_t dev) return error; } +#ifndef ATA_CAM /* probe and attach devices on this channel unless we are in early boot */ if (!ata_delayed_attach) ata_identify(dev); - return 0; + return (0); +#else + mtx_lock(&ch->state_mtx); + /* Create the device queue for our SIM. */ + devq = cam_simq_alloc(1); + if (devq == NULL) { + device_printf(dev, "Unable to allocate simq\n"); + error = ENOMEM; + goto err1; + } + /* Construct SIM entry */ + ch->sim = cam_sim_alloc(ataaction, atapoll, "ata", ch, + device_get_unit(dev), &ch->state_mtx, 1, 0, devq); + if (ch->sim == NULL) { + device_printf(dev, "unable to allocate sim\n"); + error = ENOMEM; + goto err2; + } + if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) { + device_printf(dev, "unable to register xpt bus\n"); + error = ENXIO; + goto err2; + } + if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + device_printf(dev, "unable to create path\n"); + error = ENXIO; + goto err3; + } + mtx_unlock(&ch->state_mtx); + return (0); + +err3: + xpt_bus_deregister(cam_sim_path(ch->sim)); +err2: + cam_sim_free(ch->sim, /*free_devq*/TRUE); +err1: + bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); + mtx_unlock(&ch->state_mtx); + return (error); +#endif } int ata_detach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); +#ifndef ATA_CAM device_t *children; int nchildren, i; +#endif /* check that we have a valid channel to detach */ if (!ch->r_irq) @@ -176,6 +241,7 @@ ata_detach(device_t dev) ch->state |= ATA_STALL_QUEUE; mtx_unlock(&ch->state_mtx); +#ifndef ATA_CAM /* detach & delete all children */ if (!device_get_children(dev, &children, &nchildren)) { for (i = 0; i < nchildren; i++) @@ -183,8 +249,18 @@ ata_detach(device_t dev) device_delete_child(dev, children[i]); free(children, M_TEMP); } +#endif taskqueue_drain(taskqueue_thread, &ch->conntask); +#ifdef ATA_CAM + mtx_lock(&ch->state_mtx); + xpt_async(AC_LOST_DEVICE, ch->path, NULL); + xpt_free_path(ch->path); + xpt_bus_deregister(cam_sim_path(ch->sim)); + cam_sim_free(ch->sim, /*free_devq*/TRUE); + mtx_unlock(&ch->state_mtx); +#endif + /* release resources */ bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); @@ -203,8 +279,11 @@ static void ata_conn_event(void *context, int dummy) { device_t dev = (device_t)context; + struct ata_channel *ch = device_get_softc(dev); + mtx_lock(&ch->state_mtx); ata_reinit(dev); + mtx_unlock(&ch->state_mtx); } int @@ -212,6 +291,7 @@ ata_reinit(device_t dev) { struct ata_channel *ch = device_get_softc(dev); struct ata_request *request; +#ifndef ATA_CAM device_t *children; int nchildren, i; @@ -298,7 +378,23 @@ ata_reinit(device_t dev) /* kick off requests on the queue */ ata_start(dev); - return 0; +#else + if ((request = ch->running)) { + ch->running = NULL; + if (ch->state == ATA_ACTIVE) + ch->state = ATA_IDLE; + callout_stop(&request->callout); + if (ch->dma.unload) + ch->dma.unload(request); + request->result = ERESTART; + ata_cam_end_transaction(dev, request); + } + /* reset the controller HW, the channel and device(s) */ + ATA_RESET(dev); + /* Tell the XPT about the event */ + xpt_async(AC_BUS_RESET, ch->path, NULL); +#endif + return(0); } int @@ -310,6 +406,7 @@ ata_suspend(device_t dev) if (!dev || !(ch = device_get_softc(dev))) return ENXIO; +#ifndef ATA_CAM /* wait for the channel to be IDLE or detached before suspending */ while (ch->r_irq) { mtx_lock(&ch->state_mtx); @@ -322,7 +419,8 @@ ata_suspend(device_t dev) tsleep(ch, PRIBIO, "atasusp", hz/10); } ATA_LOCKING(dev, ATA_LF_UNLOCK); - return 0; +#endif + return(0); } int @@ -337,18 +435,36 @@ ata_resume(device_t dev) /* reinit the devices, we dont know what mode/state they are in */ error = ata_reinit(dev); +#ifndef ATA_CAM /* kick off requests on the queue */ ata_start(dev); +#endif return error; } void ata_interrupt(void *data) { +#ifdef ATA_CAM + struct ata_channel *ch = (struct ata_channel *)data; + + mtx_lock(&ch->state_mtx); +#endif + ata_interrupt_locked(data); +#ifdef ATA_CAM + mtx_unlock(&ch->state_mtx); +#endif +} + +static void +ata_interrupt_locked(void *data) +{ struct ata_channel *ch = (struct ata_channel *)data; struct ata_request *request; +#ifndef ATA_CAM mtx_lock(&ch->state_mtx); +#endif do { /* ignore interrupt if its not for us */ if (ch->hw.status && !ch->hw.status(ch->dev)) @@ -374,18 +490,25 @@ ata_interrupt(void *data) ch->running = NULL; if (ch->state == ATA_ACTIVE) ch->state = ATA_IDLE; +#ifdef ATA_CAM + ata_cam_end_transaction(ch->dev, request); +#else mtx_unlock(&ch->state_mtx); ATA_LOCKING(ch->dev, ATA_LF_UNLOCK); ata_finish(request); +#endif return; } } while (0); +#ifndef ATA_CAM mtx_unlock(&ch->state_mtx); +#endif } /* * device related interfaces */ +#ifndef ATA_CAM static int ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int32_t flag, struct thread *td) @@ -467,6 +590,7 @@ ata_ioctl(struct cdev *dev, u_long cmd, } return error; } +#endif int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) @@ -566,6 +690,7 @@ ata_device_ioctl(device_t dev, u_long cm } } +#ifndef ATA_CAM static void ata_boot_attach(void) { @@ -590,11 +715,12 @@ ata_boot_attach(void) mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */ } - +#endif /* * misc support functions */ +#ifndef ATA_CAM static device_t ata_add_child(device_t parent, struct ata_device *atadev, int unit) { @@ -609,6 +735,7 @@ ata_add_child(device_t parent, struct at } return child; } +#endif int ata_getparam(struct ata_device *atadev, int init) @@ -705,6 +832,7 @@ ata_getparam(struct ata_device *atadev, return error; } +#ifndef ATA_CAM int ata_identify(device_t dev) { @@ -778,6 +906,7 @@ ata_identify(device_t dev) mtx_unlock(&Giant); return 0; } +#endif void ata_default_registers(device_t dev) @@ -798,10 +927,10 @@ ata_default_registers(device_t dev) void ata_modify_if_48bit(struct ata_request *request) { - struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_channel *ch = device_get_softc(request->parent); struct ata_device *atadev = device_get_softc(request->dev); - atadev->flags &= ~ATA_D_48BIT_ACTIVE; + request->flags &= ~ATA_R_48BIT; if (((request->u.ata.lba + request->u.ata.count) >= ATA_MAX_28BIT_LBA || request->u.ata.count > 256) && @@ -875,7 +1004,7 @@ ata_modify_if_48bit(struct ata_request * default: return; } - atadev->flags |= ATA_D_48BIT_ACTIVE; + request->flags |= ATA_R_48BIT; } else if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) { @@ -893,7 +1022,7 @@ ata_modify_if_48bit(struct ata_request * default: return; } - atadev->flags |= ATA_D_48BIT_ACTIVE; + request->flags |= ATA_R_48BIT; } } @@ -1084,6 +1213,288 @@ bpack(int8_t *src, int8_t *dst, int len) dst[j] = 0x00; } +#ifdef ATA_CAM +void +ata_cam_begin_transaction(device_t dev, union ccb *ccb) +{ + struct ata_channel *ch = device_get_softc(dev); + struct ata_request *request; + + if (!(request = ata_alloc_request())) { + device_printf(dev, "FAILURE - out of memory in start\n"); + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + return; + } + bzero(request, sizeof(*request)); + + /* setup request */ + request->dev = NULL; + request->parent = dev; + request->unit = ccb->ccb_h.target_id; + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + request->data = ccb->ataio.data_ptr; + request->bytecount = ccb->ataio.dxfer_len; + request->u.ata.command = ccb->ataio.cmd.command; + request->u.ata.feature = ((uint16_t)ccb->ataio.cmd.features_exp << 8) | + (uint16_t)ccb->ataio.cmd.features; + request->u.ata.count = ((uint16_t)ccb->ataio.cmd.sector_count_exp << 8) | + (uint16_t)ccb->ataio.cmd.sector_count; + if (ccb->ataio.cmd.flags & CAM_ATAIO_48BIT) { + request->flags |= ATA_R_48BIT; + request->u.ata.lba = + ((uint64_t)ccb->ataio.cmd.lba_high_exp << 40) | + ((uint64_t)ccb->ataio.cmd.lba_mid_exp << 32) | + ((uint64_t)ccb->ataio.cmd.lba_low_exp << 24); + } else { + request->u.ata.lba = + ((uint64_t)(ccb->ataio.cmd.device & 0x0f) << 24); + } + request->u.ata.lba |= ((uint64_t)ccb->ataio.cmd.lba_high << 16) | + ((uint64_t)ccb->ataio.cmd.lba_mid << 8) | + (uint64_t)ccb->ataio.cmd.lba_low; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && + ccb->ataio.cmd.flags & CAM_ATAIO_DMA) + request->flags |= ATA_R_DMA; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) + request->flags |= ATA_R_READ; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) + request->flags |= ATA_R_WRITE; + } else { + request->data = ccb->csio.data_ptr; + request->bytecount = ccb->csio.dxfer_len; + bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ? + ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes, + request->u.atapi.ccb, ccb->csio.cdb_len); + request->flags |= ATA_R_ATAPI; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE /*&& + ccb->ataio.cmd.flags & CAM_ATAIO_DMA*/) + request->flags |= ATA_R_DMA; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) + request->flags |= ATA_R_READ; + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) + request->flags |= ATA_R_WRITE; + } + request->transfersize = min(request->bytecount, 16*512); +// request->callback = ad_done; + request->retries = 0; + request->timeout = (ccb->ccb_h.timeout + 999) / 1000; + callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); + request->ccb = ccb; + + ch->running = request; + ch->state = ATA_ACTIVE; + if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) { + ch->running = NULL; + ch->state = ATA_IDLE; + ata_cam_end_transaction(dev, request); + return; + } +} + +void +ata_cam_end_transaction(device_t dev, struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(dev); + union ccb *ccb = request->ccb; + + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + if (request->flags & ATA_R_TIMEOUT) { + xpt_freeze_simq(ch->sim, 1); + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_CMD_TIMEOUT | CAM_RELEASE_SIMQ; + } else if (request->status & ATA_S_ERROR) { + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR; + } else { + ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + } + } else if (request->result == ERESTART) + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + else if (request->result != 0) + ccb->ccb_h.status |= CAM_REQ_CMP_ERR; + else + ccb->ccb_h.status |= CAM_REQ_CMP; + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP && + !(ccb->ccb_h.status & CAM_DEV_QFRZN)) { + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status |= CAM_DEV_QFRZN; + } + if (ccb->ccb_h.func_code == XPT_ATA_IO && + ((request->status & ATA_S_ERROR) || + (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT))) { + struct ata_res *res = &ccb->ataio.res; + res->status = request->status; + res->error = request->error; + res->lba_low = request->u.ata.lba; + res->lba_mid = request->u.ata.lba >> 8; + res->lba_high = request->u.ata.lba >> 16; + res->device = request->u.ata.lba >> 24; + res->lba_low_exp = request->u.ata.lba >> 24; + res->lba_mid_exp = request->u.ata.lba >> 32; + res->lba_high_exp = request->u.ata.lba >> 40; + res->sector_count = request->u.ata.count; + res->sector_count_exp = request->u.ata.count >> 8; + } + ata_free_request(request); + xpt_done(ccb); +} + +static void +ataaction(struct cam_sim *sim, union ccb *ccb) +{ + device_t dev; + struct ata_channel *ch; + + CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ataaction func_code=%x\n", + ccb->ccb_h.func_code)); + + ch = (struct ata_channel *)cam_sim_softc(sim); + dev = ch->dev; + switch (ccb->ccb_h.func_code) { + /* Common cases first */ + case XPT_ATA_IO: /* Execute the requested I/O operation */ + case XPT_SCSI_IO: + if ((ch->devices & ((ATA_ATA_MASTER | ATA_ATAPI_MASTER) + << ccb->ccb_h.target_id)) == 0) { + ccb->ccb_h.status = CAM_SEL_TIMEOUT; + xpt_done(ccb); + break; + } + if (ch->running) + device_printf(dev, "already running!\n"); + if (ccb->ccb_h.func_code == XPT_ATA_IO && + (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) && + (ccb->ataio.cmd.control & ATA_A_RESET)) { + struct ata_res *res = &ccb->ataio.res; + + bzero(res, sizeof(*res)); + if (ch->devices & (ATA_ATA_MASTER << ccb->ccb_h.target_id)) { + res->lba_high = 0; + res->lba_mid = 0; + } else { + res->lba_high = 0xeb; + res->lba_mid = 0x14; + } + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + ata_cam_begin_transaction(dev, ccb); + break; + case XPT_EN_LUN: /* Enable LUN as a target */ + case XPT_TARGET_IO: /* Execute target I/O request */ + case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ + case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ + case XPT_ABORT: /* Abort the specified CCB */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + case XPT_SET_TRAN_SETTINGS: + { + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + case XPT_GET_TRAN_SETTINGS: + /* Get default/user set transfer settings for the target */ + { + struct ccb_trans_settings *cts = &ccb->cts; + + cts->protocol = PROTO_ATA; + cts->protocol_version = PROTO_VERSION_UNSPECIFIED; + cts->transport = XPORT_ATA; + cts->transport_version = XPORT_VERSION_UNSPECIFIED; + cts->proto_specific.valid = 0; + cts->xport_specific.sata.valid = 0; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } +#if 0 + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg; + uint32_t size_mb; + uint32_t secs_per_cylinder; + + ccg = &ccb->ccg; + size_mb = ccg->volume_size + / ((1024L * 1024L) / ccg->block_size); + if (size_mb >= 1024 && (aha->extended_trans != 0)) { + if (size_mb >= 2048) { + ccg->heads = 255; + ccg->secs_per_track = 63; + } else { + ccg->heads = 128; + ccg->secs_per_track = 32; + } + } else { + ccg->heads = 64; + ccg->secs_per_track = 32; + } + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } +#endif + case XPT_RESET_BUS: /* Reset the specified SCSI bus */ + case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ + ata_reinit(dev); + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + case XPT_TERM_IO: /* Terminate the I/O process */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + case XPT_PATH_INQ: /* Path routing inquiry */ + { + struct ccb_pathinq *cpi = &ccb->cpi; + + cpi->version_num = 1; /* XXX??? */ + cpi->hba_inquiry = PI_SDTR_ABLE; + cpi->target_sprt = 0; + cpi->hba_misc = PIM_SEQSCAN; + cpi->hba_eng_cnt = 0; + cpi->max_target = 1; + cpi->max_lun = 0; + cpi->initiator_id = 0; + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 150000; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "ATA", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->transport = XPORT_ATA; + cpi->transport_version = XPORT_VERSION_UNSPECIFIED; + cpi->protocol = PROTO_ATA; + cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; + cpi->maxio = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS; + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } +} + +static void +atapoll(struct cam_sim *sim) +{ + struct ata_channel *ch = (struct ata_channel *)cam_sim_softc(sim); + + ata_interrupt_locked(ch); +} +#endif /* * module handeling @@ -1091,10 +1502,13 @@ bpack(int8_t *src, int8_t *dst, int len) static int ata_module_event_handler(module_t mod, int what, void *arg) { +#ifndef ATA_CAM static struct cdev *atacdev; +#endif switch (what) { case MOD_LOAD: +#ifndef ATA_CAM /* register controlling device */ atacdev = make_dev(&ata_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0600, "ata"); @@ -1112,11 +1526,14 @@ ata_module_event_handler(module_t mod, i free(ata_delayed_attach, M_TEMP); } } +#endif return 0; case MOD_UNLOAD: +#ifndef ATA_CAM /* deregister controlling device */ destroy_dev(atacdev); +#endif return 0; default: diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-all.h /storage/p4/scottl-camlock/src/sys/dev/ata/ata-all.h --- /storage/FreeBSD/head/sys/dev/ata/ata-all.h 2009-06-24 21:56:47.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-all.h 2009-10-14 15:27:03.000000000 +0300 @@ -246,7 +246,7 @@ #define ATA_AHCI_CL_OFFSET 0 #define ATA_AHCI_FB_OFFSET (ATA_AHCI_CL_SIZE * 32) #define ATA_AHCI_CT_OFFSET (ATA_AHCI_FB_OFFSET + 4096) -#define ATA_AHCI_CT_SIZE (1024 + 128) +#define ATA_AHCI_CT_SIZE (2176 + 128) struct ata_ahci_dma_prd { u_int64_t dba; @@ -260,7 +260,7 @@ struct ata_ahci_cmd_tab { u_int8_t cfis[64]; u_int8_t acmd[32]; u_int8_t reserved[32]; -#define ATA_AHCI_DMA_ENTRIES 64 +#define ATA_AHCI_DMA_ENTRIES 129 struct ata_ahci_dma_prd prd_tab[ATA_AHCI_DMA_ENTRIES]; } __packed; @@ -355,6 +355,7 @@ struct ata_composite { struct ata_request { device_t dev; /* device handle */ device_t parent; /* channel handle */ + int unit; /* physical unit */ union { struct { u_int8_t command; /* command reg */ @@ -380,6 +381,7 @@ struct ata_request { #define ATA_R_DMA 0x00000010 #define ATA_R_QUIET 0x00000020 #define ATA_R_TIMEOUT 0x00000040 +#define ATA_R_48BIT 0x00000080 #define ATA_R_ORDERED 0x00000100 #define ATA_R_AT_HEAD 0x00000200 @@ -387,6 +389,9 @@ struct ata_request { #define ATA_R_THREAD 0x00000800 #define ATA_R_DIRECT 0x00001000 +#define ATA_R_ATAPI16 0x00010000 +#define ATA_R_ATAPI_INTR 0x00020000 + #define ATA_R_DEBUG 0x10000000 #define ATA_R_DANGER1 0x20000000 #define ATA_R_DANGER2 0x40000000 @@ -407,6 +412,9 @@ struct ata_request { struct ata_composite *composite; /* for composite atomic ops */ void *driver; /* driver specific */ TAILQ_ENTRY(ata_request) chain; /* list management */ +#ifdef ATA_CAM + union ccb *ccb; +#endif }; /* define this for debugging request processing */ @@ -414,7 +422,7 @@ struct ata_request { #define ATA_DEBUG_RQ(request, string) \ { \ if (request->flags & ATA_R_DEBUG) \ - device_printf(request->dev, "req=%p %s " string "\n", \ + device_printf(request->parent, "req=%p %s " string "\n", \ request, ata_cmd2str(request)); \ } #else @@ -440,7 +448,6 @@ struct ata_device { #define ATA_D_USE_CHS 0x0001 #define ATA_D_MEDIA_CHANGED 0x0002 #define ATA_D_ENC_PRESENT 0x0004 -#define ATA_D_48BIT_ACTIVE 0x0008 }; /* structure for holding DMA Physical Region Descriptors (PRD) entries */ @@ -474,7 +481,7 @@ struct ata_dma { u_int8_t *work; /* workspace */ bus_addr_t work_bus; /* bus address of dmatab */ -#define ATA_DMA_SLOTS 32 +#define ATA_DMA_SLOTS 1 int dma_slots; /* DMA slots allocated */ struct ata_dmaslot slot[ATA_DMA_SLOTS]; u_int32_t alignment; /* DMA SG list alignment */ @@ -550,6 +557,10 @@ struct ata_channel { struct ata_request *freezepoint; /* composite freezepoint */ struct ata_request *running; /* currently running request */ struct task conntask; /* PHY events handling task */ +#ifdef ATA_CAM + struct cam_sim *sim; + struct cam_path *path; +#endif }; /* disk bay/enclosure related */ @@ -589,6 +600,10 @@ int ata_pmode(struct ata_params *ap); int ata_wmode(struct ata_params *ap); int ata_umode(struct ata_params *ap); int ata_limit_mode(device_t dev, int mode, int maxmode); +#ifdef ATA_CAM +void ata_cam_begin_transaction(device_t dev, union ccb *ccb); +void ata_cam_end_transaction(device_t dev, struct ata_request *request); +#endif /* ata-queue.c: */ int ata_controlcmd(device_t dev, u_int8_t command, u_int16_t feature, u_int64_t lba, u_int16_t count); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-dma.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-dma.c --- /storage/FreeBSD/head/sys/dev/ata/ata-dma.c 2009-09-06 17:23:22.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-dma.c 2009-10-14 15:27:03.000000000 +0300 @@ -78,7 +78,7 @@ ata_dmainit(device_t dev) ch->dma.segsize = 65536; ch->dma.max_iosize = 128 * DEV_BSIZE; ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT; - ch->dma.dma_slots = 6; + ch->dma.dma_slots = 1; if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma.alignment, 0, ch->dma.max_address, BUS_SPACE_MAXADDR, @@ -256,37 +256,36 @@ static int ata_dmaload(struct ata_request *request, void *addr, int *entries) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); struct ata_dmasetprd_args dspa; int error; ATA_DEBUG_RQ(request, "dmaload"); if (request->dma) { - device_printf(request->dev, + device_printf(request->parent, "FAILURE - already active DMA on this device\n"); return EIO; } if (!request->bytecount) { - device_printf(request->dev, + device_printf(request->parent, "FAILURE - zero length DMA transfer attempted\n"); return EIO; } if (request->bytecount & (ch->dma.alignment - 1)) { - device_printf(request->dev, + device_printf(request->parent, "FAILURE - odd-sized DMA transfer attempt %d %% %d\n", request->bytecount, ch->dma.alignment); return EIO; } if (request->bytecount > ch->dma.max_iosize) { - device_printf(request->dev, + device_printf(request->parent, "FAILURE - oversized DMA transfer attempt %d > %d\n", request->bytecount, ch->dma.max_iosize); return EIO; } - /* set our slot, unit for simplicity XXX SOS NCQ will change that */ - request->dma = &ch->dma.slot[atadev->unit]; + /* set our slot. XXX SOS NCQ will change that */ + request->dma = &ch->dma.slot[0]; if (addr) dspa.dmatab = addr; @@ -297,7 +296,7 @@ ata_dmaload(struct ata_request *request, request->data, request->bytecount, ch->dma.setprd, &dspa, BUS_DMA_NOWAIT)) || (error = dspa.error)) { - device_printf(request->dev, "FAILURE - load data\n"); + device_printf(request->parent, "FAILURE - load data\n"); goto error; } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-lowlevel.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-lowlevel.c --- /storage/FreeBSD/head/sys/dev/ata/ata-lowlevel.c 2009-03-14 17:10:01.000000000 +0200 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-lowlevel.c 2009-10-14 15:27:03.000000000 +0300 @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD: head/sys/dev/ata/ata /* prototypes */ static int ata_generic_status(device_t dev); -static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t); +static int ata_wait(struct ata_channel *ch, int unit, u_int8_t); static void ata_pio_read(struct ata_request *, int); static void ata_pio_write(struct ata_request *, int); static void ata_tf_read(struct ata_request *); @@ -77,7 +77,6 @@ int ata_begin_transaction(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); int dummy, error; ATA_DEBUG_RQ(request, "begin transaction"); @@ -88,9 +87,6 @@ ata_begin_transaction(struct ata_request (ATA_R_ATAPI | ATA_R_DMA | ATA_R_WRITE))) request->flags &= ~ATA_R_DMA; - /* check for 48 bit access and convert if needed */ - ata_modify_if_48bit(request); - switch (request->flags & (ATA_R_ATAPI | ATA_R_DMA)) { /* ATA PIO data transfer and control commands */ @@ -101,7 +97,7 @@ ata_begin_transaction(struct ata_request /* issue command */ if (ch->hw.command(request)) { - device_printf(request->dev, "error issuing %s command\n", + device_printf(request->parent, "error issuing %s command\n", ata_cmd2str(request)); request->result = EIO; goto begin_finished; @@ -122,8 +118,8 @@ ata_begin_transaction(struct ata_request /* if write command output the data */ if (write) { - if (ata_wait(ch, atadev, (ATA_S_READY | ATA_S_DRQ)) < 0) { - device_printf(request->dev, + if (ata_wait(ch, request->unit, (ATA_S_READY | ATA_S_DRQ)) < 0) { + device_printf(request->parent, "timeout waiting for write DRQ\n"); request->result = EIO; goto begin_finished; @@ -137,14 +133,14 @@ ata_begin_transaction(struct ata_request case ATA_R_DMA: /* check sanity, setup SG list and DMA engine */ if ((error = ch->dma.load(request, NULL, &dummy))) { - device_printf(request->dev, "setting up DMA failed\n"); + device_printf(request->parent, "setting up DMA failed\n"); request->result = error; goto begin_finished; } /* issue command */ if (ch->hw.command(request)) { - device_printf(request->dev, "error issuing %s command\n", + device_printf(request->parent, "error issuing %s command\n", ata_cmd2str(request)); request->result = EIO; goto begin_finished; @@ -152,7 +148,7 @@ ata_begin_transaction(struct ata_request /* start DMA engine */ if (ch->dma.start && ch->dma.start(request)) { - device_printf(request->dev, "error starting DMA\n"); + device_printf(request->parent, "error starting DMA\n"); request->result = EIO; goto begin_finished; } @@ -162,7 +158,7 @@ ata_begin_transaction(struct ata_request case ATA_R_ATAPI: /* is this just a POLL DSC command ? */ if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) { - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit)); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit)); DELAY(10); if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC)) request->result = EBUSY; @@ -171,7 +167,7 @@ ata_begin_transaction(struct ata_request /* start ATAPI operation */ if (ch->hw.command(request)) { - device_printf(request->dev, "error issuing ATA PACKET command\n"); + device_printf(request->parent, "error issuing ATA PACKET command\n"); request->result = EIO; goto begin_finished; } @@ -181,7 +177,7 @@ ata_begin_transaction(struct ata_request case ATA_R_ATAPI|ATA_R_DMA: /* is this just a POLL DSC command ? */ if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) { - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit)); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit)); DELAY(10); if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC)) request->result = EBUSY; @@ -190,14 +186,14 @@ ata_begin_transaction(struct ata_request /* check sanity, setup SG list and DMA engine */ if ((error = ch->dma.load(request, NULL, &dummy))) { - device_printf(request->dev, "setting up DMA failed\n"); + device_printf(request->parent, "setting up DMA failed\n"); request->result = error; goto begin_finished; } /* start ATAPI operation */ if (ch->hw.command(request)) { - device_printf(request->dev, "error issuing ATA PACKET command\n"); + device_printf(request->parent, "error issuing ATA PACKET command\n"); request->result = EIO; goto begin_finished; } @@ -229,7 +225,6 @@ int ata_end_transaction(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); int length; ATA_DEBUG_RQ(request, "end transaction"); @@ -266,8 +261,8 @@ ata_end_transaction(struct ata_request * if (request->u.ata.command != ATA_ATAPI_IDENTIFY) flags |= ATA_S_READY; - if (ata_wait(ch, atadev, flags) < 0) { - device_printf(request->dev, + if (ata_wait(ch, request->unit, flags) < 0) { + device_printf(request->parent, "timeout waiting for read DRQ\n"); request->result = EIO; goto end_finished; @@ -290,8 +285,8 @@ ata_end_transaction(struct ata_request * if (request->flags & ATA_R_WRITE) { /* if we get an error here we are done with the HW */ - if (ata_wait(ch, atadev, (ATA_S_READY | ATA_S_DRQ)) < 0) { - device_printf(request->dev, + if (ata_wait(ch, request->unit, (ATA_S_READY | ATA_S_DRQ)) < 0) { + device_printf(request->parent, "timeout waiting for write DRQ\n"); request->status = ATA_IDX_INB(ch, ATA_STATUS); goto end_finished; @@ -347,20 +342,19 @@ ata_end_transaction(struct ata_request * DELAY(10); if (!(request->status & ATA_S_DRQ)) { - device_printf(request->dev, "command interrupt without DRQ\n"); + device_printf(request->parent, "command interrupt without DRQ\n"); request->status = ATA_S_ERROR; goto end_finished; } ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb, - (atadev->param.config & - ATA_PROTO_MASK)== ATA_PROTO_ATAPI_12 ? 6 : 8); + (request->flags & ATA_R_ATAPI16) ? 8 : 6); /* return wait for interrupt */ goto end_continue; case ATAPI_P_WRITE: if (request->flags & ATA_R_READ) { request->status = ATA_S_ERROR; - device_printf(request->dev, + device_printf(request->parent, "%s trying to write on read buffer\n", ata_cmd2str(request)); goto end_finished; @@ -378,7 +372,7 @@ ata_end_transaction(struct ata_request * case ATAPI_P_READ: if (request->flags & ATA_R_WRITE) { request->status = ATA_S_ERROR; - device_printf(request->dev, + device_printf(request->parent, "%s trying to read on write buffer\n", ata_cmd2str(request)); goto end_finished; @@ -393,7 +387,7 @@ ata_end_transaction(struct ata_request * goto end_continue; case ATAPI_P_DONEDRQ: - device_printf(request->dev, + device_printf(request->parent, "WARNING - %s DONEDRQ non conformant device\n", ata_cmd2str(request)); if (request->flags & ATA_R_READ) { @@ -415,7 +409,7 @@ ata_end_transaction(struct ata_request * goto end_finished; default: - device_printf(request->dev, "unknown transfer phase\n"); + device_printf(request->parent, "unknown transfer phase\n"); request->status = ATA_S_ERROR; } @@ -603,7 +597,7 @@ ata_generic_status(device_t dev) } static int -ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask) +ata_wait(struct ata_channel *ch, int unit, u_int8_t mask) { u_int8_t status; int timeout = 0; @@ -616,7 +610,7 @@ ata_wait(struct ata_channel *ch, struct /* if drive fails status, reselect the drive and try again */ if (status == 0xff) { - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit)); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(unit)); timeout += 1000; DELAY(1000); continue; @@ -657,14 +651,13 @@ int ata_generic_command(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); /* select device */ - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit)); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit)); /* ready to issue command ? */ - if (ata_wait(ch, atadev, 0) < 0) { - device_printf(request->dev, "timeout waiting to issue command\n"); + if (ata_wait(ch, request->unit, 0) < 0) { + device_printf(request->parent, "timeout waiting to issue command\n"); return -1; } @@ -673,6 +666,7 @@ ata_generic_command(struct ata_request * if (request->flags & ATA_R_ATAPI) { int timeout = 5000; + int res; /* issue packet command to controller */ if (request->flags & ATA_R_DMA) { @@ -688,9 +682,16 @@ ata_generic_command(struct ata_request * ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_PACKET_CMD); /* command interrupt device ? just return and wait for interrupt */ - if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR) + if (request->flags & ATA_R_ATAPI_INTR) return 0; + /* command processed ? */ + res = ata_wait(ch, request->unit, 0); + if (res != 0) { + if (res < 0) + device_printf(request->parent, "timeout waiting for PACKET command\n"); + return (-1); + } /* wait for ready to write ATAPI command block */ while (timeout--) { int reason = ATA_IDX_INB(ch, ATA_IREASON); @@ -702,7 +703,7 @@ ata_generic_command(struct ata_request * DELAY(20); } if (timeout <= 0) { - device_printf(request->dev, "timeout waiting for ATAPI ready\n"); + device_printf(request->parent, "timeout waiting for ATAPI ready\n"); request->result = EIO; return -1; } @@ -712,8 +713,7 @@ ata_generic_command(struct ata_request * /* output command block */ ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb, - (atadev->param.config & ATA_PROTO_MASK) == - ATA_PROTO_ATAPI_12 ? 6 : 8); + (request->flags & ATA_R_ATAPI16) ? 8 : 6); } else { ch->hw.tf_write(request); @@ -728,9 +728,8 @@ static void ata_tf_read(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB); request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8); request->u.ata.lba = @@ -758,9 +757,11 @@ static void ata_tf_write(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); +#ifndef ATA_CAM struct ata_device *atadev = device_get_softc(request->dev); +#endif - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8); ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8); @@ -771,11 +772,12 @@ ata_tf_write(struct ata_request *request ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40); ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit)); } else { ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); +#ifndef ATA_CAM if (atadev->flags & ATA_D_USE_CHS) { int heads, sectors; @@ -793,18 +795,21 @@ ata_tf_write(struct ata_request *request (request->u.ata.lba / (sectors * heads))); ATA_IDX_OUTB(ch, ATA_CYL_MSB, (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) | (((request->u.ata.lba% (sectors * heads)) / sectors) & 0xf)); } else { +#endif ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); ATA_IDX_OUTB(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | + ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } } @@ -825,7 +830,7 @@ ata_pio_read(struct ata_request *request size / sizeof(int32_t)); if (request->transfersize < length) { - device_printf(request->dev, "WARNING - %s read data overrun %d>%d\n", + device_printf(request->parent, "WARNING - %s read data overrun %d>%d\n", ata_cmd2str(request), length, request->transfersize); for (resid = request->transfersize; resid < length; resid += sizeof(int16_t)) @@ -850,7 +855,7 @@ ata_pio_write(struct ata_request *reques size / sizeof(int32_t)); if (request->transfersize < length) { - device_printf(request->dev, "WARNING - %s write data underrun %d>%d\n", + device_printf(request->parent, "WARNING - %s write data underrun %d>%d\n", ata_cmd2str(request), length, request->transfersize); for (resid = request->transfersize; resid < length; resid += sizeof(int16_t)) diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-pci.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-pci.c --- /storage/FreeBSD/head/sys/dev/ata/ata-pci.c 2009-04-30 00:17:22.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-pci.c 2009-10-14 15:27:03.000000000 +0300 @@ -477,7 +477,7 @@ ata_pci_dmareset(device_t dev) ch->dma.flags &= ~ATA_DMA_ACTIVE; ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); if ((request = ch->running)) { - device_printf(request->dev, "DMA reset calling unload\n"); + device_printf(dev, "DMA reset calling unload\n"); ch->dma.unload(request); } } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-queue.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-queue.c --- /storage/FreeBSD/head/sys/dev/ata/ata-queue.c 2009-05-01 11:03:47.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-queue.c 2009-10-14 15:27:03.000000000 +0300 @@ -52,17 +52,25 @@ void ata_queue_request(struct ata_request *request) { struct ata_channel *ch; + struct ata_device *atadev = device_get_softc(request->dev); /* treat request as virgin (this might be an ATA_R_REQUEUE) */ request->result = request->status = request->error = 0; - /* check that the device is still valid */ + /* Prepare paramers required by low-level code. */ + request->unit = atadev->unit; if (!(request->parent = device_get_parent(request->dev))) { request->result = ENXIO; if (request->callback) (request->callback)(request); return; } + if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) + request->flags |= ATA_R_ATAPI16; + if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR) + request->flags |= ATA_R_ATAPI_INTR; + if ((request->flags & ATA_R_ATAPI) == 0) + ata_modify_if_48bit(request); ch = device_get_softc(request->parent); callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); if (!request->callback && !(request->flags & ATA_R_REQUEUE)) @@ -150,15 +158,11 @@ ata_atapicmd(device_t dev, u_int8_t *ccb int count, int flags, int timeout) { struct ata_request *request = ata_alloc_request(); - struct ata_device *atadev = device_get_softc(dev); int error = ENOMEM; if (request) { request->dev = dev; - if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) - bcopy(ccb, request->u.atapi.ccb, 12); - else - bcopy(ccb, request->u.atapi.ccb, 16); + bcopy(ccb, request->u.atapi.ccb, 16); request->data = data; request->bytecount = count; request->transfersize = min(request->bytecount, 65534); @@ -507,11 +511,18 @@ ata_timeout(struct ata_request *request) */ if (ch->state == ATA_ACTIVE) { request->flags |= ATA_R_TIMEOUT; - mtx_unlock(&ch->state_mtx); - ATA_LOCKING(ch->dev, ATA_LF_UNLOCK); if (ch->dma.unload) ch->dma.unload(request); +#ifdef ATA_CAM + ch->running = NULL; + ch->state = ATA_IDLE; + ata_cam_end_transaction(ch->dev, request); +#endif + mtx_unlock(&ch->state_mtx); + ATA_LOCKING(ch->dev, ATA_LF_UNLOCK); +#ifndef ATA_CAM ata_finish(request); +#endif } else { mtx_unlock(&ch->state_mtx); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/ata-sata.c /storage/p4/scottl-camlock/src/sys/dev/ata/ata-sata.c --- /storage/FreeBSD/head/sys/dev/ata/ata-sata.c 2009-06-24 21:56:47.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/ata-sata.c 2009-10-14 15:27:03.000000000 +0300 @@ -246,11 +246,10 @@ ata_sata_setmode(device_t dev, int mode) int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis) { - struct ata_device *atadev = device_get_softc(request->dev); if (request->flags & ATA_R_ATAPI) { fis[0] = 0x27; /* host to device */ - fis[1] = 0x80 | (atadev->unit & 0x0f); + fis[1] = 0x80 | (request->unit & 0x0f); fis[2] = ATA_PACKET_CMD; if (request->flags & (ATA_R_READ | ATA_R_WRITE)) fis[3] = ATA_F_DMA; @@ -263,16 +262,15 @@ ata_request2fis_h2d(struct ata_request * return 20; } else { - ata_modify_if_48bit(request); fis[0] = 0x27; /* host to device */ - fis[1] = 0x80 | (atadev->unit & 0x0f); + fis[1] = 0x80 | (request->unit & 0x0f); fis[2] = request->u.ata.command; fis[3] = request->u.ata.feature; fis[4] = request->u.ata.lba; fis[5] = request->u.ata.lba >> 8; fis[6] = request->u.ata.lba >> 16; fis[7] = ATA_D_LBA; - if (!(atadev->flags & ATA_D_48BIT_ACTIVE)) + if (!(request->flags & ATA_R_48BIT)) fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f)); fis[8] = request->u.ata.lba >> 24; fis[9] = request->u.ata.lba >> 32; @@ -339,9 +337,6 @@ ata_pm_identify(device_t dev) pm_chipid, pm_revision, pm_ports); } - /* realloc space for needed DMA slots */ - ch->dma.dma_slots = pm_ports; - /* reset all ports and register if anything connected */ for (port=0; port < pm_ports; port++) { u_int32_t signature; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/atapi-cd.c /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-cd.c --- /storage/FreeBSD/head/sys/dev/ata/atapi-cd.c 2009-07-08 09:08:58.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-cd.c 2009-10-14 15:27:03.000000000 +0300 @@ -863,9 +863,7 @@ acd_strategy(struct bio *bp) } request->dev = dev; request->bio = bp; - bcopy(ccb, request->u.atapi.ccb, - (atadev->param.config & ATA_PROTO_MASK) == - ATA_PROTO_ATAPI_12 ? 16 : 12); + bcopy(ccb, request->u.atapi.ccb, 16); request->data = bp->bio_data; request->bytecount = count * blocksize; request->transfersize = min(request->bytecount, 65534); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/atapi-fd.c /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-fd.c --- /storage/FreeBSD/head/sys/dev/ata/atapi-fd.c 2009-03-14 17:10:01.000000000 +0200 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-fd.c 2009-10-14 15:27:03.000000000 +0300 @@ -240,9 +240,7 @@ afd_strategy(struct bio *bp) } request->dev = dev; request->bio = bp; - bcopy(ccb, request->u.atapi.ccb, - (atadev->param.config & ATA_PROTO_MASK) == - ATA_PROTO_ATAPI_12 ? 16 : 12); + bcopy(ccb, request->u.atapi.ccb, 16); request->data = bp->bio_data; request->bytecount = count * fdp->sectorsize; request->transfersize = min(request->bytecount, 65534); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/atapi-tape.c /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-tape.c --- /storage/FreeBSD/head/sys/dev/ata/atapi-tape.c 2009-04-29 23:35:57.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/atapi-tape.c 2009-10-14 15:27:03.000000000 +0300 @@ -373,7 +373,6 @@ static void ast_strategy(struct bio *bp) { device_t dev = bp->bio_dev->si_drv1; - struct ata_device *atadev = device_get_softc(dev); struct ast_softc *stp = device_get_ivars(dev); struct ata_request *request; u_int32_t blkcount; @@ -426,9 +425,7 @@ ast_strategy(struct bio *bp) } request->dev = dev; request->driver = bp; - bcopy(ccb, request->u.atapi.ccb, - (atadev->param.config & ATA_PROTO_MASK) == - ATA_PROTO_ATAPI_12 ? 16 : 12); + bcopy(ccb, request->u.atapi.ccb, 16); request->data = bp->bio_data; request->bytecount = blkcount * stp->blksize; request->transfersize = min(request->bytecount, 65534); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-ahci.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-ahci.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-ahci.c 2009-07-08 09:00:09.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-ahci.c 2009-10-14 15:27:03.000000000 +0300 @@ -385,23 +385,22 @@ ata_ahci_status(device_t dev) static int ata_ahci_begin_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); struct ata_ahci_cmd_tab *ctp; struct ata_ahci_cmd_list *clp; int offset = ch->unit << 7; - int port = atadev->unit & 0x0f; + int port = request->unit & 0x0f; int entries = 0; int fis_size; /* get a piece of the workspace for this request */ ctp = (struct ata_ahci_cmd_tab *) - (ch->dma.work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE*request->tag)); + (ch->dma.work + ATA_AHCI_CT_OFFSET); /* setup the FIS for this request */ if (!(fis_size = ata_ahci_setup_fis(ctp, request))) { - device_printf(request->dev, "setting up SATA FIS failed\n"); + device_printf(request->parent, "setting up SATA FIS failed\n"); request->result = EIO; return ATA_OP_FINISHED; } @@ -409,7 +408,7 @@ ata_ahci_begin_transaction(struct ata_re /* if request moves data setup and load SG list */ if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { if (ch->dma.load(request, ctp->prd_tab, &entries)) { - device_printf(request->dev, "setting up DMA failed\n"); + device_printf(request->parent, "setting up DMA failed\n"); request->result = EIO; return ATA_OP_FINISHED; } @@ -417,7 +416,7 @@ ata_ahci_begin_transaction(struct ata_re /* setup the command list entry */ clp = (struct ata_ahci_cmd_list *) - (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); + (ch->dma.work + ATA_AHCI_CL_OFFSET); clp->prd_length = entries; clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) | @@ -426,12 +425,7 @@ ata_ahci_begin_transaction(struct ata_re (fis_size / sizeof(u_int32_t)) | (port << 12); clp->bytecount = 0; - clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET + - (ATA_AHCI_CT_SIZE * request->tag)); - - /* clear eventual ACTIVE bit */ - ATA_IDX_OUTL(ch, ATA_SACTIVE, - ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << request->tag)); + clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); /* set command type bit */ if (request->flags & ATA_R_ATAPI) @@ -444,7 +438,7 @@ ata_ahci_begin_transaction(struct ata_re ~ATA_AHCI_P_CMD_ATAPI); /* issue command to controller */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag)); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); if (!(request->flags & ATA_R_ATAPI)) { /* device reset doesn't interrupt */ @@ -476,7 +470,7 @@ ata_ahci_begin_transaction(struct ata_re static int ata_ahci_end_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); struct ata_ahci_cmd_list *clp; u_int32_t tf_data; @@ -495,13 +489,12 @@ ata_ahci_end_transaction(struct ata_requ /* on control commands read back registers to the request struct */ if (request->flags & ATA_R_CONTROL) { - struct ata_device *atadev = device_get_softc(request->dev); u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8); request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) | ((u_int64_t)fis[6] << 16); - if (atadev->flags & ATA_D_48BIT_ACTIVE) + if (request->flags & ATA_R_48BIT) request->u.ata.lba |= ((u_int64_t)fis[8] << 24) | ((u_int64_t)fis[9] << 32) | ((u_int64_t)fis[10] << 40); @@ -511,7 +504,7 @@ ata_ahci_end_transaction(struct ata_requ /* record how much data we actually moved */ clp = (struct ata_ahci_cmd_list *) - (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag)); + (ch->dma.work + ATA_AHCI_CL_OFFSET); request->donecount = clp->bytecount; /* release SG list etc */ diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-intel.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-intel.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-intel.c 2009-06-24 22:49:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-intel.c 2009-10-14 15:27:03.000000000 +0300 @@ -466,10 +466,12 @@ ata_intel_31244_status(device_t dev) static void ata_intel_31244_tf_write(struct ata_request *request) { - struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_channel *ch = device_get_softc(request->parent); +#ifndef ATA_CAM struct ata_device *atadev = device_get_softc(request->dev); +#endif - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | @@ -478,11 +480,12 @@ ata_intel_31244_tf_write(struct ata_requ ((request->u.ata.lba >> 8) & 0x00ff)); ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | ((request->u.ata.lba >> 16) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit)); } else { ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); +#ifndef ATA_CAM if (atadev->flags & ATA_D_USE_CHS) { int heads, sectors; @@ -499,18 +502,21 @@ ata_intel_31244_tf_write(struct ata_requ (request->u.ata.lba / (sectors * heads))); ATA_IDX_OUTB(ch, ATA_CYL_MSB, (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) | (((request->u.ata.lba% (sectors * heads)) / sectors) & 0xf)); } else { +#endif ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); ATA_IDX_OUTB(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | + ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-marvell.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-marvell.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-marvell.c 2009-10-07 08:22:18.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-marvell.c 2009-10-14 15:27:03.000000000 +0300 @@ -346,7 +346,7 @@ ata_marvell_edma_status(device_t dev) static int ata_marvell_edma_begin_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); u_int32_t req_in; u_int8_t *bytep; @@ -355,7 +355,9 @@ ata_marvell_edma_begin_transaction(struc /* only DMA R/W goes through the EMDA machine */ if (request->u.ata.command != ATA_READ_DMA && - request->u.ata.command != ATA_WRITE_DMA) { + request->u.ata.command != ATA_WRITE_DMA && + request->u.ata.command != ATA_READ_DMA48 && + request->u.ata.command != ATA_WRITE_DMA48) { /* disable the EDMA machinery */ if (ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001) @@ -363,12 +365,9 @@ ata_marvell_edma_begin_transaction(struc return ata_begin_transaction(request); } - /* check for 48 bit access and convert if needed */ - ata_modify_if_48bit(request); - /* check sanity, setup SG list and DMA engine */ if ((error = ch->dma.load(request, NULL, NULL))) { - device_printf(request->dev, "setting up DMA failed\n"); + device_printf(request->parent, "setting up DMA failed\n"); request->result = error; return ATA_OP_FINISHED; } @@ -438,7 +437,7 @@ ata_marvell_edma_begin_transaction(struc static int ata_marvell_edma_end_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); int offset = (ch->unit > 3 ? 0x30014 : 0x20014); u_int32_t icr = ATA_INL(ctlr->r_res1, offset); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-promise.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-promise.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-promise.c 2009-06-24 22:49:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-promise.c 2009-10-14 15:27:03.000000000 +0300 @@ -387,11 +387,10 @@ ata_promise_status(device_t dev) static int ata_promise_dmastart(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_OUTB(ctlr->r_res1, 0x11, ATA_INB(ctlr->r_res1, 0x11) | (ch->unit ? 0x08 : 0x02)); ATA_OUTL(ctlr->r_res1, ch->unit ? 0x24 : 0x20, @@ -411,12 +410,11 @@ ata_promise_dmastart(struct ata_request static int ata_promise_dmastop(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); int error; - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_OUTB(ctlr->r_res1, 0x11, ATA_INB(ctlr->r_res1, 0x11) & ~(ch->unit ? 0x08 : 0x02)); ATA_OUTL(ctlr->r_res1, ch->unit ? 0x24 : 0x20, 0); @@ -682,9 +680,8 @@ ata_promise_mio_status(device_t dev) static int ata_promise_mio_command(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); u_int32_t *wordp = (u_int32_t *)ch->dma.work; @@ -693,7 +690,7 @@ ata_promise_mio_command(struct ata_reque if ((ctlr->chip->cfg2 == PR_SATA2) || ((ctlr->chip->cfg2 == PR_CMBO2) && (ch->unit < 2))) { /* set portmultiplier port */ - ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), atadev->unit & 0x0f); + ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), request->unit & 0x0f); } /* XXX SOS add ATAPI commands support later */ @@ -1051,7 +1048,7 @@ ata_promise_sx4_intr(void *data) static int ata_promise_sx4_command(struct ata_request *request) { - device_t gparent = GRANDPARENT(request->dev); + device_t gparent = device_get_parent(request->parent); struct ata_pci_controller *ctlr = device_get_softc(gparent); struct ata_channel *ch = device_get_softc(request->parent); struct ata_dma_prdentry *prd; @@ -1158,15 +1155,14 @@ ata_promise_sx4_command(struct ata_reque static int ata_promise_apkt(u_int8_t *bytep, struct ata_request *request) { - struct ata_device *atadev = device_get_softc(request->dev); int i = 12; bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_PDC_WAIT_NBUSY|ATA_DRIVE; - bytep[i++] = ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit); + bytep[i++] = ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit); bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_CTL; bytep[i++] = ATA_A_4BIT; - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { bytep[i++] = ATA_PDC_2B | ATA_PDC_WRITE_REG | ATA_FEATURE; bytep[i++] = request->u.ata.feature >> 8; bytep[i++] = request->u.ata.feature; @@ -1183,7 +1179,7 @@ ata_promise_apkt(u_int8_t *bytep, struct bytep[i++] = request->u.ata.lba >> 40; bytep[i++] = request->u.ata.lba >> 16; bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE; - bytep[i++] = ATA_D_LBA | ATA_DEV(atadev->unit); + bytep[i++] = ATA_D_LBA | ATA_DEV(request->unit); } else { bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_FEATURE; @@ -1197,8 +1193,7 @@ ata_promise_apkt(u_int8_t *bytep, struct bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_CYL_MSB; bytep[i++] = request->u.ata.lba >> 16; bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE; - bytep[i++] = (atadev->flags & ATA_D_USE_CHS ? 0 : ATA_D_LBA) | - ATA_D_IBM | ATA_DEV(atadev->unit) | + bytep[i++] = ATA_D_LBA | ATA_D_IBM | ATA_DEV(request->unit) | ((request->u.ata.lba >> 24)&0xf); } bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_END | ATA_COMMAND; diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-serverworks.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-serverworks.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-serverworks.c 2009-06-24 22:49:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-serverworks.c 2009-10-14 15:27:03.000000000 +0300 @@ -228,9 +228,8 @@ static void ata_serverworks_tf_read(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); - struct ata_device *atadev = device_get_softc(request->dev); - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { u_int16_t temp; request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT); @@ -257,9 +256,11 @@ static void ata_serverworks_tf_write(struct ata_request *request) { struct ata_channel *ch = device_get_softc(request->parent); +#ifndef ATA_CAM struct ata_device *atadev = device_get_softc(request->dev); +#endif - if (atadev->flags & ATA_D_48BIT_ACTIVE) { + if (request->flags & ATA_R_48BIT) { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | @@ -268,11 +269,12 @@ ata_serverworks_tf_write(struct ata_requ ((request->u.ata.lba >> 8) & 0x00ff)); ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | ((request->u.ata.lba >> 16) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit)); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit)); } else { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); +#ifndef ATA_CAM if (atadev->flags & ATA_D_USE_CHS) { int heads, sectors; @@ -289,18 +291,21 @@ ata_serverworks_tf_write(struct ata_requ (request->u.ata.lba / (sectors * heads))); ATA_IDX_OUTW(ch, ATA_CYL_MSB, (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) | + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) | (((request->u.ata.lba% (sectors * heads)) / sectors) & 0xf)); } else { +#endif ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba); ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); ATA_IDX_OUTW(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) | + ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } } diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-siliconimage.c /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-siliconimage.c --- /storage/FreeBSD/head/sys/dev/ata/chipsets/ata-siliconimage.c 2009-06-24 22:49:16.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/dev/ata/chipsets/ata-siliconimage.c 2009-10-14 15:27:03.000000000 +0300 @@ -340,6 +340,7 @@ ata_sii_ch_attach(device_t dev) ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16)); } + ch->dma.max_iosize = (ATA_DMA_ENTRIES - 1) * PAGE_SIZE; if (ctlr->chip->cfg2 & SII_BUG) { /* work around errata in early chips */ ch->dma.boundary = 8192; @@ -457,7 +458,7 @@ struct ata_siiprb_dma_prdentry { u_int32_t control; } __packed; -#define ATA_SIIPRB_DMA_ENTRIES 125 +#define ATA_SIIPRB_DMA_ENTRIES 129 struct ata_siiprb_ata_command { struct ata_siiprb_dma_prdentry prd[ATA_SIIPRB_DMA_ENTRIES]; } __packed; @@ -542,7 +543,7 @@ ata_siiprb_status(device_t dev) static int ata_siiprb_begin_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); struct ata_siiprb_command *prb; struct ata_siiprb_dma_prdentry *prd; @@ -556,28 +557,25 @@ ata_siiprb_begin_transaction(struct ata_ } /* get a piece of the workspace for this request */ - prb = (struct ata_siiprb_command *) - (ch->dma.work + (sizeof(struct ata_siiprb_command) * request->tag)); + prb = (struct ata_siiprb_command *)ch->dma.work; /* clear the prb structure */ bzero(prb, sizeof(struct ata_siiprb_command)); /* setup the FIS for this request */ if (!ata_request2fis_h2d(request, &prb->fis[0])) { - device_printf(request->dev, "setting up SATA FIS failed\n"); + device_printf(request->parent, "setting up SATA FIS failed\n"); request->result = EIO; return ATA_OP_FINISHED; } /* setup transfer type */ if (request->flags & ATA_R_ATAPI) { - struct ata_device *atadev = device_get_softc(request->dev); - bcopy(request->u.atapi.ccb, prb->u.atapi.ccb, 16); - if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) - ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000020); - else + if (request->flags & ATA_R_ATAPI16) ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000020); + else + ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000020); if (request->flags & ATA_R_READ) prb->control = htole16(0x0010); if (request->flags & ATA_R_WRITE) @@ -590,19 +588,16 @@ ata_siiprb_begin_transaction(struct ata_ /* if request moves data setup and load SG list */ if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { if (ch->dma.load(request, prd, NULL)) { - device_printf(request->dev, "setting up DMA failed\n"); + device_printf(request->parent, "setting up DMA failed\n"); request->result = EIO; return ATA_OP_FINISHED; } } /* activate the prb */ - prb_bus = ch->dma.work_bus + - (sizeof(struct ata_siiprb_command) * request->tag); - ATA_OUTL(ctlr->r_res2, - 0x1c00 + offset + (request->tag * sizeof(u_int64_t)), prb_bus); - ATA_OUTL(ctlr->r_res2, - 0x1c04 + offset + (request->tag * sizeof(u_int64_t)), prb_bus>>32); + prb_bus = ch->dma.work_bus; + ATA_OUTL(ctlr->r_res2, 0x1c00 + offset, prb_bus); + ATA_OUTL(ctlr->r_res2, 0x1c04 + offset, prb_bus>>32); /* start the timeout */ callout_reset(&request->callout, request->timeout * hz, @@ -613,7 +608,7 @@ ata_siiprb_begin_transaction(struct ata_ static int ata_siiprb_end_transaction(struct ata_request *request) { - struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev)); + struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); struct ata_siiprb_command *prb; int offset = ch->unit * 0x2000; @@ -623,7 +618,7 @@ ata_siiprb_end_transaction(struct ata_re callout_stop(&request->callout); prb = (struct ata_siiprb_command *) - ((u_int8_t *)rman_get_virtual(ctlr->r_res2)+(request->tag << 7)+offset); + ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset); /* any controller errors flagged ? */ if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) { @@ -659,12 +654,10 @@ ata_siiprb_end_transaction(struct ata_re /* on control commands read back registers to the request struct */ if (request->flags & ATA_R_CONTROL) { - struct ata_device *atadev = device_get_softc(request->dev); - request->u.ata.count = prb->fis[12] | ((u_int16_t)prb->fis[13] << 8); request->u.ata.lba = prb->fis[4] | ((u_int64_t)prb->fis[5] << 8) | ((u_int64_t)prb->fis[6] << 16); - if (atadev->flags & ATA_D_48BIT_ACTIVE) + if (request->flags & ATA_R_48BIT) request->u.ata.lba |= ((u_int64_t)prb->fis[8] << 24) | ((u_int64_t)prb->fis[9] << 32) | ((u_int64_t)prb->fis[10] << 40); @@ -907,6 +900,7 @@ ata_siiprb_dmainit(device_t dev) /* note start and stop are not used here */ ch->dma.setprd = ata_siiprb_dmasetprd; ch->dma.max_address = BUS_SPACE_MAXADDR; + ch->dma.max_iosize = (ATA_SIIPRB_DMA_ENTRIES - 1) * PAGE_SIZE; } ATA_DECLARE_DRIVER(ata_sii); diff -ruNp -I FreeBSD --exclude .svn /storage/FreeBSD/head/sys/modules/cam/Makefile /storage/p4/scottl-camlock/src/sys/modules/cam/Makefile --- /storage/FreeBSD/head/sys/modules/cam/Makefile 2009-07-13 09:04:53.000000000 +0300 +++ /storage/p4/scottl-camlock/src/sys/modules/cam/Makefile 2009-10-14 15:28:33.000000000 +0300 @@ -28,6 +28,7 @@ SRCS+= scsi_xpt.c SRCS+= ata_all.c SRCS+= ata_xpt.c SRCS+= ata_da.c +SRCS+= ata_pmp.c EXPORT_SYMS= YES # XXX evaluate