Date: Sun, 9 Aug 2009 21:49:32 GMT From: Alexander Motin <mav@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 167143 for review Message-ID: <200908092149.n79LnWlR008708@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167143 Change 167143 by mav@mav_mavbook on 2009/08/09 21:49:27 Create initial wrapper turning ATA(4) controller drivers into CAM SIMs. New ATA_CAM kernel option controls it. Affected files ... .. //depot/projects/scottl-camlock/src/sys/conf/options#29 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.c#21 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.h#18 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-lowlevel.c#13 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-queue.c#18 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-sata.c#6 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-intel.c#8 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-marvell.c#7 edit .. //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-serverworks.c#6 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/conf/options#29 (text+ko) ==== @@ -350,6 +350,7 @@ # 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 ==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.c#21 (text+ko) ==== @@ -50,6 +50,15 @@ #include <dev/ata/ata-all.h> #include <ata_if.h> +#ifdef ATA_CAM +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_xpt_periph.h> +#include <cam/cam_debug.h> +#endif + /* device structure */ static d_ioctl_t ata_ioctl; static struct cdevsw ata_cdevsw = { @@ -59,7 +68,12 @@ }; /* prototypes */ +#ifndef ATA_CAM static void ata_boot_attach(void); +#else +static void ataaction(struct cam_sim *sim, union ccb *ccb); +static void atapoll(struct cam_sim *sim); +#endif static device_t ata_add_child(device_t, struct ata_device *, int); static void ata_conn_event(void *, int); static void bswap(int8_t *, int); @@ -114,6 +128,9 @@ { 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) @@ -153,18 +170,61 @@ 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) @@ -175,6 +235,7 @@ 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++) @@ -182,8 +243,18 @@ 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); @@ -373,9 +444,14 @@ ch->running = NULL; if (ch->state == ATA_ACTIVE) ch->state = ATA_IDLE; +#ifdef ATA_CAM + ata_cam_end_transaction(ch->dev, request); +#endif mtx_unlock(&ch->state_mtx); +#ifndef ATA_CAM ATA_LOCKING(ch->dev, ATA_LF_UNLOCK); ata_finish(request); +#endif return; } } while (0); @@ -575,6 +651,7 @@ } } +#ifndef ATA_CAM static void ata_boot_attach(void) { @@ -598,8 +675,8 @@ } newbus_xunlock(); } +#endif - /* * misc support functions */ @@ -1088,7 +1165,241 @@ 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; + +//device_printf(dev, "%s\n", __func__); + 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; + } else { + request->data = ccb->csio.data_ptr; + request->bytecount = ccb->csio.dxfer_len; + } + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + 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; + 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) | + ((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->ataio.cmd.flags & CAM_ATAIO_48BIT) + request->flags |= ATA_R_48BIT; + if (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, 512); +// request->callback = ad_done; + request->retries = 0; + request->timeout = ccb->ccb_h.timeout / 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) { +device_printf(dev, "XXX: EARLY FINISH!\n"); + 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; + +//device_printf(dev, "%s\n", __func__); + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + if (request->result == 0) + ccb->ccb_h.status |= CAM_REQ_CMP; + else + ccb->ccb_h.status |= CAM_REQ_CMP_ERR; + 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 (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 = SCSI_REV_2; + cts->transport = XPORT_ATA; + cts->transport_version = 2; + 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_RESET(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 = 2; + cpi->protocol = PROTO_ATA; + cpi->protocol_version = SCSI_REV_2; + 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(ch); +} +#endif + /* * module handeling */ @@ -1102,6 +1413,7 @@ /* register controlling device */ atacdev = make_dev(&ata_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0600, "ata"); +#ifndef ATA_CAM if (cold) { /* register boot attach to be run when interrupts are enabled */ if (!(ata_delayed_attach = (struct intr_config_hook *) @@ -1116,6 +1428,7 @@ free(ata_delayed_attach, M_TEMP); } } +#endif return 0; case MOD_UNLOAD: ==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.h#18 (text+ko) ==== @@ -412,6 +412,9 @@ 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 */ @@ -554,6 +557,10 @@ 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 */ @@ -593,6 +600,10 @@ 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); ==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-lowlevel.c#13 (text+ko) ==== @@ -87,9 +87,6 @@ (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 */ @@ -752,7 +749,9 @@ 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 (request->flags & ATA_R_48BIT) { ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8); @@ -770,6 +769,7 @@ 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; @@ -792,13 +792,16 @@ 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(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } } ==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-queue.c#18 (text+ko) ==== @@ -63,6 +63,8 @@ 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); /* check that the device is still valid */ if (!(request->parent = device_get_parent(request->dev))) { request->result = ENXIO; @@ -510,11 +512,16 @@ */ if (ch->state == ATA_ACTIVE) { request->flags |= ATA_R_TIMEOUT; + if (ch->dma.unload) + ch->dma.unload(request); +#ifdef ATA_CAM + ata_cam_end_transaction(ch->dev, request); +#endif mtx_unlock(&ch->state_mtx); ATA_LOCKING(ch->dev, ATA_LF_UNLOCK); - if (ch->dma.unload) - ch->dma.unload(request); +#ifndef ATA_CAM ata_finish(request); +#endif } else { mtx_unlock(&ch->state_mtx); ==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-sata.c#6 (text+ko) ==== @@ -262,7 +262,6 @@ return 20; } else { - ata_modify_if_48bit(request); fis[0] = 0x27; /* host to device */ fis[1] = 0x80 | (request->unit & 0x0f); fis[2] = request->u.ata.command; ==== //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-intel.c#8 (text+ko) ==== @@ -467,7 +467,9 @@ ata_intel_31244_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 (request->flags & ATA_R_48BIT) { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); @@ -483,6 +485,7 @@ 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; @@ -504,13 +507,16 @@ 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(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } } ==== //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-marvell.c#7 (text+ko) ==== @@ -359,9 +359,6 @@ 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->parent, "setting up DMA failed\n"); ==== //depot/projects/scottl-camlock/src/sys/dev/ata/chipsets/ata-serverworks.c#6 (text+ko) ==== @@ -256,7 +256,9 @@ 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 (request->flags & ATA_R_48BIT) { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); @@ -272,6 +274,7 @@ 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; @@ -293,13 +296,16 @@ 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(request->unit) | ((request->u.ata.lba >> 24) & 0x0f)); +#ifndef ATA_CAM } +#endif } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908092149.n79LnWlR008708>