From owner-freebsd-hackers@FreeBSD.ORG Thu Mar 31 10:17:16 2005 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 162E616A4CE; Thu, 31 Mar 2005 10:17:16 +0000 (GMT) Received: from pooker.samsco.org (pooker.samsco.org [168.103.85.57]) by mx1.FreeBSD.org (Postfix) with ESMTP id 12BAB43D53; Thu, 31 Mar 2005 10:17:13 +0000 (GMT) (envelope-from scottl@samsco.org) Received: from [192.168.254.21] (rat.samsco.home [192.168.254.21]) (authenticated bits=0) by pooker.samsco.org (8.13.1/8.13.1) with ESMTP id j2VAKsiJ016179; Thu, 31 Mar 2005 03:20:55 -0700 (MST) (envelope-from scottl@samsco.org) Message-ID: <424BCDAA.40604@samsco.org> Date: Thu, 31 Mar 2005 03:15:06 -0700 From: Scott Long User-Agent: Mozilla/5.0 (X11; U; FreeBSD amd64; en-US; rv:1.7.5) Gecko/20050321 X-Accept-Language: en-us, en MIME-Version: 1.0 To: thomas@freebsd.org Content-Type: multipart/mixed; boundary="------------090700030006080708070500" X-Spam-Status: No, score=-2.8 required=3.8 tests=ALL_TRUSTED autolearn=failed version=3.0.2 X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on pooker.samsco.org cc: hackers@freebsd.org cc: sos@freebsd.org Subject: ATAPICAM for ATA-MKIII X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Mar 2005 10:17:16 -0000 This is a multi-part message in MIME format. --------------090700030006080708070500 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Thomas, Attached are patches for atapicam for ATA-MKIII. I've only done light testing, but they seem to work as expected. They work both as a module and compiled into the kernel. Scott --------------090700030006080708070500 Content-Type: text/plain; name="atapicam.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="atapicam.diff" Index: ata-all.c =================================================================== RCS file: /usr/ncvs/src/sys/dev/ata/ata-all.c,v retrieving revision 1.236 diff -u -r1.236 ata-all.c --- ata-all.c 30 Mar 2005 12:03:37 -0000 1.236 +++ ata-all.c 31 Mar 2005 10:08:47 -0000 @@ -142,6 +142,8 @@ return error; } + device_add_child(dev, "atapicam", -1); + /* do not attach devices if we are in early boot */ if (ata_delayed_attach) return 0; Index: ata-all.h =================================================================== RCS file: /usr/ncvs/src/sys/dev/ata/ata-all.h,v retrieving revision 1.88 diff -u -r1.88 ata-all.h --- ata-all.h 30 Mar 2005 12:03:37 -0000 1.88 +++ ata-all.h 31 Mar 2005 08:05:36 -0000 @@ -270,6 +270,7 @@ int unit; /* physical unit */ #define ATA_MASTER 0x00 #define ATA_SLAVE 0x10 +#define ATA_ATAPI_CAM 0x100 struct ata_params param; /* ata param structure */ int mode; /* current transfermode */ Index: atapi-cam.c =================================================================== RCS file: /usr/ncvs/src/sys/dev/ata/atapi-cam.c,v retrieving revision 1.35 diff -u -r1.35 atapi-cam.c --- atapi-cam.c 17 Jun 2004 07:29:56 -0000 1.35 +++ atapi-cam.c 31 Mar 2005 10:08:36 -0000 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,23 @@ #include #include +#include + +/* private data associated with an ATA bus */ +struct atapi_xpt_softc { + struct ata_device atapi_cam_dev; /* must be first */ + device_t dev; + device_t parent; + struct ata_channel *ata_ch; + struct cam_path *path; + struct cam_sim *sim; + int flags; +#define BUS_REGISTERED 0x01 +#define RESOURCE_SHORTAGE 0x02 + + TAILQ_HEAD(,atapi_hcb) pending_hcbs; + struct ata_device *atadev[2]; +}; /* hardware command descriptor block */ struct atapi_hcb { @@ -67,23 +85,13 @@ TAILQ_ENTRY(atapi_hcb) chain; }; -/* private data associated with an ATA bus */ -struct atapi_xpt_softc { - struct ata_channel *ata_ch; - struct cam_path *path; - struct cam_sim *sim; - int flags; -#define BUS_REGISTERED 0x01 -#define RESOURCE_SHORTAGE 0x02 - - TAILQ_HEAD(,atapi_hcb) pending_hcbs; - LIST_ENTRY(atapi_xpt_softc) chain; -}; - enum reinit_reason { BOOT_ATTACH, ATTACH, RESET }; -static struct mtx atapicam_softc_mtx; -static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses); +/* Device methods */ +static int atapi_cam_probe(device_t dev); +static int atapi_cam_attach(device_t dev); +static int atapi_cam_detach(device_t dev); +static int atapi_cam_reinit(device_t dev); /* CAM XPT methods */ static void atapi_action(struct cam_sim *, union ccb *); @@ -94,7 +102,6 @@ /* internal functions */ static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason); -static void setup_dev(struct atapi_xpt_softc *, struct ata_device *); static void setup_async_cb(struct atapi_xpt_softc *, uint32_t); static void cam_rescan_callback(struct cam_periph *, union ccb *); static void cam_rescan(struct cam_sim *); @@ -102,64 +109,85 @@ static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *); static void free_hcb(struct atapi_hcb *hcb); static void free_softc(struct atapi_xpt_softc *scp); -static struct atapi_xpt_softc *get_softc(struct ata_channel *ata_ch); -static struct ata_device *get_ata_device(struct atapi_xpt_softc *scp, int id); static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer"); -void -atapi_cam_attach_bus(struct ata_channel *ata_ch) +static device_method_t atapi_cam_methods[] = { + DEVMETHOD(device_probe, atapi_cam_probe), + DEVMETHOD(device_attach, atapi_cam_attach), + DEVMETHOD(device_detach, atapi_cam_detach), + DEVMETHOD(ata_reinit, atapi_cam_reinit), + {0, 0} +}; + +static driver_t atapi_cam_driver = { + "atapicam", + atapi_cam_methods, + sizeof(struct atapi_xpt_softc) +}; + +static devclass_t atapi_cam_devclass; +DRIVER_MODULE(atapicam, ata, atapi_cam_driver, atapi_cam_devclass, 0, 0); +DRIVER_MODULE(atapicam, atapci, atapi_cam_driver, atapi_cam_devclass, 0, 0); +DRIVER_MODULE(atapicam, atacbus, atapi_cam_driver, atapi_cam_devclass, 0, 0); +MODULE_VERSION(atapicam, 1); +MODULE_DEPEND(atapicam, ata, 1, 1, 1); + +static int +atapi_cam_probe(device_t dev) +{ + device_set_desc(dev, "ATAPI CAM Attachment"); + return (0); +} + +static int +atapi_cam_attach(device_t dev) { struct atapi_xpt_softc *scp = NULL; struct cam_devq *devq = NULL; struct cam_sim *sim = NULL; struct cam_path *path = NULL; - int unit; - - GIANT_REQUIRED; - - if (mtx_initialized(&atapicam_softc_mtx) == 0) - mtx_init(&atapicam_softc_mtx, "ATAPI/CAM softc mutex", NULL, MTX_DEF); - - mtx_lock(&atapicam_softc_mtx); + int unit, error; - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - break; + scp = (struct atapi_xpt_softc *)device_get_softc(dev); + if (scp == NULL) { + device_printf(dev, "Cannot get softc\n"); + return (ENOMEM); } - mtx_unlock(&atapicam_softc_mtx); - - if (scp != NULL) - return; - if ((scp = malloc(sizeof(struct atapi_xpt_softc), - M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) - goto error; + /* The ATA core expects all of its children to have an ata_device */ + scp->atapi_cam_dev.unit = ATA_ATAPI_CAM; + scp->atapi_cam_dev.dev = dev; - scp->ata_ch = ata_ch; + scp->dev = dev; + scp->parent = device_get_parent(dev); + scp->ata_ch = device_get_softc(scp->parent); TAILQ_INIT(&scp->pending_hcbs); - LIST_INSERT_HEAD(&all_buses, scp, chain); - unit = device_get_unit(ata_ch->dev); + unit = device_get_unit(dev); - if ((devq = cam_simq_alloc(16)) == NULL) - goto error; + if ((devq = cam_simq_alloc(16)) == NULL) { + error = ENOMEM; + goto out; + } if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "ata", (void *)scp, unit, 1, 1, devq)) == NULL) { - cam_simq_free(devq); - goto error; + error = ENOMEM; + goto out; } scp->sim = sim; if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { - goto error; + error = EINVAL; + goto out; } scp->flags |= BUS_REGISTERED; if (xpt_create_path(&path, /*periph*/ NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - goto error; + error = ENOMEM; + goto out; } scp->path = path; @@ -167,25 +195,27 @@ setup_async_cb(scp, AC_LOST_DEVICE); reinit_bus(scp, cold ? BOOT_ATTACH : ATTACH); - return; + error = 0; -error: - free_softc(scp); +out: + if (error != 0) + free_softc(scp); + + return (error); } -void -atapi_cam_detach_bus(struct ata_channel *ata_ch) +static int +atapi_cam_detach(device_t dev) { - struct atapi_xpt_softc *scp = get_softc(ata_ch); + struct atapi_xpt_softc *scp = device_get_softc(dev); - mtx_lock(&Giant); free_softc(scp); - mtx_unlock(&Giant); + return (0); } -void -atapi_cam_reinit_bus(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp = get_softc(ata_ch); +static int +atapi_cam_reinit(device_t dev) { + struct atapi_xpt_softc *scp = device_get_softc(dev); /* * scp might be null if the bus is being reinitialised during @@ -193,21 +223,38 @@ */ if (scp != NULL) { - mtx_lock(&Giant); reinit_bus(scp, RESET); - mtx_unlock(&Giant); } + return (0); } static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) { + struct ata_device *atadev; + device_t *children; + int nchildren, i; GIANT_REQUIRED; + if (device_get_children(scp->parent, &children, &nchildren) != 0) { + return; + } + + scp->atadev[0] = NULL; + scp->atadev[1] = NULL; - if (scp->ata_ch->devices & ATA_ATAPI_MASTER) - setup_dev(scp, &scp->ata_ch->device[MASTER]); - if (scp->ata_ch->devices & ATA_ATAPI_SLAVE) - setup_dev(scp, &scp->ata_ch->device[SLAVE]); + for (i = 0; i < nchildren; i++) { + /* XXX Does the child need to actually be attached yet? */ + if (children[i] != NULL) { + atadev = device_get_softc(children[i]); + if ((atadev->unit == ATA_MASTER) && + (scp->ata_ch->devices & ATA_ATAPI_MASTER) != 0) + scp->atadev[0] = atadev; + if ((atadev->unit == ATA_SLAVE) && + (scp->ata_ch->devices & ATA_ATAPI_SLAVE) != 0) + scp->atadev[1] = atadev; + } + } + free(children, M_TEMP); switch (reason) { case BOOT_ATTACH: @@ -222,17 +269,6 @@ } static void -setup_dev(struct atapi_xpt_softc *scp, struct ata_device *atp) -{ - if (atp->softc == NULL) { - ata_set_name(atp, "atapicam", - 2 * device_get_unit(atp->channel->dev) + - (atp->unit == ATA_MASTER) ? 0 : 1); - atp->softc = (void *)scp; - } -} - -static void setup_async_cb(struct atapi_xpt_softc *scp, uint32_t events) { struct ccb_setasync csa; @@ -262,6 +298,7 @@ switch (ccb_h->func_code) { case XPT_PATH_INQ: { struct ccb_pathinq *cpi = &ccb->cpi; + int tid = ccb_h->target_id; cpi->version_num = 1; cpi->hba_inquiry = 0; @@ -281,8 +318,13 @@ cpi->bus_id = cam_sim_bus(sim); cpi->base_transfer_speed = 3300; - if (softc->ata_ch && ccb_h->target_id != CAM_TARGET_WILDCARD) { - switch (softc->ata_ch->device[ccb_h->target_id].mode) { + if (softc->ata_ch && tid != CAM_TARGET_WILDCARD) { + if (softc->atadev[tid] == NULL) { + ccb->ccb_h.status = CAM_DEV_NOT_THERE; + xpt_done(ccb); + return; + } + switch (softc->atadev[ccb_h->target_id]->mode) { case ATA_PIO1: cpi->base_transfer_speed = 5200; break; @@ -320,10 +362,9 @@ case XPT_RESET_DEV: { int tid = ccb_h->target_id; - struct ata_device *dev = get_ata_device(softc, tid); CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n")); - ata_controlcmd(dev, ATA_ATAPI_RESET, 0, 0, 0); + ata_controlcmd(softc->atadev[tid], ATA_ATAPI_RESET, 0, 0, 0); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; @@ -331,7 +372,7 @@ case XPT_RESET_BUS: CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("bus reset\n")); - ata_reinit(softc->ata_ch); + ata_reinit(softc->parent); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; @@ -370,22 +411,22 @@ case XPT_SCSI_IO: { struct ccb_scsiio *csio = &ccb->csio; int tid = ccb_h->target_id, lid = ccb_h->target_lun; - struct ata_device *dev = get_ata_device(softc, tid); int request_flags = ATA_R_QUIET | ATA_R_ATAPI; CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, ("XPT_SCSI_IO\n")); + if (softc->atadev[tid] == NULL) { + ccb->ccb_h.status = CAM_DEV_NOT_THERE; + xpt_done(ccb); + return; + } + /* check that this request was not aborted already */ if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { printf("XPT_SCSI_IO received but already in progress?\n"); xpt_done(ccb); return; } - if (dev == NULL) { - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("SCSI IO received for invalid device\n")); - goto action_invalid; - } if (lid > 0) { CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, ("SCSI IO received for invalid lun %d\n", lid)); @@ -414,10 +455,10 @@ /* No flags need to be set */ break; default: - ata_prtdev(dev, "unknown IO operation\n"); + device_printf(softc->dev, "unknown IO operation\n"); goto action_invalid; } - if (dev->mode < ATA_DMA) + if (softc->atadev[tid]->mode < ATA_DMA) request_flags &= ~ATA_R_DMA; if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) { @@ -491,7 +532,7 @@ goto action_oom; } } - request->device = dev; + request->dev = softc->atadev[tid]->dev; request->driver = hcb; request->data = buf; request->bytecount = len; @@ -764,40 +805,5 @@ printf("Can't free %s SIM (still registered)\n", cam_sim_name(scp->sim)); } - LIST_REMOVE(scp, chain); - free(scp, M_ATACAM); - } -} - -static struct atapi_xpt_softc * -get_softc(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp = NULL; - - mtx_lock(&atapicam_softc_mtx); - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - break; - } - mtx_unlock(&atapicam_softc_mtx); - return scp; -} - -static struct ata_device * -get_ata_device(struct atapi_xpt_softc *scp, int id) -{ - int role = ATA_ATAPI_MASTER; - - switch (id) { - case 1: - role = ATA_ATAPI_SLAVE; - /* FALLTHROUGH */ - - case 0: - if (scp->ata_ch->devices & role) - return &scp->ata_ch->device[id]; - /* FALLTHROUGH */ - - default: - return NULL; } } --------------090700030006080708070500 Content-Type: text/plain; name="Makefile" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile" # $FreeBSD: src/sys/modules/ata/atacam/Makefile,v 1.1 2005/03/30 12:03:39 sos Exp $ .PATH: ${.CURDIR}/../../../dev/ata KMOD= atapicam SRCS= atapi-cam.c SRCS+= opt_ata.h opt_cam.h ata_if.h device_if.h bus_if.h pci_if.h .include --------------090700030006080708070500--