diff -u /dev/null sys/dev/ata/atapi-cam.c --- /dev/null Thu Mar 21 14:49:38 2002 +++ sys/dev/ata/atapi-cam.c Thu Mar 21 14:47:38 2002 @@ -0,0 +1,567 @@ +/*- + * 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 + * + */ + +/* ATA headers used in atapi-cam.h */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* Private data associated with an ATAPI bus */ +struct atapi_xpt_softc { + struct ata_channel *ata_ch; + struct cam_path *wpath; + struct cam_sim *sim; + int flags; +#define RESOURCE_SHORTAGE 1 +}; + +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; + char *dxfer_alloc; +}; + +#define DOING_AUTOSENSE 1 + +static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer"); + +/* Internal functions */ +static void atapi_cam_attach_dev(struct ata_device * atp); +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 *); +static void free_hcb_and_ccb_done(struct atapi_hcb * hcb, union ccb * ccb, u_int32_t status); +static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc * softc, int unit, int bus); +static void free_hcb(struct atapi_hcb * hcb); +static struct ata_device *get_ata_device(struct atapi_xpt_softc * scp, int id); + +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; + int bus_registered = 0; + struct cam_path *path = NULL; + + int unit; + struct ccb_setasync csa; + + /* 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; + scp->flags = 0; + 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) { + goto error; + } + /* Register the SIM. */ + if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { + goto error; + } + bus_registered = 1; + + if (xpt_create_path(&path, /* periph */ NULL, + cam_sim_path(sim), CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + goto error; + } + scp->wpath = path; + scp->sim = sim; + + xpt_print_path(path); + printf("Registered SIM for ata%d\n", unit); + + /* Register callback for AC_LOST_DEVICE event. */ + xpt_setup_ccb(&csa.ccb_h, path, /* priority */ 5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = AC_LOST_DEVICE; + csa.callback = atapi_async; + csa.callback_arg = sim; + xpt_action((union ccb *) & csa); + + if (ata_ch->devices & ATA_ATAPI_MASTER) + atapi_cam_attach_dev(&ata_ch->device[MASTER]); + if (ata_ch->devices & ATA_ATAPI_SLAVE) + atapi_cam_attach_dev(&ata_ch->device[SLAVE]); + + return; + +error: + if (bus_registered == 1) + xpt_bus_deregister(cam_sim_path(sim)); + if (sim != NULL) + cam_sim_free(sim, /* free_devq */ FALSE); + if (devq != NULL) + cam_simq_free(devq); + if (scp != NULL) + free(scp, M_ATACAM); +} + +static void +atapi_cam_attach_dev(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); +} + +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 = 7; + 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_SCSI_IO: + { + struct ccb_scsiio *csio = &ccb->csio; + int error, 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)) == NULL) { + goto action_oom; + } + hcb->ccb = ccb; + 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 + + /* Some SCSI commands require special processing. */ + + switch (hcb->cmd[0]) { + 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 + + if (hcb->cmd[0] == MODE_SELECT_6) { + hcb->cmd[0] = MODE_SELECT_10; + } else { + hcb->cmd[0] = MODE_SENSE_10; + } + 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; + } + + len = csio->dxfer_len; + buf = csio->data_ptr; + + 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; + } + error = 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); + + if (error != 0) { + free_hcb(hcb); + break; + } + return; + } + default: + printf("atapi-cam: unsupported function code %02x\n", ccb_h->func_code); + break; + } + ccb_h->status = CAM_REQ_INVALID; + xpt_done(ccb); + +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 targ = hcb->target; */ + /* int ccb_status; */ + 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, hcb->ccb, 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, hcb->ccb, CAM_REQ_CMP); + } + splx(s); + return 0; +}; + +static void +free_hcb_and_ccb_done(struct atapi_hcb * hcb, union ccb * ccb, u_int32_t status) +{ + struct atapi_xpt_softc *softc = hcb->softc; + + 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); + printf("Lost target %u ???\n", targ); + break; + default: + break; + } +} + +static struct atapi_hcb * +allocate_hcb(struct atapi_xpt_softc * softc, int unit, int bus) +{ + 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; + } + return hcb; +} + +static void +free_hcb(struct atapi_hcb * hcb) +{ + if (hcb->dxfer_alloc != NULL) + free(hcb->dxfer_alloc, M_ATACAM); + free(hcb, 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 /dev/null sys/dev/ata/atapi-cam.h --- /dev/null Thu Mar 21 14:49:38 2002 +++ sys/dev/ata/atapi-cam.h Thu Mar 21 14:49:34 2002 @@ -0,0 +1,35 @@ +/*- + * 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:$ + */ + +#include +#include +#include + +void atapi_cam_attach_bus(struct ata_channel * ata_scp); diff -u sys/cam/cam_xpt.c.dist sys/cam/cam_xpt.c --- sys/cam/cam_xpt.c.dist Wed Dec 19 06:27:51 2001 +++ sys/cam/cam_xpt.c Thu Mar 21 14:16:41 2002 @@ -194,6 +194,7 @@ #define CAM_QUIRK_NOLUNS 0x01 #define CAM_QUIRK_NOSERIAL 0x02 #define CAM_QUIRK_HILUNS 0x04 +#define CAM_QUIRK_NOFULLINQ 0x08 u_int mintags; u_int maxtags; }; @@ -214,6 +215,7 @@ static const char samsung[] = "SAMSUNG"; static const char seagate[] = "SEAGATE"; static const char microp[] = "MICROP"; +static const char toshiba[] = "TOSHIBA"; static struct xpt_quirk_entry xpt_quirk_table[] = { @@ -411,6 +413,14 @@ }, { /* + * Many ATAPI Toshiba drives incorrectly generate a + * UNIT ATTENTION condition when asked for full inquiry info. + */ + { T_CDROM, SIP_MEDIA_REMOVABLE, toshiba, "DVD-ROM SD-M*", "*" }, + CAM_QUIRK_NOFULLINQ, /*mintags*/0, /*maxtags*/0 + }, + { + /* * This drive doesn't like multiple LUN probing. * Submitted by: Parag Patel */ @@ -5504,16 +5514,17 @@ * the amount of information the device * is willing to give. */ + xpt_find_quirk(path->device); alen = inq_buf->additional_length; if (softc->action == PROBE_INQUIRY - && alen > (SHORT_INQUIRY_LENGTH - 4)) { + && alen > (SHORT_INQUIRY_LENGTH - 4) + && (path->device->quirk->quirks + & CAM_QUIRK_NOFULLINQ) == 0) { softc->action = PROBE_FULL_INQUIRY; xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; } - - xpt_find_quirk(path->device); if ((inq_buf->flags & SID_CmdQue) != 0) softc->action = PROBE_MODE_SENSE; diff -u sys/dev/ata/ata-all.c.dist sys/dev/ata/ata-all.c --- sys/dev/ata/ata-all.c.dist Mon Mar 18 09:37:33 2002 +++ sys/dev/ata/ata-all.c Thu Mar 21 14:24:58 2002 @@ -58,6 +58,9 @@ #include #include #include +#ifdef ATAPICAM +#include +#endif /* device structures */ static d_ioctl_t ataioctl; @@ -209,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 } return 0; @@ -520,6 +527,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 } diff -u sys/dev/ata/atapi-all.c.dist sys/dev/ata/atapi-all.c --- sys/dev/ata/atapi-all.c.dist Thu Mar 21 14:10:33 2002 +++ sys/dev/ata/atapi-all.c Thu Mar 21 14:16:41 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); @@ -116,10 +118,12 @@ #endif notfound: default: +#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; } } @@ -638,6 +642,7 @@ ata_reinit(atadev->channel); } +#ifndef ATAPICAM static char * atapi_type(int type) { @@ -654,6 +659,7 @@ return "Unknown"; } } +#endif static char * atapi_cmd2str(u_int8_t cmd)