diff -u /dev/null sys/dev/ata/atapi-cam.c --- /dev/null Mon Apr 15 16:30:00 2002 +++ sys/dev/ata/atapi-cam.c Mon Apr 15 16:28:21 2002 @@ -0,0 +1,676 @@ +/*- + * Copyright (c) 2001, 2002 Thomas Quinot + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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. + * + * $FreeBSD:$ + */ + +/* + * A SIM (SCSI Interface Module) that provides access to ATAPI devices + * through CAM. + * + * This module owes much to Sergey Babkin's document 'Writing a CAM SCSI + * controller (A.K.A. Host Bus Adapter) driver', + * http://www.daemonnews.org/200006/cam-driver.html + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Hardware command descriptor block */ +struct atapi_hcb { + struct atapi_xpt_softc *softc; + int unit; + int bus; + int target; + int lun; + union ccb *ccb; + u_int8_t cmd[CAM_MAX_CDBLEN]; + int flags; +#define DOING_AUTOSENSE 1 + char *dxfer_alloc; + + TAILQ_ENTRY(atapi_hcb) chain; + /* Link within list of pending hcbs on the same channel */ +}; + +/* Private data associated with an ATAPI 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; + /* Link within the global list of all ATAPI/CAM SIMs. */ +}; + +static LIST_HEAD(,atapi_xpt_softc) all_buses + = LIST_HEAD_INITIALIZER(all_buses); + +/* CAM XPT methods */ +static void atapi_action(struct cam_sim *sim, union ccb *ccb); +static void atapi_action1(struct cam_sim *sim, union ccb *ccb); +static void atapi_poll(struct cam_sim *sim); +static void atapi_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); +static void atapi_async1(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); +static int atapi_cb(struct atapi_request *); + +/* Internal functions */ +static void setup_dev(struct atapi_xpt_softc *, struct ata_device *); +static void setup_async_cb(struct atapi_xpt_softc *, uint32_t events); +static void free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status); +static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb); +static void free_hcb(struct atapi_hcb *hcb); +static void free_softc(struct atapi_xpt_softc *scp); +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) +{ + struct atapi_xpt_softc *scp = NULL; + struct cam_devq *devq = NULL; + struct cam_sim *sim = NULL; + struct cam_path *path = NULL; + + int unit; + + /* Allocate our private control structure. */ + if ((scp = malloc(sizeof(struct atapi_xpt_softc), M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) { + goto error; + } + scp->ata_ch = ata_ch; + TAILQ_INIT(&scp->pending_hcbs); + LIST_INSERT_HEAD(&all_buses, scp, chain); + unit = device_get_unit(ata_ch->dev); + + /* Alloc one devq (either for the whole driver or for each bus). */ + if ((devq = cam_simq_alloc(16)) == NULL) { + goto error; + } + + /* Alloc a SIM descriptor for each bus. */ + if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "atapi", + (void *)scp, unit, 1, 1, devq)) == NULL) { + cam_simq_free(devq); + goto error; + } + scp->sim = sim; + + /* Register the SIM. */ + if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { + goto error; + } + 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; + } + scp->path = path; + + xpt_print_path(path); + printf("Registered SIM for ata%d\n", unit); + + /* Register callback for AC_LOST_DEVICE event. */ + setup_async_cb(scp, AC_LOST_DEVICE); + + if (ata_ch->devices & ATA_ATAPI_MASTER) + setup_dev(scp, &ata_ch->device[MASTER]); + if (ata_ch->devices & ATA_ATAPI_SLAVE) + setup_dev(scp, &ata_ch->device[SLAVE]); + + return; + +error: + free_softc(scp); +} + +void +atapi_cam_detach_bus(struct ata_channel *ata_ch) { + struct atapi_xpt_softc *scp; + LIST_FOREACH(scp, &all_buses, chain) { + if (scp->ata_ch == ata_ch) + break; + } + if (scp != NULL) + free_softc(scp); +} + +static void +setup_dev(struct atapi_xpt_softc *scp, struct ata_device *atp) +{ + if (atp->driver == NULL) { + ata_set_name(atp, "atapicam", + 2 * device_get_unit(atp->channel->dev) + + (atp->unit == ATA_MASTER) ? 0 : 1); + atp->driver = (void *) scp; + } +} + +static void +setup_async_cb(struct atapi_xpt_softc *scp, uint32_t events) { + struct ccb_setasync csa; + + xpt_setup_ccb(&csa.ccb_h, scp->path, /*priority*/ 5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = events; + csa.callback = &atapi_async; + csa.callback_arg = scp->sim; + xpt_action((union ccb *) & csa); +} + +static void +atapi_action(struct cam_sim *sim, union ccb *ccb) +{ + int s = splcam(); + atapi_action1(sim, ccb); + splx(s); +} + +static void +atapi_action1(struct cam_sim *sim, union ccb *ccb) +{ + struct atapi_xpt_softc *softc = (struct atapi_xpt_softc *) cam_sim_softc(sim); + struct ccb_hdr *ccb_h = &ccb->ccb_h; + int unit = cam_sim_unit(sim); + int bus = cam_sim_bus(sim); + int len; + char *buf; + struct atapi_hcb *hcb = NULL; + + switch (ccb_h->func_code) { + case XPT_PATH_INQ: + { + struct ccb_pathinq *cpi = &ccb->cpi; + + cpi->version_num = 1; + cpi->hba_inquiry = 0; + cpi->hba_misc = 0; + cpi->hba_eng_cnt = 0; + bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags)); + cpi->max_target = 2; + cpi->max_lun = 7; + cpi->async_flags = 0; + cpi->hpath_id = 0; + cpi->initiator_id = 7; + strncpy(cpi->sim_vid, "ATAPI-SIM", sizeof cpi->sim_vid); + strncpy(cpi->hba_vid, "ATAPI", sizeof cpi->hba_vid); + strncpy(cpi->dev_name, cam_sim_name(sim), sizeof cpi->dev_name); + cpi->unit_number = cam_sim_unit(sim); + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 3300; + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + return; + } + case XPT_RESET_DEV: + /* Should reset the device. For now, do nothing. */ +#ifdef CAMDEBUG + xpt_print_path(ccb->ccb_h.path); + printf("dev reset"); +#endif + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + return; + case XPT_RESET_BUS: + /* Should reset the ATA bus. For now, do nothing. */ +#ifdef CAMDEBUG + xpt_print_path(ccb->ccb_h.path); + printf("bus reset"); +#endif + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + return; + case XPT_SET_TRAN_SETTINGS: + /* Ignore these. We're not doing SCSI here. */ + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + return; + case XPT_GET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + cts->flags |= + (0 + | CCB_TRANS_SYNC_RATE_VALID + | CCB_TRANS_SYNC_OFFSET_VALID + | CCB_TRANS_BUS_WIDTH_VALID + | CCB_TRANS_DISC_VALID + | CCB_TRANS_TQ_VALID); + cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); + cts->sync_period = 0; + cts->sync_offset = 0; + cts->bus_width = 8; + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + return; + } + case XPT_CALC_GEOMETRY: + /* Stolen from sym_hipd.c */ + { + struct ccb_calc_geometry *ccg; + unsigned int size_mb; + unsigned int secs_per_cylinder; + int extended; + + /* + * Silly DOS geometry. + */ + ccg = &ccb->ccg; + size_mb = ccg->volume_size + / ((1024L * 1024L) / ccg->block_size); + extended = 1; + + if (size_mb > 1024 && extended) { + ccg->heads = 255; + ccg->secs_per_track = 63; + } 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); + return; + } + 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); + +#ifdef CAMDEBUG + char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; + + printf("XPT_SCSI_IO (b%d u%d t%d l%d)\n", bus, unit, tid, lid); +#endif + /* Check that this request was not aborted already. */ + if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { +#ifdef CAMDEBUG + printf("Already in progress\n"); +#endif + xpt_done(ccb); + return; + } + if (dev == NULL) { +#ifdef CAMDEBUG + printf("Invalid target %d\n", tid); +#endif + ccb_h->status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } +#if 0 + /* XXX how to determine that??? */ + if (lid > OUR_MAX_SUPPORTED_LUN) { + ccb_h->status = CAM_LUN_INVALID; + xpt_done(ccb); + return; + } +#else + /* -> while we dunno, be conservative. */ + if (lid > 0) { +#ifdef CAMDEBUG + printf("Invalid LUN %d\n", lid); +#endif + ccb_h->status = CAM_LUN_INVALID; + xpt_done(ccb); + return; + } +#endif + if ((ccb_h->flags & CAM_SCATTER_VALID)) { + /* Scatter-gather not supported. */ + xpt_print_path(ccb_h->path); + printf("ATAPI-CAM does not support scatter-gather yet!\n"); + break; + } + if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) { + goto action_oom; + } + ccb_h->status |= CAM_SIM_QUEUED; + + bcopy((ccb_h->flags & CAM_CDB_POINTER) ? + csio->cdb_io.cdb_ptr : + csio->cdb_io.cdb_bytes, + hcb->cmd, + csio->cdb_len); +#ifdef CAMDEBUG + printf("hcb@%p: %s\n", + hcb, + scsi_cdb_string(hcb->cmd, cdb_str, sizeof(cdb_str))); +#endif + + len = csio->dxfer_len; + buf = csio->data_ptr; + + /* Some SCSI commands require special processing. */ + + switch (hcb->cmd[0]) { + case INQUIRY: + /* + * Many ATAPI devices seem to report more than + * SHORT_INQUIRY_LENGTH bytes of available INQUIRY + * information, but respond with some incorrect condition + * when actually asked for it, so we are going to pretend + * that only SHORT_INQUIRY_LENGTH are expected, anyway. + */ + { + struct scsi_inquiry *inq = (struct scsi_inquiry *) &hcb->cmd[0]; + if (inq->byte2 == 0 && inq->page_code == 0 + && inq->length > SHORT_INQUIRY_LENGTH) { + bzero(buf, len); + len = inq->length = SHORT_INQUIRY_LENGTH; + } + break; + } + case MODE_SELECT_6: + /* FALLTHROUGH */ + case MODE_SENSE_6: + /* + * Not supported by ATAPI/MMC devices (per + * SCSI MMC spec): translate to _10 equivalent. + * (actually we should do this only if we + * have tried MODE_foo_6 and received + * ILLEGAL_REQUEST/INVALID COMMAND OPERATION CODE) + */ + + /* + * Alternative fix: behave like a honest CAM + * transport, do not muck with CDB contents, and change + * scsi_cd to * always use MODE_SENSE_10 in cdgetmode(), + * or let * scsi_cd know that this specific unit is an + * ATAPI/MMC one, and in /that case/ use MODE_SENSE_10. + */ + +#ifdef CAMDEBUG + xpt_print_path(ccb_h->path); + printf("Translating %s into _10 equivalent\n", + (hcb->cmd[0] == MODE_SELECT_6) ? "MODE_SELECT_6" : "MODE_SENSE_6"); +#endif + hcb->cmd[0] |= 0x40; + + hcb->cmd[6] = 0; + hcb->cmd[7] = 0; + hcb->cmd[8] = hcb->cmd[4]; + hcb->cmd[9] = hcb->cmd[5]; + hcb->cmd[4] = 0; + hcb->cmd[5] = 0; + break; + + case READ_6: + /* FALLTHROUGH */ + case WRITE_6: +#ifdef CAMDEBUG + xpt_print_path(ccb_h->path); + printf("Translating %s into _10 equivalent\n", + (hcb->cmd[0] == READ_6) ? "READ_6" : "WRITE_6"); +#endif + hcb->cmd[0] |= 0x20; + + hcb->cmd[9] = hcb->cmd[5]; + hcb->cmd[8] = hcb->cmd[4]; + hcb->cmd[7] = 0; + hcb->cmd[6] = 0; + hcb->cmd[5] = hcb->cmd[3]; + hcb->cmd[4] = hcb->cmd[2]; + hcb->cmd[3] = hcb->cmd[1] & 0x1f; + hcb->cmd[2] = 0; + hcb->cmd[1] = 0; + break; + } + + if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) { + /* + * ATA always transfers an even number of + * bytes. + */ + if ((buf = hcb->dxfer_alloc = malloc + (++len, M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) + goto action_oom; + } + TAILQ_INSERT_TAIL(&softc->pending_hcbs, hcb, chain); + if (atapi_queue_cmd + (dev, hcb->cmd, buf, len, + ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN) ? + ATPR_F_READ : 0, + ccb_h->timeout, atapi_cb, (void *)hcb) == 0) + return; + break; /* Fall trhough to action_oom */ + } + default: + printf("atapi-cam: unsupported function code 0x%02x\n", ccb_h->func_code); + ccb_h->status = CAM_REQ_INVALID; + xpt_done(ccb); + return; + } + +action_oom: + if (hcb != NULL) + free_hcb(hcb); + xpt_print_path(ccb_h->path); + printf("Out of memory: freezing queue."); + softc->flags |= RESOURCE_SHORTAGE; + xpt_freeze_simq(sim, /* count */ 1); + ccb_h->status = CAM_REQUEUE_REQ; + xpt_done(ccb); +} + +static void +atapi_poll(struct cam_sim *sim) +{ + /* + * Do nothing - we do not actually service any interrupts. + */ + printf("atapi_poll called!\n"); +}; + +int +atapi_cb(struct atapi_request *req) +{ + int s = splcam(); + struct atapi_hcb *hcb = (struct atapi_hcb *) req->driver; + int hcb_status = req->result; + struct ccb_scsiio *csio = &hcb->ccb->csio; + +#ifdef CAMDEBUG + printf("atapi_cb: hcb@%p status = %02x: (sk = %02x%s%s%s)\n", + hcb, hcb_status, hcb_status >> 4, + (hcb_status & 4) ? " ABRT" : "", + (hcb_status & 2) ? " EOM" : "", + (hcb_status & 1) ? " ILI" : ""); + printf(" %s: cmd %02x - sk=%02x asc=%02x ascq=%02x\n", + req->device->name, req->ccb[0], req->sense.sense_key, + req->sense.asc, req->sense.ascq); +#endif + if (hcb_status != 0) { + + hcb->ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + + if ((hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) { + hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID; + bcopy((void *)&req->sense, (void *)&csio->sense_data, + sizeof(struct atapi_reqsense)); + } + free_hcb_and_ccb_done(hcb, CAM_SCSI_STATUS_ERROR); + } else { + if (((hcb->ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) + && hcb->dxfer_alloc != NULL) + bcopy(hcb->dxfer_alloc, csio->data_ptr, csio->dxfer_len); + hcb->ccb->csio.scsi_status = SCSI_STATUS_OK; + free_hcb_and_ccb_done(hcb, CAM_REQ_CMP); + } + splx(s); + return 0; +}; + +static void +free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status) +{ + struct atapi_xpt_softc *softc = hcb->softc; + union ccb *ccb = hcb->ccb; + + if (hcb != NULL) { +#if 0 + untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch); +#endif + /* we're about to free a hcb, so the shortage has ended */ + if (softc->flags & RESOURCE_SHORTAGE) { + softc->flags &= ~RESOURCE_SHORTAGE; + status |= CAM_RELEASE_SIMQ; + } + free_hcb(hcb); /* also removes hcb from any internal lists */ + } + ccb->ccb_h.status = status | (ccb->ccb_h.status & ~(CAM_STATUS_MASK | CAM_SIM_QUEUED)); + xpt_done(ccb); +} + +static void +atapi_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) +{ + int s = splcam(); + atapi_async1(callback_arg, code, path, arg); + splx(s); +} + +static void +atapi_async1(void *callback_arg, u_int32_t code, struct cam_path* path, void *arg) +{ + struct atapi_xpt_softc *softc; + struct cam_sim *sim; + int targ; + + sim = (struct cam_sim *) callback_arg; + softc = (struct atapi_xpt_softc *) cam_sim_softc(sim); + switch (code) { + case AC_LOST_DEVICE: + targ = xpt_path_target_id(path); + xpt_print_path(path); + if (targ == -1) { + printf("Lost host adapter\n"); + } else { + printf("Lost target %d???\n", targ); + } + break; + default: + break; + } +} + +static struct atapi_hcb * +allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb) +{ + struct atapi_hcb *hcb = (struct atapi_hcb *) + malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | M_ZERO); + + if (hcb != NULL) { + hcb->softc = softc; + hcb->unit = unit; + hcb->bus = bus; + hcb->ccb = ccb; + } + return hcb; +} + +static void +free_hcb(struct atapi_hcb *hcb) +{ + TAILQ_REMOVE(&hcb->softc->pending_hcbs, hcb, chain); + if (hcb->dxfer_alloc != NULL) + free(hcb->dxfer_alloc, M_ATACAM); + free(hcb, M_ATACAM); +} + +static void +free_softc(struct atapi_xpt_softc *scp) { + struct atapi_hcb *hcb; + + if (scp != NULL) { + TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) { + free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR); + } + if (scp->path != NULL) { + setup_async_cb(scp, 0); + xpt_free_path(scp->path); + } + if ((scp->flags & BUS_REGISTERED) != 0) { + if (xpt_bus_deregister(cam_sim_path(scp->sim)) == CAM_REQ_CMP) { + scp->flags &= ~BUS_REGISTERED; + } + } + if (scp->sim != NULL) { + if ((scp->flags & BUS_REGISTERED) == 0) { + cam_sim_free(scp->sim, /*free_devq*/TRUE); + } else { + printf("Can't free %s SIM (still registered)\n", + cam_sim_name(scp->sim)); + } + } + LIST_REMOVE(scp, chain); + free(scp, M_ATACAM); + } +} + +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; + } +} diff -u sys/dev/ata/ata-all.c.dist sys/dev/ata/ata-all.c --- sys/dev/ata/ata-all.c.dist Thu Apr 4 00:52:49 2002 +++ sys/dev/ata/ata-all.c Fri Apr 5 13:46:55 2002 @@ -212,6 +212,10 @@ atapi_attach(&ch->device[MASTER]); if (ch->devices & ATA_ATAPI_SLAVE) atapi_attach(&ch->device[SLAVE]); +#ifdef ATAPICAM + if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) + atapi_cam_attach_bus (ch); +#endif #endif splx(s); } @@ -242,6 +246,10 @@ atapi_detach(&ch->device[MASTER]); if (ch->devices & ATA_ATAPI_SLAVE && ch->device[SLAVE].driver) atapi_detach(&ch->device[SLAVE]); +#ifdef ATAPICAM + if (ch->devices & (ATA_ATAPI_SLAVE|ATA_ATAPI_MASTER)) + atapi_cam_detach_bus(ch); +#endif #endif splx(s); @@ -572,6 +580,10 @@ atapi_attach(&ch->device[MASTER]); if (ch->devices & ATA_ATAPI_SLAVE) atapi_attach(&ch->device[SLAVE]); +#ifdef ATAPICAM + if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) + atapi_cam_attach_bus (ch); +#endif } #endif splx(s); @@ -849,6 +861,10 @@ ata_printf(ch, -1, "resetting devices .. "); ata_reset(ch); +#ifdef ATAPICAM + if (devices & (ATA_ATAPI_SLAVE|ATA_ATAPI_MASTER)) + atapi_cam_detach_bus(ch); +#endif if ((misdev = devices & ~ch->devices)) { if (misdev) printf("\n"); @@ -918,6 +934,10 @@ ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY); atapi_reinit(&ch->device[SLAVE]); } +#ifdef ATAPICAM + if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) + atapi_cam_attach_bus (ch); +#endif #endif printf("done\n"); ATA_UNLOCK_CH(ch); diff -u sys/dev/ata/atapi-all.c.dist sys/dev/ata/atapi-all.c --- sys/dev/ata/atapi-all.c.dist Tue Mar 26 10:36:43 2002 +++ sys/dev/ata/atapi-all.c Fri Apr 5 13:46:55 2002 @@ -51,7 +51,9 @@ static void atapi_write(struct atapi_request *, int); static void atapi_finish(struct atapi_request *); static void atapi_timeout(struct atapi_request *); +#ifndef ATAPICAM static char *atapi_type(int); +#endif static char *atapi_cmd2str(u_int8_t); static char *atapi_skey2str(u_int8_t); @@ -115,10 +117,12 @@ break; #endif } +#ifndef ATAPICAM ata_prtdev(atadev, "<%.40s/%.8s> %s device - NO DRIVER!\n", atadev->param->model, atadev->param->revision, atapi_type(atadev->param->type)); free(atadev->result, M_ATAPI); +#endif atadev->driver = NULL; } @@ -636,6 +640,7 @@ ata_reinit(atadev->channel); } +#ifndef ATAPICAM static char * atapi_type(int type) { @@ -652,6 +657,7 @@ return "Unknown"; } } +#endif static char * atapi_cmd2str(u_int8_t cmd) diff -u sys/dev/ata/atapi-all.h.dist sys/dev/ata/atapi-all.h --- sys/dev/ata/atapi-all.h.dist Mon Mar 18 09:37:34 2002 +++ sys/dev/ata/atapi-all.h Fri Apr 5 13:46:55 2002 @@ -172,7 +172,9 @@ }; void atapi_attach(struct ata_device *); +void atapi_cam_attach_bus(struct ata_channel *); void atapi_detach(struct ata_device *); +void atapi_cam_detach_bus(struct ata_channel *); void atapi_reinit(struct ata_device *); void atapi_start(struct ata_device *); int atapi_transfer(struct atapi_request *); @@ -191,3 +193,4 @@ int astattach(struct ata_device *); void astdetach(struct ata_device *); void ast_start(struct ata_device *); +